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