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