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