Hi Kazu,
On Tue, May 26, 2026 at 7:33 PM HAGIO KAZUHITO(萩尾 一仁)
<k-hagio-ab(a)nec.com> wrote:
On 2026/05/25 10:23, Tao Liu wrote:
> Hi Kazu,
>
> Thanks for your insight on this.
>
> On Thu, May 21, 2026 at 8:18 PM HAGIO KAZUHITO(萩尾 一仁)
> <k-hagio-ab(a)nec.com> wrote:
>>
>> On 2026/05/20 13:31, Tao Liu wrote:
>>> We have enountered the following edge case for orc unwinder which results
an
>>> incorrect stack unwinding:
>>>
>>> $ objdump -d vmlinux
>>> ffffffff8100be70 <panic>:
>>> ffffffff8100be70: f3 0f 1e fa endbr64
>>> ffffffff8100be74: e8 c7 b9 0d 00 call ffffffff810e7840
<__fentry__>
>>> ffffffff8100be79: 55 push %rbp
>>> ffffffff8100be7a: 49 89 fa mov %rdi,%r10
>>> ffffffff8100be7d: 48 89 e5 mov %rsp,%rbp
>>> ffffffff8100be80: 48 83 ec 50 sub $0x50,%rsp
>>> ...
>>> ffffffff8100bed2: 48 89 44 24 10 mov %rax,0x10(%rsp)
>>> ffffffff8100bed7: e8 f4 fc ff ff call ffffffff8100bbd0
<vpanic>
>>>
>>> ffffffff8100bedc <nmi_panic.cold>:
>>> ffffffff8100bedc: 48 c7 c7 6e c2 8b 82 mov
$0xffffffff828bc26e,%rdi
>>> ffffffff8100bee3: e8 88 ff ff ff call ffffffff8100be70
<panic>
>>>
>>> $ objtool --dump=orc vmlinux
>>> ...
>>> ffffffff8100be7a:type:call sp:sp+16 bp:prevsp-16 signal:0
>>> ffffffff8100be80:type:call sp:bp+16 bp:prevsp-16 signal:0
>>> ffffffff8100bedc:type:call sp:sp+8 bp:(und) signal:0
>>> ffffffff8100bee8:type:call sp:sp+16 bp:(und) signal:0
>>>
>>> crash> gdb bt
>>> #0 0xffffffff8126b3e4 in crash_setup_regs
>>> #1 0xffffffff8126b7a2 in __crash_kexec
>>> #2 0xffffffff8100bca9 in vpanic
>>> #3 0xffffffff8100bedc in panic
>>> #4 0xffffffff81903a9a in sysrq_handle_crash
>>> ...
>>>
>>> crash> bt -r
>>> ...
>>> ffffc9000126fc40: machine_kexec+184 sysrq_showstate_op
>>> ffffc9000126fc50: .LC4+109 __crash_kexec+114
>>> ffffc9000126fc60: 0000000000000000 0000000000000007
>>> ffffc9000126fc70: 0000000000000063 ffffc9000126fd48
>>> ffffc9000126fc80: .LC4+109 sysrq_showstate_op
>>> ffffc9000126fc90: 0000000000000002 _printk_rb_static_infos+64944
>>> ffffc9000126fca0: _printk_rb_static_descs+17712 0000000000000000
>>> ffffc9000126fcb0: 0000000000000000 0000000000000000
>>> ffffc9000126fcc0: 0000000000000001 0000000000000000
>>> ffffc9000126fcd0: ffffc9000126fc60 0000000000000000
>>> ffffc9000126fce0: crash_setup_regs+116 0000000000000010
>>> ffffc9000126fcf0: 0000000000000046 ffffc9000126fc58
>>> ffffc9000126fd00: 0000000000000018 a9e74447ad8b9200
>>> ffffc9000126fd10: sysrq_showstate_op vpanic+217
>>> ffffc9000126fd20: sysrq_crash_op ffffc9000126fd98
>>> ffffc9000126fd30: 0000000000000000 0000000000000063
>>> ffffc9000126fd40: panic+108 0000000000000008
>>> ffffc9000126fd50: ffffc9000126fda8 ffffc9000126fd68
>>> ffffc9000126fd60: a9e74447ad8b9200 a9e74447ad8b9200
>>> ffffc9000126fd70: ffff88813bc1d1c0 0000000000000000
>>> ffffc9000126fd80: 0000000000000000 0000000000000000
>>> ffffc9000126fd90: _printk_rb_static_descs+786408 0000000000000000
>>> ffffc9000126fda0: sysrq_handle_crash+26 __handle_sysrq.cold+159
>>>
>>> Within the stack, we can identify the following stackframes:
>>>
>>> 1. rsp ffffc9000126fc40, rip (machine_kexec+184)
>>> 2. rsp ffffc9000126fc58, rip (__crash_kexec+114)
>>> 3. rsp ffffc9000126fd10, rip (vpanic+217)
>>> 4. rsp ffffc9000126fd40, rip (panic+108)
>>>
>>> Before the fix, crash will directly pass rip to orc_find() to calculate
>>> each framesize, actually this is incorrect, because the rip is what
>>> we found in stack, as we all know the "call" instruction will
push
>>> the address of the next instruction into stack, rather than the address
>>> of the "call" instruction itself. So for the (panic+108, or
ffffffff8100bedc)
>>> case, orc winder finds the frame of 0xffffffff8100bedc is sp:sp+8.
>>> This is incorrect, because 0xffffffff8100bedc belongs to a different
>>> function, aka nmi_panic(), rather than panic(). So we should use (rip -
>>> 5, or ffffffff8100bed7) for orc_find(), which gives sp:bp+16 for unwind
>>> stack frame. We can confirm this by reading the disassembly at
>>> ffffffff8100be70 ~ ffffffff8100be80.
>>>
>>> This is an edge case because the address after the "call"
instruction
>>> located to a different function, which lead to orc_find() got a wrong
>>> framesize.
>>>
>>> This patch fix this by check the 1st previous instruction of rip we read
>>> from stack. If the instruction is "call", then we pass the address
of
>>> the "call" to orc_find(), to ensure we orc unwinding the correct
function.
>>
>> Hi Tao, thank you for the work!
>>
>> I tried the patchset, unfortunately it prints a bit wrong trace,
>> because the correct .cold symbols are removed, I think.
>>
>> * SysRq case
>>
>> crash> bt
>> PID: 6598 TASK: ffff8c0902d2b680 CPU: 2 COMMAND: "bash"
>> #0 [ffffcda8c346b970] machine_kexec at ffffffff908e91e8
>> #1 [ffffcda8c346b988] __crash_kexec at ffffffff90a6b7a2
>> #2 [ffffcda8c346ba48] vpanic at ffffffff9080bca9
>> #3 [ffffcda8c346ba70] panic at ffffffff9080bedc
>> #4 [ffffcda8c346bad0] sysrq_handle_crash at ffffffff91103a9a
>> #5 [ffffcda8c346bad8] sysrq_handle_loglevel at ffffffff90841048 <<--
>> #6 [ffffcda8c346bb08] write_sysrq_trigger at ffffffff91104679
>> #7 [ffffcda8c346bb30] proc_reg_write at ffffffff90dd3137
>> #8 [ffffcda8c346bb48] vfs_write at ffffffff90d17308
>> #9 [ffffcda8c346bbd8] ksys_write at ffffffff90d1783d
>> #10 [ffffcda8c346bc10] do_syscall_64 at ffffffff9168e96d
>> #11 [ffffcda8c346bf40] entry_SYSCALL_64_after_hwframe at ffffffff9180012f
>>
>> * NMI case
>>
>> crash> bt
>> PID: 0 TASK: ffffffffa3c12940 CPU: 0 COMMAND: "swapper/0"
>> #0 [fffffe7e99f94d50] machine_kexec at ffffffffa1ae91e8
>> #1 [fffffe7e99f94d68] __crash_kexec at ffffffffa1c6b7a2
>> #2 [fffffe7e99f94e28] vpanic at ffffffffa1a0bca9
>> #3 [fffffe7e99f94e50] panic at ffffffffa1a0bedc
>> #4 [fffffe7e99f94eb0] panic at ffffffffa1a0bee8 <<--
>> #5 [fffffe7e99f94eb8] unknown_nmi_error at ffffffffa1aa39a7
>> #6 [fffffe7e99f94ed0] exc_nmi at ffffffffa2891576
>> #7 [fffffe7e99f94ef0] end_repeat_nmi at ffffffffa2a01d9d
>> [exception RIP: default_idle+15]
>>
>>
>> On the other hand, kernel's call trace looks correct, so I looked into
>> how the kernel prints this.
>>
>> [ 133.526125] Call Trace:
>> [ 133.526126] <NMI>
>> [ 133.526128] dump_stack_lvl+0x4e/0x70
>> [ 133.526131] vpanic+0xc2/0x290
>> [ 133.526133] panic+0x6c/0x6c
>> [ 133.526134] nmi_panic.cold+0xc/0xc
>> [ 133.526135] unknown_nmi_error+0x77/0xa0
>> [ 133.526137] exc_nmi+0x106/0x180
>> [ 133.526140] end_repeat_nmi+0xf/0x53
>>
>>
>> * When printing a symbol for call trace, it searches for "address -
1".
>>
>> static void printk_stack_address(unsigned long address, int reliable,
>> const char *log_lvl)
>> {
>> touch_nmi_watchdog();
>> printk("%s %s%pBb\n", log_lvl, reliable ? "" :
"? ", (void *)address);
>> } ^^^^
>>
>> This "%pBb" gets to the following function.
>>
>> /**
>> * sprint_backtrace_build_id - Look up a backtrace symbol and return it in a
text buffer
>> * @buffer: buffer to be stored
>> * @address: address to lookup
>> *
>> * This function is for stack backtrace and does the same thing as
>> * sprint_symbol() but with modified/decreased @address. If there is a
>> * tail-call to the function marked "noreturn", gcc optimized out
code after
>> * the call so that the stack-saved return address could point outside of the
<<--
>> * caller. This function ensures that kallsyms will find the original caller
>> * by decreasing @address. This function also appends the module build ID to
>> * the @buffer if @address is within a kernel module.
>> *
>> * This function returns the number of bytes stored in @buffer.
>> */
>> int sprint_backtrace_build_id(char *buffer, unsigned long address)
>> {
>> return __sprint_symbol(buffer, address, -1, 1, 1);
>> } ^^^
>>
>> /* Look up a kernel symbol and return it in a text buffer. */
>> static int __sprint_symbol(char *buffer, unsigned long address,
>> int symbol_offset, int add_offset, int
add_buildid)
>> {
>> ...
>> address += symbol_offset; // search for the symbol with
symbol_offset(-1)
>> len = kallsyms_lookup_buildid(address, &size, &offset,
&modname, &buildid,
>> buffer);
>> if (!len)
>> return sprintf(buffer, "0x%lx", address -
symbol_offset);
>>
>> offset -= symbol_offset; // adjust offset (+1)
>>
>> if (add_offset) // print offset
>> len += sprintf(buffer + len, "+%#lx/%#lx", offset,
size);
>>
>>
>> * When searching for ORC data, usually "ip - 1" is used.
>>
>> bool unwind_next_frame(struct unwind_state *state)
>> {
>> ...
>> /*
>> * 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);
>> ^^^^^^^^^^^^^
>>
>> So I tried a simple patch like this at first:
>>
>> --- a/x86_64.c
>> +++ b/x86_64.c
>> @@ -3229,7 +3229,8 @@ x86_64_print_stack_entry(struct bt_info *bt, FILE *ofp,
int level,
>> if (!(bt->flags & BT_SAVE_EFRAME_IP))
>> bt->eframe_ip = 0;
>> offset = 0;
>> - sp = value_search(text, &offset);
>> + sp = value_search(text-1, &offset);
>> + offset++;
>> if (!sp)
>> return BACKTRACE_ENTRY_IGNORED;
>>
>> @@ -8811,7 +8812,9 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr,
ulong rsp, char *stack_
>> return 0;
>> }
>>
>> - if (!(sp = value_search(textaddr, &offset))) {
>> + sp = value_search(textaddr-1, &offset);
>> + offset++;
>> + if (!sp) {
>> if (!(bt->flags & BT_FRAMESIZE_DEBUG))
>> bt->flags |= BT_FRAMESIZE_DISABLE;
>> return 0;
>> @@ -8887,7 +8890,7 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr,
ulong rsp, char *stack_
>> if ((sp->value >= kt->init_begin) && (sp->value
< kt->init_end))
>> return 0;
>>
>> - if ((machdep->flags & ORC) && (korc =
orc_find(textaddr))) {
>> + if ((machdep->flags & ORC) && (korc =
orc_find(textaddr-1))) {
>> if (CRASHDEBUG(1)) {
>> struct ORC_data *orc =
&machdep->machspec->orc;
>> fprintf(fp,
>>
>>
>> This looks good at first glance.
>>
>> crash> bt
>> PID: 0 TASK: ffffffffa3c12940 CPU: 0 COMMAND: "swapper/0"
>> #0 [fffffe7e99f94d50] machine_kexec at ffffffffa1ae91e8
>> #1 [fffffe7e99f94d68] __crash_kexec at ffffffffa1c6b7a2
>> #2 [fffffe7e99f94e28] vpanic at ffffffffa1a0bca9
>> #3 [fffffe7e99f94e50] panic at ffffffffa1a0bedc
>> #4 [fffffe7e99f94eb0] nmi_panic.cold at ffffffffa1a0bee8
>> #5 [fffffe7e99f94eb8] unknown_nmi_error at ffffffffa1aa39a7
>> #6 [fffffe7e99f94ed0] exc_nmi at ffffffffa2891576
>> #7 [fffffe7e99f94ef0] end_repeat_nmi at ffffffffa2a01d9d
>> [exception RIP: default_idle+15]
>> RIP: ffffffffa2895c6f RSP: ffffffffa3c03e88 RFLAGS: 00000256
>> RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff8cb88b0ecf08
>> RDX: ffffd2b200dc74a1 RSI: 0000000000000087 RDI: 000000000008086c
>> RBP: ffffffffa3c12940 R8: 000000000008086c R9: 0000000000000000
>> R10: 0000000000000001 R11: fefefefefefefeff R12: 0000000000000000
>> R13: 000000007d41f000 R14: 000000000000000c R15: 000000007d41f000
>> ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
>> --- <NMI exception stack> ---
>> #8 [ffffffffa3c03e88] default_idle at ffffffffa2895c6f
>> #9 [ffffffffa3c03e88] default_idle_call at ffffffffa2895ef9
>> #10 [ffffffffa3c03e90] cpuidle_idle_call at ffffffffa1bbf4ba
>> #11 [ffffffffa3c03ec8] do_idle at ffffffffa1bbf573
>> ...
>>
>>
>> But there are some issues, which I've found so far:
>>
>> * How we can emulate state->signal=1 case in crash.
>> Your method (check if the prev is "call") may be good, is there any
>> more orc-based or robust way?
>
> Sorry I cannot think of a better way to emulate the state->signal=1
> case. To me, tracking the previous "call" instruction is the simple
> way to determine if we are in a normal function call chain(previous
> "call" exists) or in interruption/exception handler (previous
"call"
> not exists).
If a panic occurred at the next to a "call" instruction, it's changed
to the "call" address wrongly. I think this is an issue of this way.
in theory, if ip value is from a register or an exception frame, we
don't need -1. I'm still searching for that way..
>>
>> * "bt -s" option still prints wrong symbols.
>
> Hmm, I see...
>
> How about we keep the "x86_64: Correct the unwind address for orc when
> "call" instruction encountered" patch, and ignore "x86_64:
ignore the
> compiler generated xx.cold symbols" patch, with the following change
> applied:
>
> diff --git a/x86_64.c b/x86_64.c
> index 70bc1da..1a8d90b 100644
> --- a/x86_64.c
> +++ b/x86_64.c
> @@ -3267,7 +3267,7 @@ x86_64_print_stack_entry(struct bt_info *bt,
> FILE *ofp, int level,
> else if (!(bt->flags & BT_SCHEDULE)) {
> if (STREQ(name, "error_exit"))
> eframe_check = 8;
> - else {
> + else if (!(machdep->flags & ORC)) {
> if (CRASHDEBUG(2))
> fprintf(ofp,
> "< ignoring text symbol with no offset: %s()
>\n",
>
> This will give us the following output:
>
> crash> bt
> PID: 2074 TASK: ffff888103ea8000 CPU: 0 COMMAND: "bash"
> #0 [ffffc9000126fc40] machine_kexec at ffffffff810e91e8
> #1 [ffffc9000126fc58] __crash_kexec at ffffffff8126b7a2
> #2 [ffffc9000126fd18] vpanic at ffffffff8100bca9
> #3 [ffffc9000126fd40] nmi_panic.cold at ffffffff8100bedc
> #4 [ffffc9000126fda0] sysrq_handle_crash at ffffffff81903a9a
> #5 [ffffc9000126fda8] __handle_sysrq.cold at ffffffff81041048
> #6 [ffffc9000126fdd8] write_sysrq_trigger at ffffffff81904679
> #7 [ffffc9000126fe00] proc_reg_write at ffffffff815d3137
> #8 [ffffc9000126fe18] vfs_write at ffffffff81517308
> #9 [ffffc9000126fea8] ksys_write at ffffffff8151783d
> #10 [ffffc9000126fee0] do_syscall_64 at ffffffff81e8e96d
> #11 [ffffc9000126ff40] entry_SYSCALL_64_after_hwframe at ffffffff8200012f
> RIP: 00007faf8722f544 RSP: 00007ffe9ba94868 RFLAGS: 00000202
> RAX: ffffffffffffffda RBX: 00007faf873055c0 RCX: 00007faf8722f544
> RDX: 0000000000000002 RSI: 000055d80bde45d0 RDI: 0000000000000001
> RBP: 0000000000000002 R8: 0000000000000073 R9: 00000000ffffffff
> R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
> R13: 000055d80bde45d0 R14: 0000000000000002 R15: 00007faf87302f00
> ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
> crash> bt -s
> PID: 2074 TASK: ffff888103ea8000 CPU: 0 COMMAND: "bash"
> #0 [ffffc9000126fc40] machine_kexec+184 at ffffffff810e91e8
> #1 [ffffc9000126fc58] __crash_kexec+114 at ffffffff8126b7a2
> #2 [ffffc9000126fd18] vpanic+217 at ffffffff8100bca9
> #3 [ffffc9000126fd40] nmi_panic.cold at ffffffff8100bedc
> #4 [ffffc9000126fda0] sysrq_handle_crash+26 at ffffffff81903a9a
> #5 [ffffc9000126fda8] __handle_sysrq.cold+159 at ffffffff81041048
> #6 [ffffc9000126fdd8] write_sysrq_trigger+89 at ffffffff81904679
> #7 [ffffc9000126fe00] proc_reg_write+87 at ffffffff815d3137
> #8 [ffffc9000126fe18] vfs_write+248 at ffffffff81517308
> #9 [ffffc9000126fea8] ksys_write+109 at ffffffff8151783d
> #10 [ffffc9000126fee0] do_syscall_64+125 at ffffffff81e8e96d
> #11 [ffffc9000126ff40] entry_SYSCALL_64_after_hwframe+118 at ffffffff8200012f
> RIP: 00007faf8722f544 RSP: 00007ffe9ba94868 RFLAGS: 00000202
> RAX: ffffffffffffffda RBX: 00007faf873055c0 RCX: 00007faf8722f544
> RDX: 0000000000000002 RSI: 000055d80bde45d0 RDI: 0000000000000001
> RBP: 0000000000000002 R8: 0000000000000073 R9: 00000000ffffffff
> R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000002
> R13: 000055d80bde45d0 R14: 0000000000000002 R15: 00007faf87302f00
> ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
>
> Dmesg gives:
>
> [ 83.387009] dump_stack_lvl+0x4e/0x70
> [ 83.387653] vpanic+0xc2/0x290
> [ 83.388143] panic+0x6c/0x6c
> [ 83.388603] sysrq_handle_crash+0x1a/0x20
>
> The nmi_panic.cold at ffffffff8100bedc in fact, is panic+0x6c/0x6c in dmesg:
>
> crash> dis panic 30
> 0xffffffff8100be70 <panic>: endbr64
> ...
> 0xffffffff8100bed2 <panic+98>: mov %rax,0x10(%rsp)
> 0xffffffff8100bed7 <panic+103>: call 0xffffffff8100bbd0 <vpanic>
> 0xffffffff8100bedc <nmi_panic.cold>: mov $0xffffffff828bc26e,%rdi
> 0xffffffff8100bee3 <nmi_panic.cold+7>: call 0xffffffff8100be70
<panic>
>
> I think we don't have to translate nmi_panic.cold into
> panic+0x6c/0x6c, it doesn't cause serious confusion to me. In this way
> we don't need to hack "text - 1" as kernel does.
>
> What do you think?
Hmm, I think the nmi_panic.cold in the sysrq stack is confusing enough.
For the "bt -s" issue, introducing value_to_symstr_trace() may be good:
I tried your approach and it works. Let's go with yours, I think it is
cleaner than mine. Do you mind posting a new patch with all your code
modifications?
Thanks,
Tao Liu
--- a/defs.h
+++ b/defs.h
@@ -5798,6 +5798,7 @@ struct syment *prev_symbol(char *, struct syment *);
void get_symbol_data(char *, long, void *);
int try_get_symbol_data(char *, long, void *);
char *value_to_symstr(ulong, char *, ulong);
+char *value_to_symstr_trace(ulong, char *, ulong, int);
char *value_symbol(ulong);
ulong symbol_value(char *);
ulong symbol_value_module(char *, char *);
diff --git a/symbols.c b/symbols.c
index 3c62f54d4a93..c5747705f761 100644
--- a/symbols.c
+++ b/symbols.c
@@ -5973,6 +5973,17 @@ generic_machdep_value_to_symbol(ulong value, ulong *offset)
return NULL;
}
+char *
+value_to_symstr(ulong value, char *buf, ulong radix)
+{
+ return _value_to_symstr(value, buf, radix, 0);
+}
+
+char *
+value_to_symstr_trace(ulong value, char *buf, ulong radix)
+{
+ return _value_to_symstr(value, buf, radix, 1);
+}
/*
* For a given value, format a string containing the nearest symbol name
@@ -5980,7 +5991,7 @@ generic_machdep_value_to_symbol(ulong value, ulong *offset)
* radix (10 or 16) -- if it's 0, set it to the current pc->output_radix.
*/
char *
-value_to_symstr(ulong value, char *buf, ulong radix)
+_value_to_symstr(ulong value, char *buf, ulong radix, int trace)
{
struct syment *sp;
ulong offset;
@@ -5996,7 +6007,13 @@ value_to_symstr(ulong value, char *buf, ulong radix)
if ((radix != 10) && (radix != 16))
radix = 16;
- if ((sp = value_search(value, &offset))) {
+ if (trace) {
+ sp = value_search(value-1, &offset);
+ offset++;
+ } else
+ sp = value_search(value, &offset);
+
+ if (sp) {
if (offset)
sprintf(buf, radix == 16 ? "%s+0x%lx" :
"%s+%ld",
sp->name, offset);
diff --git a/x86_64.c b/x86_64.c
index 6a7ec67c304b..0b9a2123de07 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -3237,7 +3237,7 @@ x86_64_print_stack_entry(struct bt_info *bt, FILE *ofp, int level,
name = sp->name;
if (offset && (bt->flags & BT_SYMBOL_OFFSET))
- name_plus_offset = value_to_symstr(text, buf2, bt->radix);
+ name_plus_offset = value_to_symstr_trace(text, buf2, bt->radix);
else
name_plus_offset = NULL;
Traces look same as kernel's call traces.
* NMI case
crash> bt -sx
PID: 0 TASK: ffffffffa3c12940 CPU: 0 COMMAND: "swapper/0"
#0 [fffffe7e99f94d50] machine_kexec+0xb8 at ffffffffa1ae91e8
#1 [fffffe7e99f94d68] __crash_kexec+0x72 at ffffffffa1c6b7a2
#2 [fffffe7e99f94e28] vpanic+0xd9 at ffffffffa1a0bca9
#3 [fffffe7e99f94e50] panic+0x6c at ffffffffa1a0bedc
#4 [fffffe7e99f94eb0] nmi_panic.cold+0xc at ffffffffa1a0bee8
#5 [fffffe7e99f94eb8] unknown_nmi_error+0x77 at ffffffffa1aa39a7
#6 [fffffe7e99f94ed0] exc_nmi+0x106 at ffffffffa2891576
#7 [fffffe7e99f94ef0] end_repeat_nmi+0xf at ffffffffa2a01d9d
[exception RIP: default_idle+15]
* SysRq case
crash> bt -sx
PID: 6598 TASK: ffff8c0902d2b680 CPU: 2 COMMAND: "bash"
#0 [ffffcda8c346b970] machine_kexec+0xb8 at ffffffff908e91e8
#1 [ffffcda8c346b988] __crash_kexec+0x72 at ffffffff90a6b7a2
#2 [ffffcda8c346ba48] vpanic+0xd9 at ffffffff9080bca9
#3 [ffffcda8c346ba70] panic+0x6c at ffffffff9080bedc
#4 [ffffcda8c346bad0] sysrq_handle_crash+0x1a at ffffffff91103a9a
#5 [ffffcda8c346bad8] __handle_sysrq.cold+0x9f at ffffffff90841048
#6 [ffffcda8c346bb08] write_sysrq_trigger+0x59 at ffffffff91104679
#7 [ffffcda8c346bb30] proc_reg_write+0x57 at ffffffff90dd3137
#8 [ffffcda8c346bb48] vfs_write+0xf8 at ffffffff90d17308
#9 [ffffcda8c346bbd8] ksys_write+0x6d at ffffffff90d1783d
#10 [ffffcda8c346bc10] do_syscall_64+0x7d at ffffffff9168e96d
#11 [ffffcda8c346bf40] entry_SYSCALL_64_after_hwframe+0x76 at ffffffff9180012f
Thanks,
Kazu
>
> Thanks,
> Tao Liu
>
>>
>> What do you think about this way?
>>
>> Thanks,
>> Kazu
>>
>>
>>>
>>> Signed-off-by: Tao Liu <ltao(a)redhat.com>
>>> ---
>>> x86_64.c | 34 +++++++++++++++++++++++++++++++++-
>>> 1 file changed, 33 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/x86_64.c b/x86_64.c
>>> index b2cddbf..70bc1da 100644
>>> --- a/x86_64.c
>>> +++ b/x86_64.c
>>> @@ -8887,7 +8887,38 @@ x86_64_get_framesize(struct bt_info *bt, ulong
textaddr, ulong rsp, char *stack_
>>> if ((sp->value >= kt->init_begin) && (sp->value
< kt->init_end))
>>> return 0;
>>>
>>> - if ((machdep->flags & ORC) && (korc =
orc_find(textaddr))) {
>>> + if (machdep->flags & ORC) {
>>> + /*
>>> + * Disassemble & check if the 1st previous instruction of
textaddr
>>> + * is "call". If it does, the orc should unwind
against the
>>> + * address of the "call" inst, rather than the
textaddr itself.
>>> + */
>>> + open_tmpfile2();
>>> + sprintf(buf, "x/-1i 0x%lx", textaddr);
>>> + if (!gdb_pass_through(buf, pc->tmpfile2,
GNU_RETURN_ON_ERROR)) {
>>> + close_tmpfile2();
>>> + bt->flags |= BT_FRAMESIZE_DISABLE;
>>> + return 0;
>>> + }
>>> + rewind(pc->tmpfile2);
>>> + if (fgets(buf, BUFSIZE, pc->tmpfile2)) {
>>> + c = parse_line(buf, arglist);
>>> + for (int i = 0; i < c; i++) {
>>> + if (!strcmp(arglist[i], "call")) {
>>> + reterror = 0;
>>> + ulong tmp_val = htol(arglist[0],
>>> + RETURN_ON_ERROR,
&reterror);
>>> + if (!reterror)
>>> + textaddr = tmp_val;
>>> + break;
>>> + }
>>> + }
>>> + }
>>> + close_tmpfile2();
>>> +
>>> + if ((korc = orc_find(textaddr)) == NULL)
>>> + goto out_orc;
>>> +
>>> if (CRASHDEBUG(1)) {
>>> struct ORC_data *orc =
&machdep->machspec->orc;
>>> fprintf(fp,
>>> @@ -8939,6 +8970,7 @@ x86_64_get_framesize(struct bt_info *bt, ulong
textaddr, ulong rsp, char *stack_
>>> }
>>> }
>>>
>>> +out_orc:
>>> framesize = max = 0;
>>> max_instructions = textaddr - sp->value;
>>> instr = arg = -1;