xref: /llvm-project/lldb/unittests/ObjectFile/Breakpad/BreakpadRecordsTest.cpp (revision d2a6114f27016065f6c7e7d39c0412e7d8d5e03b)
1 //===-- BreakpadRecordsTest.cpp -------------------------------------------===//
2 //
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Plugins/ObjectFile/Breakpad/BreakpadRecords.h"
11 #include "gtest/gtest.h"
12 
13 using namespace lldb_private;
14 using namespace lldb_private::breakpad;
15 
TEST(Record,classify)16 TEST(Record, classify) {
17   EXPECT_EQ(Record::Module, Record::classify("MODULE"));
18   EXPECT_EQ(Record::Info, Record::classify("INFO"));
19   EXPECT_EQ(Record::File, Record::classify("FILE"));
20   EXPECT_EQ(Record::Func, Record::classify("FUNC"));
21   EXPECT_EQ(Record::Inline, Record::classify("INLINE"));
22   EXPECT_EQ(Record::InlineOrigin, Record::classify("INLINE_ORIGIN"));
23   EXPECT_EQ(Record::Public, Record::classify("PUBLIC"));
24   EXPECT_EQ(Record::StackCFI, Record::classify("STACK CFI"));
25   EXPECT_EQ(Record::StackWin, Record::classify("STACK WIN"));
26 
27   // Any obviously incorrect lines will be classified as such.
28   EXPECT_EQ(std::nullopt, Record::classify("STACK"));
29   EXPECT_EQ(std::nullopt, Record::classify("STACK CODE_ID"));
30   EXPECT_EQ(std::nullopt, Record::classify("CODE_ID"));
31 
32   // Any line which does not start with a known keyword will be classified as a
33   // line record, as those are the only ones that start without a keyword.
34   EXPECT_EQ(Record::Line, Record::classify("deadbeef"));
35   EXPECT_EQ(Record::Line, Record::classify("12"));
36 }
37 
TEST(ModuleRecord,parse)38 TEST(ModuleRecord, parse) {
39   EXPECT_EQ(ModuleRecord(llvm::Triple::Linux, llvm::Triple::x86_64,
40                          UUID("@ABCDEFGHIJKLMNO", 16)),
41             ModuleRecord::parse(
42                 "MODULE Linux x86_64 404142434445464748494a4b4c4d4e4f0 a.out"));
43 
44   EXPECT_EQ(std::nullopt, ModuleRecord::parse("MODULE"));
45   EXPECT_EQ(std::nullopt, ModuleRecord::parse("MODULE Linux"));
46   EXPECT_EQ(std::nullopt, ModuleRecord::parse("MODULE Linux x86_64"));
47   EXPECT_EQ(std::nullopt,
48             ModuleRecord::parse("MODULE Linux x86_64 deadbeefbaadf00d"));
49 }
50 
TEST(InfoRecord,parse)51 TEST(InfoRecord, parse) {
52   EXPECT_EQ(InfoRecord(UUID("@ABCDEFGHIJKLMNO", 16)),
53             InfoRecord::parse("INFO CODE_ID 404142434445464748494a4b4c4d4e4f"));
54   EXPECT_EQ(InfoRecord(UUID()), InfoRecord::parse("INFO CODE_ID 47 a.exe"));
55 
56   EXPECT_EQ(std::nullopt, InfoRecord::parse("INFO"));
57   EXPECT_EQ(std::nullopt, InfoRecord::parse("INFO CODE_ID"));
58 }
59 
TEST(FileRecord,parse)60 TEST(FileRecord, parse) {
61   EXPECT_EQ(FileRecord(47, "foo"), FileRecord::parse("FILE 47 foo"));
62   EXPECT_EQ(std::nullopt, FileRecord::parse("FILE 47"));
63   EXPECT_EQ(std::nullopt, FileRecord::parse("FILE"));
64   EXPECT_EQ(std::nullopt, FileRecord::parse(""));
65 }
66 
TEST(FuncRecord,parse)67 TEST(FuncRecord, parse) {
68   EXPECT_EQ(FuncRecord(true, 0x47, 0x7, 0x8, "foo"),
69             FuncRecord::parse("FUNC m 47 7 8 foo"));
70   EXPECT_EQ(FuncRecord(false, 0x47, 0x7, 0x8, "foo"),
71             FuncRecord::parse("FUNC 47 7 8 foo"));
72 
73   EXPECT_EQ(std::nullopt, FuncRecord::parse("PUBLIC 47 7 8 foo"));
74   EXPECT_EQ(std::nullopt, FuncRecord::parse("FUNC 47 7 8"));
75   EXPECT_EQ(std::nullopt, FuncRecord::parse("FUNC 47 7"));
76   EXPECT_EQ(std::nullopt, FuncRecord::parse("FUNC 47"));
77   EXPECT_EQ(std::nullopt, FuncRecord::parse("FUNC m"));
78   EXPECT_EQ(std::nullopt, FuncRecord::parse("FUNC"));
79 }
80 
TEST(InlineOriginRecord,parse)81 TEST(InlineOriginRecord, parse) {
82   EXPECT_EQ(InlineOriginRecord(47, "foo"),
83             InlineOriginRecord::parse("INLINE_ORIGIN 47 foo"));
84   EXPECT_EQ(std::nullopt, InlineOriginRecord::parse("INLINE_ORIGIN 47"));
85   EXPECT_EQ(std::nullopt, InlineOriginRecord::parse("INLINE_ORIGIN"));
86   EXPECT_EQ(std::nullopt, InlineOriginRecord::parse(""));
87 }
88 
TEST(InlineRecord,parse)89 TEST(InlineRecord, parse) {
90   InlineRecord record1 = InlineRecord(0, 1, 2, 3);
91   record1.Ranges.emplace_back(4, 5);
92   EXPECT_EQ(record1, InlineRecord::parse("INLINE 0 1 2 3 4 5"));
93   record1.Ranges.emplace_back(6, 7);
94   EXPECT_EQ(record1, InlineRecord::parse("INLINE 0 1 2 3 4 5 6 7"));
95   EXPECT_EQ(std::nullopt, InlineRecord::parse("INLINE 0 1 2 3"));
96   EXPECT_EQ(std::nullopt, InlineRecord::parse("INLINE 0 1 2 3 4 5 6"));
97   EXPECT_EQ(std::nullopt, InlineRecord::parse("INLNIE 0"));
98   EXPECT_EQ(std::nullopt, InlineRecord::parse(""));
99   EXPECT_EQ(std::nullopt, InlineRecord::parse("FUNC"));
100 }
101 
TEST(LineRecord,parse)102 TEST(LineRecord, parse) {
103   EXPECT_EQ(LineRecord(0x47, 0x74, 47, 74), LineRecord::parse("47 74 47 74"));
104   EXPECT_EQ(std::nullopt, LineRecord::parse("47 74 47"));
105   EXPECT_EQ(std::nullopt, LineRecord::parse("47 74"));
106   EXPECT_EQ(std::nullopt, LineRecord::parse("47"));
107   EXPECT_EQ(std::nullopt, LineRecord::parse(""));
108   EXPECT_EQ(std::nullopt, LineRecord::parse("FUNC"));
109 }
110 
TEST(PublicRecord,parse)111 TEST(PublicRecord, parse) {
112   EXPECT_EQ(PublicRecord(true, 0x47, 0x8, "foo"),
113             PublicRecord::parse("PUBLIC m 47 8 foo"));
114   EXPECT_EQ(PublicRecord(false, 0x47, 0x8, "foo"),
115             PublicRecord::parse("PUBLIC 47 8 foo"));
116 
117   EXPECT_EQ(std::nullopt, PublicRecord::parse("FUNC 47 8 foo"));
118   EXPECT_EQ(std::nullopt, PublicRecord::parse("PUBLIC 47 8"));
119   EXPECT_EQ(std::nullopt, PublicRecord::parse("PUBLIC 47"));
120   EXPECT_EQ(std::nullopt, PublicRecord::parse("PUBLIC m"));
121   EXPECT_EQ(std::nullopt, PublicRecord::parse("PUBLIC"));
122 }
123 
TEST(StackCFIRecord,parse)124 TEST(StackCFIRecord, parse) {
125   EXPECT_EQ(StackCFIRecord(0x47, 0x8, ".cfa: $esp 4 + $eip: .cfa 4 - ^"),
126             StackCFIRecord::parse(
127                 "STACK CFI INIT 47 8 .cfa: $esp 4 + $eip: .cfa 4 - ^"));
128 
129   EXPECT_EQ(StackCFIRecord(0x47, 0x8, ".cfa: $esp 4 +"),
130             StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: $esp 4 +  "));
131 
132   EXPECT_EQ(StackCFIRecord(0x47, std::nullopt, ".cfa: $esp 4 +"),
133             StackCFIRecord::parse("STACK CFI 47 .cfa: $esp 4 +"));
134 
135   // The validity of the register value expressions is not checked
136   EXPECT_EQ(StackCFIRecord(0x47, 0x8, ".cfa: ^ ^ ^"),
137             StackCFIRecord::parse("STACK CFI INIT 47 8 .cfa: ^ ^ ^"));
138 
139   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("STACK CFI INIT 47"));
140   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("STACK CFI INIT"));
141   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("STACK CFI"));
142   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("STACK"));
143   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("FILE 47 foo"));
144   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("42 47"));
145 }
146 
TEST(StackWinRecord,parse)147 TEST(StackWinRecord, parse) {
148   EXPECT_EQ(
149       StackWinRecord(0x47, 0x8, 3, 4, 5, llvm::StringRef("$eip $esp ^ =")),
150       StackWinRecord::parse("STACK WIN 4 47 8 1 2 3 4 5 6 1 $eip $esp ^ ="));
151 
152   EXPECT_EQ(std::nullopt, StackWinRecord::parse(
153                               "STACK WIN 0 47 8 1 0 0 0 0 0 1 $eip $esp ^ ="));
154   EXPECT_EQ(std::nullopt,
155             StackWinRecord::parse("STACK WIN 4 47 8 1 0 0 0 0 0 0 1"));
156   EXPECT_EQ(std::nullopt, StackWinRecord::parse(
157                               "STACK WIN 3 47 8 1 0 0 0 0 0 1 $eip $esp ^ ="));
158   EXPECT_EQ(std::nullopt,
159             StackWinRecord::parse("STACK WIN 3 47 8 1 0 0 0 0 0 0 1"));
160   EXPECT_EQ(std::nullopt, StackWinRecord::parse(
161                               "STACK WIN 4 47 8 1 0 0 0 0 1 $eip $esp ^ ="));
162   EXPECT_EQ(std::nullopt,
163             StackWinRecord::parse("STACK WIN 4 47 8 1 0 0 0 0 0"));
164   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47 8 1 0 0 0 0"));
165   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47 8 1 0 0 0"));
166   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47 8 1 0 0"));
167   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47 8 1 0"));
168   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47 8 1"));
169   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47 8"));
170   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4 47"));
171   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN 4"));
172   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK WIN"));
173   EXPECT_EQ(std::nullopt, StackWinRecord::parse("STACK"));
174   EXPECT_EQ(std::nullopt, StackWinRecord::parse(""));
175   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("FILE 47 foo"));
176   EXPECT_EQ(std::nullopt, StackCFIRecord::parse("42 47"));
177 }
178