From 3dadd20fe5bfd52554d9a77ecb088c20c5bfecea Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Mon, 20 Oct 2014 05:04:53 +0000 Subject: [PATCH] [ELF] Implement demangle. This adds functionality in the GNU flavor to demangle symbols when undefined symbols are displayed to the user. llvm-svn: 220184 --- lld/include/lld/ReaderWriter/ELFLinkingContext.h | 6 ++++ lld/lib/Driver/GnuLdDriver.cpp | 8 +++++ lld/lib/Driver/GnuLdOptions.td | 12 +++++++ lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp | 41 +++++++++++++++++++---- lld/test/elf/X86_64/Inputs/undefcpp.c | 1 + lld/test/elf/X86_64/Inputs/undefcpp.o | Bin 0 -> 1344 bytes lld/test/elf/X86_64/demangle.test | 10 ++++++ 7 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 lld/test/elf/X86_64/Inputs/undefcpp.c create mode 100644 lld/test/elf/X86_64/Inputs/undefcpp.o create mode 100644 lld/test/elf/X86_64/demangle.test diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h index eda445b..225d3ca 100644 --- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h +++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h @@ -275,6 +275,11 @@ public: return _dynamicallyExportedSymbols.count(name) != 0; } + /// \brief Demangle symbols. + std::string demangle(StringRef symbolName) const override; + bool demangleSymbols() const { return _demangle; } + void setDemangleSymbols(bool d) { _demangle = d; } + private: ELFLinkingContext() LLVM_DELETED_FUNCTION; @@ -299,6 +304,7 @@ protected: bool _dynamicLinkerArg; bool _noAllowDynamicLibraries; bool _mergeRODataToTextSegment; + bool _demangle; OutputMagic _outputMagic; StringRefVector _inputSearchPaths; std::unique_ptr _writer; diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp index 0d2dea3..542b1bd 100644 --- a/lld/lib/Driver/GnuLdDriver.cpp +++ b/lld/lib/Driver/GnuLdDriver.cpp @@ -305,6 +305,14 @@ bool GnuLdDriver::parse(int argc, const char *argv[], if (!parsedArgs->hasArg(OPT_nostdlib)) addPlatformSearchDirs(*ctx, triple, baseTriple); + // Handle --demangle option(For compatibility) + if (parsedArgs->getLastArg(OPT_demangle)) + ctx->setDemangleSymbols(true); + + // Handle --no-demangle option. + if (parsedArgs->getLastArg(OPT_no_demangle)) + ctx->setDemangleSymbols(false); + // Figure out output kind ( -r, -static, -shared) if (llvm::opt::Arg *kind = parsedArgs->getLastArg(OPT_relocatable, OPT_static, OPT_shared, diff --git a/lld/lib/Driver/GnuLdOptions.td b/lld/lib/Driver/GnuLdOptions.td index 590ce95..0abb7e5 100644 --- a/lld/lib/Driver/GnuLdOptions.td +++ b/lld/lib/Driver/GnuLdOptions.td @@ -215,6 +215,18 @@ def z : Separate<["-"], "z">, Group; //===----------------------------------------------------------------------===// +/// Symbol options +//===----------------------------------------------------------------------===// +def grp_symbolopts : OptionGroup<"opts">, + HelpText<"SYMBOL OPTIONS">; +def demangle : Flag<["--"], "demangle">, + HelpText<"Demangle C++ symbols">, + Group; +def no_demangle : Flag<["--"], "no-demangle">, + HelpText<"Dont demangle C++ symbols">, + Group; + +//===----------------------------------------------------------------------===// /// Optimization Options //===----------------------------------------------------------------------===// def grp_opts : OptionGroup<"opts">, diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp index e3428fb..9dba86a 100644 --- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -16,11 +16,16 @@ #include "lld/Passes/LayoutPass.h" #include "lld/Passes/RoundTripYAMLPass.h" #include "llvm/ADT/Triple.h" +#include "llvm/Config/config.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#if HAVE_CXXABI_H +#include +#endif + namespace lld { class CommandLineAbsoluteAtom : public AbsoluteAtom { @@ -53,12 +58,11 @@ ELFLinkingContext::ELFLinkingContext( llvm::Triple triple, std::unique_ptr targetHandler) : _outputELFType(elf::ET_EXEC), _triple(triple), _targetHandler(std::move(targetHandler)), _baseAddress(0), - _isStaticExecutable(false), _noInhibitExec(false), - _exportDynamic(false), _mergeCommonStrings(false), - _runLayoutPass(true), _useShlibUndefines(true), - _dynamicLinkerArg(false), _noAllowDynamicLibraries(false), - _mergeRODataToTextSegment(true), _outputMagic(OutputMagic::DEFAULT), - _sysrootPath("") {} + _isStaticExecutable(false), _noInhibitExec(false), _exportDynamic(false), + _mergeCommonStrings(false), _runLayoutPass(true), + _useShlibUndefines(true), _dynamicLinkerArg(false), + _noAllowDynamicLibraries(false), _mergeRODataToTextSegment(true), + _demangle(true), _outputMagic(OutputMagic::DEFAULT), _sysrootPath("") {} bool ELFLinkingContext::is64Bits() const { return getTriple().isArch64Bit(); } @@ -260,4 +264,29 @@ void ELFLinkingContext::notifySymbolTableCoalesce(const Atom *existingAtom, _dynamicallyExportedSymbols.insert(ua->name()); } +std::string ELFLinkingContext::demangle(StringRef symbolName) const { + 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); + const char *cstr = nullTermSym.data(); + 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/elf/X86_64/Inputs/undefcpp.c b/lld/test/elf/X86_64/Inputs/undefcpp.c new file mode 100644 index 0000000..ce84c2a --- /dev/null +++ b/lld/test/elf/X86_64/Inputs/undefcpp.c @@ -0,0 +1 @@ +int foo() { return _Z3fooPKc(); } diff --git a/lld/test/elf/X86_64/Inputs/undefcpp.o b/lld/test/elf/X86_64/Inputs/undefcpp.o new file mode 100644 index 0000000000000000000000000000000000000000..6b8ebf5b6ab0cd1a18579566fba5a6a2bc5de976 GIT binary patch literal 1344 zcmbtTPfG$(5Pz$dT2@O`M0M~OK`%jwx`ZM90VAaFP!O`NYeu>&?iSXiThOhK&`0Py z^jU(Ab`NZ3cSfEMPc`t~Z{|0DcOLt6aB>(kjJO~%#GWwNP*EWZAzu&~krtKXm(O?c zh0N6l-ge7!ue0|~*T3=HY+i25To&jB^nt`5&xFx4jnzyt^$IoDfWw0_gV+A7`5Y_G zOrnk=yH3lJfzu0ww7quQaY3p1zL2gLIP&PUvgrqweM^B(v)brdZAVDI=?C4ws)5G% z&<^do6YlMF_x}f6dQ8F3y#MqYC$5Qc2J;7KL#|(L)Da4b@O|&SPo|6y#z|5H<;SG@kdz z^ad#UPSCeLX8%dxIiL5x3!J_?%zwiR-~$sjqBg1 zeB7@pdVkfY>T_Tu#P>kuSdR~1kC_PLV<*A+#%&mRTJmTa;Pt*EWI3VzSLG7tZ6 sSlJv6jjV>}iRxt@pj@)Wom+PrcBdn4iscUYCTTc7gGjREM_zreU%^C5E&u=k literal 0 HcmV?d00001 diff --git a/lld/test/elf/X86_64/demangle.test b/lld/test/elf/X86_64/demangle.test new file mode 100644 index 0000000..820e6be --- /dev/null +++ b/lld/test/elf/X86_64/demangle.test @@ -0,0 +1,10 @@ +# Check that the linker is able to demangle strings properly. +# Once there is a way to add undefined symbols using yaml2obj, the test will be +# changed. +# +RUN: lld -flavor gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec 2>&1 | FileCheck -check-prefix=DEMANGLE %s +RUN: lld -flavor gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec --no-demangle 2>&1 | FileCheck -check-prefix=NODEMANGLE %s +RUN: lld -flavor gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec --demangle 2>&1 | FileCheck -check-prefix=DEMANGLE %s + +#DEMANGLE: undefcpp.o: foo(char const*) +#NODEMANGLE: undefcpp.o: _Z3fooPKc -- 2.7.4