diff --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp --- a/lld/MachO/MapFile.cpp +++ b/lld/MachO/MapFile.cpp @@ -40,23 +40,33 @@ using namespace lld; using namespace lld::macho; -// Returns a list of all symbols that we want to print out. -static std::vector getSymbols() { - std::vector v; +using Symbols = std::vector; +// Returns a pair where the left element is a container of all live Symbols and +// the right element is a container of all dead symbols. +static std::pair getSymbols() { + Symbols liveSymbols, deadSymbols; for (InputFile *file : inputFiles) if (isa(file)) for (Symbol *sym : file->symbols) if (auto *d = dyn_cast_or_null(sym)) - if (d->isLive() && d->isec && d->getFile() == file) { - assert(!shouldOmitFromOutput(d->isec)); - v.push_back(d); + if (d->isec && d->getFile() == file) { + if (d->isLive()) { + assert(!shouldOmitFromOutput(d->isec)); + liveSymbols.push_back(d); + } else { + deadSymbols.push_back(d); + } } - parallelSort(v.begin(), v.end(), [](Defined *a, Defined *b) { - return a->getVA() != b->getVA() ? a->getVA() < b->getVA() - : a->getName() < b->getName(); - }); - return v; + parallelSort(liveSymbols.begin(), liveSymbols.end(), + [](Defined *a, Defined *b) { + return a->getVA() != b->getVA() ? a->getVA() < b->getVA() + : a->getName() < b->getName(); + }); + parallelSort( + deadSymbols.begin(), deadSymbols.end(), + [](Defined *a, Defined *b) { return a->getName() < b->getName(); }); + return {std::move(liveSymbols), std::move(deadSymbols)}; } // Construct a map from symbols to their stringified representations. @@ -109,10 +119,6 @@ } } - // Collect symbol info that we want to print out. - std::vector syms = getSymbols(); - DenseMap symStr = getSymbolStrings(syms); - // Dump table of sections os << "# Sections:\n"; os << "# Address\tSize \tSegment\tSection\n"; @@ -126,12 +132,29 @@ } // Dump table of symbols + Symbols liveSymbols, deadSymbols; + std::tie(liveSymbols, deadSymbols) = getSymbols(); + + DenseMap liveSymbolStrings = + getSymbolStrings(liveSymbols); os << "# Symbols:\n"; os << "# Address\t File Name\n"; - for (Symbol *sym : syms) { + for (Symbol *sym : liveSymbols) { + assert(sym->isLive()); os << format("0x%08llX\t[%3u] %s\n", sym->getVA(), - readerToFileOrdinal[sym->getFile()], symStr[sym].c_str()); + readerToFileOrdinal[sym->getFile()], + liveSymbolStrings[sym].c_str()); } - // TODO: when we implement -dead_strip, we should dump dead stripped symbols + if (config->deadStrip) { + DenseMap deadSymbolStrings = + getSymbolStrings(deadSymbols); + os << "# Dead Stripped Symbols:\n"; + os << "# Address\t File Name\n"; + for (Symbol *sym : deadSymbols) { + assert(!sym->isLive()); + os << format("<>\t[%3u] %s\n", readerToFileOrdinal[sym->getFile()], + deadSymbolStrings[sym].c_str()); + } + } } diff --git a/lld/test/MachO/dead-strip.s b/lld/test/MachO/dead-strip.s --- a/lld/test/MachO/dead-strip.s +++ b/lld/test/MachO/dead-strip.s @@ -7,7 +7,6 @@ ## Check that .private_extern symbols are marked as local in the symbol table ## and aren't in the export trie. -## Dead-stripped symbols should also not be in a map file output. # RUN: %lld -lSystem -dead_strip -map %t/map -u _ref_private_extern_u \ # RUN: %t/basics.o -o %t/basics # RUN: llvm-objdump --syms --section-headers %t/basics | \ @@ -16,7 +15,6 @@ # RUN: --exports-trie --indirect-symbols %t/basics | \ # RUN: FileCheck --check-prefix=EXECDATA --implicit-check-not _unref %s # RUN: llvm-otool -l %t/basics | grep -q 'segname __PAGEZERO' -# RUN: FileCheck --check-prefix=MAP --implicit-check-not _unref %s < %t/map # EXEC-LABEL: Sections: # EXEC-LABEL: Name # EXEC-NEXT: __text @@ -44,7 +42,33 @@ # EXECDATA-DAG: _ref_com # EXECDATA-DAG: _no_dead_strip_globl # EXECDATA-DAG: __mh_execute_header + +## Check that dead stripped symbols get listed properly. +# RUN: FileCheck --check-prefix=MAP %s < %t/map + # MAP: _main +# MAP-LABEL: Dead Stripped Symbols +# MAP: <> [ 1] _unref_com +# MAP: <> [ 1] _unref_data +# MAP: <> [ 1] _unref_extern +# MAP: <> [ 1] _unref_local +# MAP: <> [ 1] _unref_private_extern +# MAP: <> [ 1] l_unref_data + +## Run dead stripping on code without any dead symbols. +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \ +# RUN: %t/no-dead-symbols.s -o %t/no-dead-symbols.o +# RUN: %lld -lSystem -dead_strip -map %t/no-dead-symbols-map \ +# RUN: %t/no-dead-symbols.o -o %t/no-dead-symbols +## Mark the end of the file with a string. +# RUN: FileCheck --check-prefix=NODEADSYMBOLS %s < %t/no-dead-symbols-map + +# NODEADSYMBOLS-LABEL: # Symbols: +# NODEADSYMBOLS-NEXT: # Address File Name +# NODEADSYMBOLS-NEXT: _main +# NODEADSYMBOLS-LABEL: # Dead Stripped Symbols: +# NODEADSYMBOLS-NEXT: # Address File Name +# NODEADSYMBOLS-EMPTY: # RUN: %lld -dylib -dead_strip -u _ref_private_extern_u %t/basics.o -o %t/basics.dylib # RUN: llvm-objdump --syms %t/basics.dylib | \ @@ -879,6 +903,12 @@ .subsections_via_symbols +#--- no-dead-symbols.s +.text +.globl _main +_main: + retq + #--- literals.s .cstring _unref_foo: