mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-09 18:11:32 -04:00
For the most part, an absolute relocation type is used for rodata. In the case of STT_SECTION, reloc->sym->offset is always zero, for the other symbol types, reloc_addend(reloc) is always zero, thus it can use a simple statement "reloc->sym->offset + reloc_addend(reloc)" to obtain the symbol offset for various symbol types. When compiling on LoongArch, there exist PC relative relocation types for rodata, it needs to calculate the symbol offset with "S + A - PC" according to the spec of "ELF for the LoongArch Architecture". If there is only one jump table in the rodata, the "PC" is the entry address which is equal with the value of reloc_offset(reloc), at this time, reloc_offset(table) is 0. If there are many jump tables in the rodata, the "PC" is the offset of the jump table's base address which is equal with the value of reloc_offset(reloc) - reloc_offset(table). So for LoongArch, if the relocation type is PC relative, it can use a statement "reloc_offset(reloc) - reloc_offset(table)" to get the "PC" value when calculating the symbol offset with "S + A - PC" for one or many jump tables in the rodata. Add an arch-specific function arch_jump_table_sym_offset() to assign the symbol offset, for the most part that is an absolute relocation, the default value is "reloc->sym->offset + reloc_addend(reloc)" in the weak definition, it can be overridden by each architecture that has different requirements. Link: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Link: https://lore.kernel.org/r/20250211115016.26913-4-yangtiezhu@loongson.cn Acked-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
104 lines
2.0 KiB
C
104 lines
2.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
|
|
*/
|
|
|
|
#ifndef _ARCH_H
|
|
#define _ARCH_H
|
|
|
|
#include <stdbool.h>
|
|
#include <linux/list.h>
|
|
#include <objtool/objtool.h>
|
|
#include <objtool/cfi.h>
|
|
|
|
enum insn_type {
|
|
INSN_JUMP_CONDITIONAL,
|
|
INSN_JUMP_UNCONDITIONAL,
|
|
INSN_JUMP_DYNAMIC,
|
|
INSN_JUMP_DYNAMIC_CONDITIONAL,
|
|
INSN_CALL,
|
|
INSN_CALL_DYNAMIC,
|
|
INSN_RETURN,
|
|
INSN_CONTEXT_SWITCH,
|
|
INSN_BUG,
|
|
INSN_NOP,
|
|
INSN_STAC,
|
|
INSN_CLAC,
|
|
INSN_STD,
|
|
INSN_CLD,
|
|
INSN_TRAP,
|
|
INSN_ENDBR,
|
|
INSN_LEA_RIP,
|
|
INSN_OTHER,
|
|
};
|
|
|
|
enum op_dest_type {
|
|
OP_DEST_REG,
|
|
OP_DEST_REG_INDIRECT,
|
|
OP_DEST_MEM,
|
|
OP_DEST_PUSH,
|
|
OP_DEST_PUSHF,
|
|
};
|
|
|
|
struct op_dest {
|
|
enum op_dest_type type;
|
|
unsigned char reg;
|
|
int offset;
|
|
};
|
|
|
|
enum op_src_type {
|
|
OP_SRC_REG,
|
|
OP_SRC_REG_INDIRECT,
|
|
OP_SRC_CONST,
|
|
OP_SRC_POP,
|
|
OP_SRC_POPF,
|
|
OP_SRC_ADD,
|
|
OP_SRC_AND,
|
|
};
|
|
|
|
struct op_src {
|
|
enum op_src_type type;
|
|
unsigned char reg;
|
|
int offset;
|
|
};
|
|
|
|
struct stack_op {
|
|
struct stack_op *next;
|
|
struct op_dest dest;
|
|
struct op_src src;
|
|
};
|
|
|
|
struct instruction;
|
|
|
|
int arch_ftrace_match(char *name);
|
|
|
|
void arch_initial_func_cfi_state(struct cfi_init_state *state);
|
|
|
|
int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
|
|
unsigned long offset, unsigned int maxlen,
|
|
struct instruction *insn);
|
|
|
|
bool arch_callee_saved_reg(unsigned char reg);
|
|
|
|
unsigned long arch_jump_destination(struct instruction *insn);
|
|
|
|
unsigned long arch_dest_reloc_offset(int addend);
|
|
|
|
const char *arch_nop_insn(int len);
|
|
const char *arch_ret_insn(int len);
|
|
|
|
int arch_decode_hint_reg(u8 sp_reg, int *base);
|
|
|
|
bool arch_is_retpoline(struct symbol *sym);
|
|
bool arch_is_rethunk(struct symbol *sym);
|
|
bool arch_is_embedded_insn(struct symbol *sym);
|
|
|
|
int arch_rewrite_retpolines(struct objtool_file *file);
|
|
|
|
bool arch_pc_relative_reloc(struct reloc *reloc);
|
|
|
|
unsigned int arch_reloc_size(struct reloc *reloc);
|
|
unsigned long arch_jump_table_sym_offset(struct reloc *reloc, struct reloc *table);
|
|
|
|
#endif /* _ARCH_H */
|