stabs_reader_unittest.cc
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 30 31 // stabs_reader_unittest.cc: Unit tests for google_breakpad::StabsReader. 32 33 #ifdef HAVE_CONFIG_H 34 #include <config.h> // Must come first 35 #endif 36 37 #include <assert.h> 38 #include <errno.h> 39 #include <stab.h> 40 #include <stdarg.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include <fstream> 45 #include <iomanip> 46 #include <iostream> 47 #include <map> 48 #include <sstream> 49 #include <string> 50 51 #include "breakpad_googletest_includes.h" 52 #include "common/stabs_reader.h" 53 #include "common/test_assembler.h" 54 #include "common/using_std_string.h" 55 56 using ::testing::Eq; 57 using ::testing::InSequence; 58 using ::testing::Return; 59 using ::testing::StrEq; 60 using ::testing::Test; 61 using ::testing::_; 62 using google_breakpad::StabsHandler; 63 using google_breakpad::StabsReader; 64 using google_breakpad::test_assembler::Label; 65 using google_breakpad::test_assembler::Section; 66 using google_breakpad::test_assembler::kBigEndian; 67 using google_breakpad::test_assembler::kLittleEndian; 68 using std::map; 69 70 namespace { 71 72 // A StringAssembler is a class for generating .stabstr sections to present 73 // as input to the STABS parser. 74 class StringAssembler: public Section { 75 public: 76 StringAssembler() : in_cu_(false) { StartCU(); } 77 78 // Add the string S to this StringAssembler, and return the string's 79 // offset within this compilation unit's strings. If S has been added 80 // already, this returns the offset of its first instance. 81 size_t Add(const string& s) { 82 map<string, size_t>::iterator it = added_.find(s); 83 if (it != added_.end()) 84 return it->second; 85 size_t offset = Size() - cu_start_; 86 AppendCString(s); 87 added_[s] = offset; 88 return offset; 89 } 90 91 // Start a fresh compilation unit string collection. 92 void StartCU() { 93 // Ignore duplicate calls to StartCU. Our test data don't always call 94 // StartCU at all, meaning that our constructor has to take care of it, 95 // meaning that tests that *do* call StartCU call it twice at the 96 // beginning. This is not worth smoothing out. 97 if (in_cu_) return; 98 99 added_.clear(); 100 cu_start_ = Size(); 101 102 // Each compilation unit's strings start with an empty string. 103 AppendCString(""); 104 added_[""] = 0; 105 106 in_cu_ = true; 107 } 108 109 // Finish off the current CU's strings. 110 size_t EndCU() { 111 assert(in_cu_); 112 in_cu_ = false; 113 return Size() - cu_start_; 114 } 115 116 private: 117 // The offset of the start of this compilation unit's strings. 118 size_t cu_start_; 119 120 // True if we're in a CU. 121 bool in_cu_; 122 123 // A map from the strings that have been added to this section to 124 // their starting indices within their compilation unit. 125 map<string, size_t> added_; 126 }; 127 128 // A StabsAssembler is a class for generating .stab sections to present as 129 // test input for the STABS parser. 130 class StabsAssembler: public Section { 131 public: 132 // Create a StabsAssembler that uses StringAssembler for its strings. 133 StabsAssembler(StringAssembler* string_assembler) 134 : Section(string_assembler->endianness()), 135 string_assembler_(string_assembler), 136 value_size_(0), 137 entry_count_(0), 138 cu_header_(NULL) { } 139 ~StabsAssembler() { assert(!cu_header_); } 140 141 // Accessor and setter for value_size_. 142 size_t value_size() const { return value_size_; } 143 StabsAssembler& set_value_size(size_t value_size) { 144 value_size_ = value_size; 145 return *this; 146 } 147 148 // Append a STAB entry to the end of this section with the given 149 // characteristics. NAME is the offset of this entry's name string within 150 // its compilation unit's portion of the .stabstr section; this can be a 151 // value generated by a StringAssembler. Return a reference to this 152 // StabsAssembler. 153 StabsAssembler& Stab(uint8_t type, uint8_t other, Label descriptor, 154 Label value, Label name) { 155 D32(name); 156 D8(type); 157 D8(other); 158 D16(descriptor); 159 Append(endianness(), value_size_, value); 160 entry_count_++; 161 return *this; 162 } 163 164 // As above, but automatically add NAME to our StringAssembler. 165 StabsAssembler& Stab(uint8_t type, uint8_t other, Label descriptor, 166 Label value, const string& name) { 167 return Stab(type, other, descriptor, value, string_assembler_->Add(name)); 168 } 169 170 // Start a compilation unit named NAME, with an N_UNDF symbol to start 171 // it, and its own portion of the string section. Return a reference to 172 // this StabsAssembler. 173 StabsAssembler& StartCU(const string& name) { 174 assert(!cu_header_); 175 cu_header_ = new CUHeader; 176 string_assembler_->StartCU(); 177 entry_count_ = 0; 178 return Stab(N_UNDF, 0, 179 cu_header_->final_entry_count, 180 cu_header_->final_string_size, 181 string_assembler_->Add(name)); 182 } 183 184 // Close off the current compilation unit. Return a reference to this 185 // StabsAssembler. 186 StabsAssembler& EndCU() { 187 assert(cu_header_); 188 cu_header_->final_entry_count = entry_count_; 189 cu_header_->final_string_size = string_assembler_->EndCU(); 190 delete cu_header_; 191 cu_header_ = NULL; 192 return *this; 193 } 194 195 private: 196 // Data used in a compilation unit header STAB that we won't know until 197 // we've finished the compilation unit. 198 struct CUHeader { 199 // The final number of entries this compilation unit will hold. 200 Label final_entry_count; 201 202 // The final size of this compilation unit's strings. 203 Label final_string_size; 204 }; 205 206 // The strings for our STABS entries. 207 StringAssembler* string_assembler_; 208 209 // The size of the 'value' field of stabs entries in this section. 210 size_t value_size_; 211 212 // The number of entries in this compilation unit so far. 213 size_t entry_count_; 214 215 // Header labels for this compilation unit, if we've started one but not 216 // finished it. 217 CUHeader* cu_header_; 218 }; 219 220 class MockStabsReaderHandler: public StabsHandler { 221 public: 222 MOCK_METHOD3(StartCompilationUnit, 223 bool(const char*, uint64_t, const char*)); 224 MOCK_METHOD1(EndCompilationUnit, bool(uint64_t)); 225 MOCK_METHOD2(StartFunction, bool(const string&, uint64_t)); 226 MOCK_METHOD1(EndFunction, bool(uint64_t)); 227 MOCK_METHOD3(Line, bool(uint64_t, const char*, int)); 228 MOCK_METHOD2(Extern, bool(const string&, uint64_t)); 229 void Warning(const char* format, ...) { MockWarning(format); } 230 MOCK_METHOD1(MockWarning, void(const char*)); 231 }; 232 233 struct StabsFixture { 234 StabsFixture() : stabs(&strings), unitized(true) { } 235 236 // Create a StabsReader to parse the mock stabs data in stabs and 237 // strings, and pass the parsed information to mock_handler. Use the 238 // endianness and value size of stabs to parse the data. If all goes 239 // well, return the result of calling the reader's Process member 240 // function. Otherwise, return false. 241 bool ApplyHandlerToMockStabsData() { 242 string stabs_contents, stabstr_contents; 243 if (!stabs.GetContents(&stabs_contents) || 244 !strings.GetContents(&stabstr_contents)) 245 return false; 246 247 // Run the parser on the test input, passing whatever we find to HANDLER. 248 StabsReader reader( 249 reinterpret_cast<const uint8_t*>(stabs_contents.data()), 250 stabs_contents.size(), 251 reinterpret_cast<const uint8_t*>(stabstr_contents.data()), 252 stabstr_contents.size(), 253 stabs.endianness() == kBigEndian, stabs.value_size(), unitized, 254 &mock_handler); 255 return reader.Process(); 256 } 257 258 StringAssembler strings; 259 StabsAssembler stabs; 260 bool unitized; 261 MockStabsReaderHandler mock_handler; 262 }; 263 264 class Stabs: public StabsFixture, public Test { }; 265 266 TEST_F(Stabs, MockStabsInput) { 267 stabs.set_endianness(kLittleEndian); 268 stabs.set_value_size(4); 269 stabs 270 .Stab(N_SO, 149, 40232, 0x18a2a72bU, "builddir/") 271 .Stab(N_FUN, 83, 50010, 0x91a5353fU, 272 "not the SO with source file name we expected ") 273 .Stab(N_SO, 165, 24791, 0xfe69d23cU, "") 274 .Stab(N_SO, 184, 34178, 0xca4d883aU, "builddir1/") 275 .Stab(N_SO, 83, 40859, 0xd2fe5df3U, "file1.c") 276 .Stab(N_LSYM, 147, 39565, 0x60d4bb8aU, "not the FUN we're looking for") 277 .Stab(N_FUN, 120, 50271, 0xa049f4b1U, "fun1") 278 .Stab(N_BINCL, 150, 15694, 0xef65c659U, 279 "something to ignore in a FUN body") 280 .Stab(N_SLINE, 147, 4967, 0xd904b3f, "") 281 .Stab(N_SOL, 177, 56135, 0xbd97b1dcU, "header.h") 282 .Stab(N_SLINE, 130, 24610, 0x90f145b, "") 283 .Stab(N_FUN, 45, 32441, 0xbf27cf93U, 284 "fun2:some stabs type info here:to trim from the name") 285 .Stab(N_SLINE, 138, 39002, 0x8148b87, "") 286 .Stab(N_SOL, 60, 49318, 0x1d06e025U, "file1.c") 287 .Stab(N_SLINE, 29, 52163, 0x6eebbb7, "") 288 .Stab(N_SO, 167, 4647, 0xd04b7448U, "") 289 .Stab(N_LSYM, 58, 37837, 0xe6b14d37U, "") 290 .Stab(N_SO, 152, 7810, 0x11759f10U, "file3.c") 291 .Stab(N_SO, 218, 12447, 0x11cfe4b5U, ""); 292 293 { 294 InSequence s; 295 296 EXPECT_CALL(mock_handler, 297 StartCompilationUnit(StrEq("file1.c"), 0xd2fe5df3U, 298 StrEq("builddir1/"))) 299 .WillOnce(Return(true)); 300 EXPECT_CALL(mock_handler, StartFunction(StrEq("fun1"), 0xa049f4b1U)) 301 .WillOnce(Return(true)); 302 EXPECT_CALL(mock_handler, 303 Line(0xa049f4b1U + 0xd904b3f, StrEq("file1.c"), 4967)) 304 .WillOnce(Return(true)); 305 EXPECT_CALL(mock_handler, 306 Line(0xa049f4b1U + 0x90f145b, StrEq("header.h"), 24610)) 307 .WillOnce(Return(true)); 308 EXPECT_CALL(mock_handler, EndFunction(0xbf27cf93U)) 309 .WillOnce(Return(true)); 310 EXPECT_CALL(mock_handler, StartFunction(StrEq("fun2"), 0xbf27cf93U)) 311 .WillOnce(Return(true)); 312 EXPECT_CALL(mock_handler, 313 Line(0xbf27cf93U + 0x8148b87, StrEq("header.h"), 39002)) 314 .WillOnce(Return(true)); 315 EXPECT_CALL(mock_handler, 316 Line(0xbf27cf93U + 0x6eebbb7, StrEq("file1.c"), 52163)) 317 .WillOnce(Return(true)); 318 EXPECT_CALL(mock_handler, EndFunction(0xd04b7448U)) 319 .WillOnce(Return(true)); 320 EXPECT_CALL(mock_handler, EndCompilationUnit(0xd04b7448U)) 321 .WillOnce(Return(true)); 322 EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"), 323 0x11759f10U, NULL)) 324 .WillOnce(Return(true)); 325 EXPECT_CALL(mock_handler, EndCompilationUnit(0x11cfe4b5U)) 326 .WillOnce(Return(true)); 327 } 328 329 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 330 } 331 332 TEST_F(Stabs, AbruptCU) { 333 stabs.set_endianness(kBigEndian); 334 stabs.set_value_size(4); 335 stabs.Stab(N_SO, 177, 23446, 0xbf10d5e4, "file2-1.c"); 336 337 { 338 InSequence s; 339 340 EXPECT_CALL(mock_handler, 341 StartCompilationUnit(StrEq("file2-1.c"), 0xbf10d5e4, NULL)) 342 .WillOnce(Return(true)); 343 EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 344 .WillOnce(Return(true)); 345 } 346 347 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 348 } 349 350 TEST_F(Stabs, AbruptFunction) { 351 stabs.set_endianness(kLittleEndian); 352 stabs.set_value_size(8); 353 stabs 354 .Stab(N_SO, 218, 26631, 0xb83ddf10U, "file3-1.c") 355 .Stab(N_FUN, 113, 24765, 0xbbd4a145U, "fun3_1"); 356 357 { 358 InSequence s; 359 360 EXPECT_CALL(mock_handler, 361 StartCompilationUnit(StrEq("file3-1.c"), 0xb83ddf10U, NULL)) 362 .WillOnce(Return(true)); 363 EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0xbbd4a145U)) 364 .WillOnce(Return(true)); 365 EXPECT_CALL(mock_handler, EndFunction(0)) 366 .WillOnce(Return(true)); 367 EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 368 .WillOnce(Return(true)); 369 } 370 371 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 372 } 373 374 TEST_F(Stabs, NoCU) { 375 stabs.set_endianness(kBigEndian); 376 stabs.set_value_size(8); 377 stabs.Stab(N_SO, 161, 25673, 0x8f676e7bU, "build-directory/"); 378 379 EXPECT_CALL(mock_handler, StartCompilationUnit(_, _, _)) 380 .Times(0); 381 EXPECT_CALL(mock_handler, StartFunction(_, _)) 382 .Times(0); 383 384 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 385 } 386 387 TEST_F(Stabs, NoCUEnd) { 388 stabs.set_endianness(kBigEndian); 389 stabs.set_value_size(8); 390 stabs 391 .Stab(N_SO, 116, 58280, 0x2f7493c9U, "file5-1.c") 392 .Stab(N_SO, 224, 23057, 0xf9f1d50fU, "file5-2.c"); 393 394 { 395 InSequence s; 396 397 EXPECT_CALL(mock_handler, 398 StartCompilationUnit(StrEq("file5-1.c"), 0x2f7493c9U, NULL)) 399 .WillOnce(Return(true)); 400 EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 401 .WillOnce(Return(true)); 402 EXPECT_CALL(mock_handler, 403 StartCompilationUnit(StrEq("file5-2.c"), 0xf9f1d50fU, NULL)) 404 .WillOnce(Return(true)); 405 EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 406 .WillOnce(Return(true)); 407 } 408 409 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 410 } 411 412 // On systems that store STABS in sections, string offsets are relative to 413 // the beginning of that compilation unit's strings, marked with N_UNDF 414 // symbols; see the comments for StabsReader::StabsReader. 415 TEST_F(Stabs, Unitized) { 416 stabs.set_endianness(kBigEndian); 417 stabs.set_value_size(4); 418 stabs 419 .StartCU("antimony") 420 .Stab(N_SO, 49, 26043, 0x7e259f1aU, "antimony") 421 .Stab(N_FUN, 101, 63253, 0x7fbcccaeU, "arsenic") 422 .Stab(N_SO, 124, 37175, 0x80b0014cU, "") 423 .EndCU() 424 .StartCU("aluminum") 425 .Stab(N_SO, 72, 23084, 0x86756839U, "aluminum") 426 .Stab(N_FUN, 59, 3305, 0xa8e120b0U, "selenium") 427 .Stab(N_SO, 178, 56949, 0xbffff983U, "") 428 .EndCU(); 429 430 { 431 InSequence s; 432 EXPECT_CALL(mock_handler, 433 StartCompilationUnit(StrEq("antimony"), 0x7e259f1aU, NULL)) 434 .WillOnce(Return(true)); 435 EXPECT_CALL(mock_handler, StartFunction(Eq("arsenic"), 0x7fbcccaeU)) 436 .WillOnce(Return(true)); 437 EXPECT_CALL(mock_handler, EndFunction(0x80b0014cU)) 438 .WillOnce(Return(true)); 439 EXPECT_CALL(mock_handler, EndCompilationUnit(0x80b0014cU)) 440 .WillOnce(Return(true)); 441 EXPECT_CALL(mock_handler, 442 StartCompilationUnit(StrEq("aluminum"), 0x86756839U, NULL)) 443 .WillOnce(Return(true)); 444 EXPECT_CALL(mock_handler, StartFunction(Eq("selenium"), 0xa8e120b0U)) 445 .WillOnce(Return(true)); 446 EXPECT_CALL(mock_handler, EndFunction(0xbffff983U)) 447 .WillOnce(Return(true)); 448 EXPECT_CALL(mock_handler, EndCompilationUnit(0xbffff983U)) 449 .WillOnce(Return(true)); 450 } 451 452 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 453 } 454 455 // On systems that store STABS entries in the real symbol table, the N_UNDF 456 // entries have no special meaning, and shouldn't mess up the string 457 // indices. 458 TEST_F(Stabs, NonUnitized) { 459 stabs.set_endianness(kLittleEndian); 460 stabs.set_value_size(4); 461 unitized = false; 462 stabs 463 .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "") 464 .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "") 465 .Stab(N_SO, 71, 45139, 0x11a97352, "Tanzania") 466 .Stab(N_SO, 221, 41976, 0x21a97352, ""); 467 468 { 469 InSequence s; 470 EXPECT_CALL(mock_handler, 471 StartCompilationUnit(StrEq("Tanzania"), 472 0x11a97352, NULL)) 473 .WillOnce(Return(true)); 474 EXPECT_CALL(mock_handler, EndCompilationUnit(0x21a97352)) 475 .WillOnce(Return(true)); 476 } 477 478 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 479 } 480 481 TEST_F(Stabs, FunctionEnd) { 482 stabs.set_endianness(kLittleEndian); 483 stabs.set_value_size(8); 484 stabs 485 .Stab(N_SO, 102, 62362, 0x52a830d644cd6942ULL, "compilation unit") 486 // This function is terminated by the start of the next function. 487 .Stab(N_FUN, 216, 38405, 0xbb5ab70ecdd23bfeULL, "function 1") 488 // This function is terminated by an explicit end-of-function stab, 489 // whose value is a size in bytes. 490 .Stab(N_FUN, 240, 10973, 0xc954de9b8fb3e5e2ULL, "function 2") 491 .Stab(N_FUN, 14, 36749, 0xc1ab, "") 492 // This function is terminated by the end of the compilation unit. 493 .Stab(N_FUN, 143, 64514, 0xdff98c9a35386e1fULL, "function 3") 494 .Stab(N_SO, 164, 60142, 0xfdacb856e78bbf57ULL, ""); 495 496 { 497 InSequence s; 498 EXPECT_CALL(mock_handler, 499 StartCompilationUnit(StrEq("compilation unit"), 500 0x52a830d644cd6942ULL, NULL)) 501 .WillOnce(Return(true)); 502 EXPECT_CALL(mock_handler, 503 StartFunction(Eq("function 1"), 0xbb5ab70ecdd23bfeULL)) 504 .WillOnce(Return(true)); 505 EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL)) 506 .WillOnce(Return(true)); 507 EXPECT_CALL(mock_handler, 508 StartFunction(Eq("function 2"), 0xc954de9b8fb3e5e2ULL)) 509 .WillOnce(Return(true)); 510 EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL + 0xc1ab)) 511 .WillOnce(Return(true)); 512 EXPECT_CALL(mock_handler, 513 StartFunction(Eq("function 3"), 0xdff98c9a35386e1fULL)) 514 .WillOnce(Return(true)); 515 EXPECT_CALL(mock_handler, EndFunction(0xfdacb856e78bbf57ULL)) 516 .WillOnce(Return(true)); 517 EXPECT_CALL(mock_handler, EndCompilationUnit(0xfdacb856e78bbf57ULL)) 518 .WillOnce(Return(true)); 519 } 520 521 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 522 } 523 524 // On Mac OS X, SLINE records can appear before the FUN stab to which they 525 // belong, and their values are absolute addresses, not offsets. 526 TEST_F(Stabs, LeadingLine) { 527 stabs.set_endianness(kBigEndian); 528 stabs.set_value_size(4); 529 stabs 530 .Stab(N_SO, 179, 27357, 0x8adabc15, "build directory/") 531 .Stab(N_SO, 52, 53058, 0x4c7e3bf4, "compilation unit") 532 .Stab(N_SOL, 165, 12086, 0x6a797ca3, "source file name") 533 .Stab(N_SLINE, 229, 20015, 0x4cb3d7e0, "") 534 .Stab(N_SLINE, 89, 43802, 0x4cba8b88, "") 535 .Stab(N_FUN, 251, 51639, 0xce1b98fa, "rutabaga") 536 .Stab(N_FUN, 218, 16113, 0x5798, "") 537 .Stab(N_SO, 52, 53058, 0xd4af4415, ""); 538 539 { 540 InSequence s; 541 EXPECT_CALL(mock_handler, 542 StartCompilationUnit(StrEq("compilation unit"), 543 0x4c7e3bf4, StrEq("build directory/"))) 544 .WillOnce(Return(true)); 545 EXPECT_CALL(mock_handler, 546 StartFunction(Eq("rutabaga"), 0xce1b98fa)) 547 .WillOnce(Return(true)); 548 EXPECT_CALL(mock_handler, 549 Line(0x4cb3d7e0, StrEq("source file name"), 20015)) 550 .WillOnce(Return(true)); 551 EXPECT_CALL(mock_handler, 552 Line(0x4cba8b88, StrEq("source file name"), 43802)) 553 .WillOnce(Return(true)); 554 EXPECT_CALL(mock_handler, EndFunction(0xce1b98fa + 0x5798)) 555 .WillOnce(Return(true)); 556 EXPECT_CALL(mock_handler, EndCompilationUnit(0xd4af4415)) 557 .WillOnce(Return(true)); 558 } 559 560 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 561 } 562 563 564 #if defined(HAVE_MACH_O_NLIST_H) 565 // These tests have no meaning on non-Mach-O-based systems, as 566 // only Mach-O uses N_SECT to represent public symbols. 567 TEST_F(Stabs, OnePublicSymbol) { 568 stabs.set_endianness(kLittleEndian); 569 stabs.set_value_size(4); 570 571 const uint32_t kExpectedAddress = 0x9000; 572 const string kExpectedFunctionName("public_function"); 573 stabs 574 .Stab(N_SECT, 1, 0, kExpectedAddress, kExpectedFunctionName); 575 576 { 577 InSequence s; 578 EXPECT_CALL(mock_handler, 579 Extern(StrEq(kExpectedFunctionName), 580 kExpectedAddress)) 581 .WillOnce(Return(true)); 582 } 583 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 584 } 585 586 TEST_F(Stabs, TwoPublicSymbols) { 587 stabs.set_endianness(kLittleEndian); 588 stabs.set_value_size(4); 589 590 const uint32_t kExpectedAddress1 = 0xB0B0B0B0; 591 const string kExpectedFunctionName1("public_function"); 592 const uint32_t kExpectedAddress2 = 0xF0F0F0F0; 593 const string kExpectedFunctionName2("something else"); 594 stabs 595 .Stab(N_SECT, 1, 0, kExpectedAddress1, kExpectedFunctionName1) 596 .Stab(N_SECT, 1, 0, kExpectedAddress2, kExpectedFunctionName2); 597 598 { 599 InSequence s; 600 EXPECT_CALL(mock_handler, 601 Extern(StrEq(kExpectedFunctionName1), 602 kExpectedAddress1)) 603 .WillOnce(Return(true)); 604 EXPECT_CALL(mock_handler, 605 Extern(StrEq(kExpectedFunctionName2), 606 kExpectedAddress2)) 607 .WillOnce(Return(true)); 608 } 609 ASSERT_TRUE(ApplyHandlerToMockStabsData()); 610 } 611 612 #endif 613 614 } // anonymous namespace