[PATCH] x86/EFI: correct symbol table generation with older GNU ld

Jan Beulich posted 1 patch 2 weeks, 3 days ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/27f291a3-6546-4834-a9cd-22a4636b152e@suse.com
[PATCH] x86/EFI: correct symbol table generation with older GNU ld
Posted by Jan Beulich 2 weeks, 3 days ago
See the extensive code comment. This isn't really nice, but unless I'm
overlooking something there doesn't look to be a way to have the linker
strip individual symbols while doing its work.

Fixes: bf6501a62e80 ("x86-64: EFI boot code")
Reported-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
Should we try to somehow avoid the introduction of the two symbols when
using new enough ld, i.e. relocs-dummy.o not needing linking in?

--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -339,6 +339,24 @@ SECTIONS
     *(.reloc)
     __base_relocs_end = .;
   }
+
+  /*
+   * When efi/relocs-dummy.o is linked into the first-pass binary, the two
+   * symbols supplied by it (for ./Makefile to use) may appear in the symbol
+   * table (newer linkers strip them, for not being properly representable).
+   * No such symbols would appear during subsequent passes.  At least some of
+   * those older ld versions emit VIRT_START as absolute, but ALT_START as if
+   * it was part of .text.  The symbols tool generating our own symbol table
+   * would hence not ignore it when passed --all-symbols, leading to the 2nd
+   * pass binary having one more symbol than the final (3rd pass) one.
+   *
+   * Arrange for both (just in case) symbols to always be there, and to always
+   * be absolute (zero).
+   */
+  PROVIDE(VIRT_START = 0);
+  PROVIDE(ALT_START = 0);
+  VIRT_START &= 0;
+  ALT_START &= 0;
 #elif defined(XEN_BUILD_EFI)
   /*
    * Due to the way EFI support is currently implemented, these two symbols

Re: [PATCH] x86/EFI: correct symbol table generation with older GNU ld
Posted by Daniel P. Smith 1 week, 2 days ago
On 1/21/26 5:05 AM, Jan Beulich wrote:
> See the extensive code comment. This isn't really nice, but unless I'm
> overlooking something there doesn't look to be a way to have the linker
> strip individual symbols while doing its work.
> 
> Fixes: bf6501a62e80 ("x86-64: EFI boot code")
> Reported-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> ---
> Should we try to somehow avoid the introduction of the two symbols when
> using new enough ld, i.e. relocs-dummy.o not needing linking in?
> 
> --- a/xen/arch/x86/xen.lds.S
> +++ b/xen/arch/x86/xen.lds.S
> @@ -339,6 +339,24 @@ SECTIONS
>       *(.reloc)
>       __base_relocs_end = .;
>     }
> +
> +  /*
> +   * When efi/relocs-dummy.o is linked into the first-pass binary, the two
> +   * symbols supplied by it (for ./Makefile to use) may appear in the symbol
> +   * table (newer linkers strip them, for not being properly representable).

Just a suggestion, but do we have the minimal version where the 
stripping is handled properly? I just think it would be good to have the 
minimum version documented here. Doing so would make it easier that if 
the minimum supported build tools are bumped past this version, 
hopefully someone will either remember or notice the comment and could 
drop these declarations.

> +   * No such symbols would appear during subsequent passes.  At least some of
> +   * those older ld versions emit VIRT_START as absolute, but ALT_START as if
> +   * it was part of .text.  The symbols tool generating our own symbol table
> +   * would hence not ignore it when passed --all-symbols, leading to the 2nd
> +   * pass binary having one more symbol than the final (3rd pass) one.
> +   *
> +   * Arrange for both (just in case) symbols to always be there, and to always
> +   * be absolute (zero).
> +   */
> +  PROVIDE(VIRT_START = 0);
> +  PROVIDE(ALT_START = 0);
> +  VIRT_START &= 0;
> +  ALT_START &= 0;
>   #elif defined(XEN_BUILD_EFI)
>     /*
>      * Due to the way EFI support is currently implemented, these two symbols


With or without the suggestion,

Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>

Re: [PATCH] x86/EFI: correct symbol table generation with older GNU ld
Posted by Jan Beulich 1 week, 2 days ago
On 29.01.2026 15:44, Daniel P. Smith wrote:
> On 1/21/26 5:05 AM, Jan Beulich wrote:
>> See the extensive code comment. This isn't really nice, but unless I'm
>> overlooking something there doesn't look to be a way to have the linker
>> strip individual symbols while doing its work.
>>
>> Fixes: bf6501a62e80 ("x86-64: EFI boot code")
>> Reported-by: Roger Pau Monné <roger.pau@citrix.com>
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>> ---
>> Should we try to somehow avoid the introduction of the two symbols when
>> using new enough ld, i.e. relocs-dummy.o not needing linking in?
>>
>> --- a/xen/arch/x86/xen.lds.S
>> +++ b/xen/arch/x86/xen.lds.S
>> @@ -339,6 +339,24 @@ SECTIONS
>>       *(.reloc)
>>       __base_relocs_end = .;
>>     }
>> +
>> +  /*
>> +   * When efi/relocs-dummy.o is linked into the first-pass binary, the two
>> +   * symbols supplied by it (for ./Makefile to use) may appear in the symbol
>> +   * table (newer linkers strip them, for not being properly representable).
> 
> Just a suggestion, but do we have the minimal version where the 
> stripping is handled properly? I just think it would be good to have the 
> minimum version documented here. Doing so would make it easier that if 
> the minimum supported build tools are bumped past this version, 
> hopefully someone will either remember or notice the comment and could 
> drop these declarations.

I've changed this to "GNU ld 2.37 and newer strip them, ...". It's always
extra work to dig out version boundaries, and then the other toolchain
(clang/llvm) still isn't covered.

>> +   * No such symbols would appear during subsequent passes.  At least some of
>> +   * those older ld versions emit VIRT_START as absolute, but ALT_START as if
>> +   * it was part of .text.  The symbols tool generating our own symbol table
>> +   * would hence not ignore it when passed --all-symbols, leading to the 2nd
>> +   * pass binary having one more symbol than the final (3rd pass) one.
>> +   *
>> +   * Arrange for both (just in case) symbols to always be there, and to always
>> +   * be absolute (zero).
>> +   */
>> +  PROVIDE(VIRT_START = 0);
>> +  PROVIDE(ALT_START = 0);
>> +  VIRT_START &= 0;
>> +  ALT_START &= 0;
>>   #elif defined(XEN_BUILD_EFI)
>>     /*
>>      * Due to the way EFI support is currently implemented, these two symbols
> 
> With or without the suggestion,
> 
> Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>

Thanks.

Jan

Ping: [PATCH] x86/EFI: correct symbol table generation with older GNU ld
Posted by Jan Beulich 1 week, 3 days ago
On 21.01.2026 11:05, Jan Beulich wrote:
> See the extensive code comment. This isn't really nice, but unless I'm
> overlooking something there doesn't look to be a way to have the linker
> strip individual symbols while doing its work.
> 
> Fixes: bf6501a62e80 ("x86-64: EFI boot code")
> Reported-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

This is, afaict, the only left piece which prevents "symbols: check table
sizes don't change between linking passes 2 and 3" from going in. May I
therefore ask for an ack or comments to move this forward?

Thanks, Jan

> ---
> Should we try to somehow avoid the introduction of the two symbols when
> using new enough ld, i.e. relocs-dummy.o not needing linking in?
> 
> --- a/xen/arch/x86/xen.lds.S
> +++ b/xen/arch/x86/xen.lds.S
> @@ -339,6 +339,24 @@ SECTIONS
>      *(.reloc)
>      __base_relocs_end = .;
>    }
> +
> +  /*
> +   * When efi/relocs-dummy.o is linked into the first-pass binary, the two
> +   * symbols supplied by it (for ./Makefile to use) may appear in the symbol
> +   * table (newer linkers strip them, for not being properly representable).
> +   * No such symbols would appear during subsequent passes.  At least some of
> +   * those older ld versions emit VIRT_START as absolute, but ALT_START as if
> +   * it was part of .text.  The symbols tool generating our own symbol table
> +   * would hence not ignore it when passed --all-symbols, leading to the 2nd
> +   * pass binary having one more symbol than the final (3rd pass) one.
> +   *
> +   * Arrange for both (just in case) symbols to always be there, and to always
> +   * be absolute (zero).
> +   */
> +  PROVIDE(VIRT_START = 0);
> +  PROVIDE(ALT_START = 0);
> +  VIRT_START &= 0;
> +  ALT_START &= 0;
>  #elif defined(XEN_BUILD_EFI)
>    /*
>     * Due to the way EFI support is currently implemented, these two symbols