[PATCH] S390: Refactor ifunc resolvers due to false debuginfo.
Stefan Liebler
stli@linux.vnet.ibm.com
Fri Jun 10 10:29:00 GMT 2016
Hi,
The current s390 ifunc resolver for vector optimized functions uses
something like that:
extern void *__resolve___strlen(unsigned long int dl_hwcap) asm (strlen);
asm (".type strlen, %gnu_indirect_function");
This leads to false debug information:
objdump --dwarf=info libc.so:
...
<1><1e6424>: Abbrev Number: 43 (DW_TAG_subprogram)
<1e6425> DW_AT_external : 1
<1e6425> DW_AT_name : (indirect string, offset: 0x1146e):
__resolve___strlen
<1e6429> DW_AT_decl_file : 1
<1e642a> DW_AT_decl_line : 23
<1e642b> DW_AT_linkage_name: (indirect string, offset: 0x1147a):
strlen
<1e642f> DW_AT_prototyped : 1
<1e642f> DW_AT_type : <0x1e4ccd>
<1e6433> DW_AT_low_pc : 0x998e0
<1e643b> DW_AT_high_pc : 0x16
<1e6443> DW_AT_frame_base : 1 byte block: 9c
(DW_OP_call_frame_cfa)
<1e6445> DW_AT_GNU_all_call_sites: 1
<1e6445> DW_AT_sibling : <0x1e6459>
<2><1e6449>: Abbrev Number: 44 (DW_TAG_formal_parameter)
<1e644a> DW_AT_name : (indirect string, offset: 0x1845):
dl_hwcap
<1e644e> DW_AT_decl_file : 1
<1e644f> DW_AT_decl_line : 23
<1e6450> DW_AT_type : <0x1e4c8d>
<1e6454> DW_AT_location : 0x122115 (location list)
...
The debuginfo for the ifunc-resolver function contains the
DW_AT_linkage_name field, which names the real function name "strlen".
If you perform an inferior function call to strlen in lldb, then it
fails due tosomething like that:
"error: no matching function for call to 'strlen'
candidate function not viable: no known conversion from 'const char [6]'
to 'unsigned long' for 1st argument"
The unsigned long is the dl_hwcap argument of the resolver function.
The strlen function itself has no debufinfo.
The s390 ifunc resolver for memset & co uses something like that:
asm (".globl FUNC"
".type FUNC, @gnu_indirect_function"
".set FUNC, __resolve_FUNC");
This way the debuginfo for the ifunc-resolver function does not contain
the DW_AT_linkage_name field and the real function has no debuginfo, too.
Using this strategy for the vector optimized functions leads to some
troubles for functions like strnlen. Here we have __strnlen and a
weak alias strnlen. The __strnlen function is the ifunc function,
which is realized with the asm-statement above. The weak_alias-macro
can't be used here due to undefined symbol:
gcc ../sysdeps/s390/multiarch/strnlen.c -c ...
In file included from <command-line>:0:0:
../sysdeps/s390/multiarch/strnlen.c:28:24: error: âstrnlenâ aliased to
undefined symbol â__strnlenâ
weak_alias (__strnlen, strnlen)
^
./../include/libc-symbols.h:111:26: note: in definition of macro
â_weak_aliasâ
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
^
../sysdeps/s390/multiarch/strnlen.c:28:1: note: in expansion of macro
âweak_aliasâ
weak_alias (__strnlen, strnlen)
^
make[2]: *** [build/string/strnlen.o] Error 1
As the __strnlen function is defined with asm-statements the function
name __strnlen isn't known by gcc. But the weak alias can also be done
with an asm statement to resolve this issue:
__asm__ (".weak strnlen\n\t"
".set strnlen,__strnlen\n");
In order to use the weak_alias macro, gcc needs to know the ifunc
function. The minimum gcc to build glibc is currently 4.7, which
supports attribute((ifunc)). See
https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html.
Usage is something like that:
__typeof (FUNC) FUNC __attribute__ ((ifunc ("__resolve_FUNC")));
Then gcc produces the same .globl, .type, .set assembler instructions
like above. And the debuginfo does not contain the DW_AT_linkage_name
field and there is no debuginfo for the real function, too.
But in order to get it work, there is also some extra work to do.
Currently, the glibc internal symbol on s390x e.g. __GI___strnlen is
not the ifunc symbol, but the fallback __strnlen_c symbol. Thus I have
to omit the libc_hidden_def macro in strnlen.c (here is the ifunc
function __strnlen) because it is already handled in strnlen-c.c
(here is __strnlen_c).
Due to libc_hidden_proto (__strnlen) in string.h, compiling fails:
gcc ../sysdeps/s390/multiarch/strnlen.c -c ...
In file included from <command-line>:0:0:
../sysdeps/s390/multiarch/strnlen.c:53:24: error: âstrnlenâ aliased to
undefined symbol â__strnlenâ
weak_alias (__strnlen, strnlen)
^
./../include/libc-symbols.h:111:26: note: in definition of macro
â_weak_aliasâ
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
^
../sysdeps/s390/multiarch/strnlen.c:53:1: note: in expansion of macro
âweak_aliasâ
weak_alias (__strnlen, strnlen)
^
make[2]: *** [build/string/strnlen.os] Error 1
I have to redirect the prototypes for __strnlen in string.h and create
a copy of the prototype for using as ifunc function:
# define __strnlen __redirect___strnlen
# include <string.h>
# undef __strnlen
extern __typeof (__redirect___strnlen) __libc___strnlen;
__typeof (__libc___strnlen) __libc___strnlen __attribute__ ((ifunc
("__resolve_strnlen")));
strong_alias (__libc___strnlen, __strnlen)
weak_alias (__libc___strnlen, strnlen)
This way there is no trouble with the internal __GI_* symbols.
Glibc builds fine with this construct and the debuginfo is "correct".
For functions without a __GI_* symbol like memccpy, this redirection is
not needed.
This patch adjusts the s390 specific ifunc helper macros in ifunc-
resolve.h to use gcc attribute ifunc to get rid of the false debuginfo.
Therefore the redirection construct is applied where needed.
Is this okay to commit?
Does anybody know a better solution for the trouble with internal symbols?
Perhaps in future we can switch some of the internal symbols __GI_*
from the fallback variant to the ifunc function. But this change is
also not straightforward due to a segmentation fault while linking
libc.so with older binutils.
Bye
Stefan
ChangeLog:
* sysdeps/s390/multiarch/ifunc-resolve.h
(s390_vx_libc_ifunc2): Use gcc attribute ifunc for ifunc symbols
and make resolver function static.
(s390_libc_ifunc): Align as most as possible to
s390_vx_libc_ifunc2.
* sysdeps/s390/multiarch/memchr.c: Redirect ifunced function in
header and create a copy of the prototype for using as ifunc
function.
* sysdeps/s390/multiarch/mempcpy.c: Likewise.
* sysdeps/s390/multiarch/rawmemchr.c: Likewise.
* sysdeps/s390/multiarch/stpcpy.c: Likewise.
* sysdeps/s390/multiarch/stpncpy.c: Likewise.
* sysdeps/s390/multiarch/strcat.c: Likewise.
* sysdeps/s390/multiarch/strchr.c: Likewise.
* sysdeps/s390/multiarch/strcmp.c: Likewise.
* sysdeps/s390/multiarch/strcpy.c: Likewise.
* sysdeps/s390/multiarch/strcspn.c: Likewise.
* sysdeps/s390/multiarch/strlen.c: Likewise.
* sysdeps/s390/multiarch/strncmp.c: Likewise.
* sysdeps/s390/multiarch/strncpy.c: Likewise.
* sysdeps/s390/multiarch/strnlen.c: Likewise.
* sysdeps/s390/multiarch/strpbrk.c: Likewise.
* sysdeps/s390/multiarch/strrchr.c: Likewise.
* sysdeps/s390/multiarch/strspn.c: Likewise.
* sysdeps/s390/multiarch/wcschr.c: Likewise.
* sysdeps/s390/multiarch/wcscmp.c: Likewise.
* sysdeps/s390/multiarch/wcspbrk.c: Likewise.
* sysdeps/s390/multiarch/wcsspn.c: Likewise.
* sysdeps/s390/multiarch/wmemchr.c: Likewise.
* sysdeps/s390/multiarch/wmemset.c: Likewise.
* sysdeps/s390/s390-32/multiarch/memcmp.c: Likewise.
* sysdeps/s390/s390-32/multiarch/memcpy.c: Likewise.
* sysdeps/s390/s390-32/multiarch/memset.c: Likewise.
* sysdeps/s390/s390-64/multiarch/memcmp.c: Likewise.
* sysdeps/s390/s390-64/multiarch/memcpy.c: Likewise.
* sysdeps/s390/s390-64/multiarch/memset.c: Likewise.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 20160610_ifunc_debuginfo.patch
Type: text/x-patch
Size: 31874 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20160610/1590d9ff/attachment.bin>
More information about the Libc-alpha
mailing list