toolkit/crashreporter/breakpad-patches/00-module-api-extras.patch

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 # HG changeset patch
michael@0 2 # User Ted Mielczarek <ted@mielczarek.org>
michael@0 3 # Date 1352220493 18000
michael@0 4 # Node ID c3b1109dd392c16a9fe4e85da693010966dbbf0b
michael@0 5 # Parent 03db269a2868503cca9e80f62ce676aabbf967fd
michael@0 6 Add APIs for querying Module data
michael@0 7 R=glandium at https://breakpad.appspot.com/511003/
michael@0 8
michael@0 9 diff --git a/src/common/module.cc b/src/common/module.cc
michael@0 10 --- a/src/common/module.cc
michael@0 11 +++ b/src/common/module.cc
michael@0 12 @@ -58,17 +58,17 @@
michael@0 13
michael@0 14 Module::~Module() {
michael@0 15 for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
michael@0 16 delete it->second;
michael@0 17 for (FunctionSet::iterator it = functions_.begin();
michael@0 18 it != functions_.end(); ++it) {
michael@0 19 delete *it;
michael@0 20 }
michael@0 21 - for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin();
michael@0 22 + for (StackFrameEntrySet::iterator it = stack_frame_entries_.begin();
michael@0 23 it != stack_frame_entries_.end(); ++it) {
michael@0 24 delete *it;
michael@0 25 }
michael@0 26 for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it)
michael@0 27 delete *it;
michael@0 28 }
michael@0 29
michael@0 30 void Module::SetLoadAddress(Address address) {
michael@0 31 @@ -88,39 +88,84 @@
michael@0 32 }
michael@0 33
michael@0 34 void Module::AddFunctions(vector<Function *>::iterator begin,
michael@0 35 vector<Function *>::iterator end) {
michael@0 36 for (vector<Function *>::iterator it = begin; it != end; ++it)
michael@0 37 AddFunction(*it);
michael@0 38 }
michael@0 39
michael@0 40 -void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) {
michael@0 41 - stack_frame_entries_.push_back(stack_frame_entry);
michael@0 42 +void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) {
michael@0 43 + std::pair<StackFrameEntrySet::iterator,bool> ret =
michael@0 44 + stack_frame_entries_.insert(stack_frame_entry);
michael@0 45 + if (!ret.second) {
michael@0 46 + // Free the duplicate that was not inserted because this Module
michael@0 47 + // now owns it.
michael@0 48 + delete stack_frame_entry;
michael@0 49 + }
michael@0 50 }
michael@0 51
michael@0 52 void Module::AddExtern(Extern *ext) {
michael@0 53 std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext);
michael@0 54 if (!ret.second) {
michael@0 55 // Free the duplicate that was not inserted because this Module
michael@0 56 // now owns it.
michael@0 57 delete ext;
michael@0 58 }
michael@0 59 }
michael@0 60
michael@0 61 void Module::GetFunctions(vector<Function *> *vec,
michael@0 62 vector<Function *>::iterator i) {
michael@0 63 vec->insert(i, functions_.begin(), functions_.end());
michael@0 64 }
michael@0 65
michael@0 66 +template<typename T>
michael@0 67 +bool EntryContainsAddress(T entry, Module::Address address) {
michael@0 68 + return entry->address <= address && address < entry->address + entry->size;
michael@0 69 +}
michael@0 70 +
michael@0 71 +Module::Function* Module::FindFunctionByAddress(Address address) {
michael@0 72 + Function search;
michael@0 73 + search.address = address;
michael@0 74 + // Ensure that name always sorts higher than the function name,
michael@0 75 + // so that upper_bound always returns the function just after
michael@0 76 + // the function containing this address.
michael@0 77 + search.name = "\xFF";
michael@0 78 + FunctionSet::iterator it = functions_.upper_bound(&search);
michael@0 79 + if (it == functions_.begin())
michael@0 80 + return NULL;
michael@0 81 +
michael@0 82 + it--;
michael@0 83 +
michael@0 84 + if (EntryContainsAddress(*it, address))
michael@0 85 + return *it;
michael@0 86 +
michael@0 87 + return NULL;
michael@0 88 +}
michael@0 89 +
michael@0 90 void Module::GetExterns(vector<Extern *> *vec,
michael@0 91 vector<Extern *>::iterator i) {
michael@0 92 vec->insert(i, externs_.begin(), externs_.end());
michael@0 93 }
michael@0 94
michael@0 95 +Module::Extern* Module::FindExternByAddress(Address address) {
michael@0 96 + Extern search;
michael@0 97 + search.address = address;
michael@0 98 + ExternSet::iterator it = externs_.upper_bound(&search);
michael@0 99 +
michael@0 100 + if (it == externs_.begin())
michael@0 101 + return NULL;
michael@0 102 +
michael@0 103 + it--;
michael@0 104 + if ((*it)->address > address)
michael@0 105 + return NULL;
michael@0 106 +
michael@0 107 + return *it;
michael@0 108 +}
michael@0 109 +
michael@0 110 Module::File *Module::FindFile(const string &name) {
michael@0 111 // A tricky bit here. The key of each map entry needs to be a
michael@0 112 // pointer to the entry's File's name string. This means that we
michael@0 113 // can't do the initial lookup with any operation that would create
michael@0 114 // an empty entry for us if the name isn't found (like, say,
michael@0 115 // operator[] or insert do), because such a created entry's key will
michael@0 116 // be a pointer the string passed as our argument. Since the key of
michael@0 117 // a map's value type is const, we can't fix it up once we've
michael@0 118 @@ -150,18 +195,35 @@
michael@0 119 }
michael@0 120
michael@0 121 void Module::GetFiles(vector<File *> *vec) {
michael@0 122 vec->clear();
michael@0 123 for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
michael@0 124 vec->push_back(it->second);
michael@0 125 }
michael@0 126
michael@0 127 -void Module::GetStackFrameEntries(vector<StackFrameEntry *> *vec) {
michael@0 128 - *vec = stack_frame_entries_;
michael@0 129 +void Module::GetStackFrameEntries(vector<StackFrameEntry *>* vec) {
michael@0 130 + vec->clear();
michael@0 131 + vec->insert(vec->begin(), stack_frame_entries_.begin(),
michael@0 132 + stack_frame_entries_.end());
michael@0 133 +}
michael@0 134 +
michael@0 135 +Module::StackFrameEntry* Module::FindStackFrameEntryByAddress(Address address) {
michael@0 136 + StackFrameEntry search;
michael@0 137 + search.address = address;
michael@0 138 + StackFrameEntrySet::iterator it = stack_frame_entries_.upper_bound(&search);
michael@0 139 +
michael@0 140 + if (it == stack_frame_entries_.begin())
michael@0 141 + return NULL;
michael@0 142 +
michael@0 143 + it--;
michael@0 144 + if (EntryContainsAddress(*it, address))
michael@0 145 + return *it;
michael@0 146 +
michael@0 147 + return NULL;
michael@0 148 }
michael@0 149
michael@0 150 void Module::AssignSourceIds() {
michael@0 151 // First, give every source file an id of -1.
michael@0 152 for (FileByNameMap::iterator file_it = files_.begin();
michael@0 153 file_it != files_.end(); ++file_it) {
michael@0 154 file_it->second->source_id = -1;
michael@0 155 }
michael@0 156 @@ -256,17 +318,17 @@
michael@0 157 stream << "PUBLIC " << hex
michael@0 158 << (ext->address - load_address_) << " 0 "
michael@0 159 << ext->name << dec << endl;
michael@0 160 }
michael@0 161 }
michael@0 162
michael@0 163 if (symbol_data != NO_CFI) {
michael@0 164 // Write out 'STACK CFI INIT' and 'STACK CFI' records.
michael@0 165 - vector<StackFrameEntry *>::const_iterator frame_it;
michael@0 166 + StackFrameEntrySet::const_iterator frame_it;
michael@0 167 for (frame_it = stack_frame_entries_.begin();
michael@0 168 frame_it != stack_frame_entries_.end(); ++frame_it) {
michael@0 169 StackFrameEntry *entry = *frame_it;
michael@0 170 stream << "STACK CFI INIT " << hex
michael@0 171 << (entry->address - load_address_) << " "
michael@0 172 << entry->size << " " << dec;
michael@0 173 if (!stream.good()
michael@0 174 || !WriteRuleMap(entry->initial_rules, stream))
michael@0 175 diff --git a/src/common/module.h b/src/common/module.h
michael@0 176 --- a/src/common/module.h
michael@0 177 +++ b/src/common/module.h
michael@0 178 @@ -164,16 +164,23 @@
michael@0 179
michael@0 180 struct ExternCompare {
michael@0 181 bool operator() (const Extern *lhs,
michael@0 182 const Extern *rhs) const {
michael@0 183 return lhs->address < rhs->address;
michael@0 184 }
michael@0 185 };
michael@0 186
michael@0 187 + struct StackFrameEntryCompare {
michael@0 188 + bool operator() (const StackFrameEntry* lhs,
michael@0 189 + const StackFrameEntry* rhs) const {
michael@0 190 + return lhs->address < rhs->address;
michael@0 191 + }
michael@0 192 + };
michael@0 193 +
michael@0 194 // Create a new module with the given name, operating system,
michael@0 195 // architecture, and ID string.
michael@0 196 Module(const string &name, const string &os, const string &architecture,
michael@0 197 const string &id);
michael@0 198 ~Module();
michael@0 199
michael@0 200 // Set the module's load address to LOAD_ADDRESS; addresses given
michael@0 201 // for functions and lines will be written to the Breakpad symbol
michael@0 202 @@ -223,37 +230,49 @@
michael@0 203
michael@0 204 // Insert pointers to the functions added to this module at I in
michael@0 205 // VEC. The pointed-to Functions are still owned by this module.
michael@0 206 // (Since this is effectively a copy of the function list, this is
michael@0 207 // mostly useful for testing; other uses should probably get a more
michael@0 208 // appropriate interface.)
michael@0 209 void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
michael@0 210
michael@0 211 + // If this module has a function at ADDRESS, return a pointer to it.
michael@0 212 + // Otherwise, return NULL.
michael@0 213 + Function* FindFunctionByAddress(Address address);
michael@0 214 +
michael@0 215 // Insert pointers to the externs added to this module at I in
michael@0 216 // VEC. The pointed-to Externs are still owned by this module.
michael@0 217 // (Since this is effectively a copy of the extern list, this is
michael@0 218 // mostly useful for testing; other uses should probably get a more
michael@0 219 // appropriate interface.)
michael@0 220 void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
michael@0 221
michael@0 222 + // If this module has an extern whose base address is less than ADDRESS,
michael@0 223 + // return a pointer to it. Otherwise, return NULL.
michael@0 224 + Extern* FindExternByAddress(Address address);
michael@0 225 +
michael@0 226 // Clear VEC and fill it with pointers to the Files added to this
michael@0 227 // module, sorted by name. The pointed-to Files are still owned by
michael@0 228 // this module. (Since this is effectively a copy of the file list,
michael@0 229 // this is mostly useful for testing; other uses should probably get
michael@0 230 // a more appropriate interface.)
michael@0 231 void GetFiles(vector<File *> *vec);
michael@0 232
michael@0 233 // Clear VEC and fill it with pointers to the StackFrameEntry
michael@0 234 // objects that have been added to this module. (Since this is
michael@0 235 // effectively a copy of the stack frame entry list, this is mostly
michael@0 236 // useful for testing; other uses should probably get
michael@0 237 // a more appropriate interface.)
michael@0 238 void GetStackFrameEntries(vector<StackFrameEntry *> *vec);
michael@0 239
michael@0 240 + // If this module has a StackFrameEntry whose address range covers
michael@0 241 + // ADDRESS, return it. Otherwise return NULL.
michael@0 242 + StackFrameEntry* FindStackFrameEntryByAddress(Address address);
michael@0 243 +
michael@0 244 // Find those files in this module that are actually referred to by
michael@0 245 // functions' line number data, and assign them source id numbers.
michael@0 246 // Set the source id numbers for all other files --- unused by the
michael@0 247 // source line data --- to -1. We do this before writing out the
michael@0 248 // symbol file, at which point we omit any unused files.
michael@0 249 void AssignSourceIds();
michael@0 250
michael@0 251 // Call AssignSourceIds, and write this module to STREAM in the
michael@0 252 @@ -299,25 +318,28 @@
michael@0 253 typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
michael@0 254
michael@0 255 // A set containing Function structures, sorted by address.
michael@0 256 typedef set<Function *, FunctionCompare> FunctionSet;
michael@0 257
michael@0 258 // A set containing Extern structures, sorted by address.
michael@0 259 typedef set<Extern *, ExternCompare> ExternSet;
michael@0 260
michael@0 261 + // A set containing StackFrameEntry structures, sorted by address.
michael@0 262 + typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet;
michael@0 263 +
michael@0 264 // The module owns all the files and functions that have been added
michael@0 265 // to it; destroying the module frees the Files and Functions these
michael@0 266 // point to.
michael@0 267 FileByNameMap files_; // This module's source files.
michael@0 268 FunctionSet functions_; // This module's functions.
michael@0 269
michael@0 270 // The module owns all the call frame info entries that have been
michael@0 271 // added to it.
michael@0 272 - vector<StackFrameEntry *> stack_frame_entries_;
michael@0 273 + StackFrameEntrySet stack_frame_entries_;
michael@0 274
michael@0 275 // The module owns all the externs that have been added to it;
michael@0 276 // destroying the module frees the Externs these point to.
michael@0 277 ExternSet externs_;
michael@0 278 };
michael@0 279
michael@0 280 } // namespace google_breakpad
michael@0 281
michael@0 282 diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
michael@0 283 --- a/src/common/module_unittest.cc
michael@0 284 +++ b/src/common/module_unittest.cc
michael@0 285 @@ -329,63 +329,63 @@
michael@0 286 entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
michael@0 287 "I think I know";
michael@0 288 m.AddStackFrameEntry(entry3);
michael@0 289
michael@0 290 // Check that Write writes STACK CFI records properly.
michael@0 291 m.Write(s, ALL_SYMBOL_DATA);
michael@0 292 string contents = s.str();
michael@0 293 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
michael@0 294 - "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n"
michael@0 295 - "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
michael@0 296 - " .cfa: I think that I shall never see"
michael@0 297 - " cannoli: a tree whose hungry mouth is prest"
michael@0 298 - " stromboli: a poem lovely as a tree\n"
michael@0 299 "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
michael@0 300 " .cfa: Whose woods are these\n"
michael@0 301 "STACK CFI 36682fad3763ffff"
michael@0 302 " .cfa: I think I know"
michael@0 303 " stromboli: his house is in\n"
michael@0 304 "STACK CFI 47ceb0f63c269d7f"
michael@0 305 " calzone: the village though"
michael@0 306 - " cannoli: he will not see me stopping here\n",
michael@0 307 + " cannoli: he will not see me stopping here\n"
michael@0 308 + "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
michael@0 309 + " .cfa: I think that I shall never see"
michael@0 310 + " cannoli: a tree whose hungry mouth is prest"
michael@0 311 + " stromboli: a poem lovely as a tree\n"
michael@0 312 + "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n",
michael@0 313 contents.c_str());
michael@0 314
michael@0 315 // Check that GetStackFrameEntries works.
michael@0 316 vector<Module::StackFrameEntry *> entries;
michael@0 317 m.GetStackFrameEntries(&entries);
michael@0 318 ASSERT_EQ(3U, entries.size());
michael@0 319 // Check first entry.
michael@0 320 - EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address);
michael@0 321 - EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size);
michael@0 322 - ASSERT_EQ(0U, entries[0]->initial_rules.size());
michael@0 323 - ASSERT_EQ(0U, entries[0]->rule_changes.size());
michael@0 324 + EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address);
michael@0 325 + EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size);
michael@0 326 + Module::RuleMap entry1_initial;
michael@0 327 + entry1_initial[".cfa"] = "Whose woods are these";
michael@0 328 + EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial));
michael@0 329 + Module::RuleChangeMap entry1_changes;
michael@0 330 + entry1_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
michael@0 331 + entry1_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
michael@0 332 + entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
michael@0 333 + entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
michael@0 334 + "he will not see me stopping here";
michael@0 335 + EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes));
michael@0 336 // Check second entry.
michael@0 337 EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
michael@0 338 EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
michael@0 339 ASSERT_EQ(3U, entries[1]->initial_rules.size());
michael@0 340 Module::RuleMap entry2_initial;
michael@0 341 entry2_initial[".cfa"] = "I think that I shall never see";
michael@0 342 entry2_initial["stromboli"] = "a poem lovely as a tree";
michael@0 343 entry2_initial["cannoli"] = "a tree whose hungry mouth is prest";
michael@0 344 EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
michael@0 345 ASSERT_EQ(0U, entries[1]->rule_changes.size());
michael@0 346 // Check third entry.
michael@0 347 - EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address);
michael@0 348 - EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size);
michael@0 349 - Module::RuleMap entry3_initial;
michael@0 350 - entry3_initial[".cfa"] = "Whose woods are these";
michael@0 351 - EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial));
michael@0 352 - Module::RuleChangeMap entry3_changes;
michael@0 353 - entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
michael@0 354 - entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
michael@0 355 - entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
michael@0 356 - entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
michael@0 357 - "he will not see me stopping here";
michael@0 358 - EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes));
michael@0 359 + EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address);
michael@0 360 + EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size);
michael@0 361 + ASSERT_EQ(0U, entries[2]->initial_rules.size());
michael@0 362 + ASSERT_EQ(0U, entries[2]->rule_changes.size());
michael@0 363 }
michael@0 364
michael@0 365 TEST(Construct, UniqueFiles) {
michael@0 366 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
michael@0 367 Module::File *file1 = m.FindFile("foo");
michael@0 368 Module::File *file2 = m.FindFile(string("bar"));
michael@0 369 Module::File *file3 = m.FindFile(string("foo"));
michael@0 370 Module::File *file4 = m.FindFile("bar");
michael@0 371 @@ -483,8 +483,155 @@
michael@0 372 m.Write(s, ALL_SYMBOL_DATA);
michael@0 373 string contents = s.str();
michael@0 374
michael@0 375 EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
michael@0 376 MODULE_ID " " MODULE_NAME "\n"
michael@0 377 "PUBLIC ffff 0 _xyz\n",
michael@0 378 contents.c_str());
michael@0 379 }
michael@0 380 +
michael@0 381 +TEST(Lookup, Function) {
michael@0 382 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
michael@0 383 +
michael@0 384 + Module::Function *function1 = new(Module::Function);
michael@0 385 + function1->name = "_abc1";
michael@0 386 + function1->address = 0x1000;
michael@0 387 + function1->size = 0x900;
michael@0 388 + function1->parameter_size = 0x0;
michael@0 389 +
michael@0 390 + Module::Function *function2 = new(Module::Function);
michael@0 391 + function2->name = "_xyz2";
michael@0 392 + function2->address = 0x2000;
michael@0 393 + function2->size = 0x900;
michael@0 394 + function2->parameter_size = 0x0;
michael@0 395 +
michael@0 396 + Module::Function *function3 = new(Module::Function);
michael@0 397 + function3->name = "_def3";
michael@0 398 + function3->address = 0x3000;
michael@0 399 + function3->size = 0x900;
michael@0 400 + function3->parameter_size = 0x0;
michael@0 401 +
michael@0 402 + // Put them in a vector.
michael@0 403 + vector<Module::Function *> vec;
michael@0 404 + vec.push_back(function1);
michael@0 405 + vec.push_back(function2);
michael@0 406 + vec.push_back(function3);
michael@0 407 +
michael@0 408 + m.AddFunctions(vec.begin(), vec.end());
michael@0 409 +
michael@0 410 + // Try looking up functions by address.
michael@0 411 + Module::Function* f = m.FindFunctionByAddress(0x1000);
michael@0 412 + EXPECT_EQ(function1, f);
michael@0 413 + f = m.FindFunctionByAddress(0x18FF);
michael@0 414 + EXPECT_EQ(function1, f);
michael@0 415 +
michael@0 416 + f = m.FindFunctionByAddress(0x1900);
michael@0 417 + EXPECT_EQ((Module::Function*)NULL, f);
michael@0 418 + f = m.FindFunctionByAddress(0x1A00);
michael@0 419 + EXPECT_EQ((Module::Function*)NULL, f);
michael@0 420 +
michael@0 421 + f = m.FindFunctionByAddress(0x2000);
michael@0 422 + EXPECT_EQ(function2, f);
michael@0 423 + f = m.FindFunctionByAddress(0x28FF);
michael@0 424 + EXPECT_EQ(function2, f);
michael@0 425 +
michael@0 426 + f = m.FindFunctionByAddress(0x3000);
michael@0 427 + EXPECT_EQ(function3, f);
michael@0 428 + f = m.FindFunctionByAddress(0x38FF);
michael@0 429 + EXPECT_EQ(function3, f);
michael@0 430 +
michael@0 431 + f = m.FindFunctionByAddress(0x3900);
michael@0 432 + EXPECT_EQ((Module::Function*)NULL, f);
michael@0 433 + f = m.FindFunctionByAddress(0x3A00);
michael@0 434 + EXPECT_EQ((Module::Function*)NULL, f);
michael@0 435 +}
michael@0 436 +
michael@0 437 +TEST(Lookup, Externs) {
michael@0 438 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
michael@0 439 +
michael@0 440 + // Two externs.
michael@0 441 + Module::Extern* extern1 = new(Module::Extern);
michael@0 442 + extern1->address = 0x1000;
michael@0 443 + extern1->name = "_abc";
michael@0 444 + Module::Extern* extern2 = new(Module::Extern);
michael@0 445 + extern2->address = 0x2000;
michael@0 446 + extern2->name = "_xyz";
michael@0 447 +
michael@0 448 + m.AddExtern(extern1);
michael@0 449 + m.AddExtern(extern2);
michael@0 450 +
michael@0 451 + Module::Extern* e = m.FindExternByAddress(0xFFF);
michael@0 452 + EXPECT_EQ((Module::Extern*)NULL, e);
michael@0 453 +
michael@0 454 + e = m.FindExternByAddress(0x1000);
michael@0 455 + EXPECT_EQ(extern1, e);
michael@0 456 + e = m.FindExternByAddress(0x1900);
michael@0 457 + EXPECT_EQ(extern1, e);
michael@0 458 + e = m.FindExternByAddress(0x1FFF);
michael@0 459 + EXPECT_EQ(extern1, e);
michael@0 460 +
michael@0 461 + e = m.FindExternByAddress(0x2000);
michael@0 462 + EXPECT_EQ(extern2, e);
michael@0 463 + e = m.FindExternByAddress(0x2900);
michael@0 464 + EXPECT_EQ(extern2, e);
michael@0 465 + e = m.FindExternByAddress(0xFFFFFFFF);
michael@0 466 + EXPECT_EQ(extern2, e);
michael@0 467 +}
michael@0 468 +
michael@0 469 +TEST(Lookup, StackFrameEntries) {
michael@0 470 + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
michael@0 471 +
michael@0 472 + // First STACK CFI entry, with no initial rules or deltas.
michael@0 473 + Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
michael@0 474 + entry1->address = 0x2000;
michael@0 475 + entry1->size = 0x900;
michael@0 476 + m.AddStackFrameEntry(entry1);
michael@0 477 +
michael@0 478 + // Second STACK CFI entry, with initial rules but no deltas.
michael@0 479 + Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
michael@0 480 + entry2->address = 0x3000;
michael@0 481 + entry2->size = 0x900;
michael@0 482 + entry2->initial_rules[".cfa"] = "I think that I shall never see";
michael@0 483 + entry2->initial_rules["stromboli"] = "a poem lovely as a tree";
michael@0 484 + entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest";
michael@0 485 + m.AddStackFrameEntry(entry2);
michael@0 486 +
michael@0 487 + // Third STACK CFI entry, with initial rules and deltas.
michael@0 488 + Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
michael@0 489 + entry3->address = 0x1000;
michael@0 490 + entry3->size = 0x900;
michael@0 491 + entry3->initial_rules[".cfa"] = "Whose woods are these";
michael@0 492 + entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
michael@0 493 + "the village though";
michael@0 494 + entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
michael@0 495 + "he will not see me stopping here";
michael@0 496 + entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
michael@0 497 + "his house is in";
michael@0 498 + entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
michael@0 499 + "I think I know";
michael@0 500 + m.AddStackFrameEntry(entry3);
michael@0 501 +
michael@0 502 + Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000);
michael@0 503 + EXPECT_EQ(entry3, s);
michael@0 504 + s = m.FindStackFrameEntryByAddress(0x18FF);
michael@0 505 + EXPECT_EQ(entry3, s);
michael@0 506 +
michael@0 507 + s = m.FindStackFrameEntryByAddress(0x1900);
michael@0 508 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
michael@0 509 + s = m.FindStackFrameEntryByAddress(0x1A00);
michael@0 510 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
michael@0 511 +
michael@0 512 + s = m.FindStackFrameEntryByAddress(0x2000);
michael@0 513 + EXPECT_EQ(entry1, s);
michael@0 514 + s = m.FindStackFrameEntryByAddress(0x28FF);
michael@0 515 + EXPECT_EQ(entry1, s);
michael@0 516 +
michael@0 517 + s = m.FindStackFrameEntryByAddress(0x3000);
michael@0 518 + EXPECT_EQ(entry2, s);
michael@0 519 + s = m.FindStackFrameEntryByAddress(0x38FF);
michael@0 520 + EXPECT_EQ(entry2, s);
michael@0 521 +
michael@0 522 + s = m.FindStackFrameEntryByAddress(0x3900);
michael@0 523 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
michael@0 524 + s = m.FindStackFrameEntryByAddress(0x3A00);
michael@0 525 + EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
michael@0 526 +}

mercurial