toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc

changeset 0
6474c204b198
     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

mercurial