Index: llvm/test/tools/llvm-objdump/COFF/arm64ec-unsupported.yaml =================================================================== --- /dev/null +++ llvm/test/tools/llvm-objdump/COFF/arm64ec-unsupported.yaml @@ -0,0 +1,106 @@ +# REQUIRES: aarch64-registered-target, !x86-registered-target + +## Check that llvm-objdump emits a warning when x86_64 target is not available. +# RUN: yaml2obj %s -o %t -DMACHINE=IMAGE_FILE_MACHINE_AMD64 +# RUN: llvm-objdump -d %t 2>&1 | FileCheck --check-prefixes=DISASM,ARM64EC,WARN1 %s +# RUN: llvm-objdump -d %t --triple arm64ec-w64-windows-gnu 2>&1 | FileCheck --check-prefixes=DISASM,ARM64EC,WARN2 %s +# RUN: llvm-readobj --coff-load-config %t | FileCheck --check-prefix=CODEMAP %s + +# RUN: yaml2obj --docnum=1 %s -o %t -DMACHINE=IMAGE_FILE_MACHINE_ARM64 +# RUN: llvm-objdump -d %t 2>&1 | FileCheck --check-prefixes=DISASM,ARM64X,WARN1 %s +# RUN: llvm-objdump -d %t --triple arm64ec-w64-windows-gnu 2>&1 | FileCheck --check-prefixes=DISASM,ARM64X,WARN2 %s +# RUN: llvm-readobj --coff-load-config %t | FileCheck --check-prefix=CODEMAP %s + +# ARM64EC: file format coff-arm64ec +# ARM64X: file format coff-arm64x + +# WARN1: llvm-objdump: warning: '{{.*}}': unable to get target for 'x86_64--', see --version and --triple. +# WARN2: llvm-objdump: warning: '{{.*}}': unable to get target for 'x86_64-w64-windows-gnu', see --version and --triple. + +# DISASM: Disassembly of section .text: +# DISASM-EMPTY: +# DISASM-NEXT: 0000000180001000 <.text>: +# DISASM-NEXT: 180001000: 52800040 mov w0, #0x2 +# DISASM-NEXT: 180001004: d65f03c0 ret +# DISASM-NEXT: ... +# DISASM-NEXT: 180001020: 000003b8 udf #0x3b8 +# DISASM-NEXT: 180001024: 00 c3 +# DISASM-EMPTY: +# DISASM-NEXT: Disassembly of section .test: +# DISASM-EMPTY: +# DISASM-NEXT: 0000000180002000 <.test>: +# DISASM-NEXT: 180002000: 000006b8 udf #0x6b8 +# DISASM-NEXT: 180002004: 00ccc300 +# DISASM-NEXT: ... +# DISASM-NEXT: 180002020: 528000a0 mov w0, #0x5 +# DISASM-NEXT: 180002024: d65f03c0 ret + +# CODEMAP: CodeMap [ +# CODEMAP-NEXT: 0x1000 - 0x1008 ARM64EC +# CODEMAP-NEXT: 0x1020 - 0x2007 X64 +# CODEMAP-NEXT: 0x2020 - 0x2028 ARM64EC +# CODEMAP-NEXT: ] + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] + LoadConfigTable: + RelativeVirtualAddress: 0x3000 + Size: 320 +header: + Machine: [[MACHINE]] + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x1000 + VirtualSize: 38 + SectionData: 40008052C0035FD6000000000000000000000000000000000000000000000000B803000000C3 + - Name: .test + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x2000 + VirtualSize: 40 + SectionData: B806000000C3CC00000000000000000000000000000000000000000000000000A0008052C0035FD6 + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x3000 + VirtualSize: 328 + StructuredData: + - LoadConfig: + CHPEMetadataPointer: 0x180004000 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + VirtualAddress: 0x4000 + VirtualSize: 112 + StructuredData: + - UInt32: 1 # Version + - UInt32: 0x4050 # CodeMap + - UInt32: 3 # CodeMapCount + - UInt32: 0 # CodeRangesToEntryPoints + - UInt32: 0 # RedirectionMetadata + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 # CodeRangesToEntryPointsCount + - UInt32: 0 # RedirectionMetadataCount + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0x1001 # CodeMap[0] + - UInt32: 0x8 + - UInt32: 0x1022 # CodeMap[1] + - UInt32: 0x0fe7 + - UInt32: 0x2021 # CodeMap[2] + - UInt32: 0x8 +symbols: [] +... Index: llvm/test/tools/llvm-objdump/COFF/arm64ec.yaml =================================================================== --- llvm/test/tools/llvm-objdump/COFF/arm64ec.yaml +++ llvm/test/tools/llvm-objdump/COFF/arm64ec.yaml @@ -1,22 +1,35 @@ -# REQUIRES: aarch64-registered-target +# REQUIRES: aarch64-registered-target, x86-registered-target ## Check that AMD64 image file with CHPE data is recognized as ARM64EC. -# RUN: yaml2obj %s -o %t -DMACHINE=IMAGE_FILE_MACHINE_AMD64 -# RUN: llvm-objdump -d %t | FileCheck --check-prefixes=DISASM,ARM64EC %s -# RUN: llvm-readobj --coff-load-config %t | FileCheck --check-prefix=CODEMAP %s +# RUN: yaml2obj --docnum=1 %s -o %t1 -DMACHINE=IMAGE_FILE_MACHINE_AMD64 +# RUN: llvm-objdump -d %t1 | FileCheck --check-prefixes=DISASM,ARM64EC %s +# RUN: llvm-readobj --coff-load-config %t1 | FileCheck --check-prefix=CODEMAP %s ## Check that ARM64 image file with CHPE data is recognized as ARM64X. -# RUN: yaml2obj %s -o %t -DMACHINE=IMAGE_FILE_MACHINE_ARM64 -# RUN: llvm-objdump -d %t | FileCheck --check-prefixes=DISASM,ARM64X %s -# RUN: llvm-readobj --coff-load-config %t | FileCheck --check-prefix=CODEMAP %s +# RUN: yaml2obj --docnum=1 %s -o %t2 -DMACHINE=IMAGE_FILE_MACHINE_ARM64 +# RUN: llvm-objdump -d %t2 | FileCheck --check-prefixes=DISASM,ARM64X %s +# RUN: llvm-readobj --coff-load-config %t2 | FileCheck --check-prefix=CODEMAP %s # ARM64EC: file format coff-arm64ec # ARM64X: file format coff-arm64x -# DISASM: 180001000: 52800040 mov w0, #0x2 +# DISASM: Disassembly of section .text: +# DISASM-EMPTY: +# DISASM-NEXT: 0000000180001000 <.text>: +# DISASM-NEXT: 180001000: 52800040 mov w0, #0x2 # DISASM-NEXT: 180001004: d65f03c0 ret # DISASM-NEXT: ... -# DISASM: 180002020: 528000a0 mov w0, #0x5 +# DISASM-NEXT: 180001020: b8 03 00 00 00 movl $0x3, %eax +# DISASM-NEXT: 180001025: c3 retq +# DISASM-EMPTY: +# DISASM-NEXT: Disassembly of section .test: +# DISASM-EMPTY: +# DISASM-NEXT: 0000000180002000 <.test>: +# DISASM-NEXT: 180002000: b8 06 00 00 00 movl $0x6, %eax +# DISASM-NEXT: 180002005: c3 retq +# DISASM-NEXT: 180002006: cc int3 +# DISASM-NEXT: ... +# DISASM-NEXT: 180002020: 528000a0 mov w0, #0x5 # DISASM-NEXT: 180002024: d65f03c0 ret # CODEMAP: CodeMap [ @@ -88,3 +101,56 @@ - UInt32: 0x8 symbols: [] ... + +## Check error handling of invalid code map RVA. +# RUN: yaml2obj --docnum=2 %s -o %t-invalid +# RUN: not llvm-objdump -d %t-invalid 2>&1 | FileCheck --check-prefixes=ERR %s +# ERR: llvm-objdump: error: {{.*}}: RVA 0x6000 for CHPE code map not found + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] + LoadConfigTable: + RelativeVirtualAddress: 0x3000 + Size: 320 +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] +sections: + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x3000 + VirtualSize: 328 + StructuredData: + - LoadConfig: + CHPEMetadataPointer: 0x180004000 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + VirtualAddress: 0x4000 + VirtualSize: 112 + StructuredData: + - UInt32: 1 # Version + - UInt32: 0x6000 # CodeMap + - UInt32: 3 # CodeMapCount + - UInt32: 0 # CodeRangesToEntryPoints + - UInt32: 0 # RedirectionMetadata + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 # CodeRangesToEntryPointsCount + - UInt32: 0 # RedirectionMetadataCount + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 +symbols: [] +... Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1122,7 +1122,9 @@ }); // Return zero for any address before the first mapping symbol; this means // we should use the default disassembly mode, depending on the target. - if (It == MappingSymbols.begin() || (--It)->first < SectionAddress) + // Only CHPE ranges, marked with upper letters, can cross section boundaries. + if (It == MappingSymbols.begin() || + ((--It)->first < SectionAddress && isLower(It->second))) return '\x00'; return It->second; } @@ -1415,8 +1417,32 @@ SourcePrinter &SP, bool InlineRelocs) { DisassemblerTarget *DT = &PrimaryTarget; bool PrimaryIsThumb = false; - if (isArmElf(Obj)) - PrimaryIsThumb = PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"); + std::vector MappingSymbols; + + if (SecondaryTarget) { + if (isArmElf(Obj)) { + PrimaryIsThumb = + PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"); + } else if (const auto *COFFObj = dyn_cast(&Obj)) { + const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata(); + if (CHPEMetadata && CHPEMetadata->CodeMapCount) { + uintptr_t CodeMapInt; + cantFail(COFFObj->getRvaPtr(CHPEMetadata->CodeMap, CodeMapInt)); + auto CodeMap = reinterpret_cast(CodeMapInt); + + for (uint32_t i = 0; i < CHPEMetadata->CodeMapCount; ++i) { + if (CodeMap[i].getType() != chpe_range_type::Amd64 || + !CodeMap[i].Length) + continue; + + // Mark x86_64 CHPE code ranges. + uint64_t Start = CodeMap[i].getStart() + COFFObj->getImageBase(); + MappingSymbols.emplace_back(Start, 'X'); + MappingSymbols.emplace_back(Start + CodeMap[i].Length, 'A'); + } + } + } + } std::map> RelocMap; if (InlineRelocs) @@ -1426,7 +1452,6 @@ // Create a mapping from virtual address to symbol name. This is used to // pretty print the symbols while disassembling. std::map AllSymbols; - std::vector MappingSymbols; SectionSymbolsTy AbsoluteSymbols; const StringRef FileName = Obj.getFileName(); const MachOObjectFile *MachO = dyn_cast(&Obj); @@ -1897,10 +1922,25 @@ char Kind = getMappingSymbolKind(MappingSymbols, SectionAddr, Index); DumpARMELFData = Kind == 'd'; if (SecondaryTarget) { - if (Kind == 'a') { + switch (Kind) { + case 'a': DT = PrimaryIsThumb ? &*SecondaryTarget : &PrimaryTarget; - } else if (Kind == 't') { + break; + case 't': DT = PrimaryIsThumb ? &PrimaryTarget : &*SecondaryTarget; + break; + case 'A': + // X64 disassembler range may have left Index unaligned, so + // make sure that it's aligned when we switch back to ARM64 + // code. + Index = llvm::alignTo(Index, 4); + DT = &PrimaryTarget; + if (Index >= End) + continue; + break; + case 'X': + DT = &*SecondaryTarget; + break; } } } @@ -2212,6 +2252,24 @@ Features.AddFeature("+thumb-mode"); SecondaryTarget.emplace(PrimaryTarget, Features); } + } else if (const auto *COFFObj = dyn_cast(Obj)) { + const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata(); + if (CHPEMetadata && CHPEMetadata->CodeMapCount) { + // Set up x86_64 disassembler for ARM64EC binaries. + Triple X64Triple(TripleName); + X64Triple.setArch(Triple::ArchType::x86_64); + + std::string Error; + const Target *X64Target = + TargetRegistry::lookupTarget("", X64Triple, Error); + if (X64Target) { + SubtargetFeatures X64Features; + SecondaryTarget.emplace(X64Target, *Obj, X64Triple.getTriple(), "", + X64Features); + } else { + reportWarning(Error, Obj->getFileName()); + } + } } const ObjectFile *DbgObj = Obj;