diff mbox series

[v2,23/30] sandbox: Augment the linker script for MSYS2

Message ID 20230430013003.1047454-24-sjg@chromium.org
State Changes Requested
Delegated to: Tom Rini
Headers show
Series Allow building sandbox with MSYS2 | expand

Commit Message

Simon Glass April 30, 2023, 1:29 a.m. UTC
We need to place the linker lists, etc. in the .rdata section but this
is not possible with the default linker script. We can only add new
sections, which causes Windows to give an "Exec format error" error.

Add a rule to create a new linker script, by obtaining the one from
the linker and adding some things to the end of the .rdata section.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v2:
- Add an awk script to augment the built-in link script

 Makefile                          | 17 ++++++++++++-----
 arch/sandbox/config.mk            | 19 ++++++++++++++++++-
 arch/sandbox/cpu/u-boot-pe.lds.in | 25 +++++++++++++++++++++++++
 scripts/add_to_rdata.awk          | 25 +++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 6 deletions(-)
 create mode 100644 arch/sandbox/cpu/u-boot-pe.lds.in
 create mode 100644 scripts/add_to_rdata.awk

Comments

Bin Meng May 3, 2023, 4:29 a.m. UTC | #1
Hi Simon,

On Sun, Apr 30, 2023 at 9:30 AM Simon Glass <sjg@chromium.org> wrote:
>
> We need to place the linker lists, etc. in the .rdata section but this
> is not possible with the default linker script. We can only add new
> sections, which causes Windows to give an "Exec format error" error.
>
> Add a rule to create a new linker script, by obtaining the one from
> the linker and adding some things to the end of the .rdata section.

I am not sure I understand this. So the arch/sandbox/cpu/u-boot.lds
does not work for MSYS2?

>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v2:
> - Add an awk script to augment the built-in link script
>
>  Makefile                          | 17 ++++++++++++-----
>  arch/sandbox/config.mk            | 19 ++++++++++++++++++-
>  arch/sandbox/cpu/u-boot-pe.lds.in | 25 +++++++++++++++++++++++++
>  scripts/add_to_rdata.awk          | 25 +++++++++++++++++++++++++
>  4 files changed, 80 insertions(+), 6 deletions(-)
>  create mode 100644 arch/sandbox/cpu/u-boot-pe.lds.in
>  create mode 100644 scripts/add_to_rdata.awk
>
> diff --git a/Makefile b/Makefile
> index a328652f0f23..760c143049aa 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1734,6 +1734,12 @@ else
>  u-boot-keep-syms-lto :=
>  endif
>
> +ifeq ($(MSYS_VERSION),0)
> +add_ld_script := -T u-boot.lds
> +else
> +add_ld_script := u-boot.lds

MSYS2 does not need "-T"?

