linux/scripts/kallsyms.c

712 lines
16 KiB

kallsyms: add support for relative offsets in kallsyms address table Similar to how relative extables are implemented, it is possible to emit the kallsyms table in such a way that it contains offsets relative to some anchor point in the kernel image rather than absolute addresses. On 64-bit architectures, it cuts the size of the kallsyms address table in half, since offsets between kernel symbols can typically be expressed in 32 bits. This saves several hundreds of kilobytes of permanent .rodata on average. In addition, the kallsyms address table is no longer subject to dynamic relocation when CONFIG_RELOCATABLE is in effect, so the relocation work done after decompression now doesn't have to do relocation updates for all these values. This saves up to 24 bytes (i.e., the size of a ELF64 RELA relocation table entry) per value, which easily adds up to a couple of megabytes of uncompressed __init data on ppc64 or arm64. Even if these relocation entries typically compress well, the combined size reduction of 2.8 MB uncompressed for a ppc64_defconfig build (of which 2.4 MB is __init data) results in a ~500 KB space saving in the compressed image. Since it is useful for some architectures (like x86) to retain the ability to emit absolute values as well, this patch also adds support for capturing both absolute and relative values when KALLSYMS_ABSOLUTE_PERCPU is in effect, by emitting absolute per-cpu addresses as positive 32-bit values, and addresses relative to the lowest encountered relative symbol as negative values, which are subtracted from the runtime address of this base symbol to produce the actual address. Support for the above is enabled by default for all architectures except IA-64 and Tile-GX, whose symbols are too far apart to capture in this manner. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Kees Cook <keescook@chromium.org> Tested-by: Kees Cook <keescook@chromium.org> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Ingo Molnar <mingo@kernel.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Michal Marek <mmarek@suse.cz> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-03-15 14:58:19 -07:00
kallsyms: Get rid of kallsyms relative base When the kallsyms relative base was introduced, per-CPU variable references on x86_64 SMP were implemented as offsets into the respective per-CPU region, rather than offsets relative to the location of the variable's template in the kernel image, which is how other architectures implement it. This required kallsyms to reason about the difference between the two, and the sign of the value in the kallsyms_offsets[] array was used to distinguish them. This meant that negative offsets were not permitted for ordinary variables, and so it was crucial that the relative base was chosen such that all offsets were positive numbers. This is no longer needed: instead, the offsets can simply be encoded as values in the range -/+ 2 GiB, which is precisely what PC32 relocations provide on most architectures. So it is possible to simplify the logic, and just use _text as the anchor directly, and let the linker calculate the final value based on the location of the entry itself. Some architectures (nios2, extensa) do not support place-relative relocations at all, but these are all 32-bit and non-relocatable, and so there is no need for place-relative relocations in the first place, and the actual symbol values can just be stored directly. This makes all entries in the kallsyms_offsets[] array visible as place-relative references in the ELF metadata, which will be important when implementing ELF-based fg-kaslr. Reviewed-by: Kees Cook <kees@kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://patch.msgid.link/20260116093359.2442297-6-ardb+git@google.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-01-16 10:34:02 +01:00
scripts/kallsyms: fix wrong kallsyms_relative_base There is the code in the read_symbol function in 'scripts/kallsyms.c': if (is_ignored_symbol(name, type)) return NULL; /* Ignore most absolute/undefined (?) symbols. */ if (strcmp(name, "_text") == 0) _text = addr; But the is_ignored_symbol function returns true for name="_text" and type='A'. So the next condition is not executed and the _text variable is always zero. It makes the wrong kallsyms_relative_base symbol as a result of the code (CONFIG_KALLSYMS_BASE_RELATIVE is defined): if (base_relative) { output_label("kallsyms_relative_base"); output_address(relative_base); printf("\n"); } Because the output_address function uses the _text variable. So the kallsyms_lookup function and all related functions in the kernel do not work properly. For example, the stack trace in oops: Call Trace: [aa095e58] [809feab8] kobj_ns_ops_tbl+0x7ff09ac8/0x7ff1c1c4 (unreliable) [aa095e98] [80002b64] kobj_ns_ops_tbl+0x7f50db74/0x80000010 [aa095ef8] [809c3d24] kobj_ns_ops_tbl+0x7feced34/0x7ff1c1c4 [aa095f28] [80002ed0] kobj_ns_ops_tbl+0x7f50dee0/0x80000010 [aa095f38] [8000f238] kobj_ns_ops_tbl+0x7f51a248/0x80000010 The right stack trace: Call Trace: [aa095e58] [809feab8] module_vdu_video_init+0x2fc/0x3bc (unreliable) [aa095e98] [80002b64] do_one_initcall+0x40/0x1f0 [aa095ef8] [809c3d24] kernel_init_freeable+0x164/0x1d8 [aa095f28] [80002ed0] kernel_init+0x14/0x124 [aa095f38] [8000f238] ret_from_kernel_thread+0x14/0x1c [masahiroy@kernel.org: This issue happens on binutils <= 2.22 The following commit fixed it: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=d2667025dd30611514810c28bee9709e4623012a The symbol type of _text is 'T' on binutils >= 2.23 The minimal supported binutils version for the kernel build is 2.21 ] Signed-off-by: Mikhail Petrov <Mikhail.Petrov@mir.dev> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
2020-03-11 23:37:09 +03:00
kallsyms: Get rid of kallsyms relative base When the kallsyms relative base was introduced, per-CPU variable references on x86_64 SMP were implemented as offsets into the respective per-CPU region, rather than offsets relative to the location of the variable's template in the kernel image, which is how other architectures implement it. This required kallsyms to reason about the difference between the two, and the sign of the value in the kallsyms_offsets[] array was used to distinguish them. This meant that negative offsets were not permitted for ordinary variables, and so it was crucial that the relative base was chosen such that all offsets were positive numbers. This is no longer needed: instead, the offsets can simply be encoded as values in the range -/+ 2 GiB, which is precisely what PC32 relocations provide on most architectures. So it is possible to simplify the logic, and just use _text as the anchor directly, and let the linker calculate the final value based on the location of the entry itself. Some architectures (nios2, extensa) do not support place-relative relocations at all, but these are all 32-bit and non-relocatable, and so there is no need for place-relative relocations in the first place, and the actual symbol values can just be stored directly. This makes all entries in the kallsyms_offsets[] array visible as place-relative references in the ELF metadata, which will be important when implementing ELF-based fg-kaslr. Reviewed-by: Kees Cook <kees@kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://patch.msgid.link/20260116093359.2442297-6-ardb+git@google.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-01-16 10:34:02 +01:00
2023-03-08 20:52:42 +09:00
2023-03-08 20:52:42 +09:00
2023-03-08 20:52:42 +09:00
2023-03-08 20:52:42 +09:00
kallsyms: Get rid of kallsyms relative base When the kallsyms relative base was introduced, per-CPU variable references on x86_64 SMP were implemented as offsets into the respective per-CPU region, rather than offsets relative to the location of the variable's template in the kernel image, which is how other architectures implement it. This required kallsyms to reason about the difference between the two, and the sign of the value in the kallsyms_offsets[] array was used to distinguish them. This meant that negative offsets were not permitted for ordinary variables, and so it was crucial that the relative base was chosen such that all offsets were positive numbers. This is no longer needed: instead, the offsets can simply be encoded as values in the range -/+ 2 GiB, which is precisely what PC32 relocations provide on most architectures. So it is possible to simplify the logic, and just use _text as the anchor directly, and let the linker calculate the final value based on the location of the entry itself. Some architectures (nios2, extensa) do not support place-relative relocations at all, but these are all 32-bit and non-relocatable, and so there is no need for place-relative relocations in the first place, and the actual symbol values can just be stored directly. This makes all entries in the kallsyms_offsets[] array visible as place-relative references in the ELF metadata, which will be important when implementing ELF-based fg-kaslr. Reviewed-by: Kees Cook <kees@kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://patch.msgid.link/20260116093359.2442297-6-ardb+git@google.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-01-16 10:34:02 +01:00
kallsyms: Get rid of kallsyms relative base When the kallsyms relative base was introduced, per-CPU variable references on x86_64 SMP were implemented as offsets into the respective per-CPU region, rather than offsets relative to the location of the variable's template in the kernel image, which is how other architectures implement it. This required kallsyms to reason about the difference between the two, and the sign of the value in the kallsyms_offsets[] array was used to distinguish them. This meant that negative offsets were not permitted for ordinary variables, and so it was crucial that the relative base was chosen such that all offsets were positive numbers. This is no longer needed: instead, the offsets can simply be encoded as values in the range -/+ 2 GiB, which is precisely what PC32 relocations provide on most architectures. So it is possible to simplify the logic, and just use _text as the anchor directly, and let the linker calculate the final value based on the location of the entry itself. Some architectures (nios2, extensa) do not support place-relative relocations at all, but these are all 32-bit and non-relocatable, and so there is no need for place-relative relocations in the first place, and the actual symbol values can just be stored directly. This makes all entries in the kallsyms_offsets[] array visible as place-relative references in the ELF metadata, which will be important when implementing ELF-based fg-kaslr. Reviewed-by: Kees Cook <kees@kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://patch.msgid.link/20260116093359.2442297-6-ardb+git@google.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-01-16 10:34:02 +01:00
kallsyms, tracing: output more proper symbol name Impact: bugfix, output more reliable symbol lookup result Debug tools(dump_stack(), ftrace...) are like to print out symbols. But it is always print out the first aliased symbol.(Aliased symbols are symbols with the same address), and the first aliased symbol is sometime not proper. # echo function_graph > current_tracer # cat trace ...... 1) 1.923 us | select_nohz_load_balancer(); 1) + 76.692 us | } 1) | default_idle() { 1) ==========> | __irqentry_text_start() { 1) 0.000 us | native_apic_mem_write(); 1) | irq_enter() { 1) 0.000 us | idle_cpu(); 1) | tick_check_idle() { 1) 0.000 us | tick_check_oneshot_broadcast(); 1) | tick_nohz_stop_idle() { ...... It's very embarrassing, it ouputs "__irqentry_text_start()", actually, it should output "smp_apic_timer_interrupt()". (these two symbol are the same address, but "__irqentry_text_start" is deemed to the first aliased symbol by scripts/kallsyms) This patch puts symbols like "__irqentry_text_start" to the second aliased symbols. And a more proper symbol name becomes the first. Aliased symbols mostly come from linker script. The solution is guessing "is this symbol defined in linker script", the symbols defined in linker script will not become the first aliased symbol. And if symbols are found to be equal in this "linker script provided" criteria, symbols are sorted by the number of prefix underscores. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Paulo Marques <pmarques@grupopie.com> LKML-Reference: <49BA06E2.7080807@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-03-13 15:10:26 +08:00
kallsyms, tracing: output more proper symbol name Impact: bugfix, output more reliable symbol lookup result Debug tools(dump_stack(), ftrace...) are like to print out symbols. But it is always print out the first aliased symbol.(Aliased symbols are symbols with the same address), and the first aliased symbol is sometime not proper. # echo function_graph > current_tracer # cat trace ...... 1) 1.923 us | select_nohz_load_balancer(); 1) + 76.692 us | } 1) | default_idle() { 1) ==========> | __irqentry_text_start() { 1) 0.000 us | native_apic_mem_write(); 1) | irq_enter() { 1) 0.000 us | idle_cpu(); 1) | tick_check_idle() { 1) 0.000 us | tick_check_oneshot_broadcast(); 1) | tick_nohz_stop_idle() { ...... It's very embarrassing, it ouputs "__irqentry_text_start()", actually, it should output "smp_apic_timer_interrupt()". (these two symbol are the same address, but "__irqentry_text_start" is deemed to the first aliased symbol by scripts/kallsyms) This patch puts symbols like "__irqentry_text_start" to the second aliased symbols. And a more proper symbol name becomes the first. Aliased symbols mostly come from linker script. The solution is guessing "is this symbol defined in linker script", the symbols defined in linker script will not become the first aliased symbol. And if symbols are found to be equal in this "linker script provided" criteria, symbols are sorted by the number of prefix underscores. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Paulo Marques <pmarques@grupopie.com> LKML-Reference: <49BA06E2.7080807@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-03-13 15:10:26 +08:00
kallsyms, tracing: output more proper symbol name Impact: bugfix, output more reliable symbol lookup result Debug tools(dump_stack(), ftrace...) are like to print out symbols. But it is always print out the first aliased symbol.(Aliased symbols are symbols with the same address), and the first aliased symbol is sometime not proper. # echo function_graph > current_tracer # cat trace ...... 1) 1.923 us | select_nohz_load_balancer(); 1) + 76.692 us | } 1) | default_idle() { 1) ==========> | __irqentry_text_start() { 1) 0.000 us | native_apic_mem_write(); 1) | irq_enter() { 1) 0.000 us | idle_cpu(); 1) | tick_check_idle() { 1) 0.000 us | tick_check_oneshot_broadcast(); 1) | tick_nohz_stop_idle() { ...... It's very embarrassing, it ouputs "__irqentry_text_start()", actually, it should output "smp_apic_timer_interrupt()". (these two symbol are the same address, but "__irqentry_text_start" is deemed to the first aliased symbol by scripts/kallsyms) This patch puts symbols like "__irqentry_text_start" to the second aliased symbols. And a more proper symbol name becomes the first. Aliased symbols mostly come from linker script. The solution is guessing "is this symbol defined in linker script", the symbols defined in linker script will not become the first aliased symbol. And if symbols are found to be equal in this "linker script provided" criteria, symbols are sorted by the number of prefix underscores. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Paulo Marques <pmarques@grupopie.com> LKML-Reference: <49BA06E2.7080807@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-03-13 15:10:26 +08:00
kallsyms, tracing: output more proper symbol name Impact: bugfix, output more reliable symbol lookup result Debug tools(dump_stack(), ftrace...) are like to print out symbols. But it is always print out the first aliased symbol.(Aliased symbols are symbols with the same address), and the first aliased symbol is sometime not proper. # echo function_graph > current_tracer # cat trace ...... 1) 1.923 us | select_nohz_load_balancer(); 1) + 76.692 us | } 1) | default_idle() { 1) ==========> | __irqentry_text_start() { 1) 0.000 us | native_apic_mem_write(); 1) | irq_enter() { 1) 0.000 us | idle_cpu(); 1) | tick_check_idle() { 1) 0.000 us | tick_check_oneshot_broadcast(); 1) | tick_nohz_stop_idle() { ...... It's very embarrassing, it ouputs "__irqentry_text_start()", actually, it should output "smp_apic_timer_interrupt()". (these two symbol are the same address, but "__irqentry_text_start" is deemed to the first aliased symbol by scripts/kallsyms) This patch puts symbols like "__irqentry_text_start" to the second aliased symbols. And a more proper symbol name becomes the first. Aliased symbols mostly come from linker script. The solution is guessing "is this symbol defined in linker script", the symbols defined in linker script will not become the first aliased symbol. And if symbols are found to be equal in this "linker script provided" criteria, symbols are sorted by the number of prefix underscores. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Paulo Marques <pmarques@grupopie.com> LKML-Reference: <49BA06E2.7080807@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-03-13 15:10:26 +08:00
kallsyms: Get rid of kallsyms relative base When the kallsyms relative base was introduced, per-CPU variable references on x86_64 SMP were implemented as offsets into the respective per-CPU region, rather than offsets relative to the location of the variable's template in the kernel image, which is how other architectures implement it. This required kallsyms to reason about the difference between the two, and the sign of the value in the kallsyms_offsets[] array was used to distinguish them. This meant that negative offsets were not permitted for ordinary variables, and so it was crucial that the relative base was chosen such that all offsets were positive numbers. This is no longer needed: instead, the offsets can simply be encoded as values in the range -/+ 2 GiB, which is precisely what PC32 relocations provide on most architectures. So it is possible to simplify the logic, and just use _text as the anchor directly, and let the linker calculate the final value based on the location of the entry itself. Some architectures (nios2, extensa) do not support place-relative relocations at all, but these are all 32-bit and non-relocatable, and so there is no need for place-relative relocations in the first place, and the actual symbol values can just be stored directly. This makes all entries in the kallsyms_offsets[] array visible as place-relative references in the ELF metadata, which will be important when implementing ELF-based fg-kaslr. Reviewed-by: Kees Cook <kees@kernel.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Link: https://patch.msgid.link/20260116093359.2442297-6-ardb+git@google.com Signed-off-by: Nathan Chancellor <nathan@kernel.org>
2026-01-16 10:34:02 +01:00