mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
x86/unwind/orc: Add ELF section with ORC version identifier
Commitsffb1b4a410
("x86/unwind/orc: Add 'signal' field to ORC metadata") andfb799447ae
("x86,objtool: Split UNWIND_HINT_EMPTY in two") changed the ORC format. Although ORC is internal to the kernel, it's the only way for external tools to get reliable kernel stack traces on x86-64. In particular, the drgn debugger [1] uses ORC for stack unwinding, and these format changes broke it [2]. As the drgn maintainer, I don't care how often or how much the kernel changes the ORC format as long as I have a way to detect the change. It suffices to store a version identifier in the vmlinux and kernel module ELF files (to use when parsing ORC sections from ELF), and in kernel memory (to use when parsing ORC from a core dump+symbol table). Rather than hard-coding a version number that needs to be manually bumped, Peterz suggested hashing the definitions from orc_types.h. If there is a format change that isn't caught by this, the hashing script can be updated. This patch adds an .orc_header allocated ELF section containing the 20-byte hash to vmlinux and kernel modules, along with the corresponding __start_orc_header and __stop_orc_header symbols in vmlinux. 1: https://github.com/osandov/drgn 2: https://github.com/osandov/drgn/issues/303 Fixes:ffb1b4a410
("x86/unwind/orc: Add 'signal' field to ORC metadata") Fixes:fb799447ae
("x86,objtool: Split UNWIND_HINT_EMPTY in two") Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Josh Poimboeuf <jpoimboe@kernel.org> Link: https://lkml.kernel.org/r/aef9c8dc43915b886a8c48509a12ec1b006ca1ca.1686690801.git.osandov@osandov.com
This commit is contained in:
parent
858fd168a9
commit
b9f174c811
@ -305,6 +305,18 @@ ifeq ($(RETPOLINE_CFLAGS),)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_UNWINDER_ORC
|
||||||
|
orc_hash_h := arch/$(SRCARCH)/include/generated/asm/orc_hash.h
|
||||||
|
orc_hash_sh := $(srctree)/scripts/orc_hash.sh
|
||||||
|
targets += $(orc_hash_h)
|
||||||
|
quiet_cmd_orc_hash = GEN $@
|
||||||
|
cmd_orc_hash = mkdir -p $(dir $@); \
|
||||||
|
$(CONFIG_SHELL) $(orc_hash_sh) < $< > $@
|
||||||
|
$(orc_hash_h): $(srctree)/arch/x86/include/asm/orc_types.h $(orc_hash_sh) FORCE
|
||||||
|
$(call if_changed,orc_hash)
|
||||||
|
archprepare: $(orc_hash_h)
|
||||||
|
endif
|
||||||
|
|
||||||
archclean:
|
archclean:
|
||||||
$(Q)rm -rf $(objtree)/arch/i386
|
$(Q)rm -rf $(objtree)/arch/i386
|
||||||
$(Q)rm -rf $(objtree)/arch/x86_64
|
$(Q)rm -rf $(objtree)/arch/x86_64
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
|
||||||
|
generated-y += orc_hash.h
|
||||||
generated-y += syscalls_32.h
|
generated-y += syscalls_32.h
|
||||||
generated-y += syscalls_64.h
|
generated-y += syscalls_64.h
|
||||||
generated-y += syscalls_x32.h
|
generated-y += syscalls_x32.h
|
||||||
|
19
arch/x86/include/asm/orc_header.h
Normal file
19
arch/x86/include/asm/orc_header.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
||||||
|
|
||||||
|
#ifndef _ORC_HEADER_H
|
||||||
|
#define _ORC_HEADER_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
#include <asm/orc_hash.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The header is currently a 20-byte hash of the ORC entry definition; see
|
||||||
|
* scripts/orc_hash.sh.
|
||||||
|
*/
|
||||||
|
#define ORC_HEADER \
|
||||||
|
__used __section(".orc_header") __aligned(4) \
|
||||||
|
static const u8 orc_header[] = { ORC_HASH }
|
||||||
|
|
||||||
|
#endif /* _ORC_HEADER_H */
|
@ -7,6 +7,9 @@
|
|||||||
#include <asm/unwind.h>
|
#include <asm/unwind.h>
|
||||||
#include <asm/orc_types.h>
|
#include <asm/orc_types.h>
|
||||||
#include <asm/orc_lookup.h>
|
#include <asm/orc_lookup.h>
|
||||||
|
#include <asm/orc_header.h>
|
||||||
|
|
||||||
|
ORC_HEADER;
|
||||||
|
|
||||||
#define orc_warn(fmt, ...) \
|
#define orc_warn(fmt, ...) \
|
||||||
printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
|
printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__)
|
||||||
|
@ -839,6 +839,9 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_UNWINDER_ORC
|
#ifdef CONFIG_UNWINDER_ORC
|
||||||
#define ORC_UNWIND_TABLE \
|
#define ORC_UNWIND_TABLE \
|
||||||
|
.orc_header : AT(ADDR(.orc_header) - LOAD_OFFSET) { \
|
||||||
|
BOUNDED_SECTION_BY(.orc_header, _orc_header) \
|
||||||
|
} \
|
||||||
. = ALIGN(4); \
|
. = ALIGN(4); \
|
||||||
.orc_unwind_ip : AT(ADDR(.orc_unwind_ip) - LOAD_OFFSET) { \
|
.orc_unwind_ip : AT(ADDR(.orc_unwind_ip) - LOAD_OFFSET) { \
|
||||||
BOUNDED_SECTION_BY(.orc_unwind_ip, _orc_unwind_ip) \
|
BOUNDED_SECTION_BY(.orc_unwind_ip, _orc_unwind_ip) \
|
||||||
|
@ -1979,6 +1979,11 @@ static void add_header(struct buffer *b, struct module *mod)
|
|||||||
buf_printf(b, "#include <linux/vermagic.h>\n");
|
buf_printf(b, "#include <linux/vermagic.h>\n");
|
||||||
buf_printf(b, "#include <linux/compiler.h>\n");
|
buf_printf(b, "#include <linux/compiler.h>\n");
|
||||||
buf_printf(b, "\n");
|
buf_printf(b, "\n");
|
||||||
|
buf_printf(b, "#ifdef CONFIG_UNWINDER_ORC\n");
|
||||||
|
buf_printf(b, "#include <asm/orc_header.h>\n");
|
||||||
|
buf_printf(b, "ORC_HEADER;\n");
|
||||||
|
buf_printf(b, "#endif\n");
|
||||||
|
buf_printf(b, "\n");
|
||||||
buf_printf(b, "BUILD_SALT;\n");
|
buf_printf(b, "BUILD_SALT;\n");
|
||||||
buf_printf(b, "BUILD_LTO_INFO;\n");
|
buf_printf(b, "BUILD_LTO_INFO;\n");
|
||||||
buf_printf(b, "\n");
|
buf_printf(b, "\n");
|
||||||
|
16
scripts/orc_hash.sh
Normal file
16
scripts/orc_hash.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
printf '%s' '#define ORC_HASH '
|
||||||
|
|
||||||
|
awk '
|
||||||
|
/^#define ORC_(REG|TYPE)_/ { print }
|
||||||
|
/^struct orc_entry {$/ { p=1 }
|
||||||
|
p { print }
|
||||||
|
/^}/ { p=0 }' |
|
||||||
|
sha1sum |
|
||||||
|
cut -d " " -f 1 |
|
||||||
|
sed 's/\([0-9a-f]\{2\}\)/0x\1,/g'
|
Loading…
Reference in New Issue
Block a user