[ARM64EC 1/?] Add parsing support to llvm-objdump/llvm-readobj.
authorEli Friedman <efriedma@quicinc.com>
Mon, 5 Sep 2022 19:25:08 +0000 (12:25 -0700)
committerEli Friedman <efriedma@quicinc.com>
Mon, 5 Sep 2022 19:25:08 +0000 (12:25 -0700)
This is the first patch of a patchset to add initial support for
ARM64EC. Basic documentation is available at
https://docs.microsoft.com/en-us/windows/uwp/porting/arm64ec-abi .
(Discourse post:
https://discourse.llvm.org/t/initial-patches-for-arm64ec-windows-11-now-posted/62449
.)

The file format for ARM64EC is basically identical to normal ARM64.
There are a few extra sections, but the existing code for reading ARM64
object files just works.

Differential Revision: https://reviews.llvm.org/D125411

llvm/include/llvm/BinaryFormat/COFF.h
llvm/lib/BinaryFormat/Magic.cpp
llvm/lib/Object/COFFImportFile.cpp
llvm/lib/Object/COFFObjectFile.cpp
llvm/lib/Object/WindowsMachineFlag.cpp
llvm/lib/Object/WindowsResource.cpp
llvm/lib/ObjectYAML/COFFEmitter.cpp
llvm/lib/ObjectYAML/COFFYAML.cpp
llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
llvm/test/tools/llvm-readobj/COFF/arm64ec.yaml [new file with mode: 0644]
llvm/tools/llvm-readobj/COFFDumper.cpp

