1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/breakpad-patches/00-module-api-extras.patch Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,526 @@ 1.4 +# HG changeset patch 1.5 +# User Ted Mielczarek <ted@mielczarek.org> 1.6 +# Date 1352220493 18000 1.7 +# Node ID c3b1109dd392c16a9fe4e85da693010966dbbf0b 1.8 +# Parent 03db269a2868503cca9e80f62ce676aabbf967fd 1.9 +Add APIs for querying Module data 1.10 +R=glandium at https://breakpad.appspot.com/511003/ 1.11 + 1.12 +diff --git a/src/common/module.cc b/src/common/module.cc 1.13 +--- a/src/common/module.cc 1.14 ++++ b/src/common/module.cc 1.15 +@@ -58,17 +58,17 @@ 1.16 + 1.17 + Module::~Module() { 1.18 + for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it) 1.19 + delete it->second; 1.20 + for (FunctionSet::iterator it = functions_.begin(); 1.21 + it != functions_.end(); ++it) { 1.22 + delete *it; 1.23 + } 1.24 +- for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin(); 1.25 ++ for (StackFrameEntrySet::iterator it = stack_frame_entries_.begin(); 1.26 + it != stack_frame_entries_.end(); ++it) { 1.27 + delete *it; 1.28 + } 1.29 + for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it) 1.30 + delete *it; 1.31 + } 1.32 + 1.33 + void Module::SetLoadAddress(Address address) { 1.34 +@@ -88,39 +88,84 @@ 1.35 + } 1.36 + 1.37 + void Module::AddFunctions(vector<Function *>::iterator begin, 1.38 + vector<Function *>::iterator end) { 1.39 + for (vector<Function *>::iterator it = begin; it != end; ++it) 1.40 + AddFunction(*it); 1.41 + } 1.42 + 1.43 +-void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) { 1.44 +- stack_frame_entries_.push_back(stack_frame_entry); 1.45 ++void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) { 1.46 ++ std::pair<StackFrameEntrySet::iterator,bool> ret = 1.47 ++ stack_frame_entries_.insert(stack_frame_entry); 1.48 ++ if (!ret.second) { 1.49 ++ // Free the duplicate that was not inserted because this Module 1.50 ++ // now owns it. 1.51 ++ delete stack_frame_entry; 1.52 ++ } 1.53 + } 1.54 + 1.55 + void Module::AddExtern(Extern *ext) { 1.56 + std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext); 1.57 + if (!ret.second) { 1.58 + // Free the duplicate that was not inserted because this Module 1.59 + // now owns it. 1.60 + delete ext; 1.61 + } 1.62 + } 1.63 + 1.64 + void Module::GetFunctions(vector<Function *> *vec, 1.65 + vector<Function *>::iterator i) { 1.66 + vec->insert(i, functions_.begin(), functions_.end()); 1.67 + } 1.68 + 1.69 ++template<typename T> 1.70 ++bool EntryContainsAddress(T entry, Module::Address address) { 1.71 ++ return entry->address <= address && address < entry->address + entry->size; 1.72 ++} 1.73 ++ 1.74 ++Module::Function* Module::FindFunctionByAddress(Address address) { 1.75 ++ Function search; 1.76 ++ search.address = address; 1.77 ++ // Ensure that name always sorts higher than the function name, 1.78 ++ // so that upper_bound always returns the function just after 1.79 ++ // the function containing this address. 1.80 ++ search.name = "\xFF"; 1.81 ++ FunctionSet::iterator it = functions_.upper_bound(&search); 1.82 ++ if (it == functions_.begin()) 1.83 ++ return NULL; 1.84 ++ 1.85 ++ it--; 1.86 ++ 1.87 ++ if (EntryContainsAddress(*it, address)) 1.88 ++ return *it; 1.89 ++ 1.90 ++ return NULL; 1.91 ++} 1.92 ++ 1.93 + void Module::GetExterns(vector<Extern *> *vec, 1.94 + vector<Extern *>::iterator i) { 1.95 + vec->insert(i, externs_.begin(), externs_.end()); 1.96 + } 1.97 + 1.98 ++Module::Extern* Module::FindExternByAddress(Address address) { 1.99 ++ Extern search; 1.100 ++ search.address = address; 1.101 ++ ExternSet::iterator it = externs_.upper_bound(&search); 1.102 ++ 1.103 ++ if (it == externs_.begin()) 1.104 ++ return NULL; 1.105 ++ 1.106 ++ it--; 1.107 ++ if ((*it)->address > address) 1.108 ++ return NULL; 1.109 ++ 1.110 ++ return *it; 1.111 ++} 1.112 ++ 1.113 + Module::File *Module::FindFile(const string &name) { 1.114 + // A tricky bit here. The key of each map entry needs to be a 1.115 + // pointer to the entry's File's name string. This means that we 1.116 + // can't do the initial lookup with any operation that would create 1.117 + // an empty entry for us if the name isn't found (like, say, 1.118 + // operator[] or insert do), because such a created entry's key will 1.119 + // be a pointer the string passed as our argument. Since the key of 1.120 + // a map's value type is const, we can't fix it up once we've 1.121 +@@ -150,18 +195,35 @@ 1.122 + } 1.123 + 1.124 + void Module::GetFiles(vector<File *> *vec) { 1.125 + vec->clear(); 1.126 + for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it) 1.127 + vec->push_back(it->second); 1.128 + } 1.129 + 1.130 +-void Module::GetStackFrameEntries(vector<StackFrameEntry *> *vec) { 1.131 +- *vec = stack_frame_entries_; 1.132 ++void Module::GetStackFrameEntries(vector<StackFrameEntry *>* vec) { 1.133 ++ vec->clear(); 1.134 ++ vec->insert(vec->begin(), stack_frame_entries_.begin(), 1.135 ++ stack_frame_entries_.end()); 1.136 ++} 1.137 ++ 1.138 ++Module::StackFrameEntry* Module::FindStackFrameEntryByAddress(Address address) { 1.139 ++ StackFrameEntry search; 1.140 ++ search.address = address; 1.141 ++ StackFrameEntrySet::iterator it = stack_frame_entries_.upper_bound(&search); 1.142 ++ 1.143 ++ if (it == stack_frame_entries_.begin()) 1.144 ++ return NULL; 1.145 ++ 1.146 ++ it--; 1.147 ++ if (EntryContainsAddress(*it, address)) 1.148 ++ return *it; 1.149 ++ 1.150 ++ return NULL; 1.151 + } 1.152 + 1.153 + void Module::AssignSourceIds() { 1.154 + // First, give every source file an id of -1. 1.155 + for (FileByNameMap::iterator file_it = files_.begin(); 1.156 + file_it != files_.end(); ++file_it) { 1.157 + file_it->second->source_id = -1; 1.158 + } 1.159 +@@ -256,17 +318,17 @@ 1.160 + stream << "PUBLIC " << hex 1.161 + << (ext->address - load_address_) << " 0 " 1.162 + << ext->name << dec << endl; 1.163 + } 1.164 + } 1.165 + 1.166 + if (symbol_data != NO_CFI) { 1.167 + // Write out 'STACK CFI INIT' and 'STACK CFI' records. 1.168 +- vector<StackFrameEntry *>::const_iterator frame_it; 1.169 ++ StackFrameEntrySet::const_iterator frame_it; 1.170 + for (frame_it = stack_frame_entries_.begin(); 1.171 + frame_it != stack_frame_entries_.end(); ++frame_it) { 1.172 + StackFrameEntry *entry = *frame_it; 1.173 + stream << "STACK CFI INIT " << hex 1.174 + << (entry->address - load_address_) << " " 1.175 + << entry->size << " " << dec; 1.176 + if (!stream.good() 1.177 + || !WriteRuleMap(entry->initial_rules, stream)) 1.178 +diff --git a/src/common/module.h b/src/common/module.h 1.179 +--- a/src/common/module.h 1.180 ++++ b/src/common/module.h 1.181 +@@ -164,16 +164,23 @@ 1.182 + 1.183 + struct ExternCompare { 1.184 + bool operator() (const Extern *lhs, 1.185 + const Extern *rhs) const { 1.186 + return lhs->address < rhs->address; 1.187 + } 1.188 + }; 1.189 + 1.190 ++ struct StackFrameEntryCompare { 1.191 ++ bool operator() (const StackFrameEntry* lhs, 1.192 ++ const StackFrameEntry* rhs) const { 1.193 ++ return lhs->address < rhs->address; 1.194 ++ } 1.195 ++ }; 1.196 ++ 1.197 + // Create a new module with the given name, operating system, 1.198 + // architecture, and ID string. 1.199 + Module(const string &name, const string &os, const string &architecture, 1.200 + const string &id); 1.201 + ~Module(); 1.202 + 1.203 + // Set the module's load address to LOAD_ADDRESS; addresses given 1.204 + // for functions and lines will be written to the Breakpad symbol 1.205 +@@ -223,37 +230,49 @@ 1.206 + 1.207 + // Insert pointers to the functions added to this module at I in 1.208 + // VEC. The pointed-to Functions are still owned by this module. 1.209 + // (Since this is effectively a copy of the function list, this is 1.210 + // mostly useful for testing; other uses should probably get a more 1.211 + // appropriate interface.) 1.212 + void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i); 1.213 + 1.214 ++ // If this module has a function at ADDRESS, return a pointer to it. 1.215 ++ // Otherwise, return NULL. 1.216 ++ Function* FindFunctionByAddress(Address address); 1.217 ++ 1.218 + // Insert pointers to the externs added to this module at I in 1.219 + // VEC. The pointed-to Externs are still owned by this module. 1.220 + // (Since this is effectively a copy of the extern list, this is 1.221 + // mostly useful for testing; other uses should probably get a more 1.222 + // appropriate interface.) 1.223 + void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i); 1.224 + 1.225 ++ // If this module has an extern whose base address is less than ADDRESS, 1.226 ++ // return a pointer to it. Otherwise, return NULL. 1.227 ++ Extern* FindExternByAddress(Address address); 1.228 ++ 1.229 + // Clear VEC and fill it with pointers to the Files added to this 1.230 + // module, sorted by name. The pointed-to Files are still owned by 1.231 + // this module. (Since this is effectively a copy of the file list, 1.232 + // this is mostly useful for testing; other uses should probably get 1.233 + // a more appropriate interface.) 1.234 + void GetFiles(vector<File *> *vec); 1.235 + 1.236 + // Clear VEC and fill it with pointers to the StackFrameEntry 1.237 + // objects that have been added to this module. (Since this is 1.238 + // effectively a copy of the stack frame entry list, this is mostly 1.239 + // useful for testing; other uses should probably get 1.240 + // a more appropriate interface.) 1.241 + void GetStackFrameEntries(vector<StackFrameEntry *> *vec); 1.242 + 1.243 ++ // If this module has a StackFrameEntry whose address range covers 1.244 ++ // ADDRESS, return it. Otherwise return NULL. 1.245 ++ StackFrameEntry* FindStackFrameEntryByAddress(Address address); 1.246 ++ 1.247 + // Find those files in this module that are actually referred to by 1.248 + // functions' line number data, and assign them source id numbers. 1.249 + // Set the source id numbers for all other files --- unused by the 1.250 + // source line data --- to -1. We do this before writing out the 1.251 + // symbol file, at which point we omit any unused files. 1.252 + void AssignSourceIds(); 1.253 + 1.254 + // Call AssignSourceIds, and write this module to STREAM in the 1.255 +@@ -299,25 +318,28 @@ 1.256 + typedef map<const string *, File *, CompareStringPtrs> FileByNameMap; 1.257 + 1.258 + // A set containing Function structures, sorted by address. 1.259 + typedef set<Function *, FunctionCompare> FunctionSet; 1.260 + 1.261 + // A set containing Extern structures, sorted by address. 1.262 + typedef set<Extern *, ExternCompare> ExternSet; 1.263 + 1.264 ++ // A set containing StackFrameEntry structures, sorted by address. 1.265 ++ typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet; 1.266 ++ 1.267 + // The module owns all the files and functions that have been added 1.268 + // to it; destroying the module frees the Files and Functions these 1.269 + // point to. 1.270 + FileByNameMap files_; // This module's source files. 1.271 + FunctionSet functions_; // This module's functions. 1.272 + 1.273 + // The module owns all the call frame info entries that have been 1.274 + // added to it. 1.275 +- vector<StackFrameEntry *> stack_frame_entries_; 1.276 ++ StackFrameEntrySet stack_frame_entries_; 1.277 + 1.278 + // The module owns all the externs that have been added to it; 1.279 + // destroying the module frees the Externs these point to. 1.280 + ExternSet externs_; 1.281 + }; 1.282 + 1.283 + } // namespace google_breakpad 1.284 + 1.285 +diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc 1.286 +--- a/src/common/module_unittest.cc 1.287 ++++ b/src/common/module_unittest.cc 1.288 +@@ -329,63 +329,63 @@ 1.289 + entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] = 1.290 + "I think I know"; 1.291 + m.AddStackFrameEntry(entry3); 1.292 + 1.293 + // Check that Write writes STACK CFI records properly. 1.294 + m.Write(s, ALL_SYMBOL_DATA); 1.295 + string contents = s.str(); 1.296 + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" 1.297 +- "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n" 1.298 +- "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407" 1.299 +- " .cfa: I think that I shall never see" 1.300 +- " cannoli: a tree whose hungry mouth is prest" 1.301 +- " stromboli: a poem lovely as a tree\n" 1.302 + "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229" 1.303 + " .cfa: Whose woods are these\n" 1.304 + "STACK CFI 36682fad3763ffff" 1.305 + " .cfa: I think I know" 1.306 + " stromboli: his house is in\n" 1.307 + "STACK CFI 47ceb0f63c269d7f" 1.308 + " calzone: the village though" 1.309 +- " cannoli: he will not see me stopping here\n", 1.310 ++ " cannoli: he will not see me stopping here\n" 1.311 ++ "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407" 1.312 ++ " .cfa: I think that I shall never see" 1.313 ++ " cannoli: a tree whose hungry mouth is prest" 1.314 ++ " stromboli: a poem lovely as a tree\n" 1.315 ++ "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n", 1.316 + contents.c_str()); 1.317 + 1.318 + // Check that GetStackFrameEntries works. 1.319 + vector<Module::StackFrameEntry *> entries; 1.320 + m.GetStackFrameEntries(&entries); 1.321 + ASSERT_EQ(3U, entries.size()); 1.322 + // Check first entry. 1.323 +- EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address); 1.324 +- EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size); 1.325 +- ASSERT_EQ(0U, entries[0]->initial_rules.size()); 1.326 +- ASSERT_EQ(0U, entries[0]->rule_changes.size()); 1.327 ++ EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address); 1.328 ++ EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size); 1.329 ++ Module::RuleMap entry1_initial; 1.330 ++ entry1_initial[".cfa"] = "Whose woods are these"; 1.331 ++ EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial)); 1.332 ++ Module::RuleChangeMap entry1_changes; 1.333 ++ entry1_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know"; 1.334 ++ entry1_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in"; 1.335 ++ entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though"; 1.336 ++ entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] = 1.337 ++ "he will not see me stopping here"; 1.338 ++ EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes)); 1.339 + // Check second entry. 1.340 + EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address); 1.341 + EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size); 1.342 + ASSERT_EQ(3U, entries[1]->initial_rules.size()); 1.343 + Module::RuleMap entry2_initial; 1.344 + entry2_initial[".cfa"] = "I think that I shall never see"; 1.345 + entry2_initial["stromboli"] = "a poem lovely as a tree"; 1.346 + entry2_initial["cannoli"] = "a tree whose hungry mouth is prest"; 1.347 + EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial)); 1.348 + ASSERT_EQ(0U, entries[1]->rule_changes.size()); 1.349 + // Check third entry. 1.350 +- EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address); 1.351 +- EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size); 1.352 +- Module::RuleMap entry3_initial; 1.353 +- entry3_initial[".cfa"] = "Whose woods are these"; 1.354 +- EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial)); 1.355 +- Module::RuleChangeMap entry3_changes; 1.356 +- entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know"; 1.357 +- entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in"; 1.358 +- entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though"; 1.359 +- entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] = 1.360 +- "he will not see me stopping here"; 1.361 +- EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes)); 1.362 ++ EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address); 1.363 ++ EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size); 1.364 ++ ASSERT_EQ(0U, entries[2]->initial_rules.size()); 1.365 ++ ASSERT_EQ(0U, entries[2]->rule_changes.size()); 1.366 + } 1.367 + 1.368 + TEST(Construct, UniqueFiles) { 1.369 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.370 + Module::File *file1 = m.FindFile("foo"); 1.371 + Module::File *file2 = m.FindFile(string("bar")); 1.372 + Module::File *file3 = m.FindFile(string("foo")); 1.373 + Module::File *file4 = m.FindFile("bar"); 1.374 +@@ -483,8 +483,155 @@ 1.375 + m.Write(s, ALL_SYMBOL_DATA); 1.376 + string contents = s.str(); 1.377 + 1.378 + EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " 1.379 + MODULE_ID " " MODULE_NAME "\n" 1.380 + "PUBLIC ffff 0 _xyz\n", 1.381 + contents.c_str()); 1.382 + } 1.383 ++ 1.384 ++TEST(Lookup, Function) { 1.385 ++ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.386 ++ 1.387 ++ Module::Function *function1 = new(Module::Function); 1.388 ++ function1->name = "_abc1"; 1.389 ++ function1->address = 0x1000; 1.390 ++ function1->size = 0x900; 1.391 ++ function1->parameter_size = 0x0; 1.392 ++ 1.393 ++ Module::Function *function2 = new(Module::Function); 1.394 ++ function2->name = "_xyz2"; 1.395 ++ function2->address = 0x2000; 1.396 ++ function2->size = 0x900; 1.397 ++ function2->parameter_size = 0x0; 1.398 ++ 1.399 ++ Module::Function *function3 = new(Module::Function); 1.400 ++ function3->name = "_def3"; 1.401 ++ function3->address = 0x3000; 1.402 ++ function3->size = 0x900; 1.403 ++ function3->parameter_size = 0x0; 1.404 ++ 1.405 ++ // Put them in a vector. 1.406 ++ vector<Module::Function *> vec; 1.407 ++ vec.push_back(function1); 1.408 ++ vec.push_back(function2); 1.409 ++ vec.push_back(function3); 1.410 ++ 1.411 ++ m.AddFunctions(vec.begin(), vec.end()); 1.412 ++ 1.413 ++ // Try looking up functions by address. 1.414 ++ Module::Function* f = m.FindFunctionByAddress(0x1000); 1.415 ++ EXPECT_EQ(function1, f); 1.416 ++ f = m.FindFunctionByAddress(0x18FF); 1.417 ++ EXPECT_EQ(function1, f); 1.418 ++ 1.419 ++ f = m.FindFunctionByAddress(0x1900); 1.420 ++ EXPECT_EQ((Module::Function*)NULL, f); 1.421 ++ f = m.FindFunctionByAddress(0x1A00); 1.422 ++ EXPECT_EQ((Module::Function*)NULL, f); 1.423 ++ 1.424 ++ f = m.FindFunctionByAddress(0x2000); 1.425 ++ EXPECT_EQ(function2, f); 1.426 ++ f = m.FindFunctionByAddress(0x28FF); 1.427 ++ EXPECT_EQ(function2, f); 1.428 ++ 1.429 ++ f = m.FindFunctionByAddress(0x3000); 1.430 ++ EXPECT_EQ(function3, f); 1.431 ++ f = m.FindFunctionByAddress(0x38FF); 1.432 ++ EXPECT_EQ(function3, f); 1.433 ++ 1.434 ++ f = m.FindFunctionByAddress(0x3900); 1.435 ++ EXPECT_EQ((Module::Function*)NULL, f); 1.436 ++ f = m.FindFunctionByAddress(0x3A00); 1.437 ++ EXPECT_EQ((Module::Function*)NULL, f); 1.438 ++} 1.439 ++ 1.440 ++TEST(Lookup, Externs) { 1.441 ++ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.442 ++ 1.443 ++ // Two externs. 1.444 ++ Module::Extern* extern1 = new(Module::Extern); 1.445 ++ extern1->address = 0x1000; 1.446 ++ extern1->name = "_abc"; 1.447 ++ Module::Extern* extern2 = new(Module::Extern); 1.448 ++ extern2->address = 0x2000; 1.449 ++ extern2->name = "_xyz"; 1.450 ++ 1.451 ++ m.AddExtern(extern1); 1.452 ++ m.AddExtern(extern2); 1.453 ++ 1.454 ++ Module::Extern* e = m.FindExternByAddress(0xFFF); 1.455 ++ EXPECT_EQ((Module::Extern*)NULL, e); 1.456 ++ 1.457 ++ e = m.FindExternByAddress(0x1000); 1.458 ++ EXPECT_EQ(extern1, e); 1.459 ++ e = m.FindExternByAddress(0x1900); 1.460 ++ EXPECT_EQ(extern1, e); 1.461 ++ e = m.FindExternByAddress(0x1FFF); 1.462 ++ EXPECT_EQ(extern1, e); 1.463 ++ 1.464 ++ e = m.FindExternByAddress(0x2000); 1.465 ++ EXPECT_EQ(extern2, e); 1.466 ++ e = m.FindExternByAddress(0x2900); 1.467 ++ EXPECT_EQ(extern2, e); 1.468 ++ e = m.FindExternByAddress(0xFFFFFFFF); 1.469 ++ EXPECT_EQ(extern2, e); 1.470 ++} 1.471 ++ 1.472 ++TEST(Lookup, StackFrameEntries) { 1.473 ++ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); 1.474 ++ 1.475 ++ // First STACK CFI entry, with no initial rules or deltas. 1.476 ++ Module::StackFrameEntry *entry1 = new Module::StackFrameEntry(); 1.477 ++ entry1->address = 0x2000; 1.478 ++ entry1->size = 0x900; 1.479 ++ m.AddStackFrameEntry(entry1); 1.480 ++ 1.481 ++ // Second STACK CFI entry, with initial rules but no deltas. 1.482 ++ Module::StackFrameEntry *entry2 = new Module::StackFrameEntry(); 1.483 ++ entry2->address = 0x3000; 1.484 ++ entry2->size = 0x900; 1.485 ++ entry2->initial_rules[".cfa"] = "I think that I shall never see"; 1.486 ++ entry2->initial_rules["stromboli"] = "a poem lovely as a tree"; 1.487 ++ entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest"; 1.488 ++ m.AddStackFrameEntry(entry2); 1.489 ++ 1.490 ++ // Third STACK CFI entry, with initial rules and deltas. 1.491 ++ Module::StackFrameEntry *entry3 = new Module::StackFrameEntry(); 1.492 ++ entry3->address = 0x1000; 1.493 ++ entry3->size = 0x900; 1.494 ++ entry3->initial_rules[".cfa"] = "Whose woods are these"; 1.495 ++ entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] = 1.496 ++ "the village though"; 1.497 ++ entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] = 1.498 ++ "he will not see me stopping here"; 1.499 ++ entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] = 1.500 ++ "his house is in"; 1.501 ++ entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] = 1.502 ++ "I think I know"; 1.503 ++ m.AddStackFrameEntry(entry3); 1.504 ++ 1.505 ++ Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000); 1.506 ++ EXPECT_EQ(entry3, s); 1.507 ++ s = m.FindStackFrameEntryByAddress(0x18FF); 1.508 ++ EXPECT_EQ(entry3, s); 1.509 ++ 1.510 ++ s = m.FindStackFrameEntryByAddress(0x1900); 1.511 ++ EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.512 ++ s = m.FindStackFrameEntryByAddress(0x1A00); 1.513 ++ EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.514 ++ 1.515 ++ s = m.FindStackFrameEntryByAddress(0x2000); 1.516 ++ EXPECT_EQ(entry1, s); 1.517 ++ s = m.FindStackFrameEntryByAddress(0x28FF); 1.518 ++ EXPECT_EQ(entry1, s); 1.519 ++ 1.520 ++ s = m.FindStackFrameEntryByAddress(0x3000); 1.521 ++ EXPECT_EQ(entry2, s); 1.522 ++ s = m.FindStackFrameEntryByAddress(0x38FF); 1.523 ++ EXPECT_EQ(entry2, s); 1.524 ++ 1.525 ++ s = m.FindStackFrameEntryByAddress(0x3900); 1.526 ++ EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.527 ++ s = m.FindStackFrameEntryByAddress(0x3A00); 1.528 ++ EXPECT_EQ((Module::StackFrameEntry*)NULL, s); 1.529 ++}