Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 | +} |