1 | //===-- SymbolTest.cpp ----------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" |
10 | #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" |
11 | #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" |
12 | #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" |
13 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
14 | #include "TestingSupport/SubsystemRAII.h" |
15 | #include "TestingSupport/TestUtilities.h" |
16 | |
17 | #include "lldb/Core/DataFileCache.h" |
18 | #include "lldb/Core/Module.h" |
19 | #include "lldb/Host/FileSystem.h" |
20 | #include "lldb/Host/HostInfo.h" |
21 | #include "lldb/Symbol/Symbol.h" |
22 | #include "lldb/Symbol/Symtab.h" |
23 | #include "lldb/Utility/DataEncoder.h" |
24 | #include "lldb/Utility/DataExtractor.h" |
25 | |
26 | #include <memory> |
27 | |
28 | #include "gtest/gtest.h" |
29 | |
30 | using namespace lldb; |
31 | using namespace lldb_private; |
32 | using namespace lldb_private::plugin::dwarf; |
33 | |
34 | class SymtabTest : public testing::Test { |
35 | SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO, SymbolFileDWARF, |
36 | ObjectFileELF, SymbolFileSymtab, TypeSystemClang> |
37 | subsystem; |
38 | }; |
39 | |
40 | static void EncodeDecode(const Symtab &object, ByteOrder byte_order) { |
41 | const uint8_t addr_size = 8; |
42 | DataEncoder file(byte_order, addr_size); |
43 | |
44 | object.Encode(encoder&: file); |
45 | llvm::ArrayRef<uint8_t> bytes = file.GetData(); |
46 | DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size); |
47 | Symtab decoded_object(object.GetObjectFile()); |
48 | offset_t data_offset = 0; |
49 | bool uuid_mismatch = false; |
50 | decoded_object.Decode(data, offset_ptr: &data_offset, uuid_mismatch); |
51 | ASSERT_EQ(object.GetNumSymbols(), decoded_object.GetNumSymbols()); |
52 | for (size_t i = 0; i < object.GetNumSymbols(); ++i) |
53 | EXPECT_EQ(*object.SymbolAtIndex(i), *decoded_object.SymbolAtIndex(i)); |
54 | } |
55 | |
56 | static void EncodeDecode(const Symtab &object) { |
57 | EncodeDecode(object, byte_order: eByteOrderLittle); |
58 | EncodeDecode(object, byte_order: eByteOrderBig); |
59 | } |
60 | |
61 | TEST_F(SymtabTest, EncodeDecodeSymtab) { |
62 | |
63 | auto ExpectedFile = TestFile::fromYaml(Yaml: R"( |
64 | --- !mach-o |
65 | FileHeader: |
66 | magic: 0xFEEDFACF |
67 | cputype: 0x100000C |
68 | cpusubtype: 0x0 |
69 | filetype: 0x2 |
70 | ncmds: 17 |
71 | sizeofcmds: 792 |
72 | flags: 0x200085 |
73 | reserved: 0x0 |
74 | LoadCommands: |
75 | - cmd: LC_SEGMENT_64 |
76 | cmdsize: 72 |
77 | segname: __PAGEZERO |
78 | vmaddr: 0 |
79 | vmsize: 4294967296 |
80 | fileoff: 0 |
81 | filesize: 0 |
82 | maxprot: 0 |
83 | initprot: 0 |
84 | nsects: 0 |
85 | flags: 0 |
86 | - cmd: LC_SEGMENT_64 |
87 | cmdsize: 232 |
88 | segname: __TEXT |
89 | vmaddr: 4294967296 |
90 | vmsize: 16384 |
91 | fileoff: 0 |
92 | filesize: 16384 |
93 | maxprot: 5 |
94 | initprot: 5 |
95 | nsects: 2 |
96 | flags: 0 |
97 | Sections: |
98 | - sectname: __text |
99 | segname: __TEXT |
100 | addr: 0x100003F94 |
101 | size: 36 |
102 | offset: 0x3F94 |
103 | align: 2 |
104 | reloff: 0x0 |
105 | nreloc: 0 |
106 | flags: 0x80000400 |
107 | reserved1: 0x0 |
108 | reserved2: 0x0 |
109 | reserved3: 0x0 |
110 | content: FF8300D1E80300AA00008052FF1F00B9E81B00B9E10B00F9E20700F9FF830091C0035FD6 |
111 | - sectname: __unwind_info |
112 | segname: __TEXT |
113 | addr: 0x100003FB8 |
114 | size: 72 |
115 | offset: 0x3FB8 |
116 | align: 2 |
117 | reloff: 0x0 |
118 | nreloc: 0 |
119 | flags: 0x0 |
120 | reserved1: 0x0 |
121 | reserved2: 0x0 |
122 | reserved3: 0x0 |
123 | content: 010000001C000000000000001C000000000000001C00000002000000943F00003400000034000000B93F00000000000034000000030000000C000100100001000000000000200002 |
124 | - cmd: LC_SEGMENT_64 |
125 | cmdsize: 72 |
126 | segname: __LINKEDIT |
127 | vmaddr: 4294983680 |
128 | vmsize: 16384 |
129 | fileoff: 16384 |
130 | filesize: 674 |
131 | maxprot: 1 |
132 | initprot: 1 |
133 | nsects: 0 |
134 | flags: 0 |
135 | - cmd: LC_DYLD_CHAINED_FIXUPS |
136 | cmdsize: 16 |
137 | dataoff: 16384 |
138 | datasize: 56 |
139 | - cmd: LC_DYLD_EXPORTS_TRIE |
140 | cmdsize: 16 |
141 | dataoff: 16440 |
142 | datasize: 48 |
143 | - cmd: LC_SYMTAB |
144 | cmdsize: 24 |
145 | symoff: 16496 |
146 | nsyms: 10 |
147 | stroff: 16656 |
148 | strsize: 128 |
149 | - cmd: LC_DYSYMTAB |
150 | cmdsize: 80 |
151 | ilocalsym: 0 |
152 | nlocalsym: 8 |
153 | iextdefsym: 8 |
154 | nextdefsym: 2 |
155 | iundefsym: 10 |
156 | nundefsym: 0 |
157 | tocoff: 0 |
158 | ntoc: 0 |
159 | modtaboff: 0 |
160 | nmodtab: 0 |
161 | extrefsymoff: 0 |
162 | nextrefsyms: 0 |
163 | indirectsymoff: 0 |
164 | nindirectsyms: 0 |
165 | extreloff: 0 |
166 | nextrel: 0 |
167 | locreloff: 0 |
168 | nlocrel: 0 |
169 | - cmd: LC_LOAD_DYLINKER |
170 | cmdsize: 32 |
171 | name: 12 |
172 | Content: '/usr/lib/dyld' |
173 | ZeroPadBytes: 7 |
174 | - cmd: LC_UUID |
175 | cmdsize: 24 |
176 | uuid: 1EECD2B8-16EA-3FEC-AB3C-F46139DBD0E2 |
177 | - cmd: LC_BUILD_VERSION |
178 | cmdsize: 32 |
179 | platform: 1 |
180 | minos: 786432 |
181 | sdk: 786432 |
182 | ntools: 1 |
183 | Tools: |
184 | - tool: 3 |
185 | version: 46596096 |
186 | - cmd: LC_SOURCE_VERSION |
187 | cmdsize: 16 |
188 | version: 0 |
189 | - cmd: LC_MAIN |
190 | cmdsize: 24 |
191 | entryoff: 16276 |
192 | stacksize: 0 |
193 | - cmd: LC_LOAD_DYLIB |
194 | cmdsize: 48 |
195 | dylib: |
196 | name: 24 |
197 | timestamp: 2 |
198 | current_version: 78643968 |
199 | compatibility_version: 65536 |
200 | Content: '/usr/lib/libc++.1.dylib' |
201 | ZeroPadBytes: 1 |
202 | - cmd: LC_LOAD_DYLIB |
203 | cmdsize: 56 |
204 | dylib: |
205 | name: 24 |
206 | timestamp: 2 |
207 | current_version: 85917696 |
208 | compatibility_version: 65536 |
209 | Content: '/usr/lib/libSystem.B.dylib' |
210 | ZeroPadBytes: 6 |
211 | - cmd: LC_FUNCTION_STARTS |
212 | cmdsize: 16 |
213 | dataoff: 16488 |
214 | datasize: 8 |
215 | - cmd: LC_DATA_IN_CODE |
216 | cmdsize: 16 |
217 | dataoff: 16496 |
218 | datasize: 0 |
219 | - cmd: LC_CODE_SIGNATURE |
220 | cmdsize: 16 |
221 | dataoff: 16784 |
222 | datasize: 274 |
223 | LinkEditData: |
224 | NameList: |
225 | - n_strx: 28 |
226 | n_type: 0x64 |
227 | n_sect: 0 |
228 | n_desc: 0 |
229 | n_value: 0 |
230 | - n_strx: 64 |
231 | n_type: 0x64 |
232 | n_sect: 0 |
233 | n_desc: 0 |
234 | n_value: 0 |
235 | - n_strx: 73 |
236 | n_type: 0x66 |
237 | n_sect: 0 |
238 | n_desc: 1 |
239 | n_value: 1639532873 |
240 | - n_strx: 1 |
241 | n_type: 0x2E |
242 | n_sect: 1 |
243 | n_desc: 0 |
244 | n_value: 4294983572 |
245 | - n_strx: 115 |
246 | n_type: 0x24 |
247 | n_sect: 1 |
248 | n_desc: 0 |
249 | n_value: 4294983572 |
250 | - n_strx: 1 |
251 | n_type: 0x24 |
252 | n_sect: 0 |
253 | n_desc: 0 |
254 | n_value: 36 |
255 | - n_strx: 1 |
256 | n_type: 0x4E |
257 | n_sect: 1 |
258 | n_desc: 0 |
259 | n_value: 36 |
260 | - n_strx: 1 |
261 | n_type: 0x64 |
262 | n_sect: 1 |
263 | n_desc: 0 |
264 | n_value: 0 |
265 | - n_strx: 2 |
266 | n_type: 0xF |
267 | n_sect: 1 |
268 | n_desc: 16 |
269 | n_value: 4294967296 |
270 | - n_strx: 22 |
271 | n_type: 0xF |
272 | n_sect: 1 |
273 | n_desc: 0 |
274 | n_value: 4294983572 |
275 | StringTable: |
276 | - ' ' |
277 | - __mh_execute_header |
278 | - _main |
279 | - '/Users/gclayton/Documents/src/args/' |
280 | - main.cpp |
281 | - '/Users/gclayton/Documents/src/args/main.o' |
282 | - _main |
283 | - '' |
284 | - '' |
285 | - '' |
286 | - '' |
287 | - '' |
288 | - '' |
289 | - '' |
290 | ... |
291 | )" ); |
292 | |
293 | ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); |
294 | auto module_sp = std::make_shared<Module>(args: ExpectedFile->moduleSpec()); |
295 | ObjectFile *objfile = module_sp->GetObjectFile(); |
296 | ASSERT_NE(objfile, nullptr); |
297 | |
298 | // Test encoding and decoding an empty symbol table. |
299 | Symtab symtab(objfile); |
300 | symtab.PreloadSymbols(); |
301 | EncodeDecode(object: symtab); |
302 | |
303 | // Now encode and decode an actual symbol table from our yaml. |
304 | Symtab *module_symtab = module_sp->GetSymtab(); |
305 | ASSERT_NE(module_symtab, nullptr); |
306 | module_symtab->PreloadSymbols(); |
307 | EncodeDecode(object: *module_symtab); |
308 | } |
309 | |
310 | TEST_F(SymtabTest, TestDecodeCStringMaps) { |
311 | // Symbol tables save out the symbols, but they also save out the symbol table |
312 | // name indexes. These name indexes are a map of sorted ConstString + T pairs |
313 | // and when they are decoded from a file, they are no longer sorted since |
314 | // ConstString objects can be sorted by "const char *" and the order in which |
315 | // these strings are created won't be the same in a new process. We need to |
316 | // ensure these name lookups happen correctly when we load the name indexes, |
317 | // so this test loads a symbol table from a cache file from |
318 | // "lldb/unittests/Symbol/Inputs/indexnames-symtab-cache" and make sure we |
319 | // can correctly lookup each of the names in the symbol table. |
320 | auto ExpectedFile = TestFile::fromYaml(Yaml: R"( |
321 | --- !mach-o |
322 | FileHeader: |
323 | magic: 0xFEEDFACF |
324 | cputype: 0x100000C |
325 | cpusubtype: 0x0 |
326 | filetype: 0x2 |
327 | ncmds: 16 |
328 | sizeofcmds: 744 |
329 | flags: 0x200085 |
330 | reserved: 0x0 |
331 | LoadCommands: |
332 | - cmd: LC_SEGMENT_64 |
333 | cmdsize: 72 |
334 | segname: __PAGEZERO |
335 | vmaddr: 0 |
336 | vmsize: 4294967296 |
337 | fileoff: 0 |
338 | filesize: 0 |
339 | maxprot: 0 |
340 | initprot: 0 |
341 | nsects: 0 |
342 | flags: 0 |
343 | - cmd: LC_SEGMENT_64 |
344 | cmdsize: 232 |
345 | segname: __TEXT |
346 | vmaddr: 4294967296 |
347 | vmsize: 16384 |
348 | fileoff: 0 |
349 | filesize: 16384 |
350 | maxprot: 5 |
351 | initprot: 5 |
352 | nsects: 2 |
353 | flags: 0 |
354 | Sections: |
355 | - sectname: __text |
356 | segname: __TEXT |
357 | addr: 0x100003F64 |
358 | size: 76 |
359 | offset: 0x3F64 |
360 | align: 2 |
361 | reloff: 0x0 |
362 | nreloc: 0 |
363 | flags: 0x80000400 |
364 | reserved1: 0x0 |
365 | reserved2: 0x0 |
366 | reserved3: 0x0 |
367 | content: 80018052C0035FD6E0028052C0035FD640048052C0035FD6FF8300D1FD7B01A9FD43009108008052E80B00B9BFC31FB8F4FFFF97F5FFFF97F6FFFF97E00B40B9FD7B41A9FF830091C0035FD6 |
368 | - sectname: __unwind_info |
369 | segname: __TEXT |
370 | addr: 0x100003FB0 |
371 | size: 80 |
372 | offset: 0x3FB0 |
373 | align: 2 |
374 | reloff: 0x0 |
375 | nreloc: 0 |
376 | flags: 0x0 |
377 | reserved1: 0x0 |
378 | reserved2: 0x0 |
379 | reserved3: 0x0 |
380 | content: 010000001C000000000000001C000000000000001C00000002000000643F00003400000034000000B13F00000000000034000000030000000C0002001400020000000001180000000000000400000002 |
381 | - cmd: LC_SEGMENT_64 |
382 | cmdsize: 72 |
383 | segname: __LINKEDIT |
384 | vmaddr: 4294983680 |
385 | vmsize: 16384 |
386 | fileoff: 16384 |
387 | filesize: 994 |
388 | maxprot: 1 |
389 | initprot: 1 |
390 | nsects: 0 |
391 | flags: 0 |
392 | - cmd: LC_DYLD_CHAINED_FIXUPS |
393 | cmdsize: 16 |
394 | dataoff: 16384 |
395 | datasize: 56 |
396 | - cmd: LC_DYLD_EXPORTS_TRIE |
397 | cmdsize: 16 |
398 | dataoff: 16440 |
399 | datasize: 80 |
400 | - cmd: LC_SYMTAB |
401 | cmdsize: 24 |
402 | symoff: 16528 |
403 | nsyms: 25 |
404 | stroff: 16928 |
405 | strsize: 176 |
406 | - cmd: LC_DYSYMTAB |
407 | cmdsize: 80 |
408 | ilocalsym: 0 |
409 | nlocalsym: 20 |
410 | iextdefsym: 20 |
411 | nextdefsym: 5 |
412 | iundefsym: 25 |
413 | nundefsym: 0 |
414 | tocoff: 0 |
415 | ntoc: 0 |
416 | modtaboff: 0 |
417 | nmodtab: 0 |
418 | extrefsymoff: 0 |
419 | nextrefsyms: 0 |
420 | indirectsymoff: 0 |
421 | nindirectsyms: 0 |
422 | extreloff: 0 |
423 | nextrel: 0 |
424 | locreloff: 0 |
425 | nlocrel: 0 |
426 | - cmd: LC_LOAD_DYLINKER |
427 | cmdsize: 32 |
428 | name: 12 |
429 | Content: '/usr/lib/dyld' |
430 | ZeroPadBytes: 7 |
431 | - cmd: LC_UUID |
432 | cmdsize: 24 |
433 | uuid: 3E94866E-0D1A-39BD-975B-64E8F1FDBAAE |
434 | - cmd: LC_BUILD_VERSION |
435 | cmdsize: 32 |
436 | platform: 1 |
437 | minos: 786432 |
438 | sdk: 787200 |
439 | ntools: 1 |
440 | Tools: |
441 | - tool: 3 |
442 | version: 49938432 |
443 | - cmd: LC_SOURCE_VERSION |
444 | cmdsize: 16 |
445 | version: 0 |
446 | - cmd: LC_MAIN |
447 | cmdsize: 24 |
448 | entryoff: 16252 |
449 | stacksize: 0 |
450 | - cmd: LC_LOAD_DYLIB |
451 | cmdsize: 56 |
452 | dylib: |
453 | name: 24 |
454 | timestamp: 2 |
455 | current_version: 85943299 |
456 | compatibility_version: 65536 |
457 | Content: '/usr/lib/libSystem.B.dylib' |
458 | ZeroPadBytes: 6 |
459 | - cmd: LC_FUNCTION_STARTS |
460 | cmdsize: 16 |
461 | dataoff: 16520 |
462 | datasize: 8 |
463 | - cmd: LC_DATA_IN_CODE |
464 | cmdsize: 16 |
465 | dataoff: 16528 |
466 | datasize: 0 |
467 | - cmd: LC_CODE_SIGNATURE |
468 | cmdsize: 16 |
469 | dataoff: 17104 |
470 | datasize: 274 |
471 | LinkEditData: |
472 | NameList: |
473 | - n_strx: 43 |
474 | n_type: 0x64 |
475 | n_sect: 0 |
476 | n_desc: 0 |
477 | n_value: 0 |
478 | - n_strx: 91 |
479 | n_type: 0x64 |
480 | n_sect: 0 |
481 | n_desc: 0 |
482 | n_value: 0 |
483 | - n_strx: 98 |
484 | n_type: 0x66 |
485 | n_sect: 0 |
486 | n_desc: 1 |
487 | n_value: 1651098491 |
488 | - n_strx: 1 |
489 | n_type: 0x2E |
490 | n_sect: 1 |
491 | n_desc: 0 |
492 | n_value: 4294983524 |
493 | - n_strx: 152 |
494 | n_type: 0x24 |
495 | n_sect: 1 |
496 | n_desc: 0 |
497 | n_value: 4294983524 |
498 | - n_strx: 1 |
499 | n_type: 0x24 |
500 | n_sect: 0 |
501 | n_desc: 0 |
502 | n_value: 8 |
503 | - n_strx: 1 |
504 | n_type: 0x4E |
505 | n_sect: 1 |
506 | n_desc: 0 |
507 | n_value: 8 |
508 | - n_strx: 1 |
509 | n_type: 0x2E |
510 | n_sect: 1 |
511 | n_desc: 0 |
512 | n_value: 4294983532 |
513 | - n_strx: 157 |
514 | n_type: 0x24 |
515 | n_sect: 1 |
516 | n_desc: 0 |
517 | n_value: 4294983532 |
518 | - n_strx: 1 |
519 | n_type: 0x24 |
520 | n_sect: 0 |
521 | n_desc: 0 |
522 | n_value: 8 |
523 | - n_strx: 1 |
524 | n_type: 0x4E |
525 | n_sect: 1 |
526 | n_desc: 0 |
527 | n_value: 8 |
528 | - n_strx: 1 |
529 | n_type: 0x2E |
530 | n_sect: 1 |
531 | n_desc: 0 |
532 | n_value: 4294983540 |
533 | - n_strx: 162 |
534 | n_type: 0x24 |
535 | n_sect: 1 |
536 | n_desc: 0 |
537 | n_value: 4294983540 |
538 | - n_strx: 1 |
539 | n_type: 0x24 |
540 | n_sect: 0 |
541 | n_desc: 0 |
542 | n_value: 8 |
543 | - n_strx: 1 |
544 | n_type: 0x4E |
545 | n_sect: 1 |
546 | n_desc: 0 |
547 | n_value: 8 |
548 | - n_strx: 1 |
549 | n_type: 0x2E |
550 | n_sect: 1 |
551 | n_desc: 0 |
552 | n_value: 4294983548 |
553 | - n_strx: 167 |
554 | n_type: 0x24 |
555 | n_sect: 1 |
556 | n_desc: 0 |
557 | n_value: 4294983548 |
558 | - n_strx: 1 |
559 | n_type: 0x24 |
560 | n_sect: 0 |
561 | n_desc: 0 |
562 | n_value: 52 |
563 | - n_strx: 1 |
564 | n_type: 0x4E |
565 | n_sect: 1 |
566 | n_desc: 0 |
567 | n_value: 52 |
568 | - n_strx: 1 |
569 | n_type: 0x64 |
570 | n_sect: 1 |
571 | n_desc: 0 |
572 | n_value: 0 |
573 | - n_strx: 2 |
574 | n_type: 0xF |
575 | n_sect: 1 |
576 | n_desc: 16 |
577 | n_value: 4294967296 |
578 | - n_strx: 22 |
579 | n_type: 0xF |
580 | n_sect: 1 |
581 | n_desc: 0 |
582 | n_value: 4294983532 |
583 | - n_strx: 27 |
584 | n_type: 0xF |
585 | n_sect: 1 |
586 | n_desc: 0 |
587 | n_value: 4294983540 |
588 | - n_strx: 32 |
589 | n_type: 0xF |
590 | n_sect: 1 |
591 | n_desc: 0 |
592 | n_value: 4294983524 |
593 | - n_strx: 37 |
594 | n_type: 0xF |
595 | n_sect: 1 |
596 | n_desc: 0 |
597 | n_value: 4294983548 |
598 | StringTable: |
599 | - ' ' |
600 | - __mh_execute_header |
601 | - _bar |
602 | - _baz |
603 | - _foo |
604 | - _main |
605 | - '/Users/gclayton/Documents/objfiles/index-names/' |
606 | - main.c |
607 | - '/Users/gclayton/Documents/objfiles/index-names/main.o' |
608 | - _foo |
609 | - _bar |
610 | - _baz |
611 | - _main |
612 | - '' |
613 | - '' |
614 | - '' |
615 | FunctionStarts: [ 0x3F64, 0x3F6C, 0x3F74, 0x3F7C ] |
616 | ... |
617 | )" ); |
618 | // This data was taken from a hex dump of the object file from the above yaml |
619 | // and hexdumped so we can load the cache data in this test. |
620 | const uint8_t symtab_cache_bytes[] = { |
621 | 0x01, 0x10, 0x3e, 0x94, 0x86, 0x6e, 0x0d, 0x1a, |
622 | 0x39, 0xbd, 0x97, 0x5b, 0x64, 0xe8, 0xf1, 0xfd, |
623 | 0xba, 0xae, 0xff, 0x53, 0x54, 0x41, 0x42, 0x91, |
624 | 0x00, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65, |
625 | 0x72, 0x73, 0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79, |
626 | 0x74, 0x6f, 0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75, |
627 | 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62, |
628 | 0x6a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69, |
629 | 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d, |
630 | 0x65, 0x73, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, |
631 | 0x63, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, |
632 | 0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79, 0x74, 0x6f, |
633 | 0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, |
634 | 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62, 0x6a, 0x66, |
635 | 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69, 0x6e, 0x64, |
636 | 0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x73, |
637 | 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6f, 0x00, |
638 | 0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, |
639 | 0x62, 0x61, 0x7a, 0x00, 0x6d, 0x61, 0x69, 0x6e, |
640 | 0x00, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, |
641 | 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, |
642 | 0x64, 0x65, 0x72, 0x00, 0x53, 0x59, 0x4d, 0x42, |
643 | 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, |
644 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2a, |
645 | 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
646 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, |
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
648 | 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
649 | 0x0a, 0x20, 0x01, 0x37, 0x00, 0x00, 0x00, 0x00, |
650 | 0x7b, 0xc3, 0x69, 0x62, 0x00, 0x00, 0x00, 0x00, |
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
652 | 0x01, 0x00, 0x66, 0x00, 0x04, 0x00, 0x00, 0x00, |
653 | 0x00, 0x00, 0x02, 0x32, 0x01, 0x6d, 0x00, 0x00, |
654 | 0x00, 0x01, 0x64, 0x3f, 0x00, 0x00, 0x01, 0x00, |
655 | 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, |
656 | 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, |
657 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x32, 0x01, 0x71, |
658 | 0x00, 0x00, 0x00, 0x01, 0x6c, 0x3f, 0x00, 0x00, |
659 | 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, |
660 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, |
661 | 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x32, |
662 | 0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x74, 0x3f, |
663 | 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, |
664 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
665 | 0x0f, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, |
666 | 0x02, 0x32, 0x01, 0x79, 0x00, 0x00, 0x00, 0x01, |
667 | 0x7c, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
668 | 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
669 | 0x00, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x00, 0x00, |
670 | 0x00, 0x00, 0x04, 0x12, 0x02, 0x7e, 0x00, 0x00, |
671 | 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, |
672 | 0x00, 0x00, 0x64, 0x3f, 0x00, 0x00, 0x00, 0x00, |
673 | 0x00, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x01, 0x00, |
674 | 0x43, 0x4d, 0x41, 0x50, 0x07, 0x00, 0x00, 0x00, |
675 | 0x6d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, |
676 | 0x75, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, |
677 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
678 | 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, |
679 | 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
680 | 0x71, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, |
681 | 0x7e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 |
682 | }; |
683 | |
684 | ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); |
685 | auto module_sp = std::make_shared<Module>(args: ExpectedFile->moduleSpec()); |
686 | ObjectFile *objfile = module_sp->GetObjectFile(); |
687 | ASSERT_NE(objfile, nullptr); |
688 | |
689 | // Test encoding and decoding an empty symbol table. |
690 | DataExtractor data(symtab_cache_bytes, sizeof(symtab_cache_bytes), |
691 | eByteOrderLittle, 8); |
692 | Symtab symtab(objfile); |
693 | offset_t data_offset = 0; |
694 | bool uuid_mismatch = false; // Gets set to true if signature doesn't match. |
695 | const bool success = symtab.Decode(data, offset_ptr: &data_offset, uuid_mismatch); |
696 | ASSERT_EQ(success, true); |
697 | ASSERT_EQ(uuid_mismatch, false); |
698 | |
699 | // Now make sure that name lookup works for all symbols. This indicates that |
700 | // the Symtab::NameToIndexMap was decoded correctly and works as expected. |
701 | Symbol *symbol = nullptr; |
702 | symbol = symtab.FindFirstSymbolWithNameAndType(name: ConstString("main" ), |
703 | symbol_type: eSymbolTypeCode, |
704 | symbol_debug_type: Symtab::eDebugAny, |
705 | symbol_visibility: Symtab::eVisibilityAny); |
706 | ASSERT_NE(symbol, nullptr); |
707 | symbol = symtab.FindFirstSymbolWithNameAndType(name: ConstString("foo" ), |
708 | symbol_type: eSymbolTypeCode, |
709 | symbol_debug_type: Symtab::eDebugAny, |
710 | symbol_visibility: Symtab::eVisibilityAny); |
711 | ASSERT_NE(symbol, nullptr); |
712 | symbol = symtab.FindFirstSymbolWithNameAndType(name: ConstString("bar" ), |
713 | symbol_type: eSymbolTypeCode, |
714 | symbol_debug_type: Symtab::eDebugAny, |
715 | symbol_visibility: Symtab::eVisibilityAny); |
716 | ASSERT_NE(symbol, nullptr); |
717 | symbol = symtab.FindFirstSymbolWithNameAndType(name: ConstString("baz" ), |
718 | symbol_type: eSymbolTypeCode, |
719 | symbol_debug_type: Symtab::eDebugAny, |
720 | symbol_visibility: Symtab::eVisibilityAny); |
721 | ASSERT_NE(symbol, nullptr); |
722 | } |
723 | |
724 | TEST_F(SymtabTest, TestSymbolFileCreatedOnDemand) { |
725 | auto ExpectedFile = TestFile::fromYaml(Yaml: R"( |
726 | --- !ELF |
727 | FileHeader: |
728 | Class: ELFCLASS64 |
729 | Data: ELFDATA2LSB |
730 | Type: ET_EXEC |
731 | Machine: EM_X86_64 |
732 | Entry: 0x0000000000400180 |
733 | Sections: |
734 | - Name: .text |
735 | Type: SHT_PROGBITS |
736 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] |
737 | Address: 0x0000000000400180 |
738 | AddressAlign: 0x0000000000000010 |
739 | Content: 554889E58B042500106000890425041060005DC3 |
740 | Symbols: |
741 | - Name: _start |
742 | Type: STT_FUNC |
743 | Section: .text |
744 | Value: 0x0000000000400180 |
745 | Size: 0x0000000000000014 |
746 | Binding: STB_GLOBAL |
747 | ... |
748 | )" ); |
749 | ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); |
750 | auto module_sp = std::make_shared<Module>(args: ExpectedFile->moduleSpec()); |
751 | |
752 | // The symbol file should not be created by default. |
753 | Symtab *module_symtab = module_sp->GetSymtab(/*can_create=*/false); |
754 | ASSERT_EQ(module_symtab, nullptr); |
755 | |
756 | // But it should be created on demand. |
757 | module_symtab = module_sp->GetSymtab(/*can_create=*/true); |
758 | ASSERT_NE(module_symtab, nullptr); |
759 | |
760 | // And we should be able to get it again once it has been created. |
761 | Symtab *cached_module_symtab = module_sp->GetSymtab(/*can_create=*/false); |
762 | ASSERT_EQ(module_symtab, cached_module_symtab); |
763 | } |
764 | |
765 | TEST_F(SymtabTest, TestSymbolTableCreatedOnDemand) { |
766 | const char *yamldata = R"( |
767 | --- !ELF |
768 | FileHeader: |
769 | Class: ELFCLASS64 |
770 | Data: ELFDATA2LSB |
771 | Type: ET_EXEC |
772 | Machine: EM_386 |
773 | DWARF: |
774 | debug_abbrev: |
775 | - Table: |
776 | - Code: 0x00000001 |
777 | Tag: DW_TAG_compile_unit |
778 | Children: DW_CHILDREN_no |
779 | Attributes: |
780 | - Attribute: DW_AT_addr_base |
781 | Form: DW_FORM_sec_offset |
782 | debug_info: |
783 | - Version: 5 |
784 | AddrSize: 4 |
785 | UnitType: DW_UT_compile |
786 | Entries: |
787 | - AbbrCode: 0x00000001 |
788 | Values: |
789 | - Value: 0x8 # Offset of the first Address past the header |
790 | - AbbrCode: 0x0 |
791 | debug_addr: |
792 | - Version: 5 |
793 | AddressSize: 4 |
794 | Entries: |
795 | - Address: 0x1234 |
796 | - Address: 0x5678 |
797 | debug_line: |
798 | - Length: 42 |
799 | Version: 2 |
800 | PrologueLength: 36 |
801 | MinInstLength: 1 |
802 | DefaultIsStmt: 1 |
803 | LineBase: 251 |
804 | LineRange: 14 |
805 | OpcodeBase: 13 |
806 | StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] |
807 | IncludeDirs: |
808 | - '/tmp' |
809 | Files: |
810 | - Name: main.cpp |
811 | DirIdx: 1 |
812 | ModTime: 0 |
813 | Length: 0 |
814 | )" ; |
815 | llvm::Expected<TestFile> file = TestFile::fromYaml(Yaml: yamldata); |
816 | EXPECT_THAT_EXPECTED(file, llvm::Succeeded()); |
817 | auto module_sp = std::make_shared<Module>(args: file->moduleSpec()); |
818 | |
819 | SymbolFile *symbol_file = module_sp->GetSymbolFile(); |
820 | // At this point, the symbol table is not created. This is because the above |
821 | // yaml data contains the necessary sections in order for |
822 | // SymbolFileDWARF::CalculateAbilities() to identify all abilities, saving it |
823 | // from calling SymbolFileDWARFDebugMap::CalculateAbilities(), which |
824 | // eventually loads the symbol table, which we don't want. |
825 | |
826 | // The symbol table should not be created if asked not to. |
827 | Symtab *symtab = symbol_file->GetSymtab(/*can_create=*/false); |
828 | ASSERT_EQ(symtab, nullptr); |
829 | |
830 | // But it should be created on demand. |
831 | symtab = symbol_file->GetSymtab(/*can_create=*/true); |
832 | ASSERT_NE(symtab, nullptr); |
833 | |
834 | // And we should be able to get it again once it has been created. |
835 | Symtab *cached_symtab = symbol_file->GetSymtab(/*can_create=*/false); |
836 | ASSERT_EQ(symtab, cached_symtab); |
837 | } |
838 | |