Skip to content

Q: How to use LTO when using AOT? #97501

Closed
@JCash

Description

@JCash

Using Clang, the linker can opt away (-flto) functions that don't seem to be used.

In my example, I produce a library (.a) using dotnet+AoT.
This library is then linked into an executable using C++ and Clang.

The issue is that some functions are removed from the executable are removed, and the the resulting executable will segfault.

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSEGV
  * frame #0: 0x000000010005e5e5 test`RhpNewArray + 71
    frame #1: 0x0000000100092748 test`_S_P_CoreLib_Internal_Runtime_CompilerHelpers_StartupCodeHelpers__CreateTypeManagers(osModule=<unavailable>, pModuleHeaders=<unavailable>, count=<unavailable>, pClasslibFunctions=<unavailable>, nClasslibFunctions=<unavailable>) at StartupCodeHelpers.cs:110
    frame #2: 0x0000000100092567 test`_S_P_CoreLib_Internal_Runtime_CompilerHelpers_StartupCodeHelpers__InitializeModules(osModule=<unavailable>, pModuleHeaders=<unavailable>, count=<unavailable>, pClasslibFunctions=<unavailable>, nClasslibFunctions=<unavailable>) at StartupCodeHelpers.cs:34
    frame #3: 0x0000000100004300 test`InitializeRuntime() at main.cpp:188:5 [opt]
    frame #4: 0x000000010000bfd5 test`Thread::ReversePInvokeAttachOrTrapThread(ReversePInvokeFrame*) [inlined] Thread::EnsureRuntimeInitialized(this=<unavailable>) at thread.cpp:1219:13 [opt]
    frame #5: 0x000000010000bfad test`Thread::ReversePInvokeAttachOrTrapThread(this=0x0000000100404268, pFrame=0x00007ff7bfefefe0) at thread.cpp:1181:13 [opt]
    frame #6: 0x0000000100079fcb test`_libNativeLibrary_CS__CsAdd(a=<unavailable>, b=<unavailable>) at Library.cs:36
    frame #7: 0x0000000100079e9f test`main(argc=1, argv=0x00007ff7bfeff2f0) at main.cpp:14:47 [opt]
    frame #8: 0x00007ff80366041f dyld`start + 1903

What is the recommended way to fix this issue?
Is there a global function that I can "extern" to make sure the linker cannot remove it?
E.g. if I in main.cpp had something like:

extern "C"  MyGlobalInit() { // Never actually used, but the linker cannot know that
    Some_AOT_Initialize_Function();
}

Or is there some other Clang trick to make sure it doesn't remove certain functions?

I would happily take any ideas on how to solve this.

Regards,
Mathias

I have an example here, which can demonstrate the issue
https://github.com/JCash/csharpextension/tree/lto-error

To build: ./scripts/compile.sh
To run: ./scripts/run.sh

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions