Re: gcc behavior of init priority of .ctors and .dtors section

2024-06-04 Thread John Baldwin

On 5/16/24 4:05 PM, Lorenzo Salvadore wrote:

On Thursday, May 16th, 2024 at 20:26, Konstantin Belousov  
wrote:

gcc13 from ports
`# gcc ctors.c && ./a.out init 1 init 2 init 5 init 4 init 3 main fini 3 fini 4 
fini 5 fini 2 fini 1`

The above order is not expected. I think clang's one is correct.

Further hacking with readelf shows that clang produces the right order of
section .rela.ctors but gcc does not.

```
# clang -fno-use-init-array -c ctors.c && readelf -r ctors.o | grep 'Relocation 
section with addend (.rela.ctors)' -A5 > clang.txt
# gcc -c ctors.c && readelf -r ctors.o | grep 'Relocation section with addend 
(.rela.ctors)' -A5 > gcc.txt
# diff clang.txt gcc.txt
3,5c3,5
<  00080001 R_X86_64_64 0060 init_65535_2 + 0
< 0008 00070001 R_X86_64_64 0040 init + 0
< 0010 00060001 R_X86_64_64 0020 init_65535 + 0
---


 00060001 R_X86_64_64 0011 init_65535 + 0
0008 00070001 R_X86_64_64 0022 init + 0
0010 00080001 R_X86_64_64 0033 init_65535_2 + 0
```


The above show clearly gcc produces the wrong order of section `.rela.ctors`.

Is that expected behavior ?

I have not tried Linux version of gcc.


Note that init array vs. init function behavior is encoded by a note added
by crt1.o. I suspect that the problem is that gcc port is built without
--enable-initfini-array configure option.


Indeed, support for .init_array and .fini_array has been added to the GCC ports
but is present in the *-devel ports only for now. I will
soon proceed to enable it for the GCC standard ports too. lang/gcc14 is soon
to be added to the ports tree and will have it since the beginning.

If this is indeed the issue, switching to a -devel GCC port should fix it.


FWIW, the devel/freebsd-gcc* ports have passed this flag to GCC's configure
for a long time (since we made the switch in clang).

--
John Baldwin




Re: gcc behavior of init priority of .ctors and .dtors section

2024-05-16 Thread Zhenlei Huang


> On May 17, 2024, at 2:26 AM, Konstantin Belousov  wrote:
> 
> On Thu, May 16, 2024 at 08:06:46PM +0800, Zhenlei Huang wrote:
>> Hi,
>> 
>> I'm recently working on https://reviews.freebsd.org/D45194 and got noticed
>> that gcc behaves weirdly.
>> 
>> A simple source file to demonstrate that.
>> 
>> ```
>> # cat ctors.c
>> 
>> #include 
>> 
>> __attribute__((constructor(101))) void init_101() { puts("init 1"); }
>> __attribute__((constructor(65535))) void init_65535() { puts("init 3"); }
>> __attribute__((constructor)) void init() { puts("init 4"); }
>> __attribute__((constructor(65535))) void init_65535_2() { puts("init 5"); }
>> __attribute__((constructor(65534))) void init_65534() { puts("init 2"); }
>> 
>> int main() { puts("main"); }
>> 
>> __attribute__((destructor(65534))) void fini_65534() { puts("fini 2"); }
>> __attribute__((destructor(65535))) void fini_65535() { puts("fini 3"); }
>> __attribute__((destructor)) void fini() { puts("fini 4"); }
>> __attribute__((destructor(65535))) void fini_65535_2() { puts("fini 5"); }
>> __attribute__((destructor(101))) void fini_101() { puts("fini 1"); }
>> 
>> # clang ctors.c && ./a.out
>> init 1
>> init 2
>> init 3
>> init 4
>> init 5
>> main
>> fini 5
>> fini 4
>> fini 3
>> fini 2
>> fini 1
>> ```
>> 
>> clang with the option -fno-use-init-array and run will produce the same 
>> result, which
>> is what I expected.
> Why do you add that switch?

gcc13 in ports is not configured with option --enable-initfini-array then it 
only produces .ctors / .dtors sections but
not .init_array / .fini_array sections. So I add that switch for clang to 
produce `.ctors` sections instead as
a baseline ( .ctors produced by clang indeed works as expected, the same with 
.init_array ).

