Question about deduplication of COMDAT sections with different alignment

Jens Remus jremus@linux.ibm.com
Wed May 21 15:21:55 GMT 2025


On 20.05.2025 17:38, Jan Beulich wrote:
> On 20.05.2025 17:19, Jens Remus wrote:
>> On 20.05.2025 16:01, Jan Beulich wrote:
>>> On 20.05.2025 15:49, Jens Remus wrote:
>>>> On 16.05.2025 15:24, Jens Remus wrote:
>>>>> Shouldn't the linker retain the maximum section alignment when
>>>>> deduplicating COMDAT sections with the same group signature, but
>>>>> different section alignment?
>>>>
>>>> Following is a minimal example showing the issue:
>>>>
>>>> $ cat sample.sh
>>>> #!/bin/bash
>>>> set -e -u -x
>>>>
>>>> AS="${AS:-as}"
>>>> LD="${LD:-ld}"
>>>> READELF="${READELF:-readelf}"
>>>>
>>>> cat <<EOF > sample.s
>>>>         .text
>>>>         .globl _start
>>>> _start:
>>>>         nop
>>>>
>>>>         .data
>>>> pfoo:   .quad foo
>>>> EOF
>>>>
>>>> cat <<EOF > foo-1.s
>>>>         .section .rodata.foo,"aG",@progbits,foo_group,comdat
>>>>         .align 1
>>>>         .globl foo
>>>>         .type foo,@object
>>>> foo:
>>>>         .byte 1
>>>>         .size foo, .-foo
>>>> EOF
>>>>
>>>> cat <<EOF > foo-2.s
>>>>         .section .rodata.foo,"aG",@progbits,foo_group,comdat
>>>>         .align 2
>>>>         .globl foo
>>>>         .type foo,@object
>>>> foo:
>>>>         .byte 2
>>>>         .size foo, .-foo
>>>> EOF
>>>>
>>>> $AS -o sample.o sample.s
>>>> $AS -o foo-1.o foo-1.s
>>>> $AS -o foo-2.o foo-2.s
>>>> $LD -o sample-12 sample.o foo-1.o foo-2.o
>>>> $LD -o sample-21 sample.o foo-2.o foo-1.o
>>>> $READELF -WS foo-1.o foo-2.o sample-12 sample-21 | grep -E "File:|\[Nr\]|\.rodata"
>>>>
>>>> $ ./sample.sh
>>>> [output truncated and reformatted]
>>>> File      Name        Off    Size   ES Flg Lk Inf Al
>>>> foo-1.o   .rodata.foo 000048 000001 00  AG  0   0  1
>>>> foo-2.o   .rodata.foo 000048 000002 00  AG  0   0  2
>>>> sample-12 .rodata     0000b4 000001 00   A  0   0  1 <-- !
>>>> sample-21 .rodata     0000b4 000002 00   A  0   0  2
>>>>
>>>> Shouldn't section .rodata in both sample-12 and sample-21 better have a
>>>> 2-byte alignment, regardless of which instance of COMDAT section group
>>>> foo_group got deduplicated?  After all code in foo-2.o (not part of this
>>>> example) may rely on foo being 2-byte aligned.
>>>
>>> Well. I may need to look into this in more detail, but one aspect right away:
>>> Generally the expectation is that any of the instances can be picked, on the
>>> basis that they're all functionally equivalent. While it's conceivable that
>>> code (insn sequences) may differ across instances, I find it more difficult
>>> to see how data (i.e. value, size, and alignment) could sensibly be different.
>>
>> I agree that for data the value and size should be identical.  In my
>> example I only used different values for debugging purposes to see
>> which instance remains and which one gets discarded.  In practice the
>> assembler pads the section size to a multiple of the section alignment,
>> unless assembler option --no-pad-sections is used, which explains the
>> difference in section size.
>> For code (e.g. C++ inline function) value and size are likely to be
>> different if different compilers are used, although functionality
>> should never the less be identical.  Is mixing compilers a no-go?
> 
> It shouldn't be in theory, but you may run into unexpected issues, as such
> mixing likely isn't tested very heavily.
> 
>> In the reported issue (described in my initial post) C++ code compiled
>> with Clang and GCC was mixed and C++ type information (data) had same
>> value and size (the symbols had the same size), but different alignment.
>> Luckily the code from both modules did not rely on that alignment.  It
>> was an erroneous GOT access relaxation in the linker that caused issues
>> with the alignment.  This would not have been any issue, if the linker
>> would have used the highest alignment for each deduplicated COMDAT
>> section group.
>>
>> If COMDAT section groups with same group signature with different
>> alignment would be considered a no-go, then the linker should maybe
>> alternatively print a warning?
> 
> It's again data vs code that we first need to distinguish. I don't think
> there should be a warning for code disagreeing on alignment. That may
> simply be a result of different optimization levels used when the
> different instances were compiled. For data, perhaps there should be a
> warning (not just about disagreeing alignment, but perhaps also about
> disagreeing size, and maybe even different values). Thing is - I'm
> unaware of a properly spelled out spec as to how COMDAT is to work
> (with all corner cases - like this one - covered).
> 
> And then, with (r/o) data and code mixed in a section, how would you
> tell apart the two cases?

Given there is apparently no spec and things apparently work mostly fine
as they are currently implemented:  Wouldn't using the highest alignment
for each COMDAT section then be the most reasonable and least intrusive
change to resolve potential issues with code relying on a particular
COMDAT section alignment?

In my other reply to Alan I am showing an example how to trigger the
issue using plain C++ code without any linker GOT access relaxation
involvement.  Of course that would go away once we fix Clang on S390
align the emitted COMDAT section to ensure symbol value alignment on
2-byte boundary, as mandated by the s390x (64-bit) ELF ABI.

Thanks and regards,
Jens
-- 
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com

IBM

IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/



More information about the Binutils mailing list