arm64: don't interpret DW_CFA_GNU_window_save
DW_CFA_AARCH64_negate_ra_state uses the same encoding as
DW_CFA_GNU_window_save. It is meant to indicate that x30/LR
has been signed, but breakpad does not require this information.
Bug: b/239086293
Change-Id: I5a17bd5e0673a3ff80a8c6e347013d66054314e8
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3781136
Reviewed-by: Mark Mentovai <mark@chromium.org>
diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc
index 6bd2614..33a63fc 100644
--- a/src/common/dwarf/dwarf2reader.cc
+++ b/src/common/dwarf/dwarf2reader.cc
@@ -2721,23 +2721,32 @@
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 97e5fea..0526ee7 100644
--- a/src/common/dwarf/dwarf2reader.h
+++ b/src/common/dwarf/dwarf2reader.h
@@ -1332,6 +1332,9 @@
// 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 5f70379..686ecb1 100644
--- a/src/common/dwarf/dwarf2reader_cfi_unittest.cc
+++ b/src/common/dwarf/dwarf2reader_cfi_unittest.cc
@@ -114,6 +114,7 @@
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 @@
.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 739b9fe..794bab5 100644
--- a/src/common/dwarf_cfi_to_module.cc
+++ b/src/common/dwarf_cfi_to_module.cc
@@ -264,6 +264,10 @@
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 3e2e6ff..b6d5fce 100644
--- a/src/common/dwarf_cfi_to_module.h
+++ b/src/common/dwarf_cfi_to_module.h
@@ -152,6 +152,8 @@
const string& expression);
virtual bool End();
+ virtual string Architecture();
+
private:
// Return the name to use for register REG.
string RegisterName(int i);