From: madvenka@linux.microsoft.com
To: jpoimboe@redhat.com, peterz@infradead.org,
chenzhongjin@huawei.com, mark.rutland@arm.com,
broonie@kernel.org, nobuta.keiya@fujitsu.com,
sjitindarsingh@gmail.com, catalin.marinas@arm.com,
will@kernel.org, jamorris@linux.microsoft.com,
linux-arm-kernel@lists.infradead.org,
live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
madvenka@linux.microsoft.com
Subject: [RFC PATCH v3 04/22] objtool: Reorganize Unwind hint code
Date: Thu, 2 Feb 2023 01:40:18 -0600 [thread overview]
Message-ID: <20230202074036.507249-5-madvenka@linux.microsoft.com> (raw)
In-Reply-To: <20230202074036.507249-1-madvenka@linux.microsoft.com>
From: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com>
Unwind hint macros and struct unwind_hint are arch-specific. Move them
into the arch-specific file asm/unwind_hints.h. But the unwind hint
types are generic. Retain them in linux/objtool.h.
Unwind hints can be used with static stack validation as well as other
forms of validation such as dynamic FP validation. Move the function
read_unwind_hints() from check.c to a new file unwind_hints.c so that
it can be shared across validation schemes.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
---
arch/x86/include/asm/unwind_hints.h | 83 ++++++++++++
arch/x86/kernel/unwind_orc.c | 2 +-
include/linux/objtool.h | 67 ---------
tools/arch/x86/include/asm/unwind_hints.h | 157 ++++++++++++++++++++++
tools/include/linux/objtool.h | 67 ---------
tools/objtool/Build | 1 +
tools/objtool/check.c | 96 -------------
tools/objtool/include/objtool/insn.h | 1 +
tools/objtool/sync-check.sh | 1 +
tools/objtool/unwind_hints.c | 106 +++++++++++++++
10 files changed, 350 insertions(+), 231 deletions(-)
create mode 100644 tools/arch/x86/include/asm/unwind_hints.h
create mode 100644 tools/objtool/unwind_hints.c
diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h
index f66fbe6537dd..07c8d911266c 100644
--- a/arch/x86/include/asm/unwind_hints.h
+++ b/arch/x86/include/asm/unwind_hints.h
@@ -1,10 +1,93 @@
#ifndef _ASM_X86_UNWIND_HINTS_H
#define _ASM_X86_UNWIND_HINTS_H
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * This struct is used by asm and inline asm code to manually annotate the
+ * location of registers on the stack.
+ */
+struct unwind_hint {
+ u32 ip;
+ s16 sp_offset;
+ u8 sp_reg;
+ u8 type;
+ u8 end;
+};
+#endif
+
#include <linux/objtool.h>
#include "orc_types.h"
+#ifdef CONFIG_OBJTOOL
+
+#ifndef __ASSEMBLY__
+
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "987: \n\t" \
+ ".pushsection .discard.unwind_hints\n\t" \
+ /* struct unwind_hint */ \
+ ".long 987b - .\n\t" \
+ ".short " __stringify(sp_offset) "\n\t" \
+ ".byte " __stringify(sp_reg) "\n\t" \
+ ".byte " __stringify(type) "\n\t" \
+ ".byte " __stringify(end) "\n\t" \
+ ".balign 4 \n\t" \
+ ".popsection\n\t"
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * In asm, there are two kinds of code: normal C-type callable functions and
+ * the rest. The normal callable functions can be called by other code, and
+ * don't do anything unusual with the stack. Such normal callable functions
+ * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
+ * category. In this case, no special debugging annotations are needed because
+ * objtool can automatically generate the ORC data for the ORC unwinder to read
+ * at runtime.
+ *
+ * Anything which doesn't fall into the above category, such as syscall and
+ * interrupt handlers, tends to not be called directly by other functions, and
+ * often does unusual non-C-function-type things with the stack pointer. Such
+ * code needs to be annotated such that objtool can understand it. The
+ * following CFI hint macros are for this type of code.
+ *
+ * These macros provide hints to objtool about the state of the stack at each
+ * instruction. Objtool starts from the hints and follows the code flow,
+ * making automatic CFI adjustments when it sees pushes and pops, filling out
+ * the debuginfo as necessary. It will also warn if it sees any
+ * inconsistencies.
+ */
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.Lunwind_hint_ip_\@:
+ .pushsection .discard.unwind_hints
+ /* struct unwind_hint */
+ .long .Lunwind_hint_ip_\@ - .
+ .short \sp_offset
+ .byte \sp_reg
+ .byte \type
+ .byte \end
+ .balign 4
+ .popsection
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#else /* !CONFIG_OBJTOOL */
+
+#ifndef __ASSEMBLY__
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "\n\t"
+#else
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.endm
+#endif
+
+#endif /* CONFIG_OBJTOOL */
+
#ifdef __ASSEMBLY__
.macro UNWIND_HINT_EMPTY
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index c059820dfaea..c2bfc597d909 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
-#include <linux/objtool.h>
#include <linux/module.h>
#include <linux/sort.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>
#include <asm/unwind.h>
+#include <asm/unwind_hints.h>
#include <asm/orc_types.h>
#include <asm/orc_lookup.h>
diff --git a/include/linux/objtool.h b/include/linux/objtool.h
index 62c54ffbeeaa..1af295efc12c 100644
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -2,23 +2,6 @@
#ifndef _LINUX_OBJTOOL_H
#define _LINUX_OBJTOOL_H
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/*
- * This struct is used by asm and inline asm code to manually annotate the
- * location of registers on the stack.
- */
-struct unwind_hint {
- u32 ip;
- s16 sp_offset;
- u8 sp_reg;
- u8 type;
- u8 end;
-};
-#endif
-
/*
* UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
* (the caller's SP right before it made the call). Used for all callable
@@ -49,18 +32,6 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "987: \n\t" \
- ".pushsection .discard.unwind_hints\n\t" \
- /* struct unwind_hint */ \
- ".long 987b - .\n\t" \
- ".short " __stringify(sp_offset) "\n\t" \
- ".byte " __stringify(sp_reg) "\n\t" \
- ".byte " __stringify(type) "\n\t" \
- ".byte " __stringify(end) "\n\t" \
- ".balign 4 \n\t" \
- ".popsection\n\t"
-
/*
* This macro marks the given function's stack frame as "non-standard", which
* tells objtool to ignore the function when doing stack metadata validation.
@@ -108,40 +79,6 @@ struct unwind_hint {
.long 999b; \
.popsection;
-/*
- * In asm, there are two kinds of code: normal C-type callable functions and
- * the rest. The normal callable functions can be called by other code, and
- * don't do anything unusual with the stack. Such normal callable functions
- * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
- * category. In this case, no special debugging annotations are needed because
- * objtool can automatically generate the ORC data for the ORC unwinder to read
- * at runtime.
- *
- * Anything which doesn't fall into the above category, such as syscall and
- * interrupt handlers, tends to not be called directly by other functions, and
- * often does unusual non-C-function-type things with the stack pointer. Such
- * code needs to be annotated such that objtool can understand it. The
- * following CFI hint macros are for this type of code.
- *
- * These macros provide hints to objtool about the state of the stack at each
- * instruction. Objtool starts from the hints and follows the code flow,
- * making automatic CFI adjustments when it sees pushes and pops, filling out
- * the debuginfo as necessary. It will also warn if it sees any
- * inconsistencies.
- */
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.Lunwind_hint_ip_\@:
- .pushsection .discard.unwind_hints
- /* struct unwind_hint */
- .long .Lunwind_hint_ip_\@ - .
- .short \sp_offset
- .byte \sp_reg
- .byte \type
- .byte \end
- .balign 4
- .popsection
-.endm
-
.macro STACK_FRAME_NON_STANDARD func:req
.pushsection .discard.func_stack_frame_non_standard, "aw"
_ASM_PTR \func
@@ -174,16 +111,12 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "\n\t"
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
.macro ANNOTATE_NOENDBR
diff --git a/tools/arch/x86/include/asm/unwind_hints.h b/tools/arch/x86/include/asm/unwind_hints.h
new file mode 100644
index 000000000000..07c8d911266c
--- /dev/null
+++ b/tools/arch/x86/include/asm/unwind_hints.h
@@ -0,0 +1,157 @@
+#ifndef _ASM_X86_UNWIND_HINTS_H
+#define _ASM_X86_UNWIND_HINTS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * This struct is used by asm and inline asm code to manually annotate the
+ * location of registers on the stack.
+ */
+struct unwind_hint {
+ u32 ip;
+ s16 sp_offset;
+ u8 sp_reg;
+ u8 type;
+ u8 end;
+};
+#endif
+
+#include <linux/objtool.h>
+
+#include "orc_types.h"
+
+#ifdef CONFIG_OBJTOOL
+
+#ifndef __ASSEMBLY__
+
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "987: \n\t" \
+ ".pushsection .discard.unwind_hints\n\t" \
+ /* struct unwind_hint */ \
+ ".long 987b - .\n\t" \
+ ".short " __stringify(sp_offset) "\n\t" \
+ ".byte " __stringify(sp_reg) "\n\t" \
+ ".byte " __stringify(type) "\n\t" \
+ ".byte " __stringify(end) "\n\t" \
+ ".balign 4 \n\t" \
+ ".popsection\n\t"
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * In asm, there are two kinds of code: normal C-type callable functions and
+ * the rest. The normal callable functions can be called by other code, and
+ * don't do anything unusual with the stack. Such normal callable functions
+ * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
+ * category. In this case, no special debugging annotations are needed because
+ * objtool can automatically generate the ORC data for the ORC unwinder to read
+ * at runtime.
+ *
+ * Anything which doesn't fall into the above category, such as syscall and
+ * interrupt handlers, tends to not be called directly by other functions, and
+ * often does unusual non-C-function-type things with the stack pointer. Such
+ * code needs to be annotated such that objtool can understand it. The
+ * following CFI hint macros are for this type of code.
+ *
+ * These macros provide hints to objtool about the state of the stack at each
+ * instruction. Objtool starts from the hints and follows the code flow,
+ * making automatic CFI adjustments when it sees pushes and pops, filling out
+ * the debuginfo as necessary. It will also warn if it sees any
+ * inconsistencies.
+ */
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.Lunwind_hint_ip_\@:
+ .pushsection .discard.unwind_hints
+ /* struct unwind_hint */
+ .long .Lunwind_hint_ip_\@ - .
+ .short \sp_offset
+ .byte \sp_reg
+ .byte \type
+ .byte \end
+ .balign 4
+ .popsection
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#else /* !CONFIG_OBJTOOL */
+
+#ifndef __ASSEMBLY__
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "\n\t"
+#else
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.endm
+#endif
+
+#endif /* CONFIG_OBJTOOL */
+
+#ifdef __ASSEMBLY__
+
+.macro UNWIND_HINT_EMPTY
+ UNWIND_HINT type=UNWIND_HINT_TYPE_CALL end=1
+.endm
+
+.macro UNWIND_HINT_ENTRY
+ UNWIND_HINT type=UNWIND_HINT_TYPE_ENTRY end=1
+.endm
+
+.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0
+ .if \base == %rsp
+ .if \indirect
+ .set sp_reg, ORC_REG_SP_INDIRECT
+ .else
+ .set sp_reg, ORC_REG_SP
+ .endif
+ .elseif \base == %rbp
+ .set sp_reg, ORC_REG_BP
+ .elseif \base == %rdi
+ .set sp_reg, ORC_REG_DI
+ .elseif \base == %rdx
+ .set sp_reg, ORC_REG_DX
+ .elseif \base == %r10
+ .set sp_reg, ORC_REG_R10
+ .else
+ .error "UNWIND_HINT_REGS: bad base register"
+ .endif
+
+ .set sp_offset, \offset
+
+ .if \partial
+ .set type, UNWIND_HINT_TYPE_REGS_PARTIAL
+ .elseif \extra == 0
+ .set type, UNWIND_HINT_TYPE_REGS_PARTIAL
+ .set sp_offset, \offset + (16*8)
+ .else
+ .set type, UNWIND_HINT_TYPE_REGS
+ .endif
+
+ UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type
+.endm
+
+.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
+ UNWIND_HINT_REGS base=\base offset=\offset partial=1
+.endm
+
+.macro UNWIND_HINT_FUNC
+ UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=8 type=UNWIND_HINT_TYPE_FUNC
+.endm
+
+.macro UNWIND_HINT_SAVE
+ UNWIND_HINT type=UNWIND_HINT_TYPE_SAVE
+.endm
+
+.macro UNWIND_HINT_RESTORE
+ UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE
+.endm
+
+#else
+
+#define UNWIND_HINT_FUNC \
+ UNWIND_HINT(ORC_REG_SP, 8, UNWIND_HINT_TYPE_FUNC, 0)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_X86_UNWIND_HINTS_H */
diff --git a/tools/include/linux/objtool.h b/tools/include/linux/objtool.h
index 62c54ffbeeaa..1af295efc12c 100644
--- a/tools/include/linux/objtool.h
+++ b/tools/include/linux/objtool.h
@@ -2,23 +2,6 @@
#ifndef _LINUX_OBJTOOL_H
#define _LINUX_OBJTOOL_H
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/*
- * This struct is used by asm and inline asm code to manually annotate the
- * location of registers on the stack.
- */
-struct unwind_hint {
- u32 ip;
- s16 sp_offset;
- u8 sp_reg;
- u8 type;
- u8 end;
-};
-#endif
-
/*
* UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
* (the caller's SP right before it made the call). Used for all callable
@@ -49,18 +32,6 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "987: \n\t" \
- ".pushsection .discard.unwind_hints\n\t" \
- /* struct unwind_hint */ \
- ".long 987b - .\n\t" \
- ".short " __stringify(sp_offset) "\n\t" \
- ".byte " __stringify(sp_reg) "\n\t" \
- ".byte " __stringify(type) "\n\t" \
- ".byte " __stringify(end) "\n\t" \
- ".balign 4 \n\t" \
- ".popsection\n\t"
-
/*
* This macro marks the given function's stack frame as "non-standard", which
* tells objtool to ignore the function when doing stack metadata validation.
@@ -108,40 +79,6 @@ struct unwind_hint {
.long 999b; \
.popsection;
-/*
- * In asm, there are two kinds of code: normal C-type callable functions and
- * the rest. The normal callable functions can be called by other code, and
- * don't do anything unusual with the stack. Such normal callable functions
- * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
- * category. In this case, no special debugging annotations are needed because
- * objtool can automatically generate the ORC data for the ORC unwinder to read
- * at runtime.
- *
- * Anything which doesn't fall into the above category, such as syscall and
- * interrupt handlers, tends to not be called directly by other functions, and
- * often does unusual non-C-function-type things with the stack pointer. Such
- * code needs to be annotated such that objtool can understand it. The
- * following CFI hint macros are for this type of code.
- *
- * These macros provide hints to objtool about the state of the stack at each
- * instruction. Objtool starts from the hints and follows the code flow,
- * making automatic CFI adjustments when it sees pushes and pops, filling out
- * the debuginfo as necessary. It will also warn if it sees any
- * inconsistencies.
- */
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.Lunwind_hint_ip_\@:
- .pushsection .discard.unwind_hints
- /* struct unwind_hint */
- .long .Lunwind_hint_ip_\@ - .
- .short \sp_offset
- .byte \sp_reg
- .byte \type
- .byte \end
- .balign 4
- .popsection
-.endm
-
.macro STACK_FRAME_NON_STANDARD func:req
.pushsection .discard.func_stack_frame_non_standard, "aw"
_ASM_PTR \func
@@ -174,16 +111,12 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "\n\t"
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
.macro ANNOTATE_NOENDBR
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 8afe56cd0c2d..c4666d0b40ba 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -8,6 +8,7 @@ objtool-y += builtin-check.o
objtool-y += cfi.o
objtool-y += insn.o
objtool-y += decode.o
+objtool-y += unwind_hints.o
objtool-y += elf.o
objtool-y += objtool.o
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index be3f6564104a..d14a2b7b8b37 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1670,102 +1670,6 @@ static int add_jump_table_alts(struct objtool_file *file)
return 0;
}
-static int read_unwind_hints(struct objtool_file *file)
-{
- struct cfi_state cfi = init_cfi;
- struct section *sec, *relocsec;
- struct unwind_hint *hint;
- struct instruction *insn;
- struct reloc *reloc;
- int i;
-
- sec = find_section_by_name(file->elf, ".discard.unwind_hints");
- if (!sec)
- return 0;
-
- relocsec = sec->reloc;
- if (!relocsec) {
- WARN("missing .rela.discard.unwind_hints section");
- return -1;
- }
-
- if (sec->sh.sh_size % sizeof(struct unwind_hint)) {
- WARN("struct unwind_hint size mismatch");
- return -1;
- }
-
- file->hints = true;
-
- for (i = 0; i < sec->sh.sh_size / sizeof(struct unwind_hint); i++) {
- hint = (struct unwind_hint *)sec->data->d_buf + i;
-
- reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
- if (!reloc) {
- WARN("can't find reloc for unwind_hints[%d]", i);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc->addend);
- if (!insn) {
- WARN("can't find insn for unwind_hints[%d]", i);
- return -1;
- }
-
- insn->hint = true;
-
- if (hint->type == UNWIND_HINT_TYPE_SAVE) {
- insn->hint = false;
- insn->save = true;
- continue;
- }
-
- if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
- insn->restore = true;
- continue;
- }
-
- if (hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) {
- struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset);
-
- if (sym && sym->bind == STB_GLOBAL) {
- if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
- WARN_FUNC("UNWIND_HINT_IRET_REGS without ENDBR",
- insn->sec, insn->offset);
- }
-
- insn->entry = 1;
- }
- }
-
- if (hint->type == UNWIND_HINT_TYPE_ENTRY) {
- hint->type = UNWIND_HINT_TYPE_CALL;
- insn->entry = 1;
- }
-
- if (hint->type == UNWIND_HINT_TYPE_FUNC) {
- insn->cfi = &func_cfi;
- continue;
- }
-
- if (insn->cfi)
- cfi = *(insn->cfi);
-
- if (arch_decode_hint_reg(hint->sp_reg, &cfi.cfa.base)) {
- WARN_FUNC("unsupported unwind_hint sp base reg %d",
- insn->sec, insn->offset, hint->sp_reg);
- return -1;
- }
-
- cfi.cfa.offset = bswap_if_needed(hint->sp_offset);
- cfi.type = hint->type;
- cfi.end = hint->end;
-
- insn->cfi = cfi_hash_find_or_add(&cfi);
- }
-
- return 0;
-}
-
static int read_noendbr_hints(struct objtool_file *file)
{
struct section *sec;
diff --git a/tools/objtool/include/objtool/insn.h b/tools/objtool/include/objtool/insn.h
index b74c7f0d9076..cfd1ae7e2e8e 100644
--- a/tools/objtool/include/objtool/insn.h
+++ b/tools/objtool/include/objtool/insn.h
@@ -89,6 +89,7 @@ bool same_function(struct instruction *insn1, struct instruction *insn2);
bool is_first_func_insn(struct objtool_file *file, struct instruction *insn);
int decode_instructions(struct objtool_file *file);
+int read_unwind_hints(struct objtool_file *file);
#define for_each_insn(file, insn) \
list_for_each_entry(insn, &file->insn_list, list)
diff --git a/tools/objtool/sync-check.sh b/tools/objtool/sync-check.sh
index 105a291ff8e7..ee49b4e9e72c 100755
--- a/tools/objtool/sync-check.sh
+++ b/tools/objtool/sync-check.sh
@@ -14,6 +14,7 @@ arch/x86/include/asm/nops.h
arch/x86/include/asm/inat_types.h
arch/x86/include/asm/orc_types.h
arch/x86/include/asm/emulate_prefix.h
+arch/x86/include/asm/unwind_hints.h
arch/x86/lib/x86-opcode-map.txt
arch/x86/tools/gen-insn-attr-x86.awk
include/linux/static_call_types.h
diff --git a/tools/objtool/unwind_hints.c b/tools/objtool/unwind_hints.c
new file mode 100644
index 000000000000..f2521659bae5
--- /dev/null
+++ b/tools/objtool/unwind_hints.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
+ */
+#include <asm/unwind_hints.h>
+
+#include <objtool/builtin.h>
+#include <objtool/endianness.h>
+#include <objtool/insn.h>
+#include <objtool/warn.h>
+
+int read_unwind_hints(struct objtool_file *file)
+{
+ struct cfi_state cfi = init_cfi;
+ struct section *sec, *relocsec;
+ struct unwind_hint *hint;
+ struct instruction *insn;
+ struct reloc *reloc;
+ int i;
+
+ sec = find_section_by_name(file->elf, ".discard.unwind_hints");
+ if (!sec)
+ return 0;
+
+ relocsec = sec->reloc;
+ if (!relocsec) {
+ WARN("missing .rela.discard.unwind_hints section");
+ return -1;
+ }
+
+ if (sec->sh.sh_size % sizeof(struct unwind_hint)) {
+ WARN("struct unwind_hint size mismatch");
+ return -1;
+ }
+
+ file->hints = true;
+
+ for (i = 0; i < sec->sh.sh_size / sizeof(struct unwind_hint); i++) {
+ hint = (struct unwind_hint *)sec->data->d_buf + i;
+
+ reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
+ if (!reloc) {
+ WARN("can't find reloc for unwind_hints[%d]", i);
+ return -1;
+ }
+
+ insn = find_insn(file, reloc->sym->sec, reloc->addend);
+ if (!insn) {
+ WARN("can't find insn for unwind_hints[%d]", i);
+ return -1;
+ }
+
+ insn->hint = true;
+
+ if (hint->type == UNWIND_HINT_TYPE_SAVE) {
+ insn->hint = false;
+ insn->save = true;
+ continue;
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
+ insn->restore = true;
+ continue;
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) {
+ struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset);
+
+ if (sym && sym->bind == STB_GLOBAL) {
+ if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
+ WARN_FUNC("UNWIND_HINT_IRET_REGS without ENDBR",
+ insn->sec, insn->offset);
+ }
+
+ insn->entry = 1;
+ }
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_ENTRY) {
+ hint->type = UNWIND_HINT_TYPE_CALL;
+ insn->entry = 1;
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_FUNC) {
+ insn->cfi = &func_cfi;
+ continue;
+ }
+
+ if (insn->cfi)
+ cfi = *(insn->cfi);
+
+ if (arch_decode_hint_reg(hint->sp_reg, &cfi.cfa.base)) {
+ WARN_FUNC("unsupported unwind_hint sp base reg %d",
+ insn->sec, insn->offset, hint->sp_reg);
+ return -1;
+ }
+
+ cfi.cfa.offset = bswap_if_needed(hint->sp_offset);
+ cfi.type = hint->type;
+ cfi.end = hint->end;
+
+ insn->cfi = cfi_hash_find_or_add(&cfi);
+ }
+
+ return 0;
+}
--
2.25.1
WARNING: multiple messages have this Message-ID (diff)
From: madvenka@linux.microsoft.com
To: jpoimboe@redhat.com, peterz@infradead.org,
chenzhongjin@huawei.com, mark.rutland@arm.com,
broonie@kernel.org, nobuta.keiya@fujitsu.com,
sjitindarsingh@gmail.com, catalin.marinas@arm.com,
will@kernel.org, jamorris@linux.microsoft.com,
linux-arm-kernel@lists.infradead.org,
live-patching@vger.kernel.org, linux-kernel@vger.kernel.org,
madvenka@linux.microsoft.com
Subject: [RFC PATCH v3 04/22] objtool: Reorganize Unwind hint code
Date: Thu, 2 Feb 2023 01:40:18 -0600 [thread overview]
Message-ID: <20230202074036.507249-5-madvenka@linux.microsoft.com> (raw)
In-Reply-To: <20230202074036.507249-1-madvenka@linux.microsoft.com>
From: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com>
Unwind hint macros and struct unwind_hint are arch-specific. Move them
into the arch-specific file asm/unwind_hints.h. But the unwind hint
types are generic. Retain them in linux/objtool.h.
Unwind hints can be used with static stack validation as well as other
forms of validation such as dynamic FP validation. Move the function
read_unwind_hints() from check.c to a new file unwind_hints.c so that
it can be shared across validation schemes.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
---
arch/x86/include/asm/unwind_hints.h | 83 ++++++++++++
arch/x86/kernel/unwind_orc.c | 2 +-
include/linux/objtool.h | 67 ---------
tools/arch/x86/include/asm/unwind_hints.h | 157 ++++++++++++++++++++++
tools/include/linux/objtool.h | 67 ---------
tools/objtool/Build | 1 +
tools/objtool/check.c | 96 -------------
tools/objtool/include/objtool/insn.h | 1 +
tools/objtool/sync-check.sh | 1 +
tools/objtool/unwind_hints.c | 106 +++++++++++++++
10 files changed, 350 insertions(+), 231 deletions(-)
create mode 100644 tools/arch/x86/include/asm/unwind_hints.h
create mode 100644 tools/objtool/unwind_hints.c
diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h
index f66fbe6537dd..07c8d911266c 100644
--- a/arch/x86/include/asm/unwind_hints.h
+++ b/arch/x86/include/asm/unwind_hints.h
@@ -1,10 +1,93 @@
#ifndef _ASM_X86_UNWIND_HINTS_H
#define _ASM_X86_UNWIND_HINTS_H
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * This struct is used by asm and inline asm code to manually annotate the
+ * location of registers on the stack.
+ */
+struct unwind_hint {
+ u32 ip;
+ s16 sp_offset;
+ u8 sp_reg;
+ u8 type;
+ u8 end;
+};
+#endif
+
#include <linux/objtool.h>
#include "orc_types.h"
+#ifdef CONFIG_OBJTOOL
+
+#ifndef __ASSEMBLY__
+
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "987: \n\t" \
+ ".pushsection .discard.unwind_hints\n\t" \
+ /* struct unwind_hint */ \
+ ".long 987b - .\n\t" \
+ ".short " __stringify(sp_offset) "\n\t" \
+ ".byte " __stringify(sp_reg) "\n\t" \
+ ".byte " __stringify(type) "\n\t" \
+ ".byte " __stringify(end) "\n\t" \
+ ".balign 4 \n\t" \
+ ".popsection\n\t"
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * In asm, there are two kinds of code: normal C-type callable functions and
+ * the rest. The normal callable functions can be called by other code, and
+ * don't do anything unusual with the stack. Such normal callable functions
+ * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
+ * category. In this case, no special debugging annotations are needed because
+ * objtool can automatically generate the ORC data for the ORC unwinder to read
+ * at runtime.
+ *
+ * Anything which doesn't fall into the above category, such as syscall and
+ * interrupt handlers, tends to not be called directly by other functions, and
+ * often does unusual non-C-function-type things with the stack pointer. Such
+ * code needs to be annotated such that objtool can understand it. The
+ * following CFI hint macros are for this type of code.
+ *
+ * These macros provide hints to objtool about the state of the stack at each
+ * instruction. Objtool starts from the hints and follows the code flow,
+ * making automatic CFI adjustments when it sees pushes and pops, filling out
+ * the debuginfo as necessary. It will also warn if it sees any
+ * inconsistencies.
+ */
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.Lunwind_hint_ip_\@:
+ .pushsection .discard.unwind_hints
+ /* struct unwind_hint */
+ .long .Lunwind_hint_ip_\@ - .
+ .short \sp_offset
+ .byte \sp_reg
+ .byte \type
+ .byte \end
+ .balign 4
+ .popsection
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#else /* !CONFIG_OBJTOOL */
+
+#ifndef __ASSEMBLY__
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "\n\t"
+#else
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.endm
+#endif
+
+#endif /* CONFIG_OBJTOOL */
+
#ifdef __ASSEMBLY__
.macro UNWIND_HINT_EMPTY
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index c059820dfaea..c2bfc597d909 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
-#include <linux/objtool.h>
#include <linux/module.h>
#include <linux/sort.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>
#include <asm/unwind.h>
+#include <asm/unwind_hints.h>
#include <asm/orc_types.h>
#include <asm/orc_lookup.h>
diff --git a/include/linux/objtool.h b/include/linux/objtool.h
index 62c54ffbeeaa..1af295efc12c 100644
--- a/include/linux/objtool.h
+++ b/include/linux/objtool.h
@@ -2,23 +2,6 @@
#ifndef _LINUX_OBJTOOL_H
#define _LINUX_OBJTOOL_H
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/*
- * This struct is used by asm and inline asm code to manually annotate the
- * location of registers on the stack.
- */
-struct unwind_hint {
- u32 ip;
- s16 sp_offset;
- u8 sp_reg;
- u8 type;
- u8 end;
-};
-#endif
-
/*
* UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
* (the caller's SP right before it made the call). Used for all callable
@@ -49,18 +32,6 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "987: \n\t" \
- ".pushsection .discard.unwind_hints\n\t" \
- /* struct unwind_hint */ \
- ".long 987b - .\n\t" \
- ".short " __stringify(sp_offset) "\n\t" \
- ".byte " __stringify(sp_reg) "\n\t" \
- ".byte " __stringify(type) "\n\t" \
- ".byte " __stringify(end) "\n\t" \
- ".balign 4 \n\t" \
- ".popsection\n\t"
-
/*
* This macro marks the given function's stack frame as "non-standard", which
* tells objtool to ignore the function when doing stack metadata validation.
@@ -108,40 +79,6 @@ struct unwind_hint {
.long 999b; \
.popsection;
-/*
- * In asm, there are two kinds of code: normal C-type callable functions and
- * the rest. The normal callable functions can be called by other code, and
- * don't do anything unusual with the stack. Such normal callable functions
- * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
- * category. In this case, no special debugging annotations are needed because
- * objtool can automatically generate the ORC data for the ORC unwinder to read
- * at runtime.
- *
- * Anything which doesn't fall into the above category, such as syscall and
- * interrupt handlers, tends to not be called directly by other functions, and
- * often does unusual non-C-function-type things with the stack pointer. Such
- * code needs to be annotated such that objtool can understand it. The
- * following CFI hint macros are for this type of code.
- *
- * These macros provide hints to objtool about the state of the stack at each
- * instruction. Objtool starts from the hints and follows the code flow,
- * making automatic CFI adjustments when it sees pushes and pops, filling out
- * the debuginfo as necessary. It will also warn if it sees any
- * inconsistencies.
- */
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.Lunwind_hint_ip_\@:
- .pushsection .discard.unwind_hints
- /* struct unwind_hint */
- .long .Lunwind_hint_ip_\@ - .
- .short \sp_offset
- .byte \sp_reg
- .byte \type
- .byte \end
- .balign 4
- .popsection
-.endm
-
.macro STACK_FRAME_NON_STANDARD func:req
.pushsection .discard.func_stack_frame_non_standard, "aw"
_ASM_PTR \func
@@ -174,16 +111,12 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "\n\t"
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
.macro ANNOTATE_NOENDBR
diff --git a/tools/arch/x86/include/asm/unwind_hints.h b/tools/arch/x86/include/asm/unwind_hints.h
new file mode 100644
index 000000000000..07c8d911266c
--- /dev/null
+++ b/tools/arch/x86/include/asm/unwind_hints.h
@@ -0,0 +1,157 @@
+#ifndef _ASM_X86_UNWIND_HINTS_H
+#define _ASM_X86_UNWIND_HINTS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * This struct is used by asm and inline asm code to manually annotate the
+ * location of registers on the stack.
+ */
+struct unwind_hint {
+ u32 ip;
+ s16 sp_offset;
+ u8 sp_reg;
+ u8 type;
+ u8 end;
+};
+#endif
+
+#include <linux/objtool.h>
+
+#include "orc_types.h"
+
+#ifdef CONFIG_OBJTOOL
+
+#ifndef __ASSEMBLY__
+
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "987: \n\t" \
+ ".pushsection .discard.unwind_hints\n\t" \
+ /* struct unwind_hint */ \
+ ".long 987b - .\n\t" \
+ ".short " __stringify(sp_offset) "\n\t" \
+ ".byte " __stringify(sp_reg) "\n\t" \
+ ".byte " __stringify(type) "\n\t" \
+ ".byte " __stringify(end) "\n\t" \
+ ".balign 4 \n\t" \
+ ".popsection\n\t"
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * In asm, there are two kinds of code: normal C-type callable functions and
+ * the rest. The normal callable functions can be called by other code, and
+ * don't do anything unusual with the stack. Such normal callable functions
+ * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
+ * category. In this case, no special debugging annotations are needed because
+ * objtool can automatically generate the ORC data for the ORC unwinder to read
+ * at runtime.
+ *
+ * Anything which doesn't fall into the above category, such as syscall and
+ * interrupt handlers, tends to not be called directly by other functions, and
+ * often does unusual non-C-function-type things with the stack pointer. Such
+ * code needs to be annotated such that objtool can understand it. The
+ * following CFI hint macros are for this type of code.
+ *
+ * These macros provide hints to objtool about the state of the stack at each
+ * instruction. Objtool starts from the hints and follows the code flow,
+ * making automatic CFI adjustments when it sees pushes and pops, filling out
+ * the debuginfo as necessary. It will also warn if it sees any
+ * inconsistencies.
+ */
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.Lunwind_hint_ip_\@:
+ .pushsection .discard.unwind_hints
+ /* struct unwind_hint */
+ .long .Lunwind_hint_ip_\@ - .
+ .short \sp_offset
+ .byte \sp_reg
+ .byte \type
+ .byte \end
+ .balign 4
+ .popsection
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#else /* !CONFIG_OBJTOOL */
+
+#ifndef __ASSEMBLY__
+#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
+ "\n\t"
+#else
+.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
+.endm
+#endif
+
+#endif /* CONFIG_OBJTOOL */
+
+#ifdef __ASSEMBLY__
+
+.macro UNWIND_HINT_EMPTY
+ UNWIND_HINT type=UNWIND_HINT_TYPE_CALL end=1
+.endm
+
+.macro UNWIND_HINT_ENTRY
+ UNWIND_HINT type=UNWIND_HINT_TYPE_ENTRY end=1
+.endm
+
+.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0
+ .if \base == %rsp
+ .if \indirect
+ .set sp_reg, ORC_REG_SP_INDIRECT
+ .else
+ .set sp_reg, ORC_REG_SP
+ .endif
+ .elseif \base == %rbp
+ .set sp_reg, ORC_REG_BP
+ .elseif \base == %rdi
+ .set sp_reg, ORC_REG_DI
+ .elseif \base == %rdx
+ .set sp_reg, ORC_REG_DX
+ .elseif \base == %r10
+ .set sp_reg, ORC_REG_R10
+ .else
+ .error "UNWIND_HINT_REGS: bad base register"
+ .endif
+
+ .set sp_offset, \offset
+
+ .if \partial
+ .set type, UNWIND_HINT_TYPE_REGS_PARTIAL
+ .elseif \extra == 0
+ .set type, UNWIND_HINT_TYPE_REGS_PARTIAL
+ .set sp_offset, \offset + (16*8)
+ .else
+ .set type, UNWIND_HINT_TYPE_REGS
+ .endif
+
+ UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type
+.endm
+
+.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
+ UNWIND_HINT_REGS base=\base offset=\offset partial=1
+.endm
+
+.macro UNWIND_HINT_FUNC
+ UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=8 type=UNWIND_HINT_TYPE_FUNC
+.endm
+
+.macro UNWIND_HINT_SAVE
+ UNWIND_HINT type=UNWIND_HINT_TYPE_SAVE
+.endm
+
+.macro UNWIND_HINT_RESTORE
+ UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE
+.endm
+
+#else
+
+#define UNWIND_HINT_FUNC \
+ UNWIND_HINT(ORC_REG_SP, 8, UNWIND_HINT_TYPE_FUNC, 0)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_X86_UNWIND_HINTS_H */
diff --git a/tools/include/linux/objtool.h b/tools/include/linux/objtool.h
index 62c54ffbeeaa..1af295efc12c 100644
--- a/tools/include/linux/objtool.h
+++ b/tools/include/linux/objtool.h
@@ -2,23 +2,6 @@
#ifndef _LINUX_OBJTOOL_H
#define _LINUX_OBJTOOL_H
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/*
- * This struct is used by asm and inline asm code to manually annotate the
- * location of registers on the stack.
- */
-struct unwind_hint {
- u32 ip;
- s16 sp_offset;
- u8 sp_reg;
- u8 type;
- u8 end;
-};
-#endif
-
/*
* UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
* (the caller's SP right before it made the call). Used for all callable
@@ -49,18 +32,6 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "987: \n\t" \
- ".pushsection .discard.unwind_hints\n\t" \
- /* struct unwind_hint */ \
- ".long 987b - .\n\t" \
- ".short " __stringify(sp_offset) "\n\t" \
- ".byte " __stringify(sp_reg) "\n\t" \
- ".byte " __stringify(type) "\n\t" \
- ".byte " __stringify(end) "\n\t" \
- ".balign 4 \n\t" \
- ".popsection\n\t"
-
/*
* This macro marks the given function's stack frame as "non-standard", which
* tells objtool to ignore the function when doing stack metadata validation.
@@ -108,40 +79,6 @@ struct unwind_hint {
.long 999b; \
.popsection;
-/*
- * In asm, there are two kinds of code: normal C-type callable functions and
- * the rest. The normal callable functions can be called by other code, and
- * don't do anything unusual with the stack. Such normal callable functions
- * are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
- * category. In this case, no special debugging annotations are needed because
- * objtool can automatically generate the ORC data for the ORC unwinder to read
- * at runtime.
- *
- * Anything which doesn't fall into the above category, such as syscall and
- * interrupt handlers, tends to not be called directly by other functions, and
- * often does unusual non-C-function-type things with the stack pointer. Such
- * code needs to be annotated such that objtool can understand it. The
- * following CFI hint macros are for this type of code.
- *
- * These macros provide hints to objtool about the state of the stack at each
- * instruction. Objtool starts from the hints and follows the code flow,
- * making automatic CFI adjustments when it sees pushes and pops, filling out
- * the debuginfo as necessary. It will also warn if it sees any
- * inconsistencies.
- */
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.Lunwind_hint_ip_\@:
- .pushsection .discard.unwind_hints
- /* struct unwind_hint */
- .long .Lunwind_hint_ip_\@ - .
- .short \sp_offset
- .byte \sp_reg
- .byte \type
- .byte \end
- .balign 4
- .popsection
-.endm
-
.macro STACK_FRAME_NON_STANDARD func:req
.pushsection .discard.func_stack_frame_non_standard, "aw"
_ASM_PTR \func
@@ -174,16 +111,12 @@ struct unwind_hint {
#ifndef __ASSEMBLY__
-#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
- "\n\t"
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
-.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
-.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
.macro ANNOTATE_NOENDBR
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 8afe56cd0c2d..c4666d0b40ba 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -8,6 +8,7 @@ objtool-y += builtin-check.o
objtool-y += cfi.o
objtool-y += insn.o
objtool-y += decode.o
+objtool-y += unwind_hints.o
objtool-y += elf.o
objtool-y += objtool.o
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index be3f6564104a..d14a2b7b8b37 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1670,102 +1670,6 @@ static int add_jump_table_alts(struct objtool_file *file)
return 0;
}
-static int read_unwind_hints(struct objtool_file *file)
-{
- struct cfi_state cfi = init_cfi;
- struct section *sec, *relocsec;
- struct unwind_hint *hint;
- struct instruction *insn;
- struct reloc *reloc;
- int i;
-
- sec = find_section_by_name(file->elf, ".discard.unwind_hints");
- if (!sec)
- return 0;
-
- relocsec = sec->reloc;
- if (!relocsec) {
- WARN("missing .rela.discard.unwind_hints section");
- return -1;
- }
-
- if (sec->sh.sh_size % sizeof(struct unwind_hint)) {
- WARN("struct unwind_hint size mismatch");
- return -1;
- }
-
- file->hints = true;
-
- for (i = 0; i < sec->sh.sh_size / sizeof(struct unwind_hint); i++) {
- hint = (struct unwind_hint *)sec->data->d_buf + i;
-
- reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
- if (!reloc) {
- WARN("can't find reloc for unwind_hints[%d]", i);
- return -1;
- }
-
- insn = find_insn(file, reloc->sym->sec, reloc->addend);
- if (!insn) {
- WARN("can't find insn for unwind_hints[%d]", i);
- return -1;
- }
-
- insn->hint = true;
-
- if (hint->type == UNWIND_HINT_TYPE_SAVE) {
- insn->hint = false;
- insn->save = true;
- continue;
- }
-
- if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
- insn->restore = true;
- continue;
- }
-
- if (hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) {
- struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset);
-
- if (sym && sym->bind == STB_GLOBAL) {
- if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
- WARN_FUNC("UNWIND_HINT_IRET_REGS without ENDBR",
- insn->sec, insn->offset);
- }
-
- insn->entry = 1;
- }
- }
-
- if (hint->type == UNWIND_HINT_TYPE_ENTRY) {
- hint->type = UNWIND_HINT_TYPE_CALL;
- insn->entry = 1;
- }
-
- if (hint->type == UNWIND_HINT_TYPE_FUNC) {
- insn->cfi = &func_cfi;
- continue;
- }
-
- if (insn->cfi)
- cfi = *(insn->cfi);
-
- if (arch_decode_hint_reg(hint->sp_reg, &cfi.cfa.base)) {
- WARN_FUNC("unsupported unwind_hint sp base reg %d",
- insn->sec, insn->offset, hint->sp_reg);
- return -1;
- }
-
- cfi.cfa.offset = bswap_if_needed(hint->sp_offset);
- cfi.type = hint->type;
- cfi.end = hint->end;
-
- insn->cfi = cfi_hash_find_or_add(&cfi);
- }
-
- return 0;
-}
-
static int read_noendbr_hints(struct objtool_file *file)
{
struct section *sec;
diff --git a/tools/objtool/include/objtool/insn.h b/tools/objtool/include/objtool/insn.h
index b74c7f0d9076..cfd1ae7e2e8e 100644
--- a/tools/objtool/include/objtool/insn.h
+++ b/tools/objtool/include/objtool/insn.h
@@ -89,6 +89,7 @@ bool same_function(struct instruction *insn1, struct instruction *insn2);
bool is_first_func_insn(struct objtool_file *file, struct instruction *insn);
int decode_instructions(struct objtool_file *file);
+int read_unwind_hints(struct objtool_file *file);
#define for_each_insn(file, insn) \
list_for_each_entry(insn, &file->insn_list, list)
diff --git a/tools/objtool/sync-check.sh b/tools/objtool/sync-check.sh
index 105a291ff8e7..ee49b4e9e72c 100755
--- a/tools/objtool/sync-check.sh
+++ b/tools/objtool/sync-check.sh
@@ -14,6 +14,7 @@ arch/x86/include/asm/nops.h
arch/x86/include/asm/inat_types.h
arch/x86/include/asm/orc_types.h
arch/x86/include/asm/emulate_prefix.h
+arch/x86/include/asm/unwind_hints.h
arch/x86/lib/x86-opcode-map.txt
arch/x86/tools/gen-insn-attr-x86.awk
include/linux/static_call_types.h
diff --git a/tools/objtool/unwind_hints.c b/tools/objtool/unwind_hints.c
new file mode 100644
index 000000000000..f2521659bae5
--- /dev/null
+++ b/tools/objtool/unwind_hints.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2015-2017 Josh Poimboeuf <jpoimboe@redhat.com>
+ */
+#include <asm/unwind_hints.h>
+
+#include <objtool/builtin.h>
+#include <objtool/endianness.h>
+#include <objtool/insn.h>
+#include <objtool/warn.h>
+
+int read_unwind_hints(struct objtool_file *file)
+{
+ struct cfi_state cfi = init_cfi;
+ struct section *sec, *relocsec;
+ struct unwind_hint *hint;
+ struct instruction *insn;
+ struct reloc *reloc;
+ int i;
+
+ sec = find_section_by_name(file->elf, ".discard.unwind_hints");
+ if (!sec)
+ return 0;
+
+ relocsec = sec->reloc;
+ if (!relocsec) {
+ WARN("missing .rela.discard.unwind_hints section");
+ return -1;
+ }
+
+ if (sec->sh.sh_size % sizeof(struct unwind_hint)) {
+ WARN("struct unwind_hint size mismatch");
+ return -1;
+ }
+
+ file->hints = true;
+
+ for (i = 0; i < sec->sh.sh_size / sizeof(struct unwind_hint); i++) {
+ hint = (struct unwind_hint *)sec->data->d_buf + i;
+
+ reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
+ if (!reloc) {
+ WARN("can't find reloc for unwind_hints[%d]", i);
+ return -1;
+ }
+
+ insn = find_insn(file, reloc->sym->sec, reloc->addend);
+ if (!insn) {
+ WARN("can't find insn for unwind_hints[%d]", i);
+ return -1;
+ }
+
+ insn->hint = true;
+
+ if (hint->type == UNWIND_HINT_TYPE_SAVE) {
+ insn->hint = false;
+ insn->save = true;
+ continue;
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
+ insn->restore = true;
+ continue;
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) {
+ struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset);
+
+ if (sym && sym->bind == STB_GLOBAL) {
+ if (opts.ibt && insn->type != INSN_ENDBR && !insn->noendbr) {
+ WARN_FUNC("UNWIND_HINT_IRET_REGS without ENDBR",
+ insn->sec, insn->offset);
+ }
+
+ insn->entry = 1;
+ }
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_ENTRY) {
+ hint->type = UNWIND_HINT_TYPE_CALL;
+ insn->entry = 1;
+ }
+
+ if (hint->type == UNWIND_HINT_TYPE_FUNC) {
+ insn->cfi = &func_cfi;
+ continue;
+ }
+
+ if (insn->cfi)
+ cfi = *(insn->cfi);
+
+ if (arch_decode_hint_reg(hint->sp_reg, &cfi.cfa.base)) {
+ WARN_FUNC("unsupported unwind_hint sp base reg %d",
+ insn->sec, insn->offset, hint->sp_reg);
+ return -1;
+ }
+
+ cfi.cfa.offset = bswap_if_needed(hint->sp_offset);
+ cfi.type = hint->type;
+ cfi.end = hint->end;
+
+ insn->cfi = cfi_hash_find_or_add(&cfi);
+ }
+
+ return 0;
+}
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-02-02 7:42 UTC|newest]
Thread overview: 110+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <0337266cf19f4c98388e3f6d09f590d9de258dc7>
2023-02-02 7:40 ` [RFC PATCH v3 00/22] arm64: livepatch: Use ORC for dynamic frame pointer validation madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 01/22] objtool: Reorganize CFI code madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 02/22] objtool: Reorganize instruction-related code madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 03/22] objtool: Move decode_instructions() to a separate file madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` madvenka [this message]
2023-02-02 7:40 ` [RFC PATCH v3 04/22] objtool: Reorganize Unwind hint code madvenka
2023-02-02 7:40 ` [RFC PATCH v3 05/22] objtool: Reorganize ORC types madvenka
2023-02-02 7:40 ` madvenka
2023-02-18 9:30 ` Suraj Jitindar Singh
2023-02-18 9:30 ` Suraj Jitindar Singh
2023-03-06 16:45 ` Madhavan T. Venkataraman
2023-03-06 16:45 ` Madhavan T. Venkataraman
2023-02-02 7:40 ` [RFC PATCH v3 06/22] objtool: Reorganize ORC code madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 07/22] objtool: Reorganize ORC kernel code madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 08/22] objtool: Introduce STATIC_CHECK madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 09/22] objtool: arm64: Add basic definitions and compile madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 10/22] objtool: arm64: Implement decoder for Dynamic FP validation madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 11/22] objtool: arm64: Invoke the decoder madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 12/22] objtool: arm64: Compute destinations for call and jump instructions madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 13/22] objtool: arm64: Walk instructions and compute CFI for each instruction madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 14/22] objtool: arm64: Generate ORC data from CFI for object files madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 15/22] objtool: arm64: Add unwind hint support madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 16/22] arm64: Add unwind hints to exception handlers madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 17/22] arm64: Add kernel and module support for ORC madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 18/22] arm64: Build the kernel with ORC information madvenka
2023-02-02 7:40 ` madvenka
2023-02-10 7:52 ` Tomohiro Misono (Fujitsu)
2023-02-10 7:52 ` Tomohiro Misono (Fujitsu)
2023-02-11 4:34 ` Madhavan T. Venkataraman
2023-02-11 4:34 ` Madhavan T. Venkataraman
2023-02-02 7:40 ` [RFC PATCH v3 19/22] arm64: unwinder: Add a reliability check in the unwinder based on ORC madvenka
2023-02-02 7:40 ` madvenka
2023-02-23 4:07 ` Suraj Jitindar Singh
2023-02-23 4:07 ` Suraj Jitindar Singh
2023-03-06 16:52 ` Madhavan T. Venkataraman
2023-03-06 16:52 ` Madhavan T. Venkataraman
2023-02-02 7:40 ` [RFC PATCH v3 20/22] arm64: Define HAVE_DYNAMIC_FTRACE_WITH_ARGS madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 21/22] arm64: Define TIF_PATCH_PENDING for livepatch madvenka
2023-02-02 7:40 ` madvenka
2023-02-02 7:40 ` [RFC PATCH v3 22/22] arm64: Enable livepatch for ARM64 madvenka
2023-02-02 7:40 ` madvenka
2023-03-01 3:12 ` [RFC PATCH v3 00/22] arm64: livepatch: Use ORC for dynamic frame pointer validation Tomohiro Misono (Fujitsu)
2023-03-01 3:12 ` Tomohiro Misono (Fujitsu)
2023-03-02 16:23 ` Petr Mladek
2023-03-02 16:23 ` Petr Mladek
2023-03-03 9:40 ` Tomohiro Misono (Fujitsu)
2023-03-03 9:40 ` Tomohiro Misono (Fujitsu)
2023-03-06 16:58 ` Madhavan T. Venkataraman
2023-03-06 16:58 ` Madhavan T. Venkataraman
2023-03-06 16:57 ` Madhavan T. Venkataraman
2023-03-06 16:57 ` Madhavan T. Venkataraman
2023-03-23 17:17 ` Mark Rutland
2023-03-23 17:17 ` Mark Rutland
2023-04-08 3:40 ` Madhavan T. Venkataraman
2023-04-08 3:40 ` Madhavan T. Venkataraman
2023-04-11 13:25 ` Mark Rutland
2023-04-11 13:25 ` Mark Rutland
2023-04-12 4:17 ` Josh Poimboeuf
2023-04-12 4:17 ` Josh Poimboeuf
2023-04-12 4:48 ` Madhavan T. Venkataraman
2023-04-12 4:48 ` Madhavan T. Venkataraman
2023-04-12 4:50 ` Madhavan T. Venkataraman
2023-04-12 4:50 ` Madhavan T. Venkataraman
2023-04-12 5:01 ` Josh Poimboeuf
2023-04-12 5:01 ` Josh Poimboeuf
2023-04-12 14:50 ` Madhavan T. Venkataraman
2023-04-12 14:50 ` Madhavan T. Venkataraman
2023-04-12 15:52 ` Josh Poimboeuf
2023-04-12 15:52 ` Josh Poimboeuf
2023-04-13 14:59 ` Madhavan T. Venkataraman
2023-04-13 14:59 ` Madhavan T. Venkataraman
2023-04-13 16:30 ` Josh Poimboeuf
2023-04-13 16:30 ` Josh Poimboeuf
2023-04-15 4:27 ` Madhavan T. Venkataraman
2023-04-15 4:27 ` Madhavan T. Venkataraman
2023-04-15 5:05 ` Josh Poimboeuf
2023-04-15 5:05 ` Josh Poimboeuf
2023-04-15 16:15 ` Madhavan T. Venkataraman
2023-04-15 16:15 ` Madhavan T. Venkataraman
2023-04-16 8:21 ` Indu Bhagat
2023-04-16 8:21 ` Indu Bhagat
2023-04-13 17:04 ` Nick Desaulniers
2023-04-13 17:04 ` Nick Desaulniers
2023-04-13 18:15 ` Jose E. Marchesi
2023-04-13 18:15 ` Jose E. Marchesi
2023-04-15 4:14 ` Madhavan T. Venkataraman
2023-04-15 4:14 ` Madhavan T. Venkataraman
2023-12-14 20:49 ` ARM64 Livepatch based on SFrame Madhavan T. Venkataraman
2023-12-14 20:49 ` Madhavan T. Venkataraman
2023-12-15 13:04 ` Mark Rutland
2023-12-15 13:04 ` Mark Rutland
2023-12-15 15:15 ` Madhavan T. Venkataraman
2023-12-15 15:15 ` Madhavan T. Venkataraman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230202074036.507249-5-madvenka@linux.microsoft.com \
--to=madvenka@linux.microsoft.com \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=chenzhongjin@huawei.com \
--cc=jamorris@linux.microsoft.com \
--cc=jpoimboe@redhat.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=nobuta.keiya@fujitsu.com \
--cc=peterz@infradead.org \
--cc=sjitindarsingh@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.