ldc-developers / ldc

The LLVM-based D Compiler.
http://wiki.dlang.org/LDC
Other
1.21k stars 262 forks source link

[Android] Support the lld linker #3918

Closed skyline131313 closed 7 months ago

skyline131313 commented 2 years ago

The BFD linker has been removed since r23, so it isn't going to be an option going forward.

I've tried the following linker script to try and force the two sections together but the script causes the library to not be loadable:

SECTIONS
{
    .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
    .tbss  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
}

I've also tried looking at sections_android to see what would need to be changed to support two non continuous sections but it's a bit out of my field.

https://github.com/ldc-developers/druntime/blob/ldc/src/rt/sections_android.d#L183

It might be possible to just put everything in one section in the compiler?

Tried swapping the sections manually with a program but the program still crashes, there might be more needed to be done.

skyline131313 commented 2 years ago

Looks like the problem is that it can't open the shared library file cause it is located in the apk:

https://github.com/ldc-developers/druntime/blob/ldc/src/rt/sections_android.d#L239

kinke commented 2 years ago

Looks like the problem is that it can't open the shared library file cause it is located in the apk:

You mean the lib created with the linker script above? - I think the problem is the seemingly very incomplete linker script (no .text etc.). IIRC, the default linker scripts used to be part of the NDK (*.lds files IIRC), but I haven't found any in the latest r21 and r23 NDKs.


AFAICT, NDK r23 comes with lld exclusively, so you'll probably want to edit the title (gold).


It might be possible to just put everything in one section in the compiler?

That would entail modding LLVM further. See https://github.com/ldc-developers/llvm-project/commit/e68ba964baa1c243d0886fd8e78a26e50393aa78. - Emitting everything into .tdata would be an option, at the cost of slightly increased binary sizes presumably (=> incl. all zero-initialized TLS data in image).

As stated on the Wiki page, I think going with LLVM's EmuTLS for Android would be the best way forward (no need for LLVM hack and probably paving the way for proper shared library support). TLS performance would probably suffer a bit, but AFAIK, GDC uses EmuTLS for at least Darwin and Windows targets too, so…

skyline131313 commented 2 years ago

I was modifying the shared library with a separate program to force the two sections beside each other. The linker script causes it to fail to even load the shared library. Yah I was having trouble finding any linker scripts.

Alright I'll look into EmuTLS.

kinke commented 2 years ago

Alright I'll look into EmuTLS.

All the best! :) - Make sure to use a vanilla LLVM in that case (no custom TLS emulation) and patch this: https://github.com/ldc-developers/ldc/blob/5b0bd6865f2458b2c3fd00f7ef9652086f2d875d/driver/targetmachine.cpp#L496-L501

I think that's it from the compiler side, and the real work would be in druntime's rt/sections_android.d.

kinke commented 2 years ago

And see https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/emutls.c for API/implementation details. It's part of LLVM's compiler-rt builtins library (libclang_rt.builtins.a).

kinke commented 7 months ago

Oh, good news - Android apparently supports native ELF TLS since API level 29: https://reviews.llvm.org/D147849. This means that we might be able to drop the LLVM hack, the compiler special case wrt. emutls above, and in druntime, remove rt/sections_android.d and use rt/sections_elf_shared.d (maybe with a few version(CRuntime_Bionic) special cases) instead.

s-ludwig commented 7 months ago

On a quick note, for anyone who wants to build for Android right now - it appears to be possible to work around this by copying the NDK 21 linker binary to the NDK 25 binary folder and using that instead of the shipped lld. From a quick glance, the generated binaries seem to work fine and targeting the currently required 33 API level becomes possible.