From a45167b58061b3e857c661979888fea1c9223313 Mon Sep 17 00:00:00 2001 From: Ashlyn Date: Tue, 14 Apr 2026 16:29:14 -0600 Subject: [PATCH] [lld][llvm-objcopy] Enable Xbox subsystem for PE images. (#191779) This patch enables selecting the Xbox subsystem (IMAGE_SUBSYSTEM_XBOX) for PE images. Certain existing tools used in the Xbox homebrew scene expect images to use the Xbox subsystem, so it's nice to be able to set this within the LLVM toolchain instead of invoking yet another tool or manually patching the binaries. (cherry picked from commit 18519f34650db7fc8e1885ac0293c1e9a5f1b071) --- lld/COFF/DriverUtils.cpp | 24 ++++++++++--------- lld/test/COFF/subsystem.test | 10 ++++++++ .../tools/llvm-objcopy/COFF/subsystem.test | 5 ++++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 1 + 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 42c7f93381510..3b69a6d9b3d14 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -122,17 +122,19 @@ void LinkerDriver::parseSubsystem(StringRef arg, WindowsSubsystem *sys, auto [sysStr, ver] = arg.split(','); std::string sysStrLower = sysStr.lower(); *sys = StringSwitch(sysStrLower) - .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) - .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI) - .Case("default", IMAGE_SUBSYSTEM_UNKNOWN) - .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION) - .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) - .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM) - .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) - .Case("native", IMAGE_SUBSYSTEM_NATIVE) - .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI) - .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI) - .Default(IMAGE_SUBSYSTEM_UNKNOWN); + .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) + .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI) + .Case("default", IMAGE_SUBSYSTEM_UNKNOWN) + .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION) + .Case("efi_boot_service_driver", + IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) + .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM) + .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) + .Case("native", IMAGE_SUBSYSTEM_NATIVE) + .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI) + .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI) + .Case("xbox", IMAGE_SUBSYSTEM_XBOX) + .Default(IMAGE_SUBSYSTEM_UNKNOWN); if (*sys == IMAGE_SUBSYSTEM_UNKNOWN && sysStrLower != "default") Fatal(ctx) << "unknown subsystem: " << sysStr; if (!ver.empty()) diff --git a/lld/test/COFF/subsystem.test b/lld/test/COFF/subsystem.test index e9a6966a01da9..347a489709d67 100644 --- a/lld/test/COFF/subsystem.test +++ b/lld/test/COFF/subsystem.test @@ -48,3 +48,13 @@ CHECK5: MajorOperatingSystemVersion: 1 CHECK5: MinorOperatingSystemVersion: 2 CHECK5: MajorSubsystemVersion: 3 CHECK5: MinorSubsystemVersion: 4 + +# RUN: lld-link /entry:main /out:%t.exe /subsystem:xbox,8.9 \ +# RUN: %p/Inputs/ret42.obj +# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK6 %s + +CHECK6: MajorOperatingSystemVersion: 8 +CHECK6: MinorOperatingSystemVersion: 9 +CHECK6: MajorSubsystemVersion: 8 +CHECK6: MinorSubsystemVersion: 9 +CHECK6: Subsystem: IMAGE_SUBSYSTEM_XBOX diff --git a/llvm/test/tools/llvm-objcopy/COFF/subsystem.test b/llvm/test/tools/llvm-objcopy/COFF/subsystem.test index 3ee1069d0373c..4dd2e85f5516d 100644 --- a/llvm/test/tools/llvm-objcopy/COFF/subsystem.test +++ b/llvm/test/tools/llvm-objcopy/COFF/subsystem.test @@ -51,6 +51,11 @@ # EFI-RUNTIME-DRIVER: Subsystem: IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER +# RUN: llvm-objcopy --subsystem=xbox %t.in.exe %t.out.exe +# RUN: llvm-readobj --file-headers %t.out.exe | FileCheck %s --check-prefix=XBOX + +# XBOX: Subsystem: IMAGE_SUBSYSTEM_XBOX + --- !COFF OptionalHeader: AddressOfEntryPoint: 4096 diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 8aa843b6a5155..89951d55588d2 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -821,6 +821,7 @@ objcopy::parseObjcopyOptions(ArrayRef ArgsArr, .Case("native", COFF::IMAGE_SUBSYSTEM_NATIVE) .Case("posix", COFF::IMAGE_SUBSYSTEM_POSIX_CUI) .Case("windows", COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) + .Case("xbox", COFF::IMAGE_SUBSYSTEM_XBOX) .Default(COFF::IMAGE_SUBSYSTEM_UNKNOWN); if (*COFFConfig.Subsystem == COFF::IMAGE_SUBSYSTEM_UNKNOWN) return createStringError(errc::invalid_argument,