29 #include <gmock/gmock.h>
30 #include <gtest/gtest-spi.h>
31 #include <gtest/gtest.h>
34 #include <initializer_list>
55 if (symbol.binding !=
expected.binding) {
56 ss <<
" symbols' bindings do not match: seen `" <<
57 (int)symbol.binding <<
"`, expected `" <<
62 ss <<
" symbols' names do not match: seen `" << symbol.name <<
63 "`, expected `" <<
expected.name <<
"`.\n";
66 if (symbol.address !=
expected.address) {
67 ss <<
" symbols' addresses do not match: seen `" <<
68 symbol.address <<
"`, expected `" <<
expected.address <<
"`.\n";
84 ::testing::AssertionResult
86 const Loader::Symbol& symbol,
const Loader::Symbol&
expected)
90 return ::testing::AssertionFailure() <<
"Symbols do not match (" <<
91 m_symbol <<
" != " << m_expected <<
")\n" <<
error;
93 return ::testing::AssertionSuccess();
103 ::testing::AssertionResult
105 const std::initializer_list<Loader::Symbol>&
expected)
107 if (
expected.size() != (symtab.end() - symtab.begin())) {
108 return ::testing::AssertionFailure() <<
"the number of symbols in "
109 "the table does not match expectation (seen " <<
110 (symtab.end() - symtab.begin()) <<
", expected " <<
115 auto it = symtab.begin();
116 for (
const auto& symbol :
expected) {
118 if (!
error.empty()) {
119 return ::testing::AssertionFailure() <<
error;
123 return ::testing::AssertionSuccess();
127 TEST(LoaderSymtabTest, EmptyConstruction)
129 Loader::SymbolTable symtab;
130 ASSERT_TRUE(symtab.empty());
135 TEST(LoaderSymtabTest, InsertSymbolNoName)
137 Loader::SymbolTable symtab;
139 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"", 0x10};
140 ASSERT_FALSE(symtab.insert(symbol));
145 TEST(LoaderSymtabTest, InsertOneSymbol)
147 Loader::SymbolTable symtab;
149 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"symbol", 0x10};
150 ASSERT_TRUE(symtab.insert(symbol));
152 ASSERT_FALSE(symtab.empty());
157 TEST(LoaderSymtabTest, InsertSymbolExistingName)
159 Loader::SymbolTable symtab;
161 const std::string
name =
"symbol";
162 Loader::Symbol symbols[] = {
163 {Loader::Symbol::Binding::Local,
name, 0x10},
164 {Loader::Symbol::Binding::Local,
name, 0x20},
166 ASSERT_TRUE(symtab.insert(symbols[0]));
167 ASSERT_FALSE(symtab.insert(symbols[1]));
170 ASSERT_TRUE(
checkTable(symtab, {symbols[0]}));
174 TEST(LoaderSymtabTest, InsertSymbolExistingAddress)
176 Loader::SymbolTable symtab;
179 Loader::Symbol symbols[] = {
180 {Loader::Symbol::Binding::Local,
"symbol",
addr},
181 {Loader::Symbol::Binding::Local,
"symbol2",
addr},
183 ASSERT_TRUE(symtab.insert(symbols[0]));
184 ASSERT_TRUE(symtab.insert(symbols[1]));
187 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1]}));
191 TEST(LoaderSymtabTest, InsertMultipleSymbols)
193 Loader::SymbolTable symtab;
195 Loader::Symbol symbols[] = {
196 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
197 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
198 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
200 EXPECT_TRUE(symtab.insert(symbols[0]));
201 EXPECT_TRUE(symtab.insert(symbols[1]));
202 EXPECT_TRUE(symtab.insert(symbols[2]));
204 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
210 TEST(LoaderSymtabTest, ClearMultiple)
212 Loader::SymbolTable symtab;
214 Loader::Symbol symbols[] = {
215 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
216 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
217 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
219 EXPECT_TRUE(symtab.insert(symbols[0]));
220 EXPECT_TRUE(symtab.insert(symbols[1]));
221 EXPECT_TRUE(symtab.insert(symbols[2]));
224 ASSERT_TRUE(symtab.empty());
234 Loader::SymbolTable symtab;
236 Loader::Symbol symbols[] = {
237 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
238 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
239 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
241 EXPECT_TRUE(symtab.insert(symbols[0]));
242 EXPECT_TRUE(symtab.insert(symbols[1]));
243 EXPECT_TRUE(symtab.insert(symbols[2]));
246 const auto symtab_new = symtab.offset(
offset);
249 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
252 Loader::Symbol expected_symbols[] = {
253 {symbols[0].binding, symbols[0].name, symbols[0].address +
offset},
254 {symbols[1].binding, symbols[1].name, symbols[1].address +
offset},
255 {symbols[2].binding, symbols[2].name, symbols[2].address +
offset},
257 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
258 expected_symbols[1], expected_symbols[2]}));
267 Loader::SymbolTable symtab;
269 Loader::Symbol symbols[] = {
270 {Loader::Symbol::Binding::Local,
"symbol", 0x1310},
271 {Loader::Symbol::Binding::Local,
"symbol2", 0x2810},
272 {Loader::Symbol::Binding::Local,
"symbol3", 0x2920},
273 {Loader::Symbol::Binding::Local,
"symbol4", 0x3C20},
275 EXPECT_TRUE(symtab.insert(symbols[0]));
276 EXPECT_TRUE(symtab.insert(symbols[1]));
277 EXPECT_TRUE(symtab.insert(symbols[2]));
278 EXPECT_TRUE(symtab.insert(symbols[3]));
281 const auto symtab_new = symtab.mask(
mask);
284 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
288 Loader::Symbol expected_symbols[] = {
289 {symbols[0].binding, symbols[0].name, symbols[0].address &
mask},
290 {symbols[1].binding, symbols[1].name, symbols[1].address &
mask},
291 {symbols[2].binding, symbols[2].name, symbols[2].address &
mask},
292 {symbols[3].binding, symbols[3].name, symbols[3].address &
mask},
294 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
295 expected_symbols[1], expected_symbols[2], expected_symbols[3]}));
304 Loader::SymbolTable symtab;
306 Loader::Symbol symbols[] = {
307 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
308 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
309 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
310 {Loader::Symbol::Binding::Local,
"symbol4", 0x40},
312 EXPECT_TRUE(symtab.insert(symbols[0]));
313 EXPECT_TRUE(symtab.insert(symbols[1]));
314 EXPECT_TRUE(symtab.insert(symbols[2]));
315 EXPECT_TRUE(symtab.insert(symbols[3]));
317 const auto symtab_new =
318 symtab.rename([](std::string &
name) {
name =
name +
"_suffix"; });
321 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
325 Loader::Symbol expected_symbols[] = {
326 {symbols[0].binding, symbols[0].name +
"_suffix", symbols[0].address},
327 {symbols[1].binding, symbols[1].name +
"_suffix", symbols[1].address},
328 {symbols[2].binding, symbols[2].name +
"_suffix", symbols[2].address},
329 {symbols[3].binding, symbols[3].name +
"_suffix", symbols[3].address},
331 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
332 expected_symbols[1], expected_symbols[2], expected_symbols[3]}));
339 TEST(LoaderSymtabTest, RenameNonUnique)
341 Loader::SymbolTable symtab;
343 Loader::Symbol symbols[] = {
344 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
345 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
346 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
347 {Loader::Symbol::Binding::Local,
"symbol4", 0x40},
349 EXPECT_TRUE(symtab.insert(symbols[0]));
350 EXPECT_TRUE(symtab.insert(symbols[1]));
351 EXPECT_TRUE(symtab.insert(symbols[2]));
352 EXPECT_TRUE(symtab.insert(symbols[3]));
355 const auto symtab_new = symtab.rename([&
i](std::string &
name)
357 if ((
i++ % 2) == 0) {
358 name =
"NonUniqueName";
363 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
368 Loader::Symbol expected_symbols[] = {
369 {symbols[0].binding,
"NonUniqueName", symbols[0].address},
370 {symbols[1].binding, symbols[1].name, symbols[1].address},
371 {symbols[3].binding, symbols[3].name, symbols[3].address},
373 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
374 expected_symbols[1], expected_symbols[2]}));
383 Loader::SymbolTable symtab;
385 Loader::Symbol symbols[] = {
386 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
387 {Loader::Symbol::Binding::Global,
"symbol2", 0x20},
388 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
389 {Loader::Symbol::Binding::Weak,
"symbol4", 0x40},
390 {Loader::Symbol::Binding::Weak,
"symbol5", 0x50}
392 EXPECT_TRUE(symtab.insert(symbols[0]));
393 EXPECT_TRUE(symtab.insert(symbols[1]));
394 EXPECT_TRUE(symtab.insert(symbols[2]));
395 EXPECT_TRUE(symtab.insert(symbols[3]));
396 EXPECT_TRUE(symtab.insert(symbols[4]));
398 const auto symtab_new = symtab.globals();
401 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
402 symbols[3], symbols[4]}));
405 ASSERT_TRUE(
checkTable(*symtab_new, {symbols[1]}));
414 Loader::SymbolTable symtab;
416 Loader::Symbol symbols[] = {
417 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
418 {Loader::Symbol::Binding::Global,
"symbol2", 0x20},
419 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
420 {Loader::Symbol::Binding::Weak,
"symbol4", 0x40},
421 {Loader::Symbol::Binding::Weak,
"symbol5", 0x50}
423 EXPECT_TRUE(symtab.insert(symbols[0]));
424 EXPECT_TRUE(symtab.insert(symbols[1]));
425 EXPECT_TRUE(symtab.insert(symbols[2]));
426 EXPECT_TRUE(symtab.insert(symbols[3]));
427 EXPECT_TRUE(symtab.insert(symbols[4]));
429 const auto symtab_new = symtab.locals();
432 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
433 symbols[3], symbols[4]}));
436 ASSERT_TRUE(
checkTable(*symtab_new, {symbols[0], symbols[2]}));
445 Loader::SymbolTable symtab;
447 Loader::Symbol symbols[] = {
448 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
449 {Loader::Symbol::Binding::Global,
"symbol2", 0x20},
450 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
451 {Loader::Symbol::Binding::Weak,
"symbol4", 0x40},
452 {Loader::Symbol::Binding::Weak,
"symbol5", 0x50}
454 EXPECT_TRUE(symtab.insert(symbols[0]));
455 EXPECT_TRUE(symtab.insert(symbols[1]));
456 EXPECT_TRUE(symtab.insert(symbols[2]));
457 EXPECT_TRUE(symtab.insert(symbols[3]));
458 EXPECT_TRUE(symtab.insert(symbols[4]));
460 const auto symtab_new = symtab.weaks();
463 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
464 symbols[3], symbols[4]}));
467 ASSERT_TRUE(
checkTable(*symtab_new, {symbols[3], symbols[4]}));
471 TEST(LoaderSymtabTest, FindNonExistentAddress)
473 Loader::SymbolTable symtab;
475 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"symbol", 0x10};
476 EXPECT_TRUE(symtab.insert(symbol));
478 ASSERT_EQ(symtab.find(0x0), symtab.end());
482 TEST(LoaderSymtabTest, FindUniqueAddress)
484 Loader::SymbolTable symtab;
486 Loader::Symbol symbols[] = {
487 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
488 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
489 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
491 EXPECT_TRUE(symtab.insert(symbols[0]));
492 EXPECT_TRUE(symtab.insert(symbols[1]));
493 EXPECT_TRUE(symtab.insert(symbols[2]));
495 const auto it = symtab.find(symbols[2].address);
496 ASSERT_NE(it, symtab.end());
503 TEST(LoaderSymtabTest, FindNonUniqueAddress)
505 Loader::SymbolTable symtab;
508 Loader::Symbol symbols[] = {
509 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
510 {Loader::Symbol::Binding::Local,
"symbol2",
addr},
511 {Loader::Symbol::Binding::Local,
"symbol3",
addr},
513 EXPECT_TRUE(symtab.insert(symbols[0]));
514 EXPECT_TRUE(symtab.insert(symbols[1]));
515 EXPECT_TRUE(symtab.insert(symbols[2]));
517 const auto it = symtab.find(symbols[1].address);
518 ASSERT_NE(it, symtab.end());
523 TEST(LoaderSymtabTest, FindNonExistentName)
525 Loader::SymbolTable symtab;
527 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"symbol", 0x10};
528 EXPECT_TRUE(symtab.insert(symbol));
530 const auto it = symtab.find(
"symbol2");
531 ASSERT_EQ(it, symtab.end());
535 TEST(LoaderSymtabTest, FindExistingName)
537 Loader::SymbolTable symtab;
539 Loader::Symbol symbols[] = {
540 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
541 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
542 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
544 EXPECT_TRUE(symtab.insert(symbols[0]));
545 EXPECT_TRUE(symtab.insert(symbols[1]));
546 EXPECT_TRUE(symtab.insert(symbols[2]));
548 const auto it = symtab.find(symbols[1].
name);
549 ASSERT_NE(it, symtab.end());
554 TEST(LoaderSymtabTest, FindNearestExact)
556 Loader::SymbolTable symtab;
558 Loader::Symbol symbols[] = {
559 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
560 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
562 EXPECT_TRUE(symtab.insert(symbols[0]));
563 EXPECT_TRUE(symtab.insert(symbols[1]));
565 const auto it = symtab.findNearest(symbols[1].address);
566 ASSERT_NE(it, symtab.end());
574 TEST(LoaderSymtabTest, FindNearestRound)
576 Loader::SymbolTable symtab;
578 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"symbol", 0x10};
579 EXPECT_TRUE(symtab.insert(symbol));
581 const auto it = symtab.findNearest(symbol.address + 0x1);
582 ASSERT_NE(it, symtab.end());
591 TEST(LoaderSymtabTest, FindNearestRoundWithNext)
593 Loader::SymbolTable symtab;
595 Loader::Symbol symbols[] = {
596 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
597 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
599 EXPECT_TRUE(symtab.insert(symbols[0]));
600 EXPECT_TRUE(symtab.insert(symbols[1]));
603 const auto it = symtab.findNearest(symbols[0].address + 0x1, next_addr);
604 ASSERT_NE(it, symtab.end());
606 ASSERT_EQ(next_addr, symbols[1].address);
614 TEST(LoaderSymtabTest, FindNearestRoundWithNextNonExistent)
616 Loader::SymbolTable symtab;
618 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"symbol", 0x10};
619 EXPECT_TRUE(symtab.insert(symbol));
622 const auto it = symtab.findNearest(symbol.address + 0x1, next_addr);
623 ASSERT_NE(it, symtab.end());
625 ASSERT_EQ(next_addr, 0);
632 TEST(LoaderSymtabTest, FindNearestNonExistent)
634 Loader::SymbolTable symtab;
636 Loader::Symbol symbol = {Loader::Symbol::Binding::Local,
"symbol", 0x10};
637 EXPECT_TRUE(symtab.insert(symbol));
639 const auto it = symtab.findNearest(symbol.address - 0x1);
640 ASSERT_EQ(it, symtab.end());
647 TEST(LoaderSymtabTest, InsertTableConflicting)
649 const std::string
name =
"symbol";
650 Loader::Symbol symbols[] = {
651 {Loader::Symbol::Binding::Local,
name, 0x10},
652 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
653 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
654 {Loader::Symbol::Binding::Local,
"symbol4", 0x40},
656 {Loader::Symbol::Binding::Local,
name, 0x50},
660 Loader::SymbolTable symtab;
661 EXPECT_TRUE(symtab.insert(symbols[0]));
662 EXPECT_TRUE(symtab.insert(symbols[1]));
663 EXPECT_TRUE(symtab.insert(symbols[2]));
666 Loader::SymbolTable symtab2;
667 EXPECT_TRUE(symtab2.insert(symbols[3]));
668 EXPECT_TRUE(symtab2.insert(symbols[4]));
671 ASSERT_FALSE(symtab.insert(symtab2));
674 ASSERT_TRUE(
checkTable(symtab2, {symbols[3], symbols[4]}));
675 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
682 TEST(LoaderSymtabTest, InsertTable)
684 Loader::Symbol symbols[] = {
685 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
686 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
687 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
688 {Loader::Symbol::Binding::Local,
"symbol4", 0x40},
689 {Loader::Symbol::Binding::Local,
"symbol5", 0x50},
693 Loader::SymbolTable symtab;
694 EXPECT_TRUE(symtab.insert(symbols[0]));
695 EXPECT_TRUE(symtab.insert(symbols[1]));
696 EXPECT_TRUE(symtab.insert(symbols[2]));
699 Loader::SymbolTable symtab2;
700 EXPECT_TRUE(symtab2.insert(symbols[3]));
701 EXPECT_TRUE(symtab2.insert(symbols[4]));
704 symtab.insert(symtab2);
707 ASSERT_TRUE(
checkTable(symtab2, {symbols[3], symbols[4]}));
710 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
711 symbols[3], symbols[4]}));
720 Loader::SymbolTable symtab;
721 Loader::Symbol symbols[] = {
722 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
723 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
724 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
726 EXPECT_TRUE(symtab.insert(symbols[0]));
727 EXPECT_TRUE(symtab.insert(symbols[1]));
728 EXPECT_TRUE(symtab.insert(symbols[2]));
731 std::ostringstream cp;
733 symtab.serialize(
"test", cp);
736 ASSERT_THAT(cp.str(), ::testing::StrEq(
"\n[Section1]\ntest.size=3\n"
737 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
738 "test.addr_1=32\ntest.symbol_1=symbol2\ntest.binding_1=1\n"
739 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"));
745 Loader::Symbol symbols[] = {
746 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
747 {Loader::Symbol::Binding::Local,
"symbol2", 0x20},
748 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
750 simulateSerialization(
"\n[Section1]\ntest.size=3\n"
751 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
752 "test.addr_1=32\ntest.symbol_1=symbol2\ntest.binding_1=1\n"
753 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n");
755 Loader::SymbolTable unserialized_symtab;
758 unserialized_symtab.unserialize(
"test", cp);
762 ASSERT_TRUE(
checkTable(unserialized_symtab, {symbols[0], symbols[1],
773 Loader::Symbol symbols[] = {
774 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
775 {Loader::Symbol::Binding::Global,
"symbol2", 0x20},
776 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
778 simulateSerialization(
"\n[Section1]\ntest.size=3\n"
779 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
780 "test.addr_1=32\ntest.symbol_1=symbol2\n"
781 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n");
783 Loader::SymbolTable unserialized_symtab;
787 unserialized_symtab.unserialize(
"test", cp);
791 ASSERT_TRUE(
checkTable(unserialized_symtab, {symbols[0], symbols[1],
801 UnserializationMissingBindingChangeDefault)
803 Loader::Symbol symbols[] = {
804 {Loader::Symbol::Binding::Local,
"symbol", 0x10},
805 {Loader::Symbol::Binding::Weak,
"symbol2", 0x20},
806 {Loader::Symbol::Binding::Local,
"symbol3", 0x30},
808 simulateSerialization(
"\n[Section1]\ntest.size=3\n"
809 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
810 "test.addr_1=32\ntest.symbol_1=symbol2\n"
811 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n");
813 Loader::SymbolTable unserialized_symtab;
817 unserialized_symtab.unserialize(
"test", cp,
818 Loader::Symbol::Binding::Weak);
822 ASSERT_TRUE(
checkTable(unserialized_symtab, {symbols[0], symbols[1],