Skip to content

Commit 9da48f0

Browse files
committed
[runtime] Optionally disable inlining
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, the `XA_NO_INLINE` environment property may be exported before building the repository. 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. Also add support for the `XA_NO_STRIP` variable which makes it easy to produce runtime shared libraries with full debug symbols. In normal builds, all the debugging information is stripped from the runtime shared libraries, thus making stack traces rarely point to anything more than the surrounding function name (which may sometimes be misleading, too). The `XA_NO_STRIP` environment variable can be exported before building the native runtime in order to leave the symbols in the resulting shared library.
1 parent d8f818d commit 9da48f0

File tree

7 files changed

+83
-9
lines changed

7 files changed

+83
-9
lines changed

Documentation/building/configuration.md

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
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+
<!--toc:end-->
7+
18
# Build Configuration
29

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

20+
## Options suitable to use in builds for public use
21+
1322
To modify the build process, copy
1423
[`Configuration.Override.props.in`](../../Configuration.Override.props.in)
1524
to `Configuration.Override.props`, and edit the file as appropriate.
@@ -93,7 +102,7 @@ Overridable MSBuild properties include:
93102

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

99108
/p:IgnoreMaxMonoVersion=False
@@ -129,6 +138,35 @@ Overridable MSBuild properties include:
129138
* `4`: Mono 4.6 support.
130139
* `5`: Mono 4.8 and above support. This is the default.
131140

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

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: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,37 @@ else()
3535
set(CCACHE_OPTION_DEFAULT ON)
3636
endif()
3737

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)
47+
set(STRIP_DEBUG_DEFAULT OFF)
48+
endif()
49+
3850
option(ENABLE_CLANG_ASAN "Enable the clang AddressSanitizer support" OFF)
3951
option(ENABLE_CLANG_UBSAN "Enable the clang UndefinedBehaviorSanitizer support" OFF)
4052

4153
if(ENABLE_CLANG_ASAN OR ENABLE_CLANG_UBSAN)
54+
# ASAN and UBSAN always require the debug symbols to be left in the binary
4255
set(STRIP_DEBUG_DEFAULT OFF)
4356
set(ANALYZERS_ENABLED ON)
4457
else()
45-
set(STRIP_DEBUG_DEFAULT ON)
58+
if(NOT XA_NO_STRIP)
59+
set(STRIP_DEBUG_DEFAULT ON)
60+
endif()
4661
set(ANALYZERS_ENABLED OFF)
4762
endif()
4863

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

5470
if((MINGW OR NOT WIN32) AND USE_CCACHE)
5571
if(CMAKE_CXX_COMPILER MATCHES "/ccache/")
@@ -271,6 +287,10 @@ add_compile_definitions(MONO_DLL_EXPORT)
271287
add_compile_definitions(NET)
272288
add_compile_definitions(JI_NO_VISIBILITY)
273289

290+
if(DONT_INLINE)
291+
add_compile_definitions(NO_INLINE)
292+
endif()
293+
274294
if(DEBUG_BUILD AND NOT DISABLE_DEBUG)
275295
add_compile_definitions(DEBUG)
276296
endif()
@@ -422,6 +442,13 @@ endif()
422442

423443
if(STRIP_DEBUG)
424444
list(APPEND LOCAL_COMMON_LINKER_ARGS LINKER:-S)
445+
else()
446+
# When not stripping symbols, we likely want to have precise stack traces, so
447+
# we won't omit frame pointers
448+
list(APPEND LOCAL_COMMON_COMPILER_ARGS
449+
-fno-omit-frame-pointer
450+
-fno-limit-debug-info
451+
)
425452
endif()
426453

427454
# 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
@@ -248,7 +248,7 @@ namespace xamarin::android::internal {
248248
;
249249
}
250250

251-
static force_inline c_unique_ptr<char> to_utf8 (const MonoString *s) noexcept
251+
force_inline static c_unique_ptr<char> to_utf8 (const MonoString *s) noexcept
252252
{
253253
return c_unique_ptr<char> (mono_string_to_utf8 (const_cast<MonoString*>(s)));
254254
}

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

0 commit comments

Comments
 (0)