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 &section);
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(&section);
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(&section);
709 }
710 
TEST_F(CFIInsn,DW_CFA_advance_loc)711 TEST_F(CFIInsn, DW_CFA_advance_loc) {
712   CFISection section(kBigEndian, 8);
713   StockCIEAndFDE(&section);
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(&section);
731 }
732 
TEST_F(CFIInsn,DW_CFA_advance_loc1)733 TEST_F(CFIInsn, DW_CFA_advance_loc1) {
734   CFISection section(kLittleEndian, 8);
735   StockCIEAndFDE(&section);
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(&section);
751 }
752 
TEST_F(CFIInsn,DW_CFA_advance_loc2)753 TEST_F(CFIInsn, DW_CFA_advance_loc2) {
754   CFISection section(kLittleEndian, 4);
755   StockCIEAndFDE(&section);
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(&section);
771 }
772 
TEST_F(CFIInsn,DW_CFA_advance_loc4)773 TEST_F(CFIInsn, DW_CFA_advance_loc4) {
774   CFISection section(kBigEndian, 8);
775   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
812 }
813 
TEST_F(CFIInsn,DW_CFA_def_cfa)814 TEST_F(CFIInsn, DW_CFA_def_cfa) {
815   CFISection section(kLittleEndian, 4);
816   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
954 }
955 
TEST_F(CFIInsn,DW_CFA_undefined)956 TEST_F(CFIInsn, DW_CFA_undefined) {
957   CFISection section(kLittleEndian, 4);
958   StockCIEAndFDE(&section);
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(&section);
968 }
969 
TEST_F(CFIInsn,DW_CFA_same_value)970 TEST_F(CFIInsn, DW_CFA_same_value) {
971   CFISection section(kLittleEndian, 4);
972   StockCIEAndFDE(&section);
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(&section);
982 }
983 
TEST_F(CFIInsn,DW_CFA_offset)984 TEST_F(CFIInsn, DW_CFA_offset) {
985   CFISection section(kBigEndian, 4);
986   StockCIEAndFDE(&section);
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(&section);
997 }
998 
TEST_F(CFIInsn,DW_CFA_offset_extended)999 TEST_F(CFIInsn, DW_CFA_offset_extended) {
1000   CFISection section(kBigEndian, 4);
1001   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
1035 }
1036 
TEST_F(CFIInsn,DW_CFA_val_offset)1037 TEST_F(CFIInsn, DW_CFA_val_offset) {
1038   CFISection section(kBigEndian, 4);
1039   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
1072 }
1073 
TEST_F(CFIInsn,DW_CFA_register)1074 TEST_F(CFIInsn, DW_CFA_register) {
1075   CFISection section(kLittleEndian, 8);
1076   StockCIEAndFDE(&section);
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(&section);
1086 }
1087 
TEST_F(CFIInsn,DW_CFA_expression)1088 TEST_F(CFIInsn, DW_CFA_expression) {
1089   CFISection section(kBigEndian, 8);
1090   StockCIEAndFDE(&section);
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(&section);
1103 }
1104 
TEST_F(CFIInsn,DW_CFA_val_expression)1105 TEST_F(CFIInsn, DW_CFA_val_expression) {
1106   CFISection section(kBigEndian, 4);
1107   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
1384 }
1385 
TEST_F(CFIInsn,DW_CFA_nop)1386 TEST_F(CFIInsn, DW_CFA_nop) {
1387   CFISection section(kLittleEndian, 4);
1388   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section);
1552 }
1553 
TEST_F(CFIRestore,RestoreUndefinedRuleChanged)1554 TEST_F(CFIRestore, RestoreUndefinedRuleChanged) {
1555   CFISection section(kLittleEndian, 4);
1556   StockCIEAndFDE(&section);
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(&section);
1575 }
1576 
TEST_F(CFIRestore,RestoreSameValueRuleUnchanged)1577 TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) {
1578   CFISection section(kLittleEndian, 4);
1579   StockCIEAndFDE(&section);
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(&section);
1592 }
1593 
TEST_F(CFIRestore,RestoreSameValueRuleChanged)1594 TEST_F(CFIRestore, RestoreSameValueRuleChanged) {
1595   CFISection section(kLittleEndian, 4);
1596   StockCIEAndFDE(&section);
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(&section);
1615 }
1616 
TEST_F(CFIRestore,RestoreOffsetRuleUnchanged)1617 TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) {
1618   CFISection section(kLittleEndian, 4);
1619   StockCIEAndFDE(&section);
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(&section);
1633 }
1634 
TEST_F(CFIRestore,RestoreOffsetRuleChanged)1635 TEST_F(CFIRestore, RestoreOffsetRuleChanged) {
1636   CFISection section(kLittleEndian, 4);
1637   StockCIEAndFDE(&section);
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(&section);
1658 }
1659 
TEST_F(CFIRestore,RestoreOffsetRuleChangedOffset)1660 TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) {
1661   CFISection section(kLittleEndian, 4);
1662   StockCIEAndFDE(&section);
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(&section);
1684 }
1685 
TEST_F(CFIRestore,RestoreValOffsetRuleUnchanged)1686 TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) {
1687   CFISection section(kLittleEndian, 4);
1688   StockCIEAndFDE(&section);
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(&section);
1702 }
1703 
TEST_F(CFIRestore,RestoreValOffsetRuleChanged)1704 TEST_F(CFIRestore, RestoreValOffsetRuleChanged) {
1705   CFISection section(kLittleEndian, 4);
1706   StockCIEAndFDE(&section);
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(&section);
1727 }
1728 
TEST_F(CFIRestore,RestoreValOffsetRuleChangedValOffset)1729 TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) {
1730   CFISection section(kLittleEndian, 4);
1731   StockCIEAndFDE(&section);
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(&section);
1753 }
1754 
TEST_F(CFIRestore,RestoreRegisterRuleUnchanged)1755 TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) {
1756   CFISection section(kLittleEndian, 4);
1757   StockCIEAndFDE(&section);
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(&section);
1770 }
1771 
TEST_F(CFIRestore,RestoreRegisterRuleChanged)1772 TEST_F(CFIRestore, RestoreRegisterRuleChanged) {
1773   CFISection section(kLittleEndian, 4);
1774   StockCIEAndFDE(&section);
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(&section);
1794 }
1795 
TEST_F(CFIRestore,RestoreRegisterRuleChangedRegister)1796 TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) {
1797   CFISection section(kLittleEndian, 4);
1798   StockCIEAndFDE(&section);
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(&section);
1819 }
1820 
TEST_F(CFIRestore,RestoreExpressionRuleUnchanged)1821 TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) {
1822   CFISection section(kLittleEndian, 4);
1823   StockCIEAndFDE(&section);
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(&section);
1836 }
1837 
TEST_F(CFIRestore,RestoreExpressionRuleChanged)1838 TEST_F(CFIRestore, RestoreExpressionRuleChanged) {
1839   CFISection section(kLittleEndian, 4);
1840   StockCIEAndFDE(&section);
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(&section);
1860 }
1861 
TEST_F(CFIRestore,RestoreExpressionRuleChangedExpression)1862 TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) {
1863   CFISection section(kLittleEndian, 4);
1864   StockCIEAndFDE(&section);
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(&section);
1886 }
1887 
TEST_F(CFIRestore,RestoreValExpressionRuleUnchanged)1888 TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) {
1889   CFISection section(kLittleEndian, 4);
1890   StockCIEAndFDE(&section);
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(&section);
1904 }
1905 
TEST_F(CFIRestore,RestoreValExpressionRuleChanged)1906 TEST_F(CFIRestore, RestoreValExpressionRuleChanged) {
1907   CFISection section(kLittleEndian, 4);
1908   StockCIEAndFDE(&section);
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(&section);
1931 }
1932 
TEST_F(CFIRestore,RestoreValExpressionRuleChangedValExpression)1933 TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) {
1934   CFISection section(kLittleEndian, 4);
1935   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section);
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(&section);
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(&section);
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(&section_names_header.name)
2403       .AppendCString(".shstrtab")
2404       .Mark(&cfi_header.name)
2405       .AppendCString(cfi_name)
2406       .Mark(&section_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(&section_table, null_header);
2413   AppendSectionHeader(&section_table, section_names_header);
2414   AppendSectionHeader(&section_table, cfi_header);
2415 
2416   // Append the section table and the section contents to the ELF file.
2417   elf
2418       .Mark(&section_table_offset)
2419       .Append(section_table)
2420       .Mark(&section_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