objtool: Support stack-swizzle
Natively support the stack swizzle pattern: mov %rsp, (%[tos]) mov %[tos], %rsp ... pop %rsp It uses the vals[] array to link the first two stack-ops, and detect the SP to SP_INDIRECT swizzle. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Miroslav Benes <mbenes@suse.cz> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
This commit is contained in:
Родитель
2a51282984
Коммит
aafeb14e9d
|
@ -1945,6 +1945,38 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
|
|||
cfa->offset = -cfi->vals[op->src.reg].offset;
|
||||
cfi->stack_size = cfa->offset;
|
||||
|
||||
} else if (cfa->base == CFI_SP &&
|
||||
cfi->vals[op->src.reg].base == CFI_SP_INDIRECT &&
|
||||
cfi->vals[op->src.reg].offset == cfa->offset) {
|
||||
|
||||
/*
|
||||
* Stack swizzle:
|
||||
*
|
||||
* 1: mov %rsp, (%[tos])
|
||||
* 2: mov %[tos], %rsp
|
||||
* ...
|
||||
* 3: pop %rsp
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* 1 - places a pointer to the previous
|
||||
* stack at the Top-of-Stack of the
|
||||
* new stack.
|
||||
*
|
||||
* 2 - switches to the new stack.
|
||||
*
|
||||
* 3 - pops the Top-of-Stack to restore
|
||||
* the original stack.
|
||||
*
|
||||
* Note: we set base to SP_INDIRECT
|
||||
* here and preserve offset. Therefore
|
||||
* when the unwinder reaches ToS it
|
||||
* will dereference SP and then add the
|
||||
* offset to find the next frame, IOW:
|
||||
* (%rsp) + offset.
|
||||
*/
|
||||
cfa->base = CFI_SP_INDIRECT;
|
||||
|
||||
} else {
|
||||
cfa->base = CFI_UNDEFINED;
|
||||
cfa->offset = 0;
|
||||
|
@ -2047,6 +2079,13 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
|
|||
|
||||
case OP_SRC_POP:
|
||||
case OP_SRC_POPF:
|
||||
if (op->dest.reg == CFI_SP && cfa->base == CFI_SP_INDIRECT) {
|
||||
|
||||
/* pop %rsp; # restore from a stack swizzle */
|
||||
cfa->base = CFI_SP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cfi->drap && op->dest.reg == cfa->base) {
|
||||
|
||||
/* pop %rbp */
|
||||
|
@ -2193,6 +2232,12 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
|
|||
/* mov reg, disp(%rsp) */
|
||||
save_reg(cfi, op->src.reg, CFI_CFA,
|
||||
op->dest.offset - cfi->stack_size);
|
||||
|
||||
} else if (op->src.reg == CFI_SP && op->dest.offset == 0) {
|
||||
|
||||
/* mov %rsp, (%reg); # setup a stack swizzle. */
|
||||
cfi->vals[op->dest.reg].base = CFI_SP_INDIRECT;
|
||||
cfi->vals[op->dest.reg].offset = cfa->offset;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче