diff mbox series

[1/3] x86/build: Rework binary conversion for boot/{cmdline,reloc}.c

Message ID 20220414114708.4788-2-andrew.cooper3@citrix.com (mailing list archive)
State New, archived
Headers show
Series x86/build: Clean up 32bit boot objects | expand

Commit Message

Andrew Cooper April 14, 2022, 11:47 a.m. UTC
There is no need to opencode .got.plt size check; it can be done with linker
asserts instead.  Extend the checking to all dynamic linkage sections, and
drop the $(OBJDUMP) pass.

Furthermore, instead of removing .got.plt specifically, take only .text when
converting to a flat binary.  This makes the process invariant of .text's
position relative to the start of the binary, which avoids needing to discard
all sections, and removes the need to work around sections that certain
linkers are unhappy discarding.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Wei Liu <wl@xen.org>
CC: Anthony PERARD <anthony.perard@citrix.com>
---
 xen/arch/x86/boot/Makefile    | 13 +---------
 xen/arch/x86/boot/build32.lds | 58 +++++++++++++++++++------------------------
 2 files changed, 26 insertions(+), 45 deletions(-)

Comments

Jan Beulich April 20, 2022, 10:15 a.m. UTC | #1
On 14.04.2022 13:47, Andrew Cooper wrote:
> --- a/xen/arch/x86/boot/build32.lds
> +++ b/xen/arch/x86/boot/build32.lds
> @@ -31,44 +31,36 @@ SECTIONS
>          *(.bss.*)
>    }
>  
> +  /* Dynamic linkage sections.  Collected simply so we can check they're empty. */
> +  .got : {
> +        *(.got)
> +  }
>    .got.plt : {
> -        /*
> -         * PIC/PIE executable contains .got.plt section even if it is not linked
> -         * with dynamic libraries. In such case it is just placeholder for
> -         * _GLOBAL_OFFSET_TABLE_ symbol and .PLT0. .PLT0 is filled by dynamic
> -         * linker and our code is not supposed to be loaded by dynamic linker.
> -         * So, from our point of view .PLT0 is unused. This means that there is
> -         * pretty good chance that we can safely drop .got.plt as a whole here.
> -         * Sadly this is not true. _GLOBAL_OFFSET_TABLE_ is used as a reference
> -         * for relative addressing (and only for that thing) and ld complains if
> -         * we remove .got.plt section here because it cannot find required symbol.
> -         * However, _GLOBAL_OFFSET_TABLE_ is no longer needed in final output.
> -         * So, drop .got.plt section during conversion to plain binary format.
> -         *
> -         * Please check build32.mk for more details.
> -         */
>          *(.got.plt)
>    }
> -
> -  /*
> -   * Discarding .shstrtab is not supported by LLD (LLVM LD) and will trigger an
> -   * error. Also keep the rest of the control sections to match GNU LD behavior.
> -   */
> -  .shstrtab : {
> -        *(.shstrtab)
> +  .igot.plt : {
> +        *(.igot.plt)
>    }
> -  .strtab : {
> -        *(.strtab)
> +  .iplt : {
> +        *(.iplt)
>    }
> -  .symtab : {
> -        *(.symtab)
> +  .plt : {
> +        *(.plt)
>    }
> -
> -  /DISCARD/ : {
> -        /*
> -         * Discard everything else, to prevent linkers from putting
> -         * orphaned sections ahead of .text, which needs to be first.
> -         */
> -        *(*)
> +  .rela : {
> +        *(.rela.*)
>    }
>  }
> +
> +ASSERT(SIZEOF(.got) == 0,         ".got non-empty")
> +/*
> + * At least GNU ld 2.30 and earlier fail to discard the generic part of
> + * .got.plt when no actual entries were allocated. Permit this case alongside
> + * the section being empty.
> + */
> +ASSERT(SIZEOF(.got.plt) == 0 ||
> +       SIZEOF(.got.plt) == 3 * 4, "unexpected .got.plt size")

While here you've adjusted for this being 32-bit code, ...

> +ASSERT(SIZEOF(.igot.plt) == 0,    ".igot.plt non-empty")
> +ASSERT(SIZEOF(.iplt) == 0,        ".iplt non-empty")
> +ASSERT(SIZEOF(.plt) == 0,         ".plt non-empty")
> +ASSERT(SIZEOF(.rela) == 0,        "leftover relocations")

... this (and the construct making the section) would need
converting (or amending) too, as 32-bit uses .rel.*. Then

Reviewed-by: Jan Beulich <jbeulich@suse.com>

Jan
diff mbox series

Patch

diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile
index ca8001c72b23..09d1f9f75394 100644
--- a/xen/arch/x86/boot/Makefile
+++ b/xen/arch/x86/boot/Makefile
@@ -22,19 +22,8 @@  $(head-srcs): %.S: %.bin
 	(od -v -t x $< | tr -s ' ' | awk 'NR > 1 {print s} {s=$$0}' | \
 	sed 's/ /,0x/g' | sed 's/,0x$$//' | sed 's/^[0-9]*,/ .long /') >$@
 
-# Drop .got.plt during conversion to plain binary format.
-# Please check build32.lds for more details.
 %.bin: %.lnk
-	$(OBJDUMP) -h $< | sed -n '/[0-9]/{s,00*,0,g;p;}' | \
-		while read idx name sz rest; do \
-			case "$$name" in \
-			.got.plt) \
-				test $$sz != 0c || continue; \
-				echo "Error: non-empty $$name: 0x$$sz" >&2; \
-				exit $$(expr $$idx + 1);; \
-			esac; \
-		done
-	$(OBJCOPY) -O binary -R .got.plt $< $@
+	$(OBJCOPY) -j .text -O binary $< $@
 
 %.lnk: %.o $(src)/build32.lds
 	$(LD) $(subst x86_64,i386,$(LDFLAGS_DIRECT)) -N -T $(filter %.lds,$^) -o $@ $<
diff --git a/xen/arch/x86/boot/build32.lds b/xen/arch/x86/boot/build32.lds
index 1ab941879312..d8fb9170ca40 100644
--- a/xen/arch/x86/boot/build32.lds
+++ b/xen/arch/x86/boot/build32.lds
@@ -31,44 +31,36 @@  SECTIONS
         *(.bss.*)
   }
 
+  /* Dynamic linkage sections.  Collected simply so we can check they're empty. */
+  .got : {
+        *(.got)
+  }
   .got.plt : {
-        /*
-         * PIC/PIE executable contains .got.plt section even if it is not linked
-         * with dynamic libraries. In such case it is just placeholder for
-         * _GLOBAL_OFFSET_TABLE_ symbol and .PLT0. .PLT0 is filled by dynamic
-         * linker and our code is not supposed to be loaded by dynamic linker.
-         * So, from our point of view .PLT0 is unused. This means that there is
-         * pretty good chance that we can safely drop .got.plt as a whole here.
-         * Sadly this is not true. _GLOBAL_OFFSET_TABLE_ is used as a reference
-         * for relative addressing (and only for that thing) and ld complains if
-         * we remove .got.plt section here because it cannot find required symbol.
-         * However, _GLOBAL_OFFSET_TABLE_ is no longer needed in final output.
-         * So, drop .got.plt section during conversion to plain binary format.
-         *
-         * Please check build32.mk for more details.
-         */
         *(.got.plt)
   }
-
-  /*
-   * Discarding .shstrtab is not supported by LLD (LLVM LD) and will trigger an
-   * error. Also keep the rest of the control sections to match GNU LD behavior.
-   */
-  .shstrtab : {
-        *(.shstrtab)
+  .igot.plt : {
+        *(.igot.plt)
   }
-  .strtab : {
-        *(.strtab)
+  .iplt : {
+        *(.iplt)
   }
-  .symtab : {
-        *(.symtab)
+  .plt : {
+        *(.plt)
   }
-
-  /DISCARD/ : {
-        /*
-         * Discard everything else, to prevent linkers from putting
-         * orphaned sections ahead of .text, which needs to be first.
-         */
-        *(*)
+  .rela : {
+        *(.rela.*)
   }
 }
+
+ASSERT(SIZEOF(.got) == 0,         ".got non-empty")
+/*
+ * At least GNU ld 2.30 and earlier fail to discard the generic part of
+ * .got.plt when no actual entries were allocated. Permit this case alongside
+ * the section being empty.
+ */
+ASSERT(SIZEOF(.got.plt) == 0 ||
+       SIZEOF(.got.plt) == 3 * 4, "unexpected .got.plt size")
+ASSERT(SIZEOF(.igot.plt) == 0,    ".igot.plt non-empty")
+ASSERT(SIZEOF(.iplt) == 0,        ".iplt non-empty")
+ASSERT(SIZEOF(.plt) == 0,         ".plt non-empty")
+ASSERT(SIZEOF(.rela) == 0,        "leftover relocations")