1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,661 @@ 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 +// module_unittest.cc: Unit tests for google_breakpad::Module. 1.36 + 1.37 +#include <errno.h> 1.38 +#include <stdio.h> 1.39 +#include <stdlib.h> 1.40 +#include <string.h> 1.41 + 1.42 +#include <algorithm> 1.43 +#include <sstream> 1.44 +#include <string> 1.45 + 1.46 +#include "breakpad_googletest_includes.h" 1.47 +#include "common/module.h" 1.48 +#include "common/using_std_string.h" 1.49 + 1.50 +using google_breakpad::Module; 1.51 +using google_breakpad::ToUniqueString; 1.52 +using google_breakpad::ustr__ZDcfa; 1.53 +using std::stringstream; 1.54 +using std::vector; 1.55 +using testing::ContainerEq; 1.56 + 1.57 +static Module::Function *generate_duplicate_function(const string &name) { 1.58 + const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL; 1.59 + const Module::Address DUP_SIZE = 0x200b26e605f99071LL; 1.60 + const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL; 1.61 + 1.62 + Module::Function *function = new(Module::Function); 1.63 + function->name = name; 1.64 + function->address = DUP_ADDRESS; 1.65 + function->size = DUP_SIZE; 1.66 + function->parameter_size = DUP_PARAMETER_SIZE; 1.67 + return function; 1.68 +} 1.69 + 1.70 +#define MODULE_NAME "name with spaces" 1.71 +#define MODULE_OS "os-name" 1.72 +#define MODULE_ARCH "architecture" 1.73 +#define MODULE_ID "id-string" 1.74 + 1.75 +TEST(Write, Header) { 1.76 + stringstream s; 1.77 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.78 + m.Write(s, ALL_SYMBOL_DATA); 1.79 + string contents = s.str(); 1.80 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n", 1.81 + contents.c_str()); 1.82 +} 1.83 + 1.84 +TEST(Write, OneLineFunc) { 1.85 + stringstream s; 1.86 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.87 + 1.88 + Module::File *file = m.FindFile("file_name.cc"); 1.89 + Module::Function *function = new(Module::Function); 1.90 + function->name = "function_name"; 1.91 + function->address = 0xe165bf8023b9d9abLL; 1.92 + function->size = 0x1e4bb0eb1cbf5b09LL; 1.93 + function->parameter_size = 0x772beee89114358aLL; 1.94 + Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL, 1.95 + file, 67519080 }; 1.96 + function->lines.push_back(line); 1.97 + m.AddFunction(function); 1.98 + 1.99 + m.Write(s, ALL_SYMBOL_DATA); 1.100 + string contents = s.str(); 1.101 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.102 + "FILE 0 file_name.cc\n" 1.103 + "FUNC e165bf8023b9d9ab 1e4bb0eb1cbf5b09 772beee89114358a" 1.104 + " function_name\n" 1.105 + "e165bf8023b9d9ab 1e4bb0eb1cbf5b09 67519080 0\n", 1.106 + contents.c_str()); 1.107 +} 1.108 + 1.109 +TEST(Write, RelativeLoadAddress) { 1.110 + stringstream s; 1.111 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.112 + 1.113 + // Some source files. We will expect to see them in lexicographic order. 1.114 + Module::File *file1 = m.FindFile("filename-b.cc"); 1.115 + Module::File *file2 = m.FindFile("filename-a.cc"); 1.116 + 1.117 + // A function. 1.118 + Module::Function *function = new(Module::Function); 1.119 + function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)"; 1.120 + function->address = 0xbec774ea5dd935f3LL; 1.121 + function->size = 0x2922088f98d3f6fcLL; 1.122 + function->parameter_size = 0xe5e9aa008bd5f0d0LL; 1.123 + 1.124 + // Some source lines. The module should not sort these. 1.125 + Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL, 1.126 + file1, 41676901 }; 1.127 + Module::Line line2 = { 0xdaf35bc123885c04LL, 0xcf621b8d324d0ebLL, 1.128 + file2, 67519080 }; 1.129 + function->lines.push_back(line2); 1.130 + function->lines.push_back(line1); 1.131 + 1.132 + m.AddFunction(function); 1.133 + 1.134 + // Some stack information. 1.135 + Module::StackFrameEntry *entry = new Module::StackFrameEntry(); 1.136 + entry->address = 0x30f9e5c83323973dULL; 1.137 + entry->size = 0x49fc9ca7c7c13dc2ULL; 1.138 + entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man"); 1.139 + entry->initial_rules[ToUniqueString("and")] = 1.140 + Module::Expr("what i want to know is"); 1.141 + entry->initial_rules[ToUniqueString("stallion")] = 1.142 + Module::Expr(ToUniqueString("and break"), 8, false); 1.143 + entry->initial_rules[ToUniqueString("onetwothreefourfive")] = 1.144 + Module::Expr(ToUniqueString("pigeonsjustlikethat"), 42, true); 1.145 + entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] = 1.146 + Module::Expr("do you like your blueeyed boy"); 1.147 + entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] = 1.148 + Module::Expr("Death"); 1.149 + m.AddStackFrameEntry(entry); 1.150 + 1.151 + // Set the load address. Doing this after adding all the data to 1.152 + // the module must work fine. 1.153 + m.SetLoadAddress(0x2ab698b0b6407073LL); 1.154 + 1.155 + m.Write(s, ALL_SYMBOL_DATA); 1.156 + string contents = s.str(); 1.157 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.158 + "FILE 0 filename-a.cc\n" 1.159 + "FILE 1 filename-b.cc\n" 1.160 + "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0" 1.161 + " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n" 1.162 + "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n" 1.163 + "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n" 1.164 + "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2" 1.165 + " .cfa: he was a handsome man" 1.166 + " and: what i want to know is" 1.167 + " onetwothreefourfive: pigeonsjustlikethat 42 + ^" 1.168 + " stallion: and break 8 +\n" 1.169 + "STACK CFI 6434d177ce326cb" 1.170 + " Mister: Death" 1.171 + " how: do you like your blueeyed boy\n", 1.172 + contents.c_str()); 1.173 +} 1.174 + 1.175 +TEST(Write, OmitUnusedFiles) { 1.176 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.177 + 1.178 + // Create some source files. 1.179 + Module::File *file1 = m.FindFile("filename1"); 1.180 + m.FindFile("filename2"); // not used by any line 1.181 + Module::File *file3 = m.FindFile("filename3"); 1.182 + 1.183 + // Create a function. 1.184 + Module::Function *function = new(Module::Function); 1.185 + function->name = "function_name"; 1.186 + function->address = 0x9b926d464f0b9384LL; 1.187 + function->size = 0x4f524a4ba795e6a6LL; 1.188 + function->parameter_size = 0xbbe8133a6641c9b7LL; 1.189 + 1.190 + // Source files that refer to some files, but not others. 1.191 + Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL, 1.192 + file1, 137850127 }; 1.193 + Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL, 1.194 + file3, 28113549 }; 1.195 + function->lines.push_back(line1); 1.196 + function->lines.push_back(line2); 1.197 + m.AddFunction(function); 1.198 + 1.199 + m.AssignSourceIds(); 1.200 + 1.201 + vector<Module::File *> vec; 1.202 + m.GetFiles(&vec); 1.203 + EXPECT_EQ((size_t) 3, vec.size()); 1.204 + EXPECT_STREQ("filename1", vec[0]->name.c_str()); 1.205 + EXPECT_NE(-1, vec[0]->source_id); 1.206 + // Expect filename2 not to be used. 1.207 + EXPECT_STREQ("filename2", vec[1]->name.c_str()); 1.208 + EXPECT_EQ(-1, vec[1]->source_id); 1.209 + EXPECT_STREQ("filename3", vec[2]->name.c_str()); 1.210 + EXPECT_NE(-1, vec[2]->source_id); 1.211 + 1.212 + stringstream s; 1.213 + m.Write(s, ALL_SYMBOL_DATA); 1.214 + string contents = s.str(); 1.215 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.216 + "FILE 0 filename1\n" 1.217 + "FILE 1 filename3\n" 1.218 + "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7" 1.219 + " function_name\n" 1.220 + "595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n" 1.221 + "401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n", 1.222 + contents.c_str()); 1.223 +} 1.224 + 1.225 +TEST(Write, NoCFI) { 1.226 + stringstream s; 1.227 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.228 + 1.229 + // Some source files. We will expect to see them in lexicographic order. 1.230 + Module::File *file1 = m.FindFile("filename.cc"); 1.231 + 1.232 + // A function. 1.233 + Module::Function *function = new(Module::Function); 1.234 + function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)"; 1.235 + function->address = 0xbec774ea5dd935f3LL; 1.236 + function->size = 0x2922088f98d3f6fcLL; 1.237 + function->parameter_size = 0xe5e9aa008bd5f0d0LL; 1.238 + 1.239 + // Some source lines. The module should not sort these. 1.240 + Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL, 1.241 + file1, 41676901 }; 1.242 + function->lines.push_back(line1); 1.243 + 1.244 + m.AddFunction(function); 1.245 + 1.246 + // Some stack information. 1.247 + Module::StackFrameEntry *entry = new Module::StackFrameEntry(); 1.248 + entry->address = 0x30f9e5c83323973dULL; 1.249 + entry->size = 0x49fc9ca7c7c13dc2ULL; 1.250 + entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man"); 1.251 + entry->initial_rules[ToUniqueString("and")] = 1.252 + Module::Expr("what i want to know is"); 1.253 + entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] = 1.254 + Module::Expr("do you like your blueeyed boy"); 1.255 + entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] = 1.256 + Module::Expr("Death"); 1.257 + m.AddStackFrameEntry(entry); 1.258 + 1.259 + // Set the load address. Doing this after adding all the data to 1.260 + // the module must work fine. 1.261 + m.SetLoadAddress(0x2ab698b0b6407073LL); 1.262 + 1.263 + m.Write(s, NO_CFI); 1.264 + string contents = s.str(); 1.265 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.266 + "FILE 0 filename.cc\n" 1.267 + "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0" 1.268 + " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n" 1.269 + "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n", 1.270 + contents.c_str()); 1.271 +} 1.272 + 1.273 +TEST(Construct, AddFunctions) { 1.274 + stringstream s; 1.275 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.276 + 1.277 + // Two functions. 1.278 + Module::Function *function1 = new(Module::Function); 1.279 + function1->name = "_without_form"; 1.280 + function1->address = 0xd35024aa7ca7da5cLL; 1.281 + function1->size = 0x200b26e605f99071LL; 1.282 + function1->parameter_size = 0xf14ac4fed48c4a99LL; 1.283 + 1.284 + Module::Function *function2 = new(Module::Function); 1.285 + function2->name = "_and_void"; 1.286 + function2->address = 0x2987743d0b35b13fLL; 1.287 + function2->size = 0xb369db048deb3010LL; 1.288 + function2->parameter_size = 0x938e556cb5a79988LL; 1.289 + 1.290 + // Put them in a vector. 1.291 + vector<Module::Function *> vec; 1.292 + vec.push_back(function1); 1.293 + vec.push_back(function2); 1.294 + 1.295 + m.AddFunctions(vec.begin(), vec.end()); 1.296 + 1.297 + m.Write(s, ALL_SYMBOL_DATA); 1.298 + string contents = s.str(); 1.299 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.300 + "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988" 1.301 + " _and_void\n" 1.302 + "FUNC d35024aa7ca7da5c 200b26e605f99071 f14ac4fed48c4a99" 1.303 + " _without_form\n", 1.304 + contents.c_str()); 1.305 + 1.306 + // Check that m.GetFunctions returns the functions we expect. 1.307 + vec.clear(); 1.308 + m.GetFunctions(&vec, vec.end()); 1.309 + EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function1)); 1.310 + EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function2)); 1.311 + EXPECT_EQ((size_t) 2, vec.size()); 1.312 +} 1.313 + 1.314 +TEST(Construct, AddFrames) { 1.315 + stringstream s; 1.316 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.317 + 1.318 + // First STACK CFI entry, with no initial rules or deltas. 1.319 + Module::StackFrameEntry *entry1 = new Module::StackFrameEntry(); 1.320 + entry1->address = 0xddb5f41285aa7757ULL; 1.321 + entry1->size = 0x1486493370dc5073ULL; 1.322 + m.AddStackFrameEntry(entry1); 1.323 + 1.324 + // Second STACK CFI entry, with initial rules but no deltas. 1.325 + Module::StackFrameEntry *entry2 = new Module::StackFrameEntry(); 1.326 + entry2->address = 0x8064f3af5e067e38ULL; 1.327 + entry2->size = 0x0de2a5ee55509407ULL; 1.328 + entry2->initial_rules[ustr__ZDcfa()] = 1.329 + Module::Expr("I think that I shall never see"); 1.330 + entry2->initial_rules[ToUniqueString("stromboli")] = 1.331 + Module::Expr("a poem lovely as a tree"); 1.332 + entry2->initial_rules[ToUniqueString("cannoli")] = 1.333 + Module::Expr("a tree whose hungry mouth is prest"); 1.334 + m.AddStackFrameEntry(entry2); 1.335 + 1.336 + // Third STACK CFI entry, with initial rules and deltas. 1.337 + Module::StackFrameEntry *entry3 = new Module::StackFrameEntry(); 1.338 + entry3->address = 0x5e8d0db0a7075c6cULL; 1.339 + entry3->size = 0x1c7edb12a7aea229ULL; 1.340 + entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these"); 1.341 + entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] = 1.342 + Module::Expr("the village though"); 1.343 + entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] = 1.344 + Module::Expr("he will not see me stopping here"); 1.345 + entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] = 1.346 + Module::Expr("his house is in"); 1.347 + entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] = 1.348 + Module::Expr("I think I know"); 1.349 + m.AddStackFrameEntry(entry3); 1.350 + 1.351 + // Check that Write writes STACK CFI records properly. 1.352 + m.Write(s, ALL_SYMBOL_DATA); 1.353 + string contents = s.str(); 1.354 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.355 + "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229" 1.356 + " .cfa: Whose woods are these\n" 1.357 + "STACK CFI 36682fad3763ffff" 1.358 + " .cfa: I think I know" 1.359 + " stromboli: his house is in\n" 1.360 + "STACK CFI 47ceb0f63c269d7f" 1.361 + " calzone: the village though" 1.362 + " cannoli: he will not see me stopping here\n" 1.363 + "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407" 1.364 + " .cfa: I think that I shall never see" 1.365 + " cannoli: a tree whose hungry mouth is prest" 1.366 + " stromboli: a poem lovely as a tree\n" 1.367 + "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n", 1.368 + contents.c_str()); 1.369 + 1.370 + // Check that GetStackFrameEntries works. 1.371 + vector<Module::StackFrameEntry *> entries; 1.372 + m.GetStackFrameEntries(&entries); 1.373 + ASSERT_EQ(3U, entries.size()); 1.374 + // Check first entry. 1.375 + EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address); 1.376 + EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size); 1.377 + Module::RuleMap entry1_initial; 1.378 + entry1_initial[ustr__ZDcfa()] = Module::Expr("Whose woods are these"); 1.379 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial)); 1.380 + Module::RuleChangeMap entry1_changes; 1.381 + entry1_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] = 1.382 + Module::Expr("I think I know"); 1.383 + entry1_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] = 1.384 + Module::Expr("his house is in"); 1.385 + entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] = 1.386 + Module::Expr("the village though"); 1.387 + entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] = 1.388 + Module::Expr("he will not see me stopping here"); 1.389 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes)); 1.390 + // Check second entry. 1.391 + EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address); 1.392 + EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size); 1.393 + ASSERT_EQ(3U, entries[1]->initial_rules.size()); 1.394 + Module::RuleMap entry2_initial; 1.395 + entry2_initial[ustr__ZDcfa()] = 1.396 + Module::Expr("I think that I shall never see"); 1.397 + entry2_initial[ToUniqueString("stromboli")] = 1.398 + Module::Expr("a poem lovely as a tree"); 1.399 + entry2_initial[ToUniqueString("cannoli")] = 1.400 + Module::Expr("a tree whose hungry mouth is prest"); 1.401 + EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial)); 1.402 + ASSERT_EQ(0U, entries[1]->rule_changes.size()); 1.403 + // Check third entry. 1.404 + EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address); 1.405 + EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size); 1.406 + ASSERT_EQ(0U, entries[2]->initial_rules.size()); 1.407 + ASSERT_EQ(0U, entries[2]->rule_changes.size()); 1.408 +} 1.409 + 1.410 +TEST(Construct, UniqueFiles) { 1.411 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.412 + Module::File *file1 = m.FindFile("foo"); 1.413 + Module::File *file2 = m.FindFile(string("bar")); 1.414 + Module::File *file3 = m.FindFile(string("foo")); 1.415 + Module::File *file4 = m.FindFile("bar"); 1.416 + EXPECT_NE(file1, file2); 1.417 + EXPECT_EQ(file1, file3); 1.418 + EXPECT_EQ(file2, file4); 1.419 + EXPECT_EQ(file1, m.FindExistingFile("foo")); 1.420 + EXPECT_TRUE(m.FindExistingFile("baz") == NULL); 1.421 +} 1.422 + 1.423 +TEST(Construct, DuplicateFunctions) { 1.424 + stringstream s; 1.425 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.426 + 1.427 + // Two functions. 1.428 + Module::Function *function1 = generate_duplicate_function("_without_form"); 1.429 + Module::Function *function2 = generate_duplicate_function("_without_form"); 1.430 + 1.431 + m.AddFunction(function1); 1.432 + m.AddFunction(function2); 1.433 + 1.434 + m.Write(s, ALL_SYMBOL_DATA); 1.435 + string contents = s.str(); 1.436 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.437 + "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" 1.438 + " _without_form\n", 1.439 + contents.c_str()); 1.440 +} 1.441 + 1.442 +TEST(Construct, FunctionsWithSameAddress) { 1.443 + stringstream s; 1.444 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.445 + 1.446 + // Two functions. 1.447 + Module::Function *function1 = generate_duplicate_function("_without_form"); 1.448 + Module::Function *function2 = generate_duplicate_function("_and_void"); 1.449 + 1.450 + m.AddFunction(function1); 1.451 + m.AddFunction(function2); 1.452 + 1.453 + m.Write(s, ALL_SYMBOL_DATA); 1.454 + string contents = s.str(); 1.455 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.456 + "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" 1.457 + " _and_void\n" 1.458 + "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99" 1.459 + " _without_form\n", 1.460 + contents.c_str()); 1.461 +} 1.462 + 1.463 +// Externs should be written out as PUBLIC records, sorted by 1.464 +// address. 1.465 +TEST(Construct, Externs) { 1.466 + stringstream s; 1.467 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.468 + 1.469 + // Two externs. 1.470 + Module::Extern *extern1 = new(Module::Extern); 1.471 + extern1->address = 0xffff; 1.472 + extern1->name = "_abc"; 1.473 + Module::Extern *extern2 = new(Module::Extern); 1.474 + extern2->address = 0xaaaa; 1.475 + extern2->name = "_xyz"; 1.476 + 1.477 + m.AddExtern(extern1); 1.478 + m.AddExtern(extern2); 1.479 + 1.480 + m.Write(s, ALL_SYMBOL_DATA); 1.481 + string contents = s.str(); 1.482 + 1.483 + EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " 1.484 + MODULE_ID " " MODULE_NAME "\n" 1.485 + "PUBLIC aaaa 0 _xyz\n" 1.486 + "PUBLIC ffff 0 _abc\n", 1.487 + contents.c_str()); 1.488 +} 1.489 + 1.490 +// Externs with the same address should only keep the first entry 1.491 +// added. 1.492 +TEST(Construct, DuplicateExterns) { 1.493 + stringstream s; 1.494 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.495 + 1.496 + // Two externs. 1.497 + Module::Extern *extern1 = new(Module::Extern); 1.498 + extern1->address = 0xffff; 1.499 + extern1->name = "_xyz"; 1.500 + Module::Extern *extern2 = new(Module::Extern); 1.501 + extern2->address = 0xffff; 1.502 + extern2->name = "_abc"; 1.503 + 1.504 + m.AddExtern(extern1); 1.505 + m.AddExtern(extern2); 1.506 + 1.507 + m.Write(s, ALL_SYMBOL_DATA); 1.508 + string contents = s.str(); 1.509 + 1.510 + EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " 1.511 + MODULE_ID " " MODULE_NAME "\n" 1.512 + "PUBLIC ffff 0 _xyz\n", 1.513 + contents.c_str()); 1.514 +} 1.515 + 1.516 +TEST(Lookup, Function) { 1.517 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.518 + 1.519 + Module::Function *function1 = new(Module::Function); 1.520 + function1->name = "_abc1"; 1.521 + function1->address = 0x1000; 1.522 + function1->size = 0x900; 1.523 + function1->parameter_size = 0x0; 1.524 + 1.525 + Module::Function *function2 = new(Module::Function); 1.526 + function2->name = "_xyz2"; 1.527 + function2->address = 0x2000; 1.528 + function2->size = 0x900; 1.529 + function2->parameter_size = 0x0; 1.530 + 1.531 + Module::Function *function3 = new(Module::Function); 1.532 + function3->name = "_def3"; 1.533 + function3->address = 0x3000; 1.534 + function3->size = 0x900; 1.535 + function3->parameter_size = 0x0; 1.536 + 1.537 + // Put them in a vector. 1.538 + vector<Module::Function *> vec; 1.539 + vec.push_back(function1); 1.540 + vec.push_back(function2); 1.541 + vec.push_back(function3); 1.542 + 1.543 + m.AddFunctions(vec.begin(), vec.end()); 1.544 + 1.545 + // Try looking up functions by address. 1.546 + Module::Function* f = m.FindFunctionByAddress(0x1000); 1.547 + EXPECT_EQ(function1, f); 1.548 + f = m.FindFunctionByAddress(0x18FF); 1.549 + EXPECT_EQ(function1, f); 1.550 + 1.551 + f = m.FindFunctionByAddress(0x1900); 1.552 + EXPECT_EQ((Module::Function*)NULL, f); 1.553 + f = m.FindFunctionByAddress(0x1A00); 1.554 + EXPECT_EQ((Module::Function*)NULL, f); 1.555 + 1.556 + f = m.FindFunctionByAddress(0x2000); 1.557 + EXPECT_EQ(function2, f); 1.558 + f = m.FindFunctionByAddress(0x28FF); 1.559 + EXPECT_EQ(function2, f); 1.560 + 1.561 + f = m.FindFunctionByAddress(0x3000); 1.562 + EXPECT_EQ(function3, f); 1.563 + f = m.FindFunctionByAddress(0x38FF); 1.564 + EXPECT_EQ(function3, f); 1.565 + 1.566 + f = m.FindFunctionByAddress(0x3900); 1.567 + EXPECT_EQ((Module::Function*)NULL, f); 1.568 + f = m.FindFunctionByAddress(0x3A00); 1.569 + EXPECT_EQ((Module::Function*)NULL, f); 1.570 +} 1.571 + 1.572 +TEST(Lookup, Externs) { 1.573 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.574 + 1.575 + // Two externs. 1.576 + Module::Extern* extern1 = new(Module::Extern); 1.577 + extern1->address = 0x1000; 1.578 + extern1->name = "_abc"; 1.579 + Module::Extern* extern2 = new(Module::Extern); 1.580 + extern2->address = 0x2000; 1.581 + extern2->name = "_xyz"; 1.582 + 1.583 + m.AddExtern(extern1); 1.584 + m.AddExtern(extern2); 1.585 + 1.586 + Module::Extern* e = m.FindExternByAddress(0xFFF); 1.587 + EXPECT_EQ((Module::Extern*)NULL, e); 1.588 + 1.589 + e = m.FindExternByAddress(0x1000); 1.590 + EXPECT_EQ(extern1, e); 1.591 + e = m.FindExternByAddress(0x1900); 1.592 + EXPECT_EQ(extern1, e); 1.593 + e = m.FindExternByAddress(0x1FFF); 1.594 + EXPECT_EQ(extern1, e); 1.595 + 1.596 + e = m.FindExternByAddress(0x2000); 1.597 + EXPECT_EQ(extern2, e); 1.598 + e = m.FindExternByAddress(0x2900); 1.599 + EXPECT_EQ(extern2, e); 1.600 + e = m.FindExternByAddress(0xFFFFFFFF); 1.601 + EXPECT_EQ(extern2, e); 1.602 +} 1.603 + 1.604 +TEST(Lookup, StackFrameEntries) { 1.605 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.606 + 1.607 + // First STACK CFI entry, with no initial rules or deltas. 1.608 + Module::StackFrameEntry *entry1 = new Module::StackFrameEntry(); 1.609 + entry1->address = 0x2000; 1.610 + entry1->size = 0x900; 1.611 + m.AddStackFrameEntry(entry1); 1.612 + 1.613 + // Second STACK CFI entry, with initial rules but no deltas. 1.614 + Module::StackFrameEntry *entry2 = new Module::StackFrameEntry(); 1.615 + entry2->address = 0x3000; 1.616 + entry2->size = 0x900; 1.617 + entry2->initial_rules[ustr__ZDcfa()] = 1.618 + Module::Expr("I think that I shall never see"); 1.619 + entry2->initial_rules[ToUniqueString("stromboli")] = 1.620 + Module::Expr("a poem lovely as a tree"); 1.621 + entry2->initial_rules[ToUniqueString("cannoli")] = 1.622 + Module::Expr("a tree whose hungry mouth is prest"); 1.623 + m.AddStackFrameEntry(entry2); 1.624 + 1.625 + // Third STACK CFI entry, with initial rules and deltas. 1.626 + Module::StackFrameEntry *entry3 = new Module::StackFrameEntry(); 1.627 + entry3->address = 0x1000; 1.628 + entry3->size = 0x900; 1.629 + entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these"); 1.630 + entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] = 1.631 + Module::Expr("the village though"); 1.632 + entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] = 1.633 + Module::Expr("he will not see me stopping here"); 1.634 + entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] = 1.635 + Module::Expr("his house is in"); 1.636 + entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] = 1.637 + Module::Expr("I think I know"); 1.638 + m.AddStackFrameEntry(entry3); 1.639 + 1.640 + Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000); 1.641 + EXPECT_EQ(entry3, s); 1.642 + s = m.FindStackFrameEntryByAddress(0x18FF); 1.643 + EXPECT_EQ(entry3, s); 1.644 + 1.645 + s = m.FindStackFrameEntryByAddress(0x1900); 1.646 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.647 + s = m.FindStackFrameEntryByAddress(0x1A00); 1.648 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.649 + 1.650 + s = m.FindStackFrameEntryByAddress(0x2000); 1.651 + EXPECT_EQ(entry1, s); 1.652 + s = m.FindStackFrameEntryByAddress(0x28FF); 1.653 + EXPECT_EQ(entry1, s); 1.654 + 1.655 + s = m.FindStackFrameEntryByAddress(0x3000); 1.656 + EXPECT_EQ(entry2, s); 1.657 + s = m.FindStackFrameEntryByAddress(0x38FF); 1.658 + EXPECT_EQ(entry2, s); 1.659 + 1.660 + s = m.FindStackFrameEntryByAddress(0x3900); 1.661 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.662 + s = m.FindStackFrameEntryByAddress(0x3A00); 1.663 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.664 +}