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