1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module_unittest.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,258 @@ 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 +// dump_stabs_unittest.cc: Unit tests for StabsToModule. 1.36 + 1.37 +#include <vector> 1.38 + 1.39 +#include "breakpad_googletest_includes.h" 1.40 +#include "common/stabs_to_module.h" 1.41 + 1.42 +using google_breakpad::Module; 1.43 +using google_breakpad::StabsToModule; 1.44 +using std::vector; 1.45 + 1.46 +TEST(StabsToModule, SimpleCU) { 1.47 + Module m("name", "os", "arch", "id"); 1.48 + StabsToModule h(&m); 1.49 + 1.50 + // Feed in a simple compilation unit that defines a function with 1.51 + // one line. 1.52 + EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0x9f4d1271e50db93bLL, 1.53 + "build-directory")); 1.54 + EXPECT_TRUE(h.StartFunction("function", 0xfde4abbed390c394LL)); 1.55 + EXPECT_TRUE(h.Line(0xfde4abbed390c394LL, "source-file-name", 174823314)); 1.56 + EXPECT_TRUE(h.EndFunction(0xfde4abbed390c3a4LL)); 1.57 + EXPECT_TRUE(h.EndCompilationUnit(0xfee4abbed390c3a4LL)); 1.58 + h.Finalize(); 1.59 + 1.60 + // Now check to see what has been added to the Module. 1.61 + Module::File *file = m.FindExistingFile("source-file-name"); 1.62 + ASSERT_TRUE(file != NULL); 1.63 + 1.64 + vector<Module::Function *> functions; 1.65 + m.GetFunctions(&functions, functions.end()); 1.66 + ASSERT_EQ((size_t) 1, functions.size()); 1.67 + Module::Function *function = functions[0]; 1.68 + EXPECT_STREQ("function", function->name.c_str()); 1.69 + EXPECT_EQ(0xfde4abbed390c394LL, function->address); 1.70 + EXPECT_EQ(0x10U, function->size); 1.71 + EXPECT_EQ(0U, function->parameter_size); 1.72 + ASSERT_EQ((size_t) 1, function->lines.size()); 1.73 + Module::Line *line = &function->lines[0]; 1.74 + EXPECT_EQ(0xfde4abbed390c394LL, line->address); 1.75 + EXPECT_EQ(0x10U, line->size); // derived from EndFunction 1.76 + EXPECT_TRUE(line->file == file); 1.77 + EXPECT_EQ(174823314, line->number); 1.78 +} 1.79 + 1.80 +#ifdef __GNUC__ 1.81 +// Function name mangling can vary by compiler, so only run mangled-name 1.82 +// tests on GCC for simplicity's sake. 1.83 +TEST(StabsToModule, Externs) { 1.84 + Module m("name", "os", "arch", "id"); 1.85 + StabsToModule h(&m); 1.86 + 1.87 + // Feed in a few Extern symbols. 1.88 + EXPECT_TRUE(h.Extern("_foo", 0xffff)); 1.89 + EXPECT_TRUE(h.Extern("__Z21dyldGlobalLockAcquirev", 0xaaaa)); 1.90 + EXPECT_TRUE(h.Extern("_MorphTableGetNextMorphChain", 0x1111)); 1.91 + h.Finalize(); 1.92 + 1.93 + // Now check to see what has been added to the Module. 1.94 + vector<Module::Extern *> externs; 1.95 + m.GetExterns(&externs, externs.end()); 1.96 + ASSERT_EQ((size_t) 3, externs.size()); 1.97 + Module::Extern *extern1 = externs[0]; 1.98 + EXPECT_STREQ("MorphTableGetNextMorphChain", extern1->name.c_str()); 1.99 + EXPECT_EQ((Module::Address)0x1111, extern1->address); 1.100 + Module::Extern *extern2 = externs[1]; 1.101 + EXPECT_STREQ("dyldGlobalLockAcquire()", extern2->name.c_str()); 1.102 + EXPECT_EQ((Module::Address)0xaaaa, extern2->address); 1.103 + Module::Extern *extern3 = externs[2]; 1.104 + EXPECT_STREQ("foo", extern3->name.c_str()); 1.105 + EXPECT_EQ((Module::Address)0xffff, extern3->address); 1.106 +} 1.107 +#endif // __GNUC__ 1.108 + 1.109 +TEST(StabsToModule, DuplicateFunctionNames) { 1.110 + Module m("name", "os", "arch", "id"); 1.111 + StabsToModule h(&m); 1.112 + 1.113 + // Compilation unit with one function, mangled name. 1.114 + EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xf2cfda36ecf7f46cLL, 1.115 + "build-directory")); 1.116 + EXPECT_TRUE(h.StartFunction("funcfoo", 1.117 + 0xf2cfda36ecf7f46dLL)); 1.118 + EXPECT_TRUE(h.EndFunction(0)); 1.119 + EXPECT_TRUE(h.StartFunction("funcfoo", 1.120 + 0xf2cfda36ecf7f46dLL)); 1.121 + EXPECT_TRUE(h.EndFunction(0)); 1.122 + EXPECT_TRUE(h.EndCompilationUnit(0)); 1.123 + 1.124 + h.Finalize(); 1.125 + 1.126 + // Now check to see what has been added to the Module. 1.127 + Module::File *file = m.FindExistingFile("compilation-unit"); 1.128 + ASSERT_TRUE(file != NULL); 1.129 + 1.130 + vector<Module::Function *> functions; 1.131 + m.GetFunctions(&functions, functions.end()); 1.132 + ASSERT_EQ(1U, functions.size()); 1.133 + 1.134 + Module::Function *function = functions[0]; 1.135 + EXPECT_EQ(0xf2cfda36ecf7f46dLL, function->address); 1.136 + EXPECT_LT(0U, function->size); // should have used dummy size 1.137 + EXPECT_EQ(0U, function->parameter_size); 1.138 + ASSERT_EQ(0U, function->lines.size()); 1.139 +} 1.140 + 1.141 +TEST(InferSizes, LineSize) { 1.142 + Module m("name", "os", "arch", "id"); 1.143 + StabsToModule h(&m); 1.144 + 1.145 + // Feed in a simple compilation unit that defines a function with 1.146 + // one line. 1.147 + EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xb4513962eff94e92LL, 1.148 + "build-directory")); 1.149 + EXPECT_TRUE(h.StartFunction("function", 0xb4513962eff94e92LL)); 1.150 + EXPECT_TRUE(h.Line(0xb4513962eff94e92LL, "source-file-name-1", 77396614)); 1.151 + EXPECT_TRUE(h.Line(0xb4513963eff94e92LL, "source-file-name-2", 87660088)); 1.152 + EXPECT_TRUE(h.EndFunction(0)); // unknown function end address 1.153 + EXPECT_TRUE(h.EndCompilationUnit(0)); // unknown CU end address 1.154 + EXPECT_TRUE(h.StartCompilationUnit("compilation-unit-2", 0xb4523963eff94e92LL, 1.155 + "build-directory-2")); // next boundary 1.156 + EXPECT_TRUE(h.EndCompilationUnit(0)); 1.157 + h.Finalize(); 1.158 + 1.159 + // Now check to see what has been added to the Module. 1.160 + Module::File *file1 = m.FindExistingFile("source-file-name-1"); 1.161 + ASSERT_TRUE(file1 != NULL); 1.162 + Module::File *file2 = m.FindExistingFile("source-file-name-2"); 1.163 + ASSERT_TRUE(file2 != NULL); 1.164 + 1.165 + vector<Module::Function *> functions; 1.166 + m.GetFunctions(&functions, functions.end()); 1.167 + ASSERT_EQ((size_t) 1, functions.size()); 1.168 + 1.169 + Module::Function *function = functions[0]; 1.170 + EXPECT_STREQ("function", function->name.c_str()); 1.171 + EXPECT_EQ(0xb4513962eff94e92LL, function->address); 1.172 + EXPECT_EQ(0x1000100000000ULL, function->size); // inferred from CU end 1.173 + EXPECT_EQ(0U, function->parameter_size); 1.174 + ASSERT_EQ((size_t) 2, function->lines.size()); 1.175 + 1.176 + Module::Line *line1 = &function->lines[0]; 1.177 + EXPECT_EQ(0xb4513962eff94e92LL, line1->address); 1.178 + EXPECT_EQ(0x100000000ULL, line1->size); // derived from EndFunction 1.179 + EXPECT_TRUE(line1->file == file1); 1.180 + EXPECT_EQ(77396614, line1->number); 1.181 + 1.182 + Module::Line *line2 = &function->lines[1]; 1.183 + EXPECT_EQ(0xb4513963eff94e92LL, line2->address); 1.184 + EXPECT_EQ(0x1000000000000ULL, line2->size); // derived from EndFunction 1.185 + EXPECT_TRUE(line2->file == file2); 1.186 + EXPECT_EQ(87660088, line2->number); 1.187 +} 1.188 + 1.189 +#ifdef __GNUC__ 1.190 +// Function name mangling can vary by compiler, so only run mangled-name 1.191 +// tests on GCC for simplicity's sake. 1.192 +TEST(FunctionNames, Mangled) { 1.193 + Module m("name", "os", "arch", "id"); 1.194 + StabsToModule h(&m); 1.195 + 1.196 + // Compilation unit with one function, mangled name. 1.197 + EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xf2cfda63cef7f46cLL, 1.198 + "build-directory")); 1.199 + EXPECT_TRUE(h.StartFunction("_ZNSt6vectorIySaIyEE9push_backERKy", 1.200 + 0xf2cfda63cef7f46dLL)); 1.201 + EXPECT_TRUE(h.EndFunction(0)); 1.202 + EXPECT_TRUE(h.EndCompilationUnit(0)); 1.203 + 1.204 + h.Finalize(); 1.205 + 1.206 + // Now check to see what has been added to the Module. 1.207 + Module::File *file = m.FindExistingFile("compilation-unit"); 1.208 + ASSERT_TRUE(file != NULL); 1.209 + 1.210 + vector<Module::Function *> functions; 1.211 + m.GetFunctions(&functions, functions.end()); 1.212 + ASSERT_EQ(1U, functions.size()); 1.213 + 1.214 + Module::Function *function = functions[0]; 1.215 + // This is GCC-specific, but we shouldn't be seeing STABS data anywhere 1.216 + // but Linux. 1.217 + EXPECT_STREQ("std::vector<unsigned long long, " 1.218 + "std::allocator<unsigned long long> >::" 1.219 + "push_back(unsigned long long const&)", 1.220 + function->name.c_str()); 1.221 + EXPECT_EQ(0xf2cfda63cef7f46dLL, function->address); 1.222 + EXPECT_LT(0U, function->size); // should have used dummy size 1.223 + EXPECT_EQ(0U, function->parameter_size); 1.224 + ASSERT_EQ(0U, function->lines.size()); 1.225 +} 1.226 +#endif // __GNUC__ 1.227 + 1.228 +// The GNU toolchain can omit functions that are not used; however, 1.229 +// when it does so, it doesn't clean up the debugging information that 1.230 +// refers to them. In STABS, this results in compilation units whose 1.231 +// SO addresses are zero. 1.232 +TEST(Omitted, Function) { 1.233 + Module m("name", "os", "arch", "id"); 1.234 + StabsToModule h(&m); 1.235 + 1.236 + // The StartCompilationUnit and EndCompilationUnit calls may both have an 1.237 + // address of zero if the compilation unit has had sections removed. 1.238 + EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0, "build-directory")); 1.239 + EXPECT_TRUE(h.StartFunction("function", 0x2a133596)); 1.240 + EXPECT_TRUE(h.EndFunction(0)); 1.241 + EXPECT_TRUE(h.EndCompilationUnit(0)); 1.242 +} 1.243 + 1.244 +// TODO --- if we actually cared about STABS. Even without these we've 1.245 +// got full coverage of non-failure source lines in dump_stabs.cc. 1.246 + 1.247 +// Line size from next line 1.248 +// Line size from function end 1.249 +// Line size from next function start 1.250 +// line size from cu end 1.251 +// line size from next cu start 1.252 +// fallback size is something plausible 1.253 + 1.254 +// function size from function end 1.255 +// function size from next function start 1.256 +// function size from cu end 1.257 +// function size from next cu start 1.258 +// fallback size is something plausible 1.259 + 1.260 +// omitting functions outside the compilation unit's address range 1.261 +// zero-line, one-line, many-line functions