Hi,

I've built an ARM EABI toolchain with uClibc compiled as
Thumb code using buildroot (BR2_TARGET_OPTIMIZATION="-Os -mthumb").

This works fine except that in gdb (6.8), if you stop your program
with some threads blocked in syscalls, gdb is unable to display
a call stack for those threads.

The reason for this is that gdb's calculation of the stack
frame size is off because of the "push {r7}" used in the syscall code.
(INTERNAL_SYSCALL in uClibc/libc/sysdeps/linux/arm/bits/syscalls.h)

Rather than fixing gdb (specifically thumb_analyze_prologue() in
arm-tdep.c), I made a local change to avoid changing the stack
pointer in INTERNAL_SYSCALL, like so:

-      asm volatile ("push       {r7}\n"                         \
-                    "\tmov      r7, v3\n"                       \
-                    "\tswi      0       @ syscall " #name "\n"  \
-                    "\tpop      {r7}"                           \

+       __asm__ volatile ("push {r7}\n"                         \
+                    "\tmov     r7, v3\n"                       \
+                    "\tpop     {v3}\n"                         \
+                    "\tswi     0       @ syscall " #name "\n"  \
+                    "\tmov     r7, v3\n"                               \

But just before posting here I took a peek into the NPTL
branch and noticed that there is a better patch which avoids
the "push {r7}" altogether:

$ svn diff svn://uclibc.org/trunk/uClibc/libc/sysdeps/linux/arm/bits/syscalls.h 
svn://uclibc.org/branches/uClibc-nptl/libc/sysdeps/linux/arm/bits/syscalls.h
Index: syscalls.h
===================================================================
--- syscalls.h  (.../trunk/uClibc/libc/sysdeps/linux/arm/bits/syscalls.h)       
(revision 22865)
+++ syscalls.h  
(.../branches/uClibc-nptl/libc/sysdeps/linux/arm/bits/syscalls.h)       
(revision 22865)
@@ -137,17 +137,21 @@
      (int) __sys_result; })
 #endif
 #else /* !defined(__thumb__) */
-
+/* We can't use push/pop inside the asm because that breaks
+   unwinding (ie. thread cancellation).
+ */
 #define INTERNAL_SYSCALL(name, err, nr, args...)                       \
   ({ unsigned int __sys_result;                                                
\
     {                                                                  \
+      int _sys_buf[2];                                                 \
       register int _a1 __asm__ ("a1");                                 \
+      register int *_v3 asm ("v3") = _sys_buf;                         \
+      *_v3 = (int) (SYS_ify(name));                                    \
       LOAD_ARGS_##nr (args)                                            \
-      register int _v3 __asm__ ("v3") = (int) (SYS_ify(name));         \
-      __asm__ __volatile__ ("push       {r7}\n"                                
\
-                           "\tmov      r7, v3\n"                       \
-                           "\tswi      0       @ syscall " #name "\n"  \
-                           "\tpop      {r7}"                           \
+      asm volatile ("str       r7, [v3, #4]\n"                         \
+                   "\tldr      r7, [v3]\n"                             \
+                   "\tswi      0       @ syscall " #name "\n"          \
+                   "\tldr      r7, [v3, #4]"                           \
                    : "=r" (_a1)                                        \
                    : "r" (_v3) ASM_ARGS_##nr                           \
                     : "memory");                                       \


Please consider merging this change into trunk.


Thanks,
Johannes
_______________________________________________
uClibc mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/uclibc

Reply via email to