Skip to content

Commit

Permalink
Add build option to strip out debug symbols when building MonoAOT iOS…
Browse files Browse the repository at this point in the history
… sample app
  • Loading branch information
kotlarmilos committed Jan 25, 2023
1 parent 6e773f2 commit 840ee5b
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/mono/sample/iOS/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ AOT?=false
TARGET?=iossimulator
DEPLOY_AND_RUN?=true
APP_SANDBOX?=false
STRIP_DEBUG_SYMBOLS?=false

#If DIAGNOSTIC_PORTS is enabled, RUNTIME_COMPONENTS must also be enabled.
#If RUNTIME_COMPONENTS is enabled, DIAGNOSTIC_PORTS is optional.
Expand Down Expand Up @@ -33,6 +34,7 @@ run: clean appbuilder
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) \
/p:ForceAOT=$(AOT) \
/p:StripDebugSymbols=$(STRIP_DEBUG_SYMBOLS) \

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 25, 2023

Member

We should not strip symbols when trying to run the app on a device, as stripping will cause the app to have an invalid signature. Instead this should be done only when measuring SOD via build-appbundle make target.

Making sure that the app runs properly even after stripping is a separate task which validates that the change is correct. To automate it, it will be required to add yet another build task which would resign the app, but that seems to be a stretch and out-of-scope for HelloiOS app.

This comment has been minimized.

Copy link
@kotlarmilos

kotlarmilos Jan 25, 2023

Author Member

Good point. I have checked manually that the app is working after the stripping.

'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
'/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \
'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'
Expand All @@ -44,6 +46,7 @@ run-sim: clean appbuilder
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) \
/p:ForceAOT=$(AOT) \
/p:StripDebugSymbols=$(STRIP_DEBUG_SYMBOLS) \

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 25, 2023

Member

Same as above.

'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
'/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \
'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'
Expand Down
5 changes: 5 additions & 0 deletions src/mono/sample/iOS/Program.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<RuntimeIdentifier>$(TargetOS)-$(TargetArchitecture)</RuntimeIdentifier>
<DefineConstants Condition="'$(ArchiveTests)' == 'true'">$(DefineConstants);CI_TEST</DefineConstants>
<AppName>HelloiOS</AppName>
<StripDebugSymbols Condition="'$(StripDebugSymbols)' == ''">false</StripDebugSymbols>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -97,6 +98,10 @@
<Output TaskParameter="XcodeProjectPath" PropertyName="XcodeProjectPath" />
</AppleAppBuilderTask>

<Exec Condition="'$(StripDebugSymbols)' == 'true'"
Command="dsymutil $(AppBundlePath)/$(AppName)

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 25, 2023

Member

Did we check whether dsymutil extracts the symbol properly i.e. did we try to resymbolicate with the generated .dSYM afterwards to have a debugging experience in Release mode?

This comment has been minimized.

Copy link
@kotlarmilos

kotlarmilos Jan 25, 2023

Author Member

I was able to debug both managed and native code by using xcode with stripped symbols and a .dSYM. Is there a way to explicitly load the .dSYM?

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 25, 2023

Member

I am not sure if lldb loads it by default, but there is more information about it here: https://lldb.llvm.org/use/symbolication.html

This comment has been minimized.

Copy link
@kotlarmilos

kotlarmilos Jan 30, 2023

Author Member

Crash organizer in xcode does automatic symbolication of crash reports.

It is possible to manually symbolicate the crash report in case of stripped symbols. Consider the following dummy example of a stack trace where some invocations are not symbolicated.

* thread #8, queue = 'com.apple.root.default-qos', stop reason = breakpoint 1.1
  * frame #0: 0x00000001012b0a6c HelloiOS`mono_ios_runtime_init at runtime.m:308:5
    frame #1: 0x00000001012b0124 HelloiOS`__29-[ViewController viewDidLoad]_block_invoke(.block_descriptor=0x0000000101a56a30) at main.m:49:9
    frame #2: 0x0000000102a70594 + 24
    frame #3: 0x0000000102a71d5c  + 16
    frame #4: 0x0000000102a74b50 + 1252
    frame #5: 0x0000000102a868ac + 440
    frame #6: 0x0000000102a8753c + 248
    frame #7: 0x00000001b059a8c0 + 224

