Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mono runtime binaries need to be stripped #45013

Closed
akoeplinger opened this issue Nov 20, 2020 · 8 comments
Closed

Mono runtime binaries need to be stripped #45013

akoeplinger opened this issue Nov 20, 2020 · 8 comments
Assignees
Milestone

Comments

@akoeplinger
Copy link
Member

This got lost with the CMake conversion, leading to e.g. the release build of libmonosgen-2.0.so for Android to be 20MB instead of 3MB.

@akoeplinger akoeplinger added this to the 6.0.0 milestone Nov 20, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Nov 20, 2020
@akoeplinger akoeplinger removed the untriaged New issue has not been triaged by the area owner label Nov 20, 2020
@akoeplinger akoeplinger self-assigned this Nov 20, 2020
@vargaz
Copy link
Contributor

vargaz commented Nov 22, 2020

Maybe we should compile without -g in release mode ?

@rolfbjarne
Copy link
Member

Maybe we should compile without -g in release mode ?

Not for iOS at least, you'll need the debug symbols to create the dSYM directory before stripping any binaries.

@radekdoulik
Copy link
Member

Indeed, noticed that in apkdiff output when comparing monodroid to net6-android Release configuration apks. The net6-android's libmonosgen-2.0.so has debug sections:

Size difference in bytes ([*1] apk1 only, [*2] apk2 only):
  +  10,675,800 lib/arm64-v8a/libmonosgen-2.0.so
                  Section size difference
    +   5,038,103 .debug_info *2
    +   4,928,791 .debug_loc *2
    +   1,900,544 .debug_line *2
    +   1,000,144 .debug_ranges *2
    +     531,182 .debug_str *2
    +     272,424 .debug_frame *2
    +     190,803 .debug_abbrev *2
    +      10,008 .rela.plt
    +       9,516 .gnu.hash *2
    +       6,672 .plt
    +       6,640 .got
    +         322 .debug_macinfo *2
    +          36 .note.gnu.build-id *2
    -          16 .dynamic
    -          24 .bss
    -          82 .comment
    -         590 .gnu.version
    -       1,180 .hash
    -       2,424 .got.plt *1
    -       2,428 .data
    -       6,560 .dynstr
    -       7,080 .dynsym
    -      10,056 .data.rel.ro
    -      10,920 .rela.dyn
    -     397,734 .rodata
    -   2,660,688 .text

@jonpryor
Copy link
Member

jonpryor commented Jan 8, 2021

There is an argument to be made that no .so files should be shipped as strip'd binaries, so that when a SIGSEGV occurs, there is a way to get an environment to repeat the crash and get debug symbols from the crash.

Under this worldview, strip or equivalent should be done as late as possible, e.g. during Android .apk generation.

Alternatively, the package containing the mono runtime binaries could ship with two sets of binaries: one strip'd, one not. This is what Xamarin.Android does, shipping e.g.

  • /Library/Frameworks/Xamarin.Android.framework/Versions/11.1.0.17/lib/xamarin.android/xbuild/Xamarin/Android/lib/armeabi-v7a/libmonosgen-2.0.so
  • /Library/Frameworks/Xamarin.Android.framework/Versions/11.1.0.17/lib/xamarin.android/xbuild/Xamarin/Android/lib/armeabi-v7a/libmonosgen-2.0.d.so

The .d.so is the "debug" un-strip'd library. We'll use the .d.so variants when $(_AndroidDebugNativeLibraries)=True.

However, what we could instead do is (optionally) strip all .so files at .apk creation time. This would allow everyone to ship un-strip'd binaries, permitting easier debugging for all involved, while allowing customers to get smaller .apk sizes for Release builds.

@jonpryor
Copy link
Member

jonpryor commented Jan 8, 2021

Rephrased: with .NET 6, Xamarin.Android will need a way to get an un-strip'd libmonosgen-2.0.so into the .apk, so that when an app crashes, we can get a decent stack trace.

What should that mechanism be?

As previously suggested, if the NuGet package containing the mono runtime binaries is not strip'd -- meaning this issue is a no-op -- then we have an answer: use the libmonosgen-2.0.so file in the "normal" NuGet package.

If you do strip libmonosgen-2.0.so, then we'll need to have some alternate mechanism to obtain the un-strip'd binaries.

radekdoulik added a commit to dotnet/android that referenced this issue Feb 24, 2021
Context: #5558
Context: dotnet/runtime#45013

Due to runtime issue #45013 we are producing large packages
for `Release` configurations, where native libraries contain debug
information.

So we will strip framework native libs for now. Added new target
and task to call ndk's strip tool with `--strip-debug` option.
The target should work partially.

The apk size reference files were updated, the so that we catch size
regressions in case the native libs are not stripped.

The `DotNetBuild` test was updated to check for native libs in the new
location, where we put them during build.

The apk sizes differences, before/after BuildReleaseArm64False/net6:
```
Size difference in bytes ([*1] apk1 only, [*2] apk2 only):
  +         296 lib/arm64-v8a/libxa-internal-api.so
  -         560 lib/arm64-v8a/libmonodroid.so
  -     168,344 lib/arm64-v8a/libxamarin-debug-app-helper.so
  -  14,762,720 lib/arm64-v8a/libmonosgen-2.0.so
Summary:
  +           0 Other entries 0.00% (of 58,624)
  +           0 Dalvik executables 0.00% (of 316,988)
  +           0 Assemblies 0.00% (of 690,435)
  -  14,931,328 Shared libraries -74.17% (of 20,130,552)
  +           0 Uncompressed assemblies 0.00% (of 1,357,824)
  -   4,947,968 Package size difference -62.74% (of 7,886,783)
```
Interestingly, the size of `libxa-internal-api.so` increases, only marginally though.

That get us back to much better ratio between apk sizes of legacy and net6 (BuildReleaseArm64False):
```
Summary:
  +         603 Other entries 1.04% (of 58,021)
  +          32 Dalvik executables 0.01% (of 316,956)
  -     463,004 Assemblies -40.14% (of 1,153,439)
  -   5,314,304 Shared libraries -50.55% (of 10,513,528)
  -   1,408,000 Uncompressed assemblies -50.91% (of 2,765,824)
  -   2,072,341 Package size difference -41.35% (of 5,011,156)
```
and apk sizes for legacy/net6 (BuildReleaseArm64True):
```
Summary:
  +      13,527 Other entries 1.50% (of 903,720)
  +         616 Dalvik executables 0.02% (of 3,454,376)
  +   1,022,148 Assemblies 21.87% (of 4,674,167)
  -   5,310,496 Shared libraries -50.17% (of 10,584,912)
  +   1,545,728 Uncompressed assemblies 13.69% (of 11,293,696)
  -     572,295 Package size difference -5.43% (of 10,537,118)
```

Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
@directhex
Copy link
Member

The "normal" behaviour here in the dotnet world is stripped libs (.dylib, .so) go into a runtime.nupkg, and both stripped libs and the stripped symbol companion files (.dwarf, .dbg) go into a runtime.symbols.nupkg file. That's what happens with coreclr, and the native pieces like libSystem.Native.dylib. I've made #53240 which does it to Mono too.

@steveisok
Copy link
Member

@directhex Can we close then?

@directhex
Copy link
Member

Closing, this was fixed in #53240 and subsequent fixups

@ghost ghost locked as resolved and limited conversation to collaborators Aug 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants