Skip to content

Commit 4220843

Browse files
Roger Kimint3
authored andcommitted
[lld][Macho] Include dead-stripped symbols in mapfile
ld64 outputs dead stripped symbols when using the -dead-strip flag. This change mimics that behavior for lld. ld64's -dead_strip flag outputs: ``` $ ld -map map basics.o -o out -dead_strip -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem $ cat map # Path: out # Arch: x86_64 # Object files: [ 0] linker synthesized [ 1] basics.o # Sections: # Address Size Segment Section 0x100003F97 0x00000021 __TEXT __text 0x100003FB8 0x00000048 __TEXT __unwind_info 0x100004000 0x00000008 __DATA_CONST __got 0x100008000 0x00000010 __DATA __ref_section 0x100008010 0x00000001 __DATA __common # Symbols: # Address Size File Name 0x100003F97 0x00000006 [ 1] _ref_local 0x100003F9D 0x00000001 [ 1] _ref_private_extern 0x100003F9E 0x0000000C [ 1] _main 0x100003FAA 0x00000006 [ 1] _no_dead_strip_globl 0x100003FB0 0x00000001 [ 1] _ref_from_no_dead_strip_globl 0x100003FB1 0x00000006 [ 1] _no_dead_strip_local 0x100003FB7 0x00000001 [ 1] _ref_from_no_dead_strip_local 0x100003FB8 0x00000048 [ 0] compact unwind info 0x100004000 0x00000008 [ 0] non-lazy-pointer-to-local: _ref_com 0x100008000 0x00000008 [ 1] _ref_data 0x100008008 0x00000008 [ 1] l_ref_data 0x100008010 0x00000001 [ 1] _ref_com # Dead Stripped Symbols: # Size File Name <<dead>> 0x00000006 [ 1] _unref_extern <<dead>> 0x00000001 [ 1] _unref_local <<dead>> 0x00000007 [ 1] _unref_private_extern <<dead>> 0x00000001 [ 1] _ref_private_extern_u <<dead>> 0x00000008 [ 1] _unref_data <<dead>> 0x00000008 [ 1] l_unref_data <<dead>> 0x00000001 [ 1] _unref_com ``` Reviewed By: int3, #lld-macho, thevinster Differential Revision: https://reviews.llvm.org/D114737
1 parent ad4ee2d commit 4220843

File tree

2 files changed

+73
-20
lines changed

2 files changed

+73
-20
lines changed

lld/MachO/MapFile.cpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,32 @@ using namespace llvm::sys;
4040
using namespace lld;
4141
using namespace lld::macho;
4242

43-
// Returns a list of all symbols that we want to print out.
44-
static std::vector<Defined *> getSymbols() {
45-
std::vector<Defined *> v;
43+
using Symbols = std::vector<Defined *>;
44+
// Returns a pair where the left element is a container of all live Symbols and
45+
// the right element is a container of all dead symbols.
46+
static std::pair<Symbols, Symbols> getSymbols() {
47+
Symbols liveSymbols, deadSymbols;
4648
for (InputFile *file : inputFiles)
4749
if (isa<ObjFile>(file))
4850
for (Symbol *sym : file->symbols)
4951
if (auto *d = dyn_cast_or_null<Defined>(sym))
50-
if (d->isLive() && d->isec && d->getFile() == file) {
51-
assert(!shouldOmitFromOutput(d->isec));
52-
v.push_back(d);
52+
if (d->isec && d->getFile() == file) {
53+
if (d->isLive()) {
54+
assert(!shouldOmitFromOutput(d->isec));
55+
liveSymbols.push_back(d);
56+
} else {
57+
deadSymbols.push_back(d);
58+
}
5359
}
54-
return v;
60+
parallelSort(liveSymbols.begin(), liveSymbols.end(),
61+
[](Defined *a, Defined *b) {
62+
return a->getVA() != b->getVA() ? a->getVA() < b->getVA()
63+
: a->getName() < b->getName();
64+
});
65+
parallelSort(
66+
deadSymbols.begin(), deadSymbols.end(),
67+
[](Defined *a, Defined *b) { return a->getName() < b->getName(); });
68+
return {std::move(liveSymbols), std::move(deadSymbols)};
5569
}
5670

5771
// Construct a map from symbols to their stringified representations.
@@ -104,14 +118,6 @@ void macho::writeMapFile() {
104118
}
105119
}
106120

107-
// Collect symbol info that we want to print out.
108-
std::vector<Defined *> syms = getSymbols();
109-
parallelSort(syms.begin(), syms.end(), [](Defined *a, Defined *b) {
110-
return a->getVA() != b->getVA() ? a->getVA() < b->getVA()
111-
: a->getName() < b->getName();
112-
});
113-
DenseMap<Symbol *, std::string> symStr = getSymbolStrings(syms);
114-
115121
// Dump table of sections
116122
os << "# Sections:\n";
117123
os << "# Address\tSize \tSegment\tSection\n";
@@ -125,12 +131,29 @@ void macho::writeMapFile() {
125131
}
126132

127133
// Dump table of symbols
134+
Symbols liveSymbols, deadSymbols;
135+
std::tie(liveSymbols, deadSymbols) = getSymbols();
136+
137+
DenseMap<Symbol *, std::string> liveSymbolStrings =
138+
getSymbolStrings(liveSymbols);
128139
os << "# Symbols:\n";
129140
os << "# Address\t File Name\n";
130-
for (Symbol *sym : syms) {
141+
for (Symbol *sym : liveSymbols) {
142+
assert(sym->isLive());
131143
os << format("0x%08llX\t[%3u] %s\n", sym->getVA(),
132-
readerToFileOrdinal[sym->getFile()], symStr[sym].c_str());
144+
readerToFileOrdinal[sym->getFile()],
145+
liveSymbolStrings[sym].c_str());
133146
}
134147

135-
// TODO: when we implement -dead_strip, we should dump dead stripped symbols
148+
if (config->deadStrip) {
149+
DenseMap<Symbol *, std::string> deadSymbolStrings =
150+
getSymbolStrings(deadSymbols);
151+
os << "# Dead Stripped Symbols:\n";
152+
os << "# Address\t File Name\n";
153+
for (Symbol *sym : deadSymbols) {
154+
assert(!sym->isLive());
155+
os << format("<<dead>>\t[%3u] %s\n", readerToFileOrdinal[sym->getFile()],
156+
deadSymbolStrings[sym].c_str());
157+
}
158+
}
136159
}

