__CTOR_LIST__ not populated
Page 1 of 1

Author:  pvc [ Sat Aug 17, 2019 4:01 am ]
Post subject:  __CTOR_LIST__ not populated

I am in the process of building proper hosted GCC cross compiler for my OS. I've got it to almost working state but there is one thing I am stuck for a few days already. Global/static (whatever they are called) constructors don't get called at all when linking non-static executables. For static executables everything works as it should.
What I've found for now:
  • _init function gets called,
  • .ctors and .dtors sections are generated when needed,
  • .init_array and .fini_array sections are generated but __init_array_start, __init_array_end, __fini_array_start and __fini_array_end symbols are not there,
  • __CTOR_LIST__, __CTOR_END__, __DTOR_LIST__ and hidden __DTOR_END__ symbols are there,
  • but distance between *_END__ and *_LIST__ symbols is always 8 (single pointer size), which (I assume) is not right,
  • __CTOR_LIST__ and __DTOR_LIST__ contain -1 pointer which is correct,
  • __CTOR_END__ and __DTOR_END__ all contain single NULL pointer, which is also ok

C library (musl in my case) initialization routine tries to scan over __CTOR and __DTOR lists but they are simply empty. I've followed wiki tutorial when doing the port and expanded on it a little bit to support shared libraries. Code of my GCC port is here https://github.com/pvc988/woot64/tree/m ... /gcc-9.1.0 if it helps. My OS is identified by x86_64-woot (not exactly) triplet. Or maybe I am barking up completely wrong tree and the problem lies within binutils?

EDIT: I think I am onto something. Some part of the build process is hellbent on putting constructors in .init_array section instead of .ctors. Despite using --disable-initfini-array configure option and adding gcc_cv_initfini_array=no to config.gcc. But if I manually remove .init_array and .fini_array sections from linker script then everything starts to work.

Author:  Korona [ Sat Aug 17, 2019 7:05 am ]
Post subject:  Re: __CTOR_LIST__ not populated

GCC on x86_64 does not properly work without .init_array. In fact, the calling convention of .init functions misaligns the stack and breaks if you use SSE (or anything else that relies on 16 byte alignment). Always pass --enable-initfini-array when building a cross-compiler. The dynamic linker should call .init_array.

Author:  pvc [ Sat Aug 17, 2019 7:17 am ]
Post subject:  Re: __CTOR_LIST__ not populated

I finally figured it out. Turns out that binutils also need --disable-initfini-array configure option. Passing it to both binutils and GCC makes things work.

@Korona Calling constructors from .init_array won't work for me (at least for now) since I am doing dynamic linking in the kernel. I've also disabled musl's built-in linker since I don't really want to have 2 of them. About that SSE thing. I didn't know about that. I am going to do some checking.

Author:  pvc [ Sat Aug 17, 2019 9:41 am ]
Post subject:  Re: __CTOR_LIST__ not populated

After some thinking I however decided to go with .init_array mechanism and modified musl a little bit to accomodate external dynamic linker.
crt1.c needed to make use of __init_array_start and others so linker wouldn't discard them. Then passed their addresses to __libc_start_main which resides in libc.so file. Finally added some #ifdefs and voila, constructors and destructors work perfectly.

Author:  Korona [ Sat Aug 17, 2019 10:05 am ]
Post subject:  Re: __CTOR_LIST__ not populated

Yes, that's a good idea. Let me elaborate on what I said about the calling convention of .init: on x86 and x86_64, GCC generates .init by just appending `call <constructor>` instructions to .init. For example, this is done using the `CRT_CALL_STATIC_FUNCTION` macro in gcc/config/i386/i386.h. The _init function itself is declared in config/i386/crti.S. However, assuming that the stack is aligned correctly (to a 16-byte boundary) before calling _init, it will be misaligned in the constructor functions that are called from .init, as the call instruction only advances RSP by 8 and not by 16. While this would be easy to fix in GCC (just align the stack inside crti.S), no one seems to use this code anyway (otherwise it would be functional, even on x86_64) and .init_array is the more modern alternative to it.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group