index 835b721..08a8b48 100644 (file)
@@ -98,6 +98,7 @@ enum MachineTypes : unsigned {
   IMAGE_FILE_MACHINE_ARM = 0x1C0,
   IMAGE_FILE_MACHINE_ARMNT = 0x1C4,
   IMAGE_FILE_MACHINE_ARM64 = 0xAA64,
+  IMAGE_FILE_MACHINE_ARM64EC = 0xA641,
   IMAGE_FILE_MACHINE_EBC = 0xEBC,
   IMAGE_FILE_MACHINE_I386 = 0x14C,
   IMAGE_FILE_MACHINE_IA64 = 0x200,
index 7a348f1..0e5a5ea 100644 (file)
@@ -238,6 +238,11 @@ file_magic llvm::identify_magic(StringRef Magic) {
       return file_magic::dxcontainer_object;
     break;
 
+  case 0x41: // ARM64EC windows
+    if (Magic[1] == char(0xA6))
+      return file_magic::coff_object;
+    break;
+
   default:
     break;
   }
index 91ecea1..7090d3c 100644 (file)
@@ -38,6 +38,7 @@ static bool is32bit(MachineTypes Machine) {
   default:
     llvm_unreachable("unsupported machine");
   case IMAGE_FILE_MACHINE_ARM64:
+  case IMAGE_FILE_MACHINE_ARM64EC:
   case IMAGE_FILE_MACHINE_AMD64:
     return false;
   case IMAGE_FILE_MACHINE_ARMNT:
@@ -55,6 +56,7 @@ static uint16_t getImgRelRelocation(MachineTypes Machine) {
   case IMAGE_FILE_MACHINE_ARMNT:
     return IMAGE_REL_ARM_ADDR32NB;
   case IMAGE_FILE_MACHINE_ARM64:
+  case IMAGE_FILE_MACHINE_ARM64EC:
     return IMAGE_REL_ARM64_ADDR32NB;
   case IMAGE_FILE_MACHINE_I386:
     return IMAGE_REL_I386_DIR32NB;
index 1a4bb32..d0ca50e 100644 (file)
@@ -1014,6 +1014,8 @@ StringRef COFFObjectFile::getFileFormatName() const {
     return "COFF-ARM";
   case COFF::IMAGE_FILE_MACHINE_ARM64:
     return "COFF-ARM64";
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
+    return "COFF-ARM64EC";
   default:
     return "COFF-<unknown arch>";
   }
@@ -1028,6 +1030,7 @@ Triple::ArchType COFFObjectFile::getArch() const {
   case COFF::IMAGE_FILE_MACHINE_ARMNT:
     return Triple::thumb;
   case COFF::IMAGE_FILE_MACHINE_ARM64:
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
     return Triple::aarch64;
   default:
     return Triple::UnknownArch;
@@ -1314,6 +1317,7 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
     }
     break;
   case COFF::IMAGE_FILE_MACHINE_ARM64:
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
     switch (Type) {
     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
     LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
@@ -1896,6 +1900,7 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
       RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
       break;
     case COFF::IMAGE_FILE_MACHINE_ARM64:
+    case COFF::IMAGE_FILE_MACHINE_ARM64EC:
       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
       break;
     default:
index f7f2b20..eef0ea8 100644 (file)
@@ -25,6 +25,7 @@ COFF::MachineTypes llvm::getMachineType(StringRef S) {
       .Cases("x86", "i386", COFF::IMAGE_FILE_MACHINE_I386)
       .Case("arm", COFF::IMAGE_FILE_MACHINE_ARMNT)
       .Case("arm64", COFF::IMAGE_FILE_MACHINE_ARM64)
+      .Case("arm64ec", COFF::IMAGE_FILE_MACHINE_ARM64EC)
       .Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
 }
 
@@ -34,6 +35,8 @@ StringRef llvm::machineToStr(COFF::MachineTypes MT) {
     return "arm";
   case COFF::IMAGE_FILE_MACHINE_ARM64:
     return "arm64";
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
+    return "arm64ec";
   case COFF::IMAGE_FILE_MACHINE_AMD64:
     return "x64";
   case COFF::IMAGE_FILE_MACHINE_I386:
index d90a338..9ea0e17 100644 (file)
@@ -989,6 +989,7 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
       Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB;
       break;
     case COFF::IMAGE_FILE_MACHINE_ARM64:
+    case COFF::IMAGE_FILE_MACHINE_ARM64EC:
       Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB;
       break;
     default:
index 72d7db6..787032c 100644 (file)
@@ -49,7 +49,8 @@ struct COFFParser {
   bool isPE() const { return Obj.OptionalHeader.has_value(); }
   bool is64Bit() const {
     return Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 ||
-           Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64;
+           Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 ||
+           Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64EC;
   }
 
   uint32_t getFileAlignment() const {
index 099ddb2..2fa0433 100644 (file)
@@ -65,6 +65,7 @@ void ScalarEnumerationTraits<COFF::MachineTypes>::enumeration(
   ECase(IMAGE_FILE_MACHINE_ARM);
   ECase(IMAGE_FILE_MACHINE_ARMNT);
   ECase(IMAGE_FILE_MACHINE_ARM64);
+  ECase(IMAGE_FILE_MACHINE_ARM64EC);
   ECase(IMAGE_FILE_MACHINE_EBC);
   ECase(IMAGE_FILE_MACHINE_I386);
   ECase(IMAGE_FILE_MACHINE_IA64);
@@ -429,7 +430,8 @@ void MappingTraits<COFFYAML::Relocation>::mapping(IO &IO,
     MappingNormalization<NType<COFF::RelocationTypesARM>, uint16_t> NT(
         IO, Rel.Type);
     IO.mapRequired("Type", NT->Type);
-  } else if (H.Machine == COFF::IMAGE_FILE_MACHINE_ARM64) {
+  } else if (H.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 ||
+             H.Machine == COFF::IMAGE_FILE_MACHINE_ARM64EC) {
     MappingNormalization<NType<COFF::RelocationTypesARM64>, uint16_t> NT(
         IO, Rel.Type);
     IO.mapRequired("Type", NT->Type);
index b1ad10d..f239f0e 100644 (file)
@@ -165,6 +165,7 @@ void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
     CpuType = CPUType::ARMNT;
     break;
   case COFF::IMAGE_FILE_MACHINE_ARM64:
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
     CpuType = CPUType::ARM64;
     break;
   }
diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64ec.yaml b/llvm/test/tools/llvm-readobj/COFF/arm64ec.yaml
new file mode 100644 (file)
index 0000000..bf0d827
--- /dev/null
@@ -0,0 +1,27 @@
+# RUN: yaml2obj < %s | llvm-readobj - --file-headers | FileCheck %s
+# Check we can process a simple arm64ec file.
+# CHECK: Format: COFF-ARM64EC
+# CHECK: Machine: IMAGE_FILE_MACHINE_ARM64EC (0xA641)
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_ARM64EC
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     ''
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          0
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          1
+...
index 67889f4..56c5d9c 100644 (file)
@@ -343,6 +343,7 @@ const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64    ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM      ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64    ),
+  LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64EC  ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT    ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC      ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386     ),
@@ -1670,9 +1671,10 @@ void COFFDumper::printUnwindInfo() {
     break;
   }
   case COFF::IMAGE_FILE_MACHINE_ARM64:
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
   case COFF::IMAGE_FILE_MACHINE_ARMNT: {
-    ARM::WinEH::Decoder Decoder(W, Obj->getMachine() ==
-                                       COFF::IMAGE_FILE_MACHINE_ARM64);
+    ARM::WinEH::Decoder Decoder(W, Obj->getMachine() !=
+                                       COFF::IMAGE_FILE_MACHINE_ARMNT);
     // TODO Propagate the error.
     consumeError(Decoder.dumpProcedureData(*Obj));
     break;