[lld] ed8bff1 - [lld-macho] implement options -map
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 18 07:39:30 PDT 2021
Author: caoming.roy
Date: 2021-03-18T10:39:19-04:00
New Revision: ed8bff13dcaa123721e0117fb586c3124c03a421
URL: https://github.com/llvm/llvm-project/commit/ed8bff13dcaa123721e0117fb586c3124c03a421
DIFF: https://github.com/llvm/llvm-project/commit/ed8bff13dcaa123721e0117fb586c3124c03a421.diff
LOG: [lld-macho] implement options -map
Implement command-line options -map
Reviewed By: int3, #lld-macho
Differential Revision: https://reviews.llvm.org/D98323
Added:
lld/MachO/MapFile.cpp
lld/MachO/MapFile.h
lld/test/MachO/map-file.s
Modified:
lld/MachO/CMakeLists.txt
lld/MachO/Config.h
lld/MachO/Driver.cpp
lld/MachO/Options.td
lld/MachO/Writer.cpp
Removed:
################################################################################
diff --git a/lld/MachO/CMakeLists.txt b/lld/MachO/CMakeLists.txt
index 8eb3371580b7..16b372945d07 100644
--- a/lld/MachO/CMakeLists.txt
+++ b/lld/MachO/CMakeLists.txt
@@ -24,6 +24,7 @@ add_lld_library(lldMachO2
Symbols.cpp
SyntheticSections.cpp
Target.cpp
+ MapFile.cpp
Writer.cpp
LINK_COMPONENTS
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 93c6a11c0808..611440185837 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -88,6 +88,7 @@ struct Configuration {
uint32_t timeTraceGranularity;
std::string progName;
llvm::StringRef installName;
+ llvm::StringRef mapFile;
llvm::StringRef outputFile;
llvm::StringRef ltoObjPath;
bool demangle = false;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 207dc4f36e6a..c85b72564213 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -826,6 +826,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
for (const Arg *arg : args.filtered(OPT_U))
symtab->addDynamicLookup(arg->getValue());
+ config->mapFile = args.getLastArgValue(OPT_map);
config->outputFile = args.getLastArgValue(OPT_o, "a.out");
config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32);
config->headerPadMaxInstallNames =
diff --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp
new file mode 100644
index 000000000000..e089136ee218
--- /dev/null
+++ b/lld/MachO/MapFile.cpp
@@ -0,0 +1,151 @@
+//===- MapFile.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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the -map option. It shows lists in order and
+// hierarchically the outputFile, arch, input files, output sections and
+// symbol:
+//
+// # Path: test
+// # Arch: x86_84
+// # Object files:
+// [ 0] linker synthesized
+// [ 1] a.o
+// # Sections:
+// # Address Size Segment Section
+// 0x1000005C0 0x0000004C __TEXT __text
+// # Symbols:
+// # Address File Name
+// 0x1000005C0 [ 1] _main
+//
+//===----------------------------------------------------------------------===//
+
+#include "MapFile.h"
+#include "Config.h"
+#include "InputFiles.h"
+#include "InputSection.h"
+#include "OutputSection.h"
+#include "OutputSegment.h"
+#include "Symbols.h"
+#include "Target.h"
+#include "llvm/Support/Parallel.h"
+
+using namespace llvm;
+using namespace llvm::sys;
+using namespace lld;
+using namespace lld::macho;
+
+using SymbolMapTy = DenseMap<const InputSection *, SmallVector<Defined *, 4>>;
+
+// Returns a map from sections to their symbols.
+static SymbolMapTy getSectionSyms(ArrayRef<Defined *> syms) {
+ SymbolMapTy ret;
+ for (Defined *dr : syms)
+ ret[dr->isec].push_back(dr);
+
+ // Sort symbols by address. We want to print out symbols in the
+ // order in the output file rather than the order they appeared
+ // in the input files.
+ for (auto &it : ret)
+ llvm::stable_sort(it.second, [](Defined *a, Defined *b) {
+ return a->getVA() < b->getVA();
+ });
+ return ret;
+}
+
+// Returns a list of all symbols that we want to print out.
+static std::vector<Defined *> getSymbols() {
+ std::vector<Defined *> v;
+ for (InputFile *file : inputFiles)
+ if (isa<ObjFile>(file))
+ for (Symbol *sym : file->symbols) {
+ if (sym == nullptr)
+ continue;
+ if (auto *d = dyn_cast<Defined>(sym))
+ if (d->isec && d->getFile() == file)
+ v.push_back(d);
+ }
+ return v;
+}
+
+// Construct a map from symbols to their stringified representations.
+// Demangling symbols (which is what toString() does) is slow, so
+// we do that in batch using parallel-for.
+static DenseMap<macho::Symbol *, std::string>
+getSymbolStrings(ArrayRef<Defined *> syms) {
+ std::vector<std::string> str(syms.size());
+ parallelForEachN(0, syms.size(), [&](size_t i) {
+ raw_string_ostream os(str[i]);
+ os << toString(*syms[i]);
+ });
+
+ DenseMap<macho::Symbol *, std::string> ret;
+ for (size_t i = 0, e = syms.size(); i < e; ++i)
+ ret[syms[i]] = std::move(str[i]);
+ return ret;
+}
+
+void macho::writeMapFile() {
+ if (config->mapFile.empty())
+ return;
+
+ // Open a map file for writing.
+ std::error_code ec;
+ raw_fd_ostream os(config->mapFile, ec, sys::fs::OF_None);
+ if (ec) {
+ error("cannot open " + config->mapFile + ": " + ec.message());
+ return;
+ }
+
+ // Dump output path
+ os << format("# Path: %s\n", config->outputFile.str().c_str());
+
+ // Dump output architecure
+ os << format("# Arch: %s\n",
+ getArchitectureName(config->target.Arch).str().c_str());
+
+ // Dump table of object files
+ os << "# Object files:\n";
+ os << format("[%3u] %s\n", 0, (const char *)"linker synthesized");
+ uint32_t fileIndex = 1;
+ DenseMap<lld::macho::InputFile *, uint32_t> readerToFileOrdinal;
+ for (InputFile *file : inputFiles) {
+ if (isa<ObjFile>(file)) {
+ os << format("[%3u] %s\n", fileIndex, file->getName().str().c_str());
+ readerToFileOrdinal[file] = fileIndex++;
+ }
+ }
+
+ // Collect symbol info that we want to print out.
+ std::vector<Defined *> syms = getSymbols();
+ SymbolMapTy sectionSyms = getSectionSyms(syms);
+ DenseMap<lld::macho::Symbol *, std::string> symStr = getSymbolStrings(syms);
+
+ // Dump table of sections
+ os << "# Sections:\n";
+ os << "# Address\tSize \tSegment\tSection\n";
+ for (OutputSegment *seg : outputSegments)
+ for (OutputSection *osec : seg->getSections()) {
+ if (osec->isHidden())
+ continue;
+
+ os << format("0x%08llX\t0x%08llX\t%s\t%s\n", osec->addr, osec->getSize(),
+ seg->name.str().c_str(), osec->name.str().c_str());
+ }
+
+ // Dump table of symbols
+ os << "# Symbols:\n";
+ os << "# Address\t File Name\n";
+ for (InputSection *isec : inputSections) {
+ for (macho::Symbol *sym : sectionSyms[isec]) {
+ os << format("0x%08llX\t[%3u] %s\n", sym->getVA(),
+ readerToFileOrdinal[sym->getFile()], symStr[sym].c_str());
+ }
+ }
+
+ // TODO: when we implement -dead_strip, we should dump dead stripped symbols
+}
diff --git a/lld/MachO/MapFile.h b/lld/MachO/MapFile.h
new file mode 100644
index 000000000000..bf16ffdd0382
--- /dev/null
+++ b/lld/MachO/MapFile.h
@@ -0,0 +1,18 @@
+//===- MapFile.h ------------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_MACHO_MAPFILE_H
+#define LLD_MACHO_MAPFILE_H
+
+namespace lld {
+namespace macho {
+void writeMapFile();
+} // namespace macho
+} // namespace lld
+
+#endif
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 6af0d2c4152f..af8e44e73724 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -500,7 +500,6 @@ def order_file_statistics : Flag<["-"], "order_file_statistics">,
def map : Separate<["-"], "map">,
MetaVarName<"<path>">,
HelpText<"Writes all symbols and their addresses to <path>">,
- Flags<[HelpHidden]>,
Group<grp_introspect>;
def dependency_info : Separate<["-"], "dependency_info">,
MetaVarName<"<path>">,
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 62f4eef19498..b2d316355807 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -10,6 +10,7 @@
#include "Config.h"
#include "InputFiles.h"
#include "InputSection.h"
+#include "MapFile.h"
#include "MergedOutputSection.h"
#include "OutputSection.h"
#include "OutputSegment.h"
@@ -926,6 +927,7 @@ void Writer::run() {
createLoadCommands();
finalizeAddressses();
finalizeLinkEditSegment();
+ writeMapFile();
openFile();
if (errorCount())
return;
diff --git a/lld/test/MachO/map-file.s b/lld/test/MachO/map-file.s
new file mode 100644
index 000000000000..ac5fb93898d3
--- /dev/null
+++ b/lld/test/MachO/map-file.s
@@ -0,0 +1,50 @@
+# REQUIRES: x86
+# RUN: rm -rf %t; split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
+
+# RUN: %lld -map %t/map %t/test.o %t/foo.o -o %t/test-map
+# RUN: llvm-objdump --syms --section-headers %t/test-map > %t/objdump
+# RUN: cat %t/objdump %t/map > %t/out
+# RUN: FileCheck %s < %t/out
+
+#--- foo.s
+.section __TEXT,obj
+.globl _foo
+_foo:
+
+#--- test.s
+.comm _number, 1
+.globl _main
+_main:
+ ret
+
+# CHECK: Sections:
+# CHECK-NEXT: Idx Name Size VMA Type
+# CHECK-NEXT: 0 __text {{[0-9a-f]+}} [[#%x,TEXT:]] TEXT
+# CHECK-NEXT: 1 obj {{[0-9a-f]+}} [[#%x,DATA:]] DATA
+# CHECK-NEXT: 2 __common {{[0-9a-f]+}} [[#%x,BSS:]] BSS
+
+# CHECK: SYMBOL TABLE:
+# CHECK-NEXT: [[#%x,MAIN:]] g F __TEXT,__text _main
+# CHECK-NEXT: [[#%x,NUMBER:]] g O __DATA,__common _number
+# CHECK-NEXT: [[#%x,FOO:]] g O __TEXT,obj _foo
+
+# CHECK-NEXT: # Path: {{.*}}{{/|\\}}map-file.s.tmp/test-map
+# CHECK-NEXT: # Arch: x86_64
+# CHECK-NEXT: # Object files:
+# CHECK-NEXT: [ 0] linker synthesized
+# CHECK-NEXT: [ 1] {{.*}}{{/|\\}}map-file.s.tmp/test.o
+# CHECK-NEXT: [ 2] {{.*}}{{/|\\}}map-file.s.tmp/foo.o
+
+# CHECK-NEXT: # Sections:
+# CHECK-NEXT: # Address Size Segment Section
+# CHECK-NEXT: 0x[[#TEXT]] 0x{{[0-9a-f]+}} __TEXT __text
+# CHECK-NEXT: 0x[[#DATA]] 0x{{[0-9a-f]+}} __TEXT obj
+# CHECK-NEXT: 0x[[#BSS]] 0x{{[0-9a-f]+}} __DATA __common
+
+# CHECK-NEXT: # Symbols:
+# CHECK-NEXT: # Address File Name
+# CHECK-NEXT: 0x[[#NUMBER]] [ 1] _number
+# CHECK-NEXT: 0x[[#MAIN]] [ 1] _main
+# CHECK-NEXT: 0x[[#FOO]] [ 2] _foo
More information about the llvm-commits
mailing list