labath updated this revision to Diff 193849.
labath added a comment.

merge StackCFI and StackCFIInit records
add some tests


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60268/new/

https://reviews.llvm.org/D60268

Files:
  source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
  source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
  source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
  unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp

Index: unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp
===================================================================
--- unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp
+++ 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,41 @@
   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 +"}, {"$eip", ".cfa 4 - ^"}}),
+      StackCFIRecord::parse("STACK CFI 47 .cfa: $esp 4 + $eip: .cfa 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(StackCFIRecord(0x47, 0x8, {{".cfa", "STACK CFI"}}),
+            StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: STACK CFI"));
+
+  EXPECT_EQ(llvm::None,
+            StackCFIRecord::parse("STACK CFI INIT 47 .cfa: $esp 4 +"));
+  EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK CFI 47 8 .cfa: $esp 4 +"));
+  EXPECT_EQ(llvm::None,
+            StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: $esp 4 + $eip:"));
+  EXPECT_EQ(llvm::None,
+            StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: $eip: .cfa"));
+  EXPECT_EQ(llvm::None,
+            StackCFIRecord::parse("STACK CFI INIT 47 8 $esp .cfa: $esp"));
+  EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa:"));
+  EXPECT_EQ(llvm::None, StackCFIRecord::parse("STACK CFI INIT 47 8"));
+  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"));
+}
Index: source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
===================================================================
--- source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
+++ 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: source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
===================================================================
--- source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
+++ source/Plugins/ObjectFile/Breakpad/BreakpadRecords.h
@@ -11,6 +11,7 @@
 
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-types.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/FormatProviders.h"
@@ -20,7 +21,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 +142,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<StackCFIRecord> parse(llvm::StringRef Line);
+  StackCFIRecord(lldb::addr_t Address, llvm::Optional<lldb::addr_t> Size,
+                 llvm::DenseMap<llvm::StringRef, llvm::StringRef> UnwindRules)
+      : Record(StackCFI), Address(Address), Size(Size),
+        UnwindRules(std::move(UnwindRules)) {}
+
+  lldb::addr_t Address;
+  llvm::Optional<lldb::addr_t> Size;
+  llvm::DenseMap<llvm::StringRef, 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: source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
===================================================================
--- source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
+++ source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
@@ -143,8 +143,7 @@
     Tok = consume<Token>(Line);
     switch (Tok) {
     case Token::CFI:
-      Tok = consume<Token>(Line);
-      return Tok == Token::Init ? Record::StackCFIInit : Record::StackCFI;
+      return Record::StackCFI;
     default:
       return llvm::None;
     }
@@ -359,6 +358,91 @@
                              R.Name);
 }
 
+llvm::Optional<StackCFIRecord> 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<Token>(Line) != Token::Stack)
+    return llvm::None;
+  if (consume<Token>(Line) != Token::CFI)
+    return llvm::None;
+
+  llvm::StringRef Str;
+  std::tie(Str, Line) = getToken(Line);
+
+  bool IsInitRecord = stringTo<Token>(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<lldb::addr_t> Size;
+  if (IsInitRecord) {
+    Size.emplace();
+    std::tie(Str, Line) = getToken(Line);
+    if (!to_integer(Str, *Size, 16))
+      return llvm::None;
+  }
+
+  llvm::DenseMap<llvm::StringRef, llvm::StringRef> UnwindRules;
+  llvm::StringRef LHS, RHS;
+  while (std::tie(Str, Line) = getToken(Line), !Str.empty()) {
+    if (Str.back() == ':') { // regN
+      // Flush the previous expression, if there is one.
+      if (!LHS.empty()) {
+        if (RHS.empty())
+          return llvm::None; // regN without an exprN
+        UnwindRules[LHS] = RHS;
+      }
+
+      LHS = Str.drop_back();
+      RHS = llvm::StringRef();
+      continue;
+    }
+
+    if (LHS.empty())
+      return llvm::None; // exprN without a preceding regN.
+
+    // Append token to RHS.
+    if (RHS.empty())
+      RHS = Str;
+    else
+      RHS = llvm::StringRef(RHS.begin(), Str.end() - RHS.begin());
+  }
+
+  // Append last rule, if it is valid.
+  if (RHS.empty())
+    return llvm::None;
+
+  UnwindRules[LHS] = RHS;
+  return StackCFIRecord(Address, Size, std::move(UnwindRules));
+}
+
+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);
+  llvm::StringRef Sep;
+  for (const auto &KV : R.UnwindRules) {
+    OS << Sep << KV.first << ": " << KV.second;
+    Sep = " ";
+  }
+  return OS;
+}
+
 llvm::StringRef breakpad::toString(Record::Kind K) {
   switch (K) {
   case Record::Module:
@@ -373,8 +457,6 @@
     return "LINE";
   case Record::Public:
     return "PUBLIC";
-  case Record::StackCFIInit:
-    return "STACK CFI INIT";
   case Record::StackCFI:
     return "STACK CFI";
   }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to