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

changeset 0
6474c204b198
     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 ++}

mercurial