> 
>> 
>> gcc13 from ports
>> ```
>> # gcc ctors.c && ./a.out
>> init 1
>> init 2
>> init 5
>> init 4
>> init 3
>> main
>> fini 3
>> fini 4
>> fini 5
>> fini 2
>> fini 1
>> ```
>> 
>> The above order is not expected. I think clang's one is correct.
>> 
>> Further hacking with readelf shows that clang produces the right order of
>> section .rela.ctors but gcc does not.
>> 
>> ```
>> # clang -fno-use-init-array -c ctors.c && readelf -r ctors.o | grep 
>> 'Relocation section with addend (.rela.ctors)' -A5 > clang.txt
>> # gcc -c ctors.c && readelf -r ctors.o | grep 'Relocation section with 
>> addend (.rela.ctors)' -A5 > gcc.txt
>> # diff clang.txt gcc.txt
>> 3,5c3,5
>> <  00080001 R_X86_64_64 0060 
>> init_65535_2 + 0
>> < 0008 00070001 R_X86_64_64 0040 init + 0
>> < 0010 00060001 R_X86_64_64 0020 init_65535 
>> + 0
>> ---
>>>  00060001 R_X86_64_64 0011 init_65535 + >>> 0
>>> 0008 00070001 R_X86_64_64 0022 init + 0
>>> 0010 00080001 R_X86_64_64 0033 init_65535_2 
>>> + 0
>> ```
>> 
>> The above show clearly gcc produces the wrong order of section `.rela.ctors`.
>> 
>> Is that expected behavior ?
>> 
>> I have not tried Linux version of gcc.
> Note that init array vs. init function behavior is encoded by a note added
> by crt1.o.  I suspect that the problem is that gcc port is built without
> --enable-initfini-array configure option.





Re: gcc behavior of init priority of .ctors and .dtors section

2024-05-16 Thread Konstantin Belousov
On Thu, May 16, 2024 at 08:05:57PM +, Lorenzo Salvadore wrote:
> On Thursday, May 16th, 2024 at 20:26, Konstantin Belousov 
>  wrote:
> > > gcc13 from ports
> > > `# gcc ctors.c && ./a.out init 1 init 2 init 5 init 4 init 3 main fini 3 
> > > fini 4 fini 5 fini 2 fini 1`
> > > 
> > > The above order is not expected. I think clang's one is correct.
> > > 
> > > Further hacking with readelf shows that clang produces the right order of
> > > section .rela.ctors but gcc does not.
> > > 
> > > ```
> > > # clang -fno-use-init-array -c ctors.c && readelf -r ctors.o | grep 
> > > 'Relocation section with addend (.rela.ctors)' -A5 > clang.txt
> > > # gcc -c ctors.c && readelf -r ctors.o | grep 'Relocation section with 
> > > addend (.rela.ctors)' -A5 > gcc.txt
> > > # diff clang.txt gcc.txt
> > > 3,5c3,5
> > > <  00080001 R_X86_64_64 0060 init_65535_2 + 0
> > > < 0008 00070001 R_X86_64_64 0040 init + 0
> > > < 0010 00060001 R_X86_64_64 0020 init_65535 + 0
> > > ---
> > > 
> > > >  00060001 R_X86_64_64 0011 init_65535 + 0
> > > > 0008 00070001 R_X86_64_64 0022 init + 0
> > > > 0010 00080001 R_X86_64_64 0033 init_65535_2 + 0
> > > > ```
> > > 
> > > The above show clearly gcc produces the wrong order of section 
> > > `.rela.ctors`.
> > > 
> > > Is that expected behavior ?
> > > 
> > > I have not tried Linux version of gcc.
> > 
> > Note that init array vs. init function behavior is encoded by a note added
> > by crt1.o. I suspect that the problem is that gcc port is built without
> > --enable-initfini-array configure option.
> 
> Indeed, support for .init_array and .fini_array has been added to the GCC 
> ports
> but is present in the *-devel ports only for now. I will
> soon proceed to enable it for the GCC standard ports too. lang/gcc14 is soon
> to be added to the ports tree and will have it since the beginning.
It is not 'support', but a bug.  For very long time, crt1.o instructs rtld
to use initarray instead of initfunc.  gcc generates broken binaries trying
to use initfunc.

> 
> If this is indeed the issue, switching to a -devel GCC port should fix it.
> 
> Cheers,
> 
> Lorenzo Salvadore



Re: gcc behavior of init priority of .ctors and .dtors section

