staticstruct orc_entry *__orc_find(int *ip_table, struct orc_entry *u_table, unsignedint num_entries, unsignedlong ip)
{ int *first = ip_table; int *last = ip_table + num_entries - 1; int *mid, *found = first;
if (!num_entries) return NULL;
/* * Do a binary range search to find the rightmost duplicate of a given * starting address. Some entries are section terminators which are * "weak" entries for ensuring there are no gaps. They should be * ignored when they conflict with a real entry.
*/ while (first <= last) {
mid = first + ((last - first) / 2);
if (orc_ip(mid) <= ip) {
found = mid;
first = mid + 1;
} else
last = mid - 1;
}
/* * Ftrace dynamic trampolines do not have orc entries of their own. * But they are copies of the ftrace entries that are static and * defined in ftrace_*.S, which do have orc entries. * * If the unwinder comes across a ftrace trampoline, then find the * ftrace function that was used to create it, and use that ftrace * function's orc entry, as the placement of the return code in * the stack will be identical.
*/ staticstruct orc_entry *orc_ftrace_find(unsignedlong ip)
{ struct ftrace_ops *ops; unsignedlong tramp_addr, offset;
ops = ftrace_ops_trampoline(ip); if (!ops) return NULL;
/* Set tramp_addr to the start of the code copied by the trampoline */ if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
tramp_addr = (unsignedlong)ftrace_regs_caller; else
tramp_addr = (unsignedlong)ftrace_caller;
/* Now place tramp_addr to the location within the trampoline ip is at */
offset = ip - ops->trampoline;
tramp_addr += offset;
/* * If we crash with IP==0, the last successfully executed instruction * was probably an indirect function call with a NULL function pointer, * and we don't have unwind information for NULL. * This hardcoded ORC entry for IP==0 allows us to unwind from a NULL function * pointer into its parent and then continue normally from there.
*/ staticstruct orc_entry null_orc_entry = {
.sp_offset = sizeof(long),
.sp_reg = ORC_REG_SP,
.bp_reg = ORC_REG_UNDEFINED,
.type = ORC_TYPE_CALL
};
/* Fake frame pointer entry -- used as a fallback for generated code */ staticstruct orc_entry orc_fp_entry = {
.type = ORC_TYPE_CALL,
.sp_reg = ORC_REG_BP,
.sp_offset = 16,
.bp_reg = ORC_REG_PREV_SP,
.bp_offset = -16,
};
if (a_val > b_val) return 1; if (a_val < b_val) return -1;
/* * The "weak" section terminator entries need to always be first * to ensure the lookup code skips them in favor of real entries. * These terminator entries exist to handle any gaps created by * whitelisted .o files which didn't get objtool generation.
*/
orc_a = cur_orc_table + (a - cur_orc_ip_table); return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
}
/* * The 'cur_orc_*' globals allow the orc_sort_swap() callback to * associate an .orc_unwind_ip table entry with its corresponding * .orc_unwind entry so they can both be swapped.
*/
mutex_lock(&sort_mutex);
cur_orc_ip_table = orc_ip;
cur_orc_table = orc;
sort(orc_ip, num_entries, sizeof(int), orc_sort_cmp, orc_sort_swap);
mutex_unlock(&sort_mutex);
/* * Note, the orc_unwind and orc_unwind_ip tables were already * sorted at build time via the 'sorttable' tool. * It's ready for binary search straight away, no need to sort it.
*/
/* Initialize the fast lookup table: */
lookup_num_blocks = orc_lookup_end - orc_lookup; for (i = 0; i < lookup_num_blocks-1; i++) {
orc = __orc_find(__start_orc_unwind_ip, __start_orc_unwind,
num_entries,
LOOKUP_START_IP + (LOOKUP_BLOCK_SIZE * i)); if (!orc) {
orc_warn("WARNING: Corrupt .orc_unwind table. Disabling unwinder.\n"); return;
}
/* * If state->regs is non-NULL, and points to a full pt_regs, just get the reg * value from state->regs. * * Otherwise, if state->regs just points to IRET regs, and the previous frame * had full regs, it's safe to get the value from the previous regs. This can * happen when early/late IRQ entry code gets interrupted by an NMI.
*/ staticbool get_reg(struct unwind_state *state, unsignedint reg_off, unsignedlong *val)
{ unsignedint reg = reg_off/8;
if (!state->regs) returnfalse;
if (state->full_regs) {
*val = READ_ONCE_NOCHECK(((unsignedlong *)state->regs)[reg]); returntrue;
}
if (state->prev_regs) {
*val = READ_ONCE_NOCHECK(((unsignedlong *)state->prev_regs)[reg]); returntrue;
}
/* Don't let modules unload while we're reading their ORC data. */
guard(rcu)();
/* End-of-stack check for user tasks: */ if (state->regs && user_mode(state->regs)) goto the_end;
/* * Find the orc_entry associated with the text address. * * For a call frame (as opposed to a signal frame), state->ip points to * the instruction after the call. That instruction's stack layout * could be different from the call instruction's layout, for example * if the call was to a noreturn function. So get the ORC data for the * call instruction itself.
*/
orc = orc_find(state->signal ? state->ip : state->ip - 1); if (!orc) { /* * As a fallback, try to assume this code uses a frame pointer. * This is useful for generated code, like BPF, which ORC * doesn't know about. This is just a guess, so the rest of * the unwind is no longer considered reliable.
*/
orc = &orc_fp_entry;
state->error = true;
} else { if (orc->type == ORC_TYPE_UNDEFINED) goto err;
if (orc->type == ORC_TYPE_END_OF_STACK) goto the_end;
}
state->signal = orc->signal;
/* Find the previous frame's stack: */ switch (orc->sp_reg) { case ORC_REG_SP:
sp = state->sp + orc->sp_offset; break;
case ORC_REG_BP:
sp = state->bp + orc->sp_offset; break;
case ORC_REG_SP_INDIRECT:
sp = state->sp;
indirect = true; break;
case ORC_REG_R10: if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) {
orc_warn_current("missing R10 value at %pB\n",
(void *)state->ip); goto err;
} break;
case ORC_REG_R13: if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) {
orc_warn_current("missing R13 value at %pB\n",
(void *)state->ip); goto err;
} break;
case ORC_REG_DI: if (!get_reg(state, offsetof(struct pt_regs, di), &sp)) {
orc_warn_current("missing RDI value at %pB\n",
(void *)state->ip); goto err;
} break;
case ORC_REG_DX: if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) {
orc_warn_current("missing DX value at %pB\n",
(void *)state->ip); goto err;
} break;
default:
orc_warn("unknown SP base reg %d at %pB\n",
orc->sp_reg, (void *)state->ip); goto err;
}
if (indirect) { if (!deref_stack_reg(state, sp, &sp)) goto err;
if (orc->sp_reg == ORC_REG_SP_INDIRECT)
sp += orc->sp_offset;
}
/* Find IP, SP and possibly regs: */ switch (orc->type) { case ORC_TYPE_CALL:
ip_p = sp - sizeof(long);
if (!deref_stack_reg(state, ip_p, &state->ip)) goto err;
case ORC_TYPE_REGS: if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) {
orc_warn_current("can't access registers at %pB\n",
(void *)orig_ip); goto err;
} /* * There is a small chance to interrupt at the entry of * arch_rethook_trampoline() where the ORC info doesn't exist. * That point is right after the RET to arch_rethook_trampoline() * which was modified return address. * At that point, the @addr_p of the unwind_recover_rethook() * (this has to point the address of the stack entry storing * the modified return address) must be "SP - (a stack entry)" * because SP is incremented by the RET.
*/
state->ip = unwind_recover_rethook(state, state->ip,
(unsignedlong *)(state->sp - sizeof(long)));
state->regs = (struct pt_regs *)sp;
state->prev_regs = NULL;
state->full_regs = true; break;
case ORC_TYPE_REGS_PARTIAL: if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) {
orc_warn_current("can't access iret registers at %pB\n",
(void *)orig_ip); goto err;
} /* See ORC_TYPE_REGS case comment. */
state->ip = unwind_recover_rethook(state, state->ip,
(unsignedlong *)(state->sp - sizeof(long)));
default:
orc_warn("unknown .orc_unwind entry type %d at %pB\n",
orc->type, (void *)orig_ip); goto err;
}
/* Find BP: */ switch (orc->bp_reg) { case ORC_REG_UNDEFINED: if (get_reg(state, offsetof(struct pt_regs, bp), &tmp))
state->bp = tmp; break;
case ORC_REG_PREV_SP: if (!deref_stack_reg(state, sp + orc->bp_offset, &state->bp)) goto err; break;
case ORC_REG_BP: if (!deref_stack_reg(state, state->bp + orc->bp_offset, &state->bp)) goto err; break;
default:
orc_warn("unknown BP base reg %d for ip %pB\n",
orc->bp_reg, (void *)orig_ip); goto err;
}
/* Prevent a recursive loop due to bad ORC data: */ if (state->stack_info.type == prev_type &&
on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) &&
state->sp <= prev_sp) {
orc_warn_current("stack going in the wrong direction? at %pB\n",
(void *)orig_ip); goto err;
}
/* * Refuse to unwind the stack of a task while it's executing on another * CPU. This check is racy, but that's ok: the unwinder has other * checks to prevent it from going off the rails.
*/ if (task_on_another_cpu(task)) goto err;
if (get_stack_info((unsignedlong *)state->sp, state->task,
&state->stack_info, &state->stack_mask)) { /* * We weren't on a valid stack. It's possible that * we overflowed a valid stack into a guard page. * See if the next page up is valid so that we can * generate some kind of backtrace if this happens.
*/ void *next_page = (void *)PAGE_ALIGN((unsignedlong)state->sp);
state->error = true; if (get_stack_info(next_page, state->task, &state->stack_info,
&state->stack_mask)) return;
}
/* * The caller can provide the address of the first frame directly * (first_frame) or indirectly (regs->sp) to indicate which stack frame * to start unwinding at. Skip ahead until we reach it.
*/
/* When starting from regs, skip the regs frame: */ if (regs) {
unwind_next_frame(state); return;
}
/* Otherwise, skip ahead to the user-specified starting frame: */ while (!unwind_done(state) &&
(!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
state->sp <= (unsignedlong)first_frame))
unwind_next_frame(state);