[lld] [LLD][COFF] Process all ARM64EC import symbols in getSymbols (PR #109118)

Jacek Caban via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 18 02:50:05 PDT 2024


https://github.com/cjacek created https://github.com/llvm/llvm-project/pull/109118

None

>From 4beffdd8de68f764a0d86bac2be6bb7db5ae196a Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 17 Sep 2024 23:45:44 +0200
Subject: [PATCH 1/3] [LLD][COFF] Store __imp_ symbols as Defined in InputFile

---
 lld/COFF/InputFiles.h    | 4 ++--
 lld/COFF/MapFile.cpp     | 3 +--
 lld/COFF/SymbolTable.cpp | 6 +++---
 lld/COFF/SymbolTable.h   | 4 ++--
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index 5fa93f57ef9e3a..a20b097cbe04af 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -349,7 +349,7 @@ class ImportFile : public InputFile {
   MachineTypes getMachineType() const override;
 
   DefinedImportData *impSym = nullptr;
-  Symbol *thunkSym = nullptr;
+  Defined *thunkSym = nullptr;
   ImportThunkChunkARM64EC *impchkThunk = nullptr;
   std::string dllName;
 
@@ -365,7 +365,7 @@ class ImportFile : public InputFile {
   // Auxiliary IAT symbols and chunks on ARM64EC.
   DefinedImportData *impECSym = nullptr;
   Chunk *auxLocation = nullptr;
-  Symbol *auxThunkSym = nullptr;
+  Defined *auxThunkSym = nullptr;
   DefinedImportData *auxImpCopySym = nullptr;
   Chunk *auxCopyLocation = nullptr;
 
diff --git a/lld/COFF/MapFile.cpp b/lld/COFF/MapFile.cpp
index 52e9ce996f2390..69842ced284cbd 100644
--- a/lld/COFF/MapFile.cpp
+++ b/lld/COFF/MapFile.cpp
@@ -128,8 +128,7 @@ static void getSymbols(const COFFLinkerContext &ctx,
     if (!file->thunkSym->isLive())
       continue;
 
-    if (auto *thunkSym = dyn_cast<Defined>(file->thunkSym))
-      syms.push_back(thunkSym);
+    syms.push_back(thunkSym);
 
     if (auto *impSym = dyn_cast_or_null<Defined>(file->impSym))
       syms.push_back(impSym);
diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp
index efea16ccbbfea0..fc169ec211a9fe 100644
--- a/lld/COFF/SymbolTable.cpp
+++ b/lld/COFF/SymbolTable.cpp
@@ -815,13 +815,13 @@ DefinedImportData *SymbolTable::addImportData(StringRef n, ImportFile *f,
   return nullptr;
 }
 
-Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id,
-                                    ImportThunkChunk *chunk) {
+Defined *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id,
+                                     ImportThunkChunk *chunk) {
   auto [s, wasInserted] = insert(name, nullptr);
   s->isUsedInRegularObj = true;
   if (wasInserted || isa<Undefined>(s) || s->isLazy()) {
     replaceSymbol<DefinedImportThunk>(s, ctx, name, id, chunk);
-    return s;
+    return cast<Defined>(s);
   }
 
   reportDuplicate(s, id->file);
diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h
index bf97cf442039e0..e3f674b8098f8b 100644
--- a/lld/COFF/SymbolTable.h
+++ b/lld/COFF/SymbolTable.h
@@ -105,8 +105,8 @@ class SymbolTable {
                     CommonChunk *c = nullptr);
   DefinedImportData *addImportData(StringRef n, ImportFile *f,
                                    Chunk *&location);
-  Symbol *addImportThunk(StringRef name, DefinedImportData *s,
-                         ImportThunkChunk *chunk);
+  Defined *addImportThunk(StringRef name, DefinedImportData *s,
+                          ImportThunkChunk *chunk);
   void addLibcall(StringRef name);
   void addEntryThunk(Symbol *from, Symbol *to);
   void addExitThunk(Symbol *from, Symbol *to);

>From 22125606aac91300557769db2a8ce0ca6c24af80 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Wed, 18 Sep 2024 00:00:34 +0200
Subject: [PATCH 2/3] [LLD][COFF] Process all live import symbols in
 getSymbols()

The current logic assumes that the import file is pulled by object files,
and the loop for import files only needs to handle cases where the __imp_
symbol is implicitly pulled by an import thunk. This is fragile, as the
symbol may also be pulled through other means, such as the -export argument
in tests. Additionally, this logic is insufficient for ARM64EC, which
exposes multiple symbols through an import file, and referencing any one
of them causes all of them to be defined.

With this change, import symbols are added to syms more often, but we
ensure that output symbols remain unique later in the process.
---
 lld/COFF/MapFile.cpp          | 13 +++----------
 lld/test/COFF/export-imp.test | 11 +++++++++++
 2 files changed, 14 insertions(+), 10 deletions(-)
 create mode 100644 lld/test/COFF/export-imp.test

diff --git a/lld/COFF/MapFile.cpp b/lld/COFF/MapFile.cpp
index 69842ced284cbd..b9ef32da113c4f 100644
--- a/lld/COFF/MapFile.cpp
+++ b/lld/COFF/MapFile.cpp
@@ -122,16 +122,9 @@ static void getSymbols(const COFFLinkerContext &ctx,
     if (!file->live)
       continue;
 
-    if (!file->thunkSym)
-      continue;
-
-    if (!file->thunkSym->isLive())
-      continue;
-
-    syms.push_back(thunkSym);
-
-    if (auto *impSym = dyn_cast_or_null<Defined>(file->impSym))
-      syms.push_back(impSym);
+    syms.push_back(file->impSym);
+    if (file->thunkSym && file->thunkSym->isLive())
+      syms.push_back(file->thunkSym);
   }
 
   sortUniqueSymbols(syms, ctx.config.imageBase);
diff --git a/lld/test/COFF/export-imp.test b/lld/test/COFF/export-imp.test
new file mode 100644
index 00000000000000..db71ef74641639
--- /dev/null
+++ b/lld/test/COFF/export-imp.test
@@ -0,0 +1,11 @@
+; REQUIRES: x86
+
+; RUN: llvm-lib -machine:amd64 -out:%t.imp.lib -def:%s
+; RUN: lld-link -machine:amd64 -out:%t.dll %t.imp.lib -dll -noentry -export:__imp_func,DATA -map
+
+; FileCheck %s < %t.imp.map
+; CHECK: 0001:00000098       __imp_func                 0000000180001098     export-imp-thunk.test.tmp.imp:imp.dll
+
+LIBRARY imp.dll
+EXPORTS
+        func

>From e4819ca92e71b98bc0e5b21e038f8138255fc7c3 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Tue, 17 Sep 2024 23:25:45 +0200
Subject: [PATCH 3/3] [LLD][COFF] Process all ARM64EC import symbols in
 getSymbols

---
 lld/COFF/Chunks.h                 |  3 ++-
 lld/COFF/InputFiles.cpp           |  3 ++-
 lld/COFF/MapFile.cpp              |  8 ++++++++
 lld/test/COFF/arm64ec-import.test | 28 +++++++++++++++++++++++++---
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index 24d7c37de7f3b0..0a35046fc5143e 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -624,7 +624,8 @@ class ImportThunkChunkARM64EC : public ImportThunkChunk {
   MachineTypes getMachine() const override { return ARM64EC; }
   void writeTo(uint8_t *buf) const override;
 
-  Defined *exitThunk;
+  Defined *exitThunk = nullptr;
+  Defined *sym = nullptr;
 
 private:
   ImportFile *file;
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index d9184b04735e83..b19275abebc3ac 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -1126,7 +1126,8 @@ void ImportFile::parse() {
 
       StringRef impChkName = saver().save("__impchk_" + name);
       impchkThunk = make<ImportThunkChunkARM64EC>(this);
-      ctx.symtab.addImportThunk(impChkName, impSym, impchkThunk);
+      impchkThunk->sym =
+          ctx.symtab.addImportThunk(impChkName, impSym, impchkThunk);
       ctx.driver.pullArm64ECIcallHelper();
     }
   }
diff --git a/lld/COFF/MapFile.cpp b/lld/COFF/MapFile.cpp
index b9ef32da113c4f..8f7c228f5d3b1c 100644
--- a/lld/COFF/MapFile.cpp
+++ b/lld/COFF/MapFile.cpp
@@ -125,6 +125,14 @@ static void getSymbols(const COFFLinkerContext &ctx,
     syms.push_back(file->impSym);
     if (file->thunkSym && file->thunkSym->isLive())
       syms.push_back(file->thunkSym);
+    if (file->auxThunkSym && file->auxThunkSym->isLive())
+      syms.push_back(file->auxThunkSym);
+    if (file->impchkThunk)
+      syms.push_back(file->impchkThunk->sym);
+    if (file->impECSym)
+      syms.push_back(file->impECSym);
+    if (file->auxImpCopySym)
+      syms.push_back(file->auxImpCopySym);
   }
 
   sortUniqueSymbols(syms, ctx.config.imageBase);
diff --git a/lld/test/COFF/arm64ec-import.test b/lld/test/COFF/arm64ec-import.test
index 92d7f5517bd426..08ff31ce1a8f3b 100644
--- a/lld/test/COFF/arm64ec-import.test
+++ b/lld/test/COFF/arm64ec-import.test
@@ -12,15 +12,15 @@ RUN: llvm-lib -machine:x64 -def:test.def -out:test-x86_64.lib
 
 Link using ARM64EC import library:
 RUN: lld-link -machine:arm64ec -dll -noentry -out:out.dll loadconfig-arm64ec.obj icall.obj hybmp.obj \
-RUN:          test.obj test-arm64ec.lib test2-arm64ec.lib
+RUN:          test.obj test-arm64ec.lib test2-arm64ec.lib -map
 
 Link using x86_64 import library:
 RUN: lld-link -machine:arm64ec -dll -noentry -out:out2.dll loadconfig-arm64ec.obj icall.obj hybmp.obj \
-RUN:          test.obj test-x86_64.lib test2-arm64ec.lib
+RUN:          test.obj test-x86_64.lib test2-arm64ec.lib -map
 
 Link using x86_64 object file:
 RUN: lld-link -machine:arm64ec -dll -noentry -out:out3.dll loadconfig-arm64ec.obj icall.obj hybmp.obj \
-RUN:          test-x86_64.obj test-arm64ec.lib test2-arm64ec.lib
+RUN:          test-x86_64.obj test-arm64ec.lib test2-arm64ec.lib -map
 
 RUN: llvm-readobj --coff-imports out.dll | FileCheck --check-prefix=IMPORTS %s
 RUN: llvm-readobj --coff-imports out2.dll | FileCheck --check-prefix=IMPORTS %s
@@ -87,6 +87,28 @@ TESTSEC-X64-NEXT: 0x180007010 08300000 00500000 10300000 20300000
 TESTSEC-X64-NEXT: 0x180007020 14100000 28100000 00200000 08100000
 TESTSEC-X64-NEXT: 0x180007030 3c100000 a0420000
 
+RUN: FileCheck --check-prefix=MAP %s < out.map
+RUN: FileCheck --check-prefix=MAP %s < out2.map
+RUN: FileCheck --check-prefix=MAP %s < out3.map
+MAP:      0001:00000008       #func                      0000000180001008     test{{.*}}:test.dll
+MAP-NEXT: 0001:00000014       __impchk_func              0000000180001014     test{{.*}}:test.dll
+MAP-NEXT: 0001:00000028       __impchk_func2             0000000180001028     test{{.*}}:test.dll
+MAP-NEXT: 0001:0000003c       #t2func                    000000018000103c     test2{{.*}}:test2.dll
+MAP-NEXT: 0001:00000048       __impchk_t2func            0000000180001048     test2{{.*}}:test2.dll
+MAP:      0001:00001000       func                       0000000180002000     test{{.*}}:test.dll
+MAP-NEXT: 0002:00000000       __imp_data                 0000000180003000     test{{.*}}:test.dll
+MAP-NEXT: 0002:00000008       __imp_aux_func             0000000180003008     test{{.*}}:test.dll
+MAP-NEXT: 0002:00000010       __imp_aux_func2            0000000180003010     test{{.*}}:test.dll
+MAP-NEXT: 0002:00000020       __imp_aux_t2func           0000000180003020     test2{{.*}}:test2.dll
+MAP:      0002:00001298       __auximpcopy_data          0000000180004298     test{{.*}}:test.dll
+MAP-NEXT: 0002:000012a0       __auximpcopy_func          00000001800042a0     test{{.*}}:test.dll
+MAP-NEXT: 0002:000012a8       __auximpcopy_func2         00000001800042a8     test{{.*}}:test.dll
+MAP-NEXT: 0002:000012b8       __auximpcopy_t2func        00000001800042b8     test2{{.*}}:test2.dll
+MAP:      0002:00002000       __imp_aux_data             0000000180005000     test{{.*}}:test.dll
+MAP-NEXT: 0002:00002008       __imp_func                 0000000180005008     test{{.*}}:test.dll
+MAP-NEXT: 0002:00002010       __imp_func2                0000000180005010     test{{.*}}:test.dll
+MAP-NEXT: 0002:00002020       __imp_t2func               0000000180005020     test2{{.*}}:test2.dll
+
 RUN: llvm-readobj --headers out.dll | FileCheck -check-prefix=HEADERS %s
 RUN: llvm-readobj --headers out2.dll | FileCheck -check-prefix=HEADERS %s
 RUN: llvm-readobj --headers out3.dll | FileCheck -check-prefix=HEADERS %s



More information about the llvm-commits mailing list