Index: lldb/trunk/lit/Modules/Breakpad/sections.test =================================================================== --- lldb/trunk/lit/Modules/Breakpad/sections.test +++ lldb/trunk/lit/Modules/Breakpad/sections.test @@ -73,7 +73,7 @@ CHECK: Index: 5 CHECK-NEXT: ID: 0x6 -CHECK-NEXT: Name: STACK CFI INIT +CHECK-NEXT: Name: STACK CFI CHECK-NEXT: Type: regular CHECK-NEXT: Permissions: --- CHECK-NEXT: Thread specific: no Index: lldb/trunk/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h +++ lldb/trunk/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h @@ -20,7 +20,7 @@ class Record { public: - enum Kind { Module, Info, File, Func, Line, Public, StackCFIInit, StackCFI }; + enum Kind { Module, Info, File, Func, Line, Public, StackCFI }; /// Attempt to guess the kind of the record present in the argument without /// doing a full parse. The returned kind will always be correct for valid @@ -141,6 +141,22 @@ bool operator==(const PublicRecord &L, const PublicRecord &R); llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PublicRecord &R); +class StackCFIRecord : public Record { +public: + static llvm::Optional parse(llvm::StringRef Line); + StackCFIRecord(lldb::addr_t Address, llvm::Optional Size, + llvm::StringRef UnwindRules) + : Record(StackCFI), Address(Address), Size(Size), + UnwindRules(UnwindRules) {} + + lldb::addr_t Address; + llvm::Optional Size; + llvm::StringRef UnwindRules; +}; + +bool operator==(const StackCFIRecord &L, const StackCFIRecord &R); +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StackCFIRecord &R); + } // namespace breakpad } // namespace lldb_private Index: lldb/trunk/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp +++ lldb/trunk/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp @@ -143,8 +143,7 @@ Tok = consume(Line); switch (Tok) { case Token::CFI: - Tok = consume(Line); - return Tok == Token::Init ? Record::StackCFIInit : Record::StackCFI; + return Record::StackCFI; default: return llvm::None; } @@ -359,6 +358,55 @@ R.Name); } +llvm::Optional StackCFIRecord::parse(llvm::StringRef Line) { + // STACK CFI INIT address size reg1: expr1 reg2: expr2 ... + // or + // STACK CFI address reg1: expr1 reg2: expr2 ... + // No token in exprN ends with a colon. + + if (consume(Line) != Token::Stack) + return llvm::None; + if (consume(Line) != Token::CFI) + return llvm::None; + + llvm::StringRef Str; + std::tie(Str, Line) = getToken(Line); + + bool IsInitRecord = stringTo(Str) == Token::Init; + if (IsInitRecord) + std::tie(Str, Line) = getToken(Line); + + lldb::addr_t Address; + if (!to_integer(Str, Address, 16)) + return llvm::None; + + llvm::Optional Size; + if (IsInitRecord) { + Size.emplace(); + std::tie(Str, Line) = getToken(Line); + if (!to_integer(Str, *Size, 16)) + return llvm::None; + } + + return StackCFIRecord(Address, Size, Line.trim()); +} + +bool breakpad::operator==(const StackCFIRecord &L, const StackCFIRecord &R) { + return L.Address == R.Address && L.Size == R.Size && + L.UnwindRules == R.UnwindRules; +} + +llvm::raw_ostream &breakpad::operator<<(llvm::raw_ostream &OS, + const StackCFIRecord &R) { + OS << "STACK CFI "; + if (R.Size) + OS << "INIT "; + OS << llvm::formatv("{0:x-} ", R.Address); + if (R.Size) + OS << llvm::formatv("{0:x-} ", *R.Size); + return OS << " " << R.UnwindRules; +} + llvm::StringRef breakpad::toString(Record::Kind K) { switch (K) { case Record::Module: @@ -373,8 +421,6 @@ return "LINE"; case Record::Public: return "PUBLIC"; - case Record::StackCFIInit: - return "STACK CFI INIT"; case Record::StackCFI: return "STACK CFI"; } Index: lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp +++ lldb/trunk/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp @@ -153,9 +153,6 @@ // Line records logically belong to the preceding Func record, so we put // them in the same section. next_section = Record::Func; - } else if (next_section == Record::StackCFI) { - // Same goes for StackCFI and StackCFIInit - next_section = Record::StackCFIInit; } if (next_section == current_section) continue; Index: lldb/trunk/unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp =================================================================== --- lldb/trunk/unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp +++ lldb/trunk/unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp @@ -19,7 +19,6 @@ EXPECT_EQ(Record::File, Record::classify("FILE")); EXPECT_EQ(Record::Func, Record::classify("FUNC")); EXPECT_EQ(Record::Public, Record::classify("PUBLIC")); - EXPECT_EQ(Record::StackCFIInit, Record::classify("STACK CFI INIT")); EXPECT_EQ(Record::StackCFI, Record::classify("STACK CFI")); // Any obviously incorrect lines will be classified as such. @@ -97,3 +96,26 @@ EXPECT_EQ(llvm::None, PublicRecord::parse("PUBLIC m")); EXPECT_EQ(llvm::None, PublicRecord::parse("PUBLIC")); } + +TEST(StackCFIRecord, parse) { + EXPECT_EQ(StackCFIRecord(0x47, 0x8, ".cfa: $esp 4 + $eip: .cfa 4 - ^"), + StackCFIRecord::parse( + "STACK CFI INIT 47 8 .cfa: $esp 4 + $eip: .cfa 4 - ^")); + + EXPECT_EQ(StackCFIRecord(0x47, 0x8, ".cfa: $esp 4 +"), + StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: $esp 4 + ")); + + EXPECT_EQ(StackCFIRecord(0x47, llvm::None, ".cfa: $esp 4 +"), + StackCFIRecord::parse("STACK CFI 47 .cfa: $esp 4 +")); + + // The validity of the register value expressions is not checked + EXPECT_EQ(StackCFIRecord(0x47, 0x8, ".cfa: ^ ^ ^"), + StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: ^ ^ ^")); + + EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK CFI INIT 47")); + EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK CFI INIT")); + EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK CFI")); + EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK")); + EXPECT_EQ(llvm::None, StackCFIRecord::parse("FILE 47 foo")); + EXPECT_EQ(llvm::None, StackCFIRecord::parse("42 47")); +}