[lld] r257243 - COFF: Implement DLL symbol forwarding.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 8 17:22:00 PST 2016
Author: ruiu
Date: Fri Jan 8 19:22:00 2016
New Revision: 257243
URL: http://llvm.org/viewvc/llvm-project?rev=257243&view=rev
Log:
COFF: Implement DLL symbol forwarding.
DLL export tables usually contain dllexport'ed symbol RVAs so that
applications which use the DLLs can find symbols from the DLLs.
However, there's a minor feature to "forward" DLL symbols to other
DLLs.
If you set an RVA to a string whose form is "<dllname>.<symbolname>"
(e.g. "KERNEL32.ExitProcess") instead of symbol RVA to the export
table, the loader interprets that as a forwarder symbol, and resolve
that symbol from the specified DLL.
This patch implements that feature.
Modified:
lld/trunk/COFF/Config.h
lld/trunk/COFF/DLL.cpp
lld/trunk/COFF/Driver.cpp
lld/trunk/COFF/DriverUtils.cpp
lld/trunk/test/COFF/export.test
Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=257243&r1=257242&r2=257243&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Fri Jan 8 19:22:00 2016
@@ -25,6 +25,7 @@ using llvm::COFF::WindowsSubsystem;
using llvm::StringRef;
class DefinedAbsolute;
class DefinedRelative;
+class StringChunk;
class Undefined;
// Short aliases.
@@ -42,6 +43,12 @@ struct Export {
bool Data = false;
bool Private = false;
+ // If an export is a form of /export:foo=dllname.bar, that means
+ // that foo should be exported as an alias to bar in the DLL.
+ // ForwardTo is set to "dllname.bar" part. Usually empty.
+ StringRef ForwardTo;
+ StringChunk *ForwardChunk = nullptr;
+
// True if this /export option was in .drectves section.
bool Directives = false;
StringRef SymbolName;
Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=257243&r1=257242&r2=257243&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Fri Jan 8 19:22:00 2016
@@ -320,8 +320,12 @@ public:
void writeTo(uint8_t *Buf) const override {
for (Export &E : Config->Exports) {
- auto *D = cast<Defined>(E.Sym->repl());
- write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
+ uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
+ if (E.ForwardChunk) {
+ write32le(P, E.ForwardChunk->getRVA());
+ } else {
+ write32le(P, cast<Defined>(E.Sym->repl())->getRVA());
+ }
}
}
@@ -539,6 +543,15 @@ EdataContents::EdataContents() {
for (Export &E : Config->Exports)
if (!E.Noname)
Names.push_back(new StringChunk(E.ExportName));
+
+ std::vector<Chunk *> Forwards;
+ for (Export &E : Config->Exports) {
+ if (E.ForwardTo.empty())
+ continue;
+ E.ForwardChunk = new StringChunk(E.ForwardTo);
+ Forwards.push_back(E.ForwardChunk);
+ }
+
auto *NameTab = new NamePointersChunk(Names);
auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
@@ -550,6 +563,8 @@ EdataContents::EdataContents() {
Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
for (Chunk *C : Names)
Chunks.push_back(std::unique_ptr<Chunk>(C));
+ for (Chunk *C : Forwards)
+ Chunks.push_back(std::unique_ptr<Chunk>(C));
}
} // namespace coff
Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=257243&r1=257242&r2=257243&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Fri Jan 8 19:22:00 2016
@@ -586,6 +586,8 @@ void LinkerDriver::link(llvm::ArrayRef<c
// Windows specific -- Make sure we resolve all dllexported symbols.
for (Export &E : Config->Exports) {
+ if (!E.ForwardTo.empty())
+ continue;
E.Sym = addUndefined(E.Name);
if (!E.Directives)
Symtab.mangleMaybe(E.Sym);
Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=257243&r1=257242&r2=257243&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Fri Jan 8 19:22:00 2016
@@ -321,7 +321,8 @@ void createSideBySideManifest() {
}
// Parse a string in the form of
-// "<name>[=<internalname>][, at ordinal[,NONAME]][,DATA][,PRIVATE]".
+// "<name>[=<internalname>][, at ordinal[,NONAME]][,DATA][,PRIVATE]"
+// or "<name>=<dllname>.<name>".
// Used for parsing /export arguments.
Export parseExport(StringRef Arg) {
Export E;
@@ -329,12 +330,25 @@ Export parseExport(StringRef Arg) {
std::tie(E.Name, Rest) = Arg.split(",");
if (E.Name.empty())
goto err;
+
if (E.Name.find('=') != StringRef::npos) {
- std::tie(E.ExtName, E.Name) = E.Name.split("=");
+ StringRef X, Y;
+ std::tie(X, Y) = E.Name.split("=");
+
+ // If "<name>=<dllname>.<name>".
+ if (Y.find(".") != StringRef::npos) {
+ E.Name = X;
+ E.ForwardTo = Y;
+ return E;
+ }
+
+ E.ExtName = X;
+ E.Name = Y;
if (E.Name.empty())
goto err;
}
+ // If "<name>=<internalname>[, at ordinal[,NONAME]][,DATA][,PRIVATE]"
while (!Rest.empty()) {
StringRef Tok;
std::tie(Tok, Rest) = Rest.split(",");
@@ -388,15 +402,22 @@ void fixupExports() {
}
for (Export &E : Config->Exports) {
- if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
+ if (!E.ForwardTo.empty()) {
+ E.SymbolName = E.Name;
+ } else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
E.SymbolName = U->getName();
} else {
E.SymbolName = E.Sym->getName();
}
}
- for (Export &E : Config->Exports)
- E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+ for (Export &E : Config->Exports) {
+ if (!E.ForwardTo.empty()) {
+ E.ExportName = undecorate(E.Name);
+ } else {
+ E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+ }
+ }
// Uniquefy by name.
std::map<StringRef, Export *> Map;
Modified: lld/trunk/test/COFF/export.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/export.test?rev=257243&r1=257242&r2=257243&view=diff
==============================================================================
--- lld/trunk/test/COFF/export.test (original)
+++ lld/trunk/test/COFF/export.test Fri Jan 8 19:22:00 2016
@@ -80,3 +80,14 @@ SYMTAB: __imp_exportfn2 in export.test.t
SYMTAB: exportfn2 in export.test.tmp.DLL
SYMTAB: __imp_exportfn3 in export.test.tmp.DLL
SYMTAB: exportfn3 in export.test.tmp.DLL
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:foo=kernel32.foobar
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=FORWARDER %s
+
+FORWARDER: Export Table:
+FORWARDER: DLL name: export.test.tmp.dll
+FORWARDER: Ordinal base: 0
+FORWARDER: Ordinal RVA Name
+FORWARDER: 0 0
+FORWARDER: 1 0x1010 exportfn
+FORWARDER: 2 0x2062 foo
More information about the llvm-commits
mailing list