diff options
Diffstat (limited to 'libunwindstack/DwarfSection.cpp')
-rw-r--r-- | libunwindstack/DwarfSection.cpp | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp index 18bd490f9b..bf86e6e664 100644 --- a/libunwindstack/DwarfSection.cpp +++ b/libunwindstack/DwarfSection.cpp @@ -21,6 +21,7 @@ #include <unwindstack/DwarfMemory.h> #include <unwindstack/DwarfSection.h> #include <unwindstack/DwarfStructs.h> +#include <unwindstack/Elf.h> #include <unwindstack/Log.h> #include <unwindstack/Memory.h> #include <unwindstack/Regs.h> @@ -49,7 +50,7 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* f // Now get the location information for this pc. dwarf_loc_regs_t loc_regs; - if (!GetCfaLocationInfo(pc, fde, &loc_regs)) { + if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) { return false; } loc_regs.cie = fde->cie; @@ -464,6 +465,9 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3 eval_info->return_address_undefined = true; } break; + case DWARF_LOCATION_PSEUDO_REGISTER: + last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; + return false; default: break; } @@ -491,6 +495,10 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me // Always set the dex pc to zero when evaluating. cur_regs->set_dex_pc(0); + // Reset necessary pseudo registers before evaluation. + // This is needed for ARM64, for example. + regs->ResetPseudoRegisters(); + EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, @@ -527,13 +535,19 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me AddressType* reg_ptr; if (reg >= cur_regs->total_regs()) { - // Skip this unknown register. - continue; - } - - reg_ptr = eval_info.regs_info.Save(reg); - if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { - return false; + if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) { + // Skip this unknown register. + continue; + } + if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) { + last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; + return false; + } + } else { + reg_ptr = eval_info.regs_info.Save(reg); + if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { + return false; + } } } @@ -554,8 +568,8 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me template <typename AddressType> bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, - dwarf_loc_regs_t* loc_regs) { - DwarfCfa<AddressType> cfa(&memory_, fde); + dwarf_loc_regs_t* loc_regs, ArchEnum arch) { + DwarfCfa<AddressType> cfa(&memory_, fde, arch); // Look for the cached copy of the cie data. auto reg_entry = cie_loc_regs_.find(fde->cie_offset); @@ -576,8 +590,9 @@ bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfF } template <typename AddressType> -bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) { - DwarfCfa<AddressType> cfa(&memory_, fde); +bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, + ArchEnum arch) { + DwarfCfa<AddressType> cfa(&memory_, fde, arch); // Always print the cie information. const DwarfCie* cie = fde->cie; |