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