I have a project where I am loading a shared object into a Go application. This shared object has static constructors. It works on Ubuntu and Centos, but not in Alpine where static constructors are not called because of incompatibility between musl-libc and Go runtime. GCC puts static constructors (like __attribute__((constructor))) into .init_array which is called by the loader in glibc, but not by musl-libc who leaves this to the C start-up code. In case of Go runtime does not implement these calls to the functions in .init_array.
On the other hand, on both cases the loader calls the functions in .ctors section. It looks like an ideal solution for this project.
I am trying to add my constructors (C or ASM) to the .ctors section, but after linking my shared object they seem to be moved to .init_array by the linker (ld).
Here is my example ASM code:
.intel_syntax noprefix
.text
.section .rodata
.Message:
.string "Constructor called!"
.text
Constructor:
lea rdi, .Message[rip]
jmp puts@PLT
.section .ctors,"a"
__CTOR_LIST__:
.quad Constructor
I run compile and link it but the .ctors logically empty!
$ gcc ctors.s -c -o ctors.o
$ ld -shared ctors.o -o ctors.so
$ readelf -x 14 /libctors.so
Hex dump of section '.ctors':
0x00003df8 ffffffff ffffffff 00000000 00000000 ................
Why is this happening? Can make my array stay in .ctors section? How can I add functions to the .ctors sections?