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