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