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.
838 lines
26 KiB
C++
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);
|
|
}
|