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,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,"
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue