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>
This commit is contained in:
parent
e467c59c68
commit
afc8daa2de
5 changed files with 37 additions and 16 deletions
|
@ -2721,12 +2721,20 @@ bool CallFrameInfo::State::DoInstruction() {
|
||||||
case DW_CFA_nop:
|
case DW_CFA_nop:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// case DW_CFA_AARCH64_negate_ra_state
|
||||||
|
case DW_CFA_GNU_window_save: {
|
||||||
|
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)
|
// A SPARC register window save: Registers 8 through 15 (%o0-%o7)
|
||||||
// are saved in registers 24 through 31 (%i0-%i7), and registers
|
// are saved in registers 24 through 31 (%i0-%i7), and registers
|
||||||
// 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets
|
// 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets
|
||||||
// (0-15 * the register size). The register numbers must be
|
// (0-15 * the register size). The register numbers must be
|
||||||
// hard-coded. A GNU extension, and not a pretty one.
|
// hard-coded. A GNU extension, and not a pretty one.
|
||||||
case DW_CFA_GNU_window_save: {
|
|
||||||
// Save %o0-%o7 in %i0-%i7.
|
// Save %o0-%o7 in %i0-%i7.
|
||||||
for (int i = 8; i < 16; i++)
|
for (int i = 8; i < 16; i++)
|
||||||
if (!DoRule(i, new RegisterRule(i + 16)))
|
if (!DoRule(i, new RegisterRule(i + 16)))
|
||||||
|
@ -2738,6 +2746,7 @@ bool CallFrameInfo::State::DoInstruction() {
|
||||||
if (!DoRule(i, new OffsetRule(Handler::kCFARegister,
|
if (!DoRule(i, new OffsetRule(Handler::kCFARegister,
|
||||||
(i - 16) * reader_->AddressSize())))
|
(i - 16) * reader_->AddressSize())))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1332,6 +1332,9 @@ class CallFrameInfo::Handler {
|
||||||
// should stop.
|
// should stop.
|
||||||
virtual bool End() = 0;
|
virtual bool End() = 0;
|
||||||
|
|
||||||
|
// The target architecture for the data.
|
||||||
|
virtual string Architecture() = 0;
|
||||||
|
|
||||||
// Handler functions for Linux C++ exception handling data. These are
|
// Handler functions for Linux C++ exception handling data. These are
|
||||||
// only called if the data includes 'z' augmentation strings.
|
// only called if the data includes 'z' augmentation strings.
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ class MockCallFrameInfoHandler: public CallFrameInfo::Handler {
|
||||||
MOCK_METHOD3(ValExpressionRule, bool(uint64_t address, int reg,
|
MOCK_METHOD3(ValExpressionRule, bool(uint64_t address, int reg,
|
||||||
const string& expression));
|
const string& expression));
|
||||||
MOCK_METHOD0(End, bool());
|
MOCK_METHOD0(End, bool());
|
||||||
|
MOCK_METHOD0(Architecture, string());
|
||||||
MOCK_METHOD2(PersonalityRoutine, bool(uint64_t address, bool indirect));
|
MOCK_METHOD2(PersonalityRoutine, bool(uint64_t address, bool indirect));
|
||||||
MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64_t address, bool indirect));
|
MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64_t address, bool indirect));
|
||||||
MOCK_METHOD0(SignalHandler, bool());
|
MOCK_METHOD0(SignalHandler, bool());
|
||||||
|
@ -1539,6 +1540,8 @@ TEST_F(CFIInsn, DW_CFA_GNU_window_save) {
|
||||||
.D8(google_breakpad::DW_CFA_GNU_window_save)
|
.D8(google_breakpad::DW_CFA_GNU_window_save)
|
||||||
.FinishEntry();
|
.FinishEntry();
|
||||||
|
|
||||||
|
EXPECT_CALL(handler, Architecture()).WillRepeatedly(Return("sparc"));
|
||||||
|
|
||||||
// Don't include all the rules in any particular sequence.
|
// Don't include all the rules in any particular sequence.
|
||||||
|
|
||||||
// The caller's %o0-%o7 have become the callee's %i0-%i7. This is
|
// The caller's %o0-%o7 have become the callee's %i0-%i7. This is
|
||||||
|
|
|
@ -264,6 +264,10 @@ bool DwarfCFIToModule::End() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string DwarfCFIToModule::Architecture() {
|
||||||
|
return module_->architecture();
|
||||||
|
}
|
||||||
|
|
||||||
void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
|
void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
|
||||||
fprintf(stderr, "%s, section '%s': "
|
fprintf(stderr, "%s, section '%s': "
|
||||||
"the call frame entry at offset 0x%zx refers to register %d,"
|
"the call frame entry at offset 0x%zx refers to register %d,"
|
||||||
|
|
|
@ -152,6 +152,8 @@ class DwarfCFIToModule: public CallFrameInfo::Handler {
|
||||||
const string& expression);
|
const string& expression);
|
||||||
virtual bool End();
|
virtual bool End();
|
||||||
|
|
||||||
|
virtual string Architecture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Return the name to use for register REG.
|
// Return the name to use for register REG.
|
||||||
string RegisterName(int i);
|
string RegisterName(int i);
|
||||||
|
|
Loading…
Reference in a new issue