diff options
Diffstat (limited to 'libunwindstack/DwarfCfa.cpp')
| -rw-r--r-- | libunwindstack/DwarfCfa.cpp | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp index c128b9bb7a..c6db209dbd 100644 --- a/libunwindstack/DwarfCfa.cpp +++ b/libunwindstack/DwarfCfa.cpp @@ -26,7 +26,9 @@ #include <unwindstack/DwarfError.h> #include <unwindstack/DwarfLocation.h> +#include <unwindstack/Elf.h> #include <unwindstack/Log.h> +#include <unwindstack/MachineArm64.h> #include "DwarfCfa.h" #include "DwarfEncoding.h" @@ -204,8 +206,12 @@ template <typename AddressType> bool DwarfCfa<AddressType>::LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc) { const auto* cfa = &DwarfCfaInfo::kTable[op]; - if (cfa->name[0] == '\0') { - log(indent, "Illegal"); + if (cfa->name[0] == '\0' || (arch_ != ARCH_ARM64 && op == 0x2d)) { + if (op == 0x2d) { + log(indent, "Illegal (Only valid on aarch64)"); + } else { + log(indent, "Illegal"); + } log(indent, "Raw Data: 0x%02x", op); return true; } @@ -514,6 +520,24 @@ bool DwarfCfa<AddressType>::cfa_gnu_negative_offset_extended(dwarf_loc_regs_t* l return true; } +template <typename AddressType> +bool DwarfCfa<AddressType>::cfa_aarch64_negate_ra_state(dwarf_loc_regs_t* loc_regs) { + // Only supported on aarch64. + if (arch_ != ARCH_ARM64) { + last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; + return false; + } + + auto cfa_location = loc_regs->find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE); + if (cfa_location == loc_regs->end()) { + (*loc_regs)[Arm64Reg::ARM64_PREG_RA_SIGN_STATE] = {.type = DWARF_LOCATION_PSEUDO_REGISTER, + .values = {1}}; + } else { + cfa_location->second.values[0] ^= 1; + } + return true; +} + const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = { { // 0x00 DW_CFA_nop @@ -699,7 +723,13 @@ const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = { {"", 0, 0, {}, {}}, // 0x2a illegal cfa {"", 0, 0, {}, {}}, // 0x2b illegal cfa {"", 0, 0, {}, {}}, // 0x2c illegal cfa - {"", 0, 0, {}, {}}, // 0x2d DW_CFA_GNU_window_save (Treat as illegal) + { + "DW_CFA_AARCH64_negate_ra_state", // 0x2d DW_CFA_AARCH64_negate_ra_state + 3, + 0, + {}, + {}, + }, { "DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size 2, |
