3

I'm trying to find all the places in the source of a running program where certain syscalls are used. I set breakpoints like:

catch syscall socketcall

...Which is working fine. However, when one of the breakpoints is actually hit, the backtrace always looks the same:

(gdb) bt
#0  __cp_end () at src/thread/i386/syscall_cp.s:25

And that's all she wrote! Why can't GDB walk the stack and show a full stacktrace going all the way up to main?

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
Alex D
  • 29,755
  • 7
  • 80
  • 126

2 Answers2

5

Why can't GCC walk the stack and show a full stacktrace going all the way up to main?

Most likely because hand-written assembly in syscall_cp.s lacks unwind descriptors, and is not using frame pointers. GDB needs one or the other. See also this answer.

Community
  • 1
  • 1
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • I have confirmed the hand-written asm doesn't use frame pointers -- because EBP is needed for the 6th argument for syscalls which have 6 arguments (on x86-32 Linux). – Alex D Apr 27 '15 at 07:47
  • 1
    I added the needed stack frame information with CFI directives, and now GDB can show backtraces from this assembly function! Just sent a patch to the musl libc developers, hopefully they will merge it. – Alex D Apr 27 '15 at 11:44
  • 1
    As it turns out, this is true for other architectures, MIPS specifically in my case, even with the latest musl from git (as of Jan 2020). Any advice on how to add CFI directives for MIPS? – Daniele Jan 25 '20 at 20:35
  • 1
    I added a couple of .cfi_def_cfa_offset directives copying from examples, only in the place where I was observing problems, and I can finally get a backtrace, but I'm not that familiar with MIPS asm or abi to add them everywhere. – Daniele Jan 25 '20 at 20:38
  • @DanielSantos there is no link, it's in my laptop and in our company's private repo... but I'm pretty sure I can post this here as an "answer" if you want – Daniele Apr 15 '20 at 00:28
3

Specifically for MIPS, I had to apply the following patch to musl to get a meaningful stack trace. Keep in mind that I don't really know what I'm doing, but this works for me. I was hoping to have time to submit this upstream, but it's quite hackish, incomplete, and again, I don't know what I'm doing. Still, here it is:

diff --git a/src/internal/mips/syscall.s b/src/internal/mips/syscall.s
index 5d0def52..f9bc599d 100644
--- a/src/internal/mips/syscall.s
+++ b/src/internal/mips/syscall.s
@@ -4,6 +4,7 @@
 .hidden __syscall
 .type   __syscall,@function
 __syscall:
+    .cfi_startproc
    move    $2, $4
    move    $4, $5
    move    $5, $6
@@ -13,6 +14,7 @@ __syscall:
    lw      $9, 24($sp)
    lw      $10,28($sp)
    subu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset 32
    sw      $8, 16($sp)
    sw      $9, 20($sp)
    sw      $10,24($sp)
@@ -21,6 +23,8 @@ __syscall:
    syscall
    beq     $7, $0, 1f
    addu    $sp, $sp, 32
+    .cfi_adjust_cfa_offset -32
    subu    $2, $0, $2
 1: jr      $ra
    nop
+   .cfi_endproc
diff --git a/src/ldso/mips/dlsym.s b/src/ldso/mips/dlsym.s
index 1573e519..f1036621 100644
--- a/src/ldso/mips/dlsym.s
+++ b/src/ldso/mips/dlsym.s
@@ -3,15 +3,21 @@
 .hidden __dlsym
 .type dlsym,@function
 dlsym:
+    .cfi_startproc
    lui $gp, %hi(_gp_disp)
    addiu $gp, %lo(_gp_disp)
    addu $gp, $gp, $25
    move $6, $ra
    lw $25, %call16(__dlsym)($gp)
    addiu $sp, $sp, -16
+   .cfi_adjust_cfa_offset 16
    sw $ra, 12($sp)
+    .cfi_rel_offset $ra, 12
    jalr $25
    nop
    lw $ra, 12($sp)
+    .cfi_restore $ra
    jr $ra
    addiu $sp, $sp, 16
+   .cfi_adjust_cfa_offset -16
+   .cfi_endproc
diff --git a/src/thread/mips/syscall_cp.s b/src/thread/mips/syscall_cp.s
index d2846264..ab173496 100644
--- a/src/thread/mips/syscall_cp.s
+++ b/src/thread/mips/syscall_cp.s
@@ -14,9 +14,12 @@
 .hidden __syscall_cp_asm
 .type   __syscall_cp_asm,@function
 __syscall_cp_asm:
+    .cfi_startproc
    subu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset 32
 __cp_begin:
    lw      $4, 0($4)
+   .cfi_remember_state
    bne     $4, $0, __cp_cancel
    move    $2, $5
    move    $4, $6
@@ -35,14 +38,18 @@ __cp_begin:
 __cp_end:
    beq     $7, $0, 1f
    addu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset -32
    subu    $2, $0, $2
 1: jr      $ra
    nop

 __cp_cancel:
+    .cfi_restore_state
    move    $2, $ra
+   .cfi_register $ra, $2
    bal     1f
    addu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset -32
    .gpword .
    .gpword __cancel
 1: lw      $3, ($ra)
@@ -51,3 +58,5 @@ __cp_cancel:
    addu    $25, $25, $3
    jr      $25
    move    $ra, $2
+   .cfi_restore $ra
+   .cfi_endproc
-- 
2.24.0
Daniele
  • 410
  • 7
  • 19
  • You're my hero! I'll get this upstream. At your option, please email me your full name, company name, and/or email at daniel@gsat.us and I'll appropriately notate credit. Alternatively, I'll just include this link in the comments. I was just digging into this (trying to remember .cfi syntax) when I had to jump on something else. – Daniel Santos Apr 15 '20 at 17:59