By using atos tool with image load address provided by a crash report and address to symbolicate it is possible to retrieve symbols. Here is an example

atos -arch arm64 -o HelloiOS.dSYM/Contents/Resources/DWARF/HelloiOS -l <image_load_address> 0x0000000102a868ac 

that outputs

_dispatch_root_queue_drain (in HelloiOS) + 440

However, Xcode overrides strip options during the build process.

strip -no_code_signature_warning -i -s $(MSBuildThisFileDirectory)/symbols.list $(AppBundlePath)/$(AppName)" />

<Message Importance="High" Text="Xcode: $(XcodeProjectPath)"/>
<Message Importance="High" Text="App: $(AppBundlePath)"/>
</Target>
Expand Down
111 changes: 111 additions & 0 deletions src/mono/sample/iOS/symbols.list
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
_SystemNative_Abort
_SystemNative_Exit
_SystemNative_SchedGetCpu
_SystemNative_ConvertErrorPlatformToPal
_SystemNative_ConvertErrorPalToPlatform
_SystemNative_StrErrorR
_SystemNative_GetLoadLibraryError
_SystemNative_GetProcAddress
_SystemNative_FreeLibrary
_SystemNative_GetErrNo
_SystemNative_SetErrNo
_SystemNative_GetEnviron
_SystemNative_FreeEnviron
_SystemNative_GetOSArchitecture
_SystemNative_GetNonCryptographicallySecureRandomBytes
_SystemNative_GetCryptographicallySecureRandomBytes
_SystemNative_GetSystemTimeAsTicks
_SystemNative_GetTimestamp
_SystemNative_LChflagsCanSetHiddenFlag
_SystemNative_CanGetHiddenFlag
_SystemNative_Log
_SystemNative_LogError
_SystemNative_LowLevelMonitor_Create
_SystemNative_LowLevelMonitor_Destroy
_SystemNative_LowLevelMonitor_Acquire
_SystemNative_LowLevelMonitor_Release
_SystemNative_LowLevelMonitor_Wait
_SystemNative_LowLevelMonitor_Signal_Release
_SystemNative_AlignedAlloc
_SystemNative_AlignedFree
_SystemNative_AlignedRealloc
_SystemNative_Calloc
_SystemNative_Free
_SystemNative_Malloc
_SystemNative_Realloc
_SystemNative_GetAllMountPoints
_SystemNative_GetReadDirRBufferSize
_SystemNative_ReadDirR
_SystemNative_GetEUid
_SystemNative_GetEGid
_SystemNative_GetPid
_SystemNative_CreateAutoreleasePool
_SystemNative_DrainAutoreleasePool
_SystemNative_CreateThread
_SystemNative_Access
_SystemNative_ChDir
_SystemNative_ChMod
_SystemNative_FChMod
_SystemNative_Close
_SystemNative_CopyFile
_SystemNative_LoadLibrary
_SystemNative_GetDefaultSearchOrderPseudoHandle
_SystemNative_GetFileSystemType
_SystemNative_FLock
_SystemNative_FSync
_SystemNative_FTruncate
_SystemNative_GetCpuUtilization
_SystemNative_GetCwd
_SystemNative_GetDefaultTimeZone
_SystemNative_GetEnv
_SystemNative_GetHostName
_SystemNative_GetProcessPath
_SystemNative_GetUnixVersion
_SystemNative_GetUnixRelease
_SystemNative_LChflags
_SystemNative_FChflags
_SystemNative_Link
_SystemNative_LockFileRegion
_SystemNative_LowLevelMonitor_TimedWait
_SystemNative_LSeek
_SystemNative_MkDir
_SystemNative_MkdTemp
_SystemNative_MksTemps
_SystemNative_Open
_SystemNative_PathConf
_SystemNative_PosixFAdvise
_SystemNative_FAllocate
_SystemNative_PRead
_SystemNative_PReadV
_SystemNative_PWrite
_SystemNative_PWriteV
_SystemNative_Read
_SystemNative_OpenDir
_SystemNative_CloseDir
_SystemNative_ReadLink
_SystemNative_Rename
_SystemNative_RmDir
_SystemNative_FStat
_SystemNative_Stat
_SystemNative_LStat
_SystemNative_SymLink
_SystemNative_SysConf
_SystemNative_SysLog
_SystemNative_Unlink
_SystemNative_UTimensat
_SystemNative_FUTimens
_SystemNative_Write
_SystemNative_GetGroups
_SystemNative_GetPwUidR
_SystemNative_GetPwNamR
_SystemNative_SearchPath
_SystemNative_SearchPath_TempDirectory
_SystemNative_FcntlSetFD
_SystemNative_MMap
_SystemNative_MUnmap
_SystemNative_MSync
_SystemNative_MAdvise
_SystemNative_ShmOpen
_SystemNative_ShmUnlink
_ios_register_button_click
_ios_set_text

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 25, 2023

