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