objtool: Change arch_decode_instruction() signature
In preparation to changing struct instruction around a bit, avoid passing it's members by pointer and instead pass the whole thing. A cleanup in it's own right too. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Acked-by: Josh Poimboeuf <jpoimboe@kernel.org> Tested-by: Nathan Chancellor <nathan@kernel.org> # build only Tested-by: Thomas Weißschuh <linux@weissschuh.net> # compile and run Link: https://lore.kernel.org/r/20230208172245.291087549@infradead.org
This commit is contained in:
Родитель
585a78c1f7
Коммит
20a554638d
|
@ -41,38 +41,36 @@ const char *arch_ret_insn(int len)
|
|||
|
||||
int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
|
||||
unsigned long offset, unsigned int maxlen,
|
||||
unsigned int *len, enum insn_type *type,
|
||||
unsigned long *immediate,
|
||||
struct list_head *ops_list)
|
||||
struct instruction *insn)
|
||||
{
|
||||
unsigned int opcode;
|
||||
enum insn_type typ;
|
||||
unsigned long imm;
|
||||
u32 insn;
|
||||
u32 ins;
|
||||
|
||||
insn = bswap_if_needed(file->elf, *(u32 *)(sec->data->d_buf + offset));
|
||||
opcode = insn >> 26;
|
||||
ins = bswap_if_needed(file->elf, *(u32 *)(sec->data->d_buf + offset));
|
||||
opcode = ins >> 26;
|
||||
typ = INSN_OTHER;
|
||||
imm = 0;
|
||||
|
||||
switch (opcode) {
|
||||
case 18: /* b[l][a] */
|
||||
if ((insn & 3) == 1) /* bl */
|
||||
if ((ins & 3) == 1) /* bl */
|
||||
typ = INSN_CALL;
|
||||
|
||||
imm = insn & 0x3fffffc;
|
||||
imm = ins & 0x3fffffc;
|
||||
if (imm & 0x2000000)
|
||||
imm -= 0x4000000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (opcode == 1)
|
||||
*len = 8;
|
||||
insn->len = 8;
|
||||
else
|
||||
*len = 4;
|
||||
insn->len = 4;
|
||||
|
||||
*type = typ;
|
||||
*immediate = imm;
|
||||
insn->type = typ;
|
||||
insn->immediate = imm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -146,12 +146,11 @@ static bool has_notrack_prefix(struct insn *insn)
|
|||
|
||||
int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
|
||||
unsigned long offset, unsigned int maxlen,
|
||||
unsigned int *len, enum insn_type *type,
|
||||
unsigned long *immediate,
|
||||
struct list_head *ops_list)
|
||||
struct instruction *insn)
|
||||
{
|
||||
struct list_head *ops_list = &insn->stack_ops;
|
||||
const struct elf *elf = file->elf;
|
||||
struct insn insn;
|
||||
struct insn ins;
|
||||
int x86_64, ret;
|
||||
unsigned char op1, op2, op3, prefix,
|
||||
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
|
||||
|
@ -165,42 +164,42 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
if (x86_64 == -1)
|
||||
return -1;
|
||||
|
||||
ret = insn_decode(&insn, sec->data->d_buf + offset, maxlen,
|
||||
ret = insn_decode(&ins, sec->data->d_buf + offset, maxlen,
|
||||
x86_64 ? INSN_MODE_64 : INSN_MODE_32);
|
||||
if (ret < 0) {
|
||||
WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*len = insn.length;
|
||||
*type = INSN_OTHER;
|
||||
insn->len = ins.length;
|
||||
insn->type = INSN_OTHER;
|
||||
|
||||
if (insn.vex_prefix.nbytes)
|
||||
if (ins.vex_prefix.nbytes)
|
||||
return 0;
|
||||
|
||||
prefix = insn.prefixes.bytes[0];
|
||||
prefix = ins.prefixes.bytes[0];
|
||||
|
||||
op1 = insn.opcode.bytes[0];
|
||||
op2 = insn.opcode.bytes[1];
|
||||
op3 = insn.opcode.bytes[2];
|
||||
op1 = ins.opcode.bytes[0];
|
||||
op2 = ins.opcode.bytes[1];
|
||||
op3 = ins.opcode.bytes[2];
|
||||
|
||||
if (insn.rex_prefix.nbytes) {
|
||||
rex = insn.rex_prefix.bytes[0];
|
||||
if (ins.rex_prefix.nbytes) {
|
||||
rex = ins.rex_prefix.bytes[0];
|
||||
rex_w = X86_REX_W(rex) >> 3;
|
||||
rex_r = X86_REX_R(rex) >> 2;
|
||||
rex_x = X86_REX_X(rex) >> 1;
|
||||
rex_b = X86_REX_B(rex);
|
||||
}
|
||||
|
||||
if (insn.modrm.nbytes) {
|
||||
modrm = insn.modrm.bytes[0];
|
||||
if (ins.modrm.nbytes) {
|
||||
modrm = ins.modrm.bytes[0];
|
||||
modrm_mod = X86_MODRM_MOD(modrm);
|
||||
modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
|
||||
modrm_rm = X86_MODRM_RM(modrm) + 8*rex_b;
|
||||
}
|
||||
|
||||
if (insn.sib.nbytes) {
|
||||
sib = insn.sib.bytes[0];
|
||||
if (ins.sib.nbytes) {
|
||||
sib = ins.sib.bytes[0];
|
||||
/* sib_scale = X86_SIB_SCALE(sib); */
|
||||
sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
|
||||
sib_base = X86_SIB_BASE(sib) + 8*rex_b;
|
||||
|
@ -254,7 +253,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
break;
|
||||
|
||||
case 0x70 ... 0x7f:
|
||||
*type = INSN_JUMP_CONDITIONAL;
|
||||
insn->type = INSN_JUMP_CONDITIONAL;
|
||||
break;
|
||||
|
||||
case 0x80 ... 0x83:
|
||||
|
@ -278,7 +277,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
if (!rm_is_reg(CFI_SP))
|
||||
break;
|
||||
|
||||
imm = insn.immediate.value;
|
||||
imm = ins.immediate.value;
|
||||
if (op1 & 2) { /* sign extend */
|
||||
if (op1 & 1) { /* imm32 */
|
||||
imm <<= 32;
|
||||
|
@ -309,7 +308,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
ADD_OP(op) {
|
||||
op->src.type = OP_SRC_AND;
|
||||
op->src.reg = CFI_SP;
|
||||
op->src.offset = insn.immediate.value;
|
||||
op->src.offset = ins.immediate.value;
|
||||
op->dest.type = OP_DEST_REG;
|
||||
op->dest.reg = CFI_SP;
|
||||
}
|
||||
|
@ -356,7 +355,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
op->src.reg = CFI_SP;
|
||||
op->dest.type = OP_DEST_REG_INDIRECT;
|
||||
op->dest.reg = modrm_rm;
|
||||
op->dest.offset = insn.displacement.value;
|
||||
op->dest.offset = ins.displacement.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -389,7 +388,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
op->src.reg = modrm_reg;
|
||||
op->dest.type = OP_DEST_REG_INDIRECT;
|
||||
op->dest.reg = CFI_BP;
|
||||
op->dest.offset = insn.displacement.value;
|
||||
op->dest.offset = ins.displacement.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -402,7 +401,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
op->src.reg = modrm_reg;
|
||||
op->dest.type = OP_DEST_REG_INDIRECT;
|
||||
op->dest.reg = CFI_SP;
|
||||
op->dest.offset = insn.displacement.value;
|
||||
op->dest.offset = ins.displacement.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -419,7 +418,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
ADD_OP(op) {
|
||||
op->src.type = OP_SRC_REG_INDIRECT;
|
||||
op->src.reg = CFI_BP;
|
||||
op->src.offset = insn.displacement.value;
|
||||
op->src.offset = ins.displacement.value;
|
||||
op->dest.type = OP_DEST_REG;
|
||||
op->dest.reg = modrm_reg;
|
||||
}
|
||||
|
@ -432,7 +431,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
ADD_OP(op) {
|
||||
op->src.type = OP_SRC_REG_INDIRECT;
|
||||
op->src.reg = CFI_SP;
|
||||
op->src.offset = insn.displacement.value;
|
||||
op->src.offset = ins.displacement.value;
|
||||
op->dest.type = OP_DEST_REG;
|
||||
op->dest.reg = modrm_reg;
|
||||
}
|
||||
|
@ -464,7 +463,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
|
||||
/* lea disp(%src), %dst */
|
||||
ADD_OP(op) {
|
||||
op->src.offset = insn.displacement.value;
|
||||
op->src.offset = ins.displacement.value;
|
||||
if (!op->src.offset) {
|
||||
/* lea (%src), %dst */
|
||||
op->src.type = OP_SRC_REG;
|
||||
|
@ -487,7 +486,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
break;
|
||||
|
||||
case 0x90:
|
||||
*type = INSN_NOP;
|
||||
insn->type = INSN_NOP;
|
||||
break;
|
||||
|
||||
case 0x9c:
|
||||
|
@ -511,39 +510,39 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
if (op2 == 0x01) {
|
||||
|
||||
if (modrm == 0xca)
|
||||
*type = INSN_CLAC;
|
||||
insn->type = INSN_CLAC;
|
||||
else if (modrm == 0xcb)
|
||||
*type = INSN_STAC;
|
||||
insn->type = INSN_STAC;
|
||||
|
||||
} else if (op2 >= 0x80 && op2 <= 0x8f) {
|
||||
|
||||
*type = INSN_JUMP_CONDITIONAL;
|
||||
insn->type = INSN_JUMP_CONDITIONAL;
|
||||
|
||||
} else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
|
||||
op2 == 0x35) {
|
||||
|
||||
/* sysenter, sysret */
|
||||
*type = INSN_CONTEXT_SWITCH;
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
|
||||
} else if (op2 == 0x0b || op2 == 0xb9) {
|
||||
|
||||
/* ud2 */
|
||||
*type = INSN_BUG;
|
||||
insn->type = INSN_BUG;
|
||||
|
||||
} else if (op2 == 0x0d || op2 == 0x1f) {
|
||||
|
||||
/* nopl/nopw */
|
||||
*type = INSN_NOP;
|
||||
insn->type = INSN_NOP;
|
||||
|
||||
} else if (op2 == 0x1e) {
|
||||
|
||||
if (prefix == 0xf3 && (modrm == 0xfa || modrm == 0xfb))
|
||||
*type = INSN_ENDBR;
|
||||
insn->type = INSN_ENDBR;
|
||||
|
||||
|
||||
} else if (op2 == 0x38 && op3 == 0xf8) {
|
||||
if (insn.prefixes.nbytes == 1 &&
|
||||
insn.prefixes.bytes[0] == 0xf2) {
|
||||
if (ins.prefixes.nbytes == 1 &&
|
||||
ins.prefixes.bytes[0] == 0xf2) {
|
||||
/* ENQCMD cannot be used in the kernel. */
|
||||
WARN("ENQCMD instruction at %s:%lx", sec->name,
|
||||
offset);
|
||||
|
@ -591,29 +590,29 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
|
||||
case 0xcc:
|
||||
/* int3 */
|
||||
*type = INSN_TRAP;
|
||||
insn->type = INSN_TRAP;
|
||||
break;
|
||||
|
||||
case 0xe3:
|
||||
/* jecxz/jrcxz */
|
||||
*type = INSN_JUMP_CONDITIONAL;
|
||||
insn->type = INSN_JUMP_CONDITIONAL;
|
||||
break;
|
||||
|
||||
case 0xe9:
|
||||
case 0xeb:
|
||||
*type = INSN_JUMP_UNCONDITIONAL;
|
||||
insn->type = INSN_JUMP_UNCONDITIONAL;
|
||||
break;
|
||||
|
||||
case 0xc2:
|
||||
case 0xc3:
|
||||
*type = INSN_RETURN;
|
||||
insn->type = INSN_RETURN;
|
||||
break;
|
||||
|
||||
case 0xc7: /* mov imm, r/m */
|
||||
if (!opts.noinstr)
|
||||
break;
|
||||
|
||||
if (insn.length == 3+4+4 && !strncmp(sec->name, ".init.text", 10)) {
|
||||
if (ins.length == 3+4+4 && !strncmp(sec->name, ".init.text", 10)) {
|
||||
struct reloc *immr, *disp;
|
||||
struct symbol *func;
|
||||
int idx;
|
||||
|
@ -661,17 +660,17 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
|
||||
case 0xca: /* retf */
|
||||
case 0xcb: /* retf */
|
||||
*type = INSN_CONTEXT_SWITCH;
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
break;
|
||||
|
||||
case 0xe0: /* loopne */
|
||||
case 0xe1: /* loope */
|
||||
case 0xe2: /* loop */
|
||||
*type = INSN_JUMP_CONDITIONAL;
|
||||
insn->type = INSN_JUMP_CONDITIONAL;
|
||||
break;
|
||||
|
||||
case 0xe8:
|
||||
*type = INSN_CALL;
|
||||
insn->type = INSN_CALL;
|
||||
/*
|
||||
* For the impact on the stack, a CALL behaves like
|
||||
* a PUSH of an immediate value (the return address).
|
||||
|
@ -683,30 +682,30 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
break;
|
||||
|
||||
case 0xfc:
|
||||
*type = INSN_CLD;
|
||||
insn->type = INSN_CLD;
|
||||
break;
|
||||
|
||||
case 0xfd:
|
||||
*type = INSN_STD;
|
||||
insn->type = INSN_STD;
|
||||
break;
|
||||
|
||||
case 0xff:
|
||||
if (modrm_reg == 2 || modrm_reg == 3) {
|
||||
|
||||
*type = INSN_CALL_DYNAMIC;
|
||||
if (has_notrack_prefix(&insn))
|
||||
insn->type = INSN_CALL_DYNAMIC;
|
||||
if (has_notrack_prefix(&ins))
|
||||
WARN("notrack prefix found at %s:0x%lx", sec->name, offset);
|
||||
|
||||
} else if (modrm_reg == 4) {
|
||||
|
||||
*type = INSN_JUMP_DYNAMIC;
|
||||
if (has_notrack_prefix(&insn))
|
||||
insn->type = INSN_JUMP_DYNAMIC;
|
||||
if (has_notrack_prefix(&ins))
|
||||
WARN("notrack prefix found at %s:0x%lx", sec->name, offset);
|
||||
|
||||
} else if (modrm_reg == 5) {
|
||||
|
||||
/* jmpf */
|
||||
*type = INSN_CONTEXT_SWITCH;
|
||||
insn->type = INSN_CONTEXT_SWITCH;
|
||||
|
||||
} else if (modrm_reg == 6) {
|
||||
|
||||
|
@ -723,7 +722,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
|
|||
break;
|
||||
}
|
||||
|
||||
*immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
|
||||
insn->immediate = ins.immediate.nbytes ? ins.immediate.value : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -406,9 +406,7 @@ static int decode_instructions(struct objtool_file *file)
|
|||
|
||||
ret = arch_decode_instruction(file, sec, offset,
|
||||
sec->sh.sh_size - offset,
|
||||
&insn->len, &insn->type,
|
||||
&insn->immediate,
|
||||
&insn->stack_ops);
|
||||
insn);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -75,9 +75,7 @@ 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,
|
||||
unsigned int *len, enum insn_type *type,
|
||||
unsigned long *immediate,
|
||||
struct list_head *ops_list);
|
||||
struct instruction *insn);
|
||||
|
||||
bool arch_callee_saved_reg(unsigned char reg);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче