Page MenuHomeFreeBSD

ddb: improve amd64's stack unwinding after an IP fault
ClosedPublic

Authored by markj on Jun 18 2015, 5:22 PM.
Tags
None
Referenced Files
F105968575: D2859.diff
Mon, Dec 23, 6:17 AM
Unknown Object (File)
Oct 21 2024, 7:02 AM
Unknown Object (File)
Oct 18 2024, 7:40 PM
Unknown Object (File)
Oct 1 2024, 7:49 AM
Unknown Object (File)
Sep 30 2024, 7:40 PM
Unknown Object (File)
Sep 30 2024, 11:34 AM
Unknown Object (File)
Sep 26 2024, 3:54 PM
Unknown Object (File)
Sep 24 2024, 8:30 PM
Subscribers

Details

Summary

If we can't find a symbol corresponding to the current IP, assume that
the previously-executed instruction is a call and attempt to find the
calling function using the return address on the stack. Otherwise we end
up associating the last stack frame with the current function call,
which is incorrect and causes the unwinder to skip printing of the
calling function. For example, if function A() calls B(), and B() calls
a NULL function pointer, the previous unwind logic would result in a
stack of "A() -> ??", skipping B().

Diff Detail

Lint
Lint Passed
Unit
No Test Coverage

Event Timeline

markj retitled this revision from to ddb: improve amd64's stack unwinding after an IP fault.
markj edited the test plan for this revision. (Show Details)
markj updated this object.
jhb edited edge metadata.

Can you also fix this on i386? Also, did you write a simple test for this? (A kernel module whose MOD_LOAD hook invokes a NULL function pointer would work)

This revision is now accepted and ready to land.Jun 20 2015, 2:40 PM
In D2859#55659, @jhb wrote:

Can you also fix this on i386?

Sure.

Also, did you write a simple test for this? (A kernel module whose MOD_LOAD hook invokes a NULL function pointer would work)

Yup - I changed a sysctl handler to call a NULL function pointer. With the change I get:

Fatal trap 12: page fault while in kernel mode
cpuid = 1; apic id = 01
fault virtual address = 0x0
fault code = supervisor read instruction, page not present
instruction pointer = 0x20:0x0
stack pointer = 0x28:0xfffffe00d9322780
frame pointer = 0x28:0xfffffe00d93227c0
code segment = base 0x0, limit 0xfffff, type 0x1b

= DPL 0, pres 1, long 1, def32 0, gran 1

processor eflags = interrupt enabled, resume, IOPL = 0
current process = 582 (sysctl)
[ thread pid 582 tid 100060 ]
Stopped at 0
db> bt
Tracing pid 582 tid 100060 td 0xfffff800050c9000
??() at 0
sysctl_runningspace() at sysctl_runningspace+0x43/frame 0xfffffe00d93227c0
sysctl_root_handler_locked() at sysctl_root_handler_locked+0x94/frame 0xfffffe00d9322800
sysctl_root() at sysctl_root+0x188/frame 0xfffffe00d9322850
userland_sysctl() at userland_sysctl+0x192/frame 0xfffffe00d93228f0
sys___sysctl() at sys___sysctl+0x74/frame 0xfffffe00d93229a0
amd64_syscall() at amd64_syscall+0x282/frame 0xfffffe00d9322ab0
Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe00d9322ab0

  • syscall (202, FreeBSD ELF64, sys___sysctl), rip = 0x80095086a, rsp = 0x7fffffffd9e8, rbp = 0x7fffffffda20 ---

Without the change I get

Fatal trap 12: page fault while in kernel mode
cpuid = 1; apic id = 01
fault virtual address = 0x0
fault code = supervisor read instruction, page not present
instruction pointer = 0x20:0x0
stack pointer = 0x28:0xfffffe00d9395780
frame pointer = 0x28:0xfffffe00d93957c0
code segment = base 0x0, limit 0xfffff, type 0x1b

