You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
NativeAOT produces static library that makes ld crash #88032
NativeAOT produces static library that makes ld crash.
Reproduction Steps
This is rather complicated, it would mean checking out the branch here: dotnet/macios#18489, and building the monotouch-test test for NativeAOT locally. If needed, I can help with that, but hopefully I can give enough info to avoid having to do this.
I did a simple test on empty app (dotnet new ios) to see how much effect the -dead_strip option has on reducing the final executable size.
With -dead_strip: 12_146_968
Without -dead_strip: 12_476_144
Diff: 329_176 / 2.7%
This is basically the upper limit on the savings. It will be less for real-world app that uses more of the runtime features. I think it's acceptable to disable -dead_strip for now and ship that way.
I also diffed the list of preserved symbols. I noticed that there's plenty of code in both the NativeAOT and Xamarin runtime that's never going to be used. We should eventually go through the list and remove the unused methods entirely. In the case of Xamarin runtime some of the unused methods date back all the way to legacy Xamarin/Mono and they are never used on .NET 6+ (eg. xamarin_timezone_* APIs). In the case of NativeAOT runtime there's a big unused chunk of llvm-libunwind. Then there's mono_wasi_load_icu_data and other "peanuts" that may be worth fixing eventually but probably won't make a big size difference.
Looking at https://opensource.apple.com/source/cctools/cctools-622.5.1/RelNotes/CompilerTools.html?txt it seems like object files need to be recompiled with toolchains that understand the dead_strip optimization. I wonder if the problem is that LLVM is generating the object file in a way that looks compatible with dead_strip and then it isn't because we don't know what the proprietary magic sauce is.
I assume the dead_strip is getting passed on Xamarin side since I don't see it in our .targets.
I assume the dead_strip is getting passed on Xamarin side since I don't see it in our .targets.
Yes, that is correct and as a workaround it got disabled via: dotnet/macios#18553
However, the end goal is to be able to use the flag during linking (tracked by: dotnet/macios#18605) as it can have a significant impact with projects that use third-party bindings. /cc: @rolfbjarne
I've added the os-ios label to get this off our team's .NET 8 queries since this looks iOS specific - I'll leave this up to you if this is .NET 8 or 9. It's unlikely our team will have time to look at mystery linker crashes that require a mac to repro. If I was investigating this, I would start with why the linker even thinks the objects produced by ILC are eligible for dead_strip. It's possible LLVM is injecting something into the object files on our behalf. It wouldn't be first such thing.
I am not necessarily sure that the dead-stripability of the object file is what matters here (the algorithm in ld64 is recursive and just runs out of stack space). That said, it is controlled by the MH_DEAD_STRIPPABLE_DYLIB flag in the Mach-O header. I won't be able to check until next week if we set it or not.
This does not seem to be reproducible anymore according to: dotnet/macios#20796
I am closing this issue for now and we will keep tracking if the crashes start appearing again.
Activity
rolfbjarne commentedon Jun 26, 2023
Looks like this regression is not in the P6 branch, only main (it doesn't reproduce in this PR: dotnet/macios#18497)
That means it's probably somewhere in this range: edfe491...3195fbb
rolfbjarne commentedon Jun 26, 2023
We got another bump, and the crash is gone, so seems like this was fixed.
ivanpovazan commentedon Jul 5, 2023
I am reopening this issue as I have experienced the same native linker crash when building
MAUI Podcast appwith NativeAOT using Xamarin https://github.com/xamarin/xamarin-macios/tree/release/8.0.1xx-preview6 branch.Additionally, I confirm that the workaround of not passing
-dead_stripto the native linker solves the issue.I will try to provide more context, but it seems the issue is triggered when compiling bigger applications.
/cc: @filipnavara @akoeplinger
filipnavara commentedon Jul 6, 2023
I did a simple test on empty app (
dotnet new ios) to see how much effect the-dead_stripoption has on reducing the final executable size.With
-dead_strip:12_146_968Without
-dead_strip:12_476_144Diff:
329_176/ 2.7%This is basically the upper limit on the savings. It will be less for real-world app that uses more of the runtime features. I think it's acceptable to disable
-dead_stripfor now and ship that way.I also diffed the list of preserved symbols. I noticed that there's plenty of code in both the NativeAOT and Xamarin runtime that's never going to be used. We should eventually go through the list and remove the unused methods entirely. In the case of Xamarin runtime some of the unused methods date back all the way to legacy Xamarin/Mono and they are never used on .NET 6+ (eg.
xamarin_timezone_*APIs). In the case of NativeAOT runtime there's a big unused chunk of llvm-libunwind. Then there'smono_wasi_load_icu_dataand other "peanuts" that may be worth fixing eventually but probably won't make a big size difference.ivanpovazan commentedon Jul 11, 2023
Measuring the effect on the
dotnet new mauiapp:With
-dead_strip:39_614_336Without
-dead_strip:39_769_312Diff:
154_976/0,39%Do not include -dead_strip when native linking a NativeAOT object file (
MichalStrehovsky commentedon Aug 2, 2023
Looking at https://opensource.apple.com/source/cctools/cctools-622.5.1/RelNotes/CompilerTools.html?txt it seems like object files need to be recompiled with toolchains that understand the dead_strip optimization. I wonder if the problem is that LLVM is generating the object file in a way that looks compatible with dead_strip and then it isn't because we don't know what the proprietary magic sauce is.
I assume the dead_strip is getting passed on Xamarin side since I don't see it in our .targets.
ivanpovazan commentedon Aug 2, 2023
Yes, that is correct and as a workaround it got disabled via: dotnet/macios#18553
However, the end goal is to be able to use the flag during linking (tracked by: dotnet/macios#18605) as it can have a significant impact with projects that use third-party bindings. /cc: @rolfbjarne
rolfbjarne commentedon Aug 2, 2023
Correct. In one case I saw an app go from >1gb to 40mb by using -dead_strip.
MichalStrehovsky commentedon Aug 2, 2023
I've added the os-ios label to get this off our team's .NET 8 queries since this looks iOS specific - I'll leave this up to you if this is .NET 8 or 9. It's unlikely our team will have time to look at mystery linker crashes that require a mac to repro. If I was investigating this, I would start with why the linker even thinks the objects produced by ILC are eligible for dead_strip. It's possible LLVM is injecting something into the object files on our behalf. It wouldn't be first such thing.
filipnavara commentedon Aug 3, 2023
I am not necessarily sure that the dead-stripability of the object file is what matters here (the algorithm in ld64 is recursive and just runs out of stack space). That said, it is controlled by the
MH_DEAD_STRIPPABLE_DYLIBflag in the Mach-O header. I won't be able to check until next week if we set it or not.NativeAOT: Reenable `-dead_strip` platform linker optimization by def…
ivanpovazan commentedon Jul 3, 2024
This does not seem to be reproducible anymore according to: dotnet/macios#20796
I am closing this issue for now and we will keep tracking if the crashes start appearing again.