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