Page MenuHomeFreeBSD

[MIPS/DDB] (fix) backtrace: incorrect MIPS32 reg values & truncated backtrace on MipsKernGenException inside short function
ClosedPublic

Authored by mizhka on Jun 21 2016, 4:27 PM.

Details

Summary

There are 2 bugs fixed by this patch:

  • in case of MIPS32 register values printed in backtrace are invalid due to incorrect print macro
  • in case of MipsKernGenException inside short(inline?) function (w/o usage of stack) backtrace doesn't print full call stack.

1st bug can be easily reproduced only on 32-bit MIPS CPU, because for MIPS64 it works fine. Current print macro is "%jx", i.e. it tries to print double-word, what is incorrect for 32-bit machine

2nd bug can be reproduced by writing to invalid address by bus_write_4().

Before patch the output of backtrace command is:

Stopped at      generic_bs_w_4+0x4:     jr      ra
db> bt
Tracing pid 0 tid 100000 td 0x8045ca90
db_trace_thread+30 (?,?,?,?) ra 188055c700 sp 0 sz 0
db_stack_trace+114 (0,?,ffffffff,?) ra 208055c718 sp 1 sz 1
db_command+388 (?,?,?,?) ra a88055c738 sp 0 sz 0
db_command_loop+70 (?,?,?,?) ra 188055c7e0 sp 0 sz 0
db_trap+f4 (?,?,?,?) ra 1a88055c7f8 sp 0 sz 0
kdb_trap+100 (?,?,?,?) ra 308055c9a0 sp 0 sz 0
trap+f7c (?,?,?,?) ra c08055c9d0 sp 0 sz 0
MipsKernGenException+134 (0,b800409b,9b,0) ra c88055ca90 sp 100000001 sz 1
generic_bs_w_4+4 (?,?,?,?) ra 8055cb58 sp 0 sz 0
pid 0

SP is equal to zero (1st bug) and generic_bs_w_4+4 is last item (2nd bug)

After patch:

Stopped at      generic_bs_w_4+0x4:     jr      ra
db> bt
Tracing pid 0 tid 100000 td 0x8045ca90
db_trace_thread+30 (?,?,?,?) ra 800102a4 sp 8055c700 sz 24
db_stack_trace+114 (0,?,ffffffff,?) ra 8000f85c sp 8055c718 sz 32
db_command+388 (?,?,?,?) ra 8000f9e0 sp 8055c738 sz 168
db_command_loop+70 (?,?,?,?) ra 800126fc sp 8055c7e0 sz 24
db_trap+f4 (?,?,?,?) ra 801a2e30 sp 8055c7f8 sz 424
kdb_trap+100 (?,?,?,?) ra 8034c24c sp 8055c9a0 sz 48
trap+f7c (?,?,?,?) ra 80339d60 sp 8055c9d0 sz 192
MipsKernGenException+134 (0,b800409b,9b,0) ra 803314e4 sp 8055ca90 sz 200
generic_bs_w_4+4 (?,?,?,?) ra 800608e0 sp 8055cb58 sz 0
ehci_hcreset+30 (?,?,?,?) ra 80066244 sp 8055cb58 sz 32
ehci_init+1b0 (?,?,?,?) ra 80361128 sp 8055cb78 sz 80
bhnd_ehci_attach+25c (?,?,?,?) ra 8019b018 sp 8055cbc8 sz 72
device_attach+480 (?,?,?,?) ra 8019b210 sp 8055cc10 sz 96
device_probe_and_attach+5c (?,?,?,?) ra 8019b2f4 sp 8055cc70 sz 24
bus_generic_attach+20 (?,?,?,?) ra 80360d30 sp 8055cc88 sz 24
bhnd_usb_attach+66c (?,?,?,?) ra 8019b018 sp 8055cca0 sz 80
device_attach+480 (?,?,?,?) ra 8019b210 sp 8055ccf0 sz 96
device_probe_and_attach+5c (?,?,?,?) ra 8019bc9c sp 8055cd50 sz 24
bus_generic_new_pass+10c (?,?,?,?) ra 8019bc84 sp 8055cd68 sz 40
bus_generic_new_pass+f4 (?,?,?,?) ra 8019bc84 sp 8055cd90 sz 40
bus_generic_new_pass+f4 (?,?,?,?) ra 8019bc84 sp 8055cdb8 sz 40
bus_generic_new_pass+f4 (?,?,?,?) ra 80198438 sp 8055cde0 sz 40
bus_set_pass+c0 (?,?,?,?) ra 801984ac sp 8055ce08 sz 40
root_bus_configure+14 (?,?,?,?) ra 803312bc sp 8055ce30 sz 24
configure+10 (?,?,?,?) ra 80108a14 sp 8055ce48 sz 24
mi_startup+138 (?,?,?,?) ra 80001170 sp 8055ce60 sz 32
_start+70 (?,?,?,?) ra 0 sp 8055ce80 sz 0
pid 0

