From e40e24b4cdc902c82cfe0a140cdb284611104242 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Tue, 10 Sep 2019 10:16:07 +0200 Subject: [PATCH] [aot] move method_addresses to data.rel.so section to avoid text relocations (#16729) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit [aot] move method_addresses to data.rel.so section to avoid text relocations Another revert of a revert! 🎉 After some discussions with @grendello and @radekdoulik, we came up with this solution. It's a better attempt to fix https://github.com/mono/mono/issues/16369 as it (1) works within the restrictions of Android 10 and (2) still works for armv7 AOT. `.text` relocations aren't allowed in Android 10 (and this change shouldn't hurt on Linux). AOT compilation: ```console $ MONO_PATH=/Users/lewurm/Downloads/xamarin.android-oss-v10.0.99.136_Darwin-x86_64_pr_766265b9-Debug/bin/Debug/lib/xamarin.android/xbuild-frameworks/MonoAndroid/v1.0/ \ MONO_ENV_OPTIONS="" \ ./sdks/out/android-cross-arm-release/bin/armv7-linux-android-mono-sgen \ --aot=keep-temps,outfile=here.dll.so,asmwriter,mtriple=armv7-linux-gnueabi,tool-prefix=/Users/lewurm/android-toolchain/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-,ld-flags= \ ~/Downloads/xamarin.android-oss-v10.0.99.136_Darwin-x86_64_pr_766265b9-Debug/bin/Debug/lib/xamarin.android/xbuild-frameworks/MonoAndroid/v10.0/Mono.Android.dll Mono Ahead of Time compiler - compiling assembly /Users/lewurm/Downloads/xamarin.android-oss-v10.0.99.136_Darwin-x86_64_pr_766265b9-Debug/bin/Debug/lib/xamarin.android/xbuild-frameworks/MonoAndroid/v10.0/Mono.Android.dll AOTID 7DDD05DA-37E0-813A-8C27-3E1634391BB3 Compiled: 144382/144382 Executing the native assembler: "/Users/lewurm/android-toolchain/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-as" -mfpu=vfp3 -o /var/folders/p3/5279mmgn1p575bz28j0ngfqw0000gn/T/mono_aot_550yHJ.o /var/folders/p3/5279mmgn1p575bz28j0ngfqw0000gn/T/mono_aot_550yHJ Executing the native linker: "/Users/lewurm/android-toolchain/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ld" -shared -o here.dll.so.tmp /var/folders/p3/5279mmgn1p575bz28j0ngfqw0000gn/T/mono_aot_550yHJ.o Stripping the binary: "/Users/lewurm/android-toolchain/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-strip" --strip-symbol=\$a --strip-symbol=\$d here.dll.so.tmp Retained input file. JIT time: 15031 ms, Generation time: 7374 ms, Assembly+Link time: 75130 ms. ``` Before: ```console $ grep -C 6 'method_addresses:' /var/folders/p3/5279mmgn1p575bz28j0ngfqw0000gn/T/mono_aot_550yHJ .align 3 jit_code_end: .byte 0,0,0,0 .text 1 .align 3 method_addresses: .local method_addresses .type method_addresses,#function ldr pc,=.Lm_0 .ltorg ldr pc,=.Lm_1 .ltorg $ arm-linux-androideabi-readelf -a here.dll.so | grep -i textrel 0x00000016 (TEXTREL) 0x0 0x0000001e (FLAGS) TEXTREL ``` After switching to `.data.rel.so`: ```console $ grep -C 6 'method_addresses:' /var/folders/p3/5279mmgn1p575bz28j0ngfqw0000gn/T/mono_aot_1YhAgn # assembly file produced by AOT compiler jit_code_end: .byte 0,0,0,0 .section ".data.rel.ro" .subsection 0 .align 3 method_addresses: .local method_addresses .type method_addresses,#object ldr pc,=.Lm_0 .ltorg ldr pc,=.Lm_1 .ltorg $ arm-linux-androideabi-readelf -a here.dll.so | grep -i textrel $ echo $? 1 ``` --- mono/mini/aot-compiler.c | 38 ++++++++++++++++++++++++++++++++------ mono/mini/aot-runtime.c | 7 +++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index cc1059958eb..0909752223d 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -106,6 +106,12 @@ get_method_nofail (MonoClass *klass, const char *method_name, int param_count, i #define EMIT_WIN32_UNWIND_INFO #endif +#if defined(TARGET_ANDROID) || defined(__linux__) +#define RODATA_REL_SECT ".data.rel.ro" +#else +#define RODATA_REL_SECT ".text" +#endif + #if defined(__linux__) #define RODATA_SECT ".rodata" #elif defined(TARGET_MACH) @@ -1595,6 +1601,21 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern g_assert_not_reached (); #endif } + +static void +arch_emit_label_address (MonoAotCompile *acfg, const char *target, gboolean external_call, gboolean thumb, MonoJumpInfo *ji, int *call_size) +{ +#if defined(TARGET_ARM) && defined(TARGET_ANDROID) + /* binutils ld does not support branch islands on arm32 */ + if (!thumb) { + emit_unset_mode (acfg); + fprintf (acfg->fp, "ldr pc,=%s\n", target); + fprintf (acfg->fp, ".ltorg\n"); + *call_size = 8; + } else +#endif + arch_emit_direct_call (acfg, target, external_call, thumb, ji, call_size); +} #endif /* @@ -9923,13 +9944,18 @@ emit_code (MonoAotCompile *acfg) * To work around linker issues, we emit a table of branches, and disassemble them at runtime. * This is PIE code, and the linker can update it if needed. */ - +#if defined(TARGET_ANDROID) || defined(__linux__) + gboolean is_func = FALSE; +#else + gboolean is_func = TRUE; +#endif + sprintf (symbol, "method_addresses"); - emit_section_change (acfg, ".text", 1); + emit_section_change (acfg, RODATA_REL_SECT, !!is_func); emit_alignment_code (acfg, 8); - emit_info_symbol (acfg, symbol, TRUE); + emit_info_symbol (acfg, symbol, is_func); if (acfg->aot_opts.write_symbols) - emit_local_symbol (acfg, symbol, "method_addresses_end", TRUE); + emit_local_symbol (acfg, symbol, "method_addresses_end", is_func); emit_unset_mode (acfg); if (acfg->need_no_dead_strip) fprintf (acfg->fp, " .no_dead_strip %s\n", symbol); @@ -9939,9 +9965,9 @@ emit_code (MonoAotCompile *acfg) int call_size; if (!ignore_cfg (acfg->cfgs [i])) { - arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size); + arch_emit_label_address (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size); } else { - arch_emit_direct_call (acfg, symbol, FALSE, FALSE, NULL, &call_size); + arch_emit_label_address (acfg, symbol, FALSE, FALSE, NULL, &call_size); } #endif } diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index bcf5e5828cc..02dd2247e72 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1940,6 +1940,11 @@ get_call_table_entry (void *table, int index) guint32 ins; gint32 offset; + ins_addr = (guint32 *)table + (index * 2); + if ((guint32) *ins_addr == (guint32 ) 0xe51ff004) { // ldr pc, =