-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LLD][MinGW] Add support for wrapped symbols on ARM64X #126296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Apply -wrap arguments to both symbol tables.
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-coff Author: Jacek Caban (cjacek) ChangesApply Full diff: https://github.com/llvm/llvm-project/pull/126296.diff 5 Files Affected:
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 281510b7ac6ea6..4e31ebf315b04c 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2573,11 +2573,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
ctx.symtab.addUndefinedGlob(pat);
// Create wrapped symbols for -wrap option.
- std::vector<WrappedSymbol> wrapped = addWrappedSymbols(ctx, args);
- // Load more object files that might be needed for wrapped symbols.
- if (!wrapped.empty())
- while (run())
- ;
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ addWrappedSymbols(symtab, args);
+ // Load more object files that might be needed for wrapped symbols.
+ if (!symtab.wrapped.empty())
+ while (run())
+ ;
+ });
if (config->autoImport || config->stdcallFixup) {
// MinGW specific.
@@ -2647,8 +2649,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
run();
// Apply symbol renames for -wrap.
- if (!wrapped.empty())
- wrapSymbols(ctx, wrapped);
+ ctx.forEachSymtab([](SymbolTable &symtab) {
+ if (!symtab.wrapped.empty())
+ wrapSymbols(symtab);
+ });
if (isArm64EC(config->machine))
createECExportThunks();
diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 0786353b06432a..818522b916d10e 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -207,8 +207,8 @@ static StringRef mangle(Twine sym, MachineTypes machine) {
// This function instantiates wrapper symbols. At this point, they seem
// like they are not being used at all, so we explicitly set some flags so
// that LTO won't eliminate them.
-std::vector<WrappedSymbol>
-lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
+void lld::coff::addWrappedSymbols(SymbolTable &symtab,
+ opt::InputArgList &args) {
std::vector<WrappedSymbol> v;
DenseSet<StringRef> seen;
@@ -217,14 +217,14 @@ lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
if (!seen.insert(name).second)
continue;
- Symbol *sym = ctx.symtab.findUnderscore(name);
+ Symbol *sym = symtab.findUnderscore(name);
if (!sym)
continue;
Symbol *real =
- ctx.symtab.addUndefined(mangle("__real_" + name, ctx.config.machine));
+ symtab.addUndefined(mangle("__real_" + name, symtab.machine));
Symbol *wrap =
- ctx.symtab.addUndefined(mangle("__wrap_" + name, ctx.config.machine));
+ symtab.addUndefined(mangle("__wrap_" + name, symtab.machine));
v.push_back({sym, real, wrap});
// These symbols may seem undefined initially, but don't bail out
@@ -243,7 +243,7 @@ lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
if (!isa<Undefined>(wrap))
wrap->isUsedInRegularObj = true;
}
- return v;
+ symtab.wrapped = std::move(v);
}
// Do renaming for -wrap by updating pointers to symbols.
@@ -251,29 +251,28 @@ lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
// When this function is executed, only InputFiles and symbol table
// contain pointers to symbol objects. We visit them to replace pointers,
// so that wrapped symbols are swapped as instructed by the command line.
-void lld::coff::wrapSymbols(COFFLinkerContext &ctx,
- ArrayRef<WrappedSymbol> wrapped) {
+void lld::coff::wrapSymbols(SymbolTable &symtab) {
DenseMap<Symbol *, Symbol *> map;
- for (const WrappedSymbol &w : wrapped) {
+ for (const WrappedSymbol &w : symtab.wrapped) {
map[w.sym] = w.wrap;
map[w.real] = w.sym;
if (Defined *d = dyn_cast<Defined>(w.wrap)) {
- Symbol *imp = ctx.symtab.find(("__imp_" + w.sym->getName()).str());
+ Symbol *imp = symtab.find(("__imp_" + w.sym->getName()).str());
// Create a new defined local import for the wrap symbol. If
// no imp prefixed symbol existed, there's no need for it.
// (We can't easily distinguish whether any object file actually
// referenced it or not, though.)
if (imp) {
DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
- ctx, saver().save("__imp_" + w.wrap->getName()), d);
- ctx.symtab.localImportChunks.push_back(wrapimp->getChunk());
+ symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
+ symtab.localImportChunks.push_back(wrapimp->getChunk());
map[imp] = wrapimp;
}
}
}
// Update pointers in input files.
- parallelForEach(ctx.objFileInstances, [&](ObjFile *file) {
+ parallelForEach(symtab.ctx.objFileInstances, [&](ObjFile *file) {
MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
for (auto &sym : syms)
if (Symbol *s = map.lookup(sym))
diff --git a/lld/COFF/MinGW.h b/lld/COFF/MinGW.h
index 265beb315c9a71..48bce74c616bc4 100644
--- a/lld/COFF/MinGW.h
+++ b/lld/COFF/MinGW.h
@@ -55,17 +55,9 @@ void writeDefFile(COFFLinkerContext &, StringRef name,
// symbol becomes accessible as `__real_foo`, so you can call that from your
// wrapper.
//
-// This data structure is instantiated for each -wrap option.
-struct WrappedSymbol {
- Symbol *sym;
- Symbol *real;
- Symbol *wrap;
-};
-
-std::vector<WrappedSymbol> addWrappedSymbols(COFFLinkerContext &ctx,
- llvm::opt::InputArgList &args);
+void addWrappedSymbols(SymbolTable &symtab, llvm::opt::InputArgList &args);
-void wrapSymbols(COFFLinkerContext &ctx, ArrayRef<WrappedSymbol> wrapped);
+void wrapSymbols(SymbolTable &symtab);
} // namespace lld::coff
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index ff6e8487f07344..b124998809e3ce 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -34,6 +34,13 @@ class LazyArchive;
class SectionChunk;
class Symbol;
+// This data structure is instantiated for each -wrap option.
+struct WrappedSymbol {
+ Symbol *sym;
+ Symbol *real;
+ Symbol *wrap;
+};
+
// SymbolTable is a bucket of all known symbols, including defined,
// undefined, or lazy symbols (the last one is symbols in archive
// files whose archive members are not yet loaded).
@@ -161,6 +168,9 @@ class SymbolTable {
Symbol *delayLoadHelper = nullptr;
Chunk *tailMergeUnwindInfoChunk = nullptr;
+ // A list of wrapped symbols.
+ std::vector<WrappedSymbol> wrapped;
+
void fixupExports();
void assignExportOrdinals();
void parseModuleDefs(StringRef path);
diff --git a/lld/test/COFF/arm64x-wrap.s b/lld/test/COFF/arm64x-wrap.s
new file mode 100644
index 00000000000000..4f600e38f7a830
--- /dev/null
+++ b/lld/test/COFF/arm64x-wrap.s
@@ -0,0 +1,31 @@
+// REQUIRES: aarch64
+// RUN: split-file %s %t.dir && cd %t.dir
+
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows test.s -o test-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows other.s -o other-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows other.s -o other-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
+
+// RUN: lld-link -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj other-arm64.obj other-arm64ec.obj \
+// RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -out:out.dll -wrap:sym -wrap:nosuchsym
+
+// RUN: llvm-readobj --hex-dump=.test out.dll | FileCheck %s
+// CHECK: 0x180004000 02000000 02000000 01000000 02000000
+// CHECK: 0x180004010 02000000 01000000
+
+#--- test.s
+ .section .test,"dr"
+ .word sym
+ .word __wrap_sym
+ .word __real_sym
+
+#--- other.s
+ .global sym
+ .global __wrap_sym
+ .global __real_sym
+
+sym = 1
+__wrap_sym = 2
+__real_sym = 3
|
@llvm/pr-subscribers-platform-windows Author: Jacek Caban (cjacek) ChangesApply Full diff: https://github.com/llvm/llvm-project/pull/126296.diff 5 Files Affected:
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 281510b7ac6ea6..4e31ebf315b04c 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2573,11 +2573,13 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
ctx.symtab.addUndefinedGlob(pat);
// Create wrapped symbols for -wrap option.
- std::vector<WrappedSymbol> wrapped = addWrappedSymbols(ctx, args);
- // Load more object files that might be needed for wrapped symbols.
- if (!wrapped.empty())
- while (run())
- ;
+ ctx.forEachSymtab([&](SymbolTable &symtab) {
+ addWrappedSymbols(symtab, args);
+ // Load more object files that might be needed for wrapped symbols.
+ if (!symtab.wrapped.empty())
+ while (run())
+ ;
+ });
if (config->autoImport || config->stdcallFixup) {
// MinGW specific.
@@ -2647,8 +2649,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
run();
// Apply symbol renames for -wrap.
- if (!wrapped.empty())
- wrapSymbols(ctx, wrapped);
+ ctx.forEachSymtab([](SymbolTable &symtab) {
+ if (!symtab.wrapped.empty())
+ wrapSymbols(symtab);
+ });
if (isArm64EC(config->machine))
createECExportThunks();
diff --git a/lld/COFF/MinGW.cpp b/lld/COFF/MinGW.cpp
index 0786353b06432a..818522b916d10e 100644
--- a/lld/COFF/MinGW.cpp
+++ b/lld/COFF/MinGW.cpp
@@ -207,8 +207,8 @@ static StringRef mangle(Twine sym, MachineTypes machine) {
// This function instantiates wrapper symbols. At this point, they seem
// like they are not being used at all, so we explicitly set some flags so
// that LTO won't eliminate them.
-std::vector<WrappedSymbol>
-lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
+void lld::coff::addWrappedSymbols(SymbolTable &symtab,
+ opt::InputArgList &args) {
std::vector<WrappedSymbol> v;
DenseSet<StringRef> seen;
@@ -217,14 +217,14 @@ lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
if (!seen.insert(name).second)
continue;
- Symbol *sym = ctx.symtab.findUnderscore(name);
+ Symbol *sym = symtab.findUnderscore(name);
if (!sym)
continue;
Symbol *real =
- ctx.symtab.addUndefined(mangle("__real_" + name, ctx.config.machine));
+ symtab.addUndefined(mangle("__real_" + name, symtab.machine));
Symbol *wrap =
- ctx.symtab.addUndefined(mangle("__wrap_" + name, ctx.config.machine));
+ symtab.addUndefined(mangle("__wrap_" + name, symtab.machine));
v.push_back({sym, real, wrap});
// These symbols may seem undefined initially, but don't bail out
@@ -243,7 +243,7 @@ lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
if (!isa<Undefined>(wrap))
wrap->isUsedInRegularObj = true;
}
- return v;
+ symtab.wrapped = std::move(v);
}
// Do renaming for -wrap by updating pointers to symbols.
@@ -251,29 +251,28 @@ lld::coff::addWrappedSymbols(COFFLinkerContext &ctx, opt::InputArgList &args) {
// When this function is executed, only InputFiles and symbol table
// contain pointers to symbol objects. We visit them to replace pointers,
// so that wrapped symbols are swapped as instructed by the command line.
-void lld::coff::wrapSymbols(COFFLinkerContext &ctx,
- ArrayRef<WrappedSymbol> wrapped) {
+void lld::coff::wrapSymbols(SymbolTable &symtab) {
DenseMap<Symbol *, Symbol *> map;
- for (const WrappedSymbol &w : wrapped) {
+ for (const WrappedSymbol &w : symtab.wrapped) {
map[w.sym] = w.wrap;
map[w.real] = w.sym;
if (Defined *d = dyn_cast<Defined>(w.wrap)) {
- Symbol *imp = ctx.symtab.find(("__imp_" + w.sym->getName()).str());
+ Symbol *imp = symtab.find(("__imp_" + w.sym->getName()).str());
// Create a new defined local import for the wrap symbol. If
// no imp prefixed symbol existed, there's no need for it.
// (We can't easily distinguish whether any object file actually
// referenced it or not, though.)
if (imp) {
DefinedLocalImport *wrapimp = make<DefinedLocalImport>(
- ctx, saver().save("__imp_" + w.wrap->getName()), d);
- ctx.symtab.localImportChunks.push_back(wrapimp->getChunk());
+ symtab.ctx, saver().save("__imp_" + w.wrap->getName()), d);
+ symtab.localImportChunks.push_back(wrapimp->getChunk());
map[imp] = wrapimp;
}
}
}
// Update pointers in input files.
- parallelForEach(ctx.objFileInstances, [&](ObjFile *file) {
+ parallelForEach(symtab.ctx.objFileInstances, [&](ObjFile *file) {
MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
for (auto &sym : syms)
if (Symbol *s = map.lookup(sym))
diff --git a/lld/COFF/MinGW.h b/lld/COFF/MinGW.h
index 265beb315c9a71..48bce74c616bc4 100644
--- a/lld/COFF/MinGW.h
+++ b/lld/COFF/MinGW.h
@@ -55,17 +55,9 @@ void writeDefFile(COFFLinkerContext &, StringRef name,
// symbol becomes accessible as `__real_foo`, so you can call that from your
// wrapper.
//
-// This data structure is instantiated for each -wrap option.
-struct WrappedSymbol {
- Symbol *sym;
- Symbol *real;
- Symbol *wrap;
-};
-
-std::vector<WrappedSymbol> addWrappedSymbols(COFFLinkerContext &ctx,
- llvm::opt::InputArgList &args);
+void addWrappedSymbols(SymbolTable &symtab, llvm::opt::InputArgList &args);
-void wrapSymbols(COFFLinkerContext &ctx, ArrayRef<WrappedSymbol> wrapped);
+void wrapSymbols(SymbolTable &symtab);
} // namespace lld::coff
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index ff6e8487f07344..b124998809e3ce 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -34,6 +34,13 @@ class LazyArchive;
class SectionChunk;
class Symbol;
+// This data structure is instantiated for each -wrap option.
+struct WrappedSymbol {
+ Symbol *sym;
+ Symbol *real;
+ Symbol *wrap;
+};
+
// SymbolTable is a bucket of all known symbols, including defined,
// undefined, or lazy symbols (the last one is symbols in archive
// files whose archive members are not yet loaded).
@@ -161,6 +168,9 @@ class SymbolTable {
Symbol *delayLoadHelper = nullptr;
Chunk *tailMergeUnwindInfoChunk = nullptr;
+ // A list of wrapped symbols.
+ std::vector<WrappedSymbol> wrapped;
+
void fixupExports();
void assignExportOrdinals();
void parseModuleDefs(StringRef path);
diff --git a/lld/test/COFF/arm64x-wrap.s b/lld/test/COFF/arm64x-wrap.s
new file mode 100644
index 00000000000000..4f600e38f7a830
--- /dev/null
+++ b/lld/test/COFF/arm64x-wrap.s
@@ -0,0 +1,31 @@
+// REQUIRES: aarch64
+// RUN: split-file %s %t.dir && cd %t.dir
+
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows test.s -o test-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows test.s -o test-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows other.s -o other-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows other.s -o other-arm64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
+
+// RUN: lld-link -machine:arm64x -dll -noentry test-arm64.obj test-arm64ec.obj other-arm64.obj other-arm64ec.obj \
+// RUN: loadconfig-arm64.obj loadconfig-arm64ec.obj -out:out.dll -wrap:sym -wrap:nosuchsym
+
+// RUN: llvm-readobj --hex-dump=.test out.dll | FileCheck %s
+// CHECK: 0x180004000 02000000 02000000 01000000 02000000
+// CHECK: 0x180004010 02000000 01000000
+
+#--- test.s
+ .section .test,"dr"
+ .word sym
+ .word __wrap_sym
+ .word __real_sym
+
+#--- other.s
+ .global sym
+ .global __wrap_sym
+ .global __real_sym
+
+sym = 1
+__wrap_sym = 2
+__real_sym = 3
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This is a rather uncommon feature though; did you run into this in actual use somewhere, or did you just notice it while looking at the code, including bits that you see in the code that only is handled for one namespace right now?
I just noticed it in the code, no actual use. I generally went through the entire code looking for things to change. My thinking was that skipping such cases would make things less consistent, but I don't mind skipping them if you prefer a more pragmatic approach. I don't have any more such cases in my queue, remaining changes that are more practical. |
No, I think it's probably fine to do; I agree that it's good to go through the code to catch cases like this, to make them consistent. I'm trying to feel how one would be using wrap on arm64x and what the logical behaviour would be. Practically, doing it for both sides feels most logical. I think it's possible that one could want to do it for only one side though, but it'd be messy to express this (so if one wants to do that, it's possible that one would need to supply suitable dummy symbols for the other side). So I think it's fine to merge this! |
Merged, thanks! |
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply `-wrap` arguments to both symbol tables.
Apply
-wrap
arguments to both symbol tables.