Skip to content

[llvm-lib][Object][COFF] Use ARM64 machine type for import library descriptor objects. #78537

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

Merged
merged 1 commit into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 35 additions & 26 deletions llvm/lib/Object/COFFImportFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ namespace {
class ObjectFactory {
using u16 = support::ulittle16_t;
using u32 = support::ulittle32_t;
MachineTypes Machine;
MachineTypes NativeMachine;
BumpPtrAllocator Alloc;
StringRef ImportName;
StringRef Library;
Expand All @@ -159,7 +159,7 @@ class ObjectFactory {

public:
ObjectFactory(StringRef S, MachineTypes M)
: Machine(M), ImportName(S), Library(llvm::sys::path::stem(S)),
: NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)),
ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}

Expand All @@ -182,10 +182,14 @@ class ObjectFactory {
// Create a short import file which is described in PE/COFF spec 7. Import
// Library Format.
NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
ImportType Type, ImportNameType NameType);
ImportType Type, ImportNameType NameType,
MachineTypes Machine);

// Create a weak external file which is described in PE/COFF Aux Format 3.
NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp);
NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp,
MachineTypes Machine);

bool is64Bit() const { return COFF::is64Bit(NativeMachine); }
};
} // namespace

Expand All @@ -197,7 +201,7 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {

// COFF Header
coff_file_header Header{
u16(Machine),
u16(NativeMachine),
u16(NumberOfSections),
u32(0),
u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
Expand All @@ -208,7 +212,7 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
(ImportName.size() + 1)),
u32(NumberOfSymbols),
u16(0),
u16(is64Bit(Machine) ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
u16(is64Bit() ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
};
append(Buffer, Header);

Expand Down Expand Up @@ -250,11 +254,11 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {

const coff_relocation RelocationTable[NumberOfRelocations] = {
{u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
u16(getImgRelRelocation(Machine))},
u16(getImgRelRelocation(NativeMachine))},
{u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
u32(3), u16(getImgRelRelocation(Machine))},
u32(3), u16(getImgRelRelocation(NativeMachine))},
{u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
u32(4), u16(getImgRelRelocation(Machine))},
u32(4), u16(getImgRelRelocation(NativeMachine))},
};
append(Buffer, RelocationTable);

