diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc index 6bd2614b..33a63fc4 100644 --- a/src/common/dwarf/dwarf2reader.cc +++ b/src/common/dwarf/dwarf2reader.cc @@ -2721,23 +2721,32 @@ bool CallFrameInfo::State::DoInstruction() { case DW_CFA_nop: break; - // A SPARC register window save: Registers 8 through 15 (%o0-%o7) - // are saved in registers 24 through 31 (%i0-%i7), and registers - // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets - // (0-15 * the register size). The register numbers must be - // hard-coded. A GNU extension, and not a pretty one. + // case DW_CFA_AARCH64_negate_ra_state case DW_CFA_GNU_window_save: { - // Save %o0-%o7 in %i0-%i7. - for (int i = 8; i < 16; i++) - if (!DoRule(i, new RegisterRule(i + 16))) - return false; - // Save %l0-%l7 and %i0-%i7 at the CFA. - for (int i = 16; i < 32; i++) - // Assume that the byte reader's address size is the same as - // the architecture's register size. !@#%*^ hilarious. - if (!DoRule(i, new OffsetRule(Handler::kCFARegister, - (i - 16) * reader_->AddressSize()))) - return false; + if (handler_->Architecture() == "arm64") { + // Indicates that the return address, x30 has been signed. + // Breakpad will speculatively remove pointer-authentication codes when + // interpreting return addresses, regardless of this bit. + } else if (handler_->Architecture() == "sparc" || + handler_->Architecture() == "sparcv9") { + // A SPARC register window save: Registers 8 through 15 (%o0-%o7) + // are saved in registers 24 through 31 (%i0-%i7), and registers + // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets + // (0-15 * the register size). The register numbers must be + // hard-coded. A GNU extension, and not a pretty one. + + // Save %o0-%o7 in %i0-%i7. + for (int i = 8; i < 16; i++) + if (!DoRule(i, new RegisterRule(i + 16))) + return false; + // Save %l0-%l7 and %i0-%i7 at the CFA. + for (int i = 16; i < 32; i++) + // Assume that the byte reader's address size is the same as + // the architecture's register size. !@#%*^ hilarious. + if (!DoRule(i, new OffsetRule(Handler::kCFARegister, + (i - 16) * reader_->AddressSize()))) + return false; + } break; } diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h index 97e5fea9..0526ee72 100644 --- a/src/common/dwarf/dwarf2reader.h +++ b/src/common/dwarf/dwarf2reader.h @@ -1332,6 +1332,9 @@ class CallFrameInfo::Handler { // should stop. virtual bool End() = 0; + // The target architecture for the data. + virtual string Architecture() = 0; + // Handler functions for Linux C++ exception handling data. These are // only called if the data includes 'z' augmentation strings. diff --git a/src/common/dwarf/dwarf2reader_cfi_unittest.cc b/src/common/dwarf/dwarf2reader_cfi_unittest.cc index 5f703794..686ecb14 100644 --- a/src/common/dwarf/dwarf2reader_cfi_unittest.cc +++ b/src/common/dwarf/dwarf2reader_cfi_unittest.cc @@ -114,6 +114,7 @@ class MockCallFrameInfoHandler: public CallFrameInfo::Handler { MOCK_METHOD3(ValExpressionRule, bool(uint64_t address, int reg, const string& expression)); MOCK_METHOD0(End, bool()); + MOCK_METHOD0(Architecture, string()); MOCK_METHOD2(PersonalityRoutine, bool(uint64_t address, bool indirect)); MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64_t address, bool indirect)); MOCK_METHOD0(SignalHandler, bool()); @@ -1539,6 +1540,8 @@ TEST_F(CFIInsn, DW_CFA_GNU_window_save) { .D8(google_breakpad::DW_CFA_GNU_window_save) .FinishEntry(); + EXPECT_CALL(handler, Architecture()).WillRepeatedly(Return("sparc")); + // Don't include all the rules in any particular sequence. // The caller's %o0-%o7 have become the callee's %i0-%i7. This is diff --git a/src/common/dwarf_cfi_to_module.cc b/src/common/dwarf_cfi_to_module.cc index 739b9fe0..794bab53 100644 --- a/src/common/dwarf_cfi_to_module.cc +++ b/src/common/dwarf_cfi_to_module.cc @@ -264,6 +264,10 @@ bool DwarfCFIToModule::End() { return true; } +string DwarfCFIToModule::Architecture() { + return module_->architecture(); +} + void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) { fprintf(stderr, "%s, section '%s': " "the call frame entry at offset 0x%zx refers to register %d," diff --git a/src/common/dwarf_cfi_to_module.h b/src/common/dwarf_cfi_to_module.h index 3e2e6ffe..b6d5fceb 100644 --- a/src/common/dwarf_cfi_to_module.h +++ b/src/common/dwarf_cfi_to_module.h @@ -152,6 +152,8 @@ class DwarfCFIToModule: public CallFrameInfo::Handler { const string& expression); virtual bool End(); + virtual string Architecture(); + private: // Return the name to use for register REG. string RegisterName(int i);