lld/test/MachO/dead-strip.s

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
## Check that .private_extern symbols are marked as local in the symbol table
99
## and aren't in the export trie.
10-
## Dead-stripped symbols should also not be in a map file output.
1110
# RUN: %lld -lSystem -dead_strip -map %t/map -u _ref_private_extern_u \
1211
# RUN: %t/basics.o -o %t/basics
1312
# RUN: llvm-objdump --syms --section-headers %t/basics | \
@@ -16,7 +15,6 @@
1615
# RUN: --exports-trie --indirect-symbols %t/basics | \
1716
# RUN: FileCheck --check-prefix=EXECDATA --implicit-check-not _unref %s
1817
# RUN: llvm-otool -l %t/basics | grep -q 'segname __PAGEZERO'
19-
# RUN: FileCheck --check-prefix=MAP --implicit-check-not _unref %s < %t/map
2018
# EXEC-LABEL: Sections:
2119
# EXEC-LABEL: Name
2220
# EXEC-NEXT: __text
@@ -44,7 +42,33 @@
4442
# EXECDATA-DAG: _ref_com
4543
# EXECDATA-DAG: _no_dead_strip_globl
4644
# EXECDATA-DAG: __mh_execute_header
45+
46+
## Check that dead stripped symbols get listed properly.
47+
# RUN: FileCheck --check-prefix=MAP %s < %t/map
48+
4749
# MAP: _main
50+
# MAP-LABEL: Dead Stripped Symbols
51+
# MAP: <<dead>> [ 1] _unref_com
52+
# MAP: <<dead>> [ 1] _unref_data
53+
# MAP: <<dead>> [ 1] _unref_extern
54+
# MAP: <<dead>> [ 1] _unref_local
55+
# MAP: <<dead>> [ 1] _unref_private_extern
56+
# MAP: <<dead>> [ 1] l_unref_data
57+
58+
## Run dead stripping on code without any dead symbols.
59+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \
60+
# RUN: %t/no-dead-symbols.s -o %t/no-dead-symbols.o
61+
# RUN: %lld -lSystem -dead_strip -map %t/no-dead-symbols-map \
62+
# RUN: %t/no-dead-symbols.o -o %t/no-dead-symbols
63+
## Mark the end of the file with a string.
64+
# RUN: FileCheck --check-prefix=NODEADSYMBOLS %s < %t/no-dead-symbols-map
65+
66+
# NODEADSYMBOLS-LABEL: # Symbols:
67+
# NODEADSYMBOLS-NEXT: # Address File Name
68+
# NODEADSYMBOLS-NEXT: _main
69+
# NODEADSYMBOLS-LABEL: # Dead Stripped Symbols:
70+
# NODEADSYMBOLS-NEXT: # Address File Name
71+
# NODEADSYMBOLS-EMPTY:
4872

4973
# RUN: %lld -dylib -dead_strip -u _ref_private_extern_u %t/basics.o -o %t/basics.dylib
5074
# RUN: llvm-objdump --syms %t/basics.dylib | \
@@ -879,6 +903,12 @@ _main:
879903

880904
.subsections_via_symbols
881905

906+
#--- no-dead-symbols.s
907+
.text
908+
.globl _main
909+
_main:
910+
retq
911+
882912
#--- literals.s
883913
.cstring
884914
_unref_foo:

0 commit comments

Comments
 (0)