Re: [External Mail]Re: GDB can't show QEMU ARM thread call stack/threads

2025-01-24 Thread Xu Neo
It turns out the issue comes from the wrong SP register value getting
restored by python script.

TLDR, If you happen to met that GDB cannot unwind correctly, try set
$sp=$sp+4


The issue is that when an exception happened, armv7-m could push 4 bytes to
stack, to make sure SP is 8bytes aligned.
See
https://developer.arm.com/documentation/ddi0403/d/System-Level-Architecture/System-Level-Programmers--Model/ARMv7-M-exception-model/Stack-alignment-on-exception-entry

It happens that NuttX release 12.6.0 generates code that has SP not aligned
to 4 bytes as shown below, right before triggering  SVC.
[image: img_v3_02is_bcd2a515-ec2b-4432-a86a-cbd232cb736l.jpeg]

According to the documentation, we can distinguish  this situation from
xPSR[9] bit. xPSR is pushed to stack automatically.
[image: img_v3_02is_e29e799d-75c4-4520-b145-a2369b4b5ael.jpeg]

 In this case, the real SP after restore should be `SP + 4`. After
adjusting it manually, now GDB can unwind correctly.
[image: a8GxTXm0aT.jpeg]

NuttX release 12.8.0 changes the sys_call to macro, which saves 4 bytes on
stack, avoiding this issue (coincidently?). The latest master branch does
not have this issue too, and I’m not sure if it’s guaranteed or not.

Regards,
Neo


Re: [External Mail]Re: GDB can't show QEMU ARM thread call stack/threads

2025-01-24 Thread Xu Neo
Trying again with the screenshot in text of what's going on.

> It happens that NuttX release 12.6.0 generates code that has SP not
aligned to 4 bytes as shown below, right before triggering  SVC.

```
│ 170 /* SVC with SYS_ call number and two parameters */ │
│ 171 │
│ 172 static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, │
│ 173 uintptr_t parm2) │
│ 174 { │
│ 175 register long reg0 __asm__("r0") = (long)(nbr); │
│ 176 register long reg2 __asm__("r2") = (long)(parm2); │
│ 177 register long reg1 __asm__("r1") = (long)(parm1); │
│ 178 │
│ > 179 __asm__ __volatile__ │
│ 180 ( │
│ 181 "svc %1" │
│ 182 : "=r"(reg0) │
│ 183 : "i"(SYS_syscall), "r"(reg0), "r"(reg1), "r"(reg2) │
┌┐
│B+ 0xaaf8  push {lr} │
│ 0xaafa  ldr r2, [pc, #32] @ (0xab1c
) │
│ 0xaafc  mov r3, r0 │
│ 0xaafe  ldr r0, [r2, #0] │
│ 0xab00  cbz r0, 0xab10  │
│ 0xab02  str.w r0, [r1, #156] @ 0x9c │
│ 0xab06  ldr.w r3, [r3, #156] @ 0x9c │
│ 0xab0a  str r3, [r2, #0] │
│ 0xab0c  ldr.w pc, [sp], #4 │
│ 0xab10  movs r0, #2 │
│ 0xab12  ldr.w r2, [r3, #156] @ 0x9c │
│ 0xab16  adds r1, #156 @ 0x9c │
│ >0xab18  svc 0

(gdb) p/x $sp
$3 = 0x2000667c
```


> According to the documentation, we can distinguish this situation from
xPSR[9] bit. xPSR is pushed to stack automatically.
```
│ 124 exception_common: │
│ 125 │
│ > 126 mrs r0, ipsr /* R0=exception number */

(gdb) p/x $sp
$5 = 0x20006658
(gdb) x/32x 0x20006658
0x20006658: 0x0002  0x20005c5c  0x20004f28  0x20001688
0x20006668: 0x0001  0x4f51  0xab1a
**0x01000200**  <-- this is xPSR
```

>  In this case, the real SP after restore should be `SP + 4`. After
adjusting it manually, now GDB can unwind correctly.

```
(gdb) set $sp=$sp+4
(gdb) bt
#0  up_switch_context (tcb=0x20001688 , rtcb=rtcb@entry=0x20005bc0)
at common/arm_switchcontext.c:95
#1  0x4f50 in nxsem_wait (sem=sem@entry=0x201c ) at
semaphore/sem_wait.c:175
#2  0x8192 in uart_read (filep=0x20005ecc, buffer=0x200066ef "",
buflen=1) at serial/serial.c:1058
#3  0x00015910 in nx_read (fd=, buf=buf@entry=0x200066ef,
nbytes=nbytes@entry=1) at vfs/fs_read.c:140
#4  0x0001591a in read (fd=, buf=buf@entry=0x200066ef,
nbytes=nbytes@entry=1) at vfs/fs_read.c:170
#5  0xb04a in readline_getc (vtbl=0x2000672c) at readline_fd.c:72
#6  0xd788 in readline_common (vtbl=vtbl@entry=0x2000672c,
buf=buf@entry=0x20008498
"\n", buflen=buflen@entry=1000) at readline_common.c:513
#7  0xb08e in readline_fd (buf=buf@entry=0x20008498 "\n",
buflen=buflen@entry=1000, infd=infd@entry=0, outfd=) at
readline_fd.c:222
#8  0xad9c in nsh_session (pstate=pstate@entry=0x20008210,
login=login@entry=1, argc=argc@entry=1, argv=argv@entry=0x20005fc0) at
nsh_session.c:228
#9  0xacae in nsh_consolemain (argc=argc@entry=1,
argv=argv@entry=0x20005fc0)
at nsh_consolemain.c:75
#10 0xac6c in nsh_main (argc=1, argv=0x20005fc0) at nsh_main.c:74
#11 0x8d60 in nxtask_startup (entrypt=0xac41 , argc=1,
argv=0x20005fc0) at sched/task_startup.c:70
#12 0x612a in nxtask_start () at task/task_start.c:114
#13 0x in ?? ()
(gdb)
```

Regards,
Neo


Xu Neo  于2025年1月25日周六 01:33写道:

> It turns out the issue comes from the wrong SP register value getting
> restored by python script.
>
> TLDR, If you happen to met that GDB cannot unwind correctly, try set
> $sp=$sp+4
>
>
> The issue is that when an exception happened, armv7-m could push 4 bytes
> to stack, to make sure SP is 8bytes aligned.
> See
> https://developer.arm.com/documentation/ddi0403/d/System-Level-Architecture/System-Level-Programmers--Model/ARMv7-M-exception-model/Stack-alignment-on-exception-entry
>
> It happens that NuttX release 12.6.0 generates code that has SP not
> aligned to 4 bytes as shown below, right before triggering  SVC.
> [image: img_v3_02is_bcd2a515-ec2b-4432-a86a-cbd232cb736l.jpeg]
>
> According to the documentation, we can distinguish  this situation from
> xPSR[9] bit. xPSR is pushed to stack automatically.
> [image: img_v3_02is_e29e799d-75c4-4520-b145-a2369b4b5ael.jpeg]
>
>  In this case, the real SP after restore should be `SP + 4`. After
> adjusting it manually, now GDB can unwind correctly.
> [image: a8GxTXm0aT.jpeg]
>
> NuttX release 12.8.0 changes the sys_call to macro, which saves 4 bytes on
> stack, avoiding this issue (coincidently?). The latest master branch does
> not have this issue too, and I’m not sure if it’s guaranteed or not.
>
> Regards,
> Neo
>