On 2016-03-08, at 1:07 PM, Aurelien Jarno wrote: > Dear HPPA porters, > > The glibc testsuite in version 2.22 which has been uploaded to sid 2 > days ago fails to pass on both phantom and sibaris build daemons. > There seems to be 3 failures that are regressions compared to glibc > 2.21: > > FAIL: debug/backtrace-tst
I have looked at the above failure. It seems the implementation of DL_LOOKUP_ADDRESS(addr) needs improvement. It's not possible to detect a function pointer with 100% certainty given an arbitrary address. However, the above test passes with the following change. The function pointer checks are tightened and read access checks are added to help ensure the routine doesn't fault. Dave -- John David Anglin dave.ang...@bell.net
diff --git a/sysdeps/hppa/dl-fptr.c b/sysdeps/hppa/dl-fptr.c index 083242b..79032a6 100644 --- a/sysdeps/hppa/dl-fptr.c +++ b/sysdeps/hppa/dl-fptr.c @@ -331,20 +331,36 @@ elf_machine_resolve (void) return addr; } +static inline int +_dl_read_access_allowed (unsigned int *addr) +{ + int result; + + asm ("proberi (%1),3,%0" : "=r" (result) : "r" (addr) : ); + + return result; +} + ElfW(Addr) _dl_lookup_address (const void *address) { ElfW(Addr) addr = (ElfW(Addr)) address; unsigned int *desc, *gptr; - /* Check for special cases. */ - if ((int) addr == -1 - || (unsigned int) addr < 4096 - || !((unsigned int) addr & 2)) + /* Return ADDR if the least-significant two bits of ADDR are not consistent + with ADDR being a linker defined function pointer. The normal value for + a code address in a backtrace is 3. */ + if (((unsigned int) addr & 3) != 2) + return addr; + + /* Handle special case where ADDR points to page 0. */ + if ((unsigned int) addr < 4096) return addr; /* Clear least-significant two bits from descriptor address. */ desc = (unsigned int *) ((unsigned int) addr & ~3); + if (!_dl_read_access_allowed (desc)) + return addr; /* Check if descriptor requires resolution. The following trampoline is used in each global offset table for function resolution: @@ -359,6 +375,9 @@ _dl_lookup_address (const void *address) got: .word _DYNAMIC .word "struct link map address" */ gptr = (unsigned int *) desc[0]; + if (!_dl_read_access_allowed (gptr)) + return addr; + if (gptr[0] == 0xea9f1fdd /* b,l .-12,r20 */ && gptr[1] == 0xd6801c1e /* depwi 0,31,2,r20 */ && (ElfW(Addr)) gptr[2] == elf_machine_resolve ())