gem5 v24.0.0.0
Loading...
Searching...
No Matches
symtab.test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Daniel R. Carvalho
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: 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 copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <gmock/gmock.h>
30#include <gtest/gtest-spi.h>
31#include <gtest/gtest.h>
32
33#include <cassert>
34#include <initializer_list>
35#include <sstream>
36
38#include "base/loader/symtab.hh"
39
40using namespace gem5;
41
50std::string
52{
53 std::stringstream ss;
54
55 if (symbol.binding() != expected.binding()) {
56 ss << " symbols' bindings do not match: seen `" <<
57 (int)symbol.binding() << "`, expected `" <<
58 (int)expected.binding() << "`.\n";
59 }
60
61 if (symbol.type() != expected.type()) {
62 ss << " symbols' types do not match: seen `" <<
63 (int)symbol.type() << "`, expected `" <<
64 (int)expected.type() << "`.\n";
65 }
66
67 if (symbol.name() != expected.name()) {
68 ss << " symbols' names do not match: seen `" << symbol.name() <<
69 "`, expected `" << expected.name() << "`.\n";
70 }
71
72 if (symbol.address() != expected.address()) {
73 ss << " symbols' addresses do not match: seen `" <<
74 symbol.address() << "`, expected `" << expected.address() << "`.\n";
75 }
76
77 // No error, symbols match
78 return ss.str();
79}
80
90::testing::AssertionResult
91checkSymbol(const char* m_symbol, const char* m_expected,
92 const loader::Symbol& symbol, const loader::Symbol& expected)
93{
94 const std::string error = getSymbolError(symbol, expected);
95 if (!error.empty()) {
96 return ::testing::AssertionFailure() << "Symbols do not match (" <<
97 m_symbol << " != " << m_expected << ")\n" << error;
98 }
99 return ::testing::AssertionSuccess();
100}
101
109::testing::AssertionResult
111 const std::initializer_list<loader::Symbol>& expected)
112{
113 if (expected.size() != (symtab.end() - symtab.begin())) {
114 return ::testing::AssertionFailure() << "the number of symbols in "
115 "the table does not match expectation (seen " <<
116 (symtab.end() - symtab.begin()) << ", expected " <<
117 expected.size();
118 }
119
120 // @todo We should not assume that the symbols are seen in the given order
121 auto it = symtab.begin();
122 for (const auto& symbol : expected) {
123 const std::string error = getSymbolError(*(it++), symbol);
124 if (!error.empty()) {
125 return ::testing::AssertionFailure() << error;
126 }
127 }
128
129 return ::testing::AssertionSuccess();
130}
131
133TEST(LoaderSymtabTest, EmptyConstruction)
134{
135 loader::SymbolTable symtab;
136 ASSERT_TRUE(symtab.empty());
137 ASSERT_TRUE(checkTable(symtab, {}));
138}
139
141TEST(LoaderSymtabTest, InsertSymbolNoName)
142{
143 loader::SymbolTable symtab;
144
145 loader::Symbol symbol = \
146 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
147 "", 0x10};
148 ASSERT_FALSE(symtab.insert(symbol));
149 ASSERT_TRUE(checkTable(symtab, {}));
150}
151
153TEST(LoaderSymtabTest, InsertOneSymbol)
154{
155 loader::SymbolTable symtab;
156
157 loader::Symbol symbol = \
158 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
159 "symbol", 0x10};
160 ASSERT_TRUE(symtab.insert(symbol));
161
162 ASSERT_FALSE(symtab.empty());
163 ASSERT_TRUE(checkTable(symtab, {symbol}));
164}
165
167TEST(LoaderSymtabTest, InsertSymbolExistingName)
168{
169 loader::SymbolTable symtab;
170
171 const std::string name = "symbol";
172 loader::Symbol symbols[] = {
173 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
174 name, 0x10},
175 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
176 name, 0x20},
177 };
178 ASSERT_TRUE(symtab.insert(symbols[0]));
179 ASSERT_FALSE(symtab.insert(symbols[1]));
180
181 // Check that the second symbol has not been inserted
182 ASSERT_TRUE(checkTable(symtab, {symbols[0]}));
183}
184
186TEST(LoaderSymtabTest, InsertSymbolExistingAddress)
187{
188 loader::SymbolTable symtab;
189
190 const Addr addr = 0x10;
191 loader::Symbol symbols[] = {
192 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
193 "symbol", addr},
194 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
195 "symbol2", addr},
196 };
197 ASSERT_TRUE(symtab.insert(symbols[0]));
198 ASSERT_TRUE(symtab.insert(symbols[1]));
199
200 // Check that all symbols are present
201 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1]}));
202}
203
205TEST(LoaderSymtabTest, InsertMultipleSymbols)
206{
207 loader::SymbolTable symtab;
208
209 loader::Symbol symbols[] = {
210 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
211 "symbol", 0x10},
212 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
213 "symbol2", 0x20},
214 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
215 "symbol3", 0x30},
216 };
217 EXPECT_TRUE(symtab.insert(symbols[0]));
218 EXPECT_TRUE(symtab.insert(symbols[1]));
219 EXPECT_TRUE(symtab.insert(symbols[2]));
220
221 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
222}
223
227TEST(LoaderSymtabTest, ClearMultiple)
228{
229 loader::SymbolTable symtab;
230
231 loader::Symbol symbols[] = {
232 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
233 "symbol", 0x10},
234 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
235 "symbol2", 0x20},
236 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
237 "symbol3", 0x30},
238 };
239 EXPECT_TRUE(symtab.insert(symbols[0]));
240 EXPECT_TRUE(symtab.insert(symbols[1]));
241 EXPECT_TRUE(symtab.insert(symbols[2]));
242
243 symtab.clear();
244 ASSERT_TRUE(symtab.empty());
245 ASSERT_TRUE(checkTable(symtab, {}));
246}
247
252TEST(LoaderSymtabTest, Offset)
253{
254 loader::SymbolTable symtab;
255
256 loader::Symbol symbols[] = {
257 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
258 "symbol", 0x10},
259 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
260 "symbol2", 0x20},
261 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
262 "symbol3", 0x30},
263 };
264 EXPECT_TRUE(symtab.insert(symbols[0]));
265 EXPECT_TRUE(symtab.insert(symbols[1]));
266 EXPECT_TRUE(symtab.insert(symbols[2]));
267
268 Addr offset = 0x5;
269 const auto symtab_new = symtab.offset(offset);
270
271 // Check that the original table is not modified
272 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
273
274 // Check that the new table is offset
275 loader::Symbol expected_symbols[] = {
276 {symbols[0].binding(), symbols[0].type(), symbols[0].name(),
277 symbols[0].address() + offset},
278 {symbols[1].binding(), symbols[1].type(), symbols[1].name(),
279 symbols[1].address() + offset},
280 {symbols[2].binding(), symbols[2].type(), symbols[2].name(),
281 symbols[2].address() + offset},
282 };
283 ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0],
284 expected_symbols[1], expected_symbols[2]}));
285}
286
291TEST(LoaderSymtabTest, Mask)
292{
293 loader::SymbolTable symtab;
294
295 loader::Symbol symbols[] = {
296 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
297 "symbol", 0x1310},
298 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
299 "symbol2", 0x2810},
300 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
301 "symbol3", 0x2920},
302 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
303 "symbol4", 0x3C20},
304 };
305 EXPECT_TRUE(symtab.insert(symbols[0]));
306 EXPECT_TRUE(symtab.insert(symbols[1]));
307 EXPECT_TRUE(symtab.insert(symbols[2]));
308 EXPECT_TRUE(symtab.insert(symbols[3]));
309
310 Addr mask = 0x0110;
311 const auto symtab_new = symtab.mask(mask);
312
313 // Check that the original table is not modified
314 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
315 symbols[3]}));
316
317 // Check that the new table is masked
318 loader::Symbol expected_symbols[] = {
319 {symbols[0].binding(), symbols[0].type(), symbols[0].name(),
320 symbols[0].address() & mask},
321 {symbols[1].binding(), symbols[1].type(), symbols[1].name(),
322 symbols[1].address() & mask},
323 {symbols[2].binding(), symbols[2].type(), symbols[2].name(),
324 symbols[2].address() & mask},
325 {symbols[3].binding(), symbols[3].type(), symbols[3].name(),
326 symbols[3].address() & mask},
327 };
328 ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0],
329 expected_symbols[1], expected_symbols[2], expected_symbols[3]}));
330}
331
336TEST(LoaderSymtabTest, Rename)
337{
338 loader::SymbolTable symtab;
339
340 loader::Symbol symbols[] = {
341 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
342 "symbol", 0x10},
343 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
344 "symbol2", 0x20},
345 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
346 "symbol3", 0x30},
347 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
348 "symbol4", 0x40},
349 };
350 EXPECT_TRUE(symtab.insert(symbols[0]));
351 EXPECT_TRUE(symtab.insert(symbols[1]));
352 EXPECT_TRUE(symtab.insert(symbols[2]));
353 EXPECT_TRUE(symtab.insert(symbols[3]));
354
355 const auto symtab_new =
356 symtab.rename([](const std::string &name) { return name + "_suffix"; });
357
358 // Check that the original table is not modified
359 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
360 symbols[3]}));
361
362 // Check that the new table's symbols have been renamed
363 loader::Symbol expected_symbols[] = {
364 {symbols[0].binding(), symbols[0].type(), symbols[0].name() + "_suffix",
365 symbols[0].address()},
366 {symbols[1].binding(), symbols[1].type(), symbols[1].name() + "_suffix",
367 symbols[1].address()},
368 {symbols[2].binding(), symbols[2].type(), symbols[2].name() + "_suffix",
369 symbols[2].address()},
370 {symbols[3].binding(), symbols[3].type(), symbols[3].name() + "_suffix",
371 symbols[3].address()},
372 };
373 ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0],
374 expected_symbols[1], expected_symbols[2], expected_symbols[3]}));
375}
376
381TEST(LoaderSymtabTest, RenameNonUnique)
382{
383 loader::SymbolTable symtab;
384
385 loader::Symbol symbols[] = {
386 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
387 "symbol", 0x10},
388 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
389 "symbol2", 0x20},
390 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
391 "symbol3", 0x30},
392 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
393 "symbol4", 0x40},
394 };
395 EXPECT_TRUE(symtab.insert(symbols[0]));
396 EXPECT_TRUE(symtab.insert(symbols[1]));
397 EXPECT_TRUE(symtab.insert(symbols[2]));
398 EXPECT_TRUE(symtab.insert(symbols[3]));
399
400 int i = 0;
401 const auto symtab_new = symtab.rename([&i](const std::string &name)
402 {
403 if ((i++ % 2) == 0) {
404 return std::string("NonUniqueName");
405 } else {
406 return name;
407 }
408 });
409
410 // Check that the original table is not modified
411 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
412 symbols[3]}));
413
414 // Check that the new table's symbols have been renamed, yet it does not
415 // contain the symbols with duplicated names
416 loader::Symbol expected_symbols[] = {
417 {symbols[0].binding(), symbols[0].type(), "NonUniqueName",
418 symbols[0].address()},
419 {symbols[1].binding(), symbols[1].type(), symbols[1].name(),
420 symbols[1].address()},
421 {symbols[3].binding(), symbols[3].type(), symbols[3].name(),
422 symbols[3].address()},
423 };
424 ASSERT_TRUE(checkTable(*symtab_new, {expected_symbols[0],
425 expected_symbols[1], expected_symbols[2]}));
426}
427
432TEST(LoaderSymtabTest, Globals)
433{
434 loader::SymbolTable symtab;
435
436 loader::Symbol symbols[] = {
437 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
438 "symbol", 0x10},
439 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other,
440 "symbol2", 0x20},
441 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
442 "symbol3", 0x30},
443 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
444 "symbol4", 0x40},
445 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
446 "symbol5", 0x50}
447 };
448 EXPECT_TRUE(symtab.insert(symbols[0]));
449 EXPECT_TRUE(symtab.insert(symbols[1]));
450 EXPECT_TRUE(symtab.insert(symbols[2]));
451 EXPECT_TRUE(symtab.insert(symbols[3]));
452 EXPECT_TRUE(symtab.insert(symbols[4]));
453
454 const auto symtab_new = symtab.globals();
455
456 // Check that the original table is not modified
457 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
458 symbols[3], symbols[4]}));
459
460 // Check that the new table only contains globals
461 ASSERT_TRUE(checkTable(*symtab_new, {symbols[1]}));
462}
463
468TEST(LoaderSymtabTest, Locals)
469{
470 loader::SymbolTable symtab;
471
472 loader::Symbol symbols[] = {
473 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
474 "symbol", 0x10},
475 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other,
476 "symbol2", 0x20},
477 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
478 "symbol3", 0x30},
479 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
480 "symbol4", 0x40},
481 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
482 "symbol5", 0x50}
483 };
484 EXPECT_TRUE(symtab.insert(symbols[0]));
485 EXPECT_TRUE(symtab.insert(symbols[1]));
486 EXPECT_TRUE(symtab.insert(symbols[2]));
487 EXPECT_TRUE(symtab.insert(symbols[3]));
488 EXPECT_TRUE(symtab.insert(symbols[4]));
489
490 const auto symtab_new = symtab.locals();
491
492 // Check that the original table is not modified
493 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
494 symbols[3], symbols[4]}));
495
496 // Check that the new table only contains locals
497 ASSERT_TRUE(checkTable(*symtab_new, {symbols[0], symbols[2]}));
498}
499
504TEST(LoaderSymtabTest, Weaks)
505{
506 loader::SymbolTable symtab;
507
508 loader::Symbol symbols[] = {
509 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
510 "symbol", 0x10},
511 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other,
512 "symbol2", 0x20},
513 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
514 "symbol3", 0x30},
515 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
516 "symbol4", 0x40},
517 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
518 "symbol5", 0x50}
519 };
520 EXPECT_TRUE(symtab.insert(symbols[0]));
521 EXPECT_TRUE(symtab.insert(symbols[1]));
522 EXPECT_TRUE(symtab.insert(symbols[2]));
523 EXPECT_TRUE(symtab.insert(symbols[3]));
524 EXPECT_TRUE(symtab.insert(symbols[4]));
525
526 const auto symtab_new = symtab.weaks();
527
528 // Check that the original table is not modified
529 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
530 symbols[3], symbols[4]}));
531
532 // Check that the new table only contains weaks
533 ASSERT_TRUE(checkTable(*symtab_new, {symbols[3], symbols[4]}));
534}
535
540TEST(LoaderSymtabTest, FunctionSymbols)
541{
542 loader::SymbolTable symtab;
543
544 loader::Symbol symbols[] = {
545 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::NoType,
546 "symbol", 0x10},
547 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::File,
548 "symbol2", 0x20},
549 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Function,
550 "symbol3", 0x30},
551 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Object,
552 "symbol4", 0x40},
553 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Function,
554 "symbol5", 0x50}
555 };
556 EXPECT_TRUE(symtab.insert(symbols[0]));
557 EXPECT_TRUE(symtab.insert(symbols[1]));
558 EXPECT_TRUE(symtab.insert(symbols[2]));
559 EXPECT_TRUE(symtab.insert(symbols[3]));
560 EXPECT_TRUE(symtab.insert(symbols[4]));
561
562 const auto symtab_new = symtab.functionSymbols();
563
564 // Check that the original table is not modified
565 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
566 symbols[3], symbols[4]}));
567
568 // Check that the new table only contains function symbols
569 ASSERT_TRUE(checkTable(*symtab_new, {symbols[2], symbols[4]}));
570}
571
573TEST(LoaderSymtabTest, FindNonExistentAddress)
574{
575 loader::SymbolTable symtab;
576
577 loader::Symbol symbol = \
578 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
579 "symbol", 0x10};
580 EXPECT_TRUE(symtab.insert(symbol));
581
582 ASSERT_EQ(symtab.find(0x0), symtab.end());
583}
584
586TEST(LoaderSymtabTest, FindUniqueAddress)
587{
588 loader::SymbolTable symtab;
589
590 loader::Symbol symbols[] = {
591 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
592 "symbol", 0x10},
593 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
594 "symbol2", 0x20},
595 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
596 "symbol3", 0x30},
597 };
598 EXPECT_TRUE(symtab.insert(symbols[0]));
599 EXPECT_TRUE(symtab.insert(symbols[1]));
600 EXPECT_TRUE(symtab.insert(symbols[2]));
601
602 const auto it = symtab.find(symbols[2].address());
603 ASSERT_NE(it, symtab.end());
604 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[2]);
605}
606
610TEST(LoaderSymtabTest, FindNonUniqueAddress)
611{
612 loader::SymbolTable symtab;
613
614 const Addr addr = 0x20;
615 loader::Symbol symbols[] = {
616 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
617 "symbol", 0x10},
618 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
619 "symbol2", addr},
620 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
621 "symbol3", addr},
622 };
623 EXPECT_TRUE(symtab.insert(symbols[0]));
624 EXPECT_TRUE(symtab.insert(symbols[1]));
625 EXPECT_TRUE(symtab.insert(symbols[2]));
626
627 const auto it = symtab.find(symbols[1].address());
628 ASSERT_NE(it, symtab.end());
629 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[1]);
630}
631
633TEST(LoaderSymtabTest, FindNonExistentName)
634{
635 loader::SymbolTable symtab;
636
637 loader::Symbol symbol = \
638 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
639 "symbol", 0x10};
640 EXPECT_TRUE(symtab.insert(symbol));
641
642 const auto it = symtab.find("symbol2");
643 ASSERT_EQ(it, symtab.end());
644}
645
647TEST(LoaderSymtabTest, FindExistingName)
648{
649 loader::SymbolTable symtab;
650
651 loader::Symbol symbols[] = {
652 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
653 "symbol", 0x10},
654 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
655 "symbol2", 0x20},
656 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
657 "symbol3", 0x30},
658 };
659 EXPECT_TRUE(symtab.insert(symbols[0]));
660 EXPECT_TRUE(symtab.insert(symbols[1]));
661 EXPECT_TRUE(symtab.insert(symbols[2]));
662
663 const auto it = symtab.find(symbols[1].name());
664 ASSERT_NE(it, symtab.end());
665 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[1]);
666}
667
669TEST(LoaderSymtabTest, FindNearestExact)
670{
671 loader::SymbolTable symtab;
672
673 loader::Symbol symbols[] = {
674 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
675 "symbol", 0x10},
676 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
677 "symbol2", 0x20},
678 };
679 EXPECT_TRUE(symtab.insert(symbols[0]));
680 EXPECT_TRUE(symtab.insert(symbols[1]));
681
682 const auto it = symtab.findNearest(symbols[1].address());
683 ASSERT_NE(it, symtab.end());
684 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[1]);
685}
686
691TEST(LoaderSymtabTest, FindNearestRound)
692{
693 loader::SymbolTable symtab;
694
695 loader::Symbol symbol = \
696 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
697 "symbol", 0x10};
698 EXPECT_TRUE(symtab.insert(symbol));
699
700 const auto it = symtab.findNearest(symbol.address() + 0x1);
701 ASSERT_NE(it, symtab.end());
702 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbol);
703}
704
710TEST(LoaderSymtabTest, FindNearestRoundWithNext)
711{
712 loader::SymbolTable symtab;
713
714 loader::Symbol symbols[] = {
715 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
716 "symbol", 0x10},
717 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
718 "symbol2", 0x20},
719 };
720 EXPECT_TRUE(symtab.insert(symbols[0]));
721 EXPECT_TRUE(symtab.insert(symbols[1]));
722
723 Addr next_addr = 0;
724 const auto it = symtab.findNearest(symbols[0].address() + 0x1, next_addr);
725 ASSERT_NE(it, symtab.end());
726 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbols[0]);
727 ASSERT_EQ(next_addr, symbols[1].address());
728}
729
735TEST(LoaderSymtabTest, FindNearestRoundWithNextNonExistent)
736{
737 loader::SymbolTable symtab;
738
739 loader::Symbol symbol = \
740 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
741 "symbol", 0x10};
742 EXPECT_TRUE(symtab.insert(symbol));
743
744 Addr next_addr = 0;
745 const auto it = symtab.findNearest(symbol.address() + 0x1, next_addr);
746 ASSERT_NE(it, symtab.end());
747 ASSERT_PRED_FORMAT2(checkSymbol, *it, symbol);
748 ASSERT_EQ(next_addr, 0);
749}
750
755TEST(LoaderSymtabTest, FindNearestNonExistent)
756{
757 loader::SymbolTable symtab;
758
759 loader::Symbol symbol = \
760 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
761 "symbol", 0x10};
762 EXPECT_TRUE(symtab.insert(symbol));
763
764 const auto it = symtab.findNearest(symbol.address() - 0x1);
765 ASSERT_EQ(it, symtab.end());
766}
767
772TEST(LoaderSymtabTest, InsertTableConflicting)
773{
774 const std::string name = "symbol";
775 loader::Symbol symbols[] = {
776 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
777 name, 0x10},
778 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
779 "symbol2", 0x20},
780 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
781 "symbol3", 0x30},
782 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
783 "symbol4", 0x40},
784 // Introduce name conflict
785 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
786 name, 0x50},
787 };
788
789 // Populate table 1
790 loader::SymbolTable symtab;
791 EXPECT_TRUE(symtab.insert(symbols[0]));
792 EXPECT_TRUE(symtab.insert(symbols[1]));
793 EXPECT_TRUE(symtab.insert(symbols[2]));
794
795 // Populate table 2
796 loader::SymbolTable symtab2;
797 EXPECT_TRUE(symtab2.insert(symbols[3]));
798 EXPECT_TRUE(symtab2.insert(symbols[4]));
799
800 // Do the insertion
801 ASSERT_FALSE(symtab.insert(symtab2));
802
803 // Check that none of the tables change
804 ASSERT_TRUE(checkTable(symtab2, {symbols[3], symbols[4]}));
805 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2]}));
806}
807
812TEST(LoaderSymtabTest, InsertTable)
813{
814 loader::Symbol symbols[] = {
815 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
816 "symbol", 0x10},
817 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
818 "symbol2", 0x20},
819 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
820 "symbol3", 0x30},
821 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
822 "symbol4", 0x40},
823 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
824 "symbol5", 0x50},
825 };
826
827 // Populate table 1
828 loader::SymbolTable symtab;
829 EXPECT_TRUE(symtab.insert(symbols[0]));
830 EXPECT_TRUE(symtab.insert(symbols[1]));
831 EXPECT_TRUE(symtab.insert(symbols[2]));
832
833 // Populate table 2
834 loader::SymbolTable symtab2;
835 EXPECT_TRUE(symtab2.insert(symbols[3]));
836 EXPECT_TRUE(symtab2.insert(symbols[4]));
837
838 // Do the insertion
839 symtab.insert(symtab2);
840
841 // Check that symtab2 does not change
842 ASSERT_TRUE(checkTable(symtab2, {symbols[3], symbols[4]}));
843
844 // Check that the symbols from symtab2 have been inserted in symtab
845 ASSERT_TRUE(checkTable(symtab, {symbols[0], symbols[1], symbols[2],
846 symbols[3], symbols[4]}));
847}
848
850
853{
854 // Populate the table
855 loader::SymbolTable symtab;
856 loader::Symbol symbols[] = {
857 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
858 "symbol", 0x10},
859 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
860 "symbol2", 0x20},
861 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
862 "symbol3", 0x30},
863 };
864 EXPECT_TRUE(symtab.insert(symbols[0]));
865 EXPECT_TRUE(symtab.insert(symbols[1]));
866 EXPECT_TRUE(symtab.insert(symbols[2]));
867
868 // Serialization
869 std::ostringstream cp;
871 symtab.serialize("test", cp);
872
873 // Verify the output
874 ASSERT_THAT(cp.str(), ::testing::StrEq("\n[Section1]\ntest.size=3\n"
875 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
876 "test.type_0=5\n"
877 "test.addr_1=32\ntest.symbol_1=symbol2\ntest.binding_1=1\n"
878 "test.type_1=5\n"
879 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"
880 "test.type_2=5\n"));
881}
882
885{
886 loader::Symbol symbols[] = {
887 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
888 "symbol", 0x10},
889 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
890 "symbol2", 0x20},
891 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
892 "symbol3", 0x30},
893 };
894 simulateSerialization("\n[Section1]\ntest.size=3\n"
895 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
896 "test.type_0=5\n"
897 "test.addr_1=32\ntest.symbol_1=symbol2\ntest.binding_1=1\n"
898 "test.type_1=5\n"
899 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"
900 "test.type_2=5\n");
901
902 loader::SymbolTable unserialized_symtab;
903 CheckpointIn cp(getDirName());
905 unserialized_symtab.unserialize("test", cp);
906
907 // Make sure that the symbols in symtab are present in the
908 // unserialized table
909 ASSERT_TRUE(checkTable(unserialized_symtab, {symbols[0], symbols[1],
910 symbols[2]}));
911}
912
918TEST_F(LoaderSymtabSerializationFixture, UnserializationMissingBinding)
919{
920 loader::Symbol symbols[] = {
921 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
922 "symbol", 0x10},
923 {loader::Symbol::Binding::Global, loader::Symbol::SymbolType::Other,
924 "symbol2", 0x20},
925 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
926 "symbol3", 0x30},
927 };
928 simulateSerialization("\n[Section1]\ntest.size=3\n"
929 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
930 "test.type_0=5\n"
931 "test.addr_1=32\ntest.symbol_1=symbol2\ntest.type_1=5\n"
932 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"
933 "test.type_2=5\n");
934
935 loader::SymbolTable unserialized_symtab;
936 CheckpointIn cp(getDirName());
938
939 unserialized_symtab.unserialize("test", cp);
940
941 // Make sure that the symbols in symtab are present in the
942 // unserialized table
943 ASSERT_TRUE(checkTable(unserialized_symtab, {symbols[0], symbols[1],
944 symbols[2]}));
945}
946
953 UnserializationMissingBindingChangeDefault)
954{
955 loader::Symbol symbols[] = {
956 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
957 "symbol", 0x10},
958 {loader::Symbol::Binding::Weak, loader::Symbol::SymbolType::Other,
959 "symbol2", 0x20},
960 {loader::Symbol::Binding::Local, loader::Symbol::SymbolType::Other,
961 "symbol3", 0x30},
962 };
963 simulateSerialization("\n[Section1]\ntest.size=3\n"
964 "test.addr_0=16\ntest.symbol_0=symbol\ntest.binding_0=1\n"
965 "test.type_0=5\n"
966 "test.addr_1=32\ntest.symbol_1=symbol2\n"
967 "test.type_1=5\n"
968 "test.addr_2=48\ntest.symbol_2=symbol3\ntest.binding_2=1\n"
969 "test.type_2=5\n");
970
971 loader::SymbolTable unserialized_symtab;
972 CheckpointIn cp(getDirName());
974
975 unserialized_symtab.unserialize("test", cp,
976 loader::Symbol::Binding::Weak);
977
978 // Make sure that the symbols in symtab are present in the
979 // unserialized table
980 ASSERT_TRUE(checkTable(unserialized_symtab, {symbols[0], symbols[1],
981 symbols[2]}));
982}
std::string error
Container for serializing global variables (not associated with any serialized object).
Definition globals.hh:55
Fixture class that handles temporary directory creation.
SymbolTablePtr functionSymbols() const
Generates a new symbol table containing only function symbols.
Definition symtab.hh:402
SymbolTablePtr locals() const
Generates a new symbol table containing only local symbols.
Definition symtab.hh:380
SymbolTablePtr weaks() const
Generates a new symbol table containing only weak symbols.
Definition symtab.hh:391
bool empty() const
Verifies whether the table is empty.
Definition symtab.hh:306
SymbolTablePtr globals() const
Generates a new symbol table containing only global symbols.
Definition symtab.hh:369
SymbolTablePtr rename(std::function< std::string(const std::string &)> func) const
Modify the symbols' name with a given transform function.
Definition symtab.hh:353
void clear()
Clears the table.
Definition symtab.cc:58
const_iterator end() const
Definition symtab.hh:278
void unserialize(const std::string &base, CheckpointIn &cp, Symbol::Binding default_binding=Symbol::Binding::Global)
Populate the table by unserializing a checkpoint.
Definition symtab.cc:127
const_iterator begin() const
Definition symtab.hh:275
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...
Definition symtab.hh:474
SymbolTablePtr mask(Addr m) const
Generate a new table by a mask to the symbols of the current table.
Definition symtab.hh:335
SymbolTablePtr offset(Addr addr_offset) const
Generate a new table by applying an offset to the symbols of the current table.
Definition symtab.hh:316
void serialize(const std::string &base, CheckpointOut &cp) const
Serialize the table's contents.
Definition symtab.cc:107
bool insert(const Symbol &symbol)
Insert a new symbol in the table if it does not already exist.
Definition symtab.cc:66
const_iterator find(Addr address) const
Search for a symbol by its address.
Definition symtab.hh:435
SymbolType type() const
Definition symtab.hh:102
Binding binding() const
Definition symtab.hh:98
std::string name() const
Definition symtab.hh:106
Addr address() const
Definition symtab.hh:114
std::vector< SwitchingFiber * > expected({ &a, &b, &a, &a, &a, &b, &c, &a, &c, &c, &c })
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 21 > ss
Definition misc_types.hh:60
Bitfield< 18 > scs
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
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()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:00 for gem5 by doxygen 1.11.0