[lld] r223341 - [PECOFF] Improve /export compatibility.
David Majnemer
david.majnemer at gmail.com
Wed Dec 3 22:18:41 PST 2014
What happens if the object file contains 'foo' and '_foo at 8' and you
/export:foo?
On Wed, Dec 3, 2014 at 10:09 PM, Rui Ueyama <ruiu at google.com> wrote:
> Author: ruiu
> Date: Thu Dec 4 00:09:39 2014
> New Revision: 223341
>
> URL: http://llvm.org/viewvc/llvm-project?rev=223341&view=rev
> Log:
> [PECOFF] Improve /export compatibility.
>
> Looks like the rule of /export is more complicated than
> I was thinking. If /export:foo, for example, is given, and
> if the actual symbol name in an object file is _foo@<number>,
> we need to export that symbol as foo, not as the mangled name.
>
> If only /export:_foo@<number> is given, the symbol is exported
> as _foo@<number>.
>
> If both /export:foo and /export:_foo@<number> are given,
> they are considered as duplicates, and the linker needs to
> choose the unmangled name.
>
> The basic idea seems that the linker needs to export a symbol
> with the same name as given as /export.
>
> We exported mangled symbols. This patch fixes that issue.
>
> Modified:
> lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
> lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp
> lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
> lld/trunk/test/pecoff/export.test
>
> Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223341&r1=223340&r2=223341&view=diff
>
> ==============================================================================
> --- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
> +++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Thu Dec 4
> 00:09:39 2014
> @@ -65,14 +65,17 @@ public:
> return getExternalName().compare(other.getExternalName()) < 0;
> }
>
> + StringRef getRealName() const {
> + return mangledName.empty() ? name : mangledName;
> + }
> +
> StringRef getExternalName() const {
> - if (!externalName.empty())
> - return externalName;
> - return name;
> + return externalName.empty() ? name : externalName;
> }
>
> std::string name;
> std::string externalName;
> + std::string mangledName;
> int ordinal;
> bool noname;
> bool isData;
>
> Modified: lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp?rev=223341&r1=223340&r2=223341&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/PECOFF/EdataPass.cpp Thu Dec 4 00:09:39
> 2014
> @@ -26,20 +26,54 @@ using llvm::object::export_directory_tab
> namespace lld {
> namespace pecoff {
>
> +typedef PECOFFLinkingContext::ExportDesc ExportDesc;
> +
> +// dedupExports removes duplicate export entries. If two exports are
> +// referring the same symbol, they are considered duplicates.
> +// This could happen if the same symbol name is specified as an argument
> +// to /export more than once, or an unmangled and mangled name of the
> +// same symbol are given to /export. In the latter case, we choose
> +// unmangled (shorter) name.
> +static void dedupExports(PECOFFLinkingContext &ctx) {
> + std::vector<ExportDesc> &exports = ctx.getDllExports();
> + // Pass 1: find duplicate entries
> + std::set<const ExportDesc *> dup;
> + std::map<StringRef, ExportDesc *> map;
> + for (ExportDesc &exp : exports) {
> + if (!exp.externalName.empty())
> + continue;;
>
Extra semi-colon?
> + StringRef symbol = exp.getRealName();
> + auto it = map.find(symbol);
> + if (it == map.end()) {
> + map[symbol] = &exp;
> + } else if (symbol.size() < it->second->getRealName().size()) {
> + map[symbol] = &exp;
> + dup.insert(it->second);
> + } else {
> + dup.insert(&exp);
> + }
> + }
> + // Pass 2: remove duplicate entries
> + auto pred = [&](const ExportDesc &exp) {
> + return dup.count(&exp) == 1;
> + };
> + exports.erase(std::remove_if(exports.begin(), exports.end(), pred),
> + exports.end());
> +}
> +
> static void assignOrdinals(PECOFFLinkingContext &ctx) {
> - std::vector<PECOFFLinkingContext::ExportDesc> &exports =
> ctx.getDllExports();
> + std::vector<ExportDesc> &exports = ctx.getDllExports();
> int maxOrdinal = -1;
> - for (PECOFFLinkingContext::ExportDesc &desc : exports)
> + for (ExportDesc &desc : exports)
> maxOrdinal = std::max(maxOrdinal, desc.ordinal);
>
> std::sort(exports.begin(), exports.end(),
> - [](const PECOFFLinkingContext::ExportDesc &a,
> - const PECOFFLinkingContext::ExportDesc &b) {
> + [](const ExportDesc &a, const ExportDesc &b) {
> return a.getExternalName().compare(b.getExternalName()) < 0;
> });
>
> int nextOrdinal = (maxOrdinal == -1) ? 1 : (maxOrdinal + 1);
> - for (PECOFFLinkingContext::ExportDesc &desc : exports)
> + for (ExportDesc &desc : exports)
> if (desc.ordinal == -1)
> desc.ordinal = nextOrdinal++;
> }
> @@ -51,7 +85,7 @@ static bool getExportedAtoms(PECOFFLinki
> definedAtoms[atom->name()] = atom;
>
> for (PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
> - auto it = definedAtoms.find(desc.name);
> + auto it = definedAtoms.find(desc.getRealName());
> if (it == definedAtoms.end()) {
> llvm::errs() << "Symbol <" << desc.name
> << "> is exported but not defined.\n";
> @@ -142,6 +176,7 @@ EdataPass::createOrdinalTable(const std:
> }
>
> void EdataPass::perform(std::unique_ptr<MutableFile> &file) {
> + dedupExports(_ctx);
> assignOrdinals(_ctx);
>
> std::vector<TableEntry> entries;
>
> Modified: lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h?rev=223341&r1=223340&r2=223341&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
> (original)
> +++ lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h Thu Dec
> 4 00:09:39 2014
> @@ -261,29 +261,11 @@ public:
> if (!findDecoratedSymbol(_ctx, _syms.get(), sym.str(), replace))
> return nullptr;
>
> - // We found a decorated symbol. There may be another symbol that
> - // has the same decorated name. If that's the case, we remove the
> - // duplicate item.
> - std::vector<ExportDesc> &exp = _ctx->getDllExports();
> - auto isFound = std::find_if(
> - exp.begin(), exp.end(),
> - [&](ExportDesc &e) { return e.getExternalName().equals(replace);
> });
> - if (isFound != exp.end()) {
> - exp.erase(
> - std::remove_if(exp.begin(), exp.end(),
> - [&](ExportDesc &e) { return e.name == sym; }),
> - exp.end());
> - } else {
> - for (ExportDesc &e : exp) {
> - if (e.name == sym) {
> - e.name = replace;
> - break;
> - }
> - }
> - if (_ctx->deadStrip())
> - _ctx->addDeadStripRoot(_ctx->allocate(replace));
> - }
> -
> + for (ExportDesc &exp : _ctx->getDllExports())
> + if (exp.name == sym)
> + exp.mangledName = replace;
> + if (_ctx->deadStrip())
> + _ctx->addDeadStripRoot(_ctx->allocate(replace));
> return new (_alloc) impl::SymbolRenameFile(sym, replace);
> }
>
>
> Modified: lld/trunk/test/pecoff/export.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/export.test?rev=223341&r1=223340&r2=223341&view=diff
>
> ==============================================================================
> --- lld/trunk/test/pecoff/export.test (original)
> +++ lld/trunk/test/pecoff/export.test Thu Dec 4 00:09:39 2014
> @@ -59,30 +59,31 @@ CHECK5-NEXT: 2 0x2010 exportfn
> CHECK6: Export Table:
> CHECK6: DLL name: export.test.tmp6.dll
> CHECK6: Ordinal RVA Name
> -CHECK6-NEXT: 1 0x2010 ?exportfn8@@YAXXZ
> +CHECK6-NEXT: 1 0x2010 exportfn3 at 256
> +CHECK6-NEXT: 2 0x2010 exportfn8
>
> -# RUN: lld -flavor link /out:%t6.dll /dll /entry:init \
> +# RUN: lld -flavor link /out:%t7.dll /dll /entry:init \
> # RUN: /export:exportfn7 /export:exportfn7 at 8 \
> # RUN: /export:exportfn8 /export:exportfn8 /export:exportfn3 -- %t.obj
> -# RUN: llvm-objdump -p %t6.dll | FileCheck -check-prefix=DUP %s
> +# RUN: llvm-objdump -p %t7.dll | FileCheck -check-prefix=DUP %s
>
> DUP: Export Table:
> -DUP: DLL name: export.test.tmp6.dll
> +DUP: DLL name: export.test.tmp7.dll
> DUP: Ordinal RVA Name
> -DUP-NEXT: 1 0x2010 ?exportfn8@@YAXXZ
> -DUP-NEXT: 2 0x2010 exportfn3 at 256
> -DUP-NEXT: 3 0x2010 exportfn7 at 8
> +DUP-NEXT: 1 0x2010 exportfn3
> +DUP-NEXT: 2 0x2010 exportfn7
> +DUP-NEXT: 3 0x2010 exportfn8
> DUP-NOT: ?exportfn8@@YAXXZ
> DUP-NOT: exportfn3 at 256
>
> # RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
> #
> -# RUN: lld -flavor link /out:%t1.dll /dll /entry:init \
> +# RUN: lld -flavor link /out:%t8.dll /dll /entry:init \
> # RUN: /export:f1=exportfn1 /export:f2 at 4=exportfn2,private -- %t.obj
> -# RUN: llvm-objdump -p %t1.dll | FileCheck -check-prefix=EQUAL %s
> +# RUN: llvm-objdump -p %t8.dll | FileCheck -check-prefix=EQUAL %s
>
> EQUAL: Export Table:
> -EQUAL: DLL name: export.test.tmp1.dll
> +EQUAL: DLL name: export.test.tmp8.dll
> EQUAL: Ordinal RVA Name
> EQUAL-NEXT: 1 0x2010 exportfn3 at 256
> EQUAL-NEXT: 2 0x2008 f1
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141203/4a068b0c/attachment.html>
More information about the llvm-commits
mailing list