[prev in list] [next in list] [prev in thread] [next in thread]
List: freebsd-current
Subject: Re: i386 kernel modules unusable due to .plt sections
From: Tijl Coosemans <tijl () FreeBSD ! org>
Date: 2021-08-27 16:10:24
Message-ID: 20210827181024.06f26328 () FreeBSD ! org
[Download RAW message or body]
On Fri, 27 Aug 2021 11:32:43 -0400 Mark Johnston <markj@freebsd.org>
wrote:
> On Fri, Aug 27, 2021 at 05:29:34PM +0200, Tijl Coosemans wrote:
>> On Fri, 27 Aug 2021 17:24:58 +0300 Konstantin Belousov
>> <kostikbel@gmail.com> wrote:
>>> On Fri, Aug 27, 2021 at 03:41:30PM +0200, Tijl Coosemans wrote:
>>>> I use devel/llvm* to build base and just switched to llvm12. It seems
>>>> that on i386 clang12 uses R_386_PLT32 relocations for some calls to at
>>>> least memset, memcpy and __stack_chk_fail (clang11 uses R_386_PC32).
>>>> These are converted to R_386_JMP_SLOT relocations by the linker which
>>>> aren't supported by the kernel, e.g. loading linux.ko gives "kldload:
>>>> unexpected relocation type" from sys/i386/i386/elf_machdep.c. The PLT
>>>> entries also depend on a base pointer in %ebx but kernel modules aren't
>>>> compiled with -fPIC, so this can't work and I suspect this is a
>>>> regression in clang12.
>>>>
>>>> The following code shows the difference between clang11 and clang12:
>>>>
>>>> --------
>>>> #include <string.h>
>>>>
>>>> void *
>>>> test_memset(void *p, int c, size_t len) {
>>>> return (memset(p, c, len));
>>>> }
>>>>
>>>> void *
>>>> test_memcpy(void *dst, const void *src, size_t len) {
>>>> return (memcpy(dst, src, len));
>>>> }
>>>>
>>>> void *
>>>> test_memmove(void *dst, const void *src, size_t len) {
>>>> return (memmove(dst, src, len));
>>>> }
>>>> --------
>>>>
>>>> Output of "readelf -r test.o" when compiled with "clang12 -c test.c -m32":
>>>> r_offset r_info r_type st_value st_name
>>>> 0000002c 00000504 R_386_PLT32 00000000 memset
>>>> 00000067 00000304 R_386_PLT32 00000000 memcpy
>>>> 000000a7 00000402 R_386_PC32 00000000 memmove
>>>>
>>>> With clang11:
>>>> r_offset r_info r_type st_value st_name
>>>> 00000036 00000502 R_386_PC32 00000000 memset
>>>> 00000083 00000302 R_386_PC32 00000000 memcpy
>>>> 000000d2 00000402 R_386_PC32 00000000 memmove
>>>
>>> Are you asking (for somebody) to add R_386_JMP_SLOT to i386/elf_machdep.c?
>>> Like this, not even built.
>>>
>>> diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
>>> index 3754b36d9e33..a26a4189e0ee 100644
>>> --- a/sys/i386/i386/elf_machdep.c
>>> +++ b/sys/i386/i386/elf_machdep.c
>>> @@ -245,6 +245,7 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
>>> break;
>>>
>>> case R_386_GLOB_DAT: /* S */
>>> + case R_386_JMP_SLOT:
>>> error = lookup(lf, symidx, 1, &addr);
>>> if (error != 0)
>>> return (-1);
>>
>> No, I've tried that. It handles the relocation but callers still don't
>> setup %ebx as PIC register. I'm looking for someone to confirm it's a
>> compiler bug and not a missing flag or something. I tried -fno-plt and
>> that has no effect.
>
> Does disabling -zifunc-noplt fix the problem? I believe it's set by
> default for i386.
Removing it from sys/conf/kern.pre.mk didn't help.
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic