Skip to content

Commit e206c52

Browse files
authored
[runtime] Optionally disable inlining (#8798)
The native runtime by default builds with function inlining enabled, making heavy use of the feature in order to generate faster code. However, when debugging a native crash inlining causes stack traces to point to unlikely locations, reporting the outer function as the crash location instead of the inlined function where crash actually happened. In order to make such debugging easier, do one of the following: * Export the `XA_NO_INLINE` environment variable to "true-ish" export XA_NO_INLINE=1 * Set the `$(DoNotInlineMonodroid)` MSBuild property to true, either by adding to `Configuration.Override.props`: <DoNotInlineMonodroid>true</DoNotInlineMonodroid>> or by specifying on the command-line: ./dotnet-local.sh build Xamarin.Android.sln -p:DoNotInlineMonodroid=true … This will force all normally inlined functions to be strictly preserved and kept separate. The generated code will be slower, but crash stack traces should be much more precise. Additionally, `strip`ing of the native shared runtime can be disabled, making it easier to get full debug symbols. This can similarly be enabled by doing one of the following: * Export the `XA_NO_STRIP` environment variable to "true-ish" export XA_NO_STRIP=1 * Set the `$(DoNotStripMonodroid)` MSBuild property to true, either by adding to `Configuration.Override.props`: <DoNotStripMonodroid>true</DoNotStripMonodroid>> or by specifying on the command-line: ./dotnet-local.sh build Xamarin.Android.sln -p:DoNotStripMonodroid=true … In a Debug configuration build of xamarin-android, `libmono-android*.so` will *not* be `strip`d by `src/monodroid`.
1 parent 385091a commit e206c52

File tree

8 files changed

+103
-15
lines changed

8 files changed

+103
-15
lines changed

Documentation/building/configuration.md

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
<!--toc:start-->
2+
- [Build Configuration](#build-configuration)
3+
- [Options suitable to use in builds for public use](#options-suitable-to-use-in-builds-for-public-use)
4+
- [Options suitable for local development](#options-suitable-for-local-development)
5+
- [Native runtime (`src/monodroid`)](#native-runtime-srcmonodroid)
6+
- [Disable function inlining](#disable-function-inlining)
7+
- [Don't strip the runtime shared libraries](#dont-strip-the-runtime-shared-libraries)
8+
<!--toc:end-->
9+
110
# Build Configuration
211

312
The Xamarin.Android build is heavily dependent on MSBuild, with the *intention*
@@ -10,6 +19,8 @@ However, some properties may need to be altered in order to suit your
1019
requirements, such as the location of a cache directory to store
1120
the Android SDK and NDK.
1221

22+
## Options suitable to use in builds for public use
23+
1324
To modify the build process, copy
1425
[`Configuration.Override.props.in`](../../Configuration.Override.props.in)
1526
to `Configuration.Override.props`, and edit the file as appropriate.
@@ -93,7 +104,7 @@ Overridable MSBuild properties include:
93104

94105
* `$(IgnoreMaxMonoVersion)`: Skip the enforcement of the `$(MonoRequiredMaximumVersion)`
95106
property. This is so that developers can run against the latest
96-
and greatest. But the build system can enforce the min and max
107+
and greatest. But the build system can enforce the min and max
97108
versions. The default is `true`, however on CI we use:
98109

99110
/p:IgnoreMaxMonoVersion=False
@@ -129,6 +140,43 @@ Overridable MSBuild properties include:
129140
* `4`: Mono 4.6 support.
130141
* `5`: Mono 4.8 and above support. This is the default.
131142

132-
* `$(AndroidEnableAssemblyCompression)`: Defaults to `True`. When enabled, all the
143+
* `$(AndroidEnableAssemblyCompression)`: Defaults to `True`. When enabled, all the
133144
assemblies placed in the APK will be compressed in `Release` builds. `Debug`
134145
builds are not affected.
146+
147+
## Options suitable for local development
148+
149+
### Native runtime (`src/monodroid`)
150+
151+
Note that in order for the native build settings to have full effect, one needs to make sure that
152+
the entire native runtime is rebuilt **and** that all `cmake` files are regenerated. This is true
153+
on the very first build, but rebuilds may require forcing the entire runtime to be rebuilt.
154+
155+
The simplest way to do it is to remove `src/monodroid/obj` and run the usual build from the
156+
repository's root directory.
157+
158+
#### Disable function inlining
159+
160+
The native runtime by default builds with function inlining enabled, making heavy use of
161+
the feature in order to generate faster code. However, when debugging a native crash inlining
162+
causes stack traces to point to unlikely locations, reporting the outer function as the crash
163+
location instead of the inlined function where crash actually happened. There are two ways to
164+
enable this mode of operation:
165+
166+
1. Export the `XA_NO_INLINE` environment variable before building either the entire repository
167+
or just `src/monodroid/`
168+
2. Set the MSBuild property `DoNotInlineMonodroid` to `true`, when building `src/monodroid/monodroid.csproj`
169+
170+
Doing either will force all normally inlined functions to be strictly preserved and kept
171+
separate. The generated code will be slower, but crash stack traces should be much more precise.
172+
173+
#### Don't strip the runtime shared libraries
174+
175+
Similar to the previous section, this option makes crash stack traces more informative. In normal
176+
builds, all the debugging information is stripped from the runtime shared libraries, thus making
177+
stack traces rarely point to anything more than the surrounding function name (which may sometimes
178+
be misleading, too). Just as for inlining, the no-strip mode can be enabled with one of two ways:
179+
180+
1. Export the `XA_NO_STRIP` environment variable before building either the entire repository
181+
or just `src/monodroid/`
182+
2. Set the MSBuild property `DoNotStripMonodroid` to `true`, when building `src/monodroid/monodroid.csproj`

build-tools/cmake/xa_macros.cmake

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ function(xa_common_prepare)
202202
-fno-strict-aliasing
203203
-ffunction-sections
204204
-funswitch-loops
205-
-finline-limit=300
206205
-Wa,-noexecstack
207206
-fPIC
208207
-g

src/monodroid/CMakeLists.txt

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,43 @@ set(CMAKE_C_STANDARD 11)
2929
set(CMAKE_C_STANDARD_REQUIRED ON)
3030
set(CMAKE_C_EXTENSIONS OFF)
3131

32+
if(CMAKE_BUILD_TYPE STREQUAL Debug)
33+
set(DEBUG_BUILD True)
34+
else()
35+
set(DEBUG_BUILD False)
36+
endif()
37+
38+
set(XA_NO_INLINE "$ENV{XA_NO_INLINE}")
39+
if(XA_NO_INLINE)
40+
set(DONT_INLINE_DEFAULT ON)
41+
else()
42+
set(DONT_INLINE_DEFAULT OFF)
43+
endif()
44+
45+
set(XA_NO_STRIP "$ENV{XA_NO_STRIP}")
46+
if(XA_NO_STRIP OR DEBUG_BUILD)
47+
set(STRIP_DEBUG_DEFAULT OFF)
48+
endif()
49+
3250
option(ENABLE_CLANG_ASAN "Enable the clang AddressSanitizer support" OFF)
3351
option(ENABLE_CLANG_UBSAN "Enable the clang UndefinedBehaviorSanitizer support" OFF)
3452

3553
if(ENABLE_CLANG_ASAN OR ENABLE_CLANG_UBSAN)
54+
# ASAN and UBSAN always require the debug symbols to be left in the binary
3655
set(STRIP_DEBUG_DEFAULT OFF)
3756
set(ANALYZERS_ENABLED ON)
3857
else()
39-
set(STRIP_DEBUG_DEFAULT ON)
58+
if(NOT XA_NO_STRIP)
59+
set(STRIP_DEBUG_DEFAULT ON)
60+
endif()
4061
set(ANALYZERS_ENABLED OFF)
4162
endif()
4263

4364
option(ENABLE_TIMING "Build with timing support" OFF)
4465
option(STRIP_DEBUG "Strip debugging information when linking" ${STRIP_DEBUG_DEFAULT})
4566
option(DISABLE_DEBUG "Disable the built-in debugging code" OFF)
4667
option(USE_CCACHE "Use ccache, if found, to speed up recompilation" ON)
68+
option(DONT_INLINE "Do not inline any functions which are usually inlined, to get better stack traces" ${DONT_INLINE_DEFAULT})
4769

4870
if(USE_CCACHE)
4971
if(CMAKE_CXX_COMPILER MATCHES "/ccache/")
@@ -58,11 +80,7 @@ if(USE_CCACHE)
5880
endif()
5981
endif()
6082

61-
if(CMAKE_BUILD_TYPE STREQUAL Debug)
62-
set(DEBUG_BUILD True)
63-
else()
64-
set(DEBUG_BUILD False)
65-
endif()
83+
6684

6785
if(ANDROID_STL STREQUAL none)
6886
set(USES_LIBSTDCPP False)
@@ -179,6 +197,10 @@ add_compile_definitions(MONO_DLL_EXPORT)
179197
add_compile_definitions(NET)
180198
add_compile_definitions(JI_NO_VISIBILITY)
181199

200+
if(DONT_INLINE)
201+
add_compile_definitions(NO_INLINE)
202+
endif()
203+
182204
if(DEBUG_BUILD AND NOT DISABLE_DEBUG)
183205
add_compile_definitions(DEBUG)
184206
endif()
@@ -293,6 +315,13 @@ endif()
293315

294316
if(STRIP_DEBUG)
295317
list(APPEND LOCAL_COMMON_LINKER_ARGS LINKER:-S)
318+
else()
319+
# When not stripping symbols, we likely want to have precise stack traces, so
320+
# we won't omit frame pointers
321+
list(APPEND LOCAL_COMMON_COMPILER_ARGS
322+
-fno-omit-frame-pointer
323+
-fno-limit-debug-info
324+
)
296325
endif()
297326

298327
# Parameters to both functions are (all required):

src/monodroid/jni/cpp-util.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ do_abort_unless (const char* fmt, ...)
3333
#define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_)
3434
#define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_)
3535

36+
// Helpers to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any
37+
// of the macros present.
38+
#define PD_LOG_LOCATION() log_info_nocheck (LOG_DEFAULT, "loc: %s:%d (%s)", __FILE__, __LINE__, __FUNCTION__)
39+
#define PD_LOG_FUNCTION() log_info_nocheck (LOG_DEFAULT, "%s [%s:%d]", __PRETTY_FUNCTION__, __FILE__, __LINE__)
40+
3641
namespace xamarin::android
3742
{
3843
template <typename T>

src/monodroid/jni/embedded-assemblies.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ namespace xamarin::android::internal {
282282
&& ((application_config.have_runtime_config_blob && runtime_config_blob_found) || !application_config.have_runtime_config_blob);
283283
}
284284

285-
static force_inline c_unique_ptr<char> to_utf8 (const MonoString *s) noexcept
285+
force_inline static c_unique_ptr<char> to_utf8 (const MonoString *s) noexcept
286286
{
287287
return c_unique_ptr<char> (mono_string_to_utf8 (const_cast<MonoString*>(s)));
288288
}

src/monodroid/jni/helpers.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace xamarin::android
1616
{
1717
public:
1818
template<typename Ret, typename P1, typename P2>
19-
static force_inline Ret add_with_overflow_check (const char *file, uint32_t line, P1 a, P2 b) noexcept
19+
force_inline static Ret add_with_overflow_check (const char *file, uint32_t line, P1 a, P2 b) noexcept
2020
{
2121
Ret ret;
2222

@@ -40,7 +40,7 @@ namespace xamarin::android
4040
// fail
4141
//
4242
template<typename Ret>
43-
static force_inline Ret multiply_with_overflow_check (const char *file, uint32_t line, size_t a, size_t b) noexcept
43+
force_inline static Ret multiply_with_overflow_check (const char *file, uint32_t line, size_t a, size_t b) noexcept
4444
{
4545
Ret ret;
4646

src/monodroid/jni/platform-compat.hh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55

66
static inline constexpr int DEFAULT_DIRECTORY_MODE = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
77

8-
#define force_inline inline __attribute__((always_inline))
9-
#define never_inline __attribute__((noinline))
8+
#if defined(NO_INLINE)
9+
#define force_inline [[gnu::noinline]]
10+
#define inline_calls [[gnu::flatten]]
11+
#else
12+
#define force_inline [[gnu::always_inline]]
13+
#define inline_calls
14+
#endif
1015

1116
#endif // __PLATFORM_COMPAT_HH

src/monodroid/monodroid.targets

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@
7575
Inputs="@(_ConfigureRuntimesInputs)"
7676
Outputs="@(_ConfigureRuntimesOutputs)">
7777
<PropertyGroup>
78-
<_CmakeAndroidFlags>--debug-output -GNinja -DCMAKE_MAKE_PROGRAM="$(NinjaPath)" -DXA_BUILD_CONFIGURATION=$(Configuration) -DXA_LIB_TOP_DIR=$(MicrosoftAndroidSdkOutDir) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DMONO_PATH="$(MonoSourceFullPath)" -DANDROID_STL="none" -DANDROID_CPP_FEATURES="no-rtti no-exceptions" -DANDROID_TOOLCHAIN=clang -DCMAKE_TOOLCHAIN_FILE="$(AndroidNdkDirectory)/build/cmake/android.toolchain.cmake" -DANDROID_NDK=$(AndroidNdkDirectory)</_CmakeAndroidFlags>
78+
<_NoInline Condition=" '$(DoNotInlineMonodroid)' == 'true' ">-DDONT_INLINE=ON</_NoInline>
79+
<_NoStrip Condition=" '$(DoNotStripMonodroid)' == 'true' ">-DSTRIP_DEBUG=OFF</_NoStrip>
80+
<_CmakeAndroidFlags>$(_NoInline) $(_NoStrip) --debug-output -GNinja -DCMAKE_MAKE_PROGRAM="$(NinjaPath)" -DXA_BUILD_CONFIGURATION=$(Configuration) -DXA_LIB_TOP_DIR=$(MicrosoftAndroidSdkOutDir) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DMONO_PATH="$(MonoSourceFullPath)" -DANDROID_STL="none" -DANDROID_CPP_FEATURES="no-rtti no-exceptions" -DANDROID_TOOLCHAIN=clang -DCMAKE_TOOLCHAIN_FILE="$(AndroidNdkDirectory)/build/cmake/android.toolchain.cmake" -DANDROID_NDK=$(AndroidNdkDirectory)</_CmakeAndroidFlags>
7981
</PropertyGroup>
8082
<MakeDir Directories="@(_OutputDirsToCreate)"/>
8183
<ItemGroup>

0 commit comments

Comments
 (0)