Files
clang-p2996/lldb/unittests/Symbol/SymtabTest.cpp
royitaqi 967434aa32 [lldb] Remerge #136236 (Avoid force loading symbols in statistics collection (#136795)
Fix a [test
failure](https://github.com/llvm/llvm-project/pull/136236#issuecomment-2819772879)
in #136236, apply a minor renaming of statistics, and remerge. See
details below.

# Changes in #136236

Currently, `DebuggerStats::ReportStatistics()` calls
`Module::GetSymtab(/*can_create=*/false)`, but then the latter calls
`SymbolFile::GetSymtab()`. This will load symbols if haven't yet. See
stacktrace below.

The problem is that `DebuggerStats::ReportStatistics` should be
read-only. This is especially important because it reports stats for
symtab parsing/indexing time, which could be affected by the reporting
itself if it's not read-only.

This patch fixes this problem by adding an optional parameter
`SymbolFile::GetSymtab(bool can_create = true)` and receiving the
`false` value passed down from `Module::GetSymtab(/*can_create=*/false)`
when the call is initiated from `DebuggerStats::ReportStatistics()`.

---

Notes about the following stacktrace:
1. This can be reproduced. Create a helloworld program on **macOS** with
dSYM, add `settings set target.preload-symbols false` to `~/.lldbinit`,
do `lldb a.out`, then `statistics dump`.
2. `ObjectFile::GetSymtab` has `llvm::call_once`. So the fact that it
called into `ObjectFileMachO::ParseSymtab` means that the symbol table
is actually being parsed.

```
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000124c4d5a0 LLDB`ObjectFileMachO::ParseSymtab(this=0x0000000111504e40, symtab=0x0000600000a05e00) at ObjectFileMachO.cpp:2259:44
  * frame #1: 0x0000000124fc50a0 LLDB`lldb_private::ObjectFile::GetSymtab()::$_0::operator()(this=0x000000016d35c858) const at ObjectFile.cpp:761:9
    frame #5: 0x0000000124fc4e68 LLDB`void std::__1::__call_once_proxy[abi:v160006]<std::__1::tuple<lldb_private::ObjectFile::GetSymtab()::$_0&&>>(__vp=0x000000016d35c7f0) at mutex:652:5
    frame #6: 0x0000000198afb99c libc++.1.dylib`std::__1::__call_once(unsigned long volatile&, void*, void (*)(void*)) + 196
    frame #7: 0x0000000124fc4dd0 LLDB`void std::__1::call_once[abi:v160006]<lldb_private::ObjectFile::GetSymtab()::$_0>(__flag=0x0000600003920080, __func=0x000000016d35c858) at mutex:670:9
    frame #8: 0x0000000124fc3cb0 LLDB`void llvm::call_once<lldb_private::ObjectFile::GetSymtab()::$_0>(flag=0x0000600003920080, F=0x000000016d35c858) at Threading.h:88:5
    frame #9: 0x0000000124fc2bc4 LLDB`lldb_private::ObjectFile::GetSymtab(this=0x0000000111504e40) at ObjectFile.cpp:755:5
    frame #10: 0x0000000124fe0a28 LLDB`lldb_private::SymbolFileCommon::GetSymtab(this=0x0000000104865200) at SymbolFile.cpp:158:39
    frame #11: 0x0000000124d8fedc LLDB`lldb_private::Module::GetSymtab(this=0x00000001113041a8, can_create=false) at Module.cpp:1027:21
    frame #12: 0x0000000125125bdc LLDB`lldb_private::DebuggerStats::ReportStatistics(debugger=0x000000014284d400, target=0x0000000115808200, options=0x000000014195d6d1) at Statistics.cpp:329:30
    frame #13: 0x0000000125672978 LLDB`CommandObjectStatsDump::DoExecute(this=0x000000014195d540, command=0x000000016d35d820, result=0x000000016d35e150) at CommandObjectStats.cpp:144:18
    frame #14: 0x0000000124f29b40 LLDB`lldb_private::CommandObjectParsed::Execute(this=0x000000014195d540, args_string="", result=0x000000016d35e150) at CommandObject.cpp:832:9
    frame #15: 0x0000000124efbd70 LLDB`lldb_private::CommandInterpreter::HandleCommand(this=0x0000000141b22f30, command_line="statistics dump", lazy_add_to_history=eLazyBoolCalculate, result=0x000000016d35e150, force_repeat_command=false) at CommandInterpreter.cpp:2134:14
    frame #16: 0x0000000124f007f4 LLDB`lldb_private::CommandInterpreter::IOHandlerInputComplete(this=0x0000000141b22f30, io_handler=0x00000001419b2aa8, line="statistics dump") at CommandInterpreter.cpp:3251:3
    frame #17: 0x0000000124d7b5ec LLDB`lldb_private::IOHandlerEditline::Run(this=0x00000001419b2aa8) at IOHandler.cpp:588:22
    frame #18: 0x0000000124d1e8fc LLDB`lldb_private::Debugger::RunIOHandlers(this=0x000000014284d400) at Debugger.cpp:1225:16
    frame #19: 0x0000000124f01f74 LLDB`lldb_private::CommandInterpreter::RunCommandInterpreter(this=0x0000000141b22f30, options=0x000000016d35e63c) at CommandInterpreter.cpp:3543:16
    frame #20: 0x0000000122840294 LLDB`lldb::SBDebugger::RunCommandInterpreter(this=0x000000016d35ebd8, auto_handle_events=true, spawn_thread=false) at SBDebugger.cpp:1212:42
    frame #21: 0x0000000102aa6d28 lldb`Driver::MainLoop(this=0x000000016d35ebb8) at Driver.cpp:621:18
    frame #22: 0x0000000102aa75b0 lldb`main(argc=1, argv=0x000000016d35f548) at Driver.cpp:829:26
    frame #23: 0x0000000198858274 dyld`start + 2840
```

# Changes in this PR top of the above

Fix a [test
failure](https://github.com/llvm/llvm-project/pull/136236#issuecomment-2819772879)
in `TestStats.py`. The original version of the added test checks that
all modules have symbol count zero when `target.preload-symbols ==
false`. The test failed on macOS. Due to various reasons, on macOS,
symbols can be loaded for dylibs even with that setting, but not for the
main module. For now, the fix of the test is to limit the assertion to
only the main module. The test now passes on macOS. In the future, when
we have a way to control a specific list of plug-ins to be loaded, there
may be a configuration that this test can use to assert that all modules
have symbol count zero.

Apply a minor renaming of statistics, per the
[suggestion](https://github.com/llvm/llvm-project/pull/136226#issuecomment-2825080275)
in #136226 after merge.
2025-04-24 17:23:41 -07:00

838 lines
26 KiB
C++

//===-- SymbolTest.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "TestingSupport/SubsystemRAII.h"
#include "TestingSupport/TestUtilities.h"
#include "lldb/Core/DataFileCache.h"
#include "lldb/Core/Module.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Symtab.h"
#include "lldb/Utility/DataEncoder.h"
#include "lldb/Utility/DataExtractor.h"
#include <memory>
#include "gtest/gtest.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::plugin::dwarf;
class SymtabTest : public testing::Test {
SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO, SymbolFileDWARF,
ObjectFileELF, SymbolFileSymtab, TypeSystemClang>
subsystem;
};
static void EncodeDecode(const Symtab &object, ByteOrder byte_order) {
const uint8_t addr_size = 8;
DataEncoder file(byte_order, addr_size);
object.Encode(file);
llvm::ArrayRef<uint8_t> bytes = file.GetData();
DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);
Symtab decoded_object(object.GetObjectFile());
offset_t data_offset = 0;
bool uuid_mismatch = false;
decoded_object.Decode(data, &data_offset, uuid_mismatch);
ASSERT_EQ(object.GetNumSymbols(), decoded_object.GetNumSymbols());
for (size_t i = 0; i < object.GetNumSymbols(); ++i)
EXPECT_EQ(*object.SymbolAtIndex(i), *decoded_object.SymbolAtIndex(i));
}
static void EncodeDecode(const Symtab &object) {
EncodeDecode(object, eByteOrderLittle);
EncodeDecode(object, eByteOrderBig);
}
TEST_F(SymtabTest, EncodeDecodeSymtab) {
auto ExpectedFile = TestFile::fromYaml(R"(
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x100000C
cpusubtype: 0x0
filetype: 0x2
ncmds: 17
sizeofcmds: 792
flags: 0x200085
reserved: 0x0
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __PAGEZERO
vmaddr: 0
vmsize: 4294967296
fileoff: 0
filesize: 0
maxprot: 0
initprot: 0
nsects: 0
flags: 0
- cmd: LC_SEGMENT_64
cmdsize: 232
segname: __TEXT
vmaddr: 4294967296
vmsize: 16384
fileoff: 0
filesize: 16384
maxprot: 5
initprot: 5
nsects: 2
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x100003F94
size: 36
offset: 0x3F94
align: 2
reloff: 0x0
nreloc: 0
flags: 0x80000400
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: FF8300D1E80300AA00008052FF1F00B9E81B00B9E10B00F9E20700F9FF830091C0035FD6
- sectname: __unwind_info
segname: __TEXT
addr: 0x100003FB8
size: 72
offset: 0x3FB8
align: 2
reloff: 0x0
nreloc: 0
flags: 0x0
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: 010000001C000000000000001C000000000000001C00000002000000943F00003400000034000000B93F00000000000034000000030000000C000100100001000000000000200002
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 4294983680
vmsize: 16384
fileoff: 16384
filesize: 674
maxprot: 1
initprot: 1
nsects: 0
flags: 0
- cmd: LC_DYLD_CHAINED_FIXUPS
cmdsize: 16
dataoff: 16384
datasize: 56
- cmd: LC_DYLD_EXPORTS_TRIE
cmdsize: 16
dataoff: 16440
datasize: 48
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 16496
nsyms: 10
stroff: 16656
strsize: 128
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 8
iextdefsym: 8
nextdefsym: 2
iundefsym: 10
nundefsym: 0
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 0
nindirectsyms: 0
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_LOAD_DYLINKER
cmdsize: 32
name: 12
Content: '/usr/lib/dyld'
ZeroPadBytes: 7
- cmd: LC_UUID
cmdsize: 24
uuid: 1EECD2B8-16EA-3FEC-AB3C-F46139DBD0E2
- cmd: LC_BUILD_VERSION
cmdsize: 32
platform: 1
minos: 786432
sdk: 786432
ntools: 1
Tools:
- tool: 3
version: 46596096
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_MAIN
cmdsize: 24
entryoff: 16276
stacksize: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 48
dylib:
name: 24
timestamp: 2
current_version: 78643968
compatibility_version: 65536
Content: '/usr/lib/libc++.1.dylib'
ZeroPadBytes: 1
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 85917696
compatibility_version: 65536
Content: '/usr/lib/libSystem.B.dylib'
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 16488
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 16496
datasize: 0
- cmd: LC_CODE_SIGNATURE
cmdsize: 16
dataoff: 16784
datasize: 274
LinkEditData:
NameList:
- n_strx: 28
n_type: 0x64
n_sect: 0
n_desc: 0
n_value: 0
- n_strx: 64
n_type: 0x64
n_sect: 0
n_desc: 0
n_value: 0
- n_strx: 73
n_type: 0x66
n_sect: 0
n_desc: 1
n_value: 1639532873
- n_strx: 1
n_type: 0x2E
n_sect: 1
n_desc: 0
n_value: 4294983572
- n_strx: 115
n_type: 0x24
n_sect: 1
n_desc: 0
n_value: 4294983572
- n_strx: 1
n_type: 0x24
n_sect: 0
n_desc: 0
n_value: 36
- n_strx: 1
n_type: 0x4E
n_sect: 1
n_desc: 0
n_value: 36
- n_strx: 1
n_type: 0x64
n_sect: 1
n_desc: 0
n_value: 0
- n_strx: 2
n_type: 0xF
n_sect: 1
n_desc: 16
n_value: 4294967296
- n_strx: 22
n_type: 0xF
n_sect: 1
n_desc: 0
n_value: 4294983572
StringTable:
- ' '
- __mh_execute_header
- _main
- '/Users/gclayton/Documents/src/args/'
- main.cpp
- '/Users/gclayton/Documents/src/args/main.o'
- _main
- ''
- ''
- ''
- ''
- ''
- ''
- ''
...
)");
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());
ObjectFile *objfile = module_sp->GetObjectFile();
ASSERT_NE(objfile, nullptr);
// Test encoding and decoding an empty symbol table.
Symtab symtab(objfile);
symtab.PreloadSymbols();
EncodeDecode(symtab);
// Now encode and decode an actual symbol table from our yaml.
Symtab *module_symtab = module_sp->GetSymtab();
ASSERT_NE(module_symtab, nullptr);
module_symtab->PreloadSymbols();
EncodeDecode(*module_symtab);
}
TEST_F(SymtabTest, TestDecodeCStringMaps) {
// Symbol tables save out the symbols, but they also save out the symbol table
// name indexes. These name indexes are a map of sorted ConstString + T pairs
// and when they are decoded from a file, they are no longer sorted since
// ConstString objects can be sorted by "const char *" and the order in which
// these strings are created won't be the same in a new process. We need to
// ensure these name lookups happen correctly when we load the name indexes,
// so this test loads a symbol table from a cache file from
// "lldb/unittests/Symbol/Inputs/indexnames-symtab-cache" and make sure we
// can correctly lookup each of the names in the symbol table.
auto ExpectedFile = TestFile::fromYaml(R"(
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x100000C
cpusubtype: 0x0
filetype: 0x2
ncmds: 16
sizeofcmds: 744
flags: 0x200085
reserved: 0x0
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __PAGEZERO
vmaddr: 0
vmsize: 4294967296
fileoff: 0
filesize: 0
maxprot: 0
initprot: 0
nsects: 0
flags: 0
- cmd: LC_SEGMENT_64
cmdsize: 232
segname: __TEXT
vmaddr: 4294967296
vmsize: 16384
fileoff: 0
filesize: 16384
maxprot: 5
initprot: 5
nsects: 2
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x100003F64
size: 76
offset: 0x3F64
align: 2
reloff: 0x0
nreloc: 0
flags: 0x80000400
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: 80018052C0035FD6E0028052C0035FD640048052C0035FD6FF8300D1FD7B01A9FD43009108008052E80B00B9BFC31FB8F4FFFF97F5FFFF97F6FFFF97E00B40B9FD7B41A9FF830091C0035FD6
- sectname: __unwind_info
segname: __TEXT
addr: 0x100003FB0
size: 80
offset: 0x3FB0
align: 2
reloff: 0x0
nreloc: 0
flags: 0x0
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: 010000001C000000000000001C000000000000001C00000002000000643F00003400000034000000B13F00000000000034000000030000000C0002001400020000000001180000000000000400000002
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 4294983680
vmsize: 16384
fileoff: 16384
filesize: 994
maxprot: 1
initprot: 1
nsects: 0
flags: 0
- cmd: LC_DYLD_CHAINED_FIXUPS
cmdsize: 16
dataoff: 16384
datasize: 56
- cmd: LC_DYLD_EXPORTS_TRIE
cmdsize: 16
dataoff: 16440
datasize: 80
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 16528
nsyms: 25
stroff: 16928
strsize: 176
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 20
iextdefsym: 20
nextdefsym: 5
iundefsym: 25
nundefsym: 0
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 0
nindirectsyms: 0
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_LOAD_DYLINKER
cmdsize: 32
name: 12
Content: '/usr/lib/dyld'
ZeroPadBytes: 7
- cmd: LC_UUID
cmdsize: 24
uuid: 3E94866E-0D1A-39BD-975B-64E8F1FDBAAE
- cmd: LC_BUILD_VERSION
cmdsize: 32
platform: 1
minos: 786432
sdk: 787200
ntools: 1
Tools:
- tool: 3
version: 49938432
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_MAIN
cmdsize: 24
entryoff: 16252
stacksize: 0
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 85943299
compatibility_version: 65536
Content: '/usr/lib/libSystem.B.dylib'
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 16520
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 16528
datasize: 0
- cmd: LC_CODE_SIGNATURE
cmdsize: 16
dataoff: 17104
datasize: 274
LinkEditData:
NameList:
- n_strx: 43
n_type: 0x64
n_sect: 0
n_desc: 0
n_value: 0
- n_strx: 91
n_type: 0x64
n_sect: 0
n_desc: 0
n_value: 0
- n_strx: 98
n_type: 0x66
n_sect: 0
n_desc: 1
n_value: 1651098491
- n_strx: 1
n_type: 0x2E
n_sect: 1
n_desc: 0
n_value: 4294983524
- n_strx: 152
n_type: 0x24
n_sect: 1
n_desc: 0
n_value: 4294983524
- n_strx: 1
n_type: 0x24
n_sect: 0
n_desc: 0
n_value: 8
- n_strx: 1
n_type: 0x4E
n_sect: 1
n_desc: 0
n_value: 8
- n_strx: 1
n_type: 0x2E
n_sect: 1
n_desc: 0
n_value: 4294983532
- n_strx: 157
n_type: 0x24
n_sect: 1
n_desc: 0
n_value: 4294983532
- n_strx: 1
n_type: 0x24
n_sect: 0
n_desc: 0
n_value: 8
- n_strx: 1
n_type: 0x4E
n_sect: 1
n_desc: 0
n_value: 8
- n_strx: 1
n_type: 0x2E
n_sect: 1
n_desc: 0
n_value: 4294983540
- n_strx: 162
n_type: 0x24
n_sect: 1
n_desc: 0
n_value: 4294983540
- n_strx: 1
n_type: 0x24
n_sect: 0
n_desc: 0
n_value: 8
- n_strx: 1
n_type: 0x4E
n_sect: 1
n_desc: 0
n_value: 8
- n_strx: 1
n_type: 0x2E
n_sect: 1
n_desc: 0
n_value: 4294983548
- n_strx: 167
n_type: 0x24
n_sect: 1
n_desc: 0
n_value: 4294983548
- n_strx: 1
n_type: 0x24
n_sect: 0
n_desc: 0
n_value: 52
- n_strx: 1
n_type: 0x4E
n_sect: 1
n_desc: 0
n_value: 52
- n_strx: 1
n_type: 0x64
n_sect: 1
n_desc: 0
n_value: 0
- n_strx: 2
n_type: 0xF
n_sect: 1
n_desc: 16
n_value: 4294967296
- n_strx: 22
n_type: 0xF
n_sect: 1
n_desc: 0
n_value: 4294983532
- n_strx: 27
n_type: 0xF
n_sect: 1
n_desc: 0
n_value: 4294983540
- n_strx: 32
n_type: 0xF
n_sect: 1
n_desc: 0
n_value: 4294983524
- n_strx: 37
n_type: 0xF
n_sect: 1
n_desc: 0
n_value: 4294983548
StringTable:
- ' '
- __mh_execute_header
- _bar
- _baz
- _foo
- _main
- '/Users/gclayton/Documents/objfiles/index-names/'
- main.c
- '/Users/gclayton/Documents/objfiles/index-names/main.o'
- _foo
- _bar
- _baz
- _main
- ''
- ''
- ''
FunctionStarts: [ 0x3F64, 0x3F6C, 0x3F74, 0x3F7C ]
...
)");
// This data was taken from a hex dump of the object file from the above yaml
// and hexdumped so we can load the cache data in this test.
const uint8_t symtab_cache_bytes[] = {
0x01, 0x10, 0x3e, 0x94, 0x86, 0x6e, 0x0d, 0x1a,
0x39, 0xbd, 0x97, 0x5b, 0x64, 0xe8, 0xf1, 0xfd,
0xba, 0xae, 0xff, 0x53, 0x54, 0x41, 0x42, 0x91,
0x00, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65,
0x72, 0x73, 0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79,
0x74, 0x6f, 0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62,
0x6a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69,
0x6e, 0x64, 0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d,
0x65, 0x73, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e,
0x63, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73,
0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79, 0x74, 0x6f,
0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62, 0x6a, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69, 0x6e, 0x64,
0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x73,
0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6f, 0x00,
0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00,
0x62, 0x61, 0x7a, 0x00, 0x6d, 0x61, 0x69, 0x6e,
0x00, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61,
0x64, 0x65, 0x72, 0x00, 0x53, 0x59, 0x4d, 0x42,
0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2a,
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0a, 0x20, 0x01, 0x37, 0x00, 0x00, 0x00, 0x00,
0x7b, 0xc3, 0x69, 0x62, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x66, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x32, 0x01, 0x6d, 0x00, 0x00,
0x00, 0x01, 0x64, 0x3f, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x32, 0x01, 0x71,
0x00, 0x00, 0x00, 0x01, 0x6c, 0x3f, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x32,
0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x74, 0x3f,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x32, 0x01, 0x79, 0x00, 0x00, 0x00, 0x01,
0x7c, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x12, 0x02, 0x7e, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x64, 0x3f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x01, 0x00,
0x43, 0x4d, 0x41, 0x50, 0x07, 0x00, 0x00, 0x00,
0x6d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x75, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x7e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00
};
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());
ObjectFile *objfile = module_sp->GetObjectFile();
ASSERT_NE(objfile, nullptr);
// Test encoding and decoding an empty symbol table.
DataExtractor data(symtab_cache_bytes, sizeof(symtab_cache_bytes),
eByteOrderLittle, 8);
Symtab symtab(objfile);
offset_t data_offset = 0;
bool uuid_mismatch = false; // Gets set to true if signature doesn't match.
const bool success = symtab.Decode(data, &data_offset, uuid_mismatch);
ASSERT_EQ(success, true);
ASSERT_EQ(uuid_mismatch, false);
// Now make sure that name lookup works for all symbols. This indicates that
// the Symtab::NameToIndexMap was decoded correctly and works as expected.
Symbol *symbol = nullptr;
symbol = symtab.FindFirstSymbolWithNameAndType(ConstString("main"),
eSymbolTypeCode,
Symtab::eDebugAny,
Symtab::eVisibilityAny);
ASSERT_NE(symbol, nullptr);
symbol = symtab.FindFirstSymbolWithNameAndType(ConstString("foo"),
eSymbolTypeCode,
Symtab::eDebugAny,
Symtab::eVisibilityAny);
ASSERT_NE(symbol, nullptr);
symbol = symtab.FindFirstSymbolWithNameAndType(ConstString("bar"),
eSymbolTypeCode,
Symtab::eDebugAny,
Symtab::eVisibilityAny);
ASSERT_NE(symbol, nullptr);
symbol = symtab.FindFirstSymbolWithNameAndType(ConstString("baz"),
eSymbolTypeCode,
Symtab::eDebugAny,
Symtab::eVisibilityAny);
ASSERT_NE(symbol, nullptr);
}
TEST_F(SymtabTest, TestSymbolFileCreatedOnDemand) {
auto ExpectedFile = TestFile::fromYaml(R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Entry: 0x0000000000400180
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x0000000000400180
AddressAlign: 0x0000000000000010
Content: 554889E58B042500106000890425041060005DC3
Symbols:
- Name: _start
Type: STT_FUNC
Section: .text
Value: 0x0000000000400180
Size: 0x0000000000000014
Binding: STB_GLOBAL
...
)");
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());
// The symbol file should not be created by default.
Symtab *module_symtab = module_sp->GetSymtab(/*can_create=*/false);
ASSERT_EQ(module_symtab, nullptr);
// But it should be created on demand.
module_symtab = module_sp->GetSymtab(/*can_create=*/true);
ASSERT_NE(module_symtab, nullptr);
// And we should be able to get it again once it has been created.
Symtab *cached_module_symtab = module_sp->GetSymtab(/*can_create=*/false);
ASSERT_EQ(module_symtab, cached_module_symtab);
}
TEST_F(SymtabTest, TestSymbolTableCreatedOnDemand) {
const char *yamldata = R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_386
DWARF:
debug_abbrev:
- Table:
- Code: 0x00000001
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_addr_base
Form: DW_FORM_sec_offset
debug_info:
- Version: 5
AddrSize: 4
UnitType: DW_UT_compile
Entries:
- AbbrCode: 0x00000001
Values:
- Value: 0x8 # Offset of the first Address past the header
- AbbrCode: 0x0
debug_addr:
- Version: 5
AddressSize: 4
Entries:
- Address: 0x1234
- Address: 0x5678
debug_line:
- Length: 42
Version: 2
PrologueLength: 36
MinInstLength: 1
DefaultIsStmt: 1
LineBase: 251
LineRange: 14
OpcodeBase: 13
StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
IncludeDirs:
- '/tmp'
Files:
- Name: main.cpp
DirIdx: 1
ModTime: 0
Length: 0
)";
llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata);
EXPECT_THAT_EXPECTED(file, llvm::Succeeded());
auto module_sp = std::make_shared<Module>(file->moduleSpec());
SymbolFile *symbol_file = module_sp->GetSymbolFile();
// At this point, the symbol table is not created. This is because the above
// yaml data contains the necessary sections in order for
// SymbolFileDWARF::CalculateAbilities() to identify all abilities, saving it
// from calling SymbolFileDWARFDebugMap::CalculateAbilities(), which
// eventually loads the symbol table, which we don't want.
// The symbol table should not be created if asked not to.
Symtab *symtab = symbol_file->GetSymtab(/*can_create=*/false);
ASSERT_EQ(symtab, nullptr);
// But it should be created on demand.
symtab = symbol_file->GetSymtab(/*can_create=*/true);
ASSERT_NE(symtab, nullptr);
// And we should be able to get it again once it has been created.
Symtab *cached_symtab = symbol_file->GetSymtab(/*can_create=*/false);
ASSERT_EQ(symtab, cached_symtab);
}