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