[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <045d7e22-672c-b9da-38d6-8897e854f262@loongson.cn>
Date: Thu, 13 Feb 2025 20:38:22 +0800
From: Tiezhu Yang <yangtiezhu@...ngson.cn>
To: Josh Poimboeuf <jpoimboe@...nel.org>
Cc: Andrew Morton <akpm@...ux-foundation.org>,
Peter Zijlstra <peterz@...radead.org>, loongarch@...ts.linux.dev,
linux-kernel@...r.kernel.org, Nathan Chancellor <nathan@...nel.org>,
llvm@...ts.linux.dev
Subject: Re: [PATCH] compiler.h: Specify correct attribute for
.rodata..c_jump_table
On 02/13/2025 10:39 AM, Josh Poimboeuf wrote:
> On Thu, Feb 13, 2025 at 10:20:40AM +0800, Tiezhu Yang wrote:
>> On 02/13/2025 01:50 AM, Josh Poimboeuf wrote:
>>>> @@ -133,7 +133,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
>>>> #define annotate_unreachable() __annotate_unreachable(__COUNTER__)
>>>>
>>>> /* Annotate a C jump table to allow objtool to follow the code flow */
>>>> -#define __annotate_jump_table __section(".rodata..c_jump_table")
>>>> +#define __annotate_jump_table __section(".rodata..c_jump_table,\"a\",@progbits #")
>>>
>>> This caused a regression, this hack apparently doesn't work with Clang:
>>>
>>> $ readelf -WS kernel/bpf/core.o | grep c_jump_table
>>> [43] .rodata..c_jump_table,"a",@progbits # PROGBITS 0000000000000000 00d610 000800 00 A 0 0 16
>>>
>>> Notice the section name is literally:
>>>
>>> .rodata..c_jump_table,"a",@progbits #
>>
>> Yes, I noticed this section name which contains the original name
>> ".rodata..c_jump_table" and the specified attribute compiled with
>> Clang, it should not contain the specified attribute.
>>
>> That is strange but seems no effect due to only compare the first
>> few letters of the section name in objtool.
>
> It actually does have an effect -- objtool doesn't recognize the BPF C
> jump table (see the use of C_JUMP_TABLE_SECTION in
> tools/objtool/arch/x86/special.c), resulting in a bogus warning and
> missing ORC.
>
> I do have a workaround to use strstarts() instead of strcmp(), I'll be
> posting that soon.
>
>> I will keep digging with the GNU and LLVM compiler developers.
Specify the attribute like ".rodata..c_jump_table,\"a\",@progbits #"
explicitly works for GNU toolchains, but this hack apparently doesn't
work with Clang, the generated section name is wrong, resulting in a
bogus warning and missing ORC for x86. This is because there is only
one arg for section name in LLVM, even if the so called attribute is
specified, it will be recognized as a whole for section name, so it
is not proper to specify the readonly attribute for the section.
In the top Makefile, there is "-fno-PIE" build flag. For x86, there
is no "-fPIE" build flag in arch/x86/Makefile for 64 bit kernel. But
for LoongArch, there is "-fPIE" build flag in arch/loongarch/Makefile
to override "-fno-PIE" in top Makefile. After some test with GCC and
Clang on x86 and LoongArch, it shows that the generated "W" (writable)
section attribute of the section ".rodata..c_jump_table" is depent on
the compiler option "-fPIE", and then lead to the assembler warning:
"setting incorrect section attributes for .rodata..c_jump_table".
Note that when running the following steps, x86 and LoongArch have the
same result. If compiled with GCC -fPIE, there is assembler warning for
x86 and LoongArch; if compiled with Clang -fPIE, there is no assembler
warning for x86 and LoongArch.
If just drop the prefix ".rodata" of the section name, that is to say,
rename ".rodata..c_jump_table" to ".c_jump_table", there is no assembler
warning for x86 and LoongArch.
Based on the above analysis, in order to avoid changing the behavior of
GNU assembler and silence the GNU assembler warning, is it possible to
rename ".rodata..c_jump_table" to ".c_jump_table"? Or should it do some
changes for GNU assembler?
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gas/config/obj-elf.c;hb=HEAD#l741
if (match_p->group_name == NULL)
as_warn (_("setting incorrect section attributes for %s"),
name);
(1) Here is the simple test code with the original section name:
$ cat test.c
#define __annotate_jump_table
__attribute__((__section__(".rodata..c_jump_table")))
int main()
{
static const void * const jumptable[256] __annotate_jump_table = {
[0 ... 255] = &&default_label,
};
default_label:
return 0;
}
(2) Here is the build script:
$ cat build.sh
#!/bin/bash
uname -m
echo ""
rm -f *gcc* *clang*
echo "test with gcc fpie"
gcc -fPIE -E test.c -o test_with_gcc_fpie.i
gcc -fPIE -S test_with_gcc_fpie.i -o test_with_gcc_fpie.s
gcc -fPIE -c test_with_gcc_fpie.s -o test_with_gcc_fpie.o
readelf -S test_with_gcc_fpie.o | grep -A 1 "c_j" | head -2
echo ""
echo "test with gcc fnopie"
gcc -fno-PIE -E test.c -o test_with_gcc_fnopie.i
gcc -fno-PIE -S test_with_gcc_fnopie.i -o test_with_gcc_fnopie.s
gcc -fno-PIE -c test_with_gcc_fnopie.s -o test_with_gcc_fnopie.o
readelf -S test_with_gcc_fnopie.o | grep -A 1 "c_j" | head -2
echo ""
echo "test with clang fpie"
clang -fPIE -E test.c -o test_with_clang_fpie.i
clang -fPIE -S test_with_clang_fpie.i -o test_with_clang_fpie.s
clang -fPIE -c test_with_clang_fpie.s -o test_with_clang_fpie.o
readelf -S test_with_clang_fpie.o | grep -A 1 "c_j" | head -2
echo ""
echo "test with clang fnopie"
clang -fno-PIE -E test.c -o test_with_clang_fnopie.i
clang -fno-PIE -S test_with_clang_fnopie.i -o test_with_clang_fnopie.s
clang -fno-PIE -c test_with_clang_fnopie.s -o test_with_clang_fnopie.o
readelf -S test_with_clang_fnopie.o | grep -A 1 "c_j" | head -2
(3) Here is the test result with the original section name:
$ ./build.sh
x86_64
test with gcc fpie
test_with_gcc_fpie.s: Assembler messages:
test_with_gcc_fpie.s:3: Warning: setting incorrect section attributes
for .rodata..c_jump_table
[ 4] .rodata..c_j[...] PROGBITS 0000000000000000 00000060
0000000000000800 0000000000000000 WA 0 0 32
test with gcc fnopie
[ 4] .rodata..c_j[...] PROGBITS 0000000000000000 00000060
0000000000000800 0000000000000000 A 0 0 32
test with clang fpie
[ 3] .rodata..c_j[...] PROGBITS 0000000000000000 00000050
0000000000000800 0000000000000000 WA 0 0 16
test with clang fnopie
[ 3] .rodata..c_j[...] PROGBITS 0000000000000000 00000050
0000000000000800 0000000000000000 A 0 0 16
(4) Here is the simple test code with the modified section name:
$ cat test.c
#define __annotate_jump_table __attribute__((__section__(".c_jump_table")))
int main()
{
static const void * const jumptable[256] __annotate_jump_table = {
[0 ... 255] = &&default_label,
};
default_label:
return 0;
}
(5) Here is the test result with the modified section name:
(note that build.sh is not changed)
$ ./build.sh
x86_64
test with gcc fpie
[ 4] .c_jump_table PROGBITS 0000000000000000 00000060
0000000000000800 0000000000000000 WA 0 0 32
test with gcc fnopie
[ 4] .c_jump_table PROGBITS 0000000000000000 00000060
0000000000000800 0000000000000000 A 0 0 32
test with clang fpie
[ 3] .c_jump_table PROGBITS 0000000000000000 00000050
0000000000000800 0000000000000000 WA 0 0 16
test with clang fnopie
[ 3] .c_jump_table PROGBITS 0000000000000000 00000050
0000000000000800 0000000000000000 A 0 0 16
Thanks,
Tiezhu
Powered by blists - more mailing lists