This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: RFC: Automatically test IFUNC implementations
On Wed, Sep 26, 2012 at 9:25 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Sep 26, 2012 at 9:11 AM, Richard Henderson <rth@twiddle.net> wrote:
>> On 09/24/2012 08:55 AM, H.J. Lu wrote:
>>> extern __typeof (memcpy) __memcpy_sse2;
>>> extern __typeof (memcpy) __memcpy_ssse3;
>>> extern __typeof (memcpy) __memcpy_ssse3_back;
>>>
>>> static const struct libc_func_test memcpy_list[] =
>>> {
>>> LIBC_FUNC_INIT (__memcpy_ssse3_back),
>>> LIBC_FUNC_INIT (__memcpy_ssse3),
>>> LIBC_FUNC_INIT (__memcpy_sse2),
>>> { NULL, NULL },
>>> };
>> ...
>>> const struct libc_func_test *
>>> __libc_func (const char *name)
>>
>>
>> Given that we're talking about building all shipped libcs with __libc_func included I think we should consider a different interface. One that does not require so many runtime relocations in the library image. And preferably, one in which we don't have to duplicate information between libc-func.c and all of the individual multiarch files.
>>
>> Let's first simply state that we'd like to avoid these relative relocs. Let's hide the detail of how we avoid them behind a target-specific wall, by not returning pre-allocated const arrays:
>>
>> int __libc_func(const char *name, void **array, size_t n)
>>
>> where N says how large ARRAY is. The return value is the number of implementations placed in ARRAY, or -1 for ENOSPC (i.e. increase the size of ARRAY). This adds extra overhead to __libc_func itself, but since that's for testing only, we shouldn't care.
>>
>> As a next step we can encode these function pointers as PC relative. We probably can't do this directly in C, but it's easy enough in assembler. And given that these files are already target-specific that's trivial too. Then __libc_func merely has to decode the pointers while copying to ARRAY.
>
> Let me see what I can do.
About this?
extern __typeof (memmove) __memmove_sse2 attribute_hidden;
extern __typeof (memmove) __memmove_ssse3 attribute_hidden;
extern __typeof (memmove) __memmove_ssse3_back attribute_hidden;
static struct libc_func_test *
find_memmove (void)
{
size_t n = HAS_SSSE3 ? 3 : 1;
struct libc_func_test *list
= malloc ((n + 1) * sizeof (struct libc_func_test));
if (list != NULL)
{
size_t i;
if (HAS_SSSE3)
{
list[0].name = "__memmove_ssse3_back";
list[0].fn = __memmove_ssse3_back;
list[1].name = "__memmove_ssse3_back";
list[1].fn = __memmove_ssse3;
i = 2;
}
else
i = 0;
list[i].name = "__memmove_sse2";
list[i].fn = __memmove_sse2;
list[n].name = NULL;
list[n].fn = NULL;
}
return list;
}
Relocation section '.rela.text' at offset 0x1110 contains 9 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000006 000f00000002 R_X86_64_PC32 0000000000000000 .LC0 - 4
000000000023 001400000002 R_X86_64_PC32 0000000000000000 __cpu_features + c
000000000030 001600000004 R_X86_64_PLT32 0000000000000000 malloc - 4
000000000043 001000000002 R_X86_64_PC32 000000000000001d .LC2 - 4
000000000053 001700000002 R_X86_64_PC32 0000000000000000 __memmove_sse2 - 4
000000000076 001600000004 R_X86_64_PLT32 0000000000000000 malloc - 4
000000000082 001100000002 R_X86_64_PC32 0000000000000008 .LC1 - 4
000000000089 001800000002 R_X86_64_PC32 0000000000000000 __memmove_ssse3_ba
ck - 4
00000000009c 001900000002 R_X86_64_PC32 0000000000000000 __memmove_ssse3 -
4
We can avoid malloc by caller allocates memory on stack.
--
H.J.