summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-09-30 23:15:39 +0000
committerNick Kledzik <kledzik@apple.com>2014-09-30 23:15:39 +0000
commitbe43d7ef29a6034a54c374ec619b251f18d4161a (patch)
tree3417c3a9d546256545eb3357617151d3e8309674
parentffb650856d48262ac78c1eb61f634f528c6a35d1 (diff)
downloadbcm5719-llvm-be43d7ef29a6034a54c374ec619b251f18d4161a.tar.gz
bcm5719-llvm-be43d7ef29a6034a54c374ec619b251f18d4161a.zip
[mach-o] Implement -demangle.
The darwin linker has the -demangle option which directs it to demangle C++ (and soon Swift) mangled symbol names. Long term we need some Diagnostics object for formatting errors and warnings. But for now we have the Core linker just writing messages to llvm::errs(). So, to enable demangling, I changed the Resolver to call a LinkingContext method on the symbol name. To make this more interesting, the demangling code is done via __cxa_demangle() which is part of the C++ ABI, which is only supported on some platforms, so I had to conditionalize the code with the config generated HAVE_CXXABI_H. llvm-svn: 218718
-rw-r--r--lld/include/lld/Core/LinkingContext.h5
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h6
-rw-r--r--lld/lib/Core/Resolver.cpp3
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp4
-rw-r--r--lld/lib/Driver/DarwinLdOptions.td2
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp35
-rw-r--r--lld/test/mach-o/demangle.yaml74
7 files changed, 127 insertions, 2 deletions
diff --git a/lld/include/lld/Core/LinkingContext.h b/lld/include/lld/Core/LinkingContext.h
index edb62dd98f6..b0048cc7f8e 100644
--- a/lld/include/lld/Core/LinkingContext.h
+++ b/lld/include/lld/Core/LinkingContext.h
@@ -270,6 +270,11 @@ public:
/// \returns true if there is an error with the current settings.
bool validate(raw_ostream &diagnostics);
+ /// Formats symbol name for use in error messages.
+ virtual std::string demangle(StringRef symbolName) const {
+ return symbolName;
+ }
+
/// @}
/// \name Methods used by Driver::link()
/// @{
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
index 68a003a29d2..a2968047d74 100644
--- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -66,6 +66,8 @@ public:
void addPasses(PassManager &pm) override;
bool validateImpl(raw_ostream &diagnostics) override;
+ std::string demangle(StringRef symbolName) const override;
+
bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) const override;
uint32_t getCPUType() const;
@@ -95,6 +97,9 @@ public:
bool keepPrivateExterns() const { return _keepPrivateExterns; }
void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
+ bool demangleSymbols() const { return _demangle; }
+ void setDemangleSymbols(bool d) { _demangle = d; }
+
bool minOS(StringRef mac, StringRef iOS) const;
void setDoNothing(bool value) { _doNothing = value; }
@@ -289,6 +294,7 @@ private:
bool _printAtoms;
bool _testingFileUsage;
bool _keepPrivateExterns;
+ bool _demangle;
StringRef _bundleLoader;
mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
mutable std::unique_ptr<Writer> _writer;
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index 85ecad0c127..417442de0f2 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -393,7 +393,8 @@ bool Resolver::checkUndefines() {
foundUndefines = true;
if (_context.printRemainingUndefines()) {
llvm::errs() << "Undefined symbol: " << undefAtom->file().path()
- << ": " << undefAtom->name() << "\n";
+ << ": " << _context.demangle(undefAtom->name())
+ << "\n";
}
}
if (foundUndefines) {
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
index 3f9f7012b42..407bd19fe61 100644
--- a/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -425,6 +425,10 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (parsedArgs->getLastArg(OPT_t))
ctx.setLogInputFiles(true);
+ // Handle -demangle option.
+ if (parsedArgs->getLastArg(OPT_demangle))
+ ctx.setDemangleSymbols(true);
+
// Handle -keep_private_externs
if (parsedArgs->getLastArg(OPT_keep_private_externs)) {
ctx.setKeepPrivateExterns(true);
diff --git a/lld/lib/Driver/DarwinLdOptions.td b/lld/lib/Driver/DarwinLdOptions.td
index 1392eaae3cc..73672fdad8b 100644
--- a/lld/lib/Driver/DarwinLdOptions.td
+++ b/lld/lib/Driver/DarwinLdOptions.td
@@ -144,6 +144,8 @@ def sectalign : MultiArg<["-"], "sectalign", 3>,
HelpText<"alignment for segment/section">;
def image_base : Separate<["-"], "image_base">;
def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
+def demangle : Flag<["-"], "demangle">,
+ HelpText<"Demangles symbol names in errors and warnings">;
def t : Flag<["-"], "t">,
HelpText<"Print the names of the input files as ld processes them">;
diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index e40c3d8582c..b512d48943d 100644
--- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Config/config.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MachO.h"
@@ -30,6 +31,10 @@
#include <algorithm>
+#if HAVE_CXXABI_H
+#include <cxxabi.h>
+#endif
+
using lld::mach_o::ArchHandler;
using lld::mach_o::MachODylibFile;
using namespace llvm::MachO;
@@ -137,7 +142,8 @@ MachOLinkingContext::MachOLinkingContext()
_osMinVersion(0), _pageZeroSize(0), _pageSize(4096), _baseAddress(0),
_compatibilityVersion(0), _currentVersion(0), _deadStrippableDylib(false),
_printAtoms(false), _testingFileUsage(false), _keepPrivateExterns(false),
- _archHandler(nullptr), _exportMode(ExportMode::globals) {}
+ _demangle(false), _archHandler(nullptr),
+ _exportMode(ExportMode::globals) {}
MachOLinkingContext::~MachOLinkingContext() {}
@@ -659,5 +665,32 @@ bool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
llvm_unreachable("_exportMode unknown enum value");
}
+std::string MachOLinkingContext::demangle(StringRef symbolName) const {
+ // Only try to demangle symbols if -demangle on command line
+ if (!_demangle)
+ return symbolName;
+
+ // Only try to demangle symbols that look like C++ symbols
+ if (!symbolName.startswith("__Z"))
+ return symbolName;
+
+#if HAVE_CXXABI_H
+ SmallString<256> symBuff;
+ StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
+ // Mach-O has extra leading underscore that needs to be removed.
+ const char *cstr = nullTermSym.data() + 1;
+ int status;
+ char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
+ if (demangled != NULL) {
+ std::string result(demangled);
+ // __cxa_demangle() always uses a malloc'ed buffer to return the result.
+ free(demangled);
+ return result;
+ }
+#endif
+
+ return symbolName;
+}
+
} // end namespace lld
diff --git a/lld/test/mach-o/demangle.yaml b/lld/test/mach-o/demangle.yaml
new file mode 100644
index 00000000000..64054580847
--- /dev/null
+++ b/lld/test/mach-o/demangle.yaml
@@ -0,0 +1,74 @@
+# REQUIRES: system-linker-mach-o
+#
+# RUN: not lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: -dylib -o %t %p/Inputs/libSystem.yaml 2> %t.err
+# RUN: FileCheck %s < %t.err
+#
+# RUN: not lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: -dylib -o %t %p/Inputs/libSystem.yaml -demangle 2> %t.err2
+# RUN: FileCheck %s --check-prefix=DCHECK < %t.err2
+#
+# Test -demangle option works on undefined symbol errors.
+#
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00,
+ 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x0000000B
+ type: X86_64_RELOC_BRANCH
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 2
+ - offset: 0x00000006
+ type: X86_64_RELOC_BRANCH
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 3
+ - offset: 0x00000001
+ type: X86_64_RELOC_BRANCH
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 1
+global-symbols:
+ - name: __Z1xv
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: __Znam
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: __Znotcpp
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _foo
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+
+...
+
+# CHECK: __Znotcpp
+# CHECK: __Znam
+# CHECK: _foo
+
+# DCHECK: __Znotcpp
+# DCHECK: operator new[](unsigned long)
+# DCHECK: _foo
+
OpenPOWER on IntegriCloud