1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // Original author: Jim Blandy <[email protected]> <[email protected]>
30
31 // dwarf2reader_cfi_unittest.cc: Unit tests for google_breakpad::CallFrameInfo
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h> // Must come first
35 #endif
36
37 #include <stdint.h>
38 #include <stdlib.h>
39
40 #include <string>
41 #include <vector>
42
43 // The '.eh_frame' format, used by the Linux C++ ABI for exception
44 // handling, is poorly specified. To help test our support for .eh_frame,
45 // if you #define WRITE_ELF while compiling this file, and add the
46 // 'include' directory from the binutils, gcc, or gdb source tree to the
47 // #include path, then each test that calls the
48 // PERHAPS_WRITE_DEBUG_FRAME_FILE or PERHAPS_WRITE_EH_FRAME_FILE will write
49 // an ELF file containing a .debug_frame or .eh_frame section; you can then
50 // use tools like readelf to examine the test data, and check the tools'
51 // interpretation against the test's intentions. Each ELF file is named
52 // "cfitest-TEST", where TEST identifies the particular test.
53 #ifdef WRITE_ELF
54 #include <errno.h>
55 #include <stdio.h>
56 #include <string.h>
57 extern "C" {
58 // To compile with WRITE_ELF, you should add the 'include' directory
59 // of the binutils, gcc, or gdb source tree to your #include path;
60 // that directory contains this header.
61 #include "elf/common.h"
62 }
63 #endif
64
65 #include "breakpad_googletest_includes.h"
66 #include "common/dwarf/bytereader-inl.h"
67 #include "common/dwarf/cfi_assembler.h"
68 #include "common/dwarf/dwarf2reader.h"
69 #include "common/using_std_string.h"
70 #include "google_breakpad/common/breakpad_types.h"
71
72 using google_breakpad::CFISection;
73 using google_breakpad::test_assembler::Label;
74 using google_breakpad::test_assembler::kBigEndian;
75 using google_breakpad::test_assembler::kLittleEndian;
76 using google_breakpad::test_assembler::Section;
77
78 using google_breakpad::DwarfPointerEncoding;
79 using google_breakpad::ENDIANNESS_BIG;
80 using google_breakpad::ENDIANNESS_LITTLE;
81 using google_breakpad::ByteReader;
82 using google_breakpad::CallFrameInfo;
83
84 using std::vector;
85 using testing::InSequence;
86 using testing::Return;
87 using testing::Sequence;
88 using testing::Test;
89 using testing::_;
90
91 #ifdef WRITE_ELF
92 void WriteELFFrameSection(const char *filename, const char *section_name,
93 const CFISection& section);
94 #define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section) \
95 WriteELFFrameSection("cfitest-" name, ".debug_frame", section);
96 #define PERHAPS_WRITE_EH_FRAME_FILE(name, section) \
97 WriteELFFrameSection("cfitest-" name, ".eh_frame", section);
98 #else
99 #define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section)
100 #define PERHAPS_WRITE_EH_FRAME_FILE(name, section)
101 #endif
102
103 class MockCallFrameInfoHandler: public CallFrameInfo::Handler {
104 public:
105 MOCK_METHOD6(Entry, bool(size_t offset, uint64_t address, uint64_t length,
106 uint8_t version, const string& augmentation,
107 unsigned return_address));
108 MOCK_METHOD2(UndefinedRule, bool(uint64_t address, int reg));
109 MOCK_METHOD2(SameValueRule, bool(uint64_t address, int reg));
110 MOCK_METHOD4(OffsetRule, bool(uint64_t address, int reg, int base_register,
111 long offset));
112 MOCK_METHOD4(ValOffsetRule, bool(uint64_t address, int reg, int base_register,
113 long offset));
114 MOCK_METHOD3(RegisterRule, bool(uint64_t address, int reg, int base_register));
115 MOCK_METHOD3(ExpressionRule, bool(uint64_t address, int reg,
116 const string& expression));
117 MOCK_METHOD3(ValExpressionRule, bool(uint64_t address, int reg,
118 const string& expression));
119 MOCK_METHOD0(End, bool());
120 MOCK_METHOD0(Architecture, string());
121 MOCK_METHOD2(PersonalityRoutine, bool(uint64_t address, bool indirect));
122 MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64_t address, bool indirect));
123 MOCK_METHOD0(SignalHandler, bool());
124 };
125
126 class MockCallFrameErrorReporter: public CallFrameInfo::Reporter {
127 public:
MockCallFrameErrorReporter()128 MockCallFrameErrorReporter() : Reporter("mock filename", "mock section") { }
129 MOCK_METHOD2(Incomplete, void(uint64_t, CallFrameInfo::EntryKind));
130 MOCK_METHOD1(EarlyEHTerminator, void(uint64_t));
131 MOCK_METHOD2(CIEPointerOutOfRange, void(uint64_t, uint64_t));
132 MOCK_METHOD2(BadCIEId, void(uint64_t, uint64_t));
133 MOCK_METHOD2(UnexpectedAddressSize, void(uint64_t, uint8_t));
134 MOCK_METHOD2(UnexpectedSegmentSize, void(uint64_t, uint8_t));
135 MOCK_METHOD2(UnrecognizedVersion, void(uint64_t, int version));
136 MOCK_METHOD2(UnrecognizedAugmentation, void(uint64_t, const string&));
137 MOCK_METHOD2(InvalidPointerEncoding, void(uint64_t, uint8_t));
138 MOCK_METHOD2(UnusablePointerEncoding, void(uint64_t, uint8_t));
139 MOCK_METHOD2(RestoreInCIE, void(uint64_t, uint64_t));
140 MOCK_METHOD3(BadInstruction, void(uint64_t, CallFrameInfo::EntryKind,
141 uint64_t));
142 MOCK_METHOD3(NoCFARule, void(uint64_t, CallFrameInfo::EntryKind, uint64_t));
143 MOCK_METHOD3(EmptyStateStack, void(uint64_t, CallFrameInfo::EntryKind,
144 uint64_t));
145 };
146
147 struct CFIFixture {
148
149 enum { kCFARegister = CallFrameInfo::Handler::kCFARegister };
150
CFIFixtureCFIFixture151 CFIFixture() {
152 // Default expectations for the data handler.
153 //
154 // - Leave Entry and End without expectations, as it's probably a
155 // good idea to set those explicitly in each test.
156 //
157 // - Expect the *Rule functions to not be called,
158 // so that each test can simply list the calls they expect.
159 //
160 // I gather I could use StrictMock for this, but the manual seems
161 // to suggest using that only as a last resort, and this isn't so
162 // bad.
163 EXPECT_CALL(handler, UndefinedRule(_, _)).Times(0);
164 EXPECT_CALL(handler, SameValueRule(_, _)).Times(0);
165 EXPECT_CALL(handler, OffsetRule(_, _, _, _)).Times(0);
166 EXPECT_CALL(handler, ValOffsetRule(_, _, _, _)).Times(0);
167 EXPECT_CALL(handler, RegisterRule(_, _, _)).Times(0);
168 EXPECT_CALL(handler, ExpressionRule(_, _, _)).Times(0);
169 EXPECT_CALL(handler, ValExpressionRule(_, _, _)).Times(0);
170 EXPECT_CALL(handler, PersonalityRoutine(_, _)).Times(0);
171 EXPECT_CALL(handler, LanguageSpecificDataArea(_, _)).Times(0);
172 EXPECT_CALL(handler, SignalHandler()).Times(0);
173
174 // Default expectations for the error/warning reporer.
175 EXPECT_CALL(reporter, Incomplete(_, _)).Times(0);
176 EXPECT_CALL(reporter, EarlyEHTerminator(_)).Times(0);
177 EXPECT_CALL(reporter, CIEPointerOutOfRange(_, _)).Times(0);
178 EXPECT_CALL(reporter, BadCIEId(_, _)).Times(0);
179 EXPECT_CALL(reporter, UnrecognizedVersion(_, _)).Times(0);
180 EXPECT_CALL(reporter, UnrecognizedAugmentation(_, _)).Times(0);
181 EXPECT_CALL(reporter, InvalidPointerEncoding(_, _)).Times(0);
182 EXPECT_CALL(reporter, UnusablePointerEncoding(_, _)).Times(0);
183 EXPECT_CALL(reporter, RestoreInCIE(_, _)).Times(0);
184 EXPECT_CALL(reporter, BadInstruction(_, _, _)).Times(0);
185 EXPECT_CALL(reporter, NoCFARule(_, _, _)).Times(0);
186 EXPECT_CALL(reporter, EmptyStateStack(_, _, _)).Times(0);
187 }
188
189 MockCallFrameInfoHandler handler;
190 MockCallFrameErrorReporter reporter;
191 };
192
193 class CFI: public CFIFixture, public Test { };
194
TEST_F(CFI,EmptyRegion)195 TEST_F(CFI, EmptyRegion) {
196 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
197 EXPECT_CALL(handler, End()).Times(0);
198 static const uint8_t data[] = { 42 };
199
200 ByteReader byte_reader(ENDIANNESS_BIG);
201 CallFrameInfo parser(data, 0, &byte_reader, &handler, &reporter);
202 EXPECT_TRUE(parser.Start());
203 }
204
TEST_F(CFI,IncompleteLength32)205 TEST_F(CFI, IncompleteLength32) {
206 CFISection section(kBigEndian, 8);
207 section
208 // Not even long enough for an initial length.
209 .D16(0xa0f)
210 // Padding to keep valgrind happy. We subtract these off when we
211 // construct the parser.
212 .D16(0);
213
214 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
215 EXPECT_CALL(handler, End()).Times(0);
216
217 EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
218 .WillOnce(Return());
219
220 string contents;
221 ASSERT_TRUE(section.GetContents(&contents));
222
223 ByteReader byte_reader(ENDIANNESS_BIG);
224 byte_reader.SetAddressSize(8);
225 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
226 contents.size() - 2,
227 &byte_reader, &handler, &reporter);
228 EXPECT_FALSE(parser.Start());
229 }
230
TEST_F(CFI,IncompleteLength64)231 TEST_F(CFI, IncompleteLength64) {
232 CFISection section(kLittleEndian, 4);
233 section
234 // An incomplete 64-bit DWARF initial length.
235 .D32(0xffffffff).D32(0x71fbaec2)
236 // Padding to keep valgrind happy. We subtract these off when we
237 // construct the parser.
238 .D32(0);
239
240 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
241 EXPECT_CALL(handler, End()).Times(0);
242
243 EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
244 .WillOnce(Return());
245
246 string contents;
247 ASSERT_TRUE(section.GetContents(&contents));
248
249 ByteReader byte_reader(ENDIANNESS_LITTLE);
250 byte_reader.SetAddressSize(4);
251 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
252 contents.size() - 4,
253 &byte_reader, &handler, &reporter);
254 EXPECT_FALSE(parser.Start());
255 }
256
TEST_F(CFI,IncompleteId32)257 TEST_F(CFI, IncompleteId32) {
258 CFISection section(kBigEndian, 8);
259 section
260 .D32(3) // Initial length, not long enough for id
261 .D8(0xd7).D8(0xe5).D8(0xf1) // incomplete id
262 .CIEHeader(8727, 3983, 8889, 3, "")
263 .FinishEntry();
264
265 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
266 EXPECT_CALL(handler, End()).Times(0);
267
268 EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
269 .WillOnce(Return());
270
271 string contents;
272 ASSERT_TRUE(section.GetContents(&contents));
273
274 ByteReader byte_reader(ENDIANNESS_BIG);
275 byte_reader.SetAddressSize(8);
276 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
277 contents.size(),
278 &byte_reader, &handler, &reporter);
279 EXPECT_FALSE(parser.Start());
280 }
281
TEST_F(CFI,BadId32)282 TEST_F(CFI, BadId32) {
283 CFISection section(kBigEndian, 8);
284 section
285 .D32(0x100) // Initial length
286 .D32(0xe802fade) // bogus ID
287 .Append(0x100 - 4, 0x42); // make the length true
288 section
289 .CIEHeader(1672, 9872, 8529, 3, "")
290 .FinishEntry();
291
292 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
293 EXPECT_CALL(handler, End()).Times(0);
294
295 EXPECT_CALL(reporter, CIEPointerOutOfRange(_, 0xe802fade))
296 .WillOnce(Return());
297
298 string contents;
299 ASSERT_TRUE(section.GetContents(&contents));
300
301 ByteReader byte_reader(ENDIANNESS_BIG);
302 byte_reader.SetAddressSize(8);
303 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
304 contents.size(),
305 &byte_reader, &handler, &reporter);
306 EXPECT_FALSE(parser.Start());
307 }
308
309 // A lone CIE shouldn't cause any handler calls.
TEST_F(CFI,SingleCIE)310 TEST_F(CFI, SingleCIE) {
311 CFISection section(kLittleEndian, 4);
312 section.CIEHeader(0xffe799a8, 0x3398dcdd, 0x6e9683de, 3, "");
313 section.Append(10, google_breakpad::DW_CFA_nop);
314 section.FinishEntry();
315
316 PERHAPS_WRITE_DEBUG_FRAME_FILE("SingleCIE", section);
317
318 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
319 EXPECT_CALL(handler, End()).Times(0);
320
321 string contents;
322 EXPECT_TRUE(section.GetContents(&contents));
323 ByteReader byte_reader(ENDIANNESS_LITTLE);
324 byte_reader.SetAddressSize(4);
325 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
326 contents.size(),
327 &byte_reader, &handler, &reporter);
328 EXPECT_TRUE(parser.Start());
329 }
330
331 // One FDE, one CIE.
TEST_F(CFI,OneFDE)332 TEST_F(CFI, OneFDE) {
333 CFISection section(kBigEndian, 4);
334 Label cie;
335 section
336 .Mark(&cie)
337 .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "")
338 .FinishEntry()
339 .FDEHeader(cie, 0x7714740d, 0x3d5a10cd)
340 .FinishEntry();
341
342 PERHAPS_WRITE_DEBUG_FRAME_FILE("OneFDE", section);
343
344 {
345 InSequence s;
346 EXPECT_CALL(handler,
347 Entry(_, 0x7714740d, 0x3d5a10cd, 3, "", 0x6b6efb87))
348 .WillOnce(Return(true));
349 EXPECT_CALL(handler, End()).WillOnce(Return(true));
350 }
351
352 string contents;
353 EXPECT_TRUE(section.GetContents(&contents));
354 ByteReader byte_reader(ENDIANNESS_BIG);
355 byte_reader.SetAddressSize(4);
356 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
357 contents.size(),
358 &byte_reader, &handler, &reporter);
359 EXPECT_TRUE(parser.Start());
360 }
361
362 // Two FDEs share a CIE.
TEST_F(CFI,TwoFDEsOneCIE)363 TEST_F(CFI, TwoFDEsOneCIE) {
364 CFISection section(kBigEndian, 4);
365 Label cie;
366 section
367 // First FDE. readelf complains about this one because it makes
368 // a forward reference to its CIE.
369 .FDEHeader(cie, 0xa42744df, 0xa3b42121)
370 .FinishEntry()
371 // CIE.
372 .Mark(&cie)
373 .CIEHeader(0x04f7dc7b, 0x3d00c05f, 0xbd43cb59, 3, "")
374 .FinishEntry()
375 // Second FDE.
376 .FDEHeader(cie, 0x6057d391, 0x700f608d)
377 .FinishEntry();
378
379 PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsOneCIE", section);
380
381 {
382 InSequence s;
383 EXPECT_CALL(handler,
384 Entry(_, 0xa42744df, 0xa3b42121, 3, "", 0xbd43cb59))
385 .WillOnce(Return(true));
386 EXPECT_CALL(handler, End()).WillOnce(Return(true));
387 }
388 {
389 InSequence s;
390 EXPECT_CALL(handler,
391 Entry(_, 0x6057d391, 0x700f608d, 3, "", 0xbd43cb59))
392 .WillOnce(Return(true));
393 EXPECT_CALL(handler, End()).WillOnce(Return(true));
394 }
395
396 string contents;
397 EXPECT_TRUE(section.GetContents(&contents));
398 ByteReader byte_reader(ENDIANNESS_BIG);
399 byte_reader.SetAddressSize(4);
400 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
401 contents.size(),
402 &byte_reader, &handler, &reporter);
403 EXPECT_TRUE(parser.Start());
404 }
405
406 // Two FDEs, two CIEs.
TEST_F(CFI,TwoFDEsTwoCIEs)407 TEST_F(CFI, TwoFDEsTwoCIEs) {
408 CFISection section(kLittleEndian, 8);
409 Label cie1, cie2;
410 section
411 // First CIE.
412 .Mark(&cie1)
413 .CIEHeader(0x694d5d45, 0x4233221b, 0xbf45e65a, 3, "")
414 .FinishEntry()
415 // First FDE which cites second CIE. readelf complains about
416 // this one because it makes a forward reference to its CIE.
417 .FDEHeader(cie2, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL)
418 .FinishEntry()
419 // Second FDE, which cites first CIE.
420 .FDEHeader(cie1, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL)
421 .FinishEntry()
422 // Second CIE.
423 .Mark(&cie2)
424 .CIEHeader(0xfba3fad7, 0x6287e1fd, 0x61d2c581, 2, "")
425 .FinishEntry();
426
427 PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsTwoCIEs", section);
428
429 {
430 InSequence s;
431 EXPECT_CALL(handler,
432 Entry(_, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL, 2,
433 "", 0x61d2c581))
434 .WillOnce(Return(true));
435 EXPECT_CALL(handler, End()).WillOnce(Return(true));
436 }
437 {
438 InSequence s;
439 EXPECT_CALL(handler,
440 Entry(_, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL, 3,
441 "", 0xbf45e65a))
442 .WillOnce(Return(true));
443 EXPECT_CALL(handler, End()).WillOnce(Return(true));
444 }
445
446 string contents;
447 EXPECT_TRUE(section.GetContents(&contents));
448 ByteReader byte_reader(ENDIANNESS_LITTLE);
449 byte_reader.SetAddressSize(8);
450 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
451 contents.size(),
452 &byte_reader, &handler, &reporter);
453 EXPECT_TRUE(parser.Start());
454 }
455
456 // An FDE whose CIE specifies a version we don't recognize.
TEST_F(CFI,BadVersion)457 TEST_F(CFI, BadVersion) {
458 CFISection section(kBigEndian, 4);
459 Label cie1, cie2;
460 section
461 .Mark(&cie1)
462 .CIEHeader(0xca878cf0, 0x7698ec04, 0x7b616f54, 0x52, "")
463 .FinishEntry()
464 // We should skip this entry, as its CIE specifies a version we
465 // don't recognize.
466 .FDEHeader(cie1, 0x08852292, 0x2204004a)
467 .FinishEntry()
468 // Despite the above, we should visit this entry.
469 .Mark(&cie2)
470 .CIEHeader(0x7c3ae7c9, 0xb9b9a512, 0x96cb3264, 3, "")
471 .FinishEntry()
472 .FDEHeader(cie2, 0x2094735a, 0x6e875501)
473 .FinishEntry();
474
475 PERHAPS_WRITE_DEBUG_FRAME_FILE("BadVersion", section);
476
477 EXPECT_CALL(reporter, UnrecognizedVersion(_, 0x52))
478 .WillOnce(Return());
479
480 {
481 InSequence s;
482 // We should see no mention of the first FDE, but we should get
483 // a call to Entry for the second.
484 EXPECT_CALL(handler, Entry(_, 0x2094735a, 0x6e875501, 3, "",
485 0x96cb3264))
486 .WillOnce(Return(true));
487 EXPECT_CALL(handler, End())
488 .WillOnce(Return(true));
489 }
490
491 string contents;
492 EXPECT_TRUE(section.GetContents(&contents));
493 ByteReader byte_reader(ENDIANNESS_BIG);
494 byte_reader.SetAddressSize(4);
495 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
496 contents.size(),
497 &byte_reader, &handler, &reporter);
498 EXPECT_FALSE(parser.Start());
499 }
500
501 // An FDE whose CIE specifies an augmentation we don't recognize.
TEST_F(CFI,BadAugmentation)502 TEST_F(CFI, BadAugmentation) {
503 CFISection section(kBigEndian, 4);
504 Label cie1, cie2;
505 section
506 .Mark(&cie1)
507 .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "spaniels!")
508 .FinishEntry()
509 // We should skip this entry, as its CIE specifies an
510 // augmentation we don't recognize.
511 .FDEHeader(cie1, 0x7714740d, 0x3d5a10cd)
512 .FinishEntry()
513 // Despite the above, we should visit this entry.
514 .Mark(&cie2)
515 .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 3, "")
516 .FinishEntry()
517 .FDEHeader(cie2, 0x7bf0fda0, 0xcbcd28d8)
518 .FinishEntry();
519
520 PERHAPS_WRITE_DEBUG_FRAME_FILE("BadAugmentation", section);
521
522 EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "spaniels!"))
523 .WillOnce(Return());
524
525 {
526 InSequence s;
527 // We should see no mention of the first FDE, but we should get
528 // a call to Entry for the second.
529 EXPECT_CALL(handler, Entry(_, 0x7bf0fda0, 0xcbcd28d8, 3, "",
530 0xf2f519b2))
531 .WillOnce(Return(true));
532 EXPECT_CALL(handler, End())
533 .WillOnce(Return(true));
534 }
535
536 string contents;
537 EXPECT_TRUE(section.GetContents(&contents));
538 ByteReader byte_reader(ENDIANNESS_BIG);
539 byte_reader.SetAddressSize(4);
540 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
541 contents.size(),
542 &byte_reader, &handler, &reporter);
543 EXPECT_FALSE(parser.Start());
544 }
545
546 // The return address column field is a byte in CFI version 1
547 // (DWARF2), but a ULEB128 value in version 3 (DWARF3).
TEST_F(CFI,CIEVersion1ReturnColumn)548 TEST_F(CFI, CIEVersion1ReturnColumn) {
549 CFISection section(kBigEndian, 4);
550 Label cie;
551 section
552 // CIE, using the version 1 format: return column is a ubyte.
553 .Mark(&cie)
554 // Use a value for the return column that is parsed differently
555 // as a ubyte and as a ULEB128.
556 .CIEHeader(0xbcdea24f, 0x5be28286, 0x9f, 1, "")
557 .FinishEntry()
558 // FDE, citing that CIE.
559 .FDEHeader(cie, 0xb8d347b5, 0x825e55dc)
560 .FinishEntry();
561
562 PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion1ReturnColumn", section);
563
564 {
565 InSequence s;
566 EXPECT_CALL(handler, Entry(_, 0xb8d347b5, 0x825e55dc, 1, "", 0x9f))
567 .WillOnce(Return(true));
568 EXPECT_CALL(handler, End()).WillOnce(Return(true));
569 }
570
571 string contents;
572 EXPECT_TRUE(section.GetContents(&contents));
573 ByteReader byte_reader(ENDIANNESS_BIG);
574 byte_reader.SetAddressSize(4);
575 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
576 contents.size(),
577 &byte_reader, &handler, &reporter);
578 EXPECT_TRUE(parser.Start());
579 }
580
581 // The return address column field is a byte in CFI version 1
582 // (DWARF2), but a ULEB128 value in version 3 (DWARF3).
TEST_F(CFI,CIEVersion3ReturnColumn)583 TEST_F(CFI, CIEVersion3ReturnColumn) {
584 CFISection section(kBigEndian, 4);
585 Label cie;
586 section
587 // CIE, using the version 3 format: return column is a ULEB128.
588 .Mark(&cie)
589 // Use a value for the return column that is parsed differently
590 // as a ubyte and as a ULEB128.
591 .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 3, "")
592 .FinishEntry()
593 // FDE, citing that CIE.
594 .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
595 .FinishEntry();
596
597 PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section);
598
599 {
600 InSequence s;
601 EXPECT_CALL(handler, Entry(_, 0x86763f2b, 0x2a66dc23, 3, "", 0x89))
602 .WillOnce(Return(true));
603 EXPECT_CALL(handler, End()).WillOnce(Return(true));
604 }
605
606 string contents;
607 EXPECT_TRUE(section.GetContents(&contents));
608 ByteReader byte_reader(ENDIANNESS_BIG);
609 byte_reader.SetAddressSize(4);
610 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
611 contents.size(),
612 &byte_reader, &handler, &reporter);
613 EXPECT_TRUE(parser.Start());
614 }
615
TEST_F(CFI,CIEVersion4AdditionalFields)616 TEST_F(CFI, CIEVersion4AdditionalFields) {
617 CFISection section(kBigEndian, 8);
618 Label cie;
619 section
620 .Mark(&cie)
621 // CIE version 4 with expected address (64bit) and segment size.
622 .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 4, "", true, 8, 0)
623 .FinishEntry()
624 // FDE, citing that CIE.
625 .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
626 .FinishEntry();
627
628 PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section);
629
630 {
631 InSequence s;
632 EXPECT_CALL(handler, Entry(_, 0x86763f2b, 0x2a66dc23, 4, "", 0x89))
633 .WillOnce(Return(true));
634 EXPECT_CALL(handler, End()).WillOnce(Return(true));
635 }
636
637 string contents;
638 EXPECT_TRUE(section.GetContents(&contents));
639 ByteReader byte_reader(ENDIANNESS_BIG);
640 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
641 contents.size(),
642 &byte_reader, &handler, &reporter);
643 EXPECT_TRUE(parser.Start());
644 }
645
TEST_F(CFI,CIEVersion4AdditionalFields32BitAddress)646 TEST_F(CFI, CIEVersion4AdditionalFields32BitAddress) {
647 CFISection section(kBigEndian, 4);
648 Label cie;
649 section
650 .Mark(&cie)
651 // CIE version 4 with expected address (32bit) and segment size.
652 .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 4, "", true, 4, 0)
653 .FinishEntry()
654 // FDE, citing that CIE.
655 .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
656 .FinishEntry();
657
658 PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section);
659
660 {
661 InSequence s;
662 EXPECT_CALL(handler, Entry(_, 0x86763f2b, 0x2a66dc23, 4, "", 0x89))
663 .WillOnce(Return(true));
664 EXPECT_CALL(handler, End()).WillOnce(Return(true));
665 }
666
667 string contents;
668 EXPECT_TRUE(section.GetContents(&contents));
669 ByteReader byte_reader(ENDIANNESS_BIG);
670 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
671 contents.size(),
672 &byte_reader, &handler, &reporter);
673 EXPECT_TRUE(parser.Start());
674 }
675
TEST_F(CFI,CIEVersion4AdditionalFieldsUnexpectedAddressSize)676 TEST_F(CFI, CIEVersion4AdditionalFieldsUnexpectedAddressSize) {
677 CFISection section(kBigEndian, 4);
678 Label cie;
679
680 section
681 .Mark(&cie)
682 // Unexpected address size.
683 .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 4, "", true, 3, 0)
684 .FinishEntry()
685 // FDE, citing that CIE.
686 .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
687 .FinishEntry();
688
689 PERHAPS_WRITE_DEBUG_FRAME_FILE("AdditionalFieldsUnexpectedAddress", section);
690
691 EXPECT_CALL(reporter, UnexpectedAddressSize(_, 3))
692 .WillOnce(Return());
693
694 string contents;
695 EXPECT_TRUE(section.GetContents(&contents));
696 ByteReader byte_reader(ENDIANNESS_BIG);
697 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
698 contents.size(),
699 &byte_reader, &handler, &reporter);
700 EXPECT_FALSE(parser.Start());
701 }
702
TEST_F(CFI,CIEVersion4AdditionalFieldsUnexpectedSegmentSize)703 TEST_F(CFI, CIEVersion4AdditionalFieldsUnexpectedSegmentSize) {
704 CFISection section(kBigEndian, 8);
705 Label cie;
706
707 section
708 .Mark(&cie)
709 .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 4, "", true, 8, 7)
710 .FinishEntry()
711 .FDEHeader(cie, 0x7bf0fda0, 0xcbcd28d8)
712 .FinishEntry();
713
714 PERHAPS_WRITE_DEBUG_FRAME_FILE("AdditionalFieldsUnexpectedSegment", section);
715
716 EXPECT_CALL(reporter, UnexpectedSegmentSize(_, 7))
717 .WillOnce(Return());
718
719 string contents;
720 EXPECT_TRUE(section.GetContents(&contents));
721 ByteReader byte_reader(ENDIANNESS_BIG);
722 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
723 contents.size(),
724 &byte_reader, &handler, &reporter);
725 EXPECT_FALSE(parser.Start());
726 }
727
728 struct CFIInsnFixture: public CFIFixture {
CFIInsnFixtureCFIInsnFixture729 CFIInsnFixture() : CFIFixture() {
730 data_factor = 0xb6f;
731 return_register = 0x9be1ed9f;
732 version = 3;
733 cfa_base_register = 0x383a3aa;
734 cfa_offset = 0xf748;
735 }
736
737 // Prepare SECTION to receive FDE instructions.
738 //
739 // - Append a stock CIE header that establishes the fixture's
740 // code_factor, data_factor, return_register, version, and
741 // augmentation values.
742 // - Have the CIE set up a CFA rule using cfa_base_register and
743 // cfa_offset.
744 // - Append a stock FDE header, referring to the above CIE, for the
745 // fde_size bytes at fde_start. Choose fde_start and fde_size
746 // appropriately for the section's address size.
747 // - Set appropriate expectations on handler in sequence s for the
748 // frame description entry and the CIE's CFA rule.
749 //
750 // On return, SECTION is ready to have FDE instructions appended to
751 // it, and its FinishEntry member called.
StockCIEAndFDECFIInsnFixture752 void StockCIEAndFDE(CFISection *section) {
753 // Choose appropriate constants for our address size.
754 if (section->AddressSize() == 4) {
755 fde_start = 0xc628ecfbU;
756 fde_size = 0x5dee04a2;
757 code_factor = 0x60b;
758 } else {
759 assert(section->AddressSize() == 8);
760 fde_start = 0x0005c57ce7806bd3ULL;
761 fde_size = 0x2699521b5e333100ULL;
762 code_factor = 0x01008e32855274a8ULL;
763 }
764
765 // Create the CIE.
766 (*section)
767 .Mark(&cie_label)
768 .CIEHeader(code_factor, data_factor, return_register, version,
769 "")
770 .D8(google_breakpad::DW_CFA_def_cfa)
771 .ULEB128(cfa_base_register)
772 .ULEB128(cfa_offset)
773 .FinishEntry();
774
775 // Create the FDE.
776 section->FDEHeader(cie_label, fde_start, fde_size);
777
778 // Expect an Entry call for the FDE and a ValOffsetRule call for the
779 // CIE's CFA rule.
780 EXPECT_CALL(handler, Entry(_, fde_start, fde_size, version, "",
781 return_register))
782 .InSequence(s)
783 .WillOnce(Return(true));
784 EXPECT_CALL(handler, ValOffsetRule(fde_start, kCFARegister,
785 cfa_base_register, cfa_offset))
786 .InSequence(s)
787 .WillOnce(Return(true));
788 }
789
790 // Run the contents of SECTION through a CallFrameInfo parser,
791 // expecting parser.Start to return SUCCEEDS
ParseSectionCFIInsnFixture792 void ParseSection(CFISection *section, bool succeeds = true) {
793 string contents;
794 EXPECT_TRUE(section->GetContents(&contents));
795 google_breakpad::Endianness endianness;
796 if (section->endianness() == kBigEndian)
797 endianness = ENDIANNESS_BIG;
798 else {
799 assert(section->endianness() == kLittleEndian);
800 endianness = ENDIANNESS_LITTLE;
801 }
802 ByteReader byte_reader(endianness);
803 byte_reader.SetAddressSize(section->AddressSize());
804 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
805 contents.size(),
806 &byte_reader, &handler, &reporter);
807 if (succeeds)
808 EXPECT_TRUE(parser.Start());
809 else
810 EXPECT_FALSE(parser.Start());
811 }
812
813 Label cie_label;
814 Sequence s;
815 uint64_t code_factor;
816 int data_factor;
817 unsigned return_register;
818 unsigned version;
819 unsigned cfa_base_register;
820 int cfa_offset;
821 uint64_t fde_start, fde_size;
822 };
823
824 class CFIInsn: public CFIInsnFixture, public Test { };
825
TEST_F(CFIInsn,DW_CFA_set_loc)826 TEST_F(CFIInsn, DW_CFA_set_loc) {
827 CFISection section(kBigEndian, 4);
828 StockCIEAndFDE(§ion);
829 section
830 .D8(google_breakpad::DW_CFA_set_loc).D32(0xb1ee3e7a)
831 // Use DW_CFA_def_cfa to force a handler call that we can use to
832 // check the effect of the DW_CFA_set_loc.
833 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee)
834 .FinishEntry();
835
836 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_set_loc", section);
837
838 EXPECT_CALL(handler,
839 ValOffsetRule(0xb1ee3e7a, kCFARegister, 0x4defb431, 0x6d17b0ee))
840 .InSequence(s)
841 .WillOnce(Return(true));
842 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
843
844 ParseSection(§ion);
845 }
846
TEST_F(CFIInsn,DW_CFA_advance_loc)847 TEST_F(CFIInsn, DW_CFA_advance_loc) {
848 CFISection section(kBigEndian, 8);
849 StockCIEAndFDE(§ion);
850 section
851 .D8(google_breakpad::DW_CFA_advance_loc | 0x2a)
852 // Use DW_CFA_def_cfa to force a handler call that we can use to
853 // check the effect of the DW_CFA_advance_loc.
854 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf)
855 .FinishEntry();
856
857 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc", section);
858
859 EXPECT_CALL(handler,
860 ValOffsetRule(fde_start + 0x2a * code_factor,
861 kCFARegister, 0x5bbb3715, 0x0186c7bf))
862 .InSequence(s)
863 .WillOnce(Return(true));
864 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
865
866 ParseSection(§ion);
867 }
868
TEST_F(CFIInsn,DW_CFA_advance_loc1)869 TEST_F(CFIInsn, DW_CFA_advance_loc1) {
870 CFISection section(kLittleEndian, 8);
871 StockCIEAndFDE(§ion);
872 section
873 .D8(google_breakpad::DW_CFA_advance_loc1).D8(0xd8)
874 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93)
875 .FinishEntry();
876
877 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc1", section);
878
879 EXPECT_CALL(handler,
880 ValOffsetRule((fde_start + 0xd8 * code_factor),
881 kCFARegister, 0x69d5696a, 0x1eb7fc93))
882 .InSequence(s)
883 .WillOnce(Return(true));
884 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
885
886 ParseSection(§ion);
887 }
888
TEST_F(CFIInsn,DW_CFA_advance_loc2)889 TEST_F(CFIInsn, DW_CFA_advance_loc2) {
890 CFISection section(kLittleEndian, 4);
891 StockCIEAndFDE(§ion);
892 section
893 .D8(google_breakpad::DW_CFA_advance_loc2).D16(0x3adb)
894 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37)
895 .FinishEntry();
896
897 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc2", section);
898
899 EXPECT_CALL(handler,
900 ValOffsetRule((fde_start + 0x3adb * code_factor),
901 kCFARegister, 0x3a368bed, 0x3194ee37))
902 .InSequence(s)
903 .WillOnce(Return(true));
904 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
905
906 ParseSection(§ion);
907 }
908
TEST_F(CFIInsn,DW_CFA_advance_loc4)909 TEST_F(CFIInsn, DW_CFA_advance_loc4) {
910 CFISection section(kBigEndian, 8);
911 StockCIEAndFDE(§ion);
912 section
913 .D8(google_breakpad::DW_CFA_advance_loc4).D32(0x15813c88)
914 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb)
915 .FinishEntry();
916
917 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc4", section);
918
919 EXPECT_CALL(handler,
920 ValOffsetRule((fde_start + 0x15813c88ULL * code_factor),
921 kCFARegister, 0x135270c5, 0x24bad7cb))
922 .InSequence(s)
923 .WillOnce(Return(true));
924 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
925
926 ParseSection(§ion);
927 }
928
TEST_F(CFIInsn,DW_CFA_MIPS_advance_loc8)929 TEST_F(CFIInsn, DW_CFA_MIPS_advance_loc8) {
930 code_factor = 0x2d;
931 CFISection section(kBigEndian, 8);
932 StockCIEAndFDE(§ion);
933 section
934 .D8(google_breakpad::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL)
935 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f)
936 .FinishEntry();
937
938 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc8", section);
939
940 EXPECT_CALL(handler,
941 ValOffsetRule((fde_start + 0x3c4f3945b92c14ULL * code_factor),
942 kCFARegister, 0xe17ed602, 0x3d162e7f))
943 .InSequence(s)
944 .WillOnce(Return(true));
945 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
946
947 ParseSection(§ion);
948 }
949
TEST_F(CFIInsn,DW_CFA_def_cfa)950 TEST_F(CFIInsn, DW_CFA_def_cfa) {
951 CFISection section(kLittleEndian, 4);
952 StockCIEAndFDE(§ion);
953 section
954 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7)
955 .FinishEntry();
956
957 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_def_cfa", section);
958
959 EXPECT_CALL(handler,
960 ValOffsetRule(fde_start, kCFARegister, 0x4e363a85, 0x815f9aa7))
961 .InSequence(s).WillOnce(Return(true));
962 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
963
964 ParseSection(§ion);
965 }
966
TEST_F(CFIInsn,DW_CFA_def_cfa_sf)967 TEST_F(CFIInsn, DW_CFA_def_cfa_sf) {
968 CFISection section(kBigEndian, 4);
969 StockCIEAndFDE(§ion);
970 section
971 .D8(google_breakpad::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea)
972 .D8(google_breakpad::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2)
973 .FinishEntry();
974
975 EXPECT_CALL(handler,
976 ValOffsetRule(fde_start, kCFARegister, 0x8ccb32b7,
977 0x9ea * data_factor))
978 .InSequence(s).WillOnce(Return(true));
979 EXPECT_CALL(handler,
980 ValOffsetRule(fde_start, kCFARegister, 0x9b40f5da,
981 -0x40a2 * data_factor))
982 .InSequence(s).WillOnce(Return(true));
983 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
984
985 ParseSection(§ion);
986 }
987
TEST_F(CFIInsn,DW_CFA_def_cfa_register)988 TEST_F(CFIInsn, DW_CFA_def_cfa_register) {
989 CFISection section(kLittleEndian, 8);
990 StockCIEAndFDE(§ion);
991 section
992 .D8(google_breakpad::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363)
993 .FinishEntry();
994
995 EXPECT_CALL(handler,
996 ValOffsetRule(fde_start, kCFARegister, 0x3e7e9363, cfa_offset))
997 .InSequence(s).WillOnce(Return(true));
998 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
999
1000 ParseSection(§ion);
1001 }
1002
1003 // DW_CFA_def_cfa_register should have no effect when applied to a
1004 // non-base/offset rule.
TEST_F(CFIInsn,DW_CFA_def_cfa_registerBadRule)1005 TEST_F(CFIInsn, DW_CFA_def_cfa_registerBadRule) {
1006 CFISection section(kBigEndian, 4);
1007 StockCIEAndFDE(§ion);
1008 section
1009 .D8(google_breakpad::DW_CFA_def_cfa_expression).Block("needle in a haystack")
1010 .D8(google_breakpad::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49)
1011 .FinishEntry();
1012
1013 EXPECT_CALL(handler,
1014 ValExpressionRule(fde_start, kCFARegister,
1015 "needle in a haystack"))
1016 .WillRepeatedly(Return(true));
1017 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1018
1019 ParseSection(§ion);
1020 }
1021
TEST_F(CFIInsn,DW_CFA_def_cfa_offset)1022 TEST_F(CFIInsn, DW_CFA_def_cfa_offset) {
1023 CFISection section(kBigEndian, 4);
1024 StockCIEAndFDE(§ion);
1025 section
1026 .D8(google_breakpad::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
1027 .FinishEntry();
1028
1029 EXPECT_CALL(handler,
1030 ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
1031 0x1e8e3b9b))
1032 .InSequence(s).WillOnce(Return(true));
1033 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1034
1035 ParseSection(§ion);
1036 }
1037
TEST_F(CFIInsn,DW_CFA_def_cfa_offset_sf)1038 TEST_F(CFIInsn, DW_CFA_def_cfa_offset_sf) {
1039 CFISection section(kLittleEndian, 4);
1040 StockCIEAndFDE(§ion);
1041 section
1042 .D8(google_breakpad::DW_CFA_def_cfa_offset_sf).LEB128(0x970)
1043 .D8(google_breakpad::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd)
1044 .FinishEntry();
1045
1046 EXPECT_CALL(handler,
1047 ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
1048 0x970 * data_factor))
1049 .InSequence(s).WillOnce(Return(true));
1050 EXPECT_CALL(handler,
1051 ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
1052 -0x2cd * data_factor))
1053 .InSequence(s).WillOnce(Return(true));
1054 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1055
1056 ParseSection(§ion);
1057 }
1058
1059 // DW_CFA_def_cfa_offset should have no effect when applied to a
1060 // non-base/offset rule.
TEST_F(CFIInsn,DW_CFA_def_cfa_offsetBadRule)1061 TEST_F(CFIInsn, DW_CFA_def_cfa_offsetBadRule) {
1062 CFISection section(kBigEndian, 4);
1063 StockCIEAndFDE(§ion);
1064 section
1065 .D8(google_breakpad::DW_CFA_def_cfa_expression).Block("six ways to Sunday")
1066 .D8(google_breakpad::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
1067 .FinishEntry();
1068
1069 EXPECT_CALL(handler,
1070 ValExpressionRule(fde_start, kCFARegister, "six ways to Sunday"))
1071 .WillRepeatedly(Return(true));
1072 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1073
1074 ParseSection(§ion);
1075 }
1076
TEST_F(CFIInsn,DW_CFA_def_cfa_expression)1077 TEST_F(CFIInsn, DW_CFA_def_cfa_expression) {
1078 CFISection section(kLittleEndian, 8);
1079 StockCIEAndFDE(§ion);
1080 section
1081 .D8(google_breakpad::DW_CFA_def_cfa_expression).Block("eating crow")
1082 .FinishEntry();
1083
1084 EXPECT_CALL(handler, ValExpressionRule(fde_start, kCFARegister,
1085 "eating crow"))
1086 .InSequence(s).WillOnce(Return(true));
1087 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1088
1089 ParseSection(§ion);
1090 }
1091
TEST_F(CFIInsn,DW_CFA_undefined)1092 TEST_F(CFIInsn, DW_CFA_undefined) {
1093 CFISection section(kLittleEndian, 4);
1094 StockCIEAndFDE(§ion);
1095 section
1096 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x300ce45d)
1097 .FinishEntry();
1098
1099 EXPECT_CALL(handler, UndefinedRule(fde_start, 0x300ce45d))
1100 .InSequence(s).WillOnce(Return(true));
1101 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1102
1103 ParseSection(§ion);
1104 }
1105
TEST_F(CFIInsn,DW_CFA_same_value)1106 TEST_F(CFIInsn, DW_CFA_same_value) {
1107 CFISection section(kLittleEndian, 4);
1108 StockCIEAndFDE(§ion);
1109 section
1110 .D8(google_breakpad::DW_CFA_same_value).ULEB128(0x3865a760)
1111 .FinishEntry();
1112
1113 EXPECT_CALL(handler, SameValueRule(fde_start, 0x3865a760))
1114 .InSequence(s).WillOnce(Return(true));
1115 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1116
1117 ParseSection(§ion);
1118 }
1119
TEST_F(CFIInsn,DW_CFA_offset)1120 TEST_F(CFIInsn, DW_CFA_offset) {
1121 CFISection section(kBigEndian, 4);
1122 StockCIEAndFDE(§ion);
1123 section
1124 .D8(google_breakpad::DW_CFA_offset | 0x2c).ULEB128(0x9f6)
1125 .FinishEntry();
1126
1127 EXPECT_CALL(handler,
1128 OffsetRule(fde_start, 0x2c, kCFARegister, 0x9f6 * data_factor))
1129 .InSequence(s).WillOnce(Return(true));
1130 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1131
1132 ParseSection(§ion);
1133 }
1134
TEST_F(CFIInsn,DW_CFA_offset_extended)1135 TEST_F(CFIInsn, DW_CFA_offset_extended) {
1136 CFISection section(kBigEndian, 4);
1137 StockCIEAndFDE(§ion);
1138 section
1139 .D8(google_breakpad::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48)
1140 .FinishEntry();
1141
1142 EXPECT_CALL(handler,
1143 OffsetRule(fde_start, 0x402b, kCFARegister, 0xb48 * data_factor))
1144 .InSequence(s).WillOnce(Return(true));
1145 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1146
1147 ParseSection(§ion);
1148 }
1149
TEST_F(CFIInsn,DW_CFA_offset_extended_sf)1150 TEST_F(CFIInsn, DW_CFA_offset_extended_sf) {
1151 CFISection section(kBigEndian, 8);
1152 StockCIEAndFDE(§ion);
1153 section
1154 .D8(google_breakpad::DW_CFA_offset_extended_sf)
1155 .ULEB128(0x997c23ee).LEB128(0x2d00)
1156 .D8(google_breakpad::DW_CFA_offset_extended_sf)
1157 .ULEB128(0x9519eb82).LEB128(-0xa77)
1158 .FinishEntry();
1159
1160 EXPECT_CALL(handler,
1161 OffsetRule(fde_start, 0x997c23ee,
1162 kCFARegister, 0x2d00 * data_factor))
1163 .InSequence(s).WillOnce(Return(true));
1164 EXPECT_CALL(handler,
1165 OffsetRule(fde_start, 0x9519eb82,
1166 kCFARegister, -0xa77 * data_factor))
1167 .InSequence(s).WillOnce(Return(true));
1168 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1169
1170 ParseSection(§ion);
1171 }
1172
TEST_F(CFIInsn,DW_CFA_val_offset)1173 TEST_F(CFIInsn, DW_CFA_val_offset) {
1174 CFISection section(kBigEndian, 4);
1175 StockCIEAndFDE(§ion);
1176 section
1177 .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673)
1178 .FinishEntry();
1179
1180 EXPECT_CALL(handler,
1181 ValOffsetRule(fde_start, 0x623562fe,
1182 kCFARegister, 0x673 * data_factor))
1183 .InSequence(s).WillOnce(Return(true));
1184 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1185
1186 ParseSection(§ion);
1187 }
1188
TEST_F(CFIInsn,DW_CFA_val_offset_sf)1189 TEST_F(CFIInsn, DW_CFA_val_offset_sf) {
1190 CFISection section(kBigEndian, 4);
1191 StockCIEAndFDE(§ion);
1192 section
1193 .D8(google_breakpad::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab)
1194 .D8(google_breakpad::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2)
1195 .FinishEntry();
1196
1197 EXPECT_CALL(handler,
1198 ValOffsetRule(fde_start, 0x6f4f,
1199 kCFARegister, 0xaab * data_factor))
1200 .InSequence(s).WillOnce(Return(true));
1201 EXPECT_CALL(handler,
1202 ValOffsetRule(fde_start, 0x2483,
1203 kCFARegister, -0x8a2 * data_factor))
1204 .InSequence(s).WillOnce(Return(true));
1205 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1206
1207 ParseSection(§ion);
1208 }
1209
TEST_F(CFIInsn,DW_CFA_register)1210 TEST_F(CFIInsn, DW_CFA_register) {
1211 CFISection section(kLittleEndian, 8);
1212 StockCIEAndFDE(§ion);
1213 section
1214 .D8(google_breakpad::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414)
1215 .FinishEntry();
1216
1217 EXPECT_CALL(handler, RegisterRule(fde_start, 0x278d18f9, 0x1a684414))
1218 .InSequence(s).WillOnce(Return(true));
1219 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1220
1221 ParseSection(§ion);
1222 }
1223
TEST_F(CFIInsn,DW_CFA_expression)1224 TEST_F(CFIInsn, DW_CFA_expression) {
1225 CFISection section(kBigEndian, 8);
1226 StockCIEAndFDE(§ion);
1227 section
1228 .D8(google_breakpad::DW_CFA_expression).ULEB128(0xa1619fb2)
1229 .Block("plus ça change, plus c'est la même chose")
1230 .FinishEntry();
1231
1232 EXPECT_CALL(handler,
1233 ExpressionRule(fde_start, 0xa1619fb2,
1234 "plus ça change, plus c'est la même chose"))
1235 .InSequence(s).WillOnce(Return(true));
1236 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1237
1238 ParseSection(§ion);
1239 }
1240
TEST_F(CFIInsn,DW_CFA_val_expression)1241 TEST_F(CFIInsn, DW_CFA_val_expression) {
1242 CFISection section(kBigEndian, 4);
1243 StockCIEAndFDE(§ion);
1244 section
1245 .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0xc5e4a9e3)
1246 .Block("he who has the gold makes the rules")
1247 .FinishEntry();
1248
1249 EXPECT_CALL(handler,
1250 ValExpressionRule(fde_start, 0xc5e4a9e3,
1251 "he who has the gold makes the rules"))
1252 .InSequence(s).WillOnce(Return(true));
1253 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1254
1255 ParseSection(§ion);
1256 }
1257
TEST_F(CFIInsn,DW_CFA_restore)1258 TEST_F(CFIInsn, DW_CFA_restore) {
1259 CFISection section(kLittleEndian, 8);
1260 code_factor = 0x01bd188a9b1fa083ULL;
1261 data_factor = -0x1ac8;
1262 return_register = 0x8c35b049;
1263 version = 2;
1264 fde_start = 0x2d70fe998298bbb1ULL;
1265 fde_size = 0x46ccc2e63cf0b108ULL;
1266 Label cie;
1267 section
1268 .Mark(&cie)
1269 .CIEHeader(code_factor, data_factor, return_register, version,
1270 "")
1271 // Provide a CFA rule, because register rules require them.
1272 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8)
1273 // Provide an offset(N) rule for register 0x3c.
1274 .D8(google_breakpad::DW_CFA_offset | 0x3c).ULEB128(0xb348)
1275 .FinishEntry()
1276 // In the FDE...
1277 .FDEHeader(cie, fde_start, fde_size)
1278 // At a second address, provide a new offset(N) rule for register 0x3c.
1279 .D8(google_breakpad::DW_CFA_advance_loc | 0x13)
1280 .D8(google_breakpad::DW_CFA_offset | 0x3c).ULEB128(0x9a50)
1281 // At a third address, restore the original rule for register 0x3c.
1282 .D8(google_breakpad::DW_CFA_advance_loc | 0x01)
1283 .D8(google_breakpad::DW_CFA_restore | 0x3c)
1284 .FinishEntry();
1285
1286 {
1287 InSequence s;
1288 EXPECT_CALL(handler,
1289 Entry(_, fde_start, fde_size, version, "", return_register))
1290 .WillOnce(Return(true));
1291 // CIE's CFA rule.
1292 EXPECT_CALL(handler,
1293 ValOffsetRule(fde_start, kCFARegister, 0x6ca1d50e, 0x372e38e8))
1294 .WillOnce(Return(true));
1295 // CIE's rule for register 0x3c.
1296 EXPECT_CALL(handler,
1297 OffsetRule(fde_start, 0x3c, kCFARegister, 0xb348 * data_factor))
1298 .WillOnce(Return(true));
1299 // FDE's rule for register 0x3c.
1300 EXPECT_CALL(handler,
1301 OffsetRule(fde_start + 0x13 * code_factor, 0x3c,
1302 kCFARegister, 0x9a50 * data_factor))
1303 .WillOnce(Return(true));
1304 // Restore CIE's rule for register 0x3c.
1305 EXPECT_CALL(handler,
1306 OffsetRule(fde_start + (0x13 + 0x01) * code_factor, 0x3c,
1307 kCFARegister, 0xb348 * data_factor))
1308 .WillOnce(Return(true));
1309 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1310 }
1311
1312 ParseSection(§ion);
1313 }
1314
TEST_F(CFIInsn,DW_CFA_restoreNoRule)1315 TEST_F(CFIInsn, DW_CFA_restoreNoRule) {
1316 CFISection section(kBigEndian, 4);
1317 code_factor = 0x005f78143c1c3b82ULL;
1318 data_factor = 0x25d0;
1319 return_register = 0xe8;
1320 version = 1;
1321 fde_start = 0x4062e30f;
1322 fde_size = 0x5302a389;
1323 Label cie;
1324 section
1325 .Mark(&cie)
1326 .CIEHeader(code_factor, data_factor, return_register, version, "")
1327 // Provide a CFA rule, because register rules require them.
1328 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127)
1329 .FinishEntry()
1330 // In the FDE...
1331 .FDEHeader(cie, fde_start, fde_size)
1332 // At a second address, provide an offset(N) rule for register 0x2c.
1333 .D8(google_breakpad::DW_CFA_advance_loc | 0x7)
1334 .D8(google_breakpad::DW_CFA_offset | 0x2c).ULEB128(0x1f47)
1335 // At a third address, restore the (missing) CIE rule for register 0x2c.
1336 .D8(google_breakpad::DW_CFA_advance_loc | 0xb)
1337 .D8(google_breakpad::DW_CFA_restore | 0x2c)
1338 .FinishEntry();
1339
1340 {
1341 InSequence s;
1342 EXPECT_CALL(handler,
1343 Entry(_, fde_start, fde_size, version, "", return_register))
1344 .WillOnce(Return(true));
1345 // CIE's CFA rule.
1346 EXPECT_CALL(handler,
1347 ValOffsetRule(fde_start, kCFARegister, 0x470aa334, 0x099ef127))
1348 .WillOnce(Return(true));
1349 // FDE's rule for register 0x2c.
1350 EXPECT_CALL(handler,
1351 OffsetRule(fde_start + 0x7 * code_factor, 0x2c,
1352 kCFARegister, 0x1f47 * data_factor))
1353 .WillOnce(Return(true));
1354 // Restore CIE's (missing) rule for register 0x2c.
1355 EXPECT_CALL(handler,
1356 SameValueRule(fde_start + (0x7 + 0xb) * code_factor, 0x2c))
1357 .WillOnce(Return(true));
1358 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1359 }
1360
1361 ParseSection(§ion);
1362 }
1363
TEST_F(CFIInsn,DW_CFA_restore_extended)1364 TEST_F(CFIInsn, DW_CFA_restore_extended) {
1365 CFISection section(kBigEndian, 4);
1366 code_factor = 0x126e;
1367 data_factor = -0xd8b;
1368 return_register = 0x77711787;
1369 version = 3;
1370 fde_start = 0x01f55a45;
1371 fde_size = 0x452adb80;
1372 Label cie;
1373 section
1374 .Mark(&cie)
1375 .CIEHeader(code_factor, data_factor, return_register, version,
1376 "", true /* dwarf64 */ )
1377 // Provide a CFA rule, because register rules require them.
1378 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5)
1379 // Provide an offset(N) rule for register 0x0f9b8a1c.
1380 .D8(google_breakpad::DW_CFA_offset_extended)
1381 .ULEB128(0x0f9b8a1c).ULEB128(0xc979)
1382 .FinishEntry()
1383 // In the FDE...
1384 .FDEHeader(cie, fde_start, fde_size)
1385 // At a second address, provide a new offset(N) rule for reg 0x0f9b8a1c.
1386 .D8(google_breakpad::DW_CFA_advance_loc | 0x3)
1387 .D8(google_breakpad::DW_CFA_offset_extended)
1388 .ULEB128(0x0f9b8a1c).ULEB128(0x3b7b)
1389 // At a third address, restore the original rule for register 0x0f9b8a1c.
1390 .D8(google_breakpad::DW_CFA_advance_loc | 0x04)
1391 .D8(google_breakpad::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c)
1392 .FinishEntry();
1393
1394 {
1395 InSequence s;
1396 EXPECT_CALL(handler,
1397 Entry(_, fde_start, fde_size, version, "", return_register))
1398 .WillOnce(Return(true));
1399 // CIE's CFA rule.
1400 EXPECT_CALL(handler,
1401 ValOffsetRule(fde_start, kCFARegister, 0x56fa0edd, 0x097f78a5))
1402 .WillOnce(Return(true));
1403 // CIE's rule for register 0x0f9b8a1c.
1404 EXPECT_CALL(handler,
1405 OffsetRule(fde_start, 0x0f9b8a1c, kCFARegister,
1406 0xc979 * data_factor))
1407 .WillOnce(Return(true));
1408 // FDE's rule for register 0x0f9b8a1c.
1409 EXPECT_CALL(handler,
1410 OffsetRule(fde_start + 0x3 * code_factor, 0x0f9b8a1c,
1411 kCFARegister, 0x3b7b * data_factor))
1412 .WillOnce(Return(true));
1413 // Restore CIE's rule for register 0x0f9b8a1c.
1414 EXPECT_CALL(handler,
1415 OffsetRule(fde_start + (0x3 + 0x4) * code_factor, 0x0f9b8a1c,
1416 kCFARegister, 0xc979 * data_factor))
1417 .WillOnce(Return(true));
1418 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1419 }
1420
1421 ParseSection(§ion);
1422 }
1423
TEST_F(CFIInsn,DW_CFA_remember_and_restore_state)1424 TEST_F(CFIInsn, DW_CFA_remember_and_restore_state) {
1425 CFISection section(kLittleEndian, 8);
1426 StockCIEAndFDE(§ion);
1427
1428 // We create a state, save it, modify it, and then restore. We
1429 // refer to the state that is overridden the restore as the
1430 // "outgoing" state, and the restored state the "incoming" state.
1431 //
1432 // Register outgoing incoming expect
1433 // 1 offset(N) no rule new "same value" rule
1434 // 2 register(R) offset(N) report changed rule
1435 // 3 offset(N) offset(M) report changed offset
1436 // 4 offset(N) offset(N) no report
1437 // 5 offset(N) no rule new "same value" rule
1438 section
1439 // Create the "incoming" state, which we will save and later restore.
1440 .D8(google_breakpad::DW_CFA_offset | 2).ULEB128(0x9806)
1441 .D8(google_breakpad::DW_CFA_offset | 3).ULEB128(0x995d)
1442 .D8(google_breakpad::DW_CFA_offset | 4).ULEB128(0x7055)
1443 .D8(google_breakpad::DW_CFA_remember_state)
1444 // Advance to a new instruction; an implementation could legitimately
1445 // ignore all but the final rule for a given register at a given address.
1446 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1447 // Create the "outgoing" state, which we will discard.
1448 .D8(google_breakpad::DW_CFA_offset | 1).ULEB128(0xea1a)
1449 .D8(google_breakpad::DW_CFA_register).ULEB128(2).ULEB128(0x1d2a3767)
1450 .D8(google_breakpad::DW_CFA_offset | 3).ULEB128(0xdd29)
1451 .D8(google_breakpad::DW_CFA_offset | 5).ULEB128(0xf1ce)
1452 // At a third address, restore the incoming state.
1453 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1454 .D8(google_breakpad::DW_CFA_restore_state)
1455 .FinishEntry();
1456
1457 uint64_t addr = fde_start;
1458
1459 // Expect the incoming rules to be reported.
1460 EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor))
1461 .InSequence(s).WillOnce(Return(true));
1462 EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor))
1463 .InSequence(s).WillOnce(Return(true));
1464 EXPECT_CALL(handler, OffsetRule(addr, 4, kCFARegister, 0x7055 * data_factor))
1465 .InSequence(s).WillOnce(Return(true));
1466
1467 addr += code_factor;
1468
1469 // After the save, we establish the outgoing rule set.
1470 EXPECT_CALL(handler, OffsetRule(addr, 1, kCFARegister, 0xea1a * data_factor))
1471 .InSequence(s).WillOnce(Return(true));
1472 EXPECT_CALL(handler, RegisterRule(addr, 2, 0x1d2a3767))
1473 .InSequence(s).WillOnce(Return(true));
1474 EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0xdd29 * data_factor))
1475 .InSequence(s).WillOnce(Return(true));
1476 EXPECT_CALL(handler, OffsetRule(addr, 5, kCFARegister, 0xf1ce * data_factor))
1477 .InSequence(s).WillOnce(Return(true));
1478
1479 addr += code_factor;
1480
1481 // Finally, after the restore, expect to see the differences from
1482 // the outgoing to the incoming rules reported.
1483 EXPECT_CALL(handler, SameValueRule(addr, 1))
1484 .InSequence(s).WillOnce(Return(true));
1485 EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor))
1486 .InSequence(s).WillOnce(Return(true));
1487 EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor))
1488 .InSequence(s).WillOnce(Return(true));
1489 EXPECT_CALL(handler, SameValueRule(addr, 5))
1490 .InSequence(s).WillOnce(Return(true));
1491
1492 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1493
1494 ParseSection(§ion);
1495 }
1496
1497 // Check that restoring a rule set reports changes to the CFA rule.
TEST_F(CFIInsn,DW_CFA_remember_and_restore_stateCFA)1498 TEST_F(CFIInsn, DW_CFA_remember_and_restore_stateCFA) {
1499 CFISection section(kBigEndian, 4);
1500 StockCIEAndFDE(§ion);
1501
1502 section
1503 .D8(google_breakpad::DW_CFA_remember_state)
1504 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1505 .D8(google_breakpad::DW_CFA_def_cfa_offset).ULEB128(0x90481102)
1506 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1507 .D8(google_breakpad::DW_CFA_restore_state)
1508 .FinishEntry();
1509
1510 EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, kCFARegister,
1511 cfa_base_register, 0x90481102))
1512 .InSequence(s).WillOnce(Return(true));
1513 EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor * 2, kCFARegister,
1514 cfa_base_register, cfa_offset))
1515 .InSequence(s).WillOnce(Return(true));
1516
1517 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1518
1519 ParseSection(§ion);
1520 }
1521
TEST_F(CFIInsn,DW_CFA_nop)1522 TEST_F(CFIInsn, DW_CFA_nop) {
1523 CFISection section(kLittleEndian, 4);
1524 StockCIEAndFDE(§ion);
1525 section
1526 .D8(google_breakpad::DW_CFA_nop)
1527 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b)
1528 .D8(google_breakpad::DW_CFA_nop)
1529 .FinishEntry();
1530
1531 EXPECT_CALL(handler,
1532 ValOffsetRule(fde_start, kCFARegister, 0x3fb8d4f1, 0x078dc67b))
1533 .InSequence(s).WillOnce(Return(true));
1534 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1535
1536 ParseSection(§ion);
1537 }
1538
TEST_F(CFIInsn,DW_CFA_GNU_window_save)1539 TEST_F(CFIInsn, DW_CFA_GNU_window_save) {
1540 CFISection section(kBigEndian, 4);
1541 StockCIEAndFDE(§ion);
1542 section
1543 .D8(google_breakpad::DW_CFA_GNU_window_save)
1544 .FinishEntry();
1545
1546 EXPECT_CALL(handler, Architecture()).WillRepeatedly(Return("sparc"));
1547
1548 // Don't include all the rules in any particular sequence.
1549
1550 // The caller's %o0-%o7 have become the callee's %i0-%i7. This is
1551 // the GCC register numbering.
1552 for (int i = 8; i < 16; i++)
1553 EXPECT_CALL(handler, RegisterRule(fde_start, i, i + 16))
1554 .WillOnce(Return(true));
1555 // The caller's %l0-%l7 and %i0-%i7 have been saved at the top of
1556 // its frame.
1557 for (int i = 16; i < 32; i++)
1558 EXPECT_CALL(handler, OffsetRule(fde_start, i, kCFARegister, (i-16) * 4))
1559 .WillOnce(Return(true));
1560
1561 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1562
1563 ParseSection(§ion);
1564 }
1565
TEST_F(CFIInsn,DW_CFA_GNU_args_size)1566 TEST_F(CFIInsn, DW_CFA_GNU_args_size) {
1567 CFISection section(kLittleEndian, 8);
1568 StockCIEAndFDE(§ion);
1569 section
1570 .D8(google_breakpad::DW_CFA_GNU_args_size).ULEB128(0xeddfa520)
1571 // Verify that we see this, meaning we parsed the above properly.
1572 .D8(google_breakpad::DW_CFA_offset | 0x23).ULEB128(0x269)
1573 .FinishEntry();
1574
1575 EXPECT_CALL(handler,
1576 OffsetRule(fde_start, 0x23, kCFARegister, 0x269 * data_factor))
1577 .InSequence(s).WillOnce(Return(true));
1578 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1579
1580 ParseSection(§ion);
1581 }
1582
TEST_F(CFIInsn,DW_CFA_GNU_negative_offset_extended)1583 TEST_F(CFIInsn, DW_CFA_GNU_negative_offset_extended) {
1584 CFISection section(kLittleEndian, 4);
1585 StockCIEAndFDE(§ion);
1586 section
1587 .D8(google_breakpad::DW_CFA_GNU_negative_offset_extended)
1588 .ULEB128(0x430cc87a).ULEB128(0x613)
1589 .FinishEntry();
1590
1591 EXPECT_CALL(handler,
1592 OffsetRule(fde_start, 0x430cc87a,
1593 kCFARegister, -0x613 * data_factor))
1594 .InSequence(s).WillOnce(Return(true));
1595 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1596
1597 ParseSection(§ion);
1598 }
1599
1600 // Three FDEs: skip the second
TEST_F(CFIInsn,SkipFDE)1601 TEST_F(CFIInsn, SkipFDE) {
1602 CFISection section(kBigEndian, 4);
1603 Label cie;
1604 section
1605 // CIE, used by all FDEs.
1606 .Mark(&cie)
1607 .CIEHeader(0x010269f2, 0x9177, 0xedca5849, 2, "")
1608 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad)
1609 .FinishEntry()
1610 // First FDE.
1611 .FDEHeader(cie, 0xa870ebdd, 0x60f6aa4)
1612 .D8(google_breakpad::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf)
1613 .FinishEntry()
1614 // Second FDE.
1615 .FDEHeader(cie, 0xc534f7c0, 0xf6552e9, true /* dwarf64 */)
1616 .D8(google_breakpad::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18)
1617 .FinishEntry()
1618 // Third FDE.
1619 .FDEHeader(cie, 0xf681cfc8, 0x7e4594e)
1620 .D8(google_breakpad::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4)
1621 .FinishEntry();
1622
1623 {
1624 InSequence s;
1625
1626 // Process the first FDE.
1627 EXPECT_CALL(handler, Entry(_, 0xa870ebdd, 0x60f6aa4, 2, "", 0xedca5849))
1628 .WillOnce(Return(true));
1629 EXPECT_CALL(handler, ValOffsetRule(0xa870ebdd, kCFARegister,
1630 0x42ed390b, 0x98f43aad))
1631 .WillOnce(Return(true));
1632 EXPECT_CALL(handler, RegisterRule(0xa870ebdd, 0x3a860351, 0x6c9a6bcf))
1633 .WillOnce(Return(true));
1634 EXPECT_CALL(handler, End())
1635 .WillOnce(Return(true));
1636
1637 // Skip the second FDE.
1638 EXPECT_CALL(handler, Entry(_, 0xc534f7c0, 0xf6552e9, 2, "", 0xedca5849))
1639 .WillOnce(Return(false));
1640
1641 // Process the third FDE.
1642 EXPECT_CALL(handler, Entry(_, 0xf681cfc8, 0x7e4594e, 2, "", 0xedca5849))
1643 .WillOnce(Return(true));
1644 EXPECT_CALL(handler, ValOffsetRule(0xf681cfc8, kCFARegister,
1645 0x42ed390b, 0x98f43aad))
1646 .WillOnce(Return(true));
1647 EXPECT_CALL(handler, RegisterRule(0xf681cfc8, 0x26c53934, 0x18eeb8a4))
1648 .WillOnce(Return(true));
1649 EXPECT_CALL(handler, End())
1650 .WillOnce(Return(true));
1651 }
1652
1653 ParseSection(§ion);
1654 }
1655
1656 // Quit processing in the middle of an entry's instructions.
TEST_F(CFIInsn,QuitMidentry)1657 TEST_F(CFIInsn, QuitMidentry) {
1658 CFISection section(kLittleEndian, 8);
1659 StockCIEAndFDE(§ion);
1660 section
1661 .D8(google_breakpad::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431)
1662 .D8(google_breakpad::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat")
1663 .FinishEntry();
1664
1665 EXPECT_CALL(handler, RegisterRule(fde_start, 0xe0cf850d, 0x15aab431))
1666 .InSequence(s).WillOnce(Return(false));
1667 EXPECT_CALL(handler, End())
1668 .InSequence(s).WillOnce(Return(true));
1669
1670 ParseSection(§ion, false);
1671 }
1672
1673 class CFIRestore: public CFIInsnFixture, public Test { };
1674
TEST_F(CFIRestore,RestoreUndefinedRuleUnchanged)1675 TEST_F(CFIRestore, RestoreUndefinedRuleUnchanged) {
1676 CFISection section(kLittleEndian, 4);
1677 StockCIEAndFDE(§ion);
1678 section
1679 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x0bac878e)
1680 .D8(google_breakpad::DW_CFA_remember_state)
1681 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1682 .D8(google_breakpad::DW_CFA_restore_state)
1683 .FinishEntry();
1684
1685 EXPECT_CALL(handler, UndefinedRule(fde_start, 0x0bac878e))
1686 .InSequence(s).WillOnce(Return(true));
1687 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1688
1689 ParseSection(§ion);
1690 }
1691
TEST_F(CFIRestore,RestoreUndefinedRuleChanged)1692 TEST_F(CFIRestore, RestoreUndefinedRuleChanged) {
1693 CFISection section(kLittleEndian, 4);
1694 StockCIEAndFDE(§ion);
1695 section
1696 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x7dedff5f)
1697 .D8(google_breakpad::DW_CFA_remember_state)
1698 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1699 .D8(google_breakpad::DW_CFA_same_value).ULEB128(0x7dedff5f)
1700 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1701 .D8(google_breakpad::DW_CFA_restore_state)
1702 .FinishEntry();
1703
1704 EXPECT_CALL(handler, UndefinedRule(fde_start, 0x7dedff5f))
1705 .InSequence(s).WillOnce(Return(true));
1706 EXPECT_CALL(handler, SameValueRule(fde_start + code_factor, 0x7dedff5f))
1707 .InSequence(s).WillOnce(Return(true));
1708 EXPECT_CALL(handler, UndefinedRule(fde_start + 2 * code_factor, 0x7dedff5f))
1709 .InSequence(s).WillOnce(Return(true));
1710 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1711
1712 ParseSection(§ion);
1713 }
1714
TEST_F(CFIRestore,RestoreSameValueRuleUnchanged)1715 TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) {
1716 CFISection section(kLittleEndian, 4);
1717 StockCIEAndFDE(§ion);
1718 section
1719 .D8(google_breakpad::DW_CFA_same_value).ULEB128(0xadbc9b3a)
1720 .D8(google_breakpad::DW_CFA_remember_state)
1721 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1722 .D8(google_breakpad::DW_CFA_restore_state)
1723 .FinishEntry();
1724
1725 EXPECT_CALL(handler, SameValueRule(fde_start, 0xadbc9b3a))
1726 .InSequence(s).WillOnce(Return(true));
1727 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1728
1729 ParseSection(§ion);
1730 }
1731
TEST_F(CFIRestore,RestoreSameValueRuleChanged)1732 TEST_F(CFIRestore, RestoreSameValueRuleChanged) {
1733 CFISection section(kLittleEndian, 4);
1734 StockCIEAndFDE(§ion);
1735 section
1736 .D8(google_breakpad::DW_CFA_same_value).ULEB128(0x3d90dcb5)
1737 .D8(google_breakpad::DW_CFA_remember_state)
1738 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1739 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x3d90dcb5)
1740 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1741 .D8(google_breakpad::DW_CFA_restore_state)
1742 .FinishEntry();
1743
1744 EXPECT_CALL(handler, SameValueRule(fde_start, 0x3d90dcb5))
1745 .InSequence(s).WillOnce(Return(true));
1746 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x3d90dcb5))
1747 .InSequence(s).WillOnce(Return(true));
1748 EXPECT_CALL(handler, SameValueRule(fde_start + 2 * code_factor, 0x3d90dcb5))
1749 .InSequence(s).WillOnce(Return(true));
1750 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1751
1752 ParseSection(§ion);
1753 }
1754
TEST_F(CFIRestore,RestoreOffsetRuleUnchanged)1755 TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) {
1756 CFISection section(kLittleEndian, 4);
1757 StockCIEAndFDE(§ion);
1758 section
1759 .D8(google_breakpad::DW_CFA_offset | 0x14).ULEB128(0xb6f)
1760 .D8(google_breakpad::DW_CFA_remember_state)
1761 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1762 .D8(google_breakpad::DW_CFA_restore_state)
1763 .FinishEntry();
1764
1765 EXPECT_CALL(handler, OffsetRule(fde_start, 0x14,
1766 kCFARegister, 0xb6f * data_factor))
1767 .InSequence(s).WillOnce(Return(true));
1768 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1769
1770 ParseSection(§ion);
1771 }
1772
TEST_F(CFIRestore,RestoreOffsetRuleChanged)1773 TEST_F(CFIRestore, RestoreOffsetRuleChanged) {
1774 CFISection section(kLittleEndian, 4);
1775 StockCIEAndFDE(§ion);
1776 section
1777 .D8(google_breakpad::DW_CFA_offset | 0x21).ULEB128(0xeb7)
1778 .D8(google_breakpad::DW_CFA_remember_state)
1779 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1780 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x21)
1781 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1782 .D8(google_breakpad::DW_CFA_restore_state)
1783 .FinishEntry();
1784
1785 EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
1786 kCFARegister, 0xeb7 * data_factor))
1787 .InSequence(s).WillOnce(Return(true));
1788 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x21))
1789 .InSequence(s).WillOnce(Return(true));
1790 EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21,
1791 kCFARegister, 0xeb7 * data_factor))
1792 .InSequence(s).WillOnce(Return(true));
1793 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1794
1795 ParseSection(§ion);
1796 }
1797
TEST_F(CFIRestore,RestoreOffsetRuleChangedOffset)1798 TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) {
1799 CFISection section(kLittleEndian, 4);
1800 StockCIEAndFDE(§ion);
1801 section
1802 .D8(google_breakpad::DW_CFA_offset | 0x21).ULEB128(0x134)
1803 .D8(google_breakpad::DW_CFA_remember_state)
1804 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1805 .D8(google_breakpad::DW_CFA_offset | 0x21).ULEB128(0xf4f)
1806 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1807 .D8(google_breakpad::DW_CFA_restore_state)
1808 .FinishEntry();
1809
1810 EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
1811 kCFARegister, 0x134 * data_factor))
1812 .InSequence(s).WillOnce(Return(true));
1813 EXPECT_CALL(handler, OffsetRule(fde_start + code_factor, 0x21,
1814 kCFARegister, 0xf4f * data_factor))
1815 .InSequence(s).WillOnce(Return(true));
1816 EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21,
1817 kCFARegister, 0x134 * data_factor))
1818 .InSequence(s).WillOnce(Return(true));
1819 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1820
1821 ParseSection(§ion);
1822 }
1823
TEST_F(CFIRestore,RestoreValOffsetRuleUnchanged)1824 TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) {
1825 CFISection section(kLittleEndian, 4);
1826 StockCIEAndFDE(§ion);
1827 section
1828 .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c)
1829 .D8(google_breakpad::DW_CFA_remember_state)
1830 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1831 .D8(google_breakpad::DW_CFA_restore_state)
1832 .FinishEntry();
1833
1834 EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x829caee6,
1835 kCFARegister, 0xe4c * data_factor))
1836 .InSequence(s).WillOnce(Return(true));
1837 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1838
1839 ParseSection(§ion);
1840 }
1841
TEST_F(CFIRestore,RestoreValOffsetRuleChanged)1842 TEST_F(CFIRestore, RestoreValOffsetRuleChanged) {
1843 CFISection section(kLittleEndian, 4);
1844 StockCIEAndFDE(§ion);
1845 section
1846 .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7)
1847 .D8(google_breakpad::DW_CFA_remember_state)
1848 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1849 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xf17c36d6)
1850 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1851 .D8(google_breakpad::DW_CFA_restore_state)
1852 .FinishEntry();
1853
1854 EXPECT_CALL(handler, ValOffsetRule(fde_start, 0xf17c36d6,
1855 kCFARegister, 0xeb7 * data_factor))
1856 .InSequence(s).WillOnce(Return(true));
1857 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xf17c36d6))
1858 .InSequence(s).WillOnce(Return(true));
1859 EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0xf17c36d6,
1860 kCFARegister, 0xeb7 * data_factor))
1861 .InSequence(s).WillOnce(Return(true));
1862 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1863
1864 ParseSection(§ion);
1865 }
1866
TEST_F(CFIRestore,RestoreValOffsetRuleChangedValOffset)1867 TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) {
1868 CFISection section(kLittleEndian, 4);
1869 StockCIEAndFDE(§ion);
1870 section
1871 .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562)
1872 .D8(google_breakpad::DW_CFA_remember_state)
1873 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1874 .D8(google_breakpad::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88)
1875 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1876 .D8(google_breakpad::DW_CFA_restore_state)
1877 .FinishEntry();
1878
1879 EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x2cf0ab1b,
1880 kCFARegister, 0x562 * data_factor))
1881 .InSequence(s).WillOnce(Return(true));
1882 EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, 0x2cf0ab1b,
1883 kCFARegister, 0xe88 * data_factor))
1884 .InSequence(s).WillOnce(Return(true));
1885 EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0x2cf0ab1b,
1886 kCFARegister, 0x562 * data_factor))
1887 .InSequence(s).WillOnce(Return(true));
1888 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1889
1890 ParseSection(§ion);
1891 }
1892
TEST_F(CFIRestore,RestoreRegisterRuleUnchanged)1893 TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) {
1894 CFISection section(kLittleEndian, 4);
1895 StockCIEAndFDE(§ion);
1896 section
1897 .D8(google_breakpad::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce)
1898 .D8(google_breakpad::DW_CFA_remember_state)
1899 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1900 .D8(google_breakpad::DW_CFA_restore_state)
1901 .FinishEntry();
1902
1903 EXPECT_CALL(handler, RegisterRule(fde_start, 0x77514acc, 0x464de4ce))
1904 .InSequence(s).WillOnce(Return(true));
1905 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1906
1907 ParseSection(§ion);
1908 }
1909
TEST_F(CFIRestore,RestoreRegisterRuleChanged)1910 TEST_F(CFIRestore, RestoreRegisterRuleChanged) {
1911 CFISection section(kLittleEndian, 4);
1912 StockCIEAndFDE(§ion);
1913 section
1914 .D8(google_breakpad::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559)
1915 .D8(google_breakpad::DW_CFA_remember_state)
1916 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1917 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xe39acce5)
1918 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1919 .D8(google_breakpad::DW_CFA_restore_state)
1920 .FinishEntry();
1921
1922 EXPECT_CALL(handler, RegisterRule(fde_start, 0xe39acce5, 0x095f1559))
1923 .InSequence(s).WillOnce(Return(true));
1924 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xe39acce5))
1925 .InSequence(s).WillOnce(Return(true));
1926 EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xe39acce5,
1927 0x095f1559))
1928 .InSequence(s).WillOnce(Return(true));
1929 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1930
1931 ParseSection(§ion);
1932 }
1933
TEST_F(CFIRestore,RestoreRegisterRuleChangedRegister)1934 TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) {
1935 CFISection section(kLittleEndian, 4);
1936 StockCIEAndFDE(§ion);
1937 section
1938 .D8(google_breakpad::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a)
1939 .D8(google_breakpad::DW_CFA_remember_state)
1940 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1941 .D8(google_breakpad::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742)
1942 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1943 .D8(google_breakpad::DW_CFA_restore_state)
1944 .FinishEntry();
1945
1946 EXPECT_CALL(handler, RegisterRule(fde_start, 0xd40e21b1, 0x16607d6a))
1947 .InSequence(s).WillOnce(Return(true));
1948 EXPECT_CALL(handler, RegisterRule(fde_start + code_factor, 0xd40e21b1,
1949 0xbabb4742))
1950 .InSequence(s).WillOnce(Return(true));
1951 EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xd40e21b1,
1952 0x16607d6a))
1953 .InSequence(s).WillOnce(Return(true));
1954 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1955
1956 ParseSection(§ion);
1957 }
1958
TEST_F(CFIRestore,RestoreExpressionRuleUnchanged)1959 TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) {
1960 CFISection section(kLittleEndian, 4);
1961 StockCIEAndFDE(§ion);
1962 section
1963 .D8(google_breakpad::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf")
1964 .D8(google_breakpad::DW_CFA_remember_state)
1965 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1966 .D8(google_breakpad::DW_CFA_restore_state)
1967 .FinishEntry();
1968
1969 EXPECT_CALL(handler, ExpressionRule(fde_start, 0x666ae152, "dwarf"))
1970 .InSequence(s).WillOnce(Return(true));
1971 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1972
1973 ParseSection(§ion);
1974 }
1975
TEST_F(CFIRestore,RestoreExpressionRuleChanged)1976 TEST_F(CFIRestore, RestoreExpressionRuleChanged) {
1977 CFISection section(kLittleEndian, 4);
1978 StockCIEAndFDE(§ion);
1979 section
1980 .D8(google_breakpad::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf")
1981 .D8(google_breakpad::DW_CFA_remember_state)
1982 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1983 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xb5ca5c46)
1984 .D8(google_breakpad::DW_CFA_advance_loc | 1)
1985 .D8(google_breakpad::DW_CFA_restore_state)
1986 .FinishEntry();
1987
1988 EXPECT_CALL(handler, ExpressionRule(fde_start, 0xb5ca5c46, "elf"))
1989 .InSequence(s).WillOnce(Return(true));
1990 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46))
1991 .InSequence(s).WillOnce(Return(true));
1992 EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46,
1993 "elf"))
1994 .InSequence(s).WillOnce(Return(true));
1995 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1996
1997 ParseSection(§ion);
1998 }
1999
TEST_F(CFIRestore,RestoreExpressionRuleChangedExpression)2000 TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) {
2001 CFISection section(kLittleEndian, 4);
2002 StockCIEAndFDE(§ion);
2003 section
2004 .D8(google_breakpad::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf")
2005 .D8(google_breakpad::DW_CFA_remember_state)
2006 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2007 .D8(google_breakpad::DW_CFA_expression).ULEB128(0x500f5739).Block("orc")
2008 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2009 .D8(google_breakpad::DW_CFA_restore_state)
2010 .FinishEntry();
2011
2012 EXPECT_CALL(handler, ExpressionRule(fde_start, 0x500f5739, "smurf"))
2013 .InSequence(s).WillOnce(Return(true));
2014 EXPECT_CALL(handler, ExpressionRule(fde_start + code_factor, 0x500f5739,
2015 "orc"))
2016 .InSequence(s).WillOnce(Return(true));
2017 // Expectations are not wishes.
2018 EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0x500f5739,
2019 "smurf"))
2020 .InSequence(s).WillOnce(Return(true));
2021 EXPECT_CALL(handler, End()).WillOnce(Return(true));
2022
2023 ParseSection(§ion);
2024 }
2025
TEST_F(CFIRestore,RestoreValExpressionRuleUnchanged)2026 TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) {
2027 CFISection section(kLittleEndian, 4);
2028 StockCIEAndFDE(§ion);
2029 section
2030 .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0x666ae152)
2031 .Block("hideous")
2032 .D8(google_breakpad::DW_CFA_remember_state)
2033 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2034 .D8(google_breakpad::DW_CFA_restore_state)
2035 .FinishEntry();
2036
2037 EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x666ae152, "hideous"))
2038 .InSequence(s).WillOnce(Return(true));
2039 EXPECT_CALL(handler, End()).WillOnce(Return(true));
2040
2041 ParseSection(§ion);
2042 }
2043
TEST_F(CFIRestore,RestoreValExpressionRuleChanged)2044 TEST_F(CFIRestore, RestoreValExpressionRuleChanged) {
2045 CFISection section(kLittleEndian, 4);
2046 StockCIEAndFDE(§ion);
2047 section
2048 .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0xb5ca5c46)
2049 .Block("revolting")
2050 .D8(google_breakpad::DW_CFA_remember_state)
2051 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2052 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0xb5ca5c46)
2053 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2054 .D8(google_breakpad::DW_CFA_restore_state)
2055 .FinishEntry();
2056
2057 PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChanged", section);
2058
2059 EXPECT_CALL(handler, ValExpressionRule(fde_start, 0xb5ca5c46, "revolting"))
2060 .InSequence(s).WillOnce(Return(true));
2061 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46))
2062 .InSequence(s).WillOnce(Return(true));
2063 EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46,
2064 "revolting"))
2065 .InSequence(s).WillOnce(Return(true));
2066 EXPECT_CALL(handler, End()).WillOnce(Return(true));
2067
2068 ParseSection(§ion);
2069 }
2070
TEST_F(CFIRestore,RestoreValExpressionRuleChangedValExpression)2071 TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) {
2072 CFISection section(kLittleEndian, 4);
2073 StockCIEAndFDE(§ion);
2074 section
2075 .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0x500f5739)
2076 .Block("repulsive")
2077 .D8(google_breakpad::DW_CFA_remember_state)
2078 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2079 .D8(google_breakpad::DW_CFA_val_expression).ULEB128(0x500f5739)
2080 .Block("nauseous")
2081 .D8(google_breakpad::DW_CFA_advance_loc | 1)
2082 .D8(google_breakpad::DW_CFA_restore_state)
2083 .FinishEntry();
2084
2085 PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChangedValExpression",
2086 section);
2087
2088 EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x500f5739, "repulsive"))
2089 .InSequence(s).WillOnce(Return(true));
2090 EXPECT_CALL(handler, ValExpressionRule(fde_start + code_factor, 0x500f5739,
2091 "nauseous"))
2092 .InSequence(s).WillOnce(Return(true));
2093 // Expectations are not wishes.
2094 EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0x500f5739,
2095 "repulsive"))
2096 .InSequence(s).WillOnce(Return(true));
2097 EXPECT_CALL(handler, End()).WillOnce(Return(true));
2098
2099 ParseSection(§ion);
2100 }
2101
2102 struct EHFrameFixture: public CFIInsnFixture {
EHFrameFixtureEHFrameFixture2103 EHFrameFixture()
2104 : CFIInsnFixture(), section(kBigEndian, 4, true) {
2105 encoded_pointer_bases.cfi = 0x7f496cb2;
2106 encoded_pointer_bases.text = 0x540f67b6;
2107 encoded_pointer_bases.data = 0xe3eab768;
2108 section.SetEncodedPointerBases(encoded_pointer_bases);
2109 }
2110 CFISection section;
2111 CFISection::EncodedPointerBases encoded_pointer_bases;
2112
2113 // Parse CFIInsnFixture::ParseSection, but parse the section as
2114 // .eh_frame data, supplying stock base addresses.
ParseEHFrameSectionEHFrameFixture2115 void ParseEHFrameSection(CFISection *section, bool succeeds = true) {
2116 EXPECT_TRUE(section->ContainsEHFrame());
2117 string contents;
2118 EXPECT_TRUE(section->GetContents(&contents));
2119 google_breakpad::Endianness endianness;
2120 if (section->endianness() == kBigEndian)
2121 endianness = ENDIANNESS_BIG;
2122 else {
2123 assert(section->endianness() == kLittleEndian);
2124 endianness = ENDIANNESS_LITTLE;
2125 }
2126 ByteReader byte_reader(endianness);
2127 byte_reader.SetAddressSize(section->AddressSize());
2128 byte_reader.SetCFIDataBase(encoded_pointer_bases.cfi,
2129 reinterpret_cast<const uint8_t*>(contents.data()));
2130 byte_reader.SetTextBase(encoded_pointer_bases.text);
2131 byte_reader.SetDataBase(encoded_pointer_bases.data);
2132 CallFrameInfo parser(reinterpret_cast<const uint8_t*>(contents.data()),
2133 contents.size(),
2134 &byte_reader, &handler, &reporter, true);
2135 if (succeeds)
2136 EXPECT_TRUE(parser.Start());
2137 else
2138 EXPECT_FALSE(parser.Start());
2139 }
2140
2141 };
2142
2143 class EHFrame: public EHFrameFixture, public Test { };
2144
2145 // A simple CIE, an FDE, and a terminator.
TEST_F(EHFrame,Terminator)2146 TEST_F(EHFrame, Terminator) {
2147 Label cie;
2148 section
2149 .Mark(&cie)
2150 .CIEHeader(9968, 2466, 67, 1, "")
2151 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372)
2152 .FinishEntry()
2153 .FDEHeader(cie, 0x848037a1, 0x7b30475e)
2154 .D8(google_breakpad::DW_CFA_set_loc).D32(0x17713850)
2155 .D8(google_breakpad::DW_CFA_undefined).ULEB128(5721)
2156 .FinishEntry()
2157 .D32(0) // Terminate the sequence.
2158 // This FDE should be ignored.
2159 .FDEHeader(cie, 0xf19629fe, 0x439fb09b)
2160 .FinishEntry();
2161
2162 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.Terminator", section);
2163
2164 EXPECT_CALL(handler, Entry(_, 0x848037a1, 0x7b30475e, 1, "", 67))
2165 .InSequence(s).WillOnce(Return(true));
2166 EXPECT_CALL(handler, ValOffsetRule(0x848037a1, kCFARegister, 3772, 1372))
2167 .InSequence(s).WillOnce(Return(true));
2168 EXPECT_CALL(handler, UndefinedRule(0x17713850, 5721))
2169 .InSequence(s).WillOnce(Return(true));
2170 EXPECT_CALL(handler, End())
2171 .InSequence(s).WillOnce(Return(true));
2172 EXPECT_CALL(reporter, EarlyEHTerminator(_))
2173 .InSequence(s).WillOnce(Return());
2174
2175 ParseEHFrameSection(§ion);
2176 }
2177
2178 // The parser should recognize the Linux Standards Base 'z' augmentations.
TEST_F(EHFrame,SimpleFDE)2179 TEST_F(EHFrame, SimpleFDE) {
2180 DwarfPointerEncoding lsda_encoding =
2181 DwarfPointerEncoding(google_breakpad::DW_EH_PE_indirect
2182 | google_breakpad::DW_EH_PE_datarel
2183 | google_breakpad::DW_EH_PE_sdata2);
2184 DwarfPointerEncoding fde_encoding =
2185 DwarfPointerEncoding(google_breakpad::DW_EH_PE_textrel
2186 | google_breakpad::DW_EH_PE_udata2);
2187
2188 section.SetPointerEncoding(fde_encoding);
2189 section.SetEncodedPointerBases(encoded_pointer_bases);
2190 Label cie;
2191 section
2192 .Mark(&cie)
2193 .CIEHeader(4873, 7012, 100, 1, "zSLPR")
2194 .ULEB128(7) // Augmentation data length
2195 .D8(lsda_encoding) // LSDA pointer format
2196 .D8(google_breakpad::DW_EH_PE_pcrel) // personality pointer format
2197 .EncodedPointer(0x97baa00, google_breakpad::DW_EH_PE_pcrel) // and value
2198 .D8(fde_encoding) // FDE pointer format
2199 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(6706).ULEB128(31)
2200 .FinishEntry()
2201 .FDEHeader(cie, 0x540f6b56, 0xf686)
2202 .ULEB128(2) // Augmentation data length
2203 .EncodedPointer(0xe3eab475, lsda_encoding) // LSDA pointer, signed
2204 .D8(google_breakpad::DW_CFA_set_loc)
2205 .EncodedPointer(0x540fa4ce, fde_encoding)
2206 .D8(google_breakpad::DW_CFA_undefined).ULEB128(0x675e)
2207 .FinishEntry()
2208 .D32(0); // terminator
2209
2210 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.SimpleFDE", section);
2211
2212 EXPECT_CALL(handler, Entry(_, 0x540f6b56, 0xf686, 1, "zSLPR", 100))
2213 .InSequence(s).WillOnce(Return(true));
2214 EXPECT_CALL(handler, PersonalityRoutine(0x97baa00, false))
2215 .InSequence(s).WillOnce(Return(true));
2216 EXPECT_CALL(handler, LanguageSpecificDataArea(0xe3eab475, true))
2217 .InSequence(s).WillOnce(Return(true));
2218 EXPECT_CALL(handler, SignalHandler())
2219 .InSequence(s).WillOnce(Return(true));
2220 EXPECT_CALL(handler, ValOffsetRule(0x540f6b56, kCFARegister, 6706, 31))
2221 .InSequence(s).WillOnce(Return(true));
2222 EXPECT_CALL(handler, UndefinedRule(0x540fa4ce, 0x675e))
2223 .InSequence(s).WillOnce(Return(true));
2224 EXPECT_CALL(handler, End())
2225 .InSequence(s).WillOnce(Return(true));
2226
2227 ParseEHFrameSection(§ion);
2228 }
2229
2230 // Check that we can handle an empty 'z' augmentation.
TEST_F(EHFrame,EmptyZ)2231 TEST_F(EHFrame, EmptyZ) {
2232 Label cie;
2233 section
2234 .Mark(&cie)
2235 .CIEHeader(5955, 5805, 228, 1, "z")
2236 .ULEB128(0) // Augmentation data length
2237 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247)
2238 .FinishEntry()
2239 .FDEHeader(cie, 0xda007738, 0xfb55c641)
2240 .ULEB128(0) // Augmentation data length
2241 .D8(google_breakpad::DW_CFA_advance_loc1).D8(11)
2242 .D8(google_breakpad::DW_CFA_undefined).ULEB128(3769)
2243 .FinishEntry();
2244
2245 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.EmptyZ", section);
2246
2247 EXPECT_CALL(handler, Entry(_, 0xda007738, 0xfb55c641, 1, "z", 228))
2248 .InSequence(s).WillOnce(Return(true));
2249 EXPECT_CALL(handler, ValOffsetRule(0xda007738, kCFARegister, 3629, 247))
2250 .InSequence(s).WillOnce(Return(true));
2251 EXPECT_CALL(handler, UndefinedRule(0xda007738 + 11 * 5955, 3769))
2252 .InSequence(s).WillOnce(Return(true));
2253 EXPECT_CALL(handler, End())
2254 .InSequence(s).WillOnce(Return(true));
2255
2256 ParseEHFrameSection(§ion);
2257 }
2258
2259 // Check that we recognize bad 'z' augmentation characters.
TEST_F(EHFrame,BadZ)2260 TEST_F(EHFrame, BadZ) {
2261 Label cie;
2262 section
2263 .Mark(&cie)
2264 .CIEHeader(6937, 1045, 142, 1, "zQ")
2265 .ULEB128(0) // Augmentation data length
2266 .D8(google_breakpad::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725)
2267 .FinishEntry()
2268 .FDEHeader(cie, 0x1293efa8, 0x236f53f2)
2269 .ULEB128(0) // Augmentation data length
2270 .D8(google_breakpad::DW_CFA_advance_loc | 12)
2271 .D8(google_breakpad::DW_CFA_register).ULEB128(5667).ULEB128(3462)
2272 .FinishEntry();
2273
2274 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.BadZ", section);
2275
2276 EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "zQ"))
2277 .WillOnce(Return());
2278
2279 ParseEHFrameSection(§ion, false);
2280 }
2281
TEST_F(EHFrame,zL)2282 TEST_F(EHFrame, zL) {
2283 Label cie;
2284 DwarfPointerEncoding lsda_encoding =
2285 DwarfPointerEncoding(google_breakpad::DW_EH_PE_funcrel
2286 | google_breakpad::DW_EH_PE_udata2);
2287 section
2288 .Mark(&cie)
2289 .CIEHeader(9285, 9959, 54, 1, "zL")
2290 .ULEB128(1) // Augmentation data length
2291 .D8(lsda_encoding) // encoding for LSDA pointer in FDE
2292
2293 .FinishEntry()
2294 .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
2295 .ULEB128(2) // Augmentation data length
2296 .EncodedPointer(0xd40099cd, lsda_encoding) // LSDA pointer
2297 .FinishEntry()
2298 .D32(0); // terminator
2299
2300 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zL", section);
2301
2302 EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zL", 54))
2303 .InSequence(s).WillOnce(Return(true));
2304 EXPECT_CALL(handler, LanguageSpecificDataArea(0xd40099cd, false))
2305 .InSequence(s).WillOnce(Return(true));
2306 EXPECT_CALL(handler, End())
2307 .InSequence(s).WillOnce(Return(true));
2308
2309 ParseEHFrameSection(§ion);
2310 }
2311
TEST_F(EHFrame,zP)2312 TEST_F(EHFrame, zP) {
2313 Label cie;
2314 DwarfPointerEncoding personality_encoding =
2315 DwarfPointerEncoding(google_breakpad::DW_EH_PE_datarel
2316 | google_breakpad::DW_EH_PE_udata2);
2317 section
2318 .Mark(&cie)
2319 .CIEHeader(1097, 6313, 17, 1, "zP")
2320 .ULEB128(3) // Augmentation data length
2321 .D8(personality_encoding) // encoding for personality routine
2322 .EncodedPointer(0xe3eaccac, personality_encoding) // value
2323 .FinishEntry()
2324 .FDEHeader(cie, 0x0c8350c9, 0xbef11087)
2325 .ULEB128(0) // Augmentation data length
2326 .FinishEntry()
2327 .D32(0); // terminator
2328
2329 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zP", section);
2330
2331 EXPECT_CALL(handler, Entry(_, 0x0c8350c9, 0xbef11087, 1, "zP", 17))
2332 .InSequence(s).WillOnce(Return(true));
2333 EXPECT_CALL(handler, PersonalityRoutine(0xe3eaccac, false))
2334 .InSequence(s).WillOnce(Return(true));
2335 EXPECT_CALL(handler, End())
2336 .InSequence(s).WillOnce(Return(true));
2337
2338 ParseEHFrameSection(§ion);
2339 }
2340
TEST_F(EHFrame,zR)2341 TEST_F(EHFrame, zR) {
2342 Label cie;
2343 DwarfPointerEncoding pointer_encoding =
2344 DwarfPointerEncoding(google_breakpad::DW_EH_PE_textrel
2345 | google_breakpad::DW_EH_PE_sdata2);
2346 section.SetPointerEncoding(pointer_encoding);
2347 section
2348 .Mark(&cie)
2349 .CIEHeader(8011, 5496, 75, 1, "zR")
2350 .ULEB128(1) // Augmentation data length
2351 .D8(pointer_encoding) // encoding for FDE addresses
2352 .FinishEntry()
2353 .FDEHeader(cie, 0x540f9431, 0xbd0)
2354 .ULEB128(0) // Augmentation data length
2355 .FinishEntry()
2356 .D32(0); // terminator
2357
2358 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zR", section);
2359
2360 EXPECT_CALL(handler, Entry(_, 0x540f9431, 0xbd0, 1, "zR", 75))
2361 .InSequence(s).WillOnce(Return(true));
2362 EXPECT_CALL(handler, End())
2363 .InSequence(s).WillOnce(Return(true));
2364
2365 ParseEHFrameSection(§ion);
2366 }
2367
TEST_F(EHFrame,zS)2368 TEST_F(EHFrame, zS) {
2369 Label cie;
2370 section
2371 .Mark(&cie)
2372 .CIEHeader(9217, 7694, 57, 1, "zS")
2373 .ULEB128(0) // Augmentation data length
2374 .FinishEntry()
2375 .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
2376 .ULEB128(0) // Augmentation data length
2377 .FinishEntry()
2378 .D32(0); // terminator
2379
2380 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zS", section);
2381
2382 EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zS", 57))
2383 .InSequence(s).WillOnce(Return(true));
2384 EXPECT_CALL(handler, SignalHandler())
2385 .InSequence(s).WillOnce(Return(true));
2386 EXPECT_CALL(handler, End())
2387 .InSequence(s).WillOnce(Return(true));
2388
2389 ParseEHFrameSection(§ion);
2390 }
2391
2392 // These tests require manual inspection of the test output.
2393 struct CFIReporterFixture {
CFIReporterFixtureCFIReporterFixture2394 CFIReporterFixture() : reporter("test file name", "test section name") { }
2395 CallFrameInfo::Reporter reporter;
2396 };
2397
2398 class CFIReporter: public CFIReporterFixture, public Test { };
2399
TEST_F(CFIReporter,Incomplete)2400 TEST_F(CFIReporter, Incomplete) {
2401 reporter.Incomplete(0x0102030405060708ULL, CallFrameInfo::kUnknown);
2402 }
2403
TEST_F(CFIReporter,EarlyEHTerminator)2404 TEST_F(CFIReporter, EarlyEHTerminator) {
2405 reporter.EarlyEHTerminator(0x0102030405060708ULL);
2406 }
2407
TEST_F(CFIReporter,CIEPointerOutOfRange)2408 TEST_F(CFIReporter, CIEPointerOutOfRange) {
2409 reporter.CIEPointerOutOfRange(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
2410 }
2411
TEST_F(CFIReporter,BadCIEId)2412 TEST_F(CFIReporter, BadCIEId) {
2413 reporter.BadCIEId(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
2414 }
2415
TEST_F(CFIReporter,UnrecognizedVersion)2416 TEST_F(CFIReporter, UnrecognizedVersion) {
2417 reporter.UnrecognizedVersion(0x0123456789abcdefULL, 43);
2418 }
2419
TEST_F(CFIReporter,UnrecognizedAugmentation)2420 TEST_F(CFIReporter, UnrecognizedAugmentation) {
2421 reporter.UnrecognizedAugmentation(0x0123456789abcdefULL, "poodles");
2422 }
2423
TEST_F(CFIReporter,InvalidPointerEncoding)2424 TEST_F(CFIReporter, InvalidPointerEncoding) {
2425 reporter.InvalidPointerEncoding(0x0123456789abcdefULL, 0x42);
2426 }
2427
TEST_F(CFIReporter,UnusablePointerEncoding)2428 TEST_F(CFIReporter, UnusablePointerEncoding) {
2429 reporter.UnusablePointerEncoding(0x0123456789abcdefULL, 0x42);
2430 }
2431
TEST_F(CFIReporter,RestoreInCIE)2432 TEST_F(CFIReporter, RestoreInCIE) {
2433 reporter.RestoreInCIE(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
2434 }
2435
TEST_F(CFIReporter,BadInstruction)2436 TEST_F(CFIReporter, BadInstruction) {
2437 reporter.BadInstruction(0x0123456789abcdefULL, CallFrameInfo::kFDE,
2438 0xfedcba9876543210ULL);
2439 }
2440
TEST_F(CFIReporter,NoCFARule)2441 TEST_F(CFIReporter, NoCFARule) {
2442 reporter.NoCFARule(0x0123456789abcdefULL, CallFrameInfo::kCIE,
2443 0xfedcba9876543210ULL);
2444 }
2445
TEST_F(CFIReporter,EmptyStateStack)2446 TEST_F(CFIReporter, EmptyStateStack) {
2447 reporter.EmptyStateStack(0x0123456789abcdefULL, CallFrameInfo::kTerminator,
2448 0xfedcba9876543210ULL);
2449 }
2450
TEST_F(CFIReporter,ClearingCFARule)2451 TEST_F(CFIReporter, ClearingCFARule) {
2452 reporter.ClearingCFARule(0x0123456789abcdefULL, CallFrameInfo::kFDE,
2453 0xfedcba9876543210ULL);
2454 }
2455
2456 #ifdef WRITE_ELF
2457 // See comments at the top of the file mentioning WRITE_ELF for details.
2458
2459 using google_breakpad::test_assembler::Section;
2460
2461 struct ELFSectionHeader {
ELFSectionHeaderELFSectionHeader2462 ELFSectionHeader(unsigned int set_type)
2463 : type(set_type), flags(0), address(0), link(0), info(0),
2464 alignment(1), entry_size(0) { }
2465 Label name;
2466 unsigned int type;
2467 uint64_t flags;
2468 uint64_t address;
2469 Label file_offset;
2470 Label file_size;
2471 unsigned int link;
2472 unsigned int info;
2473 uint64_t alignment;
2474 uint64_t entry_size;
2475 };
2476
AppendSectionHeader(CFISection * table,const ELFSectionHeader & header)2477 void AppendSectionHeader(CFISection* table, const ELFSectionHeader& header) {
2478 (*table)
2479 .D32(header.name) // name, index in string tbl
2480 .D32(header.type) // type
2481 .Address(header.flags) // flags
2482 .Address(header.address) // address in memory
2483 .Address(header.file_offset) // offset in ELF file
2484 .Address(header.file_size) // length in bytes
2485 .D32(header.link) // link to related section
2486 .D32(header.info) // miscellaneous
2487 .Address(header.alignment) // alignment
2488 .Address(header.entry_size); // entry size
2489 }
2490
WriteELFFrameSection(const char * filename,const char * cfi_name,const CFISection & cfi)2491 void WriteELFFrameSection(const char *filename, const char *cfi_name,
2492 const CFISection& cfi) {
2493 int elf_class = cfi.AddressSize() == 4 ? ELFCLASS32 : ELFCLASS64;
2494 int elf_data = (cfi.endianness() == kBigEndian
2495 ? ELFDATA2MSB : ELFDATA2LSB);
2496 CFISection elf(cfi.endianness(), cfi.AddressSize());
2497 Label elf_header_size, section_table_offset;
2498 elf
2499 .Append("\x7f" "ELF")
2500 .D8(elf_class) // 32-bit or 64-bit ELF
2501 .D8(elf_data) // endianness
2502 .D8(1) // ELF version
2503 .D8(ELFOSABI_LINUX) // Operating System/ABI indication
2504 .D8(0) // ABI version
2505 .Append(7, 0xda) // padding
2506 .D16(ET_EXEC) // file type: executable file
2507 .D16(EM_386) // architecture: Intel IA-32
2508 .D32(EV_CURRENT); // ELF version
2509 elf
2510 .Address(0x0123456789abcdefULL) // program entry point
2511 .Address(0) // program header offset
2512 .Address(section_table_offset) // section header offset
2513 .D32(0) // processor-specific flags
2514 .D16(elf_header_size) // ELF header size in bytes */
2515 .D16(elf_class == ELFCLASS32 ? 32 : 56) // program header entry size
2516 .D16(0) // program header table entry count
2517 .D16(elf_class == ELFCLASS32 ? 40 : 64) // section header entry size
2518 .D16(3) // section count
2519 .D16(1) // section name string table
2520 .Mark(&elf_header_size);
2521
2522 // The null section. Every ELF file has one, as the first entry in
2523 // the section header table.
2524 ELFSectionHeader null_header(SHT_NULL);
2525 null_header.file_offset = 0;
2526 null_header.file_size = 0;
2527
2528 // The CFI section. The whole reason for writing out this ELF file
2529 // is to put this in it so that we can run other dumping programs on
2530 // it to check its contents.
2531 ELFSectionHeader cfi_header(SHT_PROGBITS);
2532 cfi_header.file_size = cfi.Size();
2533
2534 // The section holding the names of the sections. This is the
2535 // section whose index appears in the e_shstrndx member of the ELF
2536 // header.
2537 ELFSectionHeader section_names_header(SHT_STRTAB);
2538 CFISection section_names(cfi.endianness(), cfi.AddressSize());
2539 section_names
2540 .Mark(&null_header.name)
2541 .AppendCString("")
2542 .Mark(§ion_names_header.name)
2543 .AppendCString(".shstrtab")
2544 .Mark(&cfi_header.name)
2545 .AppendCString(cfi_name)
2546 .Mark(§ion_names_header.file_size);
2547
2548 // Create the section table. The ELF header's e_shoff member refers
2549 // to this, and the e_shnum member gives the number of entries it
2550 // contains.
2551 CFISection section_table(cfi.endianness(), cfi.AddressSize());
2552 AppendSectionHeader(§ion_table, null_header);
2553 AppendSectionHeader(§ion_table, section_names_header);
2554 AppendSectionHeader(§ion_table, cfi_header);
2555
2556 // Append the section table and the section contents to the ELF file.
2557 elf
2558 .Mark(§ion_table_offset)
2559 .Append(section_table)
2560 .Mark(§ion_names_header.file_offset)
2561 .Append(section_names)
2562 .Mark(&cfi_header.file_offset)
2563 .Append(cfi);
2564
2565 string contents;
2566 if (!elf.GetContents(&contents)) {
2567 fprintf(stderr, "failed to get ELF file contents\n");
2568 exit(1);
2569 }
2570
2571 FILE *out = fopen(filename, "w");
2572 if (!out) {
2573 fprintf(stderr, "error opening ELF file '%s': %s\n",
2574 filename, strerror(errno));
2575 exit(1);
2576 }
2577
2578 if (fwrite(contents.data(), 1, contents.size(), out) != contents.size()) {
2579 fprintf(stderr, "error writing ELF data to '%s': %s\n",
2580 filename, strerror(errno));
2581 exit(1);
2582 }
2583
2584 if (fclose(out) == EOF) {
2585 fprintf(stderr, "error closing ELF file '%s': %s\n",
2586 filename, strerror(errno));
2587 exit(1);
2588 }
2589 }
2590 #endif
2591