Register RA & SP values are correct and we can see full stack trace.

Test Plan

Prereqs:

  • any MIPS32 board
  • ability to modify kernel code to cause MipsKernGenException by call bus_write_4 to invalid address (in my case it's KSEG1 + 0x1800496)

Tested on BCM5358 (MIP32 74K)

Diff Detail

Repository
rS FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

mizhka updated this revision to Diff 17734.Jun 21 2016, 4:27 PM
mizhka retitled this revision from to [MIPS/DDB] (fix) backtrace: incorrect MIPS32 reg values & truncated backtrace on MipsKernGenException inside short function.
mizhka updated this object.
mizhka edited the test plan for this revision. (Show Details)
mizhka added reviewers: ray, adrian.
mizhka set the repository for this revision to rS FreeBSD src repository.
adrian accepted this revision.Jun 23 2016, 4:14 PM
adrian edited edge metadata.

nice catch!

This revision is now accepted and ready to land.Jun 23 2016, 4:14 PM
jhibbits added inline comments.
sys/mips/mips/db_trace.c
81 ↗(On Diff #17734)

Why not just leave the print format as "%jx" and force a cast to uintmax_t in the call?

394 ↗(On Diff #17734)

Just cast here, no need for special casing.

imp added a comment.Jun 23 2016, 4:39 PM

Except for the needless #define for the printf format that's not needed, this looks good.

sys/mips/mips/db_trace.c
393 ↗(On Diff #17734)

The format doesn't need to change. (uintmax_t)ra, and (uintmax_t)sp) are all that's needed.

mizhka added inline comments.Jun 23 2016, 8:58 PM
sys/mips/mips/db_trace.c
393 ↗(On Diff #17734)

In case of casting, the output is like:

db> bt
...
db_command+388 (?,?,?,?) ra ffffffff8000fa00 sp ffffffff80565738 sz 168
db_command_loop+70 (?,?,?,?) ra ffffffff8001271c sp ffffffff805657e0 sz 24
...

i.e. with trailing "f".
The reason is (at least using gcc 4.2.1) cast "(uintmax_t) ra" results in:

808:   02a03021        move    a2,s5    // s5 = RA
80c:   00153fc3        sra     a3,s5,0x1f // high word filled by sign-bit of RA

"sra" fills high word by sign-bit (1 for all kernel addresses - KSEG0/1)

As quick win, I've used "%x" mask for MIPS32, but I'll appreciate any advice how to do it without this hack.

mizhka updated this revision to Diff 17836.Jun 23 2016, 10:14 PM
mizhka edited edge metadata.
  • fixed according to review remark: usage of cast instead of #define case

Tested on MIPS32 74k (BCM5358, Asus RT-N53)

This revision now requires review to proceed.Jun 23 2016, 10:14 PM
mizhka marked 3 inline comments as done.Jun 23 2016, 10:14 PM
ray accepted this revision.Jun 23 2016, 10:17 PM
ray edited edge metadata.

Now, looks fine.

This revision is now accepted and ready to land.Jun 23 2016, 10:17 PM
adrian accepted this revision.Jul 12 2016, 12:42 AM
adrian edited edge metadata.
This revision was automatically updated to reflect the committed changes.