= DPL 0, pres 1, long 1, def32 0, gran 1

processor eflags = interrupt enabled, resume, IOPL = 0
current process = 584 (sysctl)
[ thread pid 584 tid 100083 ]
Stopped at 0:KDB: reentering
KDB: stack backtrace:

db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00d9394dc0

kdb_reenter() at kdb_reenter+0x33/frame 0xfffffe00d9394dd0
trap() at trap+0x54/frame 0xfffffe00d9394fe0
calltrap() at calltrap+0x8/frame 0xfffffe00d9394fe0

  • trap 0xc, rip = 0xffffffff80690bc3, rsp = 0xfffffe00d93950a0, rbp = 0xfffffe00d9395140 ---

db_read_bytes() at db_read_bytes+0x53/frame 0xfffffe00d9395140
db_get_value() at db_get_value+0x33/frame 0xfffffe00d9395180
db_disasm() at db_disasm+0x29/frame 0xfffffe00d9395290
db_trap() at db_trap+0xbb/frame 0xfffffe00d9395320
kdb_trap() at kdb_trap+0x194/frame 0xfffffe00d93953b0
trap_fatal() at trap_fatal+0x315/frame 0xfffffe00d9395410
trap_pfault() at trap_pfault+0x23e/frame 0xfffffe00d93954b0
trap() at trap+0x4b8/frame 0xfffffe00d93956c0
calltrap() at calltrap+0x8/frame 0xfffffe00d93956c0

  • trap 0xc, rip = 0, rsp = 0xfffffe00d9395780, rbp = 0xfffffe00d93957c0 ---

uart_sab82532_class() at 0/frame 0xfffffe00d93957c0
sysctl_root_handler_locked() at sysctl_root_handler_locked+0x94/frame 0xfffffe00d9395800
sysctl_root() at sysctl_root+0x188/frame 0xfffffe00d9395850
userland_sysctl() at userland_sysctl+0x192/frame 0xfffffe00d93958f0
sys___sysctl() at sys___sysctl+0x74/frame 0xfffffe00d93959a0
amd64_syscall() at amd64_syscall+0x282/frame 0xfffffe00d9395ab0
Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe00d9395ab0

  • syscall (202, FreeBSD ELF64, sys___sysctl), rip = 0x80095086a, rsp = 0x7fffffffd9e8, rbp = 0x7fffffffda20 ---
  • error reading from address 0 ***

KDB: reentering
KDB: stack backtrace:
...
db> bt
Tracing pid 584 tid 100083 td 0xfffff800057084c0
uart_sab82532_class() at 0/frame 0xfffffe00d93957c0
sysctl_root_handler_locked() at sysctl_root_handler_locked+0x94/frame 0xfffffe00d9395800
sysctl_root() at sysctl_root+0x188/frame 0xfffffe00d9395850
userland_sysctl() at userland_sysctl+0x192/frame 0xfffffe00d93958f0
sys___sysctl() at sys___sysctl+0x74/frame 0xfffffe00d93959a0
amd64_syscall() at amd64_syscall+0x282/frame 0xfffffe00d9395ab0
Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe00d9395ab0

  • syscall (202, FreeBSD ELF64, sys___sysctl), rip = 0x80095086a, rsp = 0x7fffffffd9e8, rbp = 0x7fffffffda20 ---
markj edited edge metadata.
  • ddb: improve amd64's stack unwinding after an IP fault
  • Use a more generic name for the stack pointer argument.
  • Handle i386 as well.
This revision now requires review to proceed.Jun 21 2015, 11:04 PM
jhb edited edge metadata.
jhb added inline comments.
sys/amd64/amd64/db_trace.c
205

I would maybe go for three question marks, but that's entirely up to you. (i.e. not important)

This revision is now accepted and ready to land.Jul 21 2015, 5:04 AM
sys/amd64/amd64/db_trace.c
205

I was just copying what gdb does. I'll change it to three before committing.

This revision was automatically updated to reflect the committed changes.