Skip to content

Commit c23adc6

Browse files
committed
[lldb][Mach-O] Handle shared cache binaries correctly (llvm#117832)
The Mach-O load commands have an LC_SYMTAB / struct symtab_command which represents the offset of the symbol table (nlist records) and string table for this binary. In a mach-o binary on disk, these are file offsets. If a mach-o binary is loaded in memory with all segments consecutive, the `symoff` and `stroff` are the offsets from the TEXT segment (aka the mach-o header) virtual address to the virtual address of the start of these tables. However, if a Mach-O binary is a part of the shared cache, then the segments will be separated -- they will have different slide values. And it is possible for the LINKEDIT segment to be greater than 4GB away from the TEXT segment in the virtual address space, so these 32-bit offsets cannot express the offset from TEXT segment to these tables. Create separate uint64_t variables to track the offset to the symbol table and string table, instead of reusing the 32-bit ones in the symtab_command structure. rdar://140432279 (cherry picked from commit 448ac7d)
1 parent 2b61a59 commit c23adc6

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,11 +2244,11 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
22442244
LLDB_LOG(log, "Parsing symbol table for {0}", file_name);
22452245
Progress progress("Parsing symbol table", file_name);
22462246

2247-
llvm::MachO::symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0};
22482247
llvm::MachO::linkedit_data_command function_starts_load_command = {0, 0, 0, 0};
22492248
llvm::MachO::linkedit_data_command exports_trie_load_command = {0, 0, 0, 0};
22502249
llvm::MachO::dyld_info_command dyld_info = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
22512250
llvm::MachO::dysymtab_command dysymtab = m_dysymtab;
2251+
SymtabCommandLargeOffsets symtab_load_command;
22522252
// The data element of type bool indicates that this entry is thumb
22532253
// code.
22542254
typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts;
@@ -2285,12 +2285,20 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
22852285
// Watch for the symbol table load command
22862286
switch (lc.cmd) {
22872287
case LC_SYMTAB:
2288+
// struct symtab_command {
2289+
// uint32_t cmd; /* LC_SYMTAB */
2290+
// uint32_t cmdsize; /* sizeof(struct symtab_command) */
2291+
// uint32_t symoff; /* symbol table offset */
2292+
// uint32_t nsyms; /* number of symbol table entries */
2293+
// uint32_t stroff; /* string table offset */
2294+
// uint32_t strsize; /* string table size in bytes */
2295+
// };
22882296
symtab_load_command.cmd = lc.cmd;
22892297
symtab_load_command.cmdsize = lc.cmdsize;
2290-
// Read in the rest of the symtab load command
2291-
if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4) ==
2292-
nullptr) // fill in symoff, nsyms, stroff, strsize fields
2293-
return;
2298+
symtab_load_command.symoff = m_data.GetU32(&offset);
2299+
symtab_load_command.nsyms = m_data.GetU32(&offset);
2300+
symtab_load_command.stroff = m_data.GetU32(&offset);
2301+
symtab_load_command.strsize = m_data.GetU32(&offset);
22942302
break;
22952303

22962304
case LC_DYLD_INFO:

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,19 @@ class ObjectFileMachO : public lldb_private::ObjectFile {
256256
bool IsValid() { return all_image_infos.size() > 0; }
257257
};
258258

259+
// The LC_SYMTAB's symtab_command structure uses 32-bit file offsets
260+
// for two fields, but ObjectFileMachO needs to calculate the offsets
261+
// in virtual address layout from the start of the TEXT segment, and
262+
// that span may be larger than 4GB.
263+
struct SymtabCommandLargeOffsets {
264+
uint32_t cmd = 0; /* LC_SYMTAB */
265+
uint32_t cmdsize = 0; /* sizeof(struct symtab_command) */
266+
lldb::offset_t symoff = 0; /* symbol table offset */
267+
uint32_t nsyms = 0; /* number of symbol table entries */
268+
lldb::offset_t stroff = 0; /* string table offset */
269+
uint32_t strsize = 0; /* string table size in bytes */
270+
};
271+
259272
/// Get the list of binary images that were present in the process
260273
/// when the corefile was produced.
261274
/// \return

0 commit comments

Comments
 (0)