29#include <gmock/gmock.h>
30#include <gtest/gtest-spi.h>
31#include <gtest/gtest.h>
34#include <initializer_list>
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";
67 ss <<
" symbols' addresses do not match: seen `" <<
84::testing::AssertionResult
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)
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();
127TEST(LoaderSymtabTest, EmptyConstruction)
130 ASSERT_TRUE(symtab.
empty());
135TEST(LoaderSymtabTest, InsertSymbolNoName)
139 loader::Symbol symbol = {loader::Symbol::Binding::Local,
"", 0x10};
140 ASSERT_FALSE(symtab.
insert(symbol));
145TEST(LoaderSymtabTest, InsertOneSymbol)
149 loader::Symbol symbol = {loader::Symbol::Binding::Local,
"symbol", 0x10};
150 ASSERT_TRUE(symtab.
insert(symbol));
152 ASSERT_FALSE(symtab.
empty());
157TEST(LoaderSymtabTest, InsertSymbolExistingName)
161 const std::string
name =
"symbol";
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]}));
174TEST(LoaderSymtabTest, InsertSymbolExistingAddress)
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]}));
191TEST(LoaderSymtabTest, InsertMultipleSymbols)
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]}));
210TEST(LoaderSymtabTest, ClearMultiple)
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());
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]));
249 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
257 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
258 expected_symbols[1], expected_symbols[2]}));
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],
294 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
295 expected_symbols[1], expected_symbols[2], expected_symbols[3]}));
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 =
321 ASSERT_TRUE(
checkTable(symtab, {symbols[0], symbols[1], symbols[2],
331 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
332 expected_symbols[1], expected_symbols[2], expected_symbols[3]}));
339TEST(LoaderSymtabTest, RenameNonUnique)
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],
373 ASSERT_TRUE(
checkTable(*symtab_new, {expected_symbols[0],
374 expected_symbols[1], expected_symbols[2]}));
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]}));
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]}));
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]}));
471TEST(LoaderSymtabTest, FindNonExistentAddress)
475 loader::Symbol symbol = {loader::Symbol::Binding::Local,
"symbol", 0x10};
476 EXPECT_TRUE(symtab.
insert(symbol));
478 ASSERT_EQ(symtab.
find(0x0), symtab.
end());
482TEST(LoaderSymtabTest, FindUniqueAddress)
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());
503TEST(LoaderSymtabTest, FindNonUniqueAddress)
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());
523TEST(LoaderSymtabTest, FindNonExistentName)
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());
535TEST(LoaderSymtabTest, FindExistingName)
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());
554TEST(LoaderSymtabTest, FindNearestExact)
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());
574TEST(LoaderSymtabTest, FindNearestRound)
578 loader::Symbol symbol = {loader::Symbol::Binding::Local,
"symbol", 0x10};
579 EXPECT_TRUE(symtab.
insert(symbol));
582 ASSERT_NE(it, symtab.
end());
591TEST(LoaderSymtabTest, FindNearestRoundWithNext)
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);
614TEST(LoaderSymtabTest, FindNearestRoundWithNextNonExistent)
618 loader::Symbol symbol = {loader::Symbol::Binding::Local,
"symbol", 0x10};
619 EXPECT_TRUE(symtab.
insert(symbol));
623 ASSERT_NE(it, symtab.
end());
625 ASSERT_EQ(next_addr, 0);
632TEST(LoaderSymtabTest, FindNearestNonExistent)
636 loader::Symbol symbol = {loader::Symbol::Binding::Local,
"symbol", 0x10};
637 EXPECT_TRUE(symtab.
insert(symbol));
640 ASSERT_EQ(it, symtab.
end());
647TEST(LoaderSymtabTest, InsertTableConflicting)
649 const std::string
name =
"symbol";
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},
661 EXPECT_TRUE(symtab.
insert(symbols[0]));
662 EXPECT_TRUE(symtab.
insert(symbols[1]));
663 EXPECT_TRUE(symtab.
insert(symbols[2]));
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]}));
682TEST(LoaderSymtabTest, InsertTable)
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},
694 EXPECT_TRUE(symtab.
insert(symbols[0]));
695 EXPECT_TRUE(symtab.
insert(symbols[1]));
696 EXPECT_TRUE(symtab.
insert(symbols[2]));
700 EXPECT_TRUE(symtab2.
insert(symbols[3]));
701 EXPECT_TRUE(symtab2.
insert(symbols[4]));
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]}));
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;
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"));
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");
762 ASSERT_TRUE(
checkTable(unserialized_symtab, {symbols[0], symbols[1],
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");
791 ASSERT_TRUE(
checkTable(unserialized_symtab, {symbols[0], symbols[1],
801 UnserializationMissingBindingChangeDefault)
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");
818 loader::Symbol::Binding::Weak);
822 ASSERT_TRUE(
checkTable(unserialized_symtab, {symbols[0], symbols[1],
Container for serializing global variables (not associated with any serialized object).
Fixture class that handles temporary directory creation.
SymbolTablePtr locals() const
Generates a new symbol table containing only local symbols.
SymbolTablePtr weaks() const
Generates a new symbol table containing only weak symbols.
bool empty() const
Verifies whether the table is empty.
SymbolTablePtr globals() const
Generates a new symbol table containing only global symbols.
void clear()
Clears the table.
const_iterator end() const
void unserialize(const std::string &base, CheckpointIn &cp, Symbol::Binding default_binding=Symbol::Binding::Global)
Populate the table by unserializing a checkpoint.
const_iterator begin() const
const_iterator findNearest(Addr addr, Addr &next_addr) const
Find the nearest symbol equal to or less than the supplied address (e.g., the label for the enclosing...
SymbolTablePtr mask(Addr m) const
Generate a new table by a mask to the symbols of the current table.
SymbolTablePtr offset(Addr addr_offset) const
Generate a new table by applying an offset to the symbols of the current table.
SymbolTablePtr rename(std::function< void(std::string &)> func) const
Modify the symbols' name with a given transform function.
void serialize(const std::string &base, CheckpointOut &cp) const
Serialize the table's contents.
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
const_iterator find(Addr address) const
Search for a symbol by its address.
std::vector< SwitchingFiber * > expected({ &a, &b, &a, &a, &a, &b, &c, &a, &c, &c, &c })
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
std::string getSymbolError(const loader::Symbol &symbol, const loader::Symbol &expected)
Checks if a symbol's contents matches the expected contents to generate an error message.
::testing::AssertionResult checkSymbol(const char *m_symbol, const char *m_expected, const loader::Symbol &symbol, const loader::Symbol &expected)
Checks that a symbol's contents matches the expected contents.
TEST_F(LoaderSymtabSerializationFixture, Serialization)
Test serialization.
::testing::AssertionResult checkTable(const loader::SymbolTable &symtab, const std::initializer_list< loader::Symbol > &expected)
Checks that a symbol table contains only the expected symbols.
TEST(LoaderSymtabTest, EmptyConstruction)
Test that the constructor creates an empty table.
const std::string & name()