2024-05-16 Thread Lorenzo Salvadore
On Thursday, May 16th, 2024 at 20:26, Konstantin Belousov  
wrote:
> > gcc13 from ports
> > `# gcc ctors.c && ./a.out init 1 init 2 init 5 init 4 init 3 main fini 3 
> > fini 4 fini 5 fini 2 fini 1`
> > 
> > The above order is not expected. I think clang's one is correct.
> > 
> > Further hacking with readelf shows that clang produces the right order of
> > section .rela.ctors but gcc does not.
> > 
> > ```
> > # clang -fno-use-init-array -c ctors.c && readelf -r ctors.o | grep 
> > 'Relocation section with addend (.rela.ctors)' -A5 > clang.txt
> > # gcc -c ctors.c && readelf -r ctors.o | grep 'Relocation section with 
> > addend (.rela.ctors)' -A5 > gcc.txt
> > # diff clang.txt gcc.txt
> > 3,5c3,5
> > <  00080001 R_X86_64_64 0060 init_65535_2 + 0
> > < 0008 00070001 R_X86_64_64 0040 init + 0
> > < 0010 00060001 R_X86_64_64 0020 init_65535 + 0
> > ---
> > 
> > >  00060001 R_X86_64_64 0011 init_65535 + 0
> > > 0008 00070001 R_X86_64_64 0022 init + 0
> > > 0010 00080001 R_X86_64_64 0033 init_65535_2 + 0
> > > ```
> > 
> > The above show clearly gcc produces the wrong order of section 
> > `.rela.ctors`.
> > 
> > Is that expected behavior ?
> > 
> > I have not tried Linux version of gcc.
> 
> Note that init array vs. init function behavior is encoded by a note added
> by crt1.o. I suspect that the problem is that gcc port is built without
> --enable-initfini-array configure option.

Indeed, support for .init_array and .fini_array has been added to the GCC ports
but is present in the *-devel ports only for now. I will
soon proceed to enable it for the GCC standard ports too. lang/gcc14 is soon
to be added to the ports tree and will have it since the beginning.

If this is indeed the issue, switching to a -devel GCC port should fix it.

Cheers,

Lorenzo Salvadore



Re: gcc behavior of init priority of .ctors and .dtors section

2024-05-16 Thread Konstantin Belousov
On Thu, May 16, 2024 at 08:06:46PM +0800, Zhenlei Huang wrote:
> Hi,
> 
> I'm recently working on https://reviews.freebsd.org/D45194 and got noticed
> that gcc behaves weirdly.
> 
> A simple source file to demonstrate that.
> 
> ```
> # cat ctors.c
> 
> #include 
> 
> __attribute__((constructor(101))) void init_101() { puts("init 1"); }
> __attribute__((constructor(65535))) void init_65535() { puts("init 3"); }
> __attribute__((constructor)) void init() { puts("init 4"); }
> __attribute__((constructor(65535))) void init_65535_2() { puts("init 5"); }
> __attribute__((constructor(65534))) void init_65534() { puts("init 2"); }
> 
> int main() { puts("main"); }
> 
> __attribute__((destructor(65534))) void fini_65534() { puts("fini 2"); }
> __attribute__((destructor(65535))) void fini_65535() { puts("fini 3"); }
> __attribute__((destructor)) void fini() { puts("fini 4"); }
> __attribute__((destructor(65535))) void fini_65535_2() { puts("fini 5"); }
> __attribute__((destructor(101))) void fini_101() { puts("fini 1"); }
> 
> # clang ctors.c && ./a.out
> init 1
> init 2
> init 3
> init 4
> init 5
> main
> fini 5
> fini 4
> fini 3
> fini 2
> fini 1
> ```
> 
> clang with the option -fno-use-init-array and run will produce the same 
> result, which
> is what I expected.
Why do you add that switch?

> 
> gcc13 from ports
> ```
> # gcc ctors.c && ./a.out
> init 1
> init 2
> init 5
> init 4
> init 3
> main
> fini 3
> fini 4
> fini 5
> fini 2
> fini 1
> ```
> 
> The above order is not expected. I think clang's one is correct.
> 
> Further hacking with readelf shows that clang produces the right order of
> section .rela.ctors but gcc does not.
> 
> ```
> # clang -fno-use-init-array -c ctors.c && readelf -r ctors.o | grep 
> 'Relocation section with addend (.rela.ctors)' -A5 > clang.txt
> # gcc -c ctors.c && readelf -r ctors.o | grep 'Relocation section with addend 
> (.rela.ctors)' -A5 > gcc.txt
> # diff clang.txt gcc.txt
> 3,5c3,5
> <  00080001 R_X86_64_64 0060 init_65535_2 
> + 0
> < 0008 00070001 R_X86_64_64 0040 init + 0
> < 0010 00060001 R_X86_64_64 0020 init_65535 + > 0
> ---
> >  00060001 R_X86_64_64 0011 init_65535 + > > 0
> > 0008 00070001 R_X86_64_64 0022 init + 0
> > 0010 00080001 R_X86_64_64 0033 init_65535_2 
> > + 0
> ```
> 
> The above show clearly gcc produces the wrong order of section `.rela.ctors`.
> 
> Is that expected behavior ?
> 
> I have not tried Linux version of gcc.
Note that init array vs. init function behavior is encoded by a note added
by crt1.o.  I suspect that the problem is that gcc port is built without
--enable-initfini-array configure option.