gdb: LoongArch: Improve loongarch_scan_prologue for correct backtrace
(1) Description of Problem:
When debugging the following code, the execution result of
the backtrace command is incorrect.
$ cat test.S
.text
.globl fun1
.type fun1, @function
fun1:
or $r12,$r0,$r0
or $r4,$r12,$r0
jr $r1
.globl fun
.type fun, @function
fun:
addi.d $r3,$r3,-16
st.d $r1,$r3,8
bl fun1
or $r12,$r4,$r0
or $r4,$r12,$r0
ld.d $r1,$r3,8
addi.d $r3,$r3,16
jr $r1
.globl main
.type main, @function
main:
addi.d $r3,$r3,-16
st.d $r1,$r3,8
bl fun
nop
ld.d $r1,$r3,8
addi.d $r3,$r3,16
jr $r1
$ gcc test.S -o test
$ gdb test
...
(gdb) b fun1
Breakpoint 1 at 0x748
(gdb) r
Breakpoint 1, 0x0000555555554748 in fun1 ()
(gdb) bt
#0 0x0000555555554748 in fun1 ()
#1 0x0000555555554758 in fun ()
#2 0x0000555555554758 in fun ()
#3 0x0000555555554758 in fun ()
....
--Type <RET> for more, q to quit, c to continue without paging
(2) Root Cause Analysis:
The return address of fun() in r1(ra) is saved on the stack:
addi.d $r3,$r3,-16
st.d $r1,$r3,8
The bl instruction in fun () will call the fun1 () and save
the value of pc+4 to r1(ra).
bl fun1
or $r12,$r4,$r0
Because registers such as fp and ra saved in the stack of the sub-function
are not recorded in current code. When trace back fun() to main(), the pc
of the previous frame to be read from ra register instead of the saved location
on the stack. At this time, the value of ra register in fun() is already the
address of the next instruction after the bl. So it is impossible to trace
back to the main().
(3) Solution:
Record the location of ra, fp, s0 to s8 on the stack to ensure the correct
execution of backtrace.
(4) Test:
$ gdb test
...
(gdb) b fun1
Breakpoint 1 at 0x748
(gdb) r
Breakpoint 1, 0x0000555555554748 in fun1 ()
(gdb) bt
#0 0x0000555555554748 in fun1 ()
#1 0x0000555555554758 in fun ()
#2 0x0000555555554778 in main ()
Signed-off-by: Hui Li <lihui@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>