Skip to content

Commit cea5d28

Browse files
cjacekmstorsjo
authored andcommitted
[llvm-lib] [llvm-readobj] [llvm-cvtres] Add Support for ARM64X object files.
Similar to D125411, but for ARM64X. ARM64X PE binaries are hybrids containing both ARM64EC and pure ARM64 variants in one file. They are usually linked by passing separate ARM64EC and ARM64 object files to linker. Linked binaries use ARM64 machine and contain additional CHPE metadata in their load config. CHPE metadata support is not part of this patch, I plan to send that later. Using ARM64X as a machine type of object files themselves is somewhat ambiguous, but such files are allowed by MSVC. It treats them as ARM64 or ARM64EC object, depending on the context. Such objects can be produced with cvtres.exe -machine:arm64x. Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D148517
1 parent 85a2c50 commit cea5d28

File tree

15 files changed

+137
-12
lines changed

15 files changed

+137
-12
lines changed

llvm/include/llvm/BinaryFormat/COFF.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ enum MachineTypes : unsigned {
9999
IMAGE_FILE_MACHINE_ARMNT = 0x1C4,
100100
IMAGE_FILE_MACHINE_ARM64 = 0xAA64,
101101
IMAGE_FILE_MACHINE_ARM64EC = 0xA641,
102+
IMAGE_FILE_MACHINE_ARM64X = 0xA64E,
102103
IMAGE_FILE_MACHINE_EBC = 0xEBC,
103104
IMAGE_FILE_MACHINE_I386 = 0x14C,
104105
IMAGE_FILE_MACHINE_IA64 = 0x200,
@@ -120,6 +121,15 @@ enum MachineTypes : unsigned {
120121
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
121122
};
122123

124+
template <typename T> bool isArm64EC(T Machine) {
125+
return Machine == IMAGE_FILE_MACHINE_ARM64EC ||
126+
Machine == IMAGE_FILE_MACHINE_ARM64X;
127+
}
128+
129+
template <typename T> bool isAnyArm64(T Machine) {
130+
return Machine == IMAGE_FILE_MACHINE_ARM64 || isArm64EC(Machine);
131+
}
132+
123133
enum Characteristics : unsigned {
124134
C_Invalid = 0,
125135

llvm/lib/BinaryFormat/Magic.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ file_magic llvm::identify_magic(StringRef Magic) {
246246
return file_magic::coff_object;
247247
break;
248248

249+
case 0x4e: // ARM64X windows
250+
if (Magic[1] == char(0xA6))
251+
return file_magic::coff_object;
252+
break;
253+
249254
default:
250255
break;
251256
}

llvm/lib/Object/COFFImportFile.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ static bool is32bit(MachineTypes Machine) {
3939
llvm_unreachable("unsupported machine");
4040
case IMAGE_FILE_MACHINE_ARM64:
4141
case IMAGE_FILE_MACHINE_ARM64EC:
42+
case IMAGE_FILE_MACHINE_ARM64X:
4243
case IMAGE_FILE_MACHINE_AMD64:
4344
return false;
4445
case IMAGE_FILE_MACHINE_ARMNT:
@@ -57,6 +58,7 @@ static uint16_t getImgRelRelocation(MachineTypes Machine) {
5758
return IMAGE_REL_ARM_ADDR32NB;
5859
case IMAGE_FILE_MACHINE_ARM64:
5960
case IMAGE_FILE_MACHINE_ARM64EC:
61+
case IMAGE_FILE_MACHINE_ARM64X:
6062
return IMAGE_REL_ARM64_ADDR32NB;
6163
case IMAGE_FILE_MACHINE_I386:
6264
return IMAGE_REL_I386_DIR32NB;

llvm/lib/Object/COFFObjectFile.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,8 @@ StringRef COFFObjectFile::getFileFormatName() const {
10161016
return "COFF-ARM64";
10171017
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
10181018
return "COFF-ARM64EC";
1019+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
1020+
return "COFF-ARM64X";
10191021
default:
10201022
return "COFF-<unknown arch>";
10211023
}
@@ -1031,6 +1033,7 @@ Triple::ArchType COFFObjectFile::getArch() const {
10311033
return Triple::thumb;
10321034
case COFF::IMAGE_FILE_MACHINE_ARM64:
10331035
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
1036+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
10341037
return Triple::aarch64;
10351038
default:
10361039
return Triple::UnknownArch;
@@ -1318,6 +1321,7 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
13181321
break;
13191322
case COFF::IMAGE_FILE_MACHINE_ARM64:
13201323
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
1324+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
13211325
switch (Type) {
13221326
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
13231327
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
@@ -1901,6 +1905,7 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
19011905
break;
19021906
case COFF::IMAGE_FILE_MACHINE_ARM64:
19031907
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
1908+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
19041909
RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
19051910
break;
19061911
default:

llvm/lib/Object/WindowsMachineFlag.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ COFF::MachineTypes llvm::getMachineType(StringRef S) {
2727
.Case("arm", COFF::IMAGE_FILE_MACHINE_ARMNT)
2828
.Case("arm64", COFF::IMAGE_FILE_MACHINE_ARM64)
2929
.Case("arm64ec", COFF::IMAGE_FILE_MACHINE_ARM64EC)
30+
.Case("arm64x", COFF::IMAGE_FILE_MACHINE_ARM64X)
3031
.Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
3132
}
3233

@@ -38,6 +39,8 @@ StringRef llvm::machineToStr(COFF::MachineTypes MT) {
3839
return "arm64";
3940
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
4041
return "arm64ec";
42+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
43+
return "arm64x";
4144
case COFF::IMAGE_FILE_MACHINE_AMD64:
4245
return "x64";
4346
case COFF::IMAGE_FILE_MACHINE_I386:

llvm/lib/Object/WindowsResource.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,7 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
990990
break;
991991
case COFF::IMAGE_FILE_MACHINE_ARM64:
992992
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
993+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
993994
Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB;
994995
break;
995996
default:

llvm/lib/ObjectYAML/COFFEmitter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ struct COFFParser {
5050
bool isPE() const { return Obj.OptionalHeader.has_value(); }
5151
bool is64Bit() const {
5252
return Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 ||
53-
Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 ||
54-
Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64EC;
53+
COFF::isAnyArm64(Obj.Header.Machine);
5554
}
5655

5756
uint32_t getFileAlignment() const {

llvm/lib/ObjectYAML/COFFYAML.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ void ScalarEnumerationTraits<COFF::MachineTypes>::enumeration(
6666
ECase(IMAGE_FILE_MACHINE_ARMNT);
6767
ECase(IMAGE_FILE_MACHINE_ARM64);
6868
ECase(IMAGE_FILE_MACHINE_ARM64EC);
69+
ECase(IMAGE_FILE_MACHINE_ARM64X);
6970
ECase(IMAGE_FILE_MACHINE_EBC);
7071
ECase(IMAGE_FILE_MACHINE_I386);
7172
ECase(IMAGE_FILE_MACHINE_IA64);
@@ -430,8 +431,7 @@ void MappingTraits<COFFYAML::Relocation>::mapping(IO &IO,
430431
MappingNormalization<NType<COFF::RelocationTypesARM>, uint16_t> NT(
431432
IO, Rel.Type);
432433
IO.mapRequired("Type", NT->Type);
433-
} else if (H.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 ||
434-
H.Machine == COFF::IMAGE_FILE_MACHINE_ARM64EC) {
434+
} else if (COFF::isAnyArm64(H.Machine)) {
435435
MappingNormalization<NType<COFF::RelocationTypesARM64>, uint16_t> NT(
436436
IO, Rel.Type);
437437
IO.mapRequired("Type", NT->Type);

llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
167167
break;
168168
case COFF::IMAGE_FILE_MACHINE_ARM64:
169169
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
170+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
170171
CpuType = CPUType::ARM64;
171172
break;
172173
}

llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,7 @@ static Expected<COFF::MachineTypes> getCOFFFileMachine(MemoryBufferRef MB) {
167167
uint16_t Machine = (*Obj)->getMachine();
168168
if (Machine != COFF::IMAGE_FILE_MACHINE_I386 &&
169169
Machine != COFF::IMAGE_FILE_MACHINE_AMD64 &&
170-
Machine != COFF::IMAGE_FILE_MACHINE_ARMNT &&
171-
Machine != COFF::IMAGE_FILE_MACHINE_ARM64 &&
172-
Machine != COFF::IMAGE_FILE_MACHINE_ARM64EC) {
170+
Machine != COFF::IMAGE_FILE_MACHINE_ARMNT && !COFF::isAnyArm64(Machine)) {
173171
return createStringError(inconvertibleErrorCode(),
174172
"unknown machine: " + std::to_string(Machine));
175173
}
@@ -205,9 +203,16 @@ static bool machineMatches(COFF::MachineTypes LibMachine,
205203
return true;
206204
// ARM64EC mode allows both pure ARM64, ARM64EC and X64 objects to be mixed in
207205
// the archive.
208-
return LibMachine == COFF::IMAGE_FILE_MACHINE_ARM64EC &&
209-
(FileMachine == COFF::IMAGE_FILE_MACHINE_ARM64 ||
210-
FileMachine == COFF::IMAGE_FILE_MACHINE_AMD64);
206+
switch (LibMachine) {
207+
case COFF::IMAGE_FILE_MACHINE_ARM64:
208+
return FileMachine == COFF::IMAGE_FILE_MACHINE_ARM64X;
209+
case COFF::IMAGE_FILE_MACHINE_ARM64EC:
210+
case COFF::IMAGE_FILE_MACHINE_ARM64X:
211+
return COFF::isAnyArm64(FileMachine) ||
212+
FileMachine == COFF::IMAGE_FILE_MACHINE_AMD64;
213+
default:
214+
return false;
215+
}
211216
}
212217

213218
static void appendFile(std::vector<NewArchiveMember> &Members,
@@ -482,7 +487,7 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
482487
/*WriteSymtab=*/true,
483488
Thin ? object::Archive::K_GNU : object::Archive::K_COFF,
484489
/*Deterministic*/ true, Thin, nullptr,
485-
LibMachine == COFF::IMAGE_FILE_MACHINE_ARM64EC)) {
490+
COFF::isArm64EC(LibMachine))) {
486491
handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
487492
llvm::errs() << OutputPath << ": " << EI.message() << "\n";
488493
});

0 commit comments

Comments
 (0)