aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Prichard <rprichard@google.com>2018-06-28 00:21:50 (GMT)
committerRyan Prichard <rprichard@google.com>2018-06-28 21:03:10 (GMT)
commit4089f56e6c7438eb98cb86c249cf0c01e22219c5 (patch)
tree80affcdf249524cf1414767b8eb40f00ca8acd0b
parent81788f3d99d2c5952fa9a6d673e8d6a53b76d511 (diff)
downloadtoolchain_gcc-4089f56e6c7438eb98cb86c249cf0c01e22219c5.zip
toolchain_gcc-4089f56e6c7438eb98cb86c249cf0c01e22219c5.tar.gz
toolchain_gcc-4089f56e6c7438eb98cb86c249cf0c01e22219c5.tar.bz2
libgcc: work around old Bionic loader bug
dl_iterate_phdr returns a 0 load_base for a PIE executable when it should return the address where the executable was loaded (e.g. the load base or load bias). Recalculate the load base when it is zero. This recalculation should work on any ELF file with a PT_PHDR segment -- it will calculate 0 for a non-PIE executable. The load base is added to an ELF virtual address to produce a run-time address. Recalculate it by subtracting the PT_PHDR's virtual address from its run-time address. Bug: https://github.com/android-ndk/ndk/issues/505 Test: manual Test: run NDK tests (./checkbuild.py && ./run_tests.py) Change-Id: I7de46c07a8b04e794b59f07b4d554238cfd6d5d9
-rw-r--r--gcc-4.9/libgcc/unwind-dw2-fde-dip.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/gcc-4.9/libgcc/unwind-dw2-fde-dip.c b/gcc-4.9/libgcc/unwind-dw2-fde-dip.c
index d6c0521..db98b59 100644
--- a/gcc-4.9/libgcc/unwind-dw2-fde-dip.c
+++ b/gcc-4.9/libgcc/unwind-dw2-fde-dip.c
@@ -183,6 +183,30 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
p_eh_frame_hdr = NULL;
p_dynamic = NULL;
+#if defined(__BIONIC__) && defined(__i386__)
+ if (load_base == 0)
+ {
+ /* A load_base of 0 normally indicates a non-PIE executable. There was a
+ bug in Android's dynamic loader prior to API 18, though, where
+ dl_iterate_phdr incorrectly passed a load_base of 0 for a PIE
+ executable. Work around the bug by recalculating load_base using
+ the PT_PHDR segment. This code path isn't needed for arm32, because
+ arm32 didn't have dl_iterate_phdr until API 21.
+ https://github.com/android-ndk/ndk/issues/505. */
+ size_t i;
+ for (i = 0; i < info->dlpi_phnum; ++i)
+ {
+ const ElfW(Phdr) *fix_phdr = &info->dlpi_phdr[i];
+ if (fix_phdr->p_type == PT_PHDR)
+ {
+ load_base = (_Unwind_Ptr) info->dlpi_phdr -
+ (_Unwind_Ptr) fix_phdr->p_vaddr;
+ break;
+ }
+ }
+ }
+#endif
+
struct frame_hdr_cache_element *prev_cache_entry = NULL,
*last_cache_entry = NULL;