Expand Down Expand Up @@ -336,15 +340,15 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {

// COFF Header
coff_file_header Header{
u16(Machine),
u16(NativeMachine),
u16(NumberOfSections),
u32(0),
u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
// .idata$3
sizeof(coff_import_directory_table_entry)),
u32(NumberOfSymbols),
u16(0),
u16(is64Bit(Machine) ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
u16(is64Bit() ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
};
append(Buffer, Header);

Expand Down Expand Up @@ -393,11 +397,11 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
const uint32_t NumberOfSections = 2;
const uint32_t NumberOfSymbols = 1;
uint32_t VASize = is64Bit(Machine) ? 8 : 4;
uint32_t VASize = is64Bit() ? 8 : 4;

// COFF Header
coff_file_header Header{
u16(Machine),
u16(NativeMachine),
u16(NumberOfSections),
u32(0),
u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
Expand All @@ -407,7 +411,7 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
VASize),
u32(NumberOfSymbols),
u16(0),
u16(is64Bit(Machine) ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
u16(is64Bit() ? C_Invalid : IMAGE_FILE_32BIT_MACHINE),
};
append(Buffer, Header);

Expand All @@ -422,8 +426,7 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
u32(0),
u16(0),
u16(0),
u32((is64Bit(Machine) ? IMAGE_SCN_ALIGN_8BYTES
: IMAGE_SCN_ALIGN_4BYTES) |
u32((is64Bit() ? IMAGE_SCN_ALIGN_8BYTES : IMAGE_SCN_ALIGN_4BYTES) |
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE)},
{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
Expand All @@ -436,21 +439,20 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
u32(0),
u16(0),
u16(0),
u32((is64Bit(Machine) ? IMAGE_SCN_ALIGN_8BYTES
: IMAGE_SCN_ALIGN_4BYTES) |
u32((is64Bit() ? IMAGE_SCN_ALIGN_8BYTES : IMAGE_SCN_ALIGN_4BYTES) |
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE)},
};
append(Buffer, SectionTable);

// .idata$5, ILT
append(Buffer, u32(0));
if (is64Bit(Machine))
if (is64Bit())
append(Buffer, u32(0));

// .idata$4, IAT
append(Buffer, u32(0));
if (is64Bit(Machine))
if (is64Bit())
append(Buffer, u32(0));

// Symbol Table
Expand All @@ -475,7 +477,8 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
uint16_t Ordinal,
ImportType ImportType,
ImportNameType NameType) {
ImportNameType NameType,
MachineTypes Machine) {
size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs
size_t Size = sizeof(coff_import_header) + ImpSize;
char *Buf = Alloc.Allocate<char>(Size);
Expand All @@ -501,7 +504,8 @@ NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
}

NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
StringRef Weak, bool Imp) {
StringRef Weak, bool Imp,
MachineTypes Machine) {
std::vector<uint8_t> Buffer;
const uint32_t NumberOfSections = 1;
const uint32_t NumberOfSymbols = 5;
Expand Down Expand Up @@ -585,8 +589,11 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
MachineTypes Machine, bool MinGW) {

MachineTypes NativeMachine =
isArm64EC(Machine) ? IMAGE_FILE_MACHINE_ARM64 : Machine;

std::vector<NewArchiveMember> Members;
ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
ObjectFactory OF(llvm::sys::path::filename(ImportName), NativeMachine);

std::vector<uint8_t> ImportDescriptor;
Members.push_back(OF.createImportDescriptor(ImportDescriptor));
Expand Down Expand Up @@ -620,13 +627,15 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
return Name.takeError();

if (!E.AliasTarget.empty() && *Name != E.AliasTarget) {
Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, false));
Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, true));
Members.push_back(
OF.createWeakExternal(E.AliasTarget, *Name, false, Machine));
Members.push_back(
OF.createWeakExternal(E.AliasTarget, *Name, true, Machine));
continue;
}

Members.push_back(
OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
OF.createShortImport(*Name, E.Ordinal, ImportType, NameType, Machine));
}

return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
Expand Down
12 changes: 7 additions & 5 deletions llvm/test/tools/llvm-lib/arm64ec-implib.test
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,30 @@ RUN: llvm-lib -machine:arm64ec -def:test.def -out:test.lib

RUN: llvm-nm --print-armap test.lib | FileCheck -check-prefix=ARMAP %s

ARMAP: Archive EC map
ARMAP: Archive map
ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll
ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll
ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll
ARMAP-EMPTY:
ARMAP-NEXT: Archive EC map
ARMAP-NEXT: __imp_dataexp in test.dll
ARMAP-NEXT: __imp_funcexp in test.dll
ARMAP-NEXT: funcexp in test.dll
ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll

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

READOBJ: File: test.lib(test.dll)
READOBJ-NEXT: Format: COFF-ARM64EC
READOBJ-NEXT: Format: COFF-ARM64{{$}}
READOBJ-NEXT: Arch: aarch64
READOBJ-NEXT: AddressSize: 64bit
READOBJ-EMPTY:
READOBJ-NEXT: File: test.lib(test.dll)
READOBJ-NEXT: Format: COFF-ARM64EC
READOBJ-NEXT: Format: COFF-ARM64{{$}}
READOBJ-NEXT: Arch: aarch64
READOBJ-NEXT: AddressSize: 64bit
READOBJ-EMPTY:
READOBJ-NEXT: File: test.lib(test.dll)
READOBJ-NEXT: Format: COFF-ARM64EC
READOBJ-NEXT: Format: COFF-ARM64{{$}}
READOBJ-NEXT: Arch: aarch64
READOBJ-NEXT: AddressSize: 64bit
READOBJ-EMPTY:
Expand Down