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