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