Skip to content

Commit d1c9751

Browse files
committed
[dsymutil] Gather global and local symbol addresses in the main executable.
Usually local symbols will have their address described in the debug map. Global symbols have to have their address looked up in the symbol table of the main executable. By playing with 'ld -r' and export lists, you can get a symbol described as global by the debug map while actually being a local symbol as far as the link in concerned. By gathering the address of local symbols, we fix this issue. Also, we prefer a global symbol in case of a name collision to preserve the previous behavior. Note that using the 'ld -r' tricks, people can actually cause symbol names collisions that dsymutil has no way to figure out. This fixes the simple case where there is only one symbol of a given name. rdar://problem/32826621 Differential revision: https://reviews.llvm.org/D54922 llvm-svn: 348021
1 parent cd5115b commit d1c9751

File tree

6 files changed

+37
-7
lines changed

6 files changed

+37
-7
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// REQUIRES : system-darwin
2+
// RUN: dsymutil -oso-prepend-path %p/.. -dump-debug-map %p/../Inputs/global_downgraded_to_static.x86_64 2>&1 | FileCheck %s
3+
//
4+
// To build:
5+
// clang -g -c -DFILE1 global_downgraded_to_static.c -o 1.o
6+
// clang -g -c -DFILE2 global_downgraded_to_static.c -o 2.o
7+
// ld -r -exported_symbol _foo 1.o -o 1.r.o
8+
// clang 1.r.o 2.o -o global_downgraded_to_static.x86_64
9+
10+
#if defined(FILE1)
11+
int global_to_become_static = 42;
12+
// CHECK: sym: _global_to_become_static,
13+
// CHECK-SAME: binAddr: 0x0000000100001000
14+
int foo() {
15+
return global_to_become_static;
16+
}
17+
#elif defined(FILE2)
18+
int foo(void);
19+
int main() {
20+
return foo();
21+
}
22+
#else
23+
#error Define FILE1 or FILE2
24+
#endif

llvm/tools/dsymutil/MachODebugMapParser.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -511,14 +511,16 @@ void MachODebugMapParser::loadMainBinarySymbols(
511511
// Skip undefined and STAB entries.
512512
if ((Type == SymbolRef::ST_Debug) || (Type == SymbolRef::ST_Unknown))
513513
continue;
514-
// The only symbols of interest are the global variables. These
515-
// are the only ones that need to be queried because the address
516-
// of common data won't be described in the debug map. All other
517-
// addresses should be fetched for the debug map.
514+
// In theory, the only symbols of interest are the global variables. These
515+
// are the only ones that need to be queried because the address of common
516+
// data won't be described in the debug map. All other addresses should be
517+
// fetched for the debug map. In reality, by playing with 'ld -r' and
518+
// export lists, you can get symbols described as N_GSYM in the debug map,
519+
// but associated with a local symbol. Gather all the symbols, but prefer
520+
// the global ones.
518521
uint8_t SymType =
519522
MainBinary.getSymbolTableEntry(Sym.getRawDataRefImpl()).n_type;
520-
if (!(SymType & (MachO::N_EXT | MachO::N_PEXT)))
521-
continue;
523+
bool Extern = SymType & (MachO::N_EXT | MachO::N_PEXT);
522524
Expected<section_iterator> SectionOrErr = Sym.getSection();
523525
if (!SectionOrErr) {
524526
// TODO: Actually report errors helpfully.
@@ -538,7 +540,11 @@ void MachODebugMapParser::loadMainBinarySymbols(
538540
StringRef Name = *NameOrErr;
539541
if (Name.size() == 0 || Name[0] == '\0')
540542
continue;
541-
MainBinarySymbolAddresses[Name] = Addr;
543+
// Override only if the new key is global.
544+
if (Extern)
545+
MainBinarySymbolAddresses[Name] = Addr;
546+
else
547+
MainBinarySymbolAddresses.try_emplace(Name, Addr);
542548
}
543549
}
544550

0 commit comments

Comments
 (0)