From 692cd112f21ce00a22b7b9893b2cc6aa834a852e Mon Sep 17 00:00:00 2001 From: Nikolay Arhipov Date: Thu, 1 Jun 2023 13:05:51 +0300 Subject: [PATCH] Fixed for veneers generated by linker for interworking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A compiler can do tail call optimizations, emitting R_ARM_JUMP24 relocation instead of a normal call. If this call has interworking (was from arm function to a thumb function or vice versa), binutils produces a veneer, because it needs to do a switch. By default these veneers do jumps to an absolute address. This patch forces ld to produce veneers for position independent binaries. tldr; no need for `--no-optimize-sibling-calls` anymore, sibling calls will ✨ work ✨ An example of veneer before this patch: ``` 81000010 <__func_thumb_from_arm>: 81000010: e51ff004 ldr pc, [pc, #-4] @ 0x81000014 <$d> 81000014 <$d>: 81000014: 01 00 00 81 .word 0x81000001 ``` and after: ``` 81000010 <__func_thumb_from_arm>: 81000010: e59fc004 ldr r12, [pc, #4] @ 0x8100001c <$d> 81000014: e08fc00c add r12, pc, r12 81000018: e12fff1c bx r12 8100001c <$d>: 8100001c: e5 ff ff ff .word 0xffffffe5 ``` --- CMakeLists.txt | 1 + .../binutils/0004-fix-interworking-veneers.patch | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 patches/binutils/0004-fix-interworking-veneers.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 1efa7f0..b8765ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,7 @@ function(toolchain_deps toolchain_deps_dir toolchain_install_dir toolchain_suffi patch -d -p3 -t -N < ${PROJECT_SOURCE_DIR}/patches/binutils/0001-vita.patch && patch -d -p1 -t -N < ${PROJECT_SOURCE_DIR}/patches/binutils/0002-fix-broken-reloc.patch && patch -d -p3 -t -N < ${PROJECT_SOURCE_DIR}/patches/binutils/0003-fix-elf-vaddr.patch + && patch -d -p3 -t -N < ${PROJECT_SOURCE_DIR}/patches/binutils/0004-fix-interworking-veneers.patch CONFIGURE_COMMAND ${compiler_flags} ${wrapper_command} /configure --build=${build_native} --host=${toolchain_host} diff --git a/patches/binutils/0004-fix-interworking-veneers.patch b/patches/binutils/0004-fix-interworking-veneers.patch new file mode 100644 index 0000000..de2cde6 --- /dev/null +++ b/patches/binutils/0004-fix-interworking-veneers.patch @@ -0,0 +1,13 @@ +diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em +index a9ac12d6..627c9086 100644 +--- a/src/binutils/ld/emultempl/armelf.em ++++ b/src/binutils/ld/emultempl/armelf.em +@@ -41,7 +41,7 @@ static struct elf32_arm_params params = + BFD_ARM_STM32L4XX_FIX_NONE, /* stm32l4xx_fix */ + 0, /* no_enum_size_warning */ + 0, /* no_wchar_size_warning */ +- 0, /* pic_veneer */ ++ 1, /* pic_veneer */ + -1, /* fix_cortex_a8 */ + 1, /* fix_arm1176 */ + -1, /* merge_exidx_entries */