diff mbox series

[3/4] x86: Hand-edit coff flags to remove RELOCS_STRIPPED flag

Message ID 20240313150439.791213-4-ross.lagerwall@citrix.com (mailing list archive)
State Superseded
Headers show
Series x86: Multiboot PE support | expand

Commit Message

Ross Lagerwall March 13, 2024, 3:04 p.m. UTC
The generated PE binary is generated without relocations since it does
not need them. However, the linker sets the IMAGE_FILE_RELOCS_STRIPPED
flag which implies the binary is not relocatable and this causes some
tools to refuse to handle the binary (e.g. Shim). As there is no option
to remove this flag using the linker, post-process the binary to do it.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 .gitignore                        |  1 +
 xen/arch/x86/Makefile             |  2 +
 xen/arch/x86/efi/set-coff-flags.c | 83 +++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)
 create mode 100644 xen/arch/x86/efi/set-coff-flags.c
diff mbox series

Patch

diff --git a/.gitignore b/.gitignore
index d8b57e32f888..ab0b18352a0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -256,6 +256,7 @@  xen/arch/x86/boot/*.lnk
 xen/arch/x86/efi.lds
 xen/arch/x86/efi/check.efi
 xen/arch/x86/efi/mkreloc
+xen/arch/x86/efi/set-coff-flags
 xen/arch/x86/include/asm/asm-macros.h
 xen/arch/*/xen.lds
 xen/arch/*/efi/boot.c
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index e26b1cb35036..73b16ddeb976 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -86,6 +86,7 @@  extra-y += xen.lds
 
 hostprogs-y += boot/mkelf32
 hostprogs-y += efi/mkreloc
+hostprogs-y += efi/set-coff-flags
 
 # Allows usercopy.c to include itself
 $(obj)/usercopy.o: CFLAGS-y += -iquote .
@@ -157,6 +158,7 @@  endif
 		{ echo "No Multiboot1 header found" >&2; false; }
 	od -t x4 -N 32768 $@.tmp | grep e85250d6 > /dev/null || \
 		{ echo "No Multiboot2 header found" >&2; false; }
+	$(obj)/efi/set-coff-flags $@.tmp
 	mv $@.tmp $(TARGET)
 	$(NM) -pa --format=sysv $@ \
 		| $(objtree)/tools/symbols --all-symbols --xensyms --sysv --sort \
diff --git a/xen/arch/x86/efi/set-coff-flags.c b/xen/arch/x86/efi/set-coff-flags.c
new file mode 100644
index 000000000000..a99415e6bcbf
--- /dev/null
+++ b/xen/arch/x86/efi/set-coff-flags.c
@@ -0,0 +1,83 @@ 
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+struct mz_hdr {
+    uint16_t signature;
+#define MZ_SIGNATURE 0x5a4d
+    uint16_t last_page_size;
+    uint16_t page_count;
+    uint16_t relocation_count;
+    uint16_t header_paras;
+    uint16_t min_paras;
+    uint16_t max_paras;
+    uint16_t entry_ss;
+    uint16_t entry_sp;
+    uint16_t checksum;
+    uint16_t entry_ip;
+    uint16_t entry_cs;
+    uint16_t relocations;
+    uint16_t overlay;
+    uint8_t reserved[32];
+    uint32_t extended_header_base;
+};
+
+struct coff_hdr {
+    uint32_t signature;
+    uint16_t cpu;
+    uint16_t section_count;
+    int32_t timestamp;
+    uint32_t symbols_file_offset;
+    uint32_t symbol_count;
+    uint16_t opt_hdr_size;
+    uint16_t flags;
+};
+
+int main(int argc, char **argv)
+{
+    int fd;
+    struct mz_hdr mz_hdr;
+    struct coff_hdr coff_hdr;
+
+    if ( argc != 2 )
+    {
+        fprintf(stderr, "usage: %s <image>\n", argv[0]);
+        return 1;
+    }
+
+    fd = open(argv[1], O_RDWR);
+    if ( fd < 0 ||
+         read(fd, &mz_hdr, sizeof(mz_hdr)) != sizeof(mz_hdr) )
+    {
+        perror(argv[1]);
+        return 2;
+    }
+
+    if ( mz_hdr.signature != MZ_SIGNATURE ||
+         !mz_hdr.extended_header_base )
+    {
+        fprintf(stderr, "%s: Wrong DOS file format\n", argv[1]);
+        return 2;
+    }
+
+    if ( lseek(fd, mz_hdr.extended_header_base, SEEK_SET) < 0 ||
+         read(fd, &coff_hdr, sizeof(coff_hdr)) != sizeof(coff_hdr) )
+    {
+        perror(argv[1]);
+        return 2;
+    }
+
+    coff_hdr.flags &= ~0x1;
+
+    if ( lseek(fd, mz_hdr.extended_header_base, SEEK_SET) < 0 ||
+         write(fd, &coff_hdr, sizeof(coff_hdr)) != sizeof(coff_hdr) )
+    {
+        perror(argv[1]);
+        return 3;
+    }
+
+    close(fd);
+
+    return 0;
+}