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