Skip to content

Commit

Permalink
[Arm64EC] Copy import descriptors to the EC Map (llvm#84834)
Browse files Browse the repository at this point in the history
As noted in <llvm#78537>, MSVC
places import descriptors in both the EC and regular map - that PR moved
the descriptors to ONLY the regular map, however this causes linking
errors when linking as Arm64EC:

```
bcryptprimitives.lib(bcryptprimitives.dll) : error LNK2001: unresolved external symbol __IMPORT_DESCRIPTOR_bcryptprimitives (EC Symbol)
```

This change copies import descriptors from the regular map to the EC
map, which fixes this linking error.
  • Loading branch information
dpaoliello committed Mar 13, 2024
1 parent f69212a commit e74b197
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 6 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/Object/COFFImportFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
namespace llvm {
namespace object {

constexpr std::string_view ImportDescriptorPrefix = "__IMPORT_DESCRIPTOR_";
constexpr std::string_view NullImportDescriptorSymbolName =
"__NULL_IMPORT_DESCRIPTOR";
constexpr std::string_view NullThunkDataPrefix = "\x7f";
constexpr std::string_view NullThunkDataSuffix = "_NULL_THUNK_DATA";

class COFFImportFile : public SymbolicFile {
private:
enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol };
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Object/ArchiveWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,13 @@ static bool isECObject(object::SymbolicFile &Obj) {
return false;
}

bool isImportDescriptor(StringRef Name) {
return Name.starts_with(ImportDescriptorPrefix) ||
Name == StringRef{NullImportDescriptorSymbolName} ||
(Name.starts_with(NullThunkDataPrefix) &&
Name.ends_with(NullThunkDataSuffix));
}

static Expected<std::vector<unsigned>> getSymbols(SymbolicFile *Obj,
uint16_t Index,
raw_ostream &SymNames,
Expand Down Expand Up @@ -704,6 +711,10 @@ static Expected<std::vector<unsigned>> getSymbols(SymbolicFile *Obj,
if (Map == &SymMap->Map) {
Ret.push_back(SymNames.tell());
SymNames << Name << '\0';
// If EC is enabled, then the import descriptors are NOT put into EC
// objects so we need to copy them to the EC map manually.
if (SymMap->UseECMap && isImportDescriptor(Name))
SymMap->ECMap[Name] = Index;
}
} else {
Ret.push_back(SymNames.tell());
Expand Down
10 changes: 4 additions & 6 deletions llvm/lib/Object/COFFImportFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
}

static void writeStringTable(std::vector<uint8_t> &B,
ArrayRef<const std::string> Strings) {
ArrayRef<const std::string_view> Strings) {
// The COFF string table consists of a 4-byte value which is the size of the
// table, including the length field itself. This value is followed by the
// string content itself, which is an array of null-terminated C-style
Expand Down Expand Up @@ -171,9 +171,6 @@ static Expected<std::string> replace(StringRef S, StringRef From,
return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
}

static const std::string NullImportDescriptorSymbolName =
"__NULL_IMPORT_DESCRIPTOR";

namespace {
// This class constructs various small object files necessary to support linking
// symbols imported from a DLL. The contents are pretty strictly defined and
Expand All @@ -192,8 +189,9 @@ class ObjectFactory {
public:
ObjectFactory(StringRef S, MachineTypes M)
: NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)),
ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
ImportDescriptorSymbolName((ImportDescriptorPrefix + Library).str()),
NullThunkSymbolName(
(NullThunkDataPrefix + Library + NullThunkDataSuffix).str()) {}

// Creates an Import Descriptor. This is a small object file which contains a
// reference to the terminators and contains the library name (entry) for the
Expand Down
6 changes: 6 additions & 0 deletions llvm/test/tools/llvm-lib/arm64ec-implib.test
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ ARMAP-NEXT: #funcexp in test.dll
ARMAP-NEXT: #mangledfunc in test.dll
ARMAP-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll
ARMAP-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll
ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll
ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll
ARMAP-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll
ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll
ARMAP-NEXT: __imp_aux_expname in test.dll
Expand All @@ -28,6 +30,7 @@ ARMAP-NEXT: __imp_mangledfunc in test.dll
ARMAP-NEXT: expname in test.dll
ARMAP-NEXT: funcexp in test.dll
ARMAP-NEXT: mangledfunc in test.dll
ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll

RUN: llvm-readobj test.lib | FileCheck -check-prefix=READOBJ %s

Expand Down Expand Up @@ -107,6 +110,8 @@ EXPAS-ARMAP-NEXT: #func1 in test.dll
EXPAS-ARMAP-NEXT: #func2 in test.dll
EXPAS-ARMAP-NEXT: #func3 in test.dll
EXPAS-ARMAP-NEXT: #func4 in test.dll
EXPAS-ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll
EXPAS-ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func1 in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func2 in test.dll
EXPAS-ARMAP-NEXT: __imp_aux_func3 in test.dll
Expand All @@ -121,6 +126,7 @@ EXPAS-ARMAP-NEXT: func1 in test.dll
EXPAS-ARMAP-NEXT: func2 in test.dll
EXPAS-ARMAP-NEXT: func3 in test.dll
EXPAS-ARMAP-NEXT: func4 in test.dll
EXPAS-ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll

EXPAS-READOBJ: File: test.dll
EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC
Expand Down

0 comments on commit e74b197

Please sign in to comment.