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