Bug 20220 – pragma(crt_constructor) does not work with clang 9

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
Linux
Creation time
2019-09-17T07:04:37Z
Last change time
2019-11-15T06:58:26Z
Keywords
pull
Assigned to
No Owner
Creator
Ernesto Castellotti

Comments

Comment #0 by erny.castell — 2019-09-17T07:04:37Z
building this file: //////////////// module crttest; import core.stdc.stdio : printf; pragma (crt_constructor) extern(C) void constructor { printf("constructor called\n"); } void main() { printf("main called\n"); } with "CC=clang dmd crttest.d" When I run the executable the output is: main called instead of the expected: constructor called main called I think there is a problem in the DMD backend, probably this issue #19551 is also related to the same problem
Comment #1 by doob — 2019-09-18T17:59:48Z
Works on macOS, which uses Clang by default. So it might not be Clang related. Or it's a mix of Linux and Clang.
Comment #2 by erny.castell — 2019-09-18T18:32:56Z
Yes in MacOS works, but in linux seems not in linux
Comment #3 by erny.castell — 2019-09-18T19:26:20Z
OK I did other tests, it just happens on clang > 9.0 Jacob Carlborg can you test with clang 9 on MacOS? However I found the way to solve, DMD adds the .ctors section to the elf for crt_constructor, I discovered that using .init_array the problem does not happen
Comment #4 by doob — 2019-09-23T18:08:56Z
(In reply to Ernesto Castellotti from comment #3) > Jacob Carlborg can you test with clang 9 on MacOS? Sorry, there are no Clang 9 binaries for macOS (too lazy to compile myself). I tested with Apple Clang 11. I don't know which version that corresponds to.
Comment #5 by doob — 2019-09-23T18:22:30Z
I tried in a Docker container with DMD 2.088.0 and Clang 9. Works fine.
Comment #6 by kinke — 2019-11-13T01:01:04Z
(In reply to Ernesto Castellotti from comment #3) > However I found the way to solve, DMD adds the .ctors section to the elf for > crt_constructor, I discovered that using .init_array the problem does not > happen Yes, that's it, DMD emits the c/dtors into the .{c,d}tors sections in the object files (LDC uses .{init,fini}_array by default for Linux). Quoting an LLD maintainer from https://gitter.im/ldc-developers/main: > Most Linux distributions configure glibc with NO_CTORS_DTORS_SECTIONS nowadays. > csu/init-first.c:_init just doesn't run __libc_global_ctors (which runs > __CTOR_LIST__ hooks). The builtin linker script of GNU ld and gold's default > --ctors-in-init-array place .ctors input sections to .init_array So this apparently only works in most cases due to the GNU linkers mapping the object file sections to differently named binary sections by default. LLD doesn't have such an option, so DMD should probably just switch to the 'modern' section names.
Comment #7 by dlang-bot — 2019-11-13T01:48:43Z
@MaskRay created dlang/dmd pull request #10562 "Use .init_array/.fini_array instead of .ctors/.dtors" fixing this issue: - Use .init_array/.fini_array instead of .ctors/.dtors Fix Issue 20220. dmd places global constructors in .ctors sections. When such sections are linked by lld, the executable will not run constructors on most modern Linux distributions (musl does not support .ctors/glibc is usually configured with NO_CTORS_DTORS_SECTIONS). GNU ld and gold convert .ctors/.dtors to .init_array/.fini_array by default, so programs linked by them are fine. lld does not support the feature and it probably makes little sense to add the support (https://bugs.llvm.org/show_bug.cgi?id=31224): .init_array has been supported by glibc for 20 years and adopted by most ELF platforms. https://github.com/dlang/dmd/pull/10562
Comment #8 by erny.castell — 2019-11-13T07:00:32Z
(In reply to Dlang Bot from comment #7) > @MaskRay created dlang/dmd pull request #10562 "Use .init_array/.fini_array > instead of .ctors/.dtors" fixing this issue: > > - Use .init_array/.fini_array instead of .ctors/.dtors > > Fix Issue 20220. > > dmd places global constructors in .ctors sections. When such sections > are linked by lld, the executable will not run constructors on most > modern Linux distributions (musl does not support .ctors/glibc is > usually configured with NO_CTORS_DTORS_SECTIONS). > > GNU ld and gold convert .ctors/.dtors to .init_array/.fini_array by > default, so programs linked by them are fine. lld does not support the > feature and it probably makes little sense to add the support > (https://bugs.llvm.org/show_bug.cgi?id=31224): > .init_array has been supported by glibc for 20 years and adopted by most > ELF platforms. > > https://github.com/dlang/dmd/pull/10562 I would prefer to have an optional switch, maybe someone wants to have .ctors
Comment #9 by dlang-bot — 2019-11-15T06:58:26Z
dlang/dmd pull request #10562 "Fix Issue 20220 - Use .init_array/.fini_array instead of .ctors/.dtors on !TARGET_OPENBSD" was merged into master: - 082a9f459c863120929b86f1559a5e75fd2da60a by Fangrui Song: Fix Issue 20220 - Use .init_array/.fini_array instead of .ctors/.dtors on !TARGET_OPENBSD Global constructors are placed in .ctors sections. lld does not convert .ctors to .init_array (https://bugs.llvm.org/show_bug.cgi?id=31224). The linked executable will not run constructors on most modern Linux distributions. GNU ld and gold convert .ctors/.dtors to .init_array/.fini_array by default, so programs linked by them are fine. Fix this by using .init_array/.fini_array . Linux, DragonFlyBSD, FreeBSD and Solaris have supported .init_array for many years. The OpenBSD support is relatively new (Aug 2016), so only use .ctors/.dtors on OpenBSD. https://github.com/dlang/dmd/pull/10562