Make part of the data definition into the .data section, avoid objtool
to detect "unreachable instruction" warning.
At the same time, removing unreachable instruction flow operations
(b process_entry).
Co-developed-by: Jinyang He <[email protected]>
Signed-off-by: Jinyang He <[email protected]>
Signed-off-by: Youling Tang <[email protected]>
---
arch/loongarch/kernel/genex.S | 2 ++
arch/loongarch/kernel/relocate_kernel.S | 7 +++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/loongarch/kernel/genex.S b/arch/loongarch/kernel/genex.S
index 44ff1ff64260..883b718b5ffe 100644
--- a/arch/loongarch/kernel/genex.S
+++ b/arch/loongarch/kernel/genex.S
@@ -77,7 +77,9 @@ SYM_FUNC_END(except_vec_cex)
668:
RESTORE_ALL_AND_RET
SYM_FUNC_END(handle_\exception)
+ .pushsection ".data", "aw", %progbits
SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
+ .popsection
.endm
BUILD_HANDLER ade ade badv
diff --git a/arch/loongarch/kernel/relocate_kernel.S b/arch/loongarch/kernel/relocate_kernel.S
index d0123fa2b511..1ea3df967b46 100644
--- a/arch/loongarch/kernel/relocate_kernel.S
+++ b/arch/loongarch/kernel/relocate_kernel.S
@@ -75,7 +75,6 @@ copy_word:
LONG_ADDI s5, s5, -1
beqz s5, process_entry
b copy_word
- b process_entry
done:
ibar 0
@@ -112,6 +111,6 @@ SYM_CODE_END(kexec_smp_wait)
relocate_new_kernel_end:
-SYM_DATA_START(relocate_new_kernel_size)
- PTR relocate_new_kernel_end - relocate_new_kernel
-SYM_DATA_END(relocate_new_kernel_size)
+.pushsection ".data", "aw", %progbits
+SYM_DATA(relocate_new_kernel_size, .long relocate_new_kernel_end - relocate_new_kernel)
+.popsection
--
2.39.2
Fix the following warnings:
arch/loongarch/mm/fault.o: warning: objtool: no_context.part.0() falls through to
next function do_sigsegv()
It should mark 'dead_end' when the function is "noreturn/__noreturn".
Signed-off-by: Youling Tang <[email protected]>
---
tools/objtool/arch/loongarch/special.c | 5 +++++
tools/objtool/arch/powerpc/special.c | 3 +++
tools/objtool/arch/x86/special.c | 4 ++++
tools/objtool/check.c | 7 ++++++-
tools/objtool/include/objtool/special.h | 3 +++
5 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/tools/objtool/arch/loongarch/special.c b/tools/objtool/arch/loongarch/special.c
index 8669dbe44459..be4d5d83e331 100644
--- a/tools/objtool/arch/loongarch/special.c
+++ b/tools/objtool/arch/loongarch/special.c
@@ -5,6 +5,11 @@
#include <objtool/special.h>
#include <objtool/builtin.h>
+/* Architecture specific "noreturn" function */
+const char * const arch_noreturns[] = {
+ "die",
+};
+int arch_noreturns_size = ARRAY_SIZE(arch_noreturns);
bool arch_support_alt_relocation(struct special_alt *special_alt,
struct instruction *insn,
diff --git a/tools/objtool/arch/powerpc/special.c b/tools/objtool/arch/powerpc/special.c
index d33868147196..35107e6ae2f1 100644
--- a/tools/objtool/arch/powerpc/special.c
+++ b/tools/objtool/arch/powerpc/special.c
@@ -4,6 +4,9 @@
#include <objtool/special.h>
#include <objtool/builtin.h>
+/* Architecture specific "noreturn" function */
+const char * const arch_noreturns[] = {};
+int arch_noreturns_size = ARRAY_SIZE(arch_noreturns);
bool arch_support_alt_relocation(struct special_alt *special_alt,
struct instruction *insn,
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 7c97b7391279..48fa72f564f9 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -7,6 +7,10 @@
#define X86_FEATURE_POPCNT (4 * 32 + 23)
#define X86_FEATURE_SMAP (9 * 32 + 20)
+/* Architecture specific "noreturn" function */
+const char * const arch_noreturns[] = {};
+int arch_noreturns_size = ARRAY_SIZE(arch_noreturns);
+
void arch_handle_alternative(unsigned short feature, struct special_alt *alt)
{
switch (feature) {
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f91723010d6b..c637e54088f6 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -110,11 +110,16 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
if (func->bind == STB_WEAK)
return false;
- if (func->bind == STB_GLOBAL)
+ if (func->bind == STB_GLOBAL) {
for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
if (!strcmp(func->name, global_noreturns[i]))
return true;
+ for (i = 0; i < arch_noreturns_size; i++)
+ if (!strcmp(func->name, arch_noreturns[i]))
+ return true;
+ }
+
if (!func->len)
return false;
diff --git a/tools/objtool/include/objtool/special.h b/tools/objtool/include/objtool/special.h
index 86d4af9c5aa9..f800817f0ed8 100644
--- a/tools/objtool/include/objtool/special.h
+++ b/tools/objtool/include/objtool/special.h
@@ -30,6 +30,9 @@ struct special_alt {
unsigned int orig_len, new_len; /* group only */
};
+extern const char * const arch_noreturns[];
+extern int arch_noreturns_size;
+
int special_get_alts(struct elf *elf, struct list_head *alts);
void arch_handle_alternative(unsigned short feature, struct special_alt *alt);
--
2.39.2
Set OBJECT_FILES_NON_STANDARD for their related files and directories,
which will tell objtool to skip checking them. It's ok to skip them
because they don't affect runtime stack traces.
Signed-off-by: Youling Tang <[email protected]>
---
arch/loongarch/kernel/Makefile | 2 ++
arch/loongarch/power/Makefile | 2 ++
arch/loongarch/vdso/Makefile | 2 ++
3 files changed, 6 insertions(+)
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index fcbfa0f38b53..9ea4d6b93f4d 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -3,6 +3,8 @@
# Makefile for the Linux/LoongArch kernel.
#
+OBJECT_FILES_NON_STANDARD_head.o := y
+
extra-y := vmlinux.lds
obj-y += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
diff --git a/arch/loongarch/power/Makefile b/arch/loongarch/power/Makefile
index 58151d003e40..bbd1d4793e8b 100644
--- a/arch/loongarch/power/Makefile
+++ b/arch/loongarch/power/Makefile
@@ -1,3 +1,5 @@
+OBJECT_FILES_NON_STANDARD_suspend_asm.o := y
+
obj-y += platform.o
obj-$(CONFIG_SUSPEND) += suspend.o suspend_asm.o
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
index d89e2ac75f7b..37c7795990b8 100644
--- a/arch/loongarch/vdso/Makefile
+++ b/arch/loongarch/vdso/Makefile
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# Objects to go into the VDSO.
+OBJECT_FILES_NON_STANDARD := y
+
# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
# the inclusion of generic Makefile.
ARCH_REL_TYPE_ABS := R_LARCH_32|R_LARCH_64|R_LARCH_MARK_LA|R_LARCH_JUMP_SLOT
--
2.39.2
Currently update_cfi_state() is implemented for the x86_64 architecture. This
function is specific to the architecture. In order to avoid powerpc build
errors, define x86_64 as the default implementation and rename update_cfi_state()
to arch_update_cfi_state().
LoongArch will reimplement arch_update_cfi_state().
Co-developed-by: Jinyang He <[email protected]>
Signed-off-by: Jinyang He <[email protected]>
Signed-off-by: Youling Tang <[email protected]>
---
tools/objtool/arch/loongarch/decode.c | 76 +++++++++++++++++++++++++++
tools/objtool/check.c | 10 ++--
tools/objtool/include/objtool/arch.h | 3 ++
tools/objtool/include/objtool/check.h | 5 ++
4 files changed, 89 insertions(+), 5 deletions(-)
diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index 90adbbeab8d4..6ca8cbad6813 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -4,6 +4,8 @@
#include <stdlib.h>
#include <linux/bitops.h>
+#include <linux/objtool.h>
+
#include <asm/inst.h>
#include <asm/orc_types.h>
@@ -274,3 +276,77 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state)
state->cfa.base = CFI_SP;
state->cfa.offset = 0;
}
+
+
+int arch_update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op)
+{
+ struct cfi_reg *cfa = &cfi->cfa;
+ struct cfi_reg *regs = cfi->regs;
+
+ /* stack operations don't make sense with an undefined CFA */
+ if (cfa->base == CFI_UNDEFINED) {
+ if (insn_func(insn)) {
+ WARN_FUNC("undefined stack state", insn->sec, insn->offset);
+ return -1;
+ }
+ return 0;
+ }
+
+ if (cfi->type == UNWIND_HINT_TYPE_REGS)
+ return update_cfi_state_regs(insn, cfi, op);
+
+
+ switch (op->dest.type) {
+ case OP_DEST_REG:
+ switch (op->src.type) {
+ case OP_SRC_ADD:
+ if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) {
+ /* addi.d sp, sp, imm */
+ cfi->stack_size -= op->src.offset;
+ if (cfa->base == CFI_SP)
+ cfa->offset -= op->src.offset;
+ } else if (op->dest.reg == CFI_FP && op->src.reg == CFI_SP) {
+ /* addi.d fp, sp, imm */
+ if (cfa->base == CFI_SP && cfa->offset == op->src.offset) {
+ cfa->base = CFI_FP;
+ cfa->offset = 0;
+ }
+ } else if (op->dest.reg == CFI_SP && op->src.reg == CFI_FP) {
+ /* addi.d sp, fp, imm */
+ if (cfa->base == CFI_FP && cfa->offset == 0) {
+ cfa->base = CFI_SP;
+ cfa->offset = -op->src.offset;
+ }
+ }
+ break;
+ case OP_SRC_REG_INDIRECT:
+ /* ld.d _reg, sp, imm */
+ if (op->src.reg == CFI_SP &&
+ op->src.offset == (regs[op->dest.reg].offset + cfi->stack_size)) {
+ restore_reg(cfi, op->dest.reg);
+ /* Gcc may not restore sp, we adjust it directly. */
+ if (cfa->base == CFI_FP && cfa->offset == 0) {
+ cfa->base = CFI_SP;
+ cfa->offset = cfi->stack_size;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case OP_DEST_REG_INDIRECT:
+ if (op->src.type == OP_SRC_REG)
+ /* st.d _reg, sp, imm */
+ if (op->dest.offset)
+ save_reg(cfi, op->src.reg, CFI_CFA, op->dest.offset - cfi->stack_size);
+ break;
+ default:
+ WARN_FUNC("unknown stack-related instruction", insn->sec, insn->offset);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index c637e54088f6..42f87a33f558 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2230,7 +2230,7 @@ static bool has_valid_stack_frame(struct insn_state *state)
return false;
}
-static int update_cfi_state_regs(struct instruction *insn,
+int update_cfi_state_regs(struct instruction *insn,
struct cfi_state *cfi,
struct stack_op *op)
{
@@ -2255,7 +2255,7 @@ static int update_cfi_state_regs(struct instruction *insn,
return 0;
}
-static void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset)
+void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset)
{
if (arch_callee_saved_reg(reg) &&
cfi->regs[reg].base == CFI_UNDEFINED) {
@@ -2264,7 +2264,7 @@ static void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int off
}
}
-static void restore_reg(struct cfi_state *cfi, unsigned char reg)
+void restore_reg(struct cfi_state *cfi, unsigned char reg)
{
cfi->regs[reg].base = initial_func_cfi.regs[reg].base;
cfi->regs[reg].offset = initial_func_cfi.regs[reg].offset;
@@ -2323,7 +2323,7 @@ static void restore_reg(struct cfi_state *cfi, unsigned char reg)
* 41 5d pop %r13
* c3 retq
*/
-static int update_cfi_state(struct instruction *insn,
+int __weak arch_update_cfi_state(struct instruction *insn,
struct instruction *next_insn,
struct cfi_state *cfi, struct stack_op *op)
{
@@ -2795,7 +2795,7 @@ static int handle_insn_ops(struct instruction *insn,
for (op = insn->stack_ops; op; op = op->next) {
- if (update_cfi_state(insn, next_insn, &state->cfi, op))
+ if (arch_update_cfi_state(insn, next_insn, &state->cfi, op))
return 1;
if (!insn->alt_group)
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 2b6d2ce4f9a5..88570c598752 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -95,4 +95,7 @@ int arch_rewrite_retpolines(struct objtool_file *file);
bool arch_pc_relative_reloc(struct reloc *reloc);
+int __weak arch_update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op);
#endif /* _ARCH_H */
diff --git a/tools/objtool/include/objtool/check.h b/tools/objtool/include/objtool/check.h
index 34898364bf03..dd1b95c67620 100644
--- a/tools/objtool/include/objtool/check.h
+++ b/tools/objtool/include/objtool/check.h
@@ -33,4 +33,9 @@ struct alt_group {
extern unsigned long nr_insns;
+int update_cfi_state_regs(struct instruction *insn,
+ struct cfi_state *cfi,
+ struct stack_op *op);
+void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset);
+void restore_reg(struct cfi_state *cfi, unsigned char reg);
#endif /* _CHECK_H */
--
2.39.2