toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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.
    30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    32 // dwarf2reader_cfi_unittest.cc: Unit tests for dwarf2reader::CallFrameInfo
    34 #include <stdlib.h>
    36 #include <string>
    37 #include <vector>
    39 // The '.eh_frame' format, used by the Linux C++ ABI for exception
    40 // handling, is poorly specified. To help test our support for .eh_frame,
    41 // if you #define WRITE_ELF while compiling this file, and add the
    42 // 'include' directory from the binutils, gcc, or gdb source tree to the
    43 // #include path, then each test that calls the
    44 // PERHAPS_WRITE_DEBUG_FRAME_FILE or PERHAPS_WRITE_EH_FRAME_FILE will write
    45 // an ELF file containing a .debug_frame or .eh_frame section; you can then
    46 // use tools like readelf to examine the test data, and check the tools'
    47 // interpretation against the test's intentions. Each ELF file is named
    48 // "cfitest-TEST", where TEST identifies the particular test.
    49 #ifdef WRITE_ELF
    50 #include <errno.h>
    51 #include <stdio.h>
    52 #include <string.h>
    53 extern "C" {
    54 // To compile with WRITE_ELF, you should add the 'include' directory
    55 // of the binutils, gcc, or gdb source tree to your #include path;
    56 // that directory contains this header.
    57 #include "elf/common.h"
    58 }
    59 #endif
    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"
    68 using google_breakpad::CFISection;
    69 using google_breakpad::test_assembler::Label;
    70 using google_breakpad::test_assembler::kBigEndian;
    71 using google_breakpad::test_assembler::kLittleEndian;
    72 using google_breakpad::test_assembler::Section;
    74 using dwarf2reader::DwarfPointerEncoding;
    75 using dwarf2reader::ENDIANNESS_BIG;
    76 using dwarf2reader::ENDIANNESS_LITTLE;
    77 using dwarf2reader::ByteReader;
    78 using dwarf2reader::CallFrameInfo;
    80 using std::vector;
    81 using testing::InSequence;
    82 using testing::Return;
    83 using testing::Sequence;
    84 using testing::Test;
    85 using testing::_;
    87 #ifdef WRITE_ELF
    88 void WriteELFFrameSection(const char *filename, const char *section_name,
    89                           const CFISection &section);
    90 #define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section)                   \
    91     WriteELFFrameSection("cfitest-" name, ".debug_frame", section);
    92 #define PERHAPS_WRITE_EH_FRAME_FILE(name, section)                      \
    93     WriteELFFrameSection("cfitest-" name, ".eh_frame", section);
    94 #else
    95 #define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section)
    96 #define PERHAPS_WRITE_EH_FRAME_FILE(name, section)
    97 #endif
    99 class MockCallFrameInfoHandler: public CallFrameInfo::Handler {
   100  public:
   101   MOCK_METHOD6(Entry, bool(size_t offset, uint64 address, uint64 length,
   102                            uint8 version, const string &augmentation,
   103                            unsigned return_address));
   104   MOCK_METHOD2(UndefinedRule, bool(uint64 address, int reg));
   105   MOCK_METHOD2(SameValueRule, bool(uint64 address, int reg));
   106   MOCK_METHOD4(OffsetRule, bool(uint64 address, int reg, int base_register,
   107                                 long offset));
   108   MOCK_METHOD4(ValOffsetRule, bool(uint64 address, int reg, int base_register,
   109                                    long offset));
   110   MOCK_METHOD3(RegisterRule, bool(uint64 address, int reg, int base_register));
   111   MOCK_METHOD3(ExpressionRule, bool(uint64 address, int reg,
   112                                     const string &expression));
   113   MOCK_METHOD3(ValExpressionRule, bool(uint64 address, int reg,
   114                                        const string &expression));
   115   MOCK_METHOD0(End, bool());
   116   MOCK_METHOD2(PersonalityRoutine, bool(uint64 address, bool indirect));
   117   MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64 address, bool indirect));
   118   MOCK_METHOD0(SignalHandler, bool());
   119 };
   121 class 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 };
   138 struct CFIFixture {
   140   enum { kCFARegister = CallFrameInfo::Handler::kCFARegister };
   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);
   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   }
   180   MockCallFrameInfoHandler handler;
   181   MockCallFrameErrorReporter reporter;
   182 };
   184 class CFI: public CFIFixture, public Test { };
   186 TEST_F(CFI, EmptyRegion) {
   187   EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
   188   EXPECT_CALL(handler, End()).Times(0);
   189   static const char data[1] = { 42 };
   191   ByteReader byte_reader(ENDIANNESS_BIG);
   192   CallFrameInfo parser(data, 0, &byte_reader, &handler, &reporter);
   193   EXPECT_TRUE(parser.Start());
   194 }
   196 TEST_F(CFI, IncompleteLength32) {
   197   CFISection section(kBigEndian, 8);
   198   section
   199       // Not even long enough for an initial length.
   200       .D16(0xa0f)
   201       // Padding to keep valgrind happy. We subtract these off when we
   202       // construct the parser.
   203       .D16(0);
   205   EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
   206   EXPECT_CALL(handler, End()).Times(0);
   208   EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
   209       .WillOnce(Return());
   211   string contents;
   212   ASSERT_TRUE(section.GetContents(&contents));
   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 }
   221 TEST_F(CFI, IncompleteLength64) {
   222   CFISection section(kLittleEndian, 4);
   223   section
   224       // An incomplete 64-bit DWARF initial length.
   225       .D32(0xffffffff).D32(0x71fbaec2)
   226       // Padding to keep valgrind happy. We subtract these off when we
   227       // construct the parser.
   228       .D32(0);
   230   EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
   231   EXPECT_CALL(handler, End()).Times(0);
   233   EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
   234       .WillOnce(Return());
   236   string contents;
   237   ASSERT_TRUE(section.GetContents(&contents));
   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 }
   246 TEST_F(CFI, IncompleteId32) {
   247   CFISection section(kBigEndian, 8);
   248   section
   249       .D32(3)                      // Initial length, not long enough for id
   250       .D8(0xd7).D8(0xe5).D8(0xf1)  // incomplete id
   251       .CIEHeader(8727, 3983, 8889, 3, "")
   252       .FinishEntry();
   254   EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
   255   EXPECT_CALL(handler, End()).Times(0);
   257   EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
   258       .WillOnce(Return());
   260   string contents;
   261   ASSERT_TRUE(section.GetContents(&contents));
   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 }
   270 TEST_F(CFI, BadId32) {
   271   CFISection section(kBigEndian, 8);
   272   section
   273       .D32(0x100)                       // Initial length
   274       .D32(0xe802fade)                  // bogus ID
   275       .Append(0x100 - 4, 0x42);         // make the length true
   276   section
   277       .CIEHeader(1672, 9872, 8529, 3, "")
   278       .FinishEntry();
   280   EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
   281   EXPECT_CALL(handler, End()).Times(0);
   283   EXPECT_CALL(reporter, CIEPointerOutOfRange(_, 0xe802fade))
   284       .WillOnce(Return());
   286   string contents;
   287   ASSERT_TRUE(section.GetContents(&contents));
   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 }
   296 // A lone CIE shouldn't cause any handler calls.
   297 TEST_F(CFI, SingleCIE) {
   298   CFISection section(kLittleEndian, 4);
   299   section.CIEHeader(0xffe799a8, 0x3398dcdd, 0x6e9683de, 3, "");
   300   section.Append(10, dwarf2reader::DW_CFA_nop);
   301   section.FinishEntry();
   303   PERHAPS_WRITE_DEBUG_FRAME_FILE("SingleCIE", section);
   305   EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
   306   EXPECT_CALL(handler, End()).Times(0);
   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 }
   317 // One FDE, one CIE.
   318 TEST_F(CFI, OneFDE) {
   319   CFISection section(kBigEndian, 4);
   320   Label cie;
   321   section
   322       .Mark(&cie)
   323       .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "")
   324       .FinishEntry()
   325       .FDEHeader(cie, 0x7714740d, 0x3d5a10cd)
   326       .FinishEntry();
   328   PERHAPS_WRITE_DEBUG_FRAME_FILE("OneFDE", section);
   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   }
   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 }
   347 // Two FDEs share a CIE.
   348 TEST_F(CFI, TwoFDEsOneCIE) {
   349   CFISection section(kBigEndian, 4);
   350   Label cie;
   351   section
   352       // First FDE. readelf complains about this one because it makes
   353       // a forward reference to its CIE.
   354       .FDEHeader(cie, 0xa42744df, 0xa3b42121)
   355       .FinishEntry()
   356       // CIE.
   357       .Mark(&cie)
   358       .CIEHeader(0x04f7dc7b, 0x3d00c05f, 0xbd43cb59, 3, "")
   359       .FinishEntry()
   360       // Second FDE.
   361       .FDEHeader(cie, 0x6057d391, 0x700f608d)
   362       .FinishEntry();
   364   PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsOneCIE", section);
   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   }
   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 }
   390 // Two FDEs, two CIEs.
   391 TEST_F(CFI, TwoFDEsTwoCIEs) {
   392   CFISection section(kLittleEndian, 8);
   393   Label cie1, cie2;
   394   section
   395       // First CIE.
   396       .Mark(&cie1)
   397       .CIEHeader(0x694d5d45, 0x4233221b, 0xbf45e65a, 3, "")
   398       .FinishEntry()
   399       // First FDE which cites second CIE. readelf complains about
   400       // this one because it makes a forward reference to its CIE.
   401       .FDEHeader(cie2, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL)
   402       .FinishEntry()
   403       // Second FDE, which cites first CIE.
   404       .FDEHeader(cie1, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL)
   405       .FinishEntry()
   406       // Second CIE.
   407       .Mark(&cie2)
   408       .CIEHeader(0xfba3fad7, 0x6287e1fd, 0x61d2c581, 2, "")
   409       .FinishEntry();
   411   PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsTwoCIEs", section);
   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   }
   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 }
   439 // An FDE whose CIE specifies a version we don't recognize.
   440 TEST_F(CFI, BadVersion) {
   441   CFISection section(kBigEndian, 4);
   442   Label cie1, cie2;
   443   section
   444       .Mark(&cie1)
   445       .CIEHeader(0xca878cf0, 0x7698ec04, 0x7b616f54, 0x52, "")
   446       .FinishEntry()
   447       // We should skip this entry, as its CIE specifies a version we
   448       // don't recognize.
   449       .FDEHeader(cie1, 0x08852292, 0x2204004a)
   450       .FinishEntry()
   451       // Despite the above, we should visit this entry.
   452       .Mark(&cie2)
   453       .CIEHeader(0x7c3ae7c9, 0xb9b9a512, 0x96cb3264, 3, "")
   454       .FinishEntry()
   455       .FDEHeader(cie2, 0x2094735a, 0x6e875501)
   456       .FinishEntry();
   458   PERHAPS_WRITE_DEBUG_FRAME_FILE("BadVersion", section);
   460   EXPECT_CALL(reporter, UnrecognizedVersion(_, 0x52))
   461     .WillOnce(Return());
   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   }
   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 }
   483 // An FDE whose CIE specifies an augmentation we don't recognize.
   484 TEST_F(CFI, BadAugmentation) {
   485   CFISection section(kBigEndian, 4);
   486   Label cie1, cie2;
   487   section
   488       .Mark(&cie1)
   489       .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "spaniels!")
   490       .FinishEntry()
   491       // We should skip this entry, as its CIE specifies an
   492       // augmentation we don't recognize.
   493       .FDEHeader(cie1, 0x7714740d, 0x3d5a10cd)
   494       .FinishEntry()
   495       // Despite the above, we should visit this entry.
   496       .Mark(&cie2)
   497       .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 3, "")
   498       .FinishEntry()
   499       .FDEHeader(cie2, 0x7bf0fda0, 0xcbcd28d8)
   500       .FinishEntry();
   502   PERHAPS_WRITE_DEBUG_FRAME_FILE("BadAugmentation", section);
   504   EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "spaniels!"))
   505     .WillOnce(Return());
   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   }
   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 }
   527 // The return address column field is a byte in CFI version 1
   528 // (DWARF2), but a ULEB128 value in version 3 (DWARF3).
   529 TEST_F(CFI, CIEVersion1ReturnColumn) {
   530   CFISection section(kBigEndian, 4);
   531   Label cie;
   532   section
   533       // CIE, using the version 1 format: return column is a ubyte.
   534       .Mark(&cie)
   535       // Use a value for the return column that is parsed differently
   536       // as a ubyte and as a ULEB128.
   537       .CIEHeader(0xbcdea24f, 0x5be28286, 0x9f, 1, "")
   538       .FinishEntry()
   539       // FDE, citing that CIE.
   540       .FDEHeader(cie, 0xb8d347b5, 0x825e55dc)
   541       .FinishEntry();
   543   PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion1ReturnColumn", section);
   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   }
   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 }
   561 // The return address column field is a byte in CFI version 1
   562 // (DWARF2), but a ULEB128 value in version 3 (DWARF3).
   563 TEST_F(CFI, CIEVersion3ReturnColumn) {
   564   CFISection section(kBigEndian, 4);
   565   Label cie;
   566   section
   567       // CIE, using the version 3 format: return column is a ULEB128.
   568       .Mark(&cie)
   569       // Use a value for the return column that is parsed differently
   570       // as a ubyte and as a ULEB128.
   571       .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 3, "")
   572       .FinishEntry()
   573       // FDE, citing that CIE.
   574       .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
   575       .FinishEntry();
   577   PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section);
   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   }
   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 }
   595 struct 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   }
   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     }
   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();
   642     // Create the FDE.
   643     section->FDEHeader(cie_label, fde_start, fde_size);
   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   }
   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   }
   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 };
   690 class CFIInsn: public CFIInsnFixture, public Test { };
   692 TEST_F(CFIInsn, DW_CFA_set_loc) {
   693   CFISection section(kBigEndian, 4);
   694   StockCIEAndFDE(&section);
   695   section
   696       .D8(dwarf2reader::DW_CFA_set_loc).D32(0xb1ee3e7a)
   697       // Use DW_CFA_def_cfa to force a handler call that we can use to
   698       // check the effect of the DW_CFA_set_loc.
   699       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee)
   700       .FinishEntry();
   702   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_set_loc", section);
   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));
   710   ParseSection(&section);
   711 }
   713 TEST_F(CFIInsn, DW_CFA_advance_loc) {
   714   CFISection section(kBigEndian, 8);
   715   StockCIEAndFDE(&section);
   716   section
   717       .D8(dwarf2reader::DW_CFA_advance_loc | 0x2a)
   718       // Use DW_CFA_def_cfa to force a handler call that we can use to
   719       // check the effect of the DW_CFA_advance_loc.
   720       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf)
   721       .FinishEntry();
   723   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc", section);
   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));
   732   ParseSection(&section);
   733 }
   735 TEST_F(CFIInsn, DW_CFA_advance_loc1) {
   736   CFISection section(kLittleEndian, 8);
   737   StockCIEAndFDE(&section);
   738   section
   739       .D8(dwarf2reader::DW_CFA_advance_loc1).D8(0xd8)
   740       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93)
   741       .FinishEntry();
   743   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc1", section);
   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));
   752   ParseSection(&section);
   753 }
   755 TEST_F(CFIInsn, DW_CFA_advance_loc2) {
   756   CFISection section(kLittleEndian, 4);
   757   StockCIEAndFDE(&section);
   758   section
   759       .D8(dwarf2reader::DW_CFA_advance_loc2).D16(0x3adb)
   760       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37)
   761       .FinishEntry();
   763   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc2", section);
   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));
   772   ParseSection(&section);
   773 }
   775 TEST_F(CFIInsn, DW_CFA_advance_loc4) {
   776   CFISection section(kBigEndian, 8);
   777   StockCIEAndFDE(&section);
   778   section
   779       .D8(dwarf2reader::DW_CFA_advance_loc4).D32(0x15813c88)
   780       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb)
   781       .FinishEntry();
   783   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc4", section);
   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));
   792   ParseSection(&section);
   793 }
   795 TEST_F(CFIInsn, DW_CFA_MIPS_advance_loc8) {
   796   code_factor = 0x2d;
   797   CFISection section(kBigEndian, 8);
   798   StockCIEAndFDE(&section);
   799   section
   800       .D8(dwarf2reader::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL)
   801       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f)
   802       .FinishEntry();
   804   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc8", section);
   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));
   813   ParseSection(&section);
   814 }
   816 TEST_F(CFIInsn, DW_CFA_def_cfa) {
   817   CFISection section(kLittleEndian, 4);
   818   StockCIEAndFDE(&section);
   819   section
   820       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7)
   821       .FinishEntry();
   823   PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_def_cfa", section);
   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));
   830   ParseSection(&section);
   831 }
   833 TEST_F(CFIInsn, DW_CFA_def_cfa_sf) {
   834   CFISection section(kBigEndian, 4);
   835   StockCIEAndFDE(&section);
   836   section
   837       .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea)
   838       .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2)
   839       .FinishEntry();
   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));
   851   ParseSection(&section);
   852 }
   854 TEST_F(CFIInsn, DW_CFA_def_cfa_register) {
   855   CFISection section(kLittleEndian, 8);
   856   StockCIEAndFDE(&section);
   857   section
   858       .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363)
   859       .FinishEntry();
   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));
   866   ParseSection(&section);
   867 }
   869 // DW_CFA_def_cfa_register should have no effect when applied to a
   870 // non-base/offset rule.
   871 TEST_F(CFIInsn, DW_CFA_def_cfa_registerBadRule) {
   872   CFISection section(kBigEndian, 4);
   873   StockCIEAndFDE(&section);
   874   section
   875       .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("needle in a haystack")
   876       .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49)
   877       .FinishEntry();
   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));
   885   ParseSection(&section);
   886 }
   888 TEST_F(CFIInsn, DW_CFA_def_cfa_offset) {
   889   CFISection section(kBigEndian, 4);
   890   StockCIEAndFDE(&section);
   891   section
   892       .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
   893       .FinishEntry();
   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));
   901   ParseSection(&section);
   902 }
   904 TEST_F(CFIInsn, DW_CFA_def_cfa_offset_sf) {
   905   CFISection section(kLittleEndian, 4);
   906   StockCIEAndFDE(&section);
   907   section
   908       .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(0x970)
   909       .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd)
   910       .FinishEntry();
   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));
   922   ParseSection(&section);
   923 }
   925 // DW_CFA_def_cfa_offset should have no effect when applied to a
   926 // non-base/offset rule.
   927 TEST_F(CFIInsn, DW_CFA_def_cfa_offsetBadRule) {
   928   CFISection section(kBigEndian, 4);
   929   StockCIEAndFDE(&section);
   930   section
   931       .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("six ways to Sunday")
   932       .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
   933       .FinishEntry();
   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));
   940   ParseSection(&section);
   941 }
   943 TEST_F(CFIInsn, DW_CFA_def_cfa_expression) {
   944   CFISection section(kLittleEndian, 8);
   945   StockCIEAndFDE(&section);
   946   section
   947       .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("eating crow")
   948       .FinishEntry();
   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));
   955   ParseSection(&section);
   956 }
   958 TEST_F(CFIInsn, DW_CFA_undefined) {
   959   CFISection section(kLittleEndian, 4);
   960   StockCIEAndFDE(&section);
   961   section
   962       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x300ce45d)
   963       .FinishEntry();
   965   EXPECT_CALL(handler, UndefinedRule(fde_start, 0x300ce45d))
   966       .InSequence(s).WillOnce(Return(true));
   967   EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
   969   ParseSection(&section);
   970 }
   972 TEST_F(CFIInsn, DW_CFA_same_value) {
   973   CFISection section(kLittleEndian, 4);
   974   StockCIEAndFDE(&section);
   975   section
   976       .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3865a760)
   977       .FinishEntry();
   979   EXPECT_CALL(handler, SameValueRule(fde_start, 0x3865a760))
   980       .InSequence(s).WillOnce(Return(true));
   981   EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
   983   ParseSection(&section);
   984 }
   986 TEST_F(CFIInsn, DW_CFA_offset) {
   987   CFISection section(kBigEndian, 4);
   988   StockCIEAndFDE(&section);
   989   section
   990       .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x9f6)
   991       .FinishEntry();
   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));
   998   ParseSection(&section);
   999 }
  1001 TEST_F(CFIInsn, DW_CFA_offset_extended) {
  1002   CFISection section(kBigEndian, 4);
  1003   StockCIEAndFDE(&section);
  1004   section
  1005       .D8(dwarf2reader::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48)
  1006       .FinishEntry();
  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));
  1013   ParseSection(&section);
  1016 TEST_F(CFIInsn, DW_CFA_offset_extended_sf) {
  1017   CFISection section(kBigEndian, 8);
  1018   StockCIEAndFDE(&section);
  1019   section
  1020       .D8(dwarf2reader::DW_CFA_offset_extended_sf)
  1021           .ULEB128(0x997c23ee).LEB128(0x2d00)
  1022       .D8(dwarf2reader::DW_CFA_offset_extended_sf)
  1023           .ULEB128(0x9519eb82).LEB128(-0xa77)
  1024       .FinishEntry();
  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));
  1036   ParseSection(&section);
  1039 TEST_F(CFIInsn, DW_CFA_val_offset) {
  1040   CFISection section(kBigEndian, 4);
  1041   StockCIEAndFDE(&section);
  1042   section
  1043       .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673)
  1044       .FinishEntry();
  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));
  1052   ParseSection(&section);
  1055 TEST_F(CFIInsn, DW_CFA_val_offset_sf) {
  1056   CFISection section(kBigEndian, 4);
  1057   StockCIEAndFDE(&section);
  1058   section
  1059       .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab)
  1060       .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2)
  1061       .FinishEntry();
  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));
  1073   ParseSection(&section);
  1076 TEST_F(CFIInsn, DW_CFA_register) {
  1077   CFISection section(kLittleEndian, 8);
  1078   StockCIEAndFDE(&section);
  1079   section
  1080       .D8(dwarf2reader::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414)
  1081       .FinishEntry();
  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));
  1087   ParseSection(&section);
  1090 TEST_F(CFIInsn, DW_CFA_expression) {
  1091   CFISection section(kBigEndian, 8);
  1092   StockCIEAndFDE(&section);
  1093   section
  1094       .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xa1619fb2)
  1095       .Block("plus ça change, plus c'est la même chose")
  1096       .FinishEntry();
  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));
  1104   ParseSection(&section);
  1107 TEST_F(CFIInsn, DW_CFA_val_expression) {
  1108   CFISection section(kBigEndian, 4);
  1109   StockCIEAndFDE(&section);
  1110   section
  1111       .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xc5e4a9e3)
  1112       .Block("he who has the gold makes the rules")
  1113       .FinishEntry();
  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));
  1121   ParseSection(&section);
  1124 TEST_F(CFIInsn, DW_CFA_restore) {
  1125   CFISection section(kLittleEndian, 8);
  1126   code_factor = 0x01bd188a9b1fa083ULL;
  1127   data_factor = -0x1ac8;
  1128   return_register = 0x8c35b049;
  1129   version = 2;
  1130   fde_start = 0x2d70fe998298bbb1ULL;
  1131   fde_size = 0x46ccc2e63cf0b108ULL;
  1132   Label cie;
  1133   section
  1134       .Mark(&cie)
  1135       .CIEHeader(code_factor, data_factor, return_register, version,
  1136                  "")
  1137       // Provide a CFA rule, because register rules require them.
  1138       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8)
  1139       // Provide an offset(N) rule for register 0x3c.
  1140       .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0xb348)
  1141       .FinishEntry()
  1142       // In the FDE...
  1143       .FDEHeader(cie, fde_start, fde_size)
  1144       // At a second address, provide a new offset(N) rule for register 0x3c.
  1145       .D8(dwarf2reader::DW_CFA_advance_loc | 0x13)
  1146       .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0x9a50)
  1147       // At a third address, restore the original rule for register 0x3c.
  1148       .D8(dwarf2reader::DW_CFA_advance_loc | 0x01)
  1149       .D8(dwarf2reader::DW_CFA_restore | 0x3c)
  1150       .FinishEntry();
  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));
  1178   ParseSection(&section);
  1181 TEST_F(CFIInsn, DW_CFA_restoreNoRule) {
  1182   CFISection section(kBigEndian, 4);
  1183   code_factor = 0x005f78143c1c3b82ULL;
  1184   data_factor = 0x25d0;
  1185   return_register = 0xe8;
  1186   version = 1;
  1187   fde_start = 0x4062e30f;
  1188   fde_size = 0x5302a389;
  1189   Label cie;
  1190   section
  1191       .Mark(&cie)
  1192       .CIEHeader(code_factor, data_factor, return_register, version, "")
  1193       // Provide a CFA rule, because register rules require them.
  1194       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127)
  1195       .FinishEntry()
  1196       // In the FDE...
  1197       .FDEHeader(cie, fde_start, fde_size)
  1198       // At a second address, provide an offset(N) rule for register 0x2c.
  1199       .D8(dwarf2reader::DW_CFA_advance_loc | 0x7)
  1200       .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x1f47)
  1201       // At a third address, restore the (missing) CIE rule for register 0x2c.
  1202       .D8(dwarf2reader::DW_CFA_advance_loc | 0xb)
  1203       .D8(dwarf2reader::DW_CFA_restore | 0x2c)
  1204       .FinishEntry();
  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));
  1227   ParseSection(&section);
  1230 TEST_F(CFIInsn, DW_CFA_restore_extended) {
  1231   CFISection section(kBigEndian, 4);
  1232   code_factor = 0x126e;
  1233   data_factor = -0xd8b;
  1234   return_register = 0x77711787;
  1235   version = 3;
  1236   fde_start = 0x01f55a45;
  1237   fde_size = 0x452adb80;
  1238   Label cie;
  1239   section
  1240       .Mark(&cie)
  1241       .CIEHeader(code_factor, data_factor, return_register, version,
  1242                  "", true /* dwarf64 */ )
  1243       // Provide a CFA rule, because register rules require them.
  1244       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5)
  1245       // Provide an offset(N) rule for register 0x0f9b8a1c.
  1246       .D8(dwarf2reader::DW_CFA_offset_extended)
  1247           .ULEB128(0x0f9b8a1c).ULEB128(0xc979)
  1248       .FinishEntry()
  1249       // In the FDE...
  1250       .FDEHeader(cie, fde_start, fde_size)
  1251       // At a second address, provide a new offset(N) rule for reg 0x0f9b8a1c.
  1252       .D8(dwarf2reader::DW_CFA_advance_loc | 0x3)
  1253       .D8(dwarf2reader::DW_CFA_offset_extended)
  1254           .ULEB128(0x0f9b8a1c).ULEB128(0x3b7b)
  1255       // At a third address, restore the original rule for register 0x0f9b8a1c.
  1256       .D8(dwarf2reader::DW_CFA_advance_loc | 0x04)
  1257       .D8(dwarf2reader::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c)
  1258       .FinishEntry();
  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));
  1287   ParseSection(&section);
  1290 TEST_F(CFIInsn, DW_CFA_remember_and_restore_state) {
  1291   CFISection section(kLittleEndian, 8);
  1292   StockCIEAndFDE(&section);
  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();
  1323   uint64 addr = fde_start;
  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));
  1333   addr += code_factor;
  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));
  1345   addr += code_factor;
  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));
  1358   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1360   ParseSection(&section);
  1363 // Check that restoring a rule set reports changes to the CFA rule.
  1364 TEST_F(CFIInsn, DW_CFA_remember_and_restore_stateCFA) {
  1365   CFISection section(kBigEndian, 4);
  1366   StockCIEAndFDE(&section);
  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();
  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));
  1383   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1385   ParseSection(&section);
  1388 TEST_F(CFIInsn, DW_CFA_nop) {
  1389   CFISection section(kLittleEndian, 4);
  1390   StockCIEAndFDE(&section);
  1391   section
  1392       .D8(dwarf2reader::DW_CFA_nop)
  1393       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b)
  1394       .D8(dwarf2reader::DW_CFA_nop)
  1395       .FinishEntry();
  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));
  1402   ParseSection(&section);
  1405 TEST_F(CFIInsn, DW_CFA_GNU_window_save) {
  1406   CFISection section(kBigEndian, 4);
  1407   StockCIEAndFDE(&section);
  1408   section
  1409       .D8(dwarf2reader::DW_CFA_GNU_window_save)
  1410       .FinishEntry();
  1412   // Don't include all the rules in any particular sequence.
  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));
  1425   EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
  1427   ParseSection(&section);
  1430 TEST_F(CFIInsn, DW_CFA_GNU_args_size) {
  1431   CFISection section(kLittleEndian, 8);
  1432   StockCIEAndFDE(&section);
  1433   section
  1434       .D8(dwarf2reader::DW_CFA_GNU_args_size).ULEB128(0xeddfa520)
  1435       // Verify that we see this, meaning we parsed the above properly.
  1436       .D8(dwarf2reader::DW_CFA_offset | 0x23).ULEB128(0x269)
  1437       .FinishEntry();
  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));
  1444   ParseSection(&section);
  1447 TEST_F(CFIInsn, DW_CFA_GNU_negative_offset_extended) {
  1448   CFISection section(kLittleEndian, 4);
  1449   StockCIEAndFDE(&section);
  1450   section
  1451       .D8(dwarf2reader::DW_CFA_GNU_negative_offset_extended)
  1452       .ULEB128(0x430cc87a).ULEB128(0x613)
  1453       .FinishEntry();
  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));
  1461   ParseSection(&section);
  1464 // Three FDEs: skip the second
  1465 TEST_F(CFIInsn, SkipFDE) {
  1466   CFISection section(kBigEndian, 4);
  1467   Label cie;
  1468   section
  1469       // CIE, used by all FDEs.
  1470       .Mark(&cie)
  1471       .CIEHeader(0x010269f2, 0x9177, 0xedca5849, 2, "")
  1472       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad)
  1473       .FinishEntry()
  1474       // First FDE.
  1475       .FDEHeader(cie, 0xa870ebdd, 0x60f6aa4)
  1476       .D8(dwarf2reader::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf)
  1477       .FinishEntry()
  1478       // Second FDE.
  1479       .FDEHeader(cie, 0xc534f7c0, 0xf6552e9, true /* dwarf64 */)
  1480       .D8(dwarf2reader::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18)
  1481       .FinishEntry()
  1482       // Third FDE.
  1483       .FDEHeader(cie, 0xf681cfc8, 0x7e4594e)
  1484       .D8(dwarf2reader::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4)
  1485       .FinishEntry();
  1488     InSequence s;
  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));
  1501     // Skip the second FDE.
  1502     EXPECT_CALL(handler, Entry(_, 0xc534f7c0, 0xf6552e9, 2, "", 0xedca5849))
  1503         .WillOnce(Return(false));
  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));
  1517   ParseSection(&section);
  1520 // Quit processing in the middle of an entry's instructions.
  1521 TEST_F(CFIInsn, QuitMidentry) {
  1522   CFISection section(kLittleEndian, 8);
  1523   StockCIEAndFDE(&section);
  1524   section
  1525       .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431)
  1526       .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat")
  1527       .FinishEntry();
  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));
  1534   ParseSection(&section, false);
  1537 class CFIRestore: public CFIInsnFixture, public Test { };
  1539 TEST_F(CFIRestore, RestoreUndefinedRuleUnchanged) {
  1540   CFISection section(kLittleEndian, 4);
  1541   StockCIEAndFDE(&section);
  1542   section
  1543       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x0bac878e)
  1544       .D8(dwarf2reader::DW_CFA_remember_state)
  1545       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1546       .D8(dwarf2reader::DW_CFA_restore_state)
  1547       .FinishEntry();
  1549   EXPECT_CALL(handler, UndefinedRule(fde_start, 0x0bac878e))
  1550       .InSequence(s).WillOnce(Return(true));
  1551   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1553   ParseSection(&section);
  1556 TEST_F(CFIRestore, RestoreUndefinedRuleChanged) {
  1557   CFISection section(kLittleEndian, 4);
  1558   StockCIEAndFDE(&section);
  1559   section
  1560       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x7dedff5f)
  1561       .D8(dwarf2reader::DW_CFA_remember_state)
  1562       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1563       .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x7dedff5f)
  1564       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1565       .D8(dwarf2reader::DW_CFA_restore_state)
  1566       .FinishEntry();
  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));
  1576   ParseSection(&section);
  1579 TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) {
  1580   CFISection section(kLittleEndian, 4);
  1581   StockCIEAndFDE(&section);
  1582   section
  1583       .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0xadbc9b3a)
  1584       .D8(dwarf2reader::DW_CFA_remember_state)
  1585       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1586       .D8(dwarf2reader::DW_CFA_restore_state)
  1587       .FinishEntry();
  1589   EXPECT_CALL(handler, SameValueRule(fde_start, 0xadbc9b3a))
  1590       .InSequence(s).WillOnce(Return(true));
  1591   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1593   ParseSection(&section);
  1596 TEST_F(CFIRestore, RestoreSameValueRuleChanged) {
  1597   CFISection section(kLittleEndian, 4);
  1598   StockCIEAndFDE(&section);
  1599   section
  1600       .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3d90dcb5)
  1601       .D8(dwarf2reader::DW_CFA_remember_state)
  1602       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1603       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x3d90dcb5)
  1604       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1605       .D8(dwarf2reader::DW_CFA_restore_state)
  1606       .FinishEntry();
  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));
  1616   ParseSection(&section);
  1619 TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) {
  1620   CFISection section(kLittleEndian, 4);
  1621   StockCIEAndFDE(&section);
  1622   section
  1623       .D8(dwarf2reader::DW_CFA_offset | 0x14).ULEB128(0xb6f)
  1624       .D8(dwarf2reader::DW_CFA_remember_state)
  1625       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1626       .D8(dwarf2reader::DW_CFA_restore_state)
  1627       .FinishEntry();
  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));
  1634   ParseSection(&section);
  1637 TEST_F(CFIRestore, RestoreOffsetRuleChanged) {
  1638   CFISection section(kLittleEndian, 4);
  1639   StockCIEAndFDE(&section);
  1640   section
  1641       .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xeb7)
  1642       .D8(dwarf2reader::DW_CFA_remember_state)
  1643       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1644       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x21)
  1645       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1646       .D8(dwarf2reader::DW_CFA_restore_state)
  1647       .FinishEntry();
  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));
  1659   ParseSection(&section);
  1662 TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) {
  1663   CFISection section(kLittleEndian, 4);
  1664   StockCIEAndFDE(&section);
  1665   section
  1666       .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0x134)
  1667       .D8(dwarf2reader::DW_CFA_remember_state)
  1668       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1669       .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xf4f)
  1670       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1671       .D8(dwarf2reader::DW_CFA_restore_state)
  1672       .FinishEntry();
  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));
  1685   ParseSection(&section);
  1688 TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) {
  1689   CFISection section(kLittleEndian, 4);
  1690   StockCIEAndFDE(&section);
  1691   section
  1692       .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c)
  1693       .D8(dwarf2reader::DW_CFA_remember_state)
  1694       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1695       .D8(dwarf2reader::DW_CFA_restore_state)
  1696       .FinishEntry();
  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));
  1703   ParseSection(&section);
  1706 TEST_F(CFIRestore, RestoreValOffsetRuleChanged) {
  1707   CFISection section(kLittleEndian, 4);
  1708   StockCIEAndFDE(&section);
  1709   section
  1710       .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7)
  1711       .D8(dwarf2reader::DW_CFA_remember_state)
  1712       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1713       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xf17c36d6)
  1714       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1715       .D8(dwarf2reader::DW_CFA_restore_state)
  1716       .FinishEntry();
  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));
  1728   ParseSection(&section);
  1731 TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) {
  1732   CFISection section(kLittleEndian, 4);
  1733   StockCIEAndFDE(&section);
  1734   section
  1735       .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562)
  1736       .D8(dwarf2reader::DW_CFA_remember_state)
  1737       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1738       .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88)
  1739       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1740       .D8(dwarf2reader::DW_CFA_restore_state)
  1741       .FinishEntry();
  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));
  1754   ParseSection(&section);
  1757 TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) {
  1758   CFISection section(kLittleEndian, 4);
  1759   StockCIEAndFDE(&section);
  1760   section
  1761       .D8(dwarf2reader::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce)
  1762       .D8(dwarf2reader::DW_CFA_remember_state)
  1763       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1764       .D8(dwarf2reader::DW_CFA_restore_state)
  1765       .FinishEntry();
  1767   EXPECT_CALL(handler, RegisterRule(fde_start, 0x77514acc, 0x464de4ce))
  1768       .InSequence(s).WillOnce(Return(true));
  1769   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1771   ParseSection(&section);
  1774 TEST_F(CFIRestore, RestoreRegisterRuleChanged) {
  1775   CFISection section(kLittleEndian, 4);
  1776   StockCIEAndFDE(&section);
  1777   section
  1778       .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559)
  1779       .D8(dwarf2reader::DW_CFA_remember_state)
  1780       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1781       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xe39acce5)
  1782       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1783       .D8(dwarf2reader::DW_CFA_restore_state)
  1784       .FinishEntry();
  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));
  1795   ParseSection(&section);
  1798 TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) {
  1799   CFISection section(kLittleEndian, 4);
  1800   StockCIEAndFDE(&section);
  1801   section
  1802       .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a)
  1803       .D8(dwarf2reader::DW_CFA_remember_state)
  1804       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1805       .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742)
  1806       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1807       .D8(dwarf2reader::DW_CFA_restore_state)
  1808       .FinishEntry();
  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));
  1820   ParseSection(&section);
  1823 TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) {
  1824   CFISection section(kLittleEndian, 4);
  1825   StockCIEAndFDE(&section);
  1826   section
  1827       .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf")
  1828       .D8(dwarf2reader::DW_CFA_remember_state)
  1829       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1830       .D8(dwarf2reader::DW_CFA_restore_state)
  1831       .FinishEntry();
  1833   EXPECT_CALL(handler, ExpressionRule(fde_start, 0x666ae152, "dwarf"))
  1834       .InSequence(s).WillOnce(Return(true));
  1835   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1837   ParseSection(&section);
  1840 TEST_F(CFIRestore, RestoreExpressionRuleChanged) {
  1841   CFISection section(kLittleEndian, 4);
  1842   StockCIEAndFDE(&section);
  1843   section
  1844       .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf")
  1845       .D8(dwarf2reader::DW_CFA_remember_state)
  1846       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1847       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46)
  1848       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1849       .D8(dwarf2reader::DW_CFA_restore_state)
  1850       .FinishEntry();
  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));
  1861   ParseSection(&section);
  1864 TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) {
  1865   CFISection section(kLittleEndian, 4);
  1866   StockCIEAndFDE(&section);
  1867   section
  1868       .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf")
  1869       .D8(dwarf2reader::DW_CFA_remember_state)
  1870       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1871       .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("orc")
  1872       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1873       .D8(dwarf2reader::DW_CFA_restore_state)
  1874       .FinishEntry();
  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));
  1887   ParseSection(&section);
  1890 TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) {
  1891   CFISection section(kLittleEndian, 4);
  1892   StockCIEAndFDE(&section);
  1893   section
  1894       .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x666ae152)
  1895       .Block("hideous")
  1896       .D8(dwarf2reader::DW_CFA_remember_state)
  1897       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1898       .D8(dwarf2reader::DW_CFA_restore_state)
  1899       .FinishEntry();
  1901   EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x666ae152, "hideous"))
  1902       .InSequence(s).WillOnce(Return(true));
  1903   EXPECT_CALL(handler, End()).WillOnce(Return(true));
  1905   ParseSection(&section);
  1908 TEST_F(CFIRestore, RestoreValExpressionRuleChanged) {
  1909   CFISection section(kLittleEndian, 4);
  1910   StockCIEAndFDE(&section);
  1911   section
  1912       .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xb5ca5c46)
  1913       .Block("revolting")
  1914       .D8(dwarf2reader::DW_CFA_remember_state)
  1915       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1916       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46)
  1917       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1918       .D8(dwarf2reader::DW_CFA_restore_state)
  1919       .FinishEntry();
  1921   PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChanged", section);
  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));
  1932   ParseSection(&section);
  1935 TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) {
  1936   CFISection section(kLittleEndian, 4);
  1937   StockCIEAndFDE(&section);
  1938   section
  1939       .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739)
  1940       .Block("repulsive")
  1941       .D8(dwarf2reader::DW_CFA_remember_state)
  1942       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1943       .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739)
  1944       .Block("nauseous")
  1945       .D8(dwarf2reader::DW_CFA_advance_loc | 1)
  1946       .D8(dwarf2reader::DW_CFA_restore_state)
  1947       .FinishEntry();
  1949   PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChangedValExpression",
  1950                                  section);
  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));
  1963   ParseSection(&section);
  1966 struct 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);
  1974   CFISection section;
  1975   CFISection::EncodedPointerBases encoded_pointer_bases;
  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;
  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());
  2003 };
  2005 class EHFrame: public EHFrameFixture, public Test { };
  2007 // A simple CIE, an FDE, and a terminator.
  2008 TEST_F(EHFrame, Terminator) {
  2009   Label cie;
  2010   section
  2011       .Mark(&cie)
  2012       .CIEHeader(9968, 2466, 67, 1, "")
  2013       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372)
  2014       .FinishEntry()
  2015       .FDEHeader(cie, 0x848037a1, 0x7b30475e)
  2016       .D8(dwarf2reader::DW_CFA_set_loc).D32(0x17713850)
  2017       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(5721)
  2018       .FinishEntry()
  2019       .D32(0)                           // Terminate the sequence.
  2020       // This FDE should be ignored.
  2021       .FDEHeader(cie, 0xf19629fe, 0x439fb09b)
  2022       .FinishEntry();
  2024   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.Terminator", section);
  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());
  2037   ParseEHFrameSection(&section);
  2040 // The parser should recognize the Linux Standards Base 'z' augmentations.
  2041 TEST_F(EHFrame, SimpleFDE) {
  2042   DwarfPointerEncoding lsda_encoding =
  2043       DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect
  2044                            | dwarf2reader::DW_EH_PE_datarel
  2045                            | dwarf2reader::DW_EH_PE_sdata2);
  2046   DwarfPointerEncoding fde_encoding =
  2047       DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
  2048                            | dwarf2reader::DW_EH_PE_udata2);
  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
  2072   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.SimpleFDE", section);
  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));
  2089   ParseEHFrameSection(&section);
  2092 // Check that we can handle an empty 'z' augmentation.
  2093 TEST_F(EHFrame, EmptyZ) {
  2094   Label cie;
  2095   section
  2096       .Mark(&cie)
  2097       .CIEHeader(5955, 5805, 228, 1, "z")
  2098       .ULEB128(0)                                // Augmentation data length
  2099       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247)
  2100       .FinishEntry()
  2101       .FDEHeader(cie, 0xda007738, 0xfb55c641)
  2102       .ULEB128(0)                                // Augmentation data length
  2103       .D8(dwarf2reader::DW_CFA_advance_loc1).D8(11)
  2104       .D8(dwarf2reader::DW_CFA_undefined).ULEB128(3769)
  2105       .FinishEntry();
  2107   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.EmptyZ", section);
  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));
  2118   ParseEHFrameSection(&section);
  2121 // Check that we recognize bad 'z' augmentation characters.
  2122 TEST_F(EHFrame, BadZ) {
  2123   Label cie;
  2124   section
  2125       .Mark(&cie)
  2126       .CIEHeader(6937, 1045, 142, 1, "zQ")
  2127       .ULEB128(0)                                // Augmentation data length
  2128       .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725)
  2129       .FinishEntry()
  2130       .FDEHeader(cie, 0x1293efa8, 0x236f53f2)
  2131       .ULEB128(0)                                // Augmentation data length
  2132       .D8(dwarf2reader::DW_CFA_advance_loc | 12)
  2133       .D8(dwarf2reader::DW_CFA_register).ULEB128(5667).ULEB128(3462)
  2134       .FinishEntry();
  2136   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.BadZ", section);
  2138   EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "zQ"))
  2139       .WillOnce(Return());
  2141   ParseEHFrameSection(&section, false);
  2144 TEST_F(EHFrame, zL) {
  2145   Label cie;
  2146   DwarfPointerEncoding lsda_encoding =
  2147       DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel
  2148                            | dwarf2reader::DW_EH_PE_udata2);
  2149   section
  2150       .Mark(&cie)
  2151       .CIEHeader(9285, 9959, 54, 1, "zL")
  2152       .ULEB128(1)                       // Augmentation data length
  2153       .D8(lsda_encoding)                // encoding for LSDA pointer in FDE
  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
  2162   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zL", section);
  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));
  2171   ParseEHFrameSection(&section);
  2174 TEST_F(EHFrame, zP) {
  2175   Label cie;
  2176   DwarfPointerEncoding personality_encoding =
  2177       DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel
  2178                            | dwarf2reader::DW_EH_PE_udata2);
  2179   section
  2180       .Mark(&cie)
  2181       .CIEHeader(1097, 6313, 17, 1, "zP")
  2182       .ULEB128(3)                  // Augmentation data length
  2183       .D8(personality_encoding)    // encoding for personality routine
  2184       .EncodedPointer(0xe3eaccac, personality_encoding) // value
  2185       .FinishEntry()
  2186       .FDEHeader(cie, 0x0c8350c9, 0xbef11087)
  2187       .ULEB128(0)                       // Augmentation data length
  2188       .FinishEntry()
  2189       .D32(0);                                   // terminator
  2191   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zP", section);
  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));
  2200   ParseEHFrameSection(&section);
  2203 TEST_F(EHFrame, zR) {
  2204   Label cie;
  2205   DwarfPointerEncoding pointer_encoding =
  2206       DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
  2207                            | dwarf2reader::DW_EH_PE_sdata2);
  2208   section.SetPointerEncoding(pointer_encoding);
  2209   section
  2210       .Mark(&cie)
  2211       .CIEHeader(8011, 5496, 75, 1, "zR")
  2212       .ULEB128(1)                       // Augmentation data length
  2213       .D8(pointer_encoding)             // encoding for FDE addresses
  2214       .FinishEntry()
  2215       .FDEHeader(cie, 0x540f9431, 0xbd0)
  2216       .ULEB128(0)                       // Augmentation data length
  2217       .FinishEntry()
  2218       .D32(0);                          // terminator
  2220   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zR", section);
  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));
  2227   ParseEHFrameSection(&section);
  2230 TEST_F(EHFrame, zS) {
  2231   Label cie;
  2232   section
  2233       .Mark(&cie)
  2234       .CIEHeader(9217, 7694, 57, 1, "zS")
  2235       .ULEB128(0)                                // Augmentation data length
  2236       .FinishEntry()
  2237       .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
  2238       .ULEB128(0)                                // Augmentation data length
  2239       .FinishEntry()
  2240       .D32(0);                                   // terminator
  2242   PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zS", section);
  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));
  2251   ParseEHFrameSection(&section);
  2254 // These tests require manual inspection of the test output.
  2255 struct CFIReporterFixture {
  2256   CFIReporterFixture() : reporter("test file name", "test section name") { }
  2257   CallFrameInfo::Reporter reporter;
  2258 };
  2260 class CFIReporter: public CFIReporterFixture, public Test { };
  2262 TEST_F(CFIReporter, Incomplete) {
  2263   reporter.Incomplete(0x0102030405060708ULL, CallFrameInfo::kUnknown);
  2266 TEST_F(CFIReporter, EarlyEHTerminator) {
  2267   reporter.EarlyEHTerminator(0x0102030405060708ULL);
  2270 TEST_F(CFIReporter, CIEPointerOutOfRange) {
  2271   reporter.CIEPointerOutOfRange(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
  2274 TEST_F(CFIReporter, BadCIEId) {
  2275   reporter.BadCIEId(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
  2278 TEST_F(CFIReporter, UnrecognizedVersion) {
  2279   reporter.UnrecognizedVersion(0x0123456789abcdefULL, 43);
  2282 TEST_F(CFIReporter, UnrecognizedAugmentation) {
  2283   reporter.UnrecognizedAugmentation(0x0123456789abcdefULL, "poodles");
  2286 TEST_F(CFIReporter, InvalidPointerEncoding) {
  2287   reporter.InvalidPointerEncoding(0x0123456789abcdefULL, 0x42);
  2290 TEST_F(CFIReporter, UnusablePointerEncoding) {
  2291   reporter.UnusablePointerEncoding(0x0123456789abcdefULL, 0x42);
  2294 TEST_F(CFIReporter, RestoreInCIE) {
  2295   reporter.RestoreInCIE(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
  2298 TEST_F(CFIReporter, BadInstruction) {
  2299   reporter.BadInstruction(0x0123456789abcdefULL, CallFrameInfo::kFDE,
  2300                           0xfedcba9876543210ULL);
  2303 TEST_F(CFIReporter, NoCFARule) {
  2304   reporter.NoCFARule(0x0123456789abcdefULL, CallFrameInfo::kCIE,
  2305                      0xfedcba9876543210ULL);
  2308 TEST_F(CFIReporter, EmptyStateStack) {
  2309   reporter.EmptyStateStack(0x0123456789abcdefULL, CallFrameInfo::kTerminator,
  2310                            0xfedcba9876543210ULL);
  2313 TEST_F(CFIReporter, ClearingCFARule) {
  2314   reporter.ClearingCFARule(0x0123456789abcdefULL, CallFrameInfo::kFDE,
  2315                            0xfedcba9876543210ULL);
  2318 #ifdef WRITE_ELF
  2319 // See comments at the top of the file mentioning WRITE_ELF for details.
  2321 using google_breakpad::test_assembler::Section;
  2323 struct 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 };
  2339 void AppendSectionHeader(CFISection *table, const ELFSectionHeader &header) {
  2340   (*table)
  2341       .D32(header.name)                   // name, index in string tbl
  2342       .D32(header.type)                   // type
  2343       .Address(header.flags)              // flags
  2344       .Address(header.address)            // address in memory
  2345       .Address(header.file_offset)        // offset in ELF file
  2346       .Address(header.file_size)          // length in bytes
  2347       .D32(header.link)                   // link to related section
  2348       .D32(header.info)                   // miscellaneous
  2349       .Address(header.alignment)          // alignment
  2350       .Address(header.entry_size);        // entry size
  2353 void WriteELFFrameSection(const char *filename, const char *cfi_name,
  2354                           const CFISection &cfi) {
  2355   int elf_class = cfi.AddressSize() == 4 ? ELFCLASS32 : ELFCLASS64;
  2356   int elf_data = (cfi.endianness() == kBigEndian
  2357                   ? ELFDATA2MSB : ELFDATA2LSB);
  2358   CFISection elf(cfi.endianness(), cfi.AddressSize());
  2359   Label elf_header_size, section_table_offset;
  2360   elf
  2361       .Append("\x7f" "ELF")
  2362       .D8(elf_class)              // 32-bit or 64-bit ELF
  2363       .D8(elf_data)               // endianness
  2364       .D8(1)                      // ELF version
  2365       .D8(ELFOSABI_LINUX)         // Operating System/ABI indication
  2366       .D8(0)                      // ABI version
  2367       .Append(7, 0xda)            // padding
  2368       .D16(ET_EXEC)               // file type: executable file
  2369       .D16(EM_386)                // architecture: Intel IA-32
  2370       .D32(EV_CURRENT);           // ELF version
  2371   elf
  2372       .Address(0x0123456789abcdefULL) // program entry point
  2373       .Address(0)                 // program header offset
  2374       .Address(section_table_offset) // section header offset
  2375       .D32(0)                     // processor-specific flags
  2376       .D16(elf_header_size)       // ELF header size in bytes */
  2377       .D16(elf_class == ELFCLASS32 ? 32 : 56) // program header entry size
  2378       .D16(0)                     // program header table entry count
  2379       .D16(elf_class == ELFCLASS32 ? 40 : 64) // section header entry size
  2380       .D16(3)                     // section  count
  2381       .D16(1)                     // section name string table
  2382       .Mark(&elf_header_size);
  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;
  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();
  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);
  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);
  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);
  2427   string contents;
  2428   if (!elf.GetContents(&contents)) {
  2429     fprintf(stderr, "failed to get ELF file contents\n");
  2430     exit(1);
  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);
  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);
  2446   if (fclose(out) == EOF) {
  2447     fprintf(stderr, "error closing ELF file '%s': %s\n",
  2448             filename, strerror(errno));
  2449     exit(1);
  2452 #endif

mercurial