/ src / common / module_unittest.cc
module_unittest.cc
  1  // Copyright 2010 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 30  
 31  // module_unittest.cc: Unit tests for google_breakpad::Module.
 32  
 33  #ifdef HAVE_CONFIG_H
 34  #include <config.h>  // Must come first
 35  #endif
 36  
 37  #include <errno.h>
 38  #include <stdio.h>
 39  #include <stdlib.h>
 40  #include <string.h>
 41  
 42  #include <algorithm>
 43  #include <memory>
 44  #include <sstream>
 45  #include <string>
 46  #include <utility>
 47  
 48  #include "breakpad_googletest_includes.h"
 49  #include "common/module.h"
 50  #include "common/using_std_string.h"
 51  
 52  using google_breakpad::Module;
 53  using google_breakpad::StringView;
 54  using std::stringstream;
 55  using std::vector;
 56  using testing::ContainerEq;
 57  
 58  static Module::Function* generate_duplicate_function(StringView name) {
 59    const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cULL;
 60    const Module::Address DUP_SIZE = 0x200b26e605f99071ULL;
 61    const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99ULL;
 62  
 63    Module::Function* function = new Module::Function(name, DUP_ADDRESS);
 64    Module::Range range(DUP_ADDRESS, DUP_SIZE);
 65    function->ranges.push_back(range);
 66    function->parameter_size = DUP_PARAMETER_SIZE;
 67    return function;
 68  }
 69  
 70  #define MODULE_NAME "name with spaces"
 71  #define MODULE_OS "os-name"
 72  #define MODULE_ARCH "architecture"
 73  #define MODULE_ID "id-string"
 74  #define MODULE_CODE_ID "code-id-string"
 75  
 76  TEST(Module, WriteHeader) {
 77    stringstream s;
 78    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
 79    m.Write(s, ALL_SYMBOL_DATA);
 80    string contents = s.str();
 81    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n",
 82                 contents.c_str());
 83  }
 84  
 85  TEST(Module, WriteHeaderCodeId) {
 86    stringstream s;
 87    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID, MODULE_CODE_ID);
 88    m.Write(s, ALL_SYMBOL_DATA);
 89    string contents = s.str();
 90    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
 91                 "INFO CODE_ID code-id-string\n",
 92                 contents.c_str());
 93  }
 94  
 95  TEST(Module, WriteOneLineFunc) {
 96    stringstream s;
 97    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
 98  
 99    Module::File* file = m.FindFile("file_name.cc");
100    Module::Function* function = new Module::Function(
101        "function_name", 0xe165bf8023b9d9abULL);
102    Module::Range range(0xe165bf8023b9d9abULL, 0x1e4bb0eb1cbf5b09ULL);
103    function->ranges.push_back(range);
104    function->parameter_size = 0x772beee89114358aULL;
105    Module::Line line = { 0xe165bf8023b9d9abULL, 0x1e4bb0eb1cbf5b09ULL,
106                          file, 67519080 };
107    function->lines.push_back(line);
108    m.AddFunction(function);
109  
110    m.Write(s, ALL_SYMBOL_DATA);
111    string contents = s.str();
112    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
113                 "FILE 0 file_name.cc\n"
114                 "FUNC e165bf8023b9d9ab 1e4bb0eb1cbf5b09 772beee89114358a"
115                 " function_name\n"
116                 "e165bf8023b9d9ab 1e4bb0eb1cbf5b09 67519080 0\n",
117                 contents.c_str());
118  }
119  
120  TEST(Module, WriteRelativeLoadAddress) {
121    stringstream s;
122    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
123  
124    // Some source files.  We will expect to see them in lexicographic order.
125    Module::File* file1 = m.FindFile("filename-b.cc");
126    Module::File* file2 = m.FindFile("filename-a.cc");
127  
128    // A function.
129    Module::Function* function = new Module::Function(
130        "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3ULL);
131    Module::Range range(0xbec774ea5dd935f3ULL, 0x2922088f98d3f6fcULL);
132    function->ranges.push_back(range);
133    function->parameter_size = 0xe5e9aa008bd5f0d0ULL;
134  
135    // Some source lines.  The module should not sort these.
136    Module::Line line1 = { 0xbec774ea5dd935f3ULL, 0x1c2be6d6c5af2611ULL,
137                           file1, 41676901 };
138    Module::Line line2 = { 0xdaf35bc123885c04ULL, 0xcf621b8d324d0ebULL,
139                           file2, 67519080 };
140    function->lines.push_back(line2);
141    function->lines.push_back(line1);
142  
143    m.AddFunction(function);
144  
145    // Some stack information.
146    auto entry = std::make_unique<Module::StackFrameEntry>();
147    entry->address = 0x30f9e5c83323973dULL;
148    entry->size = 0x49fc9ca7c7c13dc2ULL;
149    entry->initial_rules[".cfa"] = "he was a handsome man";
150    entry->initial_rules["and"] = "what i want to know is";
151    entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
152      "do you like your blueeyed boy";
153    entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
154    m.AddStackFrameEntry(std::move(entry));
155  
156    // Set the load address.  Doing this after adding all the data to
157    // the module must work fine.
158    m.SetLoadAddress(0x2ab698b0b6407073ULL);
159  
160    m.Write(s, ALL_SYMBOL_DATA);
161    string contents = s.str();
162    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
163                 "FILE 0 filename-a.cc\n"
164                 "FILE 1 filename-b.cc\n"
165                 "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
166                 " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
167                 "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n"
168                 "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n"
169                 "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2"
170                 " .cfa: he was a handsome man"
171                 " and: what i want to know is\n"
172                 "STACK CFI 6434d177ce326cb"
173                 " Mister: Death"
174                 " how: do you like your blueeyed boy\n",
175                 contents.c_str());
176  }
177  
178  TEST(Module, WriteOmitUnusedFiles) {
179    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
180  
181    // Create some source files.
182    Module::File* file1 = m.FindFile("filename1");
183    m.FindFile("filename2");  // not used by any line
184    Module::File* file3 = m.FindFile("filename3");
185  
186    // Create a function.
187    Module::Function* function = new Module::Function(
188        "function_name", 0x9b926d464f0b9384ULL);
189    Module::Range range(0x9b926d464f0b9384ULL, 0x4f524a4ba795e6a6ULL);
190    function->ranges.push_back(range);
191    function->parameter_size = 0xbbe8133a6641c9b7ULL;
192  
193    // Source files that refer to some files, but not others.
194    Module::Line line1 = { 0xab415089485e1a20ULL, 0x126e3124979291f2ULL,
195                           file1, 137850127 };
196    Module::Line line2 = { 0xb2675b5c3c2ed33fULL, 0x1df77f5551dbd68cULL,
197                           file3, 28113549 };
198    function->lines.push_back(line1);
199    function->lines.push_back(line2);
200    m.AddFunction(function);
201    m.AssignSourceIds();
202  
203    vector<Module::File*> vec;
204    m.GetFiles(&vec);
205    EXPECT_EQ((size_t) 3, vec.size());
206    EXPECT_STREQ("filename1", vec[0]->name.c_str());
207    EXPECT_NE(-1, vec[0]->source_id);
208    // Expect filename2 not to be used.
209    EXPECT_STREQ("filename2", vec[1]->name.c_str());
210    EXPECT_EQ(-1, vec[1]->source_id);
211    EXPECT_STREQ("filename3", vec[2]->name.c_str());
212    EXPECT_NE(-1, vec[2]->source_id);
213  
214    stringstream s;
215    m.Write(s, ALL_SYMBOL_DATA);
216    string contents = s.str();
217    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
218                 "FILE 0 filename1\n"
219                 "FILE 1 filename3\n"
220                 "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7"
221                 " function_name\n"
222                 "ab415089485e1a20 126e3124979291f2 137850127 0\n"
223                 "b2675b5c3c2ed33f 1df77f5551dbd68c 28113549 1\n",
224                 contents.c_str());
225  }
226  
227  TEST(Module, WriteNoCFI) {
228    stringstream s;
229    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
230  
231    // Some source files.  We will expect to see them in lexicographic order.
232    Module::File* file1 = m.FindFile("filename.cc");
233  
234    // A function.
235    Module::Function* function = new Module::Function(
236        "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3ULL);
237    Module::Range range(0xbec774ea5dd935f3ULL, 0x2922088f98d3f6fcULL);
238    function->ranges.push_back(range);
239    function->parameter_size = 0xe5e9aa008bd5f0d0ULL;
240  
241    // Some source lines.  The module should not sort these.
242    Module::Line line1 = { 0xbec774ea5dd935f3ULL, 0x1c2be6d6c5af2611ULL,
243                           file1, 41676901 };
244    function->lines.push_back(line1);
245  
246    m.AddFunction(function);
247  
248    // Some stack information.
249    auto entry = std::make_unique<Module::StackFrameEntry>();
250    entry->address = 0x30f9e5c83323973dULL;
251    entry->size = 0x49fc9ca7c7c13dc2ULL;
252    entry->initial_rules[".cfa"] = "he was a handsome man";
253    entry->initial_rules["and"] = "what i want to know is";
254    entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
255      "do you like your blueeyed boy";
256    entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
257    m.AddStackFrameEntry(std::move(entry));
258  
259    // Set the load address.  Doing this after adding all the data to
260    // the module must work fine.
261    m.SetLoadAddress(0x2ab698b0b6407073ULL);
262  
263    m.Write(s, SYMBOLS_AND_FILES | INLINES);
264    string contents = s.str();
265    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
266                 "FILE 0 filename.cc\n"
267                 "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
268                 " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
269                 "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n",
270                 contents.c_str());
271  }
272  
273  TEST(Module, ConstructAddFunction) {
274    stringstream s;
275    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
276  
277    // Two functions.
278    Module::Function* function1 = new Module::Function(
279        "_without_form", 0xd35024aa7ca7da5cULL);
280    Module::Range r1(0xd35024aa7ca7da5cULL, 0x200b26e605f99071ULL);
281    function1->ranges.push_back(r1);
282    function1->parameter_size = 0xf14ac4fed48c4a99ULL;
283  
284    Module::Function* function2 = new Module::Function(
285        "_and_void", 0x2987743d0b35b13fULL);
286    Module::Range r2(0x2987743d0b35b13fULL, 0xb369db048deb3010ULL);
287    function2->ranges.push_back(r2);
288    function2->parameter_size = 0x938e556cb5a79988ULL;
289  
290    // Put them in a vector.
291    vector<Module::Function*> vec;
292    vec.push_back(function1);
293    vec.push_back(function2);
294  
295    for (Module::Function* func: vec)
296      m.AddFunction(func);
297  
298    m.Write(s, ALL_SYMBOL_DATA);
299    string contents = s.str();
300    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
301                 "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988"
302                 " _and_void\n"
303                 "FUNC d35024aa7ca7da5c 200b26e605f99071 f14ac4fed48c4a99"
304                 " _without_form\n",
305                 contents.c_str());
306  
307    // Check that m.GetFunctions returns the functions we expect.
308    vec.clear();
309    m.GetFunctions(&vec, vec.end());
310    EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function1));
311    EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function2));
312    EXPECT_EQ((size_t) 2, vec.size());
313  }
314  
315  TEST(Module, WriteOutOfRangeAddresses) {
316    stringstream s;
317    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
318  
319    // Specify an allowed address range, representing a PT_LOAD segment in a
320    // module.
321    vector<Module::Range> address_ranges = {
322      Module::Range(0x2000ULL, 0x1000ULL),
323    };
324    m.SetAddressRanges(address_ranges);
325  
326    // Add three stack frames (one lower, one in, and one higher than the allowed
327    // address range).  Only the middle frame should be captured.
328    auto entry1 = std::make_unique<Module::StackFrameEntry>();
329    entry1->address = 0x1000ULL;
330    entry1->size = 0x100ULL;
331    m.AddStackFrameEntry(std::move(entry1));
332    auto entry2 = std::make_unique<Module::StackFrameEntry>();
333    entry2->address = 0x2000ULL;
334    entry2->size = 0x100ULL;
335    m.AddStackFrameEntry(std::move(entry2));
336    auto entry3 = std::make_unique<Module::StackFrameEntry>();
337    entry3->address = 0x3000ULL;
338    entry3->size = 0x100ULL;
339    m.AddStackFrameEntry(std::move(entry3));
340  
341    // Add a function outside the allowed range.
342    Module::File* file = m.FindFile("file_name.cc");
343    Module::Function* function = new Module::Function(
344        "function_name", 0x4000ULL);
345    Module::Range range(0x4000ULL, 0x1000ULL);
346    function->ranges.push_back(range);
347    function->parameter_size = 0x100ULL;
348    Module::Line line = { 0x4000ULL, 0x100ULL, file, 67519080 };
349    function->lines.push_back(line);
350    m.AddFunction(function);
351  
352    // Add an extern outside the allowed range.
353    auto extern1 = std::make_unique<Module::Extern>(0x5000ULL);
354    extern1->name = "_xyz";
355    m.AddExtern(std::move(extern1));
356  
357    m.Write(s, ALL_SYMBOL_DATA);
358  
359    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
360                 "STACK CFI INIT 2000 100 \n",
361                 s.str().c_str());
362  
363    // Cleanup - Prevent Memory Leak errors.
364    delete (function);
365  }
366  
367  TEST(Module, ConstructAddFrames) {
368    stringstream s;
369    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
370  
371    // First STACK CFI entry, with no initial rules or deltas.
372    auto entry1 = std::make_unique<Module::StackFrameEntry>();
373    entry1->address = 0xddb5f41285aa7757ULL;
374    entry1->size = 0x1486493370dc5073ULL;
375    m.AddStackFrameEntry(std::move(entry1));
376  
377    // Second STACK CFI entry, with initial rules but no deltas.
378    auto entry2 = std::make_unique<Module::StackFrameEntry>();
379    entry2->address = 0x8064f3af5e067e38ULL;
380    entry2->size = 0x0de2a5ee55509407ULL;
381    entry2->initial_rules[".cfa"] = "I think that I shall never see";
382    entry2->initial_rules["stromboli"] = "a poem lovely as a tree";
383    entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest";
384    m.AddStackFrameEntry(std::move(entry2));
385  
386    // Third STACK CFI entry, with initial rules and deltas.
387    auto entry3 = std::make_unique<Module::StackFrameEntry>();
388    entry3->address = 0x5e8d0db0a7075c6cULL;
389    entry3->size = 0x1c7edb12a7aea229ULL;
390    entry3->initial_rules[".cfa"] = "Whose woods are these";
391    entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
392      "the village though";
393    entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
394      "he will not see me stopping here";
395    entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
396      "his house is in";
397    entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
398      "I think I know";
399    m.AddStackFrameEntry(std::move(entry3));
400  
401    // Check that Write writes STACK CFI records properly.
402    m.Write(s, ALL_SYMBOL_DATA);
403    string contents = s.str();
404    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
405                 "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n"
406                 "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
407                 " .cfa: I think that I shall never see"
408                 " cannoli: a tree whose hungry mouth is prest"
409                 " stromboli: a poem lovely as a tree\n"
410                 "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
411                 " .cfa: Whose woods are these\n"
412                 "STACK CFI 36682fad3763ffff"
413                 " .cfa: I think I know"
414                 " stromboli: his house is in\n"
415                 "STACK CFI 47ceb0f63c269d7f"
416                 " calzone: the village though"
417                 " cannoli: he will not see me stopping here\n",
418                 contents.c_str());
419  
420    // Check that GetStackFrameEntries works.
421    vector<Module::StackFrameEntry*> entries;
422    m.GetStackFrameEntries(&entries);
423    ASSERT_EQ(3U, entries.size());
424    // Check first entry.
425    EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address);
426    EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size);
427    ASSERT_EQ(0U, entries[0]->initial_rules.size());
428    ASSERT_EQ(0U, entries[0]->rule_changes.size());
429    // Check second entry.
430    EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
431    EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
432    ASSERT_EQ(3U, entries[1]->initial_rules.size());
433    Module::RuleMap entry2_initial;
434    entry2_initial[".cfa"] = "I think that I shall never see";
435    entry2_initial["stromboli"] = "a poem lovely as a tree";
436    entry2_initial["cannoli"] = "a tree whose hungry mouth is prest";
437    EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
438    ASSERT_EQ(0U, entries[1]->rule_changes.size());
439    // Check third entry.
440    EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address);
441    EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size);
442    Module::RuleMap entry3_initial;
443    entry3_initial[".cfa"] = "Whose woods are these";
444    EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial));
445    Module::RuleChangeMap entry3_changes;
446    entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
447    entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
448    entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
449    entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
450      "he will not see me stopping here";
451    EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes));
452  }
453  
454  TEST(Module, ConstructUniqueFiles) {
455    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
456    Module::File* file1 = m.FindFile("foo");
457    Module::File* file2 = m.FindFile(string("bar"));
458    Module::File* file3 = m.FindFile(string("foo"));
459    Module::File* file4 = m.FindFile("bar");
460    EXPECT_NE(file1, file2);
461    EXPECT_EQ(file1, file3);
462    EXPECT_EQ(file2, file4);
463    EXPECT_EQ(file1, m.FindExistingFile("foo"));
464    EXPECT_TRUE(m.FindExistingFile("baz") == NULL);
465  }
466  
467  TEST(Module, ConstructDuplicateFunctions) {
468    stringstream s;
469    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
470  
471    // Two functions.
472    Module::Function* function1 = generate_duplicate_function("_without_form");
473    Module::Function* function2 = generate_duplicate_function("_without_form");
474  
475    m.AddFunction(function1);
476    // If this succeeds, we'll have a double-free with the `delete` below. Avoid
477    // that.
478    ASSERT_FALSE(m.AddFunction(function2));
479    delete function2;
480  
481    m.Write(s, ALL_SYMBOL_DATA);
482    string contents = s.str();
483    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
484                 "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
485                 " _without_form\n",
486                 contents.c_str());
487  }
488  
489  TEST(Module, ConstructFunctionsWithSameAddress) {
490    stringstream s;
491    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
492  
493    // Two functions.
494    Module::Function* function1 = generate_duplicate_function("_without_form");
495    Module::Function* function2 = generate_duplicate_function("_and_void");
496  
497    m.AddFunction(function1);
498    m.AddFunction(function2);
499  
500    m.Write(s, ALL_SYMBOL_DATA);
501    string contents = s.str();
502    EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
503                 "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
504                 " _and_void\n"
505                 "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
506                 " _without_form\n",
507                 contents.c_str());
508  }
509  
510  // If multiple fields are enabled, only one function is included per address.
511  // The entry will be tagged with `m` to show that there are multiple symbols
512  // at that address.
513  // TODO(lgrey): Remove the non-multiple versions of these tests and remove the
514  // suffixes from the suffxed ones when removing `enable_multiple_field_`.
515  TEST(Module, ConstructFunctionsWithSameAddressMultiple) {
516    stringstream s;
517    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID, "", true);
518  
519    // Two functions.
520    Module::Function* function1 = generate_duplicate_function("_without_form");
521    Module::Function* function2 = generate_duplicate_function("_and_void");
522  
523    m.AddFunction(function1);
524    // If this succeeds, we'll have a double-free with the `delete` below. Avoid
525    // that.
526    ASSERT_FALSE(m.AddFunction(function2));
527    delete function2;
528  
529    m.Write(s, ALL_SYMBOL_DATA);
530    string contents = s.str();
531    EXPECT_STREQ(
532        "MODULE os-name architecture id-string name with spaces\n"
533        "FUNC m d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
534        " _without_form\n",
535        contents.c_str());
536  }
537  
538  // Externs should be written out as PUBLIC records, sorted by
539  // address.
540  TEST(Module, ConstructExterns) {
541    stringstream s;
542    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
543  
544    // Two externs.
545    auto extern1 = std::make_unique<Module::Extern>(0xffff);
546    extern1->name = "_abc";
547    auto extern2 = std::make_unique<Module::Extern>(0xaaaa);
548    extern2->name = "_xyz";
549  
550    m.AddExtern(std::move(extern1));
551    m.AddExtern(std::move(extern2));
552  
553    m.Write(s, ALL_SYMBOL_DATA);
554    string contents = s.str();
555  
556    EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
557                 MODULE_ID " " MODULE_NAME "\n"
558                 "PUBLIC aaaa 0 _xyz\n"
559                 "PUBLIC ffff 0 _abc\n",
560                 contents.c_str());
561  }
562  
563  // Externs with the same address should only keep the first entry
564  // added.
565  TEST(Module, ConstructDuplicateExterns) {
566    stringstream s;
567    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
568  
569    // Two externs.
570    auto extern1 = std::make_unique<Module::Extern>(0xffff);
571    extern1->name = "_xyz";
572    auto extern2 = std::make_unique<Module::Extern>(0xffff);
573    extern2->name = "_abc";
574  
575    m.AddExtern(std::move(extern1));
576    m.AddExtern(std::move(extern2));
577  
578    m.Write(s, ALL_SYMBOL_DATA);
579    string contents = s.str();
580  
581    EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
582                 MODULE_ID " " MODULE_NAME "\n"
583                 "PUBLIC ffff 0 _xyz\n",
584                 contents.c_str());
585  }
586  // Externs with the same address  have the `m` tag if the multiple field are
587  // enabled.
588  TEST(Module, ConstructDuplicateExternsMultiple) {
589    stringstream s;
590    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID, "", true);
591  
592    // Two externs.
593    auto extern1 = std::make_unique<Module::Extern>(0xffff);
594    extern1->name = "_xyz";
595    auto extern2 = std::make_unique<Module::Extern>(0xffff);
596    extern2->name = "_abc";
597  
598    m.AddExtern(std::move(extern1));
599    m.AddExtern(std::move(extern2));
600  
601    m.Write(s, ALL_SYMBOL_DATA);
602    string contents = s.str();
603  
604    EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " MODULE_ID " " MODULE_NAME
605                 "\n"
606                 "PUBLIC m ffff 0 _xyz\n",
607                 contents.c_str());
608  }
609  
610  // If there exists an extern and a function at the same address, only write
611  // out the FUNC entry.
612  TEST(Module, ConstructFunctionsAndExternsWithSameAddress) {
613    stringstream s;
614    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
615  
616    // Two externs.
617    auto extern1 = std::make_unique<Module::Extern>(0xabc0);
618    extern1->name = "abc";
619    auto extern2 = std::make_unique<Module::Extern>(0xfff0);
620    extern2->name = "xyz";
621  
622    m.AddExtern(std::move(extern1));
623    m.AddExtern(std::move(extern2));
624  
625    Module::Function* function = new Module::Function("_xyz", 0xfff0);
626    Module::Range range(0xfff0, 0x10);
627    function->ranges.push_back(range);
628    function->parameter_size = 0;
629    m.AddFunction(function);
630  
631    m.Write(s, ALL_SYMBOL_DATA);
632    string contents = s.str();
633  
634    EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
635                 MODULE_ID " " MODULE_NAME "\n"
636                 "FUNC fff0 10 0 _xyz\n"
637                 "PUBLIC abc0 0 abc\n",
638                 contents.c_str());
639  }
640  
641  // If there exists an extern and a function at the same address, only write
642  // out the FUNC entry.
643  TEST(Module, ConstructFunctionsAndExternsWithSameAddressPreferExternName) {
644    stringstream s;
645    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID, "", false, true);
646  
647    // Two externs.
648    auto extern1 = std::make_unique<Module::Extern>(0xabc0);
649    extern1->name = "extern1";
650    auto extern2 = std::make_unique<Module::Extern>(0xfff0);
651    extern2->name = "extern2";
652  
653    m.AddExtern(std::move(extern1));
654    m.AddExtern(std::move(extern2));
655  
656    Module::Function* function = new Module::Function("function2", 0xfff0);
657    Module::Range range(0xfff0, 0x10);
658    function->ranges.push_back(range);
659    function->parameter_size = 0;
660    m.AddFunction(function);
661  
662    m.Write(s, ALL_SYMBOL_DATA);
663    string contents = s.str();
664  
665    EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " MODULE_ID " " MODULE_NAME
666                 "\n"
667                 "FUNC fff0 10 0 extern2\n"
668                 "PUBLIC abc0 0 extern1\n",
669                 contents.c_str());
670  }
671  
672  // If there exists an extern and a function at the same address, only write
673  // out the FUNC entry, and mark it with `m` if the multiple field is enabled.
674  TEST(Module, ConstructFunctionsAndExternsWithSameAddressMultiple) {
675    stringstream s;
676    Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID, "", true);
677  
678    // Two externs.
679    auto extern1 = std::make_unique<Module::Extern>(0xabc0);
680    extern1->name = "abc";
681    auto extern2 = std::make_unique<Module::Extern>(0xfff0);
682    extern2->name = "xyz";
683  
684    m.AddExtern(std::move(extern1));
685    m.AddExtern(std::move(extern2));
686  
687    Module::Function* function = new Module::Function("_xyz", 0xfff0);
688    Module::Range range(0xfff0, 0x10);
689    function->ranges.push_back(range);
690    function->parameter_size = 0;
691    m.AddFunction(function);
692  
693    m.Write(s, ALL_SYMBOL_DATA);
694    string contents = s.str();
695  
696    EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " " MODULE_ID " " MODULE_NAME
697                 "\n"
698                 "FUNC m fff0 10 0 _xyz\n"
699                 "PUBLIC abc0 0 abc\n",
700                 contents.c_str());
701  }
702  
703  // If there exists an extern and a function at the same address, only write
704  // out the FUNC entry. For ARM THUMB, the extern that comes from the ELF
705  // symbol section has bit 0 set.
706  TEST(Module, ConstructFunctionsAndThumbExternsWithSameAddress) {
707    stringstream s;
708    Module m(MODULE_NAME, MODULE_OS, "arm", MODULE_ID);
709  
710    // Two THUMB externs.
711    auto thumb_extern1 = std::make_unique<Module::Extern>(0xabc1);
712    thumb_extern1->name = "thumb_abc";
713    auto thumb_extern2 = std::make_unique<Module::Extern>(0xfff1);
714    thumb_extern2->name = "thumb_xyz";
715  
716    auto arm_extern1 = std::make_unique<Module::Extern>(0xcc00);
717    arm_extern1->name = "arm_func";
718  
719    m.AddExtern(std::move(thumb_extern1));
720    m.AddExtern(std::move(thumb_extern2));
721    m.AddExtern(std::move(arm_extern1));
722  
723    // The corresponding function from the DWARF debug data have the actual
724    // address.
725    Module::Function* function = new Module::Function("_thumb_xyz", 0xfff0);
726    Module::Range range(0xfff0, 0x10);
727    function->ranges.push_back(range);
728    function->parameter_size = 0;
729    m.AddFunction(function);
730  
731    m.Write(s, ALL_SYMBOL_DATA);
732    string contents = s.str();
733  
734    EXPECT_STREQ("MODULE " MODULE_OS " arm "
735                 MODULE_ID " " MODULE_NAME "\n"
736                 "FUNC fff0 10 0 _thumb_xyz\n"
737                 "PUBLIC abc1 0 thumb_abc\n"
738                 "PUBLIC cc00 0 arm_func\n",
739                 contents.c_str());
740  }