> +endif
> +
>  # Rule to link u-boot
>  # May be overridden by arch/$(ARCH)/config.mk
>  ifeq ($(LTO_ENABLE),y)
> @@ -1742,7 +1748,7 @@ quiet_cmd_u-boot__ ?= LTO     $@
>                 $(CC) -nostdlib -nostartfiles                                   \
>                 $(LTO_FINAL_LDFLAGS) $(c_flags)                                 \
>                 $(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@       \
> -               -T u-boot.lds $(u-boot-init)                                    \
> +               $(add_ld_script) $(u-boot-init)                                 \
>                 -Wl,--whole-archive                                             \
>                         $(u-boot-main)                                          \
>                         $(u-boot-keep-syms-lto)                                 \
> @@ -1753,7 +1759,7 @@ quiet_cmd_u-boot__ ?= LTO     $@
>  else
>  quiet_cmd_u-boot__ ?= LD      $@
>        cmd_u-boot__ ?= $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_u-boot) -o $@          \
> -               -T u-boot.lds $(u-boot-init)                                    \
> +               $(add_ld_script) $(u-boot-init)                                 \
>                 --whole-archive                                                 \
>                         $(u-boot-main)                                          \
>                 --no-whole-archive                                              \
> @@ -1905,10 +1911,11 @@ endif
>  # prepare2 creates a makefile if using a separate output directory
>  prepare2: prepare3 outputmakefile cfg
>
> +# Allow the linker script to be generated from LDSCRIPT_IN
>  prepare1: prepare2 $(version_h) $(timestamp_h) $(dt_h) $(env_h) \
> -                   include/config/auto.conf
> -ifeq ($(wildcard $(LDSCRIPT)),)
> -       @echo >&2 "  Could not find linker script."
> +                   include/config/auto.conf $(if $(LDSCRIPT_IN),$(LDSCRIPT))
> +ifeq ($(wildcard $(LDSCRIPT))$(LDSCRIPT_IN),)
> +       @echo >&2 "  Could not find linker script $(LDSCRIPT)"
>         @/bin/false
>  endif
>
> diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
> index 2d184c5f652a..c97c39d4301b 100644
> --- a/arch/sandbox/config.mk
> +++ b/arch/sandbox/config.mk
> @@ -1,4 +1,4 @@
> -# SPDX-License-Identifier: GPL-2.0+
> +       # SPDX-License-Identifier: GPL-2.0+
>  # Copyright (c) 2011 The Chromium OS Authors.
>
>  PLATFORM_CPPFLAGS += -D__SANDBOX__ -U_FORTIFY_SOURCE
> @@ -71,3 +71,20 @@ EFI_CRT0 := crt0_sandbox_efi.o
>  EFI_RELOC := reloc_sandbox_efi.o
>  AFLAGS_crt0_sandbox_efi.o += -DHOST_ARCH="$(HOST_ARCH)"
>  CFLAGS_reloc_sandbox_efi.o += -DHOST_ARCH="$(HOST_ARCH)"
> +
> +ifneq ($(MSYS_VERSION),0)
> +LDSCRIPT := $(objtree)/u-boot-pe.lds
> +
> +AWK_RDATA := ${srctree}/scripts/add_to_rdata.awk
> +LDSCRIPT_IN := ${srctree}/arch/sandbox/cpu/u-boot-pe.lds.in
> +
> +quiet_cmd_gen_lds = GEN LDS $@
> +cmd_gen_lds = echo "int main() { return 0; }" | $(CC) -x c - -Wl,-verbose | \
> +               awk -f $(AWK_RDATA) -v INFILE=$< >$@
> +
> +# Write out the contents of INFILE immediately before the close of the .rdata
> +# block
> +$(LDSCRIPT): $(LDSCRIPT_IN) $(AWK_RDATA) FORCE
> +       $(call if_changed,gen_lds)
> +
> +endif
> diff --git a/arch/sandbox/cpu/u-boot-pe.lds.in b/arch/sandbox/cpu/u-boot-pe.lds.in
> new file mode 100644
> index 000000000000..0ec7ef3bb350
> --- /dev/null
> +++ b/arch/sandbox/cpu/u-boot-pe.lds.in
> @@ -0,0 +1,25 @@
> +       /* U-Boot additions from here on */
> +       . = ALIGN(4);
> +       KEEP(*(SORT(__u_boot_list*)));
> +
> +       *(_u_boot_sandbox_getopt_start)
> +       *(_u_boot_sandbox_getopt)
> +       *(_u_boot_sandbox_getopt_end)
> +
> +       *(___efi_runtime_start)
> +       *(efi_runtime_text)
> +       *(efi_runtime_data)
> +       *(___efi_runtime_stop)
> +
> +       *(___efi_runtime_rel_start)
> +       *(.relefi_runtime_text)
> +       *(.relefi_runtime_data)
> +       *(___efi_runtime_rel_stop)
> +
> +       . = ALIGN(4);
> +       *(.rodata.ttf.init)
> +       *(.rodata.splash.init)
> +       *(.rodata.helloworld.init)
> +       *(.dtb.init.rodata)
> +
> +       /* U-Boot additions end */
> diff --git a/scripts/add_to_rdata.awk b/scripts/add_to_rdata.awk
> new file mode 100644
> index 000000000000..43fdfe8bb789
> --- /dev/null
> +++ b/scripts/add_to_rdata.awk
> @@ -0,0 +1,25 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# Copyright 2023 Google, Inc
> +#
> +# Awk script to extract the default link script from the linker and write out
> +# the contents of INFILE immediately before the close of the .rdata section.
> +
> +# to a C string which can be compiled into U-Boot.
> +
> +# INS = 1 if we are inside the link script (delimited by ======== lines)
> +# INR = 1 if we are inside the .rdata section
> +
> +# When we see } while in the .rdata part of the link script, insert INFILE
> +/}/ { if (INS && INR) { while ((getline < INFILE) > 0) {print}; DONE=1; INR=0; $0="}"; }}
> +
> +# Find start and end of link script
> +/===================/ { if (INS) exit; INS=1; next; }
> +
> +# If inside the link script, print each line
> +{ if (INS) print; }
> +
> +# Detect the .rdata section and get ready to insert INFILE when we see the end }
> +/\.rdata.*:/ {INR=1; }
> +
> +END { if (!DONE) { print "add_to_rdata.awk: Could not find link script in ld output" > "/dev/stderr"; exit 1;} }
> --

