Bug 6204

Summary: _syscallX() macros do not compile in PIC mode
Product: Platform Specific/Hardware Reporter: Markus Gutschke (markus)
Component: i386Assignee: platform_i386
Status: CLOSED CODE_FIX    
Severity: normal    
Priority: P2    
Hardware: i386   
OS: Linux   
Kernel Version: 2.6.15.6 Subsystem:
Regression: --- Bisected commit-id:
Attachments: This patch introduces alternative macros that will be used in PIC mode
Updated patch that was applied to -mm tree

Description Markus Gutschke 2006-03-09 14:57:08 UTC
Most recent kernel where this bug did not occur: n/a
Distribution: n/a
Hardware Environment: n/a
Software Environment: gcc/g++ with -fpic or -fPIC commandline option
Problem Description: gcc reserves %ebx when generating
position-independent-code. The _syscallX() macros in include/asm-i386/unistd.h
fail to preserve this register and are thus uncompilable in PIC mode.

Steps to reproduce:

Compile the following program with "gcc -fpic"

  #include <stdio.h>
  #include <asm/unistd.h>
  #include <errno.h>
  #include <unistd.h>
  
  #define __NR_my_write __NR_write
  static inline _syscall3(ssize_t, my_write, int, fd, const void *, buf, size_t,
count);
  
  int main() {
  #ifdef __PIC__
          const char s[] = "PIC is defined\n";
  #else
          const char s[] = "PIC is undefined\n";
  #endif
          my_write(1, s, sizeof(s));
          return 0;
  }

Bug fix:

--- linux/include/asm-i386/unistd.h.orig	2006-03-05 11:07:54.000000000 -0800
+++ linux/include/asm-i386/unistd.h	2006-03-09 14:25:45.000000000 -0800
@@ -326,6 +326,7 @@
 __syscall_return(type,__res); \
 }
 
+#ifndef __PIC__
 #define _syscall1(type,name,type1,arg1) \
 type name(type1 arg1) \
 { \
@@ -393,6 +394,82 @@
 __syscall_return(type,__res); \
 }
 
+#else /* __PIC__ */
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+long __res; \
+__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
+	: "=a" (__res) \
+	: "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+long __res; \
+__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
+	: "=a" (__res) \
+	: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+long __res; \
+__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
+	: "=a" (__res) \
+	: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \
+		  "d" ((long)(arg3)) : "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+long __res; \
+__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \
+	: "=a" (__res) \
+	: "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \
+	  "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \
+__syscall_return(type,__res); \
+} 
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+	  type5,arg5) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+long __res; \
+__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " \
+                  "int $0x80 ; pop %%ebx" \
+	: "=a" (__res) \
+	: "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \
+	  "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+	  type5,arg5,type6,arg6) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
+{ \
+long __res; \
+  struct { long __a1; long __a6; } __s = { (long)arg1, (long)arg6 }; \
+__asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \
+                  "movl 0(%2),%%ebx ; movl %1,%%eax ; int $0x80 ; " \
+                  "pop %%ebx ;  pop %%ebp" \
+	: "=a" (__res) \
+	: "i" (__NR_##name),"0" ((long)(&__s)),"c" ((long)(arg2)), \
+	  "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \
+	: "memory"); \
+__syscall_return(type,__res); \
+}
+#endif /* __PIC__ */
+
 #ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
Comment 1 Markus Gutschke 2006-03-09 14:58:28 UTC
Created attachment 7552 [details]
This patch introduces alternative macros that will be used in PIC mode
Comment 2 Markus Gutschke 2006-03-14 20:16:37 UTC
Created attachment 7574 [details]
Updated patch that was applied to -mm tree

This patch was applied to the -mm tree by Andrew Morton and will hopefully make
it into Linus' tree at some point.
Comment 3 Markus Gutschke 2006-03-23 19:31:49 UTC
The patch has been merged into Linus' tree:
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=aeefc956d5d8f8402216a5447bd72ade9eb37eff