toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:54fb6080fdff
1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31
32 // module_unittest.cc: Unit tests for google_breakpad::Module.
33
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include <algorithm>
40 #include <sstream>
41 #include <string>
42
43 #include "breakpad_googletest_includes.h"
44 #include "common/module.h"
45 #include "common/using_std_string.h"
46
47 using google_breakpad::Module;
48 using google_breakpad::ToUniqueString;
49 using google_breakpad::ustr__ZDcfa;
50 using std::stringstream;
51 using std::vector;
52 using testing::ContainerEq;
53
54 static Module::Function *generate_duplicate_function(const string &name) {
55 const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL;
56 const Module::Address DUP_SIZE = 0x200b26e605f99071LL;
57 const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
58
59 Module::Function *function = new(Module::Function);
60 function->name = name;
61 function->address = DUP_ADDRESS;
62 function->size = DUP_SIZE;
63 function->parameter_size = DUP_PARAMETER_SIZE;
64 return function;
65 }
66
67 #define MODULE_NAME "name with spaces"
68 #define MODULE_OS "os-name"
69 #define MODULE_ARCH "architecture"
70 #define MODULE_ID "id-string"
71
72 TEST(Write, Header) {
73 stringstream s;
74 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
75 m.Write(s, ALL_SYMBOL_DATA);
76 string contents = s.str();
77 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n",
78 contents.c_str());
79 }
80
81 TEST(Write, OneLineFunc) {
82 stringstream s;
83 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
84
85 Module::File *file = m.FindFile("file_name.cc");
86 Module::Function *function = new(Module::Function);
87 function->name = "function_name";
88 function->address = 0xe165bf8023b9d9abLL;
89 function->size = 0x1e4bb0eb1cbf5b09LL;
90 function->parameter_size = 0x772beee89114358aLL;
91 Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL,
92 file, 67519080 };
93 function->lines.push_back(line);
94 m.AddFunction(function);
95
96 m.Write(s, ALL_SYMBOL_DATA);
97 string contents = s.str();
98 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
99 "FILE 0 file_name.cc\n"
100 "FUNC e165bf8023b9d9ab 1e4bb0eb1cbf5b09 772beee89114358a"
101 " function_name\n"
102 "e165bf8023b9d9ab 1e4bb0eb1cbf5b09 67519080 0\n",
103 contents.c_str());
104 }
105
106 TEST(Write, RelativeLoadAddress) {
107 stringstream s;
108 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
109
110 // Some source files. We will expect to see them in lexicographic order.
111 Module::File *file1 = m.FindFile("filename-b.cc");
112 Module::File *file2 = m.FindFile("filename-a.cc");
113
114 // A function.
115 Module::Function *function = new(Module::Function);
116 function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)";
117 function->address = 0xbec774ea5dd935f3LL;
118 function->size = 0x2922088f98d3f6fcLL;
119 function->parameter_size = 0xe5e9aa008bd5f0d0LL;
120
121 // Some source lines. The module should not sort these.
122 Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
123 file1, 41676901 };
124 Module::Line line2 = { 0xdaf35bc123885c04LL, 0xcf621b8d324d0ebLL,
125 file2, 67519080 };
126 function->lines.push_back(line2);
127 function->lines.push_back(line1);
128
129 m.AddFunction(function);
130
131 // Some stack information.
132 Module::StackFrameEntry *entry = new Module::StackFrameEntry();
133 entry->address = 0x30f9e5c83323973dULL;
134 entry->size = 0x49fc9ca7c7c13dc2ULL;
135 entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man");
136 entry->initial_rules[ToUniqueString("and")] =
137 Module::Expr("what i want to know is");
138 entry->initial_rules[ToUniqueString("stallion")] =
139 Module::Expr(ToUniqueString("and break"), 8, false);
140 entry->initial_rules[ToUniqueString("onetwothreefourfive")] =
141 Module::Expr(ToUniqueString("pigeonsjustlikethat"), 42, true);
142 entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] =
143 Module::Expr("do you like your blueeyed boy");
144 entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] =
145 Module::Expr("Death");
146 m.AddStackFrameEntry(entry);
147
148 // Set the load address. Doing this after adding all the data to
149 // the module must work fine.
150 m.SetLoadAddress(0x2ab698b0b6407073LL);
151
152 m.Write(s, ALL_SYMBOL_DATA);
153 string contents = s.str();
154 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
155 "FILE 0 filename-a.cc\n"
156 "FILE 1 filename-b.cc\n"
157 "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
158 " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
159 "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n"
160 "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n"
161 "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2"
162 " .cfa: he was a handsome man"
163 " and: what i want to know is"
164 " onetwothreefourfive: pigeonsjustlikethat 42 + ^"
165 " stallion: and break 8 +\n"
166 "STACK CFI 6434d177ce326cb"
167 " Mister: Death"
168 " how: do you like your blueeyed boy\n",
169 contents.c_str());
170 }
171
172 TEST(Write, OmitUnusedFiles) {
173 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
174
175 // Create some source files.
176 Module::File *file1 = m.FindFile("filename1");
177 m.FindFile("filename2"); // not used by any line
178 Module::File *file3 = m.FindFile("filename3");
179
180 // Create a function.
181 Module::Function *function = new(Module::Function);
182 function->name = "function_name";
183 function->address = 0x9b926d464f0b9384LL;
184 function->size = 0x4f524a4ba795e6a6LL;
185 function->parameter_size = 0xbbe8133a6641c9b7LL;
186
187 // Source files that refer to some files, but not others.
188 Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL,
189 file1, 137850127 };
190 Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL,
191 file3, 28113549 };
192 function->lines.push_back(line1);
193 function->lines.push_back(line2);
194 m.AddFunction(function);
195
196 m.AssignSourceIds();
197
198 vector<Module::File *> vec;
199 m.GetFiles(&vec);
200 EXPECT_EQ((size_t) 3, vec.size());
201 EXPECT_STREQ("filename1", vec[0]->name.c_str());
202 EXPECT_NE(-1, vec[0]->source_id);
203 // Expect filename2 not to be used.
204 EXPECT_STREQ("filename2", vec[1]->name.c_str());
205 EXPECT_EQ(-1, vec[1]->source_id);
206 EXPECT_STREQ("filename3", vec[2]->name.c_str());
207 EXPECT_NE(-1, vec[2]->source_id);
208
209 stringstream s;
210 m.Write(s, ALL_SYMBOL_DATA);
211 string contents = s.str();
212 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
213 "FILE 0 filename1\n"
214 "FILE 1 filename3\n"
215 "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7"
216 " function_name\n"
217 "595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n"
218 "401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n",
219 contents.c_str());
220 }
221
222 TEST(Write, NoCFI) {
223 stringstream s;
224 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
225
226 // Some source files. We will expect to see them in lexicographic order.
227 Module::File *file1 = m.FindFile("filename.cc");
228
229 // A function.
230 Module::Function *function = new(Module::Function);
231 function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)";
232 function->address = 0xbec774ea5dd935f3LL;
233 function->size = 0x2922088f98d3f6fcLL;
234 function->parameter_size = 0xe5e9aa008bd5f0d0LL;
235
236 // Some source lines. The module should not sort these.
237 Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
238 file1, 41676901 };
239 function->lines.push_back(line1);
240
241 m.AddFunction(function);
242
243 // Some stack information.
244 Module::StackFrameEntry *entry = new Module::StackFrameEntry();
245 entry->address = 0x30f9e5c83323973dULL;
246 entry->size = 0x49fc9ca7c7c13dc2ULL;
247 entry->initial_rules[ustr__ZDcfa()] = Module::Expr("he was a handsome man");
248 entry->initial_rules[ToUniqueString("and")] =
249 Module::Expr("what i want to know is");
250 entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("how")] =
251 Module::Expr("do you like your blueeyed boy");
252 entry->rule_changes[0x30f9e5c83323973eULL][ToUniqueString("Mister")] =
253 Module::Expr("Death");
254 m.AddStackFrameEntry(entry);
255
256 // Set the load address. Doing this after adding all the data to
257 // the module must work fine.
258 m.SetLoadAddress(0x2ab698b0b6407073LL);
259
260 m.Write(s, NO_CFI);
261 string contents = s.str();
262 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
263 "FILE 0 filename.cc\n"
264 "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
265 " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
266 "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n",
267 contents.c_str());
268 }
269
270 TEST(Construct, AddFunctions) {
271 stringstream s;
272 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
273
274 // Two functions.
275 Module::Function *function1 = new(Module::Function);
276 function1->name = "_without_form";
277 function1->address = 0xd35024aa7ca7da5cLL;
278 function1->size = 0x200b26e605f99071LL;
279 function1->parameter_size = 0xf14ac4fed48c4a99LL;
280
281 Module::Function *function2 = new(Module::Function);
282 function2->name = "_and_void";
283 function2->address = 0x2987743d0b35b13fLL;
284 function2->size = 0xb369db048deb3010LL;
285 function2->parameter_size = 0x938e556cb5a79988LL;
286
287 // Put them in a vector.
288 vector<Module::Function *> vec;
289 vec.push_back(function1);
290 vec.push_back(function2);
291
292 m.AddFunctions(vec.begin(), vec.end());
293
294 m.Write(s, ALL_SYMBOL_DATA);
295 string contents = s.str();
296 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
297 "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988"
298 " _and_void\n"
299 "FUNC d35024aa7ca7da5c 200b26e605f99071 f14ac4fed48c4a99"
300 " _without_form\n",
301 contents.c_str());
302
303 // Check that m.GetFunctions returns the functions we expect.
304 vec.clear();
305 m.GetFunctions(&vec, vec.end());
306 EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function1));
307 EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function2));
308 EXPECT_EQ((size_t) 2, vec.size());
309 }
310
311 TEST(Construct, AddFrames) {
312 stringstream s;
313 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
314
315 // First STACK CFI entry, with no initial rules or deltas.
316 Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
317 entry1->address = 0xddb5f41285aa7757ULL;
318 entry1->size = 0x1486493370dc5073ULL;
319 m.AddStackFrameEntry(entry1);
320
321 // Second STACK CFI entry, with initial rules but no deltas.
322 Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
323 entry2->address = 0x8064f3af5e067e38ULL;
324 entry2->size = 0x0de2a5ee55509407ULL;
325 entry2->initial_rules[ustr__ZDcfa()] =
326 Module::Expr("I think that I shall never see");
327 entry2->initial_rules[ToUniqueString("stromboli")] =
328 Module::Expr("a poem lovely as a tree");
329 entry2->initial_rules[ToUniqueString("cannoli")] =
330 Module::Expr("a tree whose hungry mouth is prest");
331 m.AddStackFrameEntry(entry2);
332
333 // Third STACK CFI entry, with initial rules and deltas.
334 Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
335 entry3->address = 0x5e8d0db0a7075c6cULL;
336 entry3->size = 0x1c7edb12a7aea229ULL;
337 entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
338 entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
339 Module::Expr("the village though");
340 entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
341 Module::Expr("he will not see me stopping here");
342 entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
343 Module::Expr("his house is in");
344 entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
345 Module::Expr("I think I know");
346 m.AddStackFrameEntry(entry3);
347
348 // Check that Write writes STACK CFI records properly.
349 m.Write(s, ALL_SYMBOL_DATA);
350 string contents = s.str();
351 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
352 "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
353 " .cfa: Whose woods are these\n"
354 "STACK CFI 36682fad3763ffff"
355 " .cfa: I think I know"
356 " stromboli: his house is in\n"
357 "STACK CFI 47ceb0f63c269d7f"
358 " calzone: the village though"
359 " cannoli: he will not see me stopping here\n"
360 "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
361 " .cfa: I think that I shall never see"
362 " cannoli: a tree whose hungry mouth is prest"
363 " stromboli: a poem lovely as a tree\n"
364 "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n",
365 contents.c_str());
366
367 // Check that GetStackFrameEntries works.
368 vector<Module::StackFrameEntry *> entries;
369 m.GetStackFrameEntries(&entries);
370 ASSERT_EQ(3U, entries.size());
371 // Check first entry.
372 EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address);
373 EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size);
374 Module::RuleMap entry1_initial;
375 entry1_initial[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
376 EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial));
377 Module::RuleChangeMap entry1_changes;
378 entry1_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
379 Module::Expr("I think I know");
380 entry1_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
381 Module::Expr("his house is in");
382 entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
383 Module::Expr("the village though");
384 entry1_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
385 Module::Expr("he will not see me stopping here");
386 EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes));
387 // Check second entry.
388 EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
389 EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
390 ASSERT_EQ(3U, entries[1]->initial_rules.size());
391 Module::RuleMap entry2_initial;
392 entry2_initial[ustr__ZDcfa()] =
393 Module::Expr("I think that I shall never see");
394 entry2_initial[ToUniqueString("stromboli")] =
395 Module::Expr("a poem lovely as a tree");
396 entry2_initial[ToUniqueString("cannoli")] =
397 Module::Expr("a tree whose hungry mouth is prest");
398 EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
399 ASSERT_EQ(0U, entries[1]->rule_changes.size());
400 // Check third entry.
401 EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address);
402 EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size);
403 ASSERT_EQ(0U, entries[2]->initial_rules.size());
404 ASSERT_EQ(0U, entries[2]->rule_changes.size());
405 }
406
407 TEST(Construct, UniqueFiles) {
408 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
409 Module::File *file1 = m.FindFile("foo");
410 Module::File *file2 = m.FindFile(string("bar"));
411 Module::File *file3 = m.FindFile(string("foo"));
412 Module::File *file4 = m.FindFile("bar");
413 EXPECT_NE(file1, file2);
414 EXPECT_EQ(file1, file3);
415 EXPECT_EQ(file2, file4);
416 EXPECT_EQ(file1, m.FindExistingFile("foo"));
417 EXPECT_TRUE(m.FindExistingFile("baz") == NULL);
418 }
419
420 TEST(Construct, DuplicateFunctions) {
421 stringstream s;
422 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
423
424 // Two functions.
425 Module::Function *function1 = generate_duplicate_function("_without_form");
426 Module::Function *function2 = generate_duplicate_function("_without_form");
427
428 m.AddFunction(function1);
429 m.AddFunction(function2);
430
431 m.Write(s, ALL_SYMBOL_DATA);
432 string contents = s.str();
433 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
434 "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
435 " _without_form\n",
436 contents.c_str());
437 }
438
439 TEST(Construct, FunctionsWithSameAddress) {
440 stringstream s;
441 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
442
443 // Two functions.
444 Module::Function *function1 = generate_duplicate_function("_without_form");
445 Module::Function *function2 = generate_duplicate_function("_and_void");
446
447 m.AddFunction(function1);
448 m.AddFunction(function2);
449
450 m.Write(s, ALL_SYMBOL_DATA);
451 string contents = s.str();
452 EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
453 "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
454 " _and_void\n"
455 "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
456 " _without_form\n",
457 contents.c_str());
458 }
459
460 // Externs should be written out as PUBLIC records, sorted by
461 // address.
462 TEST(Construct, Externs) {
463 stringstream s;
464 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
465
466 // Two externs.
467 Module::Extern *extern1 = new(Module::Extern);
468 extern1->address = 0xffff;
469 extern1->name = "_abc";
470 Module::Extern *extern2 = new(Module::Extern);
471 extern2->address = 0xaaaa;
472 extern2->name = "_xyz";
473
474 m.AddExtern(extern1);
475 m.AddExtern(extern2);
476
477 m.Write(s, ALL_SYMBOL_DATA);
478 string contents = s.str();
479
480 EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
481 MODULE_ID " " MODULE_NAME "\n"
482 "PUBLIC aaaa 0 _xyz\n"
483 "PUBLIC ffff 0 _abc\n",
484 contents.c_str());
485 }
486
487 // Externs with the same address should only keep the first entry
488 // added.
489 TEST(Construct, DuplicateExterns) {
490 stringstream s;
491 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
492
493 // Two externs.
494 Module::Extern *extern1 = new(Module::Extern);
495 extern1->address = 0xffff;
496 extern1->name = "_xyz";
497 Module::Extern *extern2 = new(Module::Extern);
498 extern2->address = 0xffff;
499 extern2->name = "_abc";
500
501 m.AddExtern(extern1);
502 m.AddExtern(extern2);
503
504 m.Write(s, ALL_SYMBOL_DATA);
505 string contents = s.str();
506
507 EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
508 MODULE_ID " " MODULE_NAME "\n"
509 "PUBLIC ffff 0 _xyz\n",
510 contents.c_str());
511 }
512
513 TEST(Lookup, Function) {
514 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
515
516 Module::Function *function1 = new(Module::Function);
517 function1->name = "_abc1";
518 function1->address = 0x1000;
519 function1->size = 0x900;
520 function1->parameter_size = 0x0;
521
522 Module::Function *function2 = new(Module::Function);
523 function2->name = "_xyz2";
524 function2->address = 0x2000;
525 function2->size = 0x900;
526 function2->parameter_size = 0x0;
527
528 Module::Function *function3 = new(Module::Function);
529 function3->name = "_def3";
530 function3->address = 0x3000;
531 function3->size = 0x900;
532 function3->parameter_size = 0x0;
533
534 // Put them in a vector.
535 vector<Module::Function *> vec;
536 vec.push_back(function1);
537 vec.push_back(function2);
538 vec.push_back(function3);
539
540 m.AddFunctions(vec.begin(), vec.end());
541
542 // Try looking up functions by address.
543 Module::Function* f = m.FindFunctionByAddress(0x1000);
544 EXPECT_EQ(function1, f);
545 f = m.FindFunctionByAddress(0x18FF);
546 EXPECT_EQ(function1, f);
547
548 f = m.FindFunctionByAddress(0x1900);
549 EXPECT_EQ((Module::Function*)NULL, f);
550 f = m.FindFunctionByAddress(0x1A00);
551 EXPECT_EQ((Module::Function*)NULL, f);
552
553 f = m.FindFunctionByAddress(0x2000);
554 EXPECT_EQ(function2, f);
555 f = m.FindFunctionByAddress(0x28FF);
556 EXPECT_EQ(function2, f);
557
558 f = m.FindFunctionByAddress(0x3000);
559 EXPECT_EQ(function3, f);
560 f = m.FindFunctionByAddress(0x38FF);
561 EXPECT_EQ(function3, f);
562
563 f = m.FindFunctionByAddress(0x3900);
564 EXPECT_EQ((Module::Function*)NULL, f);
565 f = m.FindFunctionByAddress(0x3A00);
566 EXPECT_EQ((Module::Function*)NULL, f);
567 }
568
569 TEST(Lookup, Externs) {
570 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
571
572 // Two externs.
573 Module::Extern* extern1 = new(Module::Extern);
574 extern1->address = 0x1000;
575 extern1->name = "_abc";
576 Module::Extern* extern2 = new(Module::Extern);
577 extern2->address = 0x2000;
578 extern2->name = "_xyz";
579
580 m.AddExtern(extern1);
581 m.AddExtern(extern2);
582
583 Module::Extern* e = m.FindExternByAddress(0xFFF);
584 EXPECT_EQ((Module::Extern*)NULL, e);
585
586 e = m.FindExternByAddress(0x1000);
587 EXPECT_EQ(extern1, e);
588 e = m.FindExternByAddress(0x1900);
589 EXPECT_EQ(extern1, e);
590 e = m.FindExternByAddress(0x1FFF);
591 EXPECT_EQ(extern1, e);
592
593 e = m.FindExternByAddress(0x2000);
594 EXPECT_EQ(extern2, e);
595 e = m.FindExternByAddress(0x2900);
596 EXPECT_EQ(extern2, e);
597 e = m.FindExternByAddress(0xFFFFFFFF);
598 EXPECT_EQ(extern2, e);
599 }
600
601 TEST(Lookup, StackFrameEntries) {
602 Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
603
604 // First STACK CFI entry, with no initial rules or deltas.
605 Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
606 entry1->address = 0x2000;
607 entry1->size = 0x900;
608 m.AddStackFrameEntry(entry1);
609
610 // Second STACK CFI entry, with initial rules but no deltas.
611 Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
612 entry2->address = 0x3000;
613 entry2->size = 0x900;
614 entry2->initial_rules[ustr__ZDcfa()] =
615 Module::Expr("I think that I shall never see");
616 entry2->initial_rules[ToUniqueString("stromboli")] =
617 Module::Expr("a poem lovely as a tree");
618 entry2->initial_rules[ToUniqueString("cannoli")] =
619 Module::Expr("a tree whose hungry mouth is prest");
620 m.AddStackFrameEntry(entry2);
621
622 // Third STACK CFI entry, with initial rules and deltas.
623 Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
624 entry3->address = 0x1000;
625 entry3->size = 0x900;
626 entry3->initial_rules[ustr__ZDcfa()] = Module::Expr("Whose woods are these");
627 entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("calzone")] =
628 Module::Expr("the village though");
629 entry3->rule_changes[0x47ceb0f63c269d7fULL][ToUniqueString("cannoli")] =
630 Module::Expr("he will not see me stopping here");
631 entry3->rule_changes[0x36682fad3763ffffULL][ToUniqueString("stromboli")] =
632 Module::Expr("his house is in");
633 entry3->rule_changes[0x36682fad3763ffffULL][ustr__ZDcfa()] =
634 Module::Expr("I think I know");
635 m.AddStackFrameEntry(entry3);
636
637 Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000);
638 EXPECT_EQ(entry3, s);
639 s = m.FindStackFrameEntryByAddress(0x18FF);
640 EXPECT_EQ(entry3, s);
641
642 s = m.FindStackFrameEntryByAddress(0x1900);
643 EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
644 s = m.FindStackFrameEntryByAddress(0x1A00);
645 EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
646
647 s = m.FindStackFrameEntryByAddress(0x2000);
648 EXPECT_EQ(entry1, s);
649 s = m.FindStackFrameEntryByAddress(0x28FF);
650 EXPECT_EQ(entry1, s);
651
652 s = m.FindStackFrameEntryByAddress(0x3000);
653 EXPECT_EQ(entry2, s);
654 s = m.FindStackFrameEntryByAddress(0x38FF);
655 EXPECT_EQ(entry2, s);
656
657 s = m.FindStackFrameEntryByAddress(0x3900);
658 EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
659 s = m.FindStackFrameEntryByAddress(0x3A00);
660 EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
661 }

mercurial