.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
| 2 | +#include <linux/objtool.h> |
---|
1 | 3 | #include <linux/module.h> |
---|
2 | 4 | #include <linux/sort.h> |
---|
3 | 5 | #include <asm/ptrace.h> |
---|
.. | .. |
---|
7 | 9 | #include <asm/orc_lookup.h> |
---|
8 | 10 | |
---|
9 | 11 | #define orc_warn(fmt, ...) \ |
---|
10 | | - printk_deferred_once(KERN_WARNING pr_fmt("WARNING: " fmt), ##__VA_ARGS__) |
---|
| 12 | + printk_deferred_once(KERN_WARNING "WARNING: " fmt, ##__VA_ARGS__) |
---|
| 13 | + |
---|
| 14 | +#define orc_warn_current(args...) \ |
---|
| 15 | +({ \ |
---|
| 16 | + if (state->task == current) \ |
---|
| 17 | + orc_warn(args); \ |
---|
| 18 | +}) |
---|
11 | 19 | |
---|
12 | 20 | extern int __start_orc_unwind_ip[]; |
---|
13 | 21 | extern int __stop_orc_unwind_ip[]; |
---|
14 | 22 | extern struct orc_entry __start_orc_unwind[]; |
---|
15 | 23 | extern struct orc_entry __stop_orc_unwind[]; |
---|
16 | 24 | |
---|
17 | | -static DEFINE_MUTEX(sort_mutex); |
---|
18 | | -int *cur_orc_ip_table = __start_orc_unwind_ip; |
---|
19 | | -struct orc_entry *cur_orc_table = __start_orc_unwind; |
---|
20 | | - |
---|
21 | | -unsigned int lookup_num_blocks; |
---|
22 | | -bool orc_init; |
---|
| 25 | +static bool orc_init __ro_after_init; |
---|
| 26 | +static unsigned int lookup_num_blocks __ro_after_init; |
---|
23 | 27 | |
---|
24 | 28 | static inline unsigned long orc_ip(const int *ip) |
---|
25 | 29 | { |
---|
.. | .. |
---|
81 | 85 | * But they are copies of the ftrace entries that are static and |
---|
82 | 86 | * defined in ftrace_*.S, which do have orc entries. |
---|
83 | 87 | * |
---|
84 | | - * If the undwinder comes across a ftrace trampoline, then find the |
---|
| 88 | + * If the unwinder comes across a ftrace trampoline, then find the |
---|
85 | 89 | * ftrace function that was used to create it, and use that ftrace |
---|
86 | | - * function's orc entrie, as the placement of the return code in |
---|
| 90 | + * function's orc entry, as the placement of the return code in |
---|
87 | 91 | * the stack will be identical. |
---|
88 | 92 | */ |
---|
89 | 93 | static struct orc_entry *orc_ftrace_find(unsigned long ip) |
---|
90 | 94 | { |
---|
91 | 95 | struct ftrace_ops *ops; |
---|
92 | | - unsigned long caller; |
---|
| 96 | + unsigned long tramp_addr, offset; |
---|
93 | 97 | |
---|
94 | 98 | ops = ftrace_ops_trampoline(ip); |
---|
95 | 99 | if (!ops) |
---|
96 | 100 | return NULL; |
---|
97 | 101 | |
---|
| 102 | + /* Set tramp_addr to the start of the code copied by the trampoline */ |
---|
98 | 103 | if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) |
---|
99 | | - caller = (unsigned long)ftrace_regs_call; |
---|
| 104 | + tramp_addr = (unsigned long)ftrace_regs_caller; |
---|
100 | 105 | else |
---|
101 | | - caller = (unsigned long)ftrace_call; |
---|
| 106 | + tramp_addr = (unsigned long)ftrace_caller; |
---|
| 107 | + |
---|
| 108 | + /* Now place tramp_addr to the location within the trampoline ip is at */ |
---|
| 109 | + offset = ip - ops->trampoline; |
---|
| 110 | + tramp_addr += offset; |
---|
102 | 111 | |
---|
103 | 112 | /* Prevent unlikely recursion */ |
---|
104 | | - if (ip == caller) |
---|
| 113 | + if (ip == tramp_addr) |
---|
105 | 114 | return NULL; |
---|
106 | 115 | |
---|
107 | | - return orc_find(caller); |
---|
| 116 | + return orc_find(tramp_addr); |
---|
108 | 117 | } |
---|
109 | 118 | #else |
---|
110 | 119 | static struct orc_entry *orc_ftrace_find(unsigned long ip) |
---|
.. | .. |
---|
124 | 133 | .sp_offset = sizeof(long), |
---|
125 | 134 | .sp_reg = ORC_REG_SP, |
---|
126 | 135 | .bp_reg = ORC_REG_UNDEFINED, |
---|
127 | | - .type = ORC_TYPE_CALL |
---|
| 136 | + .type = UNWIND_HINT_TYPE_CALL |
---|
| 137 | +}; |
---|
| 138 | + |
---|
| 139 | +/* Fake frame pointer entry -- used as a fallback for generated code */ |
---|
| 140 | +static struct orc_entry orc_fp_entry = { |
---|
| 141 | + .type = UNWIND_HINT_TYPE_CALL, |
---|
| 142 | + .sp_reg = ORC_REG_BP, |
---|
| 143 | + .sp_offset = 16, |
---|
| 144 | + .bp_reg = ORC_REG_PREV_SP, |
---|
| 145 | + .bp_offset = -16, |
---|
| 146 | + .end = 0, |
---|
128 | 147 | }; |
---|
129 | 148 | |
---|
130 | 149 | static struct orc_entry *orc_find(unsigned long ip) |
---|
.. | .. |
---|
173 | 192 | return orc_ftrace_find(ip); |
---|
174 | 193 | } |
---|
175 | 194 | |
---|
| 195 | +#ifdef CONFIG_MODULES |
---|
| 196 | + |
---|
| 197 | +static DEFINE_MUTEX(sort_mutex); |
---|
| 198 | +static int *cur_orc_ip_table = __start_orc_unwind_ip; |
---|
| 199 | +static struct orc_entry *cur_orc_table = __start_orc_unwind; |
---|
| 200 | + |
---|
176 | 201 | static void orc_sort_swap(void *_a, void *_b, int size) |
---|
177 | 202 | { |
---|
178 | 203 | struct orc_entry *orc_a, *orc_b; |
---|
.. | .. |
---|
215 | 240 | return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; |
---|
216 | 241 | } |
---|
217 | 242 | |
---|
218 | | -#ifdef CONFIG_MODULES |
---|
219 | 243 | void unwind_module_init(struct module *mod, void *_orc_ip, size_t orc_ip_size, |
---|
220 | 244 | void *_orc, size_t orc_size) |
---|
221 | 245 | { |
---|
.. | .. |
---|
259 | 283 | return; |
---|
260 | 284 | } |
---|
261 | 285 | |
---|
262 | | - /* Sort the .orc_unwind and .orc_unwind_ip tables: */ |
---|
263 | | - sort(__start_orc_unwind_ip, num_entries, sizeof(int), orc_sort_cmp, |
---|
264 | | - orc_sort_swap); |
---|
| 286 | + /* |
---|
| 287 | + * Note, the orc_unwind and orc_unwind_ip tables were already |
---|
| 288 | + * sorted at build time via the 'sorttable' tool. |
---|
| 289 | + * It's ready for binary search straight away, no need to sort it. |
---|
| 290 | + */ |
---|
265 | 291 | |
---|
266 | 292 | /* Initialize the fast lookup table: */ |
---|
267 | 293 | lookup_num_blocks = orc_lookup_end - orc_lookup; |
---|
.. | .. |
---|
420 | 446 | * call instruction itself. |
---|
421 | 447 | */ |
---|
422 | 448 | orc = orc_find(state->signal ? state->ip : state->ip - 1); |
---|
423 | | - if (!orc) |
---|
424 | | - goto err; |
---|
| 449 | + if (!orc) { |
---|
| 450 | + /* |
---|
| 451 | + * As a fallback, try to assume this code uses a frame pointer. |
---|
| 452 | + * This is useful for generated code, like BPF, which ORC |
---|
| 453 | + * doesn't know about. This is just a guess, so the rest of |
---|
| 454 | + * the unwind is no longer considered reliable. |
---|
| 455 | + */ |
---|
| 456 | + orc = &orc_fp_entry; |
---|
| 457 | + state->error = true; |
---|
| 458 | + } |
---|
425 | 459 | |
---|
426 | 460 | /* End-of-stack check for kernel threads: */ |
---|
427 | 461 | if (orc->sp_reg == ORC_REG_UNDEFINED) { |
---|
.. | .. |
---|
453 | 487 | |
---|
454 | 488 | case ORC_REG_R10: |
---|
455 | 489 | if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) { |
---|
456 | | - orc_warn("missing regs for base reg R10 at ip %pB\n", |
---|
457 | | - (void *)state->ip); |
---|
| 490 | + orc_warn_current("missing R10 value at %pB\n", |
---|
| 491 | + (void *)state->ip); |
---|
458 | 492 | goto err; |
---|
459 | 493 | } |
---|
460 | 494 | break; |
---|
461 | 495 | |
---|
462 | 496 | case ORC_REG_R13: |
---|
463 | 497 | if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) { |
---|
464 | | - orc_warn("missing regs for base reg R13 at ip %pB\n", |
---|
465 | | - (void *)state->ip); |
---|
| 498 | + orc_warn_current("missing R13 value at %pB\n", |
---|
| 499 | + (void *)state->ip); |
---|
466 | 500 | goto err; |
---|
467 | 501 | } |
---|
468 | 502 | break; |
---|
469 | 503 | |
---|
470 | 504 | case ORC_REG_DI: |
---|
471 | 505 | if (!get_reg(state, offsetof(struct pt_regs, di), &sp)) { |
---|
472 | | - orc_warn("missing regs for base reg DI at ip %pB\n", |
---|
473 | | - (void *)state->ip); |
---|
| 506 | + orc_warn_current("missing RDI value at %pB\n", |
---|
| 507 | + (void *)state->ip); |
---|
474 | 508 | goto err; |
---|
475 | 509 | } |
---|
476 | 510 | break; |
---|
477 | 511 | |
---|
478 | 512 | case ORC_REG_DX: |
---|
479 | 513 | if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) { |
---|
480 | | - orc_warn("missing regs for base reg DX at ip %pB\n", |
---|
481 | | - (void *)state->ip); |
---|
| 514 | + orc_warn_current("missing DX value at %pB\n", |
---|
| 515 | + (void *)state->ip); |
---|
482 | 516 | goto err; |
---|
483 | 517 | } |
---|
484 | 518 | break; |
---|
485 | 519 | |
---|
486 | 520 | default: |
---|
487 | | - orc_warn("unknown SP base reg %d for ip %pB\n", |
---|
| 521 | + orc_warn("unknown SP base reg %d at %pB\n", |
---|
488 | 522 | orc->sp_reg, (void *)state->ip); |
---|
489 | 523 | goto err; |
---|
490 | 524 | } |
---|
.. | .. |
---|
496 | 530 | |
---|
497 | 531 | /* Find IP, SP and possibly regs: */ |
---|
498 | 532 | switch (orc->type) { |
---|
499 | | - case ORC_TYPE_CALL: |
---|
| 533 | + case UNWIND_HINT_TYPE_CALL: |
---|
500 | 534 | ip_p = sp - sizeof(long); |
---|
501 | 535 | |
---|
502 | 536 | if (!deref_stack_reg(state, ip_p, &state->ip)) |
---|
.. | .. |
---|
511 | 545 | state->signal = false; |
---|
512 | 546 | break; |
---|
513 | 547 | |
---|
514 | | - case ORC_TYPE_REGS: |
---|
| 548 | + case UNWIND_HINT_TYPE_REGS: |
---|
515 | 549 | if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) { |
---|
516 | | - orc_warn("can't dereference registers at %p for ip %pB\n", |
---|
517 | | - (void *)sp, (void *)orig_ip); |
---|
| 550 | + orc_warn_current("can't access registers at %pB\n", |
---|
| 551 | + (void *)orig_ip); |
---|
518 | 552 | goto err; |
---|
519 | 553 | } |
---|
520 | 554 | |
---|
.. | .. |
---|
524 | 558 | state->signal = true; |
---|
525 | 559 | break; |
---|
526 | 560 | |
---|
527 | | - case ORC_TYPE_REGS_IRET: |
---|
| 561 | + case UNWIND_HINT_TYPE_REGS_PARTIAL: |
---|
528 | 562 | if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) { |
---|
529 | | - orc_warn("can't dereference iret registers at %p for ip %pB\n", |
---|
530 | | - (void *)sp, (void *)orig_ip); |
---|
| 563 | + orc_warn_current("can't access iret registers at %pB\n", |
---|
| 564 | + (void *)orig_ip); |
---|
531 | 565 | goto err; |
---|
532 | 566 | } |
---|
533 | 567 | |
---|
.. | .. |
---|
539 | 573 | break; |
---|
540 | 574 | |
---|
541 | 575 | default: |
---|
542 | | - orc_warn("unknown .orc_unwind entry type %d for ip %pB\n", |
---|
| 576 | + orc_warn("unknown .orc_unwind entry type %d at %pB\n", |
---|
543 | 577 | orc->type, (void *)orig_ip); |
---|
544 | 578 | goto err; |
---|
545 | 579 | } |
---|
.. | .. |
---|
571 | 605 | if (state->stack_info.type == prev_type && |
---|
572 | 606 | on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) && |
---|
573 | 607 | state->sp <= prev_sp) { |
---|
574 | | - orc_warn("stack going in the wrong direction? ip=%pB\n", |
---|
575 | | - (void *)orig_ip); |
---|
| 608 | + orc_warn_current("stack going in the wrong direction? at %pB\n", |
---|
| 609 | + (void *)orig_ip); |
---|
576 | 610 | goto err; |
---|
577 | 611 | } |
---|
578 | 612 | |
---|
.. | .. |
---|
611 | 645 | goto the_end; |
---|
612 | 646 | |
---|
613 | 647 | state->ip = regs->ip; |
---|
614 | | - state->sp = kernel_stack_pointer(regs); |
---|
| 648 | + state->sp = regs->sp; |
---|
615 | 649 | state->bp = regs->bp; |
---|
616 | 650 | state->regs = regs; |
---|
617 | 651 | state->full_regs = true; |
---|
.. | .. |
---|
663 | 697 | /* Otherwise, skip ahead to the user-specified starting frame: */ |
---|
664 | 698 | while (!unwind_done(state) && |
---|
665 | 699 | (!on_stack(&state->stack_info, first_frame, sizeof(long)) || |
---|
666 | | - state->sp < (unsigned long)first_frame)) |
---|
| 700 | + state->sp <= (unsigned long)first_frame)) |
---|
667 | 701 | unwind_next_frame(state); |
---|
668 | 702 | |
---|
669 | 703 | return; |
---|