Regards,
Bin
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index a328652f0f23..760c143049aa 100644
--- a/Makefile
+++ b/Makefile
@@ -1734,6 +1734,12 @@  else
 u-boot-keep-syms-lto :=
 endif
 
+ifeq ($(MSYS_VERSION),0)
+add_ld_script := -T u-boot.lds
+else
+add_ld_script := u-boot.lds
+endif
+
 # Rule to link u-boot
 # May be overridden by arch/$(ARCH)/config.mk
 ifeq ($(LTO_ENABLE),y)
@@ -1742,7 +1748,7 @@  quiet_cmd_u-boot__ ?= LTO     $@
 		$(CC) -nostdlib -nostartfiles					\
 		$(LTO_FINAL_LDFLAGS) $(c_flags)					\
 		$(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@	\
-		-T u-boot.lds $(u-boot-init)					\
+		$(add_ld_script) $(u-boot-init)					\
 		-Wl,--whole-archive						\
 			$(u-boot-main)						\
 			$(u-boot-keep-syms-lto)					\
@@ -1753,7 +1759,7 @@  quiet_cmd_u-boot__ ?= LTO     $@
 else
 quiet_cmd_u-boot__ ?= LD      $@
       cmd_u-boot__ ?= $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_u-boot) -o $@		\
-		-T u-boot.lds $(u-boot-init)					\
+		$(add_ld_script) $(u-boot-init)					\
 		--whole-archive							\
 			$(u-boot-main)						\
 		--no-whole-archive						\
@@ -1905,10 +1911,11 @@  endif
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile cfg
 
+# Allow the linker script to be generated from LDSCRIPT_IN
 prepare1: prepare2 $(version_h) $(timestamp_h) $(dt_h) $(env_h) \
-                   include/config/auto.conf
-ifeq ($(wildcard $(LDSCRIPT)),)
-	@echo >&2 "  Could not find linker script."
+                   include/config/auto.conf $(if $(LDSCRIPT_IN),$(LDSCRIPT))
+ifeq ($(wildcard $(LDSCRIPT))$(LDSCRIPT_IN),)
+	@echo >&2 "  Could not find linker script $(LDSCRIPT)"
 	@/bin/false
 endif
 
diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk
index 2d184c5f652a..c97c39d4301b 100644
--- a/arch/sandbox/config.mk
+++ b/arch/sandbox/config.mk
@@ -1,4 +1,4 @@ 
-# SPDX-License-Identifier: GPL-2.0+
+	# SPDX-License-Identifier: GPL-2.0+
 # Copyright (c) 2011 The Chromium OS Authors.
 
 PLATFORM_CPPFLAGS += -D__SANDBOX__ -U_FORTIFY_SOURCE