Member

I believe only:

  • _ios_register_button_click
  • _ios_set_text

are required to be in this file, the other symbols are something Xamarin collects for a MySingleView app and is most likely not necessary for HelloiOS to work.
PS It would be good to also rename the file to something like referenced_symbols.list or symbols_to_keep (or *_preserve) rather than symbols.list

This comment has been minimized.

Copy link
@kotlarmilos

kotlarmilos Jan 25, 2023

Author Member

I didn't manage to run the app with only these two symbols. Do you have an idea how to identify which of the symbols are necessary?

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 25, 2023

Member

Is there a stack trace of the failure when the app is ran?

This comment has been minimized.

Copy link
@kotlarmilos

kotlarmilos Jan 30, 2023

Author Member

Here is the stack trace from iossimulator when keeping only the two mentioned symbols:

[14:53:20.6938730]   at Xamarin.Hosting.Services.LaunchApplicationInSimulatorInternalAsyncSimCtl (Xamarin.Hosting.SimulatorLaunchConfig config) [0x00555] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Hosting/Services.cs:1053 
[14:53:20.6939100]   at Xamarin.Hosting.Services.LaunchApplicationInSimulatorAsync (Xamarin.Hosting.SimulatorLaunchConfig config) [0x0038c] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Hosting/Services.cs:1171 
[14:53:20.6939150]   at Xamarin.Launcher.SimController.LaunchAsync (Xamarin.Hosting.SimulatorLaunchConfig config) [0x000de] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Launcher/controller-simulator.cs:689 
[14:53:20.6939180]   at Xamarin.Launcher.Driver.LaunchSimulatorAsync () [0x004a7] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Launcher/Main.cs:808 
[14:53:20.6939430]   at Xamarin.Utils.NSRunLoopExtensions.RunUntilTaskCompletion[T] (Foundation.NSRunLoop this, System.Threading.Tasks.Task`1[TResult] task) [0x00082] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Utils/Extensions.cs:35 
[14:53:20.6939590]   at Xamarin.Launcher.Driver.Main2 (System.String[] args) [0x00ba3] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Launcher/Main.cs:435 
[14:53:20.6939620]   at Xamarin.Launcher.Driver.Main (System.String[] args) [0x0006d] in /Users/builder/azdo/_work/2/s/tools/mlaunch/Xamarin.Hosting/Xamarin.Launcher/Main.cs:123 
[14:53:20.7041950] Process mlaunch exited with 1

It might rely on Xamarin launch framework and thus require the same symbols as for a Xamarin run.

This comment has been minimized.

Copy link
@ivanpovazan

ivanpovazan Jan 30, 2023

Member

What is the difference in size when only _ios_register_button_click and _ios_set_text are kept after stripping, compared to the full set of symbols specified in symbols.list file?

This comment has been minimized.

Copy link
@kotlarmilos

kotlarmilos Jan 30, 2023

Author Member

SOD difference is 4600 bytes. With only _ios_register_button_click and _ios_set_text SOD is 12695176 bytes while extended set SOD is 12699776 bytes.

0 comments on commit 840ee5b

Please sign in to comment.