[PATCH v2] Arm: do a 4th linking pass if necessary

Jan Beulich posted 1 patch 2 days, 8 hours ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/59fc2b14-073b-42a6-8f30-503ad789fbab@suse.com
[PATCH v2] Arm: do a 4th linking pass if necessary
Posted by Jan Beulich 2 days, 8 hours ago
The .rodata growth between 1st and 2nd linking passes may affect the
number of stubs the linker wants to insert, which in turn affects the
number of symbols. If symbol table sizes change after the 2nd linking
pass, insert another one before the final one. (As a comment in Linux puts
it, "In theory it's possible this results in even more stubs, but
unlikely.")

To use the $(compare-symbol-tables) macro in a shell "if", it needs
slightly adjusting (and then wrapping to be run in a sub-shell).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
There's imo no good Fixes: tag, since (aiui) stubs (veneers) may also be
inserted for reasons other than errata workarounds.

For context: The Cortex A53 erratum 843419 workaround in GNU ld comes in
two flavors: In the general case a stub is inserted, but if the problem
ADRP can be replaced by ADR (i.e. the target symbol is within ±1Mb), then
that's preferred and no stub is needed. The addition of the symbol table
data is what then results in the stub-less form to no longer be usable in
affected configurations. A possible countermeasure could be to move
.rodata ahead of .text. (Also, from looking at generated code, it may well
be that newer gcc simply avoids producing problematic insn sequences.)

Linux simply compares object file sizes, but I consider that fragile: A
change in size of one of the symbol table constituents may not necessarily
change the object file size, due to padding which may be in use.

Once we generalize linking, we may want to introduce an equivalent of
Linux'es KALLSYMS_EXTRA_PASS as well. I don't think doing this right here
would make overly much sense, though.
---
v2: Add "set -e".

--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -99,9 +99,21 @@ $(TARGET)-syms: $(objtree)/prelink.o $(o
 		| $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
 		> $(dot-target).2.S
 	$(MAKE) $(build)=$(@D) $(dot-target).2.o
-	$(call compare-symbol-tables, $(dot-target).1.o, $(dot-target).2.o)
+	if ! { $(call compare-symbol-tables, $(dot-target).1.o, $(dot-target).2.o) >/dev/null; }; \
+	then \
+		set -e; \
+		$(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds $< $(build_id_linker) \
+		    $(dot-target).2.o -o $(dot-target).2; \
+		$(NM) -pa --format=sysv $(dot-target).2 \
+			| $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
+			> $(dot-target).3.S; \
+		$(MAKE) $(build)=$(@D) $(dot-target).3.o; \
+		$(call compare-symbol-tables, $(dot-target).2.o, $(dot-target).3.o); \
+	else \
+		ln -sf $(dot-target).2.o $(dot-target).3.o; \
+	fi
 	$(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds $< $(build_id_linker) \
-	    $(dot-target).2.o -o $@
+	    $(dot-target).3.o -o $@
 	$(NM) -pa --format=sysv $@ \
 		| $(objtree)/tools/symbols --all-symbols --xensyms --sysv --sort \
 		> $@.map
--- a/xen/scripts/Kbuild.include
+++ b/xen/scripts/Kbuild.include
@@ -65,7 +65,7 @@ define compare-symbol-tables
     $(OBJDUMP) -t $(@D)/.cst.$$$$ > $(1).sym; \
     ln -f $(2) $(@D)/.cst.$$$$; \
     $(OBJDUMP) -t $(@D)/.cst.$$$$ > $(2).sym; \
-    rm -f $(@D)/.cst.$$$$
+    rm -f $(@D)/.cst.$$$$; \
     diff -u $(1).sym $(2).sym
 endef
 

Re: [PATCH v2] Arm: do a 4th linking pass if necessary
Posted by Bertrand Marquis 2 days, 3 hours ago
Hi Jan,

> On 21 May 2026, at 14:02, Jan Beulich <jbeulich@suse.com> wrote:
> 
> The .rodata growth between 1st and 2nd linking passes may affect the
> number of stubs the linker wants to insert, which in turn affects the
> number of symbols. If symbol table sizes change after the 2nd linking
> pass, insert another one before the final one. (As a comment in Linux puts
> it, "In theory it's possible this results in even more stubs, but
> unlikely.")
> 
> To use the $(compare-symbol-tables) macro in a shell "if", it needs
> slightly adjusting (and then wrapping to be run in a sub-shell).
> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Acked-by: Bertrand Marquis <bertrand.marquis@arm.com>

Cheers
Bertrand

> ---
> There's imo no good Fixes: tag, since (aiui) stubs (veneers) may also be
> inserted for reasons other than errata workarounds.
> 
> For context: The Cortex A53 erratum 843419 workaround in GNU ld comes in
> two flavors: In the general case a stub is inserted, but if the problem
> ADRP can be replaced by ADR (i.e. the target symbol is within ±1Mb), then
> that's preferred and no stub is needed. The addition of the symbol table
> data is what then results in the stub-less form to no longer be usable in
> affected configurations. A possible countermeasure could be to move
> .rodata ahead of .text. (Also, from looking at generated code, it may well
> be that newer gcc simply avoids producing problematic insn sequences.)
> 
> Linux simply compares object file sizes, but I consider that fragile: A
> change in size of one of the symbol table constituents may not necessarily
> change the object file size, due to padding which may be in use.
> 
> Once we generalize linking, we may want to introduce an equivalent of
> Linux'es KALLSYMS_EXTRA_PASS as well. I don't think doing this right here
> would make overly much sense, though.
> ---
> v2: Add "set -e".
> 
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -99,9 +99,21 @@ $(TARGET)-syms: $(objtree)/prelink.o $(o
> | $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
> > $(dot-target).2.S
> $(MAKE) $(build)=$(@D) $(dot-target).2.o
> - $(call compare-symbol-tables, $(dot-target).1.o, $(dot-target).2.o)
> + if ! { $(call compare-symbol-tables, $(dot-target).1.o, $(dot-target).2.o) >/dev/null; }; \
> + then \
> + set -e; \
> + $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds $< $(build_id_linker) \
> +    $(dot-target).2.o -o $(dot-target).2; \
> + $(NM) -pa --format=sysv $(dot-target).2 \
> + | $(objtree)/tools/symbols $(all_symbols) --sysv --sort \
> + > $(dot-target).3.S; \
> + $(MAKE) $(build)=$(@D) $(dot-target).3.o; \
> + $(call compare-symbol-tables, $(dot-target).2.o, $(dot-target).3.o); \
> + else \
> + ln -sf $(dot-target).2.o $(dot-target).3.o; \
> + fi
> $(LD) $(XEN_LDFLAGS) -T $(obj)/xen.lds $< $(build_id_linker) \
> -    $(dot-target).2.o -o $@
> +    $(dot-target).3.o -o $@
> $(NM) -pa --format=sysv $@ \
> | $(objtree)/tools/symbols --all-symbols --xensyms --sysv --sort \
> > $@.map
> --- a/xen/scripts/Kbuild.include
> +++ b/xen/scripts/Kbuild.include
> @@ -65,7 +65,7 @@ define compare-symbol-tables
>     $(OBJDUMP) -t $(@D)/.cst.$$$$ > $(1).sym; \
>     ln -f $(2) $(@D)/.cst.$$$$; \
>     $(OBJDUMP) -t $(@D)/.cst.$$$$ > $(2).sym; \
> -    rm -f $(@D)/.cst.$$$$
> +    rm -f $(@D)/.cst.$$$$; \
>     diff -u $(1).sym $(2).sym
> endef
> 

Re: [PATCH v2] Arm: do a 4th linking pass if necessary
Posted by Anthony PERARD 2 days, 7 hours ago
On Thu, May 21, 2026 at 02:02:59PM +0200, Jan Beulich wrote:
> The .rodata growth between 1st and 2nd linking passes may affect the
> number of stubs the linker wants to insert, which in turn affects the
> number of symbols. If symbol table sizes change after the 2nd linking
> pass, insert another one before the final one. (As a comment in Linux puts
> it, "In theory it's possible this results in even more stubs, but
> unlikely.")
> 
> To use the $(compare-symbol-tables) macro in a shell "if", it needs
> slightly adjusting (and then wrapping to be run in a sub-shell).
> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>

Thanks,


-- 
Anthony Perard | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech