Loading libbacktrace/UnwindStack.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, back_frame->rel_pc = frame->rel_pc; back_frame->rel_pc = frame->rel_pc; back_frame->pc = frame->pc; back_frame->pc = frame->pc; back_frame->sp = frame->sp; back_frame->sp = frame->sp; back_frame->dex_pc = frame->dex_pc; back_frame->func_name = demangle(frame->function_name.c_str()); back_frame->func_name = demangle(frame->function_name.c_str()); back_frame->func_offset = frame->function_offset; back_frame->func_offset = frame->function_offset; Loading libbacktrace/include/backtrace/Backtrace.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,7 @@ struct backtrace_frame_data_t { uintptr_t rel_pc; // The relative pc. uintptr_t rel_pc; // The relative pc. uintptr_t sp; // The top of the stack. uintptr_t sp; // The top of the stack. size_t stack_size; // The size of the stack, zero indicate an unknown stack size. size_t stack_size; // The size of the stack, zero indicate an unknown stack size. uint64_t dex_pc; // If non-zero, the Dex PC for the ART interpreter. backtrace_map_t map; // The map associated with the given pc. backtrace_map_t map; // The map associated with the given pc. std::string func_name; // The function name associated with this pc, NULL if not found. std::string func_name; // The function name associated with this pc, NULL if not found. uintptr_t func_offset; // pc relative to the start of the function, only valid if func_name is not NULL. uintptr_t func_offset; // pc relative to the start of the function, only valid if func_name is not NULL. Loading libunwindstack/DwarfSection.cpp +112 −71 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,8 @@ namespace unwindstack { namespace unwindstack { constexpr uint64_t DEX_PC_REG = 0x20444558; DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { Loading Loading @@ -97,6 +99,84 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin return true; return true; } } template <typename AddressType> struct EvalInfo { const dwarf_loc_regs_t* loc_regs; const DwarfCie* cie; RegsImpl<AddressType>* cur_regs; Memory* regular_memory; AddressType cfa; bool return_address_undefined = false; uint64_t reg_map = 0; AddressType reg_values[64]; }; template <typename AddressType> bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info) { EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info); Memory* regular_memory = eval_info->regular_memory; switch (loc->type) { case DWARF_LOCATION_OFFSET: if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } break; case DWARF_LOCATION_VAL_OFFSET: *reg_ptr = eval_info->cfa + loc->values[0]; break; case DWARF_LOCATION_REGISTER: { uint32_t cur_reg = loc->values[0]; if (cur_reg >= eval_info->cur_regs->total_regs()) { last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg]; const auto& entry = eval_info->loc_regs->find(cur_reg); if (entry != eval_info->loc_regs->end()) { if (!(eval_info->reg_map & (1 << cur_reg))) { eval_info->reg_map |= 1 << cur_reg; eval_info->reg_values[cur_reg] = *cur_reg_ptr; if (!EvalRegister(&entry->second, cur_reg, cur_reg_ptr, eval_info)) { return false; } } // Use the register value from before any evaluations. *reg_ptr = eval_info->reg_values[cur_reg] + loc->values[1]; } else { *reg_ptr = *cur_reg_ptr + loc->values[1]; } break; } case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_VAL_EXPRESSION: { AddressType value; if (!EvalExpression(*loc, eval_info->cie->version, regular_memory, &value)) { return false; } if (loc->type == DWARF_LOCATION_EXPRESSION) { if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } else { *reg_ptr = value; } break; } case DWARF_LOCATION_UNDEFINED: if (reg == eval_info->cie->return_address_register) { eval_info->return_address_undefined = true; } default: break; } return true; } template <typename AddressType> template <typename AddressType> bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, Regs* regs, const dwarf_loc_regs_t& loc_regs, Regs* regs, Loading @@ -114,9 +194,13 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me return false; return false; } } // Always set the dex pc to zero when evaluating. cur_regs->set_dex_pc(0); AddressType prev_cfa = regs->sp(); AddressType prev_cfa = regs->sp(); AddressType cfa; EvalInfo<AddressType> eval_info{ .loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, .cur_regs = cur_regs}; const DwarfLocation* loc = &cfa_entry->second; const DwarfLocation* loc = &cfa_entry->second; // Only a few location types are valid for the cfa. // Only a few location types are valid for the cfa. switch (loc->type) { switch (loc->type) { Loading @@ -129,11 +213,11 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // pointer register does not have any associated location // pointer register does not have any associated location // information, use the current cfa value. // information, use the current cfa value. if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) { if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) { cfa = prev_cfa; eval_info.cfa = prev_cfa; } else { } else { cfa = (*cur_regs)[loc->values[0]]; eval_info.cfa = (*cur_regs)[loc->values[0]]; } } cfa += loc->values[1]; eval_info.cfa += loc->values[1]; break; break; case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_VAL_EXPRESSION: { case DWARF_LOCATION_VAL_EXPRESSION: { Loading @@ -142,12 +226,12 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me return false; return false; } } if (loc->type == DWARF_LOCATION_EXPRESSION) { if (loc->type == DWARF_LOCATION_EXPRESSION) { if (!regular_memory->ReadFully(value, &cfa, sizeof(AddressType))) { if (!regular_memory->ReadFully(value, &eval_info.cfa, sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; return false; } } } else { } else { cfa = value; eval_info.cfa = value; } } break; break; } } Loading @@ -156,81 +240,38 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me return false; return false; } } // This code is not guaranteed to work in cases where a register location // is a double indirection to the actual value. For example, if r3 is set // to r5 + 4, and r5 is set to CFA + 4, then this won't necessarily work // because it does not guarantee that r5 is evaluated before r3. // Check that this case does not exist, and error if it does. bool return_address_undefined = false; for (const auto& entry : loc_regs) { for (const auto& entry : loc_regs) { uint16_t reg = entry.first; uint32_t reg = entry.first; // Already handled the CFA register. // Already handled the CFA register. if (reg == CFA_REG) continue; if (reg == CFA_REG) continue; if (reg >= cur_regs->total_regs()) { AddressType* reg_ptr; // Skip this unknown register. AddressType dex_pc = 0; if (reg == DEX_PC_REG) { // Special register that indicates this is a dex pc. dex_pc = 0; reg_ptr = &dex_pc; } else if (reg >= cur_regs->total_regs() || eval_info.reg_map & (1 << reg)) { // Skip this unknown register, or a register that has already been // processed. continue; continue; } else { reg_ptr = &(*cur_regs)[reg]; eval_info.reg_map |= 1 << reg; eval_info.reg_values[reg] = *reg_ptr; } } const DwarfLocation* loc = &entry.second; if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { switch (loc->type) { case DWARF_LOCATION_OFFSET: if (!regular_memory->ReadFully(cfa + loc->values[0], &(*cur_regs)[reg], sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } break; case DWARF_LOCATION_VAL_OFFSET: (*cur_regs)[reg] = cfa + loc->values[0]; break; case DWARF_LOCATION_REGISTER: { uint16_t cur_reg = loc->values[0]; if (cur_reg >= cur_regs->total_regs()) { last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } if (loc_regs.find(cur_reg) != loc_regs.end()) { // This is a double indirection, a register definition references // another register which is also defined as something other // than a register. log(0, "Invalid indirection: register %d references register %d which is " "not a plain register.\n", reg, cur_reg); last_error_ = DWARF_ERROR_ILLEGAL_STATE; return false; return false; } } (*cur_regs)[reg] = (*cur_regs)[cur_reg] + loc->values[1]; break; if (reg == DEX_PC_REG) { } cur_regs->set_dex_pc(dex_pc); case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_VAL_EXPRESSION: { AddressType value; if (!EvalExpression(*loc, cie->version, regular_memory, &value)) { return false; } if (loc->type == DWARF_LOCATION_EXPRESSION) { if (!regular_memory->ReadFully(value, &(*cur_regs)[reg], sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } else { (*cur_regs)[reg] = value; } break; } case DWARF_LOCATION_UNDEFINED: if (reg == cie->return_address_register) { return_address_undefined = true; } default: break; } } } } // Find the return address location. // Find the return address location. if (return_address_undefined) { if (eval_info.return_address_undefined) { cur_regs->set_pc(0); cur_regs->set_pc(0); } else { } else { cur_regs->set_pc((*cur_regs)[cie->return_address_register]); cur_regs->set_pc((*cur_regs)[cie->return_address_register]); Loading @@ -239,7 +280,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // If the pc was set to zero, consider this the final frame. // If the pc was set to zero, consider this the final frame. *finished = (cur_regs->pc() == 0) ? true : false; *finished = (cur_regs->pc() == 0) ? true : false; cur_regs->set_sp(cfa); cur_regs->set_sp(eval_info.cfa); return true; return true; } } Loading libunwindstack/Unwinder.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc frame->num = frame_num; frame->num = frame_num; frame->sp = regs_->sp(); frame->sp = regs_->sp(); frame->rel_pc = adjusted_rel_pc; frame->rel_pc = adjusted_rel_pc; frame->dex_pc = regs_->dex_pc(); if (map_info == nullptr) { if (map_info == nullptr) { frame->pc = regs_->pc(); frame->pc = regs_->pc(); Loading libunwindstack/include/unwindstack/DwarfLocation.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -38,7 +38,7 @@ struct DwarfLocation { uint64_t values[2]; uint64_t values[2]; }; }; typedef std::unordered_map<uint16_t, DwarfLocation> dwarf_loc_regs_t; typedef std::unordered_map<uint32_t, DwarfLocation> dwarf_loc_regs_t; } // namespace unwindstack } // namespace unwindstack Loading Loading
libbacktrace/UnwindStack.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, back_frame->rel_pc = frame->rel_pc; back_frame->rel_pc = frame->rel_pc; back_frame->pc = frame->pc; back_frame->pc = frame->pc; back_frame->sp = frame->sp; back_frame->sp = frame->sp; back_frame->dex_pc = frame->dex_pc; back_frame->func_name = demangle(frame->function_name.c_str()); back_frame->func_name = demangle(frame->function_name.c_str()); back_frame->func_offset = frame->function_offset; back_frame->func_offset = frame->function_offset; Loading
libbacktrace/include/backtrace/Backtrace.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -81,6 +81,7 @@ struct backtrace_frame_data_t { uintptr_t rel_pc; // The relative pc. uintptr_t rel_pc; // The relative pc. uintptr_t sp; // The top of the stack. uintptr_t sp; // The top of the stack. size_t stack_size; // The size of the stack, zero indicate an unknown stack size. size_t stack_size; // The size of the stack, zero indicate an unknown stack size. uint64_t dex_pc; // If non-zero, the Dex PC for the ART interpreter. backtrace_map_t map; // The map associated with the given pc. backtrace_map_t map; // The map associated with the given pc. std::string func_name; // The function name associated with this pc, NULL if not found. std::string func_name; // The function name associated with this pc, NULL if not found. uintptr_t func_offset; // pc relative to the start of the function, only valid if func_name is not NULL. uintptr_t func_offset; // pc relative to the start of the function, only valid if func_name is not NULL. Loading
libunwindstack/DwarfSection.cpp +112 −71 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,8 @@ namespace unwindstack { namespace unwindstack { constexpr uint64_t DEX_PC_REG = 0x20444558; DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { Loading Loading @@ -97,6 +99,84 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin return true; return true; } } template <typename AddressType> struct EvalInfo { const dwarf_loc_regs_t* loc_regs; const DwarfCie* cie; RegsImpl<AddressType>* cur_regs; Memory* regular_memory; AddressType cfa; bool return_address_undefined = false; uint64_t reg_map = 0; AddressType reg_values[64]; }; template <typename AddressType> bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info) { EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info); Memory* regular_memory = eval_info->regular_memory; switch (loc->type) { case DWARF_LOCATION_OFFSET: if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } break; case DWARF_LOCATION_VAL_OFFSET: *reg_ptr = eval_info->cfa + loc->values[0]; break; case DWARF_LOCATION_REGISTER: { uint32_t cur_reg = loc->values[0]; if (cur_reg >= eval_info->cur_regs->total_regs()) { last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg]; const auto& entry = eval_info->loc_regs->find(cur_reg); if (entry != eval_info->loc_regs->end()) { if (!(eval_info->reg_map & (1 << cur_reg))) { eval_info->reg_map |= 1 << cur_reg; eval_info->reg_values[cur_reg] = *cur_reg_ptr; if (!EvalRegister(&entry->second, cur_reg, cur_reg_ptr, eval_info)) { return false; } } // Use the register value from before any evaluations. *reg_ptr = eval_info->reg_values[cur_reg] + loc->values[1]; } else { *reg_ptr = *cur_reg_ptr + loc->values[1]; } break; } case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_VAL_EXPRESSION: { AddressType value; if (!EvalExpression(*loc, eval_info->cie->version, regular_memory, &value)) { return false; } if (loc->type == DWARF_LOCATION_EXPRESSION) { if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } else { *reg_ptr = value; } break; } case DWARF_LOCATION_UNDEFINED: if (reg == eval_info->cie->return_address_register) { eval_info->return_address_undefined = true; } default: break; } return true; } template <typename AddressType> template <typename AddressType> bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, Regs* regs, const dwarf_loc_regs_t& loc_regs, Regs* regs, Loading @@ -114,9 +194,13 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me return false; return false; } } // Always set the dex pc to zero when evaluating. cur_regs->set_dex_pc(0); AddressType prev_cfa = regs->sp(); AddressType prev_cfa = regs->sp(); AddressType cfa; EvalInfo<AddressType> eval_info{ .loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, .cur_regs = cur_regs}; const DwarfLocation* loc = &cfa_entry->second; const DwarfLocation* loc = &cfa_entry->second; // Only a few location types are valid for the cfa. // Only a few location types are valid for the cfa. switch (loc->type) { switch (loc->type) { Loading @@ -129,11 +213,11 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // pointer register does not have any associated location // pointer register does not have any associated location // information, use the current cfa value. // information, use the current cfa value. if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) { if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) { cfa = prev_cfa; eval_info.cfa = prev_cfa; } else { } else { cfa = (*cur_regs)[loc->values[0]]; eval_info.cfa = (*cur_regs)[loc->values[0]]; } } cfa += loc->values[1]; eval_info.cfa += loc->values[1]; break; break; case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_VAL_EXPRESSION: { case DWARF_LOCATION_VAL_EXPRESSION: { Loading @@ -142,12 +226,12 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me return false; return false; } } if (loc->type == DWARF_LOCATION_EXPRESSION) { if (loc->type == DWARF_LOCATION_EXPRESSION) { if (!regular_memory->ReadFully(value, &cfa, sizeof(AddressType))) { if (!regular_memory->ReadFully(value, &eval_info.cfa, sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; return false; } } } else { } else { cfa = value; eval_info.cfa = value; } } break; break; } } Loading @@ -156,81 +240,38 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me return false; return false; } } // This code is not guaranteed to work in cases where a register location // is a double indirection to the actual value. For example, if r3 is set // to r5 + 4, and r5 is set to CFA + 4, then this won't necessarily work // because it does not guarantee that r5 is evaluated before r3. // Check that this case does not exist, and error if it does. bool return_address_undefined = false; for (const auto& entry : loc_regs) { for (const auto& entry : loc_regs) { uint16_t reg = entry.first; uint32_t reg = entry.first; // Already handled the CFA register. // Already handled the CFA register. if (reg == CFA_REG) continue; if (reg == CFA_REG) continue; if (reg >= cur_regs->total_regs()) { AddressType* reg_ptr; // Skip this unknown register. AddressType dex_pc = 0; if (reg == DEX_PC_REG) { // Special register that indicates this is a dex pc. dex_pc = 0; reg_ptr = &dex_pc; } else if (reg >= cur_regs->total_regs() || eval_info.reg_map & (1 << reg)) { // Skip this unknown register, or a register that has already been // processed. continue; continue; } else { reg_ptr = &(*cur_regs)[reg]; eval_info.reg_map |= 1 << reg; eval_info.reg_values[reg] = *reg_ptr; } } const DwarfLocation* loc = &entry.second; if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { switch (loc->type) { case DWARF_LOCATION_OFFSET: if (!regular_memory->ReadFully(cfa + loc->values[0], &(*cur_regs)[reg], sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } break; case DWARF_LOCATION_VAL_OFFSET: (*cur_regs)[reg] = cfa + loc->values[0]; break; case DWARF_LOCATION_REGISTER: { uint16_t cur_reg = loc->values[0]; if (cur_reg >= cur_regs->total_regs()) { last_error_ = DWARF_ERROR_ILLEGAL_VALUE; return false; } if (loc_regs.find(cur_reg) != loc_regs.end()) { // This is a double indirection, a register definition references // another register which is also defined as something other // than a register. log(0, "Invalid indirection: register %d references register %d which is " "not a plain register.\n", reg, cur_reg); last_error_ = DWARF_ERROR_ILLEGAL_STATE; return false; return false; } } (*cur_regs)[reg] = (*cur_regs)[cur_reg] + loc->values[1]; break; if (reg == DEX_PC_REG) { } cur_regs->set_dex_pc(dex_pc); case DWARF_LOCATION_EXPRESSION: case DWARF_LOCATION_VAL_EXPRESSION: { AddressType value; if (!EvalExpression(*loc, cie->version, regular_memory, &value)) { return false; } if (loc->type == DWARF_LOCATION_EXPRESSION) { if (!regular_memory->ReadFully(value, &(*cur_regs)[reg], sizeof(AddressType))) { last_error_ = DWARF_ERROR_MEMORY_INVALID; return false; } } else { (*cur_regs)[reg] = value; } break; } case DWARF_LOCATION_UNDEFINED: if (reg == cie->return_address_register) { return_address_undefined = true; } default: break; } } } } // Find the return address location. // Find the return address location. if (return_address_undefined) { if (eval_info.return_address_undefined) { cur_regs->set_pc(0); cur_regs->set_pc(0); } else { } else { cur_regs->set_pc((*cur_regs)[cie->return_address_register]); cur_regs->set_pc((*cur_regs)[cie->return_address_register]); Loading @@ -239,7 +280,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // If the pc was set to zero, consider this the final frame. // If the pc was set to zero, consider this the final frame. *finished = (cur_regs->pc() == 0) ? true : false; *finished = (cur_regs->pc() == 0) ? true : false; cur_regs->set_sp(cfa); cur_regs->set_sp(eval_info.cfa); return true; return true; } } Loading
libunwindstack/Unwinder.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -40,6 +40,7 @@ void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc frame->num = frame_num; frame->num = frame_num; frame->sp = regs_->sp(); frame->sp = regs_->sp(); frame->rel_pc = adjusted_rel_pc; frame->rel_pc = adjusted_rel_pc; frame->dex_pc = regs_->dex_pc(); if (map_info == nullptr) { if (map_info == nullptr) { frame->pc = regs_->pc(); frame->pc = regs_->pc(); Loading
libunwindstack/include/unwindstack/DwarfLocation.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -38,7 +38,7 @@ struct DwarfLocation { uint64_t values[2]; uint64_t values[2]; }; }; typedef std::unordered_map<uint16_t, DwarfLocation> dwarf_loc_regs_t; typedef std::unordered_map<uint32_t, DwarfLocation> dwarf_loc_regs_t; } // namespace unwindstack } // namespace unwindstack Loading