1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2452 @@ 1.4 +// Copyright (c) 2010, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.34 + 1.35 +// dwarf2reader_cfi_unittest.cc: Unit tests for dwarf2reader::CallFrameInfo 1.36 + 1.37 +#include <stdlib.h> 1.38 + 1.39 +#include <string> 1.40 +#include <vector> 1.41 + 1.42 +// The '.eh_frame' format, used by the Linux C++ ABI for exception 1.43 +// handling, is poorly specified. To help test our support for .eh_frame, 1.44 +// if you #define WRITE_ELF while compiling this file, and add the 1.45 +// 'include' directory from the binutils, gcc, or gdb source tree to the 1.46 +// #include path, then each test that calls the 1.47 +// PERHAPS_WRITE_DEBUG_FRAME_FILE or PERHAPS_WRITE_EH_FRAME_FILE will write 1.48 +// an ELF file containing a .debug_frame or .eh_frame section; you can then 1.49 +// use tools like readelf to examine the test data, and check the tools' 1.50 +// interpretation against the test's intentions. Each ELF file is named 1.51 +// "cfitest-TEST", where TEST identifies the particular test. 1.52 +#ifdef WRITE_ELF 1.53 +#include <errno.h> 1.54 +#include <stdio.h> 1.55 +#include <string.h> 1.56 +extern "C" { 1.57 +// To compile with WRITE_ELF, you should add the 'include' directory 1.58 +// of the binutils, gcc, or gdb source tree to your #include path; 1.59 +// that directory contains this header. 1.60 +#include "elf/common.h" 1.61 +} 1.62 +#endif 1.63 + 1.64 +#include "breakpad_googletest_includes.h" 1.65 +#include "common/dwarf/bytereader-inl.h" 1.66 +#include "common/dwarf/cfi_assembler.h" 1.67 +#include "common/dwarf/dwarf2reader.h" 1.68 +#include "common/using_std_string.h" 1.69 +#include "google_breakpad/common/breakpad_types.h" 1.70 + 1.71 +using google_breakpad::CFISection; 1.72 +using google_breakpad::test_assembler::Label; 1.73 +using google_breakpad::test_assembler::kBigEndian; 1.74 +using google_breakpad::test_assembler::kLittleEndian; 1.75 +using google_breakpad::test_assembler::Section; 1.76 + 1.77 +using dwarf2reader::DwarfPointerEncoding; 1.78 +using dwarf2reader::ENDIANNESS_BIG; 1.79 +using dwarf2reader::ENDIANNESS_LITTLE; 1.80 +using dwarf2reader::ByteReader; 1.81 +using dwarf2reader::CallFrameInfo; 1.82 + 1.83 +using std::vector; 1.84 +using testing::InSequence; 1.85 +using testing::Return; 1.86 +using testing::Sequence; 1.87 +using testing::Test; 1.88 +using testing::_; 1.89 + 1.90 +#ifdef WRITE_ELF 1.91 +void WriteELFFrameSection(const char *filename, const char *section_name, 1.92 + const CFISection §ion); 1.93 +#define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section) \ 1.94 + WriteELFFrameSection("cfitest-" name, ".debug_frame", section); 1.95 +#define PERHAPS_WRITE_EH_FRAME_FILE(name, section) \ 1.96 + WriteELFFrameSection("cfitest-" name, ".eh_frame", section); 1.97 +#else 1.98 +#define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section) 1.99 +#define PERHAPS_WRITE_EH_FRAME_FILE(name, section) 1.100 +#endif 1.101 + 1.102 +class MockCallFrameInfoHandler: public CallFrameInfo::Handler { 1.103 + public: 1.104 + MOCK_METHOD6(Entry, bool(size_t offset, uint64 address, uint64 length, 1.105 + uint8 version, const string &augmentation, 1.106 + unsigned return_address)); 1.107 + MOCK_METHOD2(UndefinedRule, bool(uint64 address, int reg)); 1.108 + MOCK_METHOD2(SameValueRule, bool(uint64 address, int reg)); 1.109 + MOCK_METHOD4(OffsetRule, bool(uint64 address, int reg, int base_register, 1.110 + long offset)); 1.111 + MOCK_METHOD4(ValOffsetRule, bool(uint64 address, int reg, int base_register, 1.112 + long offset)); 1.113 + MOCK_METHOD3(RegisterRule, bool(uint64 address, int reg, int base_register)); 1.114 + MOCK_METHOD3(ExpressionRule, bool(uint64 address, int reg, 1.115 + const string &expression)); 1.116 + MOCK_METHOD3(ValExpressionRule, bool(uint64 address, int reg, 1.117 + const string &expression)); 1.118 + MOCK_METHOD0(End, bool()); 1.119 + MOCK_METHOD2(PersonalityRoutine, bool(uint64 address, bool indirect)); 1.120 + MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64 address, bool indirect)); 1.121 + MOCK_METHOD0(SignalHandler, bool()); 1.122 +}; 1.123 + 1.124 +class MockCallFrameErrorReporter: public CallFrameInfo::Reporter { 1.125 + public: 1.126 + MockCallFrameErrorReporter() : Reporter("mock filename", "mock section") { } 1.127 + MOCK_METHOD2(Incomplete, void(uint64, CallFrameInfo::EntryKind)); 1.128 + MOCK_METHOD1(EarlyEHTerminator, void(uint64)); 1.129 + MOCK_METHOD2(CIEPointerOutOfRange, void(uint64, uint64)); 1.130 + MOCK_METHOD2(BadCIEId, void(uint64, uint64)); 1.131 + MOCK_METHOD2(UnrecognizedVersion, void(uint64, int version)); 1.132 + MOCK_METHOD2(UnrecognizedAugmentation, void(uint64, const string &)); 1.133 + MOCK_METHOD2(InvalidPointerEncoding, void(uint64, uint8)); 1.134 + MOCK_METHOD2(UnusablePointerEncoding, void(uint64, uint8)); 1.135 + MOCK_METHOD2(RestoreInCIE, void(uint64, uint64)); 1.136 + MOCK_METHOD3(BadInstruction, void(uint64, CallFrameInfo::EntryKind, uint64)); 1.137 + MOCK_METHOD3(NoCFARule, void(uint64, CallFrameInfo::EntryKind, uint64)); 1.138 + MOCK_METHOD3(EmptyStateStack, void(uint64, CallFrameInfo::EntryKind, uint64)); 1.139 +}; 1.140 + 1.141 +struct CFIFixture { 1.142 + 1.143 + enum { kCFARegister = CallFrameInfo::Handler::kCFARegister }; 1.144 + 1.145 + CFIFixture() { 1.146 + // Default expectations for the data handler. 1.147 + // 1.148 + // - Leave Entry and End without expectations, as it's probably a 1.149 + // good idea to set those explicitly in each test. 1.150 + // 1.151 + // - Expect the *Rule functions to not be called, 1.152 + // so that each test can simply list the calls they expect. 1.153 + // 1.154 + // I gather I could use StrictMock for this, but the manual seems 1.155 + // to suggest using that only as a last resort, and this isn't so 1.156 + // bad. 1.157 + EXPECT_CALL(handler, UndefinedRule(_, _)).Times(0); 1.158 + EXPECT_CALL(handler, SameValueRule(_, _)).Times(0); 1.159 + EXPECT_CALL(handler, OffsetRule(_, _, _, _)).Times(0); 1.160 + EXPECT_CALL(handler, ValOffsetRule(_, _, _, _)).Times(0); 1.161 + EXPECT_CALL(handler, RegisterRule(_, _, _)).Times(0); 1.162 + EXPECT_CALL(handler, ExpressionRule(_, _, _)).Times(0); 1.163 + EXPECT_CALL(handler, ValExpressionRule(_, _, _)).Times(0); 1.164 + EXPECT_CALL(handler, PersonalityRoutine(_, _)).Times(0); 1.165 + EXPECT_CALL(handler, LanguageSpecificDataArea(_, _)).Times(0); 1.166 + EXPECT_CALL(handler, SignalHandler()).Times(0); 1.167 + 1.168 + // Default expectations for the error/warning reporer. 1.169 + EXPECT_CALL(reporter, Incomplete(_, _)).Times(0); 1.170 + EXPECT_CALL(reporter, EarlyEHTerminator(_)).Times(0); 1.171 + EXPECT_CALL(reporter, CIEPointerOutOfRange(_, _)).Times(0); 1.172 + EXPECT_CALL(reporter, BadCIEId(_, _)).Times(0); 1.173 + EXPECT_CALL(reporter, UnrecognizedVersion(_, _)).Times(0); 1.174 + EXPECT_CALL(reporter, UnrecognizedAugmentation(_, _)).Times(0); 1.175 + EXPECT_CALL(reporter, InvalidPointerEncoding(_, _)).Times(0); 1.176 + EXPECT_CALL(reporter, UnusablePointerEncoding(_, _)).Times(0); 1.177 + EXPECT_CALL(reporter, RestoreInCIE(_, _)).Times(0); 1.178 + EXPECT_CALL(reporter, BadInstruction(_, _, _)).Times(0); 1.179 + EXPECT_CALL(reporter, NoCFARule(_, _, _)).Times(0); 1.180 + EXPECT_CALL(reporter, EmptyStateStack(_, _, _)).Times(0); 1.181 + } 1.182 + 1.183 + MockCallFrameInfoHandler handler; 1.184 + MockCallFrameErrorReporter reporter; 1.185 +}; 1.186 + 1.187 +class CFI: public CFIFixture, public Test { }; 1.188 + 1.189 +TEST_F(CFI, EmptyRegion) { 1.190 + EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0); 1.191 + EXPECT_CALL(handler, End()).Times(0); 1.192 + static const char data[1] = { 42 }; 1.193 + 1.194 + ByteReader byte_reader(ENDIANNESS_BIG); 1.195 + CallFrameInfo parser(data, 0, &byte_reader, &handler, &reporter); 1.196 + EXPECT_TRUE(parser.Start()); 1.197 +} 1.198 + 1.199 +TEST_F(CFI, IncompleteLength32) { 1.200 + CFISection section(kBigEndian, 8); 1.201 + section 1.202 + // Not even long enough for an initial length. 1.203 + .D16(0xa0f) 1.204 + // Padding to keep valgrind happy. We subtract these off when we 1.205 + // construct the parser. 1.206 + .D16(0); 1.207 + 1.208 + EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0); 1.209 + EXPECT_CALL(handler, End()).Times(0); 1.210 + 1.211 + EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown)) 1.212 + .WillOnce(Return()); 1.213 + 1.214 + string contents; 1.215 + ASSERT_TRUE(section.GetContents(&contents)); 1.216 + 1.217 + ByteReader byte_reader(ENDIANNESS_BIG); 1.218 + byte_reader.SetAddressSize(8); 1.219 + CallFrameInfo parser(contents.data(), contents.size() - 2, 1.220 + &byte_reader, &handler, &reporter); 1.221 + EXPECT_FALSE(parser.Start()); 1.222 +} 1.223 + 1.224 +TEST_F(CFI, IncompleteLength64) { 1.225 + CFISection section(kLittleEndian, 4); 1.226 + section 1.227 + // An incomplete 64-bit DWARF initial length. 1.228 + .D32(0xffffffff).D32(0x71fbaec2) 1.229 + // Padding to keep valgrind happy. We subtract these off when we 1.230 + // construct the parser. 1.231 + .D32(0); 1.232 + 1.233 + EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0); 1.234 + EXPECT_CALL(handler, End()).Times(0); 1.235 + 1.236 + EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown)) 1.237 + .WillOnce(Return()); 1.238 + 1.239 + string contents; 1.240 + ASSERT_TRUE(section.GetContents(&contents)); 1.241 + 1.242 + ByteReader byte_reader(ENDIANNESS_LITTLE); 1.243 + byte_reader.SetAddressSize(4); 1.244 + CallFrameInfo parser(contents.data(), contents.size() - 4, 1.245 + &byte_reader, &handler, &reporter); 1.246 + EXPECT_FALSE(parser.Start()); 1.247 +} 1.248 + 1.249 +TEST_F(CFI, IncompleteId32) { 1.250 + CFISection section(kBigEndian, 8); 1.251 + section 1.252 + .D32(3) // Initial length, not long enough for id 1.253 + .D8(0xd7).D8(0xe5).D8(0xf1) // incomplete id 1.254 + .CIEHeader(8727, 3983, 8889, 3, "") 1.255 + .FinishEntry(); 1.256 + 1.257 + EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0); 1.258 + EXPECT_CALL(handler, End()).Times(0); 1.259 + 1.260 + EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown)) 1.261 + .WillOnce(Return()); 1.262 + 1.263 + string contents; 1.264 + ASSERT_TRUE(section.GetContents(&contents)); 1.265 + 1.266 + ByteReader byte_reader(ENDIANNESS_BIG); 1.267 + byte_reader.SetAddressSize(8); 1.268 + CallFrameInfo parser(contents.data(), contents.size(), 1.269 + &byte_reader, &handler, &reporter); 1.270 + EXPECT_FALSE(parser.Start()); 1.271 +} 1.272 + 1.273 +TEST_F(CFI, BadId32) { 1.274 + CFISection section(kBigEndian, 8); 1.275 + section 1.276 + .D32(0x100) // Initial length 1.277 + .D32(0xe802fade) // bogus ID 1.278 + .Append(0x100 - 4, 0x42); // make the length true 1.279 + section 1.280 + .CIEHeader(1672, 9872, 8529, 3, "") 1.281 + .FinishEntry(); 1.282 + 1.283 + EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0); 1.284 + EXPECT_CALL(handler, End()).Times(0); 1.285 + 1.286 + EXPECT_CALL(reporter, CIEPointerOutOfRange(_, 0xe802fade)) 1.287 + .WillOnce(Return()); 1.288 + 1.289 + string contents; 1.290 + ASSERT_TRUE(section.GetContents(&contents)); 1.291 + 1.292 + ByteReader byte_reader(ENDIANNESS_BIG); 1.293 + byte_reader.SetAddressSize(8); 1.294 + CallFrameInfo parser(contents.data(), contents.size(), 1.295 + &byte_reader, &handler, &reporter); 1.296 + EXPECT_FALSE(parser.Start()); 1.297 +} 1.298 + 1.299 +// A lone CIE shouldn't cause any handler calls. 1.300 +TEST_F(CFI, SingleCIE) { 1.301 + CFISection section(kLittleEndian, 4); 1.302 + section.CIEHeader(0xffe799a8, 0x3398dcdd, 0x6e9683de, 3, ""); 1.303 + section.Append(10, dwarf2reader::DW_CFA_nop); 1.304 + section.FinishEntry(); 1.305 + 1.306 + PERHAPS_WRITE_DEBUG_FRAME_FILE("SingleCIE", section); 1.307 + 1.308 + EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0); 1.309 + EXPECT_CALL(handler, End()).Times(0); 1.310 + 1.311 + string contents; 1.312 + EXPECT_TRUE(section.GetContents(&contents)); 1.313 + ByteReader byte_reader(ENDIANNESS_LITTLE); 1.314 + byte_reader.SetAddressSize(4); 1.315 + CallFrameInfo parser(contents.data(), contents.size(), 1.316 + &byte_reader, &handler, &reporter); 1.317 + EXPECT_TRUE(parser.Start()); 1.318 +} 1.319 + 1.320 +// One FDE, one CIE. 1.321 +TEST_F(CFI, OneFDE) { 1.322 + CFISection section(kBigEndian, 4); 1.323 + Label cie; 1.324 + section 1.325 + .Mark(&cie) 1.326 + .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "") 1.327 + .FinishEntry() 1.328 + .FDEHeader(cie, 0x7714740d, 0x3d5a10cd) 1.329 + .FinishEntry(); 1.330 + 1.331 + PERHAPS_WRITE_DEBUG_FRAME_FILE("OneFDE", section); 1.332 + 1.333 + { 1.334 + InSequence s; 1.335 + EXPECT_CALL(handler, 1.336 + Entry(_, 0x7714740d, 0x3d5a10cd, 3, "", 0x6b6efb87)) 1.337 + .WillOnce(Return(true)); 1.338 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.339 + } 1.340 + 1.341 + string contents; 1.342 + EXPECT_TRUE(section.GetContents(&contents)); 1.343 + ByteReader byte_reader(ENDIANNESS_BIG); 1.344 + byte_reader.SetAddressSize(4); 1.345 + CallFrameInfo parser(contents.data(), contents.size(), 1.346 + &byte_reader, &handler, &reporter); 1.347 + EXPECT_TRUE(parser.Start()); 1.348 +} 1.349 + 1.350 +// Two FDEs share a CIE. 1.351 +TEST_F(CFI, TwoFDEsOneCIE) { 1.352 + CFISection section(kBigEndian, 4); 1.353 + Label cie; 1.354 + section 1.355 + // First FDE. readelf complains about this one because it makes 1.356 + // a forward reference to its CIE. 1.357 + .FDEHeader(cie, 0xa42744df, 0xa3b42121) 1.358 + .FinishEntry() 1.359 + // CIE. 1.360 + .Mark(&cie) 1.361 + .CIEHeader(0x04f7dc7b, 0x3d00c05f, 0xbd43cb59, 3, "") 1.362 + .FinishEntry() 1.363 + // Second FDE. 1.364 + .FDEHeader(cie, 0x6057d391, 0x700f608d) 1.365 + .FinishEntry(); 1.366 + 1.367 + PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsOneCIE", section); 1.368 + 1.369 + { 1.370 + InSequence s; 1.371 + EXPECT_CALL(handler, 1.372 + Entry(_, 0xa42744df, 0xa3b42121, 3, "", 0xbd43cb59)) 1.373 + .WillOnce(Return(true)); 1.374 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.375 + } 1.376 + { 1.377 + InSequence s; 1.378 + EXPECT_CALL(handler, 1.379 + Entry(_, 0x6057d391, 0x700f608d, 3, "", 0xbd43cb59)) 1.380 + .WillOnce(Return(true)); 1.381 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.382 + } 1.383 + 1.384 + string contents; 1.385 + EXPECT_TRUE(section.GetContents(&contents)); 1.386 + ByteReader byte_reader(ENDIANNESS_BIG); 1.387 + byte_reader.SetAddressSize(4); 1.388 + CallFrameInfo parser(contents.data(), contents.size(), 1.389 + &byte_reader, &handler, &reporter); 1.390 + EXPECT_TRUE(parser.Start()); 1.391 +} 1.392 + 1.393 +// Two FDEs, two CIEs. 1.394 +TEST_F(CFI, TwoFDEsTwoCIEs) { 1.395 + CFISection section(kLittleEndian, 8); 1.396 + Label cie1, cie2; 1.397 + section 1.398 + // First CIE. 1.399 + .Mark(&cie1) 1.400 + .CIEHeader(0x694d5d45, 0x4233221b, 0xbf45e65a, 3, "") 1.401 + .FinishEntry() 1.402 + // First FDE which cites second CIE. readelf complains about 1.403 + // this one because it makes a forward reference to its CIE. 1.404 + .FDEHeader(cie2, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL) 1.405 + .FinishEntry() 1.406 + // Second FDE, which cites first CIE. 1.407 + .FDEHeader(cie1, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL) 1.408 + .FinishEntry() 1.409 + // Second CIE. 1.410 + .Mark(&cie2) 1.411 + .CIEHeader(0xfba3fad7, 0x6287e1fd, 0x61d2c581, 2, "") 1.412 + .FinishEntry(); 1.413 + 1.414 + PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsTwoCIEs", section); 1.415 + 1.416 + { 1.417 + InSequence s; 1.418 + EXPECT_CALL(handler, 1.419 + Entry(_, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL, 2, 1.420 + "", 0x61d2c581)) 1.421 + .WillOnce(Return(true)); 1.422 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.423 + } 1.424 + { 1.425 + InSequence s; 1.426 + EXPECT_CALL(handler, 1.427 + Entry(_, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL, 3, 1.428 + "", 0xbf45e65a)) 1.429 + .WillOnce(Return(true)); 1.430 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.431 + } 1.432 + 1.433 + string contents; 1.434 + EXPECT_TRUE(section.GetContents(&contents)); 1.435 + ByteReader byte_reader(ENDIANNESS_LITTLE); 1.436 + byte_reader.SetAddressSize(8); 1.437 + CallFrameInfo parser(contents.data(), contents.size(), 1.438 + &byte_reader, &handler, &reporter); 1.439 + EXPECT_TRUE(parser.Start()); 1.440 +} 1.441 + 1.442 +// An FDE whose CIE specifies a version we don't recognize. 1.443 +TEST_F(CFI, BadVersion) { 1.444 + CFISection section(kBigEndian, 4); 1.445 + Label cie1, cie2; 1.446 + section 1.447 + .Mark(&cie1) 1.448 + .CIEHeader(0xca878cf0, 0x7698ec04, 0x7b616f54, 0x52, "") 1.449 + .FinishEntry() 1.450 + // We should skip this entry, as its CIE specifies a version we 1.451 + // don't recognize. 1.452 + .FDEHeader(cie1, 0x08852292, 0x2204004a) 1.453 + .FinishEntry() 1.454 + // Despite the above, we should visit this entry. 1.455 + .Mark(&cie2) 1.456 + .CIEHeader(0x7c3ae7c9, 0xb9b9a512, 0x96cb3264, 3, "") 1.457 + .FinishEntry() 1.458 + .FDEHeader(cie2, 0x2094735a, 0x6e875501) 1.459 + .FinishEntry(); 1.460 + 1.461 + PERHAPS_WRITE_DEBUG_FRAME_FILE("BadVersion", section); 1.462 + 1.463 + EXPECT_CALL(reporter, UnrecognizedVersion(_, 0x52)) 1.464 + .WillOnce(Return()); 1.465 + 1.466 + { 1.467 + InSequence s; 1.468 + // We should see no mention of the first FDE, but we should get 1.469 + // a call to Entry for the second. 1.470 + EXPECT_CALL(handler, Entry(_, 0x2094735a, 0x6e875501, 3, "", 1.471 + 0x96cb3264)) 1.472 + .WillOnce(Return(true)); 1.473 + EXPECT_CALL(handler, End()) 1.474 + .WillOnce(Return(true)); 1.475 + } 1.476 + 1.477 + string contents; 1.478 + EXPECT_TRUE(section.GetContents(&contents)); 1.479 + ByteReader byte_reader(ENDIANNESS_BIG); 1.480 + byte_reader.SetAddressSize(4); 1.481 + CallFrameInfo parser(contents.data(), contents.size(), 1.482 + &byte_reader, &handler, &reporter); 1.483 + EXPECT_FALSE(parser.Start()); 1.484 +} 1.485 + 1.486 +// An FDE whose CIE specifies an augmentation we don't recognize. 1.487 +TEST_F(CFI, BadAugmentation) { 1.488 + CFISection section(kBigEndian, 4); 1.489 + Label cie1, cie2; 1.490 + section 1.491 + .Mark(&cie1) 1.492 + .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "spaniels!") 1.493 + .FinishEntry() 1.494 + // We should skip this entry, as its CIE specifies an 1.495 + // augmentation we don't recognize. 1.496 + .FDEHeader(cie1, 0x7714740d, 0x3d5a10cd) 1.497 + .FinishEntry() 1.498 + // Despite the above, we should visit this entry. 1.499 + .Mark(&cie2) 1.500 + .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 3, "") 1.501 + .FinishEntry() 1.502 + .FDEHeader(cie2, 0x7bf0fda0, 0xcbcd28d8) 1.503 + .FinishEntry(); 1.504 + 1.505 + PERHAPS_WRITE_DEBUG_FRAME_FILE("BadAugmentation", section); 1.506 + 1.507 + EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "spaniels!")) 1.508 + .WillOnce(Return()); 1.509 + 1.510 + { 1.511 + InSequence s; 1.512 + // We should see no mention of the first FDE, but we should get 1.513 + // a call to Entry for the second. 1.514 + EXPECT_CALL(handler, Entry(_, 0x7bf0fda0, 0xcbcd28d8, 3, "", 1.515 + 0xf2f519b2)) 1.516 + .WillOnce(Return(true)); 1.517 + EXPECT_CALL(handler, End()) 1.518 + .WillOnce(Return(true)); 1.519 + } 1.520 + 1.521 + string contents; 1.522 + EXPECT_TRUE(section.GetContents(&contents)); 1.523 + ByteReader byte_reader(ENDIANNESS_BIG); 1.524 + byte_reader.SetAddressSize(4); 1.525 + CallFrameInfo parser(contents.data(), contents.size(), 1.526 + &byte_reader, &handler, &reporter); 1.527 + EXPECT_FALSE(parser.Start()); 1.528 +} 1.529 + 1.530 +// The return address column field is a byte in CFI version 1 1.531 +// (DWARF2), but a ULEB128 value in version 3 (DWARF3). 1.532 +TEST_F(CFI, CIEVersion1ReturnColumn) { 1.533 + CFISection section(kBigEndian, 4); 1.534 + Label cie; 1.535 + section 1.536 + // CIE, using the version 1 format: return column is a ubyte. 1.537 + .Mark(&cie) 1.538 + // Use a value for the return column that is parsed differently 1.539 + // as a ubyte and as a ULEB128. 1.540 + .CIEHeader(0xbcdea24f, 0x5be28286, 0x9f, 1, "") 1.541 + .FinishEntry() 1.542 + // FDE, citing that CIE. 1.543 + .FDEHeader(cie, 0xb8d347b5, 0x825e55dc) 1.544 + .FinishEntry(); 1.545 + 1.546 + PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion1ReturnColumn", section); 1.547 + 1.548 + { 1.549 + InSequence s; 1.550 + EXPECT_CALL(handler, Entry(_, 0xb8d347b5, 0x825e55dc, 1, "", 0x9f)) 1.551 + .WillOnce(Return(true)); 1.552 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.553 + } 1.554 + 1.555 + string contents; 1.556 + EXPECT_TRUE(section.GetContents(&contents)); 1.557 + ByteReader byte_reader(ENDIANNESS_BIG); 1.558 + byte_reader.SetAddressSize(4); 1.559 + CallFrameInfo parser(contents.data(), contents.size(), 1.560 + &byte_reader, &handler, &reporter); 1.561 + EXPECT_TRUE(parser.Start()); 1.562 +} 1.563 + 1.564 +// The return address column field is a byte in CFI version 1 1.565 +// (DWARF2), but a ULEB128 value in version 3 (DWARF3). 1.566 +TEST_F(CFI, CIEVersion3ReturnColumn) { 1.567 + CFISection section(kBigEndian, 4); 1.568 + Label cie; 1.569 + section 1.570 + // CIE, using the version 3 format: return column is a ULEB128. 1.571 + .Mark(&cie) 1.572 + // Use a value for the return column that is parsed differently 1.573 + // as a ubyte and as a ULEB128. 1.574 + .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 3, "") 1.575 + .FinishEntry() 1.576 + // FDE, citing that CIE. 1.577 + .FDEHeader(cie, 0x86763f2b, 0x2a66dc23) 1.578 + .FinishEntry(); 1.579 + 1.580 + PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section); 1.581 + 1.582 + { 1.583 + InSequence s; 1.584 + EXPECT_CALL(handler, Entry(_, 0x86763f2b, 0x2a66dc23, 3, "", 0x89)) 1.585 + .WillOnce(Return(true)); 1.586 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.587 + } 1.588 + 1.589 + string contents; 1.590 + EXPECT_TRUE(section.GetContents(&contents)); 1.591 + ByteReader byte_reader(ENDIANNESS_BIG); 1.592 + byte_reader.SetAddressSize(4); 1.593 + CallFrameInfo parser(contents.data(), contents.size(), 1.594 + &byte_reader, &handler, &reporter); 1.595 + EXPECT_TRUE(parser.Start()); 1.596 +} 1.597 + 1.598 +struct CFIInsnFixture: public CFIFixture { 1.599 + CFIInsnFixture() : CFIFixture() { 1.600 + data_factor = 0xb6f; 1.601 + return_register = 0x9be1ed9f; 1.602 + version = 3; 1.603 + cfa_base_register = 0x383a3aa; 1.604 + cfa_offset = 0xf748; 1.605 + } 1.606 + 1.607 + // Prepare SECTION to receive FDE instructions. 1.608 + // 1.609 + // - Append a stock CIE header that establishes the fixture's 1.610 + // code_factor, data_factor, return_register, version, and 1.611 + // augmentation values. 1.612 + // - Have the CIE set up a CFA rule using cfa_base_register and 1.613 + // cfa_offset. 1.614 + // - Append a stock FDE header, referring to the above CIE, for the 1.615 + // fde_size bytes at fde_start. Choose fde_start and fde_size 1.616 + // appropriately for the section's address size. 1.617 + // - Set appropriate expectations on handler in sequence s for the 1.618 + // frame description entry and the CIE's CFA rule. 1.619 + // 1.620 + // On return, SECTION is ready to have FDE instructions appended to 1.621 + // it, and its FinishEntry member called. 1.622 + void StockCIEAndFDE(CFISection *section) { 1.623 + // Choose appropriate constants for our address size. 1.624 + if (section->AddressSize() == 4) { 1.625 + fde_start = 0xc628ecfbU; 1.626 + fde_size = 0x5dee04a2; 1.627 + code_factor = 0x60b; 1.628 + } else { 1.629 + assert(section->AddressSize() == 8); 1.630 + fde_start = 0x0005c57ce7806bd3ULL; 1.631 + fde_size = 0x2699521b5e333100ULL; 1.632 + code_factor = 0x01008e32855274a8ULL; 1.633 + } 1.634 + 1.635 + // Create the CIE. 1.636 + (*section) 1.637 + .Mark(&cie_label) 1.638 + .CIEHeader(code_factor, data_factor, return_register, version, 1.639 + "") 1.640 + .D8(dwarf2reader::DW_CFA_def_cfa) 1.641 + .ULEB128(cfa_base_register) 1.642 + .ULEB128(cfa_offset) 1.643 + .FinishEntry(); 1.644 + 1.645 + // Create the FDE. 1.646 + section->FDEHeader(cie_label, fde_start, fde_size); 1.647 + 1.648 + // Expect an Entry call for the FDE and a ValOffsetRule call for the 1.649 + // CIE's CFA rule. 1.650 + EXPECT_CALL(handler, Entry(_, fde_start, fde_size, version, "", 1.651 + return_register)) 1.652 + .InSequence(s) 1.653 + .WillOnce(Return(true)); 1.654 + EXPECT_CALL(handler, ValOffsetRule(fde_start, kCFARegister, 1.655 + cfa_base_register, cfa_offset)) 1.656 + .InSequence(s) 1.657 + .WillOnce(Return(true)); 1.658 + } 1.659 + 1.660 + // Run the contents of SECTION through a CallFrameInfo parser, 1.661 + // expecting parser.Start to return SUCCEEDS 1.662 + void ParseSection(CFISection *section, bool succeeds = true) { 1.663 + string contents; 1.664 + EXPECT_TRUE(section->GetContents(&contents)); 1.665 + dwarf2reader::Endianness endianness; 1.666 + if (section->endianness() == kBigEndian) 1.667 + endianness = ENDIANNESS_BIG; 1.668 + else { 1.669 + assert(section->endianness() == kLittleEndian); 1.670 + endianness = ENDIANNESS_LITTLE; 1.671 + } 1.672 + ByteReader byte_reader(endianness); 1.673 + byte_reader.SetAddressSize(section->AddressSize()); 1.674 + CallFrameInfo parser(contents.data(), contents.size(), 1.675 + &byte_reader, &handler, &reporter); 1.676 + if (succeeds) 1.677 + EXPECT_TRUE(parser.Start()); 1.678 + else 1.679 + EXPECT_FALSE(parser.Start()); 1.680 + } 1.681 + 1.682 + Label cie_label; 1.683 + Sequence s; 1.684 + uint64 code_factor; 1.685 + int data_factor; 1.686 + unsigned return_register; 1.687 + unsigned version; 1.688 + unsigned cfa_base_register; 1.689 + int cfa_offset; 1.690 + uint64 fde_start, fde_size; 1.691 +}; 1.692 + 1.693 +class CFIInsn: public CFIInsnFixture, public Test { }; 1.694 + 1.695 +TEST_F(CFIInsn, DW_CFA_set_loc) { 1.696 + CFISection section(kBigEndian, 4); 1.697 + StockCIEAndFDE(§ion); 1.698 + section 1.699 + .D8(dwarf2reader::DW_CFA_set_loc).D32(0xb1ee3e7a) 1.700 + // Use DW_CFA_def_cfa to force a handler call that we can use to 1.701 + // check the effect of the DW_CFA_set_loc. 1.702 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee) 1.703 + .FinishEntry(); 1.704 + 1.705 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_set_loc", section); 1.706 + 1.707 + EXPECT_CALL(handler, 1.708 + ValOffsetRule(0xb1ee3e7a, kCFARegister, 0x4defb431, 0x6d17b0ee)) 1.709 + .InSequence(s) 1.710 + .WillOnce(Return(true)); 1.711 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.712 + 1.713 + ParseSection(§ion); 1.714 +} 1.715 + 1.716 +TEST_F(CFIInsn, DW_CFA_advance_loc) { 1.717 + CFISection section(kBigEndian, 8); 1.718 + StockCIEAndFDE(§ion); 1.719 + section 1.720 + .D8(dwarf2reader::DW_CFA_advance_loc | 0x2a) 1.721 + // Use DW_CFA_def_cfa to force a handler call that we can use to 1.722 + // check the effect of the DW_CFA_advance_loc. 1.723 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf) 1.724 + .FinishEntry(); 1.725 + 1.726 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc", section); 1.727 + 1.728 + EXPECT_CALL(handler, 1.729 + ValOffsetRule(fde_start + 0x2a * code_factor, 1.730 + kCFARegister, 0x5bbb3715, 0x0186c7bf)) 1.731 + .InSequence(s) 1.732 + .WillOnce(Return(true)); 1.733 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.734 + 1.735 + ParseSection(§ion); 1.736 +} 1.737 + 1.738 +TEST_F(CFIInsn, DW_CFA_advance_loc1) { 1.739 + CFISection section(kLittleEndian, 8); 1.740 + StockCIEAndFDE(§ion); 1.741 + section 1.742 + .D8(dwarf2reader::DW_CFA_advance_loc1).D8(0xd8) 1.743 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93) 1.744 + .FinishEntry(); 1.745 + 1.746 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc1", section); 1.747 + 1.748 + EXPECT_CALL(handler, 1.749 + ValOffsetRule((fde_start + 0xd8 * code_factor), 1.750 + kCFARegister, 0x69d5696a, 0x1eb7fc93)) 1.751 + .InSequence(s) 1.752 + .WillOnce(Return(true)); 1.753 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.754 + 1.755 + ParseSection(§ion); 1.756 +} 1.757 + 1.758 +TEST_F(CFIInsn, DW_CFA_advance_loc2) { 1.759 + CFISection section(kLittleEndian, 4); 1.760 + StockCIEAndFDE(§ion); 1.761 + section 1.762 + .D8(dwarf2reader::DW_CFA_advance_loc2).D16(0x3adb) 1.763 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37) 1.764 + .FinishEntry(); 1.765 + 1.766 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc2", section); 1.767 + 1.768 + EXPECT_CALL(handler, 1.769 + ValOffsetRule((fde_start + 0x3adb * code_factor), 1.770 + kCFARegister, 0x3a368bed, 0x3194ee37)) 1.771 + .InSequence(s) 1.772 + .WillOnce(Return(true)); 1.773 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.774 + 1.775 + ParseSection(§ion); 1.776 +} 1.777 + 1.778 +TEST_F(CFIInsn, DW_CFA_advance_loc4) { 1.779 + CFISection section(kBigEndian, 8); 1.780 + StockCIEAndFDE(§ion); 1.781 + section 1.782 + .D8(dwarf2reader::DW_CFA_advance_loc4).D32(0x15813c88) 1.783 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb) 1.784 + .FinishEntry(); 1.785 + 1.786 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc4", section); 1.787 + 1.788 + EXPECT_CALL(handler, 1.789 + ValOffsetRule((fde_start + 0x15813c88ULL * code_factor), 1.790 + kCFARegister, 0x135270c5, 0x24bad7cb)) 1.791 + .InSequence(s) 1.792 + .WillOnce(Return(true)); 1.793 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.794 + 1.795 + ParseSection(§ion); 1.796 +} 1.797 + 1.798 +TEST_F(CFIInsn, DW_CFA_MIPS_advance_loc8) { 1.799 + code_factor = 0x2d; 1.800 + CFISection section(kBigEndian, 8); 1.801 + StockCIEAndFDE(§ion); 1.802 + section 1.803 + .D8(dwarf2reader::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL) 1.804 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f) 1.805 + .FinishEntry(); 1.806 + 1.807 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc8", section); 1.808 + 1.809 + EXPECT_CALL(handler, 1.810 + ValOffsetRule((fde_start + 0x3c4f3945b92c14ULL * code_factor), 1.811 + kCFARegister, 0xe17ed602, 0x3d162e7f)) 1.812 + .InSequence(s) 1.813 + .WillOnce(Return(true)); 1.814 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.815 + 1.816 + ParseSection(§ion); 1.817 +} 1.818 + 1.819 +TEST_F(CFIInsn, DW_CFA_def_cfa) { 1.820 + CFISection section(kLittleEndian, 4); 1.821 + StockCIEAndFDE(§ion); 1.822 + section 1.823 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7) 1.824 + .FinishEntry(); 1.825 + 1.826 + PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_def_cfa", section); 1.827 + 1.828 + EXPECT_CALL(handler, 1.829 + ValOffsetRule(fde_start, kCFARegister, 0x4e363a85, 0x815f9aa7)) 1.830 + .InSequence(s).WillOnce(Return(true)); 1.831 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.832 + 1.833 + ParseSection(§ion); 1.834 +} 1.835 + 1.836 +TEST_F(CFIInsn, DW_CFA_def_cfa_sf) { 1.837 + CFISection section(kBigEndian, 4); 1.838 + StockCIEAndFDE(§ion); 1.839 + section 1.840 + .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea) 1.841 + .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2) 1.842 + .FinishEntry(); 1.843 + 1.844 + EXPECT_CALL(handler, 1.845 + ValOffsetRule(fde_start, kCFARegister, 0x8ccb32b7, 1.846 + 0x9ea * data_factor)) 1.847 + .InSequence(s).WillOnce(Return(true)); 1.848 + EXPECT_CALL(handler, 1.849 + ValOffsetRule(fde_start, kCFARegister, 0x9b40f5da, 1.850 + -0x40a2 * data_factor)) 1.851 + .InSequence(s).WillOnce(Return(true)); 1.852 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.853 + 1.854 + ParseSection(§ion); 1.855 +} 1.856 + 1.857 +TEST_F(CFIInsn, DW_CFA_def_cfa_register) { 1.858 + CFISection section(kLittleEndian, 8); 1.859 + StockCIEAndFDE(§ion); 1.860 + section 1.861 + .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363) 1.862 + .FinishEntry(); 1.863 + 1.864 + EXPECT_CALL(handler, 1.865 + ValOffsetRule(fde_start, kCFARegister, 0x3e7e9363, cfa_offset)) 1.866 + .InSequence(s).WillOnce(Return(true)); 1.867 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.868 + 1.869 + ParseSection(§ion); 1.870 +} 1.871 + 1.872 +// DW_CFA_def_cfa_register should have no effect when applied to a 1.873 +// non-base/offset rule. 1.874 +TEST_F(CFIInsn, DW_CFA_def_cfa_registerBadRule) { 1.875 + CFISection section(kBigEndian, 4); 1.876 + StockCIEAndFDE(§ion); 1.877 + section 1.878 + .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("needle in a haystack") 1.879 + .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49) 1.880 + .FinishEntry(); 1.881 + 1.882 + EXPECT_CALL(handler, 1.883 + ValExpressionRule(fde_start, kCFARegister, 1.884 + "needle in a haystack")) 1.885 + .WillRepeatedly(Return(true)); 1.886 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.887 + 1.888 + ParseSection(§ion); 1.889 +} 1.890 + 1.891 +TEST_F(CFIInsn, DW_CFA_def_cfa_offset) { 1.892 + CFISection section(kBigEndian, 4); 1.893 + StockCIEAndFDE(§ion); 1.894 + section 1.895 + .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b) 1.896 + .FinishEntry(); 1.897 + 1.898 + EXPECT_CALL(handler, 1.899 + ValOffsetRule(fde_start, kCFARegister, cfa_base_register, 1.900 + 0x1e8e3b9b)) 1.901 + .InSequence(s).WillOnce(Return(true)); 1.902 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.903 + 1.904 + ParseSection(§ion); 1.905 +} 1.906 + 1.907 +TEST_F(CFIInsn, DW_CFA_def_cfa_offset_sf) { 1.908 + CFISection section(kLittleEndian, 4); 1.909 + StockCIEAndFDE(§ion); 1.910 + section 1.911 + .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(0x970) 1.912 + .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd) 1.913 + .FinishEntry(); 1.914 + 1.915 + EXPECT_CALL(handler, 1.916 + ValOffsetRule(fde_start, kCFARegister, cfa_base_register, 1.917 + 0x970 * data_factor)) 1.918 + .InSequence(s).WillOnce(Return(true)); 1.919 + EXPECT_CALL(handler, 1.920 + ValOffsetRule(fde_start, kCFARegister, cfa_base_register, 1.921 + -0x2cd * data_factor)) 1.922 + .InSequence(s).WillOnce(Return(true)); 1.923 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.924 + 1.925 + ParseSection(§ion); 1.926 +} 1.927 + 1.928 +// DW_CFA_def_cfa_offset should have no effect when applied to a 1.929 +// non-base/offset rule. 1.930 +TEST_F(CFIInsn, DW_CFA_def_cfa_offsetBadRule) { 1.931 + CFISection section(kBigEndian, 4); 1.932 + StockCIEAndFDE(§ion); 1.933 + section 1.934 + .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("six ways to Sunday") 1.935 + .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b) 1.936 + .FinishEntry(); 1.937 + 1.938 + EXPECT_CALL(handler, 1.939 + ValExpressionRule(fde_start, kCFARegister, "six ways to Sunday")) 1.940 + .WillRepeatedly(Return(true)); 1.941 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.942 + 1.943 + ParseSection(§ion); 1.944 +} 1.945 + 1.946 +TEST_F(CFIInsn, DW_CFA_def_cfa_expression) { 1.947 + CFISection section(kLittleEndian, 8); 1.948 + StockCIEAndFDE(§ion); 1.949 + section 1.950 + .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("eating crow") 1.951 + .FinishEntry(); 1.952 + 1.953 + EXPECT_CALL(handler, ValExpressionRule(fde_start, kCFARegister, 1.954 + "eating crow")) 1.955 + .InSequence(s).WillOnce(Return(true)); 1.956 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.957 + 1.958 + ParseSection(§ion); 1.959 +} 1.960 + 1.961 +TEST_F(CFIInsn, DW_CFA_undefined) { 1.962 + CFISection section(kLittleEndian, 4); 1.963 + StockCIEAndFDE(§ion); 1.964 + section 1.965 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x300ce45d) 1.966 + .FinishEntry(); 1.967 + 1.968 + EXPECT_CALL(handler, UndefinedRule(fde_start, 0x300ce45d)) 1.969 + .InSequence(s).WillOnce(Return(true)); 1.970 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.971 + 1.972 + ParseSection(§ion); 1.973 +} 1.974 + 1.975 +TEST_F(CFIInsn, DW_CFA_same_value) { 1.976 + CFISection section(kLittleEndian, 4); 1.977 + StockCIEAndFDE(§ion); 1.978 + section 1.979 + .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3865a760) 1.980 + .FinishEntry(); 1.981 + 1.982 + EXPECT_CALL(handler, SameValueRule(fde_start, 0x3865a760)) 1.983 + .InSequence(s).WillOnce(Return(true)); 1.984 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.985 + 1.986 + ParseSection(§ion); 1.987 +} 1.988 + 1.989 +TEST_F(CFIInsn, DW_CFA_offset) { 1.990 + CFISection section(kBigEndian, 4); 1.991 + StockCIEAndFDE(§ion); 1.992 + section 1.993 + .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x9f6) 1.994 + .FinishEntry(); 1.995 + 1.996 + EXPECT_CALL(handler, 1.997 + OffsetRule(fde_start, 0x2c, kCFARegister, 0x9f6 * data_factor)) 1.998 + .InSequence(s).WillOnce(Return(true)); 1.999 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1000 + 1.1001 + ParseSection(§ion); 1.1002 +} 1.1003 + 1.1004 +TEST_F(CFIInsn, DW_CFA_offset_extended) { 1.1005 + CFISection section(kBigEndian, 4); 1.1006 + StockCIEAndFDE(§ion); 1.1007 + section 1.1008 + .D8(dwarf2reader::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48) 1.1009 + .FinishEntry(); 1.1010 + 1.1011 + EXPECT_CALL(handler, 1.1012 + OffsetRule(fde_start, 0x402b, kCFARegister, 0xb48 * data_factor)) 1.1013 + .InSequence(s).WillOnce(Return(true)); 1.1014 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1015 + 1.1016 + ParseSection(§ion); 1.1017 +} 1.1018 + 1.1019 +TEST_F(CFIInsn, DW_CFA_offset_extended_sf) { 1.1020 + CFISection section(kBigEndian, 8); 1.1021 + StockCIEAndFDE(§ion); 1.1022 + section 1.1023 + .D8(dwarf2reader::DW_CFA_offset_extended_sf) 1.1024 + .ULEB128(0x997c23ee).LEB128(0x2d00) 1.1025 + .D8(dwarf2reader::DW_CFA_offset_extended_sf) 1.1026 + .ULEB128(0x9519eb82).LEB128(-0xa77) 1.1027 + .FinishEntry(); 1.1028 + 1.1029 + EXPECT_CALL(handler, 1.1030 + OffsetRule(fde_start, 0x997c23ee, 1.1031 + kCFARegister, 0x2d00 * data_factor)) 1.1032 + .InSequence(s).WillOnce(Return(true)); 1.1033 + EXPECT_CALL(handler, 1.1034 + OffsetRule(fde_start, 0x9519eb82, 1.1035 + kCFARegister, -0xa77 * data_factor)) 1.1036 + .InSequence(s).WillOnce(Return(true)); 1.1037 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1038 + 1.1039 + ParseSection(§ion); 1.1040 +} 1.1041 + 1.1042 +TEST_F(CFIInsn, DW_CFA_val_offset) { 1.1043 + CFISection section(kBigEndian, 4); 1.1044 + StockCIEAndFDE(§ion); 1.1045 + section 1.1046 + .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673) 1.1047 + .FinishEntry(); 1.1048 + 1.1049 + EXPECT_CALL(handler, 1.1050 + ValOffsetRule(fde_start, 0x623562fe, 1.1051 + kCFARegister, 0x673 * data_factor)) 1.1052 + .InSequence(s).WillOnce(Return(true)); 1.1053 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1054 + 1.1055 + ParseSection(§ion); 1.1056 +} 1.1057 + 1.1058 +TEST_F(CFIInsn, DW_CFA_val_offset_sf) { 1.1059 + CFISection section(kBigEndian, 4); 1.1060 + StockCIEAndFDE(§ion); 1.1061 + section 1.1062 + .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab) 1.1063 + .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2) 1.1064 + .FinishEntry(); 1.1065 + 1.1066 + EXPECT_CALL(handler, 1.1067 + ValOffsetRule(fde_start, 0x6f4f, 1.1068 + kCFARegister, 0xaab * data_factor)) 1.1069 + .InSequence(s).WillOnce(Return(true)); 1.1070 + EXPECT_CALL(handler, 1.1071 + ValOffsetRule(fde_start, 0x2483, 1.1072 + kCFARegister, -0x8a2 * data_factor)) 1.1073 + .InSequence(s).WillOnce(Return(true)); 1.1074 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1075 + 1.1076 + ParseSection(§ion); 1.1077 +} 1.1078 + 1.1079 +TEST_F(CFIInsn, DW_CFA_register) { 1.1080 + CFISection section(kLittleEndian, 8); 1.1081 + StockCIEAndFDE(§ion); 1.1082 + section 1.1083 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414) 1.1084 + .FinishEntry(); 1.1085 + 1.1086 + EXPECT_CALL(handler, RegisterRule(fde_start, 0x278d18f9, 0x1a684414)) 1.1087 + .InSequence(s).WillOnce(Return(true)); 1.1088 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1089 + 1.1090 + ParseSection(§ion); 1.1091 +} 1.1092 + 1.1093 +TEST_F(CFIInsn, DW_CFA_expression) { 1.1094 + CFISection section(kBigEndian, 8); 1.1095 + StockCIEAndFDE(§ion); 1.1096 + section 1.1097 + .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xa1619fb2) 1.1098 + .Block("plus ça change, plus c'est la même chose") 1.1099 + .FinishEntry(); 1.1100 + 1.1101 + EXPECT_CALL(handler, 1.1102 + ExpressionRule(fde_start, 0xa1619fb2, 1.1103 + "plus ça change, plus c'est la même chose")) 1.1104 + .InSequence(s).WillOnce(Return(true)); 1.1105 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1106 + 1.1107 + ParseSection(§ion); 1.1108 +} 1.1109 + 1.1110 +TEST_F(CFIInsn, DW_CFA_val_expression) { 1.1111 + CFISection section(kBigEndian, 4); 1.1112 + StockCIEAndFDE(§ion); 1.1113 + section 1.1114 + .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xc5e4a9e3) 1.1115 + .Block("he who has the gold makes the rules") 1.1116 + .FinishEntry(); 1.1117 + 1.1118 + EXPECT_CALL(handler, 1.1119 + ValExpressionRule(fde_start, 0xc5e4a9e3, 1.1120 + "he who has the gold makes the rules")) 1.1121 + .InSequence(s).WillOnce(Return(true)); 1.1122 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1123 + 1.1124 + ParseSection(§ion); 1.1125 +} 1.1126 + 1.1127 +TEST_F(CFIInsn, DW_CFA_restore) { 1.1128 + CFISection section(kLittleEndian, 8); 1.1129 + code_factor = 0x01bd188a9b1fa083ULL; 1.1130 + data_factor = -0x1ac8; 1.1131 + return_register = 0x8c35b049; 1.1132 + version = 2; 1.1133 + fde_start = 0x2d70fe998298bbb1ULL; 1.1134 + fde_size = 0x46ccc2e63cf0b108ULL; 1.1135 + Label cie; 1.1136 + section 1.1137 + .Mark(&cie) 1.1138 + .CIEHeader(code_factor, data_factor, return_register, version, 1.1139 + "") 1.1140 + // Provide a CFA rule, because register rules require them. 1.1141 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8) 1.1142 + // Provide an offset(N) rule for register 0x3c. 1.1143 + .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0xb348) 1.1144 + .FinishEntry() 1.1145 + // In the FDE... 1.1146 + .FDEHeader(cie, fde_start, fde_size) 1.1147 + // At a second address, provide a new offset(N) rule for register 0x3c. 1.1148 + .D8(dwarf2reader::DW_CFA_advance_loc | 0x13) 1.1149 + .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0x9a50) 1.1150 + // At a third address, restore the original rule for register 0x3c. 1.1151 + .D8(dwarf2reader::DW_CFA_advance_loc | 0x01) 1.1152 + .D8(dwarf2reader::DW_CFA_restore | 0x3c) 1.1153 + .FinishEntry(); 1.1154 + 1.1155 + { 1.1156 + InSequence s; 1.1157 + EXPECT_CALL(handler, 1.1158 + Entry(_, fde_start, fde_size, version, "", return_register)) 1.1159 + .WillOnce(Return(true)); 1.1160 + // CIE's CFA rule. 1.1161 + EXPECT_CALL(handler, 1.1162 + ValOffsetRule(fde_start, kCFARegister, 0x6ca1d50e, 0x372e38e8)) 1.1163 + .WillOnce(Return(true)); 1.1164 + // CIE's rule for register 0x3c. 1.1165 + EXPECT_CALL(handler, 1.1166 + OffsetRule(fde_start, 0x3c, kCFARegister, 0xb348 * data_factor)) 1.1167 + .WillOnce(Return(true)); 1.1168 + // FDE's rule for register 0x3c. 1.1169 + EXPECT_CALL(handler, 1.1170 + OffsetRule(fde_start + 0x13 * code_factor, 0x3c, 1.1171 + kCFARegister, 0x9a50 * data_factor)) 1.1172 + .WillOnce(Return(true)); 1.1173 + // Restore CIE's rule for register 0x3c. 1.1174 + EXPECT_CALL(handler, 1.1175 + OffsetRule(fde_start + (0x13 + 0x01) * code_factor, 0x3c, 1.1176 + kCFARegister, 0xb348 * data_factor)) 1.1177 + .WillOnce(Return(true)); 1.1178 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1179 + } 1.1180 + 1.1181 + ParseSection(§ion); 1.1182 +} 1.1183 + 1.1184 +TEST_F(CFIInsn, DW_CFA_restoreNoRule) { 1.1185 + CFISection section(kBigEndian, 4); 1.1186 + code_factor = 0x005f78143c1c3b82ULL; 1.1187 + data_factor = 0x25d0; 1.1188 + return_register = 0xe8; 1.1189 + version = 1; 1.1190 + fde_start = 0x4062e30f; 1.1191 + fde_size = 0x5302a389; 1.1192 + Label cie; 1.1193 + section 1.1194 + .Mark(&cie) 1.1195 + .CIEHeader(code_factor, data_factor, return_register, version, "") 1.1196 + // Provide a CFA rule, because register rules require them. 1.1197 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127) 1.1198 + .FinishEntry() 1.1199 + // In the FDE... 1.1200 + .FDEHeader(cie, fde_start, fde_size) 1.1201 + // At a second address, provide an offset(N) rule for register 0x2c. 1.1202 + .D8(dwarf2reader::DW_CFA_advance_loc | 0x7) 1.1203 + .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x1f47) 1.1204 + // At a third address, restore the (missing) CIE rule for register 0x2c. 1.1205 + .D8(dwarf2reader::DW_CFA_advance_loc | 0xb) 1.1206 + .D8(dwarf2reader::DW_CFA_restore | 0x2c) 1.1207 + .FinishEntry(); 1.1208 + 1.1209 + { 1.1210 + InSequence s; 1.1211 + EXPECT_CALL(handler, 1.1212 + Entry(_, fde_start, fde_size, version, "", return_register)) 1.1213 + .WillOnce(Return(true)); 1.1214 + // CIE's CFA rule. 1.1215 + EXPECT_CALL(handler, 1.1216 + ValOffsetRule(fde_start, kCFARegister, 0x470aa334, 0x099ef127)) 1.1217 + .WillOnce(Return(true)); 1.1218 + // FDE's rule for register 0x2c. 1.1219 + EXPECT_CALL(handler, 1.1220 + OffsetRule(fde_start + 0x7 * code_factor, 0x2c, 1.1221 + kCFARegister, 0x1f47 * data_factor)) 1.1222 + .WillOnce(Return(true)); 1.1223 + // Restore CIE's (missing) rule for register 0x2c. 1.1224 + EXPECT_CALL(handler, 1.1225 + SameValueRule(fde_start + (0x7 + 0xb) * code_factor, 0x2c)) 1.1226 + .WillOnce(Return(true)); 1.1227 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1228 + } 1.1229 + 1.1230 + ParseSection(§ion); 1.1231 +} 1.1232 + 1.1233 +TEST_F(CFIInsn, DW_CFA_restore_extended) { 1.1234 + CFISection section(kBigEndian, 4); 1.1235 + code_factor = 0x126e; 1.1236 + data_factor = -0xd8b; 1.1237 + return_register = 0x77711787; 1.1238 + version = 3; 1.1239 + fde_start = 0x01f55a45; 1.1240 + fde_size = 0x452adb80; 1.1241 + Label cie; 1.1242 + section 1.1243 + .Mark(&cie) 1.1244 + .CIEHeader(code_factor, data_factor, return_register, version, 1.1245 + "", true /* dwarf64 */ ) 1.1246 + // Provide a CFA rule, because register rules require them. 1.1247 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5) 1.1248 + // Provide an offset(N) rule for register 0x0f9b8a1c. 1.1249 + .D8(dwarf2reader::DW_CFA_offset_extended) 1.1250 + .ULEB128(0x0f9b8a1c).ULEB128(0xc979) 1.1251 + .FinishEntry() 1.1252 + // In the FDE... 1.1253 + .FDEHeader(cie, fde_start, fde_size) 1.1254 + // At a second address, provide a new offset(N) rule for reg 0x0f9b8a1c. 1.1255 + .D8(dwarf2reader::DW_CFA_advance_loc | 0x3) 1.1256 + .D8(dwarf2reader::DW_CFA_offset_extended) 1.1257 + .ULEB128(0x0f9b8a1c).ULEB128(0x3b7b) 1.1258 + // At a third address, restore the original rule for register 0x0f9b8a1c. 1.1259 + .D8(dwarf2reader::DW_CFA_advance_loc | 0x04) 1.1260 + .D8(dwarf2reader::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c) 1.1261 + .FinishEntry(); 1.1262 + 1.1263 + { 1.1264 + InSequence s; 1.1265 + EXPECT_CALL(handler, 1.1266 + Entry(_, fde_start, fde_size, version, "", return_register)) 1.1267 + .WillOnce(Return(true)); 1.1268 + // CIE's CFA rule. 1.1269 + EXPECT_CALL(handler, 1.1270 + ValOffsetRule(fde_start, kCFARegister, 0x56fa0edd, 0x097f78a5)) 1.1271 + .WillOnce(Return(true)); 1.1272 + // CIE's rule for register 0x0f9b8a1c. 1.1273 + EXPECT_CALL(handler, 1.1274 + OffsetRule(fde_start, 0x0f9b8a1c, kCFARegister, 1.1275 + 0xc979 * data_factor)) 1.1276 + .WillOnce(Return(true)); 1.1277 + // FDE's rule for register 0x0f9b8a1c. 1.1278 + EXPECT_CALL(handler, 1.1279 + OffsetRule(fde_start + 0x3 * code_factor, 0x0f9b8a1c, 1.1280 + kCFARegister, 0x3b7b * data_factor)) 1.1281 + .WillOnce(Return(true)); 1.1282 + // Restore CIE's rule for register 0x0f9b8a1c. 1.1283 + EXPECT_CALL(handler, 1.1284 + OffsetRule(fde_start + (0x3 + 0x4) * code_factor, 0x0f9b8a1c, 1.1285 + kCFARegister, 0xc979 * data_factor)) 1.1286 + .WillOnce(Return(true)); 1.1287 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1288 + } 1.1289 + 1.1290 + ParseSection(§ion); 1.1291 +} 1.1292 + 1.1293 +TEST_F(CFIInsn, DW_CFA_remember_and_restore_state) { 1.1294 + CFISection section(kLittleEndian, 8); 1.1295 + StockCIEAndFDE(§ion); 1.1296 + 1.1297 + // We create a state, save it, modify it, and then restore. We 1.1298 + // refer to the state that is overridden the restore as the 1.1299 + // "outgoing" state, and the restored state the "incoming" state. 1.1300 + // 1.1301 + // Register outgoing incoming expect 1.1302 + // 1 offset(N) no rule new "same value" rule 1.1303 + // 2 register(R) offset(N) report changed rule 1.1304 + // 3 offset(N) offset(M) report changed offset 1.1305 + // 4 offset(N) offset(N) no report 1.1306 + // 5 offset(N) no rule new "same value" rule 1.1307 + section 1.1308 + // Create the "incoming" state, which we will save and later restore. 1.1309 + .D8(dwarf2reader::DW_CFA_offset | 2).ULEB128(0x9806) 1.1310 + .D8(dwarf2reader::DW_CFA_offset | 3).ULEB128(0x995d) 1.1311 + .D8(dwarf2reader::DW_CFA_offset | 4).ULEB128(0x7055) 1.1312 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1313 + // Advance to a new instruction; an implementation could legitimately 1.1314 + // ignore all but the final rule for a given register at a given address. 1.1315 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1316 + // Create the "outgoing" state, which we will discard. 1.1317 + .D8(dwarf2reader::DW_CFA_offset | 1).ULEB128(0xea1a) 1.1318 + .D8(dwarf2reader::DW_CFA_register).ULEB128(2).ULEB128(0x1d2a3767) 1.1319 + .D8(dwarf2reader::DW_CFA_offset | 3).ULEB128(0xdd29) 1.1320 + .D8(dwarf2reader::DW_CFA_offset | 5).ULEB128(0xf1ce) 1.1321 + // At a third address, restore the incoming state. 1.1322 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1323 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1324 + .FinishEntry(); 1.1325 + 1.1326 + uint64 addr = fde_start; 1.1327 + 1.1328 + // Expect the incoming rules to be reported. 1.1329 + EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor)) 1.1330 + .InSequence(s).WillOnce(Return(true)); 1.1331 + EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor)) 1.1332 + .InSequence(s).WillOnce(Return(true)); 1.1333 + EXPECT_CALL(handler, OffsetRule(addr, 4, kCFARegister, 0x7055 * data_factor)) 1.1334 + .InSequence(s).WillOnce(Return(true)); 1.1335 + 1.1336 + addr += code_factor; 1.1337 + 1.1338 + // After the save, we establish the outgoing rule set. 1.1339 + EXPECT_CALL(handler, OffsetRule(addr, 1, kCFARegister, 0xea1a * data_factor)) 1.1340 + .InSequence(s).WillOnce(Return(true)); 1.1341 + EXPECT_CALL(handler, RegisterRule(addr, 2, 0x1d2a3767)) 1.1342 + .InSequence(s).WillOnce(Return(true)); 1.1343 + EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0xdd29 * data_factor)) 1.1344 + .InSequence(s).WillOnce(Return(true)); 1.1345 + EXPECT_CALL(handler, OffsetRule(addr, 5, kCFARegister, 0xf1ce * data_factor)) 1.1346 + .InSequence(s).WillOnce(Return(true)); 1.1347 + 1.1348 + addr += code_factor; 1.1349 + 1.1350 + // Finally, after the restore, expect to see the differences from 1.1351 + // the outgoing to the incoming rules reported. 1.1352 + EXPECT_CALL(handler, SameValueRule(addr, 1)) 1.1353 + .InSequence(s).WillOnce(Return(true)); 1.1354 + EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor)) 1.1355 + .InSequence(s).WillOnce(Return(true)); 1.1356 + EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor)) 1.1357 + .InSequence(s).WillOnce(Return(true)); 1.1358 + EXPECT_CALL(handler, SameValueRule(addr, 5)) 1.1359 + .InSequence(s).WillOnce(Return(true)); 1.1360 + 1.1361 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1362 + 1.1363 + ParseSection(§ion); 1.1364 +} 1.1365 + 1.1366 +// Check that restoring a rule set reports changes to the CFA rule. 1.1367 +TEST_F(CFIInsn, DW_CFA_remember_and_restore_stateCFA) { 1.1368 + CFISection section(kBigEndian, 4); 1.1369 + StockCIEAndFDE(§ion); 1.1370 + 1.1371 + section 1.1372 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1373 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1374 + .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x90481102) 1.1375 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1376 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1377 + .FinishEntry(); 1.1378 + 1.1379 + EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, kCFARegister, 1.1380 + cfa_base_register, 0x90481102)) 1.1381 + .InSequence(s).WillOnce(Return(true)); 1.1382 + EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor * 2, kCFARegister, 1.1383 + cfa_base_register, cfa_offset)) 1.1384 + .InSequence(s).WillOnce(Return(true)); 1.1385 + 1.1386 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1387 + 1.1388 + ParseSection(§ion); 1.1389 +} 1.1390 + 1.1391 +TEST_F(CFIInsn, DW_CFA_nop) { 1.1392 + CFISection section(kLittleEndian, 4); 1.1393 + StockCIEAndFDE(§ion); 1.1394 + section 1.1395 + .D8(dwarf2reader::DW_CFA_nop) 1.1396 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b) 1.1397 + .D8(dwarf2reader::DW_CFA_nop) 1.1398 + .FinishEntry(); 1.1399 + 1.1400 + EXPECT_CALL(handler, 1.1401 + ValOffsetRule(fde_start, kCFARegister, 0x3fb8d4f1, 0x078dc67b)) 1.1402 + .InSequence(s).WillOnce(Return(true)); 1.1403 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1404 + 1.1405 + ParseSection(§ion); 1.1406 +} 1.1407 + 1.1408 +TEST_F(CFIInsn, DW_CFA_GNU_window_save) { 1.1409 + CFISection section(kBigEndian, 4); 1.1410 + StockCIEAndFDE(§ion); 1.1411 + section 1.1412 + .D8(dwarf2reader::DW_CFA_GNU_window_save) 1.1413 + .FinishEntry(); 1.1414 + 1.1415 + // Don't include all the rules in any particular sequence. 1.1416 + 1.1417 + // The caller's %o0-%o7 have become the callee's %i0-%i7. This is 1.1418 + // the GCC register numbering. 1.1419 + for (int i = 8; i < 16; i++) 1.1420 + EXPECT_CALL(handler, RegisterRule(fde_start, i, i + 16)) 1.1421 + .WillOnce(Return(true)); 1.1422 + // The caller's %l0-%l7 and %i0-%i7 have been saved at the top of 1.1423 + // its frame. 1.1424 + for (int i = 16; i < 32; i++) 1.1425 + EXPECT_CALL(handler, OffsetRule(fde_start, i, kCFARegister, (i-16) * 4)) 1.1426 + .WillOnce(Return(true)); 1.1427 + 1.1428 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1429 + 1.1430 + ParseSection(§ion); 1.1431 +} 1.1432 + 1.1433 +TEST_F(CFIInsn, DW_CFA_GNU_args_size) { 1.1434 + CFISection section(kLittleEndian, 8); 1.1435 + StockCIEAndFDE(§ion); 1.1436 + section 1.1437 + .D8(dwarf2reader::DW_CFA_GNU_args_size).ULEB128(0xeddfa520) 1.1438 + // Verify that we see this, meaning we parsed the above properly. 1.1439 + .D8(dwarf2reader::DW_CFA_offset | 0x23).ULEB128(0x269) 1.1440 + .FinishEntry(); 1.1441 + 1.1442 + EXPECT_CALL(handler, 1.1443 + OffsetRule(fde_start, 0x23, kCFARegister, 0x269 * data_factor)) 1.1444 + .InSequence(s).WillOnce(Return(true)); 1.1445 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1446 + 1.1447 + ParseSection(§ion); 1.1448 +} 1.1449 + 1.1450 +TEST_F(CFIInsn, DW_CFA_GNU_negative_offset_extended) { 1.1451 + CFISection section(kLittleEndian, 4); 1.1452 + StockCIEAndFDE(§ion); 1.1453 + section 1.1454 + .D8(dwarf2reader::DW_CFA_GNU_negative_offset_extended) 1.1455 + .ULEB128(0x430cc87a).ULEB128(0x613) 1.1456 + .FinishEntry(); 1.1457 + 1.1458 + EXPECT_CALL(handler, 1.1459 + OffsetRule(fde_start, 0x430cc87a, 1.1460 + kCFARegister, -0x613 * data_factor)) 1.1461 + .InSequence(s).WillOnce(Return(true)); 1.1462 + EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true)); 1.1463 + 1.1464 + ParseSection(§ion); 1.1465 +} 1.1466 + 1.1467 +// Three FDEs: skip the second 1.1468 +TEST_F(CFIInsn, SkipFDE) { 1.1469 + CFISection section(kBigEndian, 4); 1.1470 + Label cie; 1.1471 + section 1.1472 + // CIE, used by all FDEs. 1.1473 + .Mark(&cie) 1.1474 + .CIEHeader(0x010269f2, 0x9177, 0xedca5849, 2, "") 1.1475 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad) 1.1476 + .FinishEntry() 1.1477 + // First FDE. 1.1478 + .FDEHeader(cie, 0xa870ebdd, 0x60f6aa4) 1.1479 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf) 1.1480 + .FinishEntry() 1.1481 + // Second FDE. 1.1482 + .FDEHeader(cie, 0xc534f7c0, 0xf6552e9, true /* dwarf64 */) 1.1483 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18) 1.1484 + .FinishEntry() 1.1485 + // Third FDE. 1.1486 + .FDEHeader(cie, 0xf681cfc8, 0x7e4594e) 1.1487 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4) 1.1488 + .FinishEntry(); 1.1489 + 1.1490 + { 1.1491 + InSequence s; 1.1492 + 1.1493 + // Process the first FDE. 1.1494 + EXPECT_CALL(handler, Entry(_, 0xa870ebdd, 0x60f6aa4, 2, "", 0xedca5849)) 1.1495 + .WillOnce(Return(true)); 1.1496 + EXPECT_CALL(handler, ValOffsetRule(0xa870ebdd, kCFARegister, 1.1497 + 0x42ed390b, 0x98f43aad)) 1.1498 + .WillOnce(Return(true)); 1.1499 + EXPECT_CALL(handler, RegisterRule(0xa870ebdd, 0x3a860351, 0x6c9a6bcf)) 1.1500 + .WillOnce(Return(true)); 1.1501 + EXPECT_CALL(handler, End()) 1.1502 + .WillOnce(Return(true)); 1.1503 + 1.1504 + // Skip the second FDE. 1.1505 + EXPECT_CALL(handler, Entry(_, 0xc534f7c0, 0xf6552e9, 2, "", 0xedca5849)) 1.1506 + .WillOnce(Return(false)); 1.1507 + 1.1508 + // Process the third FDE. 1.1509 + EXPECT_CALL(handler, Entry(_, 0xf681cfc8, 0x7e4594e, 2, "", 0xedca5849)) 1.1510 + .WillOnce(Return(true)); 1.1511 + EXPECT_CALL(handler, ValOffsetRule(0xf681cfc8, kCFARegister, 1.1512 + 0x42ed390b, 0x98f43aad)) 1.1513 + .WillOnce(Return(true)); 1.1514 + EXPECT_CALL(handler, RegisterRule(0xf681cfc8, 0x26c53934, 0x18eeb8a4)) 1.1515 + .WillOnce(Return(true)); 1.1516 + EXPECT_CALL(handler, End()) 1.1517 + .WillOnce(Return(true)); 1.1518 + } 1.1519 + 1.1520 + ParseSection(§ion); 1.1521 +} 1.1522 + 1.1523 +// Quit processing in the middle of an entry's instructions. 1.1524 +TEST_F(CFIInsn, QuitMidentry) { 1.1525 + CFISection section(kLittleEndian, 8); 1.1526 + StockCIEAndFDE(§ion); 1.1527 + section 1.1528 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431) 1.1529 + .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat") 1.1530 + .FinishEntry(); 1.1531 + 1.1532 + EXPECT_CALL(handler, RegisterRule(fde_start, 0xe0cf850d, 0x15aab431)) 1.1533 + .InSequence(s).WillOnce(Return(false)); 1.1534 + EXPECT_CALL(handler, End()) 1.1535 + .InSequence(s).WillOnce(Return(true)); 1.1536 + 1.1537 + ParseSection(§ion, false); 1.1538 +} 1.1539 + 1.1540 +class CFIRestore: public CFIInsnFixture, public Test { }; 1.1541 + 1.1542 +TEST_F(CFIRestore, RestoreUndefinedRuleUnchanged) { 1.1543 + CFISection section(kLittleEndian, 4); 1.1544 + StockCIEAndFDE(§ion); 1.1545 + section 1.1546 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x0bac878e) 1.1547 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1548 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1549 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1550 + .FinishEntry(); 1.1551 + 1.1552 + EXPECT_CALL(handler, UndefinedRule(fde_start, 0x0bac878e)) 1.1553 + .InSequence(s).WillOnce(Return(true)); 1.1554 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1555 + 1.1556 + ParseSection(§ion); 1.1557 +} 1.1558 + 1.1559 +TEST_F(CFIRestore, RestoreUndefinedRuleChanged) { 1.1560 + CFISection section(kLittleEndian, 4); 1.1561 + StockCIEAndFDE(§ion); 1.1562 + section 1.1563 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x7dedff5f) 1.1564 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1565 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1566 + .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x7dedff5f) 1.1567 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1568 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1569 + .FinishEntry(); 1.1570 + 1.1571 + EXPECT_CALL(handler, UndefinedRule(fde_start, 0x7dedff5f)) 1.1572 + .InSequence(s).WillOnce(Return(true)); 1.1573 + EXPECT_CALL(handler, SameValueRule(fde_start + code_factor, 0x7dedff5f)) 1.1574 + .InSequence(s).WillOnce(Return(true)); 1.1575 + EXPECT_CALL(handler, UndefinedRule(fde_start + 2 * code_factor, 0x7dedff5f)) 1.1576 + .InSequence(s).WillOnce(Return(true)); 1.1577 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1578 + 1.1579 + ParseSection(§ion); 1.1580 +} 1.1581 + 1.1582 +TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) { 1.1583 + CFISection section(kLittleEndian, 4); 1.1584 + StockCIEAndFDE(§ion); 1.1585 + section 1.1586 + .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0xadbc9b3a) 1.1587 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1588 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1589 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1590 + .FinishEntry(); 1.1591 + 1.1592 + EXPECT_CALL(handler, SameValueRule(fde_start, 0xadbc9b3a)) 1.1593 + .InSequence(s).WillOnce(Return(true)); 1.1594 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1595 + 1.1596 + ParseSection(§ion); 1.1597 +} 1.1598 + 1.1599 +TEST_F(CFIRestore, RestoreSameValueRuleChanged) { 1.1600 + CFISection section(kLittleEndian, 4); 1.1601 + StockCIEAndFDE(§ion); 1.1602 + section 1.1603 + .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3d90dcb5) 1.1604 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1605 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1606 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x3d90dcb5) 1.1607 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1608 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1609 + .FinishEntry(); 1.1610 + 1.1611 + EXPECT_CALL(handler, SameValueRule(fde_start, 0x3d90dcb5)) 1.1612 + .InSequence(s).WillOnce(Return(true)); 1.1613 + EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x3d90dcb5)) 1.1614 + .InSequence(s).WillOnce(Return(true)); 1.1615 + EXPECT_CALL(handler, SameValueRule(fde_start + 2 * code_factor, 0x3d90dcb5)) 1.1616 + .InSequence(s).WillOnce(Return(true)); 1.1617 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1618 + 1.1619 + ParseSection(§ion); 1.1620 +} 1.1621 + 1.1622 +TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) { 1.1623 + CFISection section(kLittleEndian, 4); 1.1624 + StockCIEAndFDE(§ion); 1.1625 + section 1.1626 + .D8(dwarf2reader::DW_CFA_offset | 0x14).ULEB128(0xb6f) 1.1627 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1628 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1629 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1630 + .FinishEntry(); 1.1631 + 1.1632 + EXPECT_CALL(handler, OffsetRule(fde_start, 0x14, 1.1633 + kCFARegister, 0xb6f * data_factor)) 1.1634 + .InSequence(s).WillOnce(Return(true)); 1.1635 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1636 + 1.1637 + ParseSection(§ion); 1.1638 +} 1.1639 + 1.1640 +TEST_F(CFIRestore, RestoreOffsetRuleChanged) { 1.1641 + CFISection section(kLittleEndian, 4); 1.1642 + StockCIEAndFDE(§ion); 1.1643 + section 1.1644 + .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xeb7) 1.1645 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1646 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1647 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x21) 1.1648 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1649 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1650 + .FinishEntry(); 1.1651 + 1.1652 + EXPECT_CALL(handler, OffsetRule(fde_start, 0x21, 1.1653 + kCFARegister, 0xeb7 * data_factor)) 1.1654 + .InSequence(s).WillOnce(Return(true)); 1.1655 + EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x21)) 1.1656 + .InSequence(s).WillOnce(Return(true)); 1.1657 + EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21, 1.1658 + kCFARegister, 0xeb7 * data_factor)) 1.1659 + .InSequence(s).WillOnce(Return(true)); 1.1660 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1661 + 1.1662 + ParseSection(§ion); 1.1663 +} 1.1664 + 1.1665 +TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) { 1.1666 + CFISection section(kLittleEndian, 4); 1.1667 + StockCIEAndFDE(§ion); 1.1668 + section 1.1669 + .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0x134) 1.1670 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1671 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1672 + .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xf4f) 1.1673 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1674 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1675 + .FinishEntry(); 1.1676 + 1.1677 + EXPECT_CALL(handler, OffsetRule(fde_start, 0x21, 1.1678 + kCFARegister, 0x134 * data_factor)) 1.1679 + .InSequence(s).WillOnce(Return(true)); 1.1680 + EXPECT_CALL(handler, OffsetRule(fde_start + code_factor, 0x21, 1.1681 + kCFARegister, 0xf4f * data_factor)) 1.1682 + .InSequence(s).WillOnce(Return(true)); 1.1683 + EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21, 1.1684 + kCFARegister, 0x134 * data_factor)) 1.1685 + .InSequence(s).WillOnce(Return(true)); 1.1686 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1687 + 1.1688 + ParseSection(§ion); 1.1689 +} 1.1690 + 1.1691 +TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) { 1.1692 + CFISection section(kLittleEndian, 4); 1.1693 + StockCIEAndFDE(§ion); 1.1694 + section 1.1695 + .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c) 1.1696 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1697 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1698 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1699 + .FinishEntry(); 1.1700 + 1.1701 + EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x829caee6, 1.1702 + kCFARegister, 0xe4c * data_factor)) 1.1703 + .InSequence(s).WillOnce(Return(true)); 1.1704 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1705 + 1.1706 + ParseSection(§ion); 1.1707 +} 1.1708 + 1.1709 +TEST_F(CFIRestore, RestoreValOffsetRuleChanged) { 1.1710 + CFISection section(kLittleEndian, 4); 1.1711 + StockCIEAndFDE(§ion); 1.1712 + section 1.1713 + .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7) 1.1714 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1715 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1716 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xf17c36d6) 1.1717 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1718 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1719 + .FinishEntry(); 1.1720 + 1.1721 + EXPECT_CALL(handler, ValOffsetRule(fde_start, 0xf17c36d6, 1.1722 + kCFARegister, 0xeb7 * data_factor)) 1.1723 + .InSequence(s).WillOnce(Return(true)); 1.1724 + EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xf17c36d6)) 1.1725 + .InSequence(s).WillOnce(Return(true)); 1.1726 + EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0xf17c36d6, 1.1727 + kCFARegister, 0xeb7 * data_factor)) 1.1728 + .InSequence(s).WillOnce(Return(true)); 1.1729 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1730 + 1.1731 + ParseSection(§ion); 1.1732 +} 1.1733 + 1.1734 +TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) { 1.1735 + CFISection section(kLittleEndian, 4); 1.1736 + StockCIEAndFDE(§ion); 1.1737 + section 1.1738 + .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562) 1.1739 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1740 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1741 + .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88) 1.1742 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1743 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1744 + .FinishEntry(); 1.1745 + 1.1746 + EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x2cf0ab1b, 1.1747 + kCFARegister, 0x562 * data_factor)) 1.1748 + .InSequence(s).WillOnce(Return(true)); 1.1749 + EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, 0x2cf0ab1b, 1.1750 + kCFARegister, 0xe88 * data_factor)) 1.1751 + .InSequence(s).WillOnce(Return(true)); 1.1752 + EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0x2cf0ab1b, 1.1753 + kCFARegister, 0x562 * data_factor)) 1.1754 + .InSequence(s).WillOnce(Return(true)); 1.1755 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1756 + 1.1757 + ParseSection(§ion); 1.1758 +} 1.1759 + 1.1760 +TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) { 1.1761 + CFISection section(kLittleEndian, 4); 1.1762 + StockCIEAndFDE(§ion); 1.1763 + section 1.1764 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce) 1.1765 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1766 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1767 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1768 + .FinishEntry(); 1.1769 + 1.1770 + EXPECT_CALL(handler, RegisterRule(fde_start, 0x77514acc, 0x464de4ce)) 1.1771 + .InSequence(s).WillOnce(Return(true)); 1.1772 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1773 + 1.1774 + ParseSection(§ion); 1.1775 +} 1.1776 + 1.1777 +TEST_F(CFIRestore, RestoreRegisterRuleChanged) { 1.1778 + CFISection section(kLittleEndian, 4); 1.1779 + StockCIEAndFDE(§ion); 1.1780 + section 1.1781 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559) 1.1782 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1783 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1784 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xe39acce5) 1.1785 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1786 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1787 + .FinishEntry(); 1.1788 + 1.1789 + EXPECT_CALL(handler, RegisterRule(fde_start, 0xe39acce5, 0x095f1559)) 1.1790 + .InSequence(s).WillOnce(Return(true)); 1.1791 + EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xe39acce5)) 1.1792 + .InSequence(s).WillOnce(Return(true)); 1.1793 + EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xe39acce5, 1.1794 + 0x095f1559)) 1.1795 + .InSequence(s).WillOnce(Return(true)); 1.1796 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1797 + 1.1798 + ParseSection(§ion); 1.1799 +} 1.1800 + 1.1801 +TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) { 1.1802 + CFISection section(kLittleEndian, 4); 1.1803 + StockCIEAndFDE(§ion); 1.1804 + section 1.1805 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a) 1.1806 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1807 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1808 + .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742) 1.1809 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1810 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1811 + .FinishEntry(); 1.1812 + 1.1813 + EXPECT_CALL(handler, RegisterRule(fde_start, 0xd40e21b1, 0x16607d6a)) 1.1814 + .InSequence(s).WillOnce(Return(true)); 1.1815 + EXPECT_CALL(handler, RegisterRule(fde_start + code_factor, 0xd40e21b1, 1.1816 + 0xbabb4742)) 1.1817 + .InSequence(s).WillOnce(Return(true)); 1.1818 + EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xd40e21b1, 1.1819 + 0x16607d6a)) 1.1820 + .InSequence(s).WillOnce(Return(true)); 1.1821 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1822 + 1.1823 + ParseSection(§ion); 1.1824 +} 1.1825 + 1.1826 +TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) { 1.1827 + CFISection section(kLittleEndian, 4); 1.1828 + StockCIEAndFDE(§ion); 1.1829 + section 1.1830 + .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf") 1.1831 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1832 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1833 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1834 + .FinishEntry(); 1.1835 + 1.1836 + EXPECT_CALL(handler, ExpressionRule(fde_start, 0x666ae152, "dwarf")) 1.1837 + .InSequence(s).WillOnce(Return(true)); 1.1838 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1839 + 1.1840 + ParseSection(§ion); 1.1841 +} 1.1842 + 1.1843 +TEST_F(CFIRestore, RestoreExpressionRuleChanged) { 1.1844 + CFISection section(kLittleEndian, 4); 1.1845 + StockCIEAndFDE(§ion); 1.1846 + section 1.1847 + .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf") 1.1848 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1849 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1850 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46) 1.1851 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1852 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1853 + .FinishEntry(); 1.1854 + 1.1855 + EXPECT_CALL(handler, ExpressionRule(fde_start, 0xb5ca5c46, "elf")) 1.1856 + .InSequence(s).WillOnce(Return(true)); 1.1857 + EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46)) 1.1858 + .InSequence(s).WillOnce(Return(true)); 1.1859 + EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46, 1.1860 + "elf")) 1.1861 + .InSequence(s).WillOnce(Return(true)); 1.1862 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1863 + 1.1864 + ParseSection(§ion); 1.1865 +} 1.1866 + 1.1867 +TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) { 1.1868 + CFISection section(kLittleEndian, 4); 1.1869 + StockCIEAndFDE(§ion); 1.1870 + section 1.1871 + .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf") 1.1872 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1873 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1874 + .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("orc") 1.1875 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1876 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1877 + .FinishEntry(); 1.1878 + 1.1879 + EXPECT_CALL(handler, ExpressionRule(fde_start, 0x500f5739, "smurf")) 1.1880 + .InSequence(s).WillOnce(Return(true)); 1.1881 + EXPECT_CALL(handler, ExpressionRule(fde_start + code_factor, 0x500f5739, 1.1882 + "orc")) 1.1883 + .InSequence(s).WillOnce(Return(true)); 1.1884 + // Expectations are not wishes. 1.1885 + EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0x500f5739, 1.1886 + "smurf")) 1.1887 + .InSequence(s).WillOnce(Return(true)); 1.1888 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1889 + 1.1890 + ParseSection(§ion); 1.1891 +} 1.1892 + 1.1893 +TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) { 1.1894 + CFISection section(kLittleEndian, 4); 1.1895 + StockCIEAndFDE(§ion); 1.1896 + section 1.1897 + .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x666ae152) 1.1898 + .Block("hideous") 1.1899 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1900 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1901 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1902 + .FinishEntry(); 1.1903 + 1.1904 + EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x666ae152, "hideous")) 1.1905 + .InSequence(s).WillOnce(Return(true)); 1.1906 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1907 + 1.1908 + ParseSection(§ion); 1.1909 +} 1.1910 + 1.1911 +TEST_F(CFIRestore, RestoreValExpressionRuleChanged) { 1.1912 + CFISection section(kLittleEndian, 4); 1.1913 + StockCIEAndFDE(§ion); 1.1914 + section 1.1915 + .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xb5ca5c46) 1.1916 + .Block("revolting") 1.1917 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1918 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1919 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46) 1.1920 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1921 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1922 + .FinishEntry(); 1.1923 + 1.1924 + PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChanged", section); 1.1925 + 1.1926 + EXPECT_CALL(handler, ValExpressionRule(fde_start, 0xb5ca5c46, "revolting")) 1.1927 + .InSequence(s).WillOnce(Return(true)); 1.1928 + EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46)) 1.1929 + .InSequence(s).WillOnce(Return(true)); 1.1930 + EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46, 1.1931 + "revolting")) 1.1932 + .InSequence(s).WillOnce(Return(true)); 1.1933 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1934 + 1.1935 + ParseSection(§ion); 1.1936 +} 1.1937 + 1.1938 +TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) { 1.1939 + CFISection section(kLittleEndian, 4); 1.1940 + StockCIEAndFDE(§ion); 1.1941 + section 1.1942 + .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739) 1.1943 + .Block("repulsive") 1.1944 + .D8(dwarf2reader::DW_CFA_remember_state) 1.1945 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1946 + .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739) 1.1947 + .Block("nauseous") 1.1948 + .D8(dwarf2reader::DW_CFA_advance_loc | 1) 1.1949 + .D8(dwarf2reader::DW_CFA_restore_state) 1.1950 + .FinishEntry(); 1.1951 + 1.1952 + PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChangedValExpression", 1.1953 + section); 1.1954 + 1.1955 + EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x500f5739, "repulsive")) 1.1956 + .InSequence(s).WillOnce(Return(true)); 1.1957 + EXPECT_CALL(handler, ValExpressionRule(fde_start + code_factor, 0x500f5739, 1.1958 + "nauseous")) 1.1959 + .InSequence(s).WillOnce(Return(true)); 1.1960 + // Expectations are not wishes. 1.1961 + EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0x500f5739, 1.1962 + "repulsive")) 1.1963 + .InSequence(s).WillOnce(Return(true)); 1.1964 + EXPECT_CALL(handler, End()).WillOnce(Return(true)); 1.1965 + 1.1966 + ParseSection(§ion); 1.1967 +} 1.1968 + 1.1969 +struct EHFrameFixture: public CFIInsnFixture { 1.1970 + EHFrameFixture() 1.1971 + : CFIInsnFixture(), section(kBigEndian, 4, true) { 1.1972 + encoded_pointer_bases.cfi = 0x7f496cb2; 1.1973 + encoded_pointer_bases.text = 0x540f67b6; 1.1974 + encoded_pointer_bases.data = 0xe3eab768; 1.1975 + section.SetEncodedPointerBases(encoded_pointer_bases); 1.1976 + } 1.1977 + CFISection section; 1.1978 + CFISection::EncodedPointerBases encoded_pointer_bases; 1.1979 + 1.1980 + // Parse CFIInsnFixture::ParseSection, but parse the section as 1.1981 + // .eh_frame data, supplying stock base addresses. 1.1982 + void ParseEHFrameSection(CFISection *section, bool succeeds = true) { 1.1983 + EXPECT_TRUE(section->ContainsEHFrame()); 1.1984 + string contents; 1.1985 + EXPECT_TRUE(section->GetContents(&contents)); 1.1986 + dwarf2reader::Endianness endianness; 1.1987 + if (section->endianness() == kBigEndian) 1.1988 + endianness = ENDIANNESS_BIG; 1.1989 + else { 1.1990 + assert(section->endianness() == kLittleEndian); 1.1991 + endianness = ENDIANNESS_LITTLE; 1.1992 + } 1.1993 + ByteReader byte_reader(endianness); 1.1994 + byte_reader.SetAddressSize(section->AddressSize()); 1.1995 + byte_reader.SetCFIDataBase(encoded_pointer_bases.cfi, contents.data()); 1.1996 + byte_reader.SetTextBase(encoded_pointer_bases.text); 1.1997 + byte_reader.SetDataBase(encoded_pointer_bases.data); 1.1998 + CallFrameInfo parser(contents.data(), contents.size(), 1.1999 + &byte_reader, &handler, &reporter, true); 1.2000 + if (succeeds) 1.2001 + EXPECT_TRUE(parser.Start()); 1.2002 + else 1.2003 + EXPECT_FALSE(parser.Start()); 1.2004 + } 1.2005 + 1.2006 +}; 1.2007 + 1.2008 +class EHFrame: public EHFrameFixture, public Test { }; 1.2009 + 1.2010 +// A simple CIE, an FDE, and a terminator. 1.2011 +TEST_F(EHFrame, Terminator) { 1.2012 + Label cie; 1.2013 + section 1.2014 + .Mark(&cie) 1.2015 + .CIEHeader(9968, 2466, 67, 1, "") 1.2016 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372) 1.2017 + .FinishEntry() 1.2018 + .FDEHeader(cie, 0x848037a1, 0x7b30475e) 1.2019 + .D8(dwarf2reader::DW_CFA_set_loc).D32(0x17713850) 1.2020 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(5721) 1.2021 + .FinishEntry() 1.2022 + .D32(0) // Terminate the sequence. 1.2023 + // This FDE should be ignored. 1.2024 + .FDEHeader(cie, 0xf19629fe, 0x439fb09b) 1.2025 + .FinishEntry(); 1.2026 + 1.2027 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.Terminator", section); 1.2028 + 1.2029 + EXPECT_CALL(handler, Entry(_, 0x848037a1, 0x7b30475e, 1, "", 67)) 1.2030 + .InSequence(s).WillOnce(Return(true)); 1.2031 + EXPECT_CALL(handler, ValOffsetRule(0x848037a1, kCFARegister, 3772, 1372)) 1.2032 + .InSequence(s).WillOnce(Return(true)); 1.2033 + EXPECT_CALL(handler, UndefinedRule(0x17713850, 5721)) 1.2034 + .InSequence(s).WillOnce(Return(true)); 1.2035 + EXPECT_CALL(handler, End()) 1.2036 + .InSequence(s).WillOnce(Return(true)); 1.2037 + EXPECT_CALL(reporter, EarlyEHTerminator(_)) 1.2038 + .InSequence(s).WillOnce(Return()); 1.2039 + 1.2040 + ParseEHFrameSection(§ion); 1.2041 +} 1.2042 + 1.2043 +// The parser should recognize the Linux Standards Base 'z' augmentations. 1.2044 +TEST_F(EHFrame, SimpleFDE) { 1.2045 + DwarfPointerEncoding lsda_encoding = 1.2046 + DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect 1.2047 + | dwarf2reader::DW_EH_PE_datarel 1.2048 + | dwarf2reader::DW_EH_PE_sdata2); 1.2049 + DwarfPointerEncoding fde_encoding = 1.2050 + DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel 1.2051 + | dwarf2reader::DW_EH_PE_udata2); 1.2052 + 1.2053 + section.SetPointerEncoding(fde_encoding); 1.2054 + section.SetEncodedPointerBases(encoded_pointer_bases); 1.2055 + Label cie; 1.2056 + section 1.2057 + .Mark(&cie) 1.2058 + .CIEHeader(4873, 7012, 100, 1, "zSLPR") 1.2059 + .ULEB128(7) // Augmentation data length 1.2060 + .D8(lsda_encoding) // LSDA pointer format 1.2061 + .D8(dwarf2reader::DW_EH_PE_pcrel) // personality pointer format 1.2062 + .EncodedPointer(0x97baa00, dwarf2reader::DW_EH_PE_pcrel) // and value 1.2063 + .D8(fde_encoding) // FDE pointer format 1.2064 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(6706).ULEB128(31) 1.2065 + .FinishEntry() 1.2066 + .FDEHeader(cie, 0x540f6b56, 0xf686) 1.2067 + .ULEB128(2) // Augmentation data length 1.2068 + .EncodedPointer(0xe3eab475, lsda_encoding) // LSDA pointer, signed 1.2069 + .D8(dwarf2reader::DW_CFA_set_loc) 1.2070 + .EncodedPointer(0x540fa4ce, fde_encoding) 1.2071 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x675e) 1.2072 + .FinishEntry() 1.2073 + .D32(0); // terminator 1.2074 + 1.2075 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.SimpleFDE", section); 1.2076 + 1.2077 + EXPECT_CALL(handler, Entry(_, 0x540f6b56, 0xf686, 1, "zSLPR", 100)) 1.2078 + .InSequence(s).WillOnce(Return(true)); 1.2079 + EXPECT_CALL(handler, PersonalityRoutine(0x97baa00, false)) 1.2080 + .InSequence(s).WillOnce(Return(true)); 1.2081 + EXPECT_CALL(handler, LanguageSpecificDataArea(0xe3eab475, true)) 1.2082 + .InSequence(s).WillOnce(Return(true)); 1.2083 + EXPECT_CALL(handler, SignalHandler()) 1.2084 + .InSequence(s).WillOnce(Return(true)); 1.2085 + EXPECT_CALL(handler, ValOffsetRule(0x540f6b56, kCFARegister, 6706, 31)) 1.2086 + .InSequence(s).WillOnce(Return(true)); 1.2087 + EXPECT_CALL(handler, UndefinedRule(0x540fa4ce, 0x675e)) 1.2088 + .InSequence(s).WillOnce(Return(true)); 1.2089 + EXPECT_CALL(handler, End()) 1.2090 + .InSequence(s).WillOnce(Return(true)); 1.2091 + 1.2092 + ParseEHFrameSection(§ion); 1.2093 +} 1.2094 + 1.2095 +// Check that we can handle an empty 'z' augmentation. 1.2096 +TEST_F(EHFrame, EmptyZ) { 1.2097 + Label cie; 1.2098 + section 1.2099 + .Mark(&cie) 1.2100 + .CIEHeader(5955, 5805, 228, 1, "z") 1.2101 + .ULEB128(0) // Augmentation data length 1.2102 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247) 1.2103 + .FinishEntry() 1.2104 + .FDEHeader(cie, 0xda007738, 0xfb55c641) 1.2105 + .ULEB128(0) // Augmentation data length 1.2106 + .D8(dwarf2reader::DW_CFA_advance_loc1).D8(11) 1.2107 + .D8(dwarf2reader::DW_CFA_undefined).ULEB128(3769) 1.2108 + .FinishEntry(); 1.2109 + 1.2110 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.EmptyZ", section); 1.2111 + 1.2112 + EXPECT_CALL(handler, Entry(_, 0xda007738, 0xfb55c641, 1, "z", 228)) 1.2113 + .InSequence(s).WillOnce(Return(true)); 1.2114 + EXPECT_CALL(handler, ValOffsetRule(0xda007738, kCFARegister, 3629, 247)) 1.2115 + .InSequence(s).WillOnce(Return(true)); 1.2116 + EXPECT_CALL(handler, UndefinedRule(0xda007738 + 11 * 5955, 3769)) 1.2117 + .InSequence(s).WillOnce(Return(true)); 1.2118 + EXPECT_CALL(handler, End()) 1.2119 + .InSequence(s).WillOnce(Return(true)); 1.2120 + 1.2121 + ParseEHFrameSection(§ion); 1.2122 +} 1.2123 + 1.2124 +// Check that we recognize bad 'z' augmentation characters. 1.2125 +TEST_F(EHFrame, BadZ) { 1.2126 + Label cie; 1.2127 + section 1.2128 + .Mark(&cie) 1.2129 + .CIEHeader(6937, 1045, 142, 1, "zQ") 1.2130 + .ULEB128(0) // Augmentation data length 1.2131 + .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725) 1.2132 + .FinishEntry() 1.2133 + .FDEHeader(cie, 0x1293efa8, 0x236f53f2) 1.2134 + .ULEB128(0) // Augmentation data length 1.2135 + .D8(dwarf2reader::DW_CFA_advance_loc | 12) 1.2136 + .D8(dwarf2reader::DW_CFA_register).ULEB128(5667).ULEB128(3462) 1.2137 + .FinishEntry(); 1.2138 + 1.2139 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.BadZ", section); 1.2140 + 1.2141 + EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "zQ")) 1.2142 + .WillOnce(Return()); 1.2143 + 1.2144 + ParseEHFrameSection(§ion, false); 1.2145 +} 1.2146 + 1.2147 +TEST_F(EHFrame, zL) { 1.2148 + Label cie; 1.2149 + DwarfPointerEncoding lsda_encoding = 1.2150 + DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel 1.2151 + | dwarf2reader::DW_EH_PE_udata2); 1.2152 + section 1.2153 + .Mark(&cie) 1.2154 + .CIEHeader(9285, 9959, 54, 1, "zL") 1.2155 + .ULEB128(1) // Augmentation data length 1.2156 + .D8(lsda_encoding) // encoding for LSDA pointer in FDE 1.2157 + 1.2158 + .FinishEntry() 1.2159 + .FDEHeader(cie, 0xd40091aa, 0x9aa6e746) 1.2160 + .ULEB128(2) // Augmentation data length 1.2161 + .EncodedPointer(0xd40099cd, lsda_encoding) // LSDA pointer 1.2162 + .FinishEntry() 1.2163 + .D32(0); // terminator 1.2164 + 1.2165 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zL", section); 1.2166 + 1.2167 + EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zL", 54)) 1.2168 + .InSequence(s).WillOnce(Return(true)); 1.2169 + EXPECT_CALL(handler, LanguageSpecificDataArea(0xd40099cd, false)) 1.2170 + .InSequence(s).WillOnce(Return(true)); 1.2171 + EXPECT_CALL(handler, End()) 1.2172 + .InSequence(s).WillOnce(Return(true)); 1.2173 + 1.2174 + ParseEHFrameSection(§ion); 1.2175 +} 1.2176 + 1.2177 +TEST_F(EHFrame, zP) { 1.2178 + Label cie; 1.2179 + DwarfPointerEncoding personality_encoding = 1.2180 + DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel 1.2181 + | dwarf2reader::DW_EH_PE_udata2); 1.2182 + section 1.2183 + .Mark(&cie) 1.2184 + .CIEHeader(1097, 6313, 17, 1, "zP") 1.2185 + .ULEB128(3) // Augmentation data length 1.2186 + .D8(personality_encoding) // encoding for personality routine 1.2187 + .EncodedPointer(0xe3eaccac, personality_encoding) // value 1.2188 + .FinishEntry() 1.2189 + .FDEHeader(cie, 0x0c8350c9, 0xbef11087) 1.2190 + .ULEB128(0) // Augmentation data length 1.2191 + .FinishEntry() 1.2192 + .D32(0); // terminator 1.2193 + 1.2194 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zP", section); 1.2195 + 1.2196 + EXPECT_CALL(handler, Entry(_, 0x0c8350c9, 0xbef11087, 1, "zP", 17)) 1.2197 + .InSequence(s).WillOnce(Return(true)); 1.2198 + EXPECT_CALL(handler, PersonalityRoutine(0xe3eaccac, false)) 1.2199 + .InSequence(s).WillOnce(Return(true)); 1.2200 + EXPECT_CALL(handler, End()) 1.2201 + .InSequence(s).WillOnce(Return(true)); 1.2202 + 1.2203 + ParseEHFrameSection(§ion); 1.2204 +} 1.2205 + 1.2206 +TEST_F(EHFrame, zR) { 1.2207 + Label cie; 1.2208 + DwarfPointerEncoding pointer_encoding = 1.2209 + DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel 1.2210 + | dwarf2reader::DW_EH_PE_sdata2); 1.2211 + section.SetPointerEncoding(pointer_encoding); 1.2212 + section 1.2213 + .Mark(&cie) 1.2214 + .CIEHeader(8011, 5496, 75, 1, "zR") 1.2215 + .ULEB128(1) // Augmentation data length 1.2216 + .D8(pointer_encoding) // encoding for FDE addresses 1.2217 + .FinishEntry() 1.2218 + .FDEHeader(cie, 0x540f9431, 0xbd0) 1.2219 + .ULEB128(0) // Augmentation data length 1.2220 + .FinishEntry() 1.2221 + .D32(0); // terminator 1.2222 + 1.2223 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zR", section); 1.2224 + 1.2225 + EXPECT_CALL(handler, Entry(_, 0x540f9431, 0xbd0, 1, "zR", 75)) 1.2226 + .InSequence(s).WillOnce(Return(true)); 1.2227 + EXPECT_CALL(handler, End()) 1.2228 + .InSequence(s).WillOnce(Return(true)); 1.2229 + 1.2230 + ParseEHFrameSection(§ion); 1.2231 +} 1.2232 + 1.2233 +TEST_F(EHFrame, zS) { 1.2234 + Label cie; 1.2235 + section 1.2236 + .Mark(&cie) 1.2237 + .CIEHeader(9217, 7694, 57, 1, "zS") 1.2238 + .ULEB128(0) // Augmentation data length 1.2239 + .FinishEntry() 1.2240 + .FDEHeader(cie, 0xd40091aa, 0x9aa6e746) 1.2241 + .ULEB128(0) // Augmentation data length 1.2242 + .FinishEntry() 1.2243 + .D32(0); // terminator 1.2244 + 1.2245 + PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zS", section); 1.2246 + 1.2247 + EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zS", 57)) 1.2248 + .InSequence(s).WillOnce(Return(true)); 1.2249 + EXPECT_CALL(handler, SignalHandler()) 1.2250 + .InSequence(s).WillOnce(Return(true)); 1.2251 + EXPECT_CALL(handler, End()) 1.2252 + .InSequence(s).WillOnce(Return(true)); 1.2253 + 1.2254 + ParseEHFrameSection(§ion); 1.2255 +} 1.2256 + 1.2257 +// These tests require manual inspection of the test output. 1.2258 +struct CFIReporterFixture { 1.2259 + CFIReporterFixture() : reporter("test file name", "test section name") { } 1.2260 + CallFrameInfo::Reporter reporter; 1.2261 +}; 1.2262 + 1.2263 +class CFIReporter: public CFIReporterFixture, public Test { }; 1.2264 + 1.2265 +TEST_F(CFIReporter, Incomplete) { 1.2266 + reporter.Incomplete(0x0102030405060708ULL, CallFrameInfo::kUnknown); 1.2267 +} 1.2268 + 1.2269 +TEST_F(CFIReporter, EarlyEHTerminator) { 1.2270 + reporter.EarlyEHTerminator(0x0102030405060708ULL); 1.2271 +} 1.2272 + 1.2273 +TEST_F(CFIReporter, CIEPointerOutOfRange) { 1.2274 + reporter.CIEPointerOutOfRange(0x0123456789abcdefULL, 0xfedcba9876543210ULL); 1.2275 +} 1.2276 + 1.2277 +TEST_F(CFIReporter, BadCIEId) { 1.2278 + reporter.BadCIEId(0x0123456789abcdefULL, 0xfedcba9876543210ULL); 1.2279 +} 1.2280 + 1.2281 +TEST_F(CFIReporter, UnrecognizedVersion) { 1.2282 + reporter.UnrecognizedVersion(0x0123456789abcdefULL, 43); 1.2283 +} 1.2284 + 1.2285 +TEST_F(CFIReporter, UnrecognizedAugmentation) { 1.2286 + reporter.UnrecognizedAugmentation(0x0123456789abcdefULL, "poodles"); 1.2287 +} 1.2288 + 1.2289 +TEST_F(CFIReporter, InvalidPointerEncoding) { 1.2290 + reporter.InvalidPointerEncoding(0x0123456789abcdefULL, 0x42); 1.2291 +} 1.2292 + 1.2293 +TEST_F(CFIReporter, UnusablePointerEncoding) { 1.2294 + reporter.UnusablePointerEncoding(0x0123456789abcdefULL, 0x42); 1.2295 +} 1.2296 + 1.2297 +TEST_F(CFIReporter, RestoreInCIE) { 1.2298 + reporter.RestoreInCIE(0x0123456789abcdefULL, 0xfedcba9876543210ULL); 1.2299 +} 1.2300 + 1.2301 +TEST_F(CFIReporter, BadInstruction) { 1.2302 + reporter.BadInstruction(0x0123456789abcdefULL, CallFrameInfo::kFDE, 1.2303 + 0xfedcba9876543210ULL); 1.2304 +} 1.2305 + 1.2306 +TEST_F(CFIReporter, NoCFARule) { 1.2307 + reporter.NoCFARule(0x0123456789abcdefULL, CallFrameInfo::kCIE, 1.2308 + 0xfedcba9876543210ULL); 1.2309 +} 1.2310 + 1.2311 +TEST_F(CFIReporter, EmptyStateStack) { 1.2312 + reporter.EmptyStateStack(0x0123456789abcdefULL, CallFrameInfo::kTerminator, 1.2313 + 0xfedcba9876543210ULL); 1.2314 +} 1.2315 + 1.2316 +TEST_F(CFIReporter, ClearingCFARule) { 1.2317 + reporter.ClearingCFARule(0x0123456789abcdefULL, CallFrameInfo::kFDE, 1.2318 + 0xfedcba9876543210ULL); 1.2319 +} 1.2320 + 1.2321 +#ifdef WRITE_ELF 1.2322 +// See comments at the top of the file mentioning WRITE_ELF for details. 1.2323 + 1.2324 +using google_breakpad::test_assembler::Section; 1.2325 + 1.2326 +struct ELFSectionHeader { 1.2327 + ELFSectionHeader(unsigned int set_type) 1.2328 + : type(set_type), flags(0), address(0), link(0), info(0), 1.2329 + alignment(1), entry_size(0) { } 1.2330 + Label name; 1.2331 + unsigned int type; 1.2332 + uint64_t flags; 1.2333 + uint64_t address; 1.2334 + Label file_offset; 1.2335 + Label file_size; 1.2336 + unsigned int link; 1.2337 + unsigned int info; 1.2338 + uint64_t alignment; 1.2339 + uint64_t entry_size; 1.2340 +}; 1.2341 + 1.2342 +void AppendSectionHeader(CFISection *table, const ELFSectionHeader &header) { 1.2343 + (*table) 1.2344 + .D32(header.name) // name, index in string tbl 1.2345 + .D32(header.type) // type 1.2346 + .Address(header.flags) // flags 1.2347 + .Address(header.address) // address in memory 1.2348 + .Address(header.file_offset) // offset in ELF file 1.2349 + .Address(header.file_size) // length in bytes 1.2350 + .D32(header.link) // link to related section 1.2351 + .D32(header.info) // miscellaneous 1.2352 + .Address(header.alignment) // alignment 1.2353 + .Address(header.entry_size); // entry size 1.2354 +} 1.2355 + 1.2356 +void WriteELFFrameSection(const char *filename, const char *cfi_name, 1.2357 + const CFISection &cfi) { 1.2358 + int elf_class = cfi.AddressSize() == 4 ? ELFCLASS32 : ELFCLASS64; 1.2359 + int elf_data = (cfi.endianness() == kBigEndian 1.2360 + ? ELFDATA2MSB : ELFDATA2LSB); 1.2361 + CFISection elf(cfi.endianness(), cfi.AddressSize()); 1.2362 + Label elf_header_size, section_table_offset; 1.2363 + elf 1.2364 + .Append("\x7f" "ELF") 1.2365 + .D8(elf_class) // 32-bit or 64-bit ELF 1.2366 + .D8(elf_data) // endianness 1.2367 + .D8(1) // ELF version 1.2368 + .D8(ELFOSABI_LINUX) // Operating System/ABI indication 1.2369 + .D8(0) // ABI version 1.2370 + .Append(7, 0xda) // padding 1.2371 + .D16(ET_EXEC) // file type: executable file 1.2372 + .D16(EM_386) // architecture: Intel IA-32 1.2373 + .D32(EV_CURRENT); // ELF version 1.2374 + elf 1.2375 + .Address(0x0123456789abcdefULL) // program entry point 1.2376 + .Address(0) // program header offset 1.2377 + .Address(section_table_offset) // section header offset 1.2378 + .D32(0) // processor-specific flags 1.2379 + .D16(elf_header_size) // ELF header size in bytes */ 1.2380 + .D16(elf_class == ELFCLASS32 ? 32 : 56) // program header entry size 1.2381 + .D16(0) // program header table entry count 1.2382 + .D16(elf_class == ELFCLASS32 ? 40 : 64) // section header entry size 1.2383 + .D16(3) // section count 1.2384 + .D16(1) // section name string table 1.2385 + .Mark(&elf_header_size); 1.2386 + 1.2387 + // The null section. Every ELF file has one, as the first entry in 1.2388 + // the section header table. 1.2389 + ELFSectionHeader null_header(SHT_NULL); 1.2390 + null_header.file_offset = 0; 1.2391 + null_header.file_size = 0; 1.2392 + 1.2393 + // The CFI section. The whole reason for writing out this ELF file 1.2394 + // is to put this in it so that we can run other dumping programs on 1.2395 + // it to check its contents. 1.2396 + ELFSectionHeader cfi_header(SHT_PROGBITS); 1.2397 + cfi_header.file_size = cfi.Size(); 1.2398 + 1.2399 + // The section holding the names of the sections. This is the 1.2400 + // section whose index appears in the e_shstrndx member of the ELF 1.2401 + // header. 1.2402 + ELFSectionHeader section_names_header(SHT_STRTAB); 1.2403 + CFISection section_names(cfi.endianness(), cfi.AddressSize()); 1.2404 + section_names 1.2405 + .Mark(&null_header.name) 1.2406 + .AppendCString("") 1.2407 + .Mark(§ion_names_header.name) 1.2408 + .AppendCString(".shstrtab") 1.2409 + .Mark(&cfi_header.name) 1.2410 + .AppendCString(cfi_name) 1.2411 + .Mark(§ion_names_header.file_size); 1.2412 + 1.2413 + // Create the section table. The ELF header's e_shoff member refers 1.2414 + // to this, and the e_shnum member gives the number of entries it 1.2415 + // contains. 1.2416 + CFISection section_table(cfi.endianness(), cfi.AddressSize()); 1.2417 + AppendSectionHeader(§ion_table, null_header); 1.2418 + AppendSectionHeader(§ion_table, section_names_header); 1.2419 + AppendSectionHeader(§ion_table, cfi_header); 1.2420 + 1.2421 + // Append the section table and the section contents to the ELF file. 1.2422 + elf 1.2423 + .Mark(§ion_table_offset) 1.2424 + .Append(section_table) 1.2425 + .Mark(§ion_names_header.file_offset) 1.2426 + .Append(section_names) 1.2427 + .Mark(&cfi_header.file_offset) 1.2428 + .Append(cfi); 1.2429 + 1.2430 + string contents; 1.2431 + if (!elf.GetContents(&contents)) { 1.2432 + fprintf(stderr, "failed to get ELF file contents\n"); 1.2433 + exit(1); 1.2434 + } 1.2435 + 1.2436 + FILE *out = fopen(filename, "w"); 1.2437 + if (!out) { 1.2438 + fprintf(stderr, "error opening ELF file '%s': %s\n", 1.2439 + filename, strerror(errno)); 1.2440 + exit(1); 1.2441 + } 1.2442 + 1.2443 + if (fwrite(contents.data(), 1, contents.size(), out) != contents.size()) { 1.2444 + fprintf(stderr, "error writing ELF data to '%s': %s\n", 1.2445 + filename, strerror(errno)); 1.2446 + exit(1); 1.2447 + } 1.2448 + 1.2449 + if (fclose(out) == EOF) { 1.2450 + fprintf(stderr, "error closing ELF file '%s': %s\n", 1.2451 + filename, strerror(errno)); 1.2452 + exit(1); 1.2453 + } 1.2454 +} 1.2455 +#endif