1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,611 @@ 1.4 +// Copyright (c) 2010 Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.34 + 1.35 +// stabs_reader_unittest.cc: Unit tests for google_breakpad::StabsReader. 1.36 + 1.37 +#include <assert.h> 1.38 +#include <errno.h> 1.39 +#include <stab.h> 1.40 +#include <stdarg.h> 1.41 +#include <stdlib.h> 1.42 +#include <string.h> 1.43 + 1.44 +#include <fstream> 1.45 +#include <iomanip> 1.46 +#include <iostream> 1.47 +#include <map> 1.48 +#include <sstream> 1.49 +#include <string> 1.50 + 1.51 +#include "breakpad_googletest_includes.h" 1.52 +#include "common/stabs_reader.h" 1.53 +#include "common/test_assembler.h" 1.54 +#include "common/using_std_string.h" 1.55 + 1.56 +using ::testing::Eq; 1.57 +using ::testing::InSequence; 1.58 +using ::testing::Return; 1.59 +using ::testing::StrEq; 1.60 +using ::testing::Test; 1.61 +using ::testing::_; 1.62 +using google_breakpad::StabsHandler; 1.63 +using google_breakpad::StabsReader; 1.64 +using google_breakpad::test_assembler::Label; 1.65 +using google_breakpad::test_assembler::Section; 1.66 +using google_breakpad::test_assembler::kBigEndian; 1.67 +using google_breakpad::test_assembler::kLittleEndian; 1.68 +using std::map; 1.69 + 1.70 +namespace { 1.71 + 1.72 +// A StringAssembler is a class for generating .stabstr sections to present 1.73 +// as input to the STABS parser. 1.74 +class StringAssembler: public Section { 1.75 + public: 1.76 + StringAssembler() : in_cu_(false) { StartCU(); } 1.77 + 1.78 + // Add the string S to this StringAssembler, and return the string's 1.79 + // offset within this compilation unit's strings. If S has been added 1.80 + // already, this returns the offset of its first instance. 1.81 + size_t Add(const string &s) { 1.82 + map<string, size_t>::iterator it = added_.find(s); 1.83 + if (it != added_.end()) 1.84 + return it->second; 1.85 + size_t offset = Size() - cu_start_; 1.86 + AppendCString(s); 1.87 + added_[s] = offset; 1.88 + return offset; 1.89 + } 1.90 + 1.91 + // Start a fresh compilation unit string collection. 1.92 + void StartCU() { 1.93 + // Ignore duplicate calls to StartCU. Our test data don't always call 1.94 + // StartCU at all, meaning that our constructor has to take care of it, 1.95 + // meaning that tests that *do* call StartCU call it twice at the 1.96 + // beginning. This is not worth smoothing out. 1.97 + if (in_cu_) return; 1.98 + 1.99 + added_.clear(); 1.100 + cu_start_ = Size(); 1.101 + 1.102 + // Each compilation unit's strings start with an empty string. 1.103 + AppendCString(""); 1.104 + added_[""] = 0; 1.105 + 1.106 + in_cu_ = true; 1.107 + } 1.108 + 1.109 + // Finish off the current CU's strings. 1.110 + size_t EndCU() { 1.111 + assert(in_cu_); 1.112 + in_cu_ = false; 1.113 + return Size() - cu_start_; 1.114 + } 1.115 + 1.116 + private: 1.117 + // The offset of the start of this compilation unit's strings. 1.118 + size_t cu_start_; 1.119 + 1.120 + // True if we're in a CU. 1.121 + bool in_cu_; 1.122 + 1.123 + // A map from the strings that have been added to this section to 1.124 + // their starting indices within their compilation unit. 1.125 + map<string, size_t> added_; 1.126 +}; 1.127 + 1.128 +// A StabsAssembler is a class for generating .stab sections to present as 1.129 +// test input for the STABS parser. 1.130 +class StabsAssembler: public Section { 1.131 + public: 1.132 + // Create a StabsAssembler that uses StringAssembler for its strings. 1.133 + StabsAssembler(StringAssembler *string_assembler) 1.134 + : Section(string_assembler->endianness()), 1.135 + string_assembler_(string_assembler), 1.136 + value_size_(0), 1.137 + entry_count_(0), 1.138 + cu_header_(NULL) { } 1.139 + ~StabsAssembler() { assert(!cu_header_); } 1.140 + 1.141 + // Accessor and setter for value_size_. 1.142 + size_t value_size() const { return value_size_; } 1.143 + StabsAssembler &set_value_size(size_t value_size) { 1.144 + value_size_ = value_size; 1.145 + return *this; 1.146 + } 1.147 + 1.148 + // Append a STAB entry to the end of this section with the given 1.149 + // characteristics. NAME is the offset of this entry's name string within 1.150 + // its compilation unit's portion of the .stabstr section; this can be a 1.151 + // value generated by a StringAssembler. Return a reference to this 1.152 + // StabsAssembler. 1.153 + StabsAssembler &Stab(uint8_t type, uint8_t other, Label descriptor, 1.154 + Label value, Label name) { 1.155 + D32(name); 1.156 + D8(type); 1.157 + D8(other); 1.158 + D16(descriptor); 1.159 + Append(endianness(), value_size_, value); 1.160 + entry_count_++; 1.161 + return *this; 1.162 + } 1.163 + 1.164 + // As above, but automatically add NAME to our StringAssembler. 1.165 + StabsAssembler &Stab(uint8_t type, uint8_t other, Label descriptor, 1.166 + Label value, const string &name) { 1.167 + return Stab(type, other, descriptor, value, string_assembler_->Add(name)); 1.168 + } 1.169 + 1.170 + // Start a compilation unit named NAME, with an N_UNDF symbol to start 1.171 + // it, and its own portion of the string section. Return a reference to 1.172 + // this StabsAssembler. 1.173 + StabsAssembler &StartCU(const string &name) { 1.174 + assert(!cu_header_); 1.175 + cu_header_ = new CUHeader; 1.176 + string_assembler_->StartCU(); 1.177 + entry_count_ = 0; 1.178 + return Stab(N_UNDF, 0, 1.179 + cu_header_->final_entry_count, 1.180 + cu_header_->final_string_size, 1.181 + string_assembler_->Add(name)); 1.182 + } 1.183 + 1.184 + // Close off the current compilation unit. Return a reference to this 1.185 + // StabsAssembler. 1.186 + StabsAssembler &EndCU() { 1.187 + assert(cu_header_); 1.188 + cu_header_->final_entry_count = entry_count_; 1.189 + cu_header_->final_string_size = string_assembler_->EndCU(); 1.190 + delete cu_header_; 1.191 + cu_header_ = NULL; 1.192 + return *this; 1.193 + } 1.194 + 1.195 + private: 1.196 + // Data used in a compilation unit header STAB that we won't know until 1.197 + // we've finished the compilation unit. 1.198 + struct CUHeader { 1.199 + // The final number of entries this compilation unit will hold. 1.200 + Label final_entry_count; 1.201 + 1.202 + // The final size of this compilation unit's strings. 1.203 + Label final_string_size; 1.204 + }; 1.205 + 1.206 + // The strings for our STABS entries. 1.207 + StringAssembler *string_assembler_; 1.208 + 1.209 + // The size of the 'value' field of stabs entries in this section. 1.210 + size_t value_size_; 1.211 + 1.212 + // The number of entries in this compilation unit so far. 1.213 + size_t entry_count_; 1.214 + 1.215 + // Header labels for this compilation unit, if we've started one but not 1.216 + // finished it. 1.217 + CUHeader *cu_header_; 1.218 +}; 1.219 + 1.220 +class MockStabsReaderHandler: public StabsHandler { 1.221 + public: 1.222 + MOCK_METHOD3(StartCompilationUnit, 1.223 + bool(const char *, uint64_t, const char *)); 1.224 + MOCK_METHOD1(EndCompilationUnit, bool(uint64_t)); 1.225 + MOCK_METHOD2(StartFunction, bool(const string &, uint64_t)); 1.226 + MOCK_METHOD1(EndFunction, bool(uint64_t)); 1.227 + MOCK_METHOD3(Line, bool(uint64_t, const char *, int)); 1.228 + MOCK_METHOD2(Extern, bool(const string &, uint64_t)); 1.229 + void Warning(const char *format, ...) { MockWarning(format); } 1.230 + MOCK_METHOD1(MockWarning, void(const char *)); 1.231 +}; 1.232 + 1.233 +struct StabsFixture { 1.234 + StabsFixture() : stabs(&strings), unitized(true) { } 1.235 + 1.236 + // Create a StabsReader to parse the mock stabs data in stabs and 1.237 + // strings, and pass the parsed information to mock_handler. Use the 1.238 + // endianness and value size of stabs to parse the data. If all goes 1.239 + // well, return the result of calling the reader's Process member 1.240 + // function. Otherwise, return false. 1.241 + bool ApplyHandlerToMockStabsData() { 1.242 + string stabs_contents, stabstr_contents; 1.243 + if (!stabs.GetContents(&stabs_contents) || 1.244 + !strings.GetContents(&stabstr_contents)) 1.245 + return false; 1.246 + 1.247 + // Run the parser on the test input, passing whatever we find to HANDLER. 1.248 + StabsReader reader( 1.249 + reinterpret_cast<const uint8_t *>(stabs_contents.data()), 1.250 + stabs_contents.size(), 1.251 + reinterpret_cast<const uint8_t *>(stabstr_contents.data()), 1.252 + stabstr_contents.size(), 1.253 + stabs.endianness() == kBigEndian, stabs.value_size(), unitized, 1.254 + &mock_handler); 1.255 + return reader.Process(); 1.256 + } 1.257 + 1.258 + StringAssembler strings; 1.259 + StabsAssembler stabs; 1.260 + bool unitized; 1.261 + MockStabsReaderHandler mock_handler; 1.262 +}; 1.263 + 1.264 +class Stabs: public StabsFixture, public Test { }; 1.265 + 1.266 +TEST_F(Stabs, MockStabsInput) { 1.267 + stabs.set_endianness(kLittleEndian); 1.268 + stabs.set_value_size(4); 1.269 + stabs 1.270 + .Stab(N_SO, 149, 40232, 0x18a2a72bU, "builddir/") 1.271 + .Stab(N_FUN, 83, 50010, 0x91a5353fU, 1.272 + "not the SO with source file name we expected ") 1.273 + .Stab(N_SO, 165, 24791, 0xfe69d23cU, "") 1.274 + .Stab(N_SO, 184, 34178, 0xca4d883aU, "builddir1/") 1.275 + .Stab(N_SO, 83, 40859, 0xd2fe5df3U, "file1.c") 1.276 + .Stab(N_LSYM, 147, 39565, 0x60d4bb8aU, "not the FUN we're looking for") 1.277 + .Stab(N_FUN, 120, 50271, 0xa049f4b1U, "fun1") 1.278 + .Stab(N_BINCL, 150, 15694, 0xef65c659U, 1.279 + "something to ignore in a FUN body") 1.280 + .Stab(N_SLINE, 147, 4967, 0xd904b3f, "") 1.281 + .Stab(N_SOL, 177, 56135, 0xbd97b1dcU, "header.h") 1.282 + .Stab(N_SLINE, 130, 24610, 0x90f145b, "") 1.283 + .Stab(N_FUN, 45, 32441, 0xbf27cf93U, 1.284 + "fun2:some stabs type info here:to trim from the name") 1.285 + .Stab(N_SLINE, 138, 39002, 0x8148b87, "") 1.286 + .Stab(N_SOL, 60, 49318, 0x1d06e025U, "file1.c") 1.287 + .Stab(N_SLINE, 29, 52163, 0x6eebbb7, "") 1.288 + .Stab(N_SO, 167, 4647, 0xd04b7448U, "") 1.289 + .Stab(N_LSYM, 58, 37837, 0xe6b14d37U, "") 1.290 + .Stab(N_SO, 152, 7810, 0x11759f10U, "file3.c") 1.291 + .Stab(N_SO, 218, 12447, 0x11cfe4b5U, ""); 1.292 + 1.293 + { 1.294 + InSequence s; 1.295 + 1.296 + EXPECT_CALL(mock_handler, 1.297 + StartCompilationUnit(StrEq("file1.c"), 0xd2fe5df3U, 1.298 + StrEq("builddir1/"))) 1.299 + .WillOnce(Return(true)); 1.300 + EXPECT_CALL(mock_handler, StartFunction(StrEq("fun1"), 0xa049f4b1U)) 1.301 + .WillOnce(Return(true)); 1.302 + EXPECT_CALL(mock_handler, 1.303 + Line(0xa049f4b1U + 0xd904b3f, StrEq("file1.c"), 4967)) 1.304 + .WillOnce(Return(true)); 1.305 + EXPECT_CALL(mock_handler, 1.306 + Line(0xa049f4b1U + 0x90f145b, StrEq("header.h"), 24610)) 1.307 + .WillOnce(Return(true)); 1.308 + EXPECT_CALL(mock_handler, EndFunction(0xbf27cf93U)) 1.309 + .WillOnce(Return(true)); 1.310 + EXPECT_CALL(mock_handler, StartFunction(StrEq("fun2"), 0xbf27cf93U)) 1.311 + .WillOnce(Return(true)); 1.312 + EXPECT_CALL(mock_handler, 1.313 + Line(0xbf27cf93U + 0x8148b87, StrEq("header.h"), 39002)) 1.314 + .WillOnce(Return(true)); 1.315 + EXPECT_CALL(mock_handler, 1.316 + Line(0xbf27cf93U + 0x6eebbb7, StrEq("file1.c"), 52163)) 1.317 + .WillOnce(Return(true)); 1.318 + EXPECT_CALL(mock_handler, EndFunction(0xd04b7448U)) 1.319 + .WillOnce(Return(true)); 1.320 + EXPECT_CALL(mock_handler, EndCompilationUnit(0xd04b7448U)) 1.321 + .WillOnce(Return(true)); 1.322 + EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"), 1.323 + 0x11759f10U, NULL)) 1.324 + .WillOnce(Return(true)); 1.325 + EXPECT_CALL(mock_handler, EndCompilationUnit(0x11cfe4b5U)) 1.326 + .WillOnce(Return(true)); 1.327 + } 1.328 + 1.329 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.330 +} 1.331 + 1.332 +TEST_F(Stabs, AbruptCU) { 1.333 + stabs.set_endianness(kBigEndian); 1.334 + stabs.set_value_size(4); 1.335 + stabs.Stab(N_SO, 177, 23446, 0xbf10d5e4, "file2-1.c"); 1.336 + 1.337 + { 1.338 + InSequence s; 1.339 + 1.340 + EXPECT_CALL(mock_handler, 1.341 + StartCompilationUnit(StrEq("file2-1.c"), 0xbf10d5e4, NULL)) 1.342 + .WillOnce(Return(true)); 1.343 + EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 1.344 + .WillOnce(Return(true)); 1.345 + } 1.346 + 1.347 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.348 +} 1.349 + 1.350 +TEST_F(Stabs, AbruptFunction) { 1.351 + stabs.set_endianness(kLittleEndian); 1.352 + stabs.set_value_size(8); 1.353 + stabs 1.354 + .Stab(N_SO, 218, 26631, 0xb83ddf10U, "file3-1.c") 1.355 + .Stab(N_FUN, 113, 24765, 0xbbd4a145U, "fun3_1"); 1.356 + 1.357 + { 1.358 + InSequence s; 1.359 + 1.360 + EXPECT_CALL(mock_handler, 1.361 + StartCompilationUnit(StrEq("file3-1.c"), 0xb83ddf10U, NULL)) 1.362 + .WillOnce(Return(true)); 1.363 + EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0xbbd4a145U)) 1.364 + .WillOnce(Return(true)); 1.365 + EXPECT_CALL(mock_handler, EndFunction(0)) 1.366 + .WillOnce(Return(true)); 1.367 + EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 1.368 + .WillOnce(Return(true)); 1.369 + } 1.370 + 1.371 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.372 +} 1.373 + 1.374 +TEST_F(Stabs, NoCU) { 1.375 + stabs.set_endianness(kBigEndian); 1.376 + stabs.set_value_size(8); 1.377 + stabs.Stab(N_SO, 161, 25673, 0x8f676e7bU, "build-directory/"); 1.378 + 1.379 + EXPECT_CALL(mock_handler, StartCompilationUnit(_, _, _)) 1.380 + .Times(0); 1.381 + EXPECT_CALL(mock_handler, StartFunction(_, _)) 1.382 + .Times(0); 1.383 + 1.384 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.385 +} 1.386 + 1.387 +TEST_F(Stabs, NoCUEnd) { 1.388 + stabs.set_endianness(kBigEndian); 1.389 + stabs.set_value_size(8); 1.390 + stabs 1.391 + .Stab(N_SO, 116, 58280, 0x2f7493c9U, "file5-1.c") 1.392 + .Stab(N_SO, 224, 23057, 0xf9f1d50fU, "file5-2.c"); 1.393 + 1.394 + { 1.395 + InSequence s; 1.396 + 1.397 + EXPECT_CALL(mock_handler, 1.398 + StartCompilationUnit(StrEq("file5-1.c"), 0x2f7493c9U, NULL)) 1.399 + .WillOnce(Return(true)); 1.400 + EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 1.401 + .WillOnce(Return(true)); 1.402 + EXPECT_CALL(mock_handler, 1.403 + StartCompilationUnit(StrEq("file5-2.c"), 0xf9f1d50fU, NULL)) 1.404 + .WillOnce(Return(true)); 1.405 + EXPECT_CALL(mock_handler, EndCompilationUnit(0)) 1.406 + .WillOnce(Return(true)); 1.407 + } 1.408 + 1.409 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.410 +} 1.411 + 1.412 +// On systems that store STABS in sections, string offsets are relative to 1.413 +// the beginning of that compilation unit's strings, marked with N_UNDF 1.414 +// symbols; see the comments for StabsReader::StabsReader. 1.415 +TEST_F(Stabs, Unitized) { 1.416 + stabs.set_endianness(kBigEndian); 1.417 + stabs.set_value_size(4); 1.418 + stabs 1.419 + .StartCU("antimony") 1.420 + .Stab(N_SO, 49, 26043, 0x7e259f1aU, "antimony") 1.421 + .Stab(N_FUN, 101, 63253, 0x7fbcccaeU, "arsenic") 1.422 + .Stab(N_SO, 124, 37175, 0x80b0014cU, "") 1.423 + .EndCU() 1.424 + .StartCU("aluminum") 1.425 + .Stab(N_SO, 72, 23084, 0x86756839U, "aluminum") 1.426 + .Stab(N_FUN, 59, 3305, 0xa8e120b0U, "selenium") 1.427 + .Stab(N_SO, 178, 56949, 0xbffff983U, "") 1.428 + .EndCU(); 1.429 + 1.430 + { 1.431 + InSequence s; 1.432 + EXPECT_CALL(mock_handler, 1.433 + StartCompilationUnit(StrEq("antimony"), 0x7e259f1aU, NULL)) 1.434 + .WillOnce(Return(true)); 1.435 + EXPECT_CALL(mock_handler, StartFunction(Eq("arsenic"), 0x7fbcccaeU)) 1.436 + .WillOnce(Return(true)); 1.437 + EXPECT_CALL(mock_handler, EndFunction(0x80b0014cU)) 1.438 + .WillOnce(Return(true)); 1.439 + EXPECT_CALL(mock_handler, EndCompilationUnit(0x80b0014cU)) 1.440 + .WillOnce(Return(true)); 1.441 + EXPECT_CALL(mock_handler, 1.442 + StartCompilationUnit(StrEq("aluminum"), 0x86756839U, NULL)) 1.443 + .WillOnce(Return(true)); 1.444 + EXPECT_CALL(mock_handler, StartFunction(Eq("selenium"), 0xa8e120b0U)) 1.445 + .WillOnce(Return(true)); 1.446 + EXPECT_CALL(mock_handler, EndFunction(0xbffff983U)) 1.447 + .WillOnce(Return(true)); 1.448 + EXPECT_CALL(mock_handler, EndCompilationUnit(0xbffff983U)) 1.449 + .WillOnce(Return(true)); 1.450 + } 1.451 + 1.452 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.453 +} 1.454 + 1.455 +// On systems that store STABS entries in the real symbol table, the N_UNDF 1.456 +// entries have no special meaning, and shouldn't mess up the string 1.457 +// indices. 1.458 +TEST_F(Stabs, NonUnitized) { 1.459 + stabs.set_endianness(kLittleEndian); 1.460 + stabs.set_value_size(4); 1.461 + unitized = false; 1.462 + stabs 1.463 + .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "") 1.464 + .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "") 1.465 + .Stab(N_SO, 71, 45139, 0x11a97352, "Tanzania") 1.466 + .Stab(N_SO, 221, 41976, 0x21a97352, ""); 1.467 + 1.468 + { 1.469 + InSequence s; 1.470 + EXPECT_CALL(mock_handler, 1.471 + StartCompilationUnit(StrEq("Tanzania"), 1.472 + 0x11a97352, NULL)) 1.473 + .WillOnce(Return(true)); 1.474 + EXPECT_CALL(mock_handler, EndCompilationUnit(0x21a97352)) 1.475 + .WillOnce(Return(true)); 1.476 + } 1.477 + 1.478 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.479 +} 1.480 + 1.481 +TEST_F(Stabs, FunctionEnd) { 1.482 + stabs.set_endianness(kLittleEndian); 1.483 + stabs.set_value_size(8); 1.484 + stabs 1.485 + .Stab(N_SO, 102, 62362, 0x52a830d644cd6942ULL, "compilation unit") 1.486 + // This function is terminated by the start of the next function. 1.487 + .Stab(N_FUN, 216, 38405, 0xbb5ab70ecdd23bfeULL, "function 1") 1.488 + // This function is terminated by an explicit end-of-function stab, 1.489 + // whose value is a size in bytes. 1.490 + .Stab(N_FUN, 240, 10973, 0xc954de9b8fb3e5e2ULL, "function 2") 1.491 + .Stab(N_FUN, 14, 36749, 0xc1ab, "") 1.492 + // This function is terminated by the end of the compilation unit. 1.493 + .Stab(N_FUN, 143, 64514, 0xdff98c9a35386e1fULL, "function 3") 1.494 + .Stab(N_SO, 164, 60142, 0xfdacb856e78bbf57ULL, ""); 1.495 + 1.496 + { 1.497 + InSequence s; 1.498 + EXPECT_CALL(mock_handler, 1.499 + StartCompilationUnit(StrEq("compilation unit"), 1.500 + 0x52a830d644cd6942ULL, NULL)) 1.501 + .WillOnce(Return(true)); 1.502 + EXPECT_CALL(mock_handler, 1.503 + StartFunction(Eq("function 1"), 0xbb5ab70ecdd23bfeULL)) 1.504 + .WillOnce(Return(true)); 1.505 + EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL)) 1.506 + .WillOnce(Return(true)); 1.507 + EXPECT_CALL(mock_handler, 1.508 + StartFunction(Eq("function 2"), 0xc954de9b8fb3e5e2ULL)) 1.509 + .WillOnce(Return(true)); 1.510 + EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL + 0xc1ab)) 1.511 + .WillOnce(Return(true)); 1.512 + EXPECT_CALL(mock_handler, 1.513 + StartFunction(Eq("function 3"), 0xdff98c9a35386e1fULL)) 1.514 + .WillOnce(Return(true)); 1.515 + EXPECT_CALL(mock_handler, EndFunction(0xfdacb856e78bbf57ULL)) 1.516 + .WillOnce(Return(true)); 1.517 + EXPECT_CALL(mock_handler, EndCompilationUnit(0xfdacb856e78bbf57ULL)) 1.518 + .WillOnce(Return(true)); 1.519 + } 1.520 + 1.521 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.522 +} 1.523 + 1.524 +// On Mac OS X, SLINE records can appear before the FUN stab to which they 1.525 +// belong, and their values are absolute addresses, not offsets. 1.526 +TEST_F(Stabs, LeadingLine) { 1.527 + stabs.set_endianness(kBigEndian); 1.528 + stabs.set_value_size(4); 1.529 + stabs 1.530 + .Stab(N_SO, 179, 27357, 0x8adabc15, "build directory/") 1.531 + .Stab(N_SO, 52, 53058, 0x4c7e3bf4, "compilation unit") 1.532 + .Stab(N_SOL, 165, 12086, 0x6a797ca3, "source file name") 1.533 + .Stab(N_SLINE, 229, 20015, 0x4cb3d7e0, "") 1.534 + .Stab(N_SLINE, 89, 43802, 0x4cba8b88, "") 1.535 + .Stab(N_FUN, 251, 51639, 0xce1b98fa, "rutabaga") 1.536 + .Stab(N_FUN, 218, 16113, 0x5798, "") 1.537 + .Stab(N_SO, 52, 53058, 0xd4af4415, ""); 1.538 + 1.539 + { 1.540 + InSequence s; 1.541 + EXPECT_CALL(mock_handler, 1.542 + StartCompilationUnit(StrEq("compilation unit"), 1.543 + 0x4c7e3bf4, StrEq("build directory/"))) 1.544 + .WillOnce(Return(true)); 1.545 + EXPECT_CALL(mock_handler, 1.546 + StartFunction(Eq("rutabaga"), 0xce1b98fa)) 1.547 + .WillOnce(Return(true)); 1.548 + EXPECT_CALL(mock_handler, 1.549 + Line(0x4cb3d7e0, StrEq("source file name"), 20015)) 1.550 + .WillOnce(Return(true)); 1.551 + EXPECT_CALL(mock_handler, 1.552 + Line(0x4cba8b88, StrEq("source file name"), 43802)) 1.553 + .WillOnce(Return(true)); 1.554 + EXPECT_CALL(mock_handler, EndFunction(0xce1b98fa + 0x5798)) 1.555 + .WillOnce(Return(true)); 1.556 + EXPECT_CALL(mock_handler, EndCompilationUnit(0xd4af4415)) 1.557 + .WillOnce(Return(true)); 1.558 + } 1.559 + 1.560 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.561 +} 1.562 + 1.563 + 1.564 +#if defined(HAVE_MACH_O_NLIST_H) 1.565 +// These tests have no meaning on non-Mach-O-based systems, as 1.566 +// only Mach-O uses N_SECT to represent public symbols. 1.567 +TEST_F(Stabs, OnePublicSymbol) { 1.568 + stabs.set_endianness(kLittleEndian); 1.569 + stabs.set_value_size(4); 1.570 + 1.571 + const uint32_t kExpectedAddress = 0x9000; 1.572 + const string kExpectedFunctionName("public_function"); 1.573 + stabs 1.574 + .Stab(N_SECT, 1, 0, kExpectedAddress, kExpectedFunctionName); 1.575 + 1.576 + { 1.577 + InSequence s; 1.578 + EXPECT_CALL(mock_handler, 1.579 + Extern(StrEq(kExpectedFunctionName), 1.580 + kExpectedAddress)) 1.581 + .WillOnce(Return(true)); 1.582 + } 1.583 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.584 +} 1.585 + 1.586 +TEST_F(Stabs, TwoPublicSymbols) { 1.587 + stabs.set_endianness(kLittleEndian); 1.588 + stabs.set_value_size(4); 1.589 + 1.590 + const uint32_t kExpectedAddress1 = 0xB0B0B0B0; 1.591 + const string kExpectedFunctionName1("public_function"); 1.592 + const uint32_t kExpectedAddress2 = 0xF0F0F0F0; 1.593 + const string kExpectedFunctionName2("something else"); 1.594 + stabs 1.595 + .Stab(N_SECT, 1, 0, kExpectedAddress1, kExpectedFunctionName1) 1.596 + .Stab(N_SECT, 1, 0, kExpectedAddress2, kExpectedFunctionName2); 1.597 + 1.598 + { 1.599 + InSequence s; 1.600 + EXPECT_CALL(mock_handler, 1.601 + Extern(StrEq(kExpectedFunctionName1), 1.602 + kExpectedAddress1)) 1.603 + .WillOnce(Return(true)); 1.604 + EXPECT_CALL(mock_handler, 1.605 + Extern(StrEq(kExpectedFunctionName2), 1.606 + kExpectedAddress2)) 1.607 + .WillOnce(Return(true)); 1.608 + } 1.609 + ASSERT_TRUE(ApplyHandlerToMockStabsData()); 1.610 +} 1.611 + 1.612 +#endif 1.613 + 1.614 +} // anonymous namespace