@@ -71,3 +71,20 @@  EFI_CRT0 := crt0_sandbox_efi.o
 EFI_RELOC := reloc_sandbox_efi.o
 AFLAGS_crt0_sandbox_efi.o += -DHOST_ARCH="$(HOST_ARCH)"
 CFLAGS_reloc_sandbox_efi.o += -DHOST_ARCH="$(HOST_ARCH)"
+
+ifneq ($(MSYS_VERSION),0)
+LDSCRIPT := $(objtree)/u-boot-pe.lds
+
+AWK_RDATA := ${srctree}/scripts/add_to_rdata.awk
+LDSCRIPT_IN := ${srctree}/arch/sandbox/cpu/u-boot-pe.lds.in
+
+quiet_cmd_gen_lds = GEN LDS $@
+cmd_gen_lds = echo "int main() { return 0; }" | $(CC) -x c - -Wl,-verbose | \
+		awk -f $(AWK_RDATA) -v INFILE=$< >$@
+
+# Write out the contents of INFILE immediately before the close of the .rdata
+# block
+$(LDSCRIPT): $(LDSCRIPT_IN) $(AWK_RDATA) FORCE
+	$(call if_changed,gen_lds)
+
+endif
diff --git a/arch/sandbox/cpu/u-boot-pe.lds.in b/arch/sandbox/cpu/u-boot-pe.lds.in
new file mode 100644
index 000000000000..0ec7ef3bb350
--- /dev/null
+++ b/arch/sandbox/cpu/u-boot-pe.lds.in
@@ -0,0 +1,25 @@ 
+	/* U-Boot additions from here on */
+	. = ALIGN(4);
+	KEEP(*(SORT(__u_boot_list*)));
+
+	*(_u_boot_sandbox_getopt_start)
+	*(_u_boot_sandbox_getopt)
+	*(_u_boot_sandbox_getopt_end)
+
+	*(___efi_runtime_start)
+	*(efi_runtime_text)
+	*(efi_runtime_data)
+	*(___efi_runtime_stop)
+
+	*(___efi_runtime_rel_start)
+	*(.relefi_runtime_text)
+	*(.relefi_runtime_data)
+	*(___efi_runtime_rel_stop)
+
+	. = ALIGN(4);
+	*(.rodata.ttf.init)
+	*(.rodata.splash.init)
+	*(.rodata.helloworld.init)
+	*(.dtb.init.rodata)
+
+	/* U-Boot additions end */
diff --git a/scripts/add_to_rdata.awk b/scripts/add_to_rdata.awk
new file mode 100644
index 000000000000..43fdfe8bb789
--- /dev/null
+++ b/scripts/add_to_rdata.awk
@@ -0,0 +1,25 @@ 
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2023 Google, Inc
+#
+# Awk script to extract the default link script from the linker and write out
+# the contents of INFILE immediately before the close of the .rdata section.
+
+# to a C string which can be compiled into U-Boot.
+
+# INS = 1 if we are inside the link script (delimited by ======== lines)
+# INR = 1 if we are inside the .rdata section
+
+# When we see } while in the .rdata part of the link script, insert INFILE
+/}/ { if (INS && INR) { while ((getline < INFILE) > 0) {print}; DONE=1; INR=0; $0="}"; }}
+
+# Find start and end of link script
+/===================/ { if (INS) exit; INS=1; next; }
+
+# If inside the link script, print each line
+{ if (INS) print; }
+
+# Detect the .rdata section and get ready to insert INFILE when we see the end }
+/\.rdata.*:/ {INR=1; }
+
+END { if (!DONE) { print "add_to_rdata.awk: Could not find link script in ld output" > "/dev/stderr"; exit 1;} }