Fixes for ptrace() argument parsing.
* process.c: Add parsing of PTRACE_SETOPTIONS, PTRACE_GETEVENTMSG,
PTRACE_GETSIGINFO, PTRACE_SETSIGINFO.
* strace.c (handle_stopped_tcbs): Make PTRACE_SETOPTIONS
define check more robust.
* defs.h: Declare several "extern const struct xlat" arrays here.
* desc.c: Remove open_mode_flags[] and open_access_modes[]
extern declarations.
* net.c: Remove open_mode_flags[] extern declaration.
* sock.c: Remove addrfams[] extern declaration.
* util.c: Remove struct_user_offsets[] extern declaration.
* signal.c: Remove open_mode_flags[] extern declaration.
diff --git a/ChangeLog b/ChangeLog
index ac67497..5a3d0fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-01-13  Denys Vlasenko  <dvlasenk@redhat.com>
+
+	Fixes for ptrace() argument parsing.
+	* process.c: Add parsing of PTRACE_SETOPTIONS, PTRACE_GETEVENTMSG,
+	PTRACE_GETSIGINFO, PTRACE_SETSIGINFO.
+	* strace.c (handle_stopped_tcbs): Make PTRACE_SETOPTIONS
+	define check more robust.
+	* defs.h: Declare several "extern const struct xlat" arrays here.
+	* desc.c: Remove open_mode_flags[] and open_access_modes[]
+	extern declarations.
+	* net.c: Remove open_mode_flags[] extern declaration.
+	* sock.c: Remove addrfams[] extern declaration.
+	* util.c: Remove struct_user_offsets[] extern declaration.
+	* signal.c: Remove open_mode_flags[] extern declaration.
+
 2009-01-09  Denys Vlasenko  <dvlasenk@redhat.com>
 
 	* defs.h: Add new struct tcb fields: wait_status, next_need_service.
diff --git a/defs.h b/defs.h
index f9e4ecc..1366a6e 100644
--- a/defs.h
+++ b/defs.h
@@ -417,6 +417,11 @@
 	char *str;
 };
 
+extern const struct xlat open_mode_flags[];
+extern const struct xlat addrfams[];
+extern const struct xlat struct_user_offsets[];
+extern const struct xlat open_access_modes[];
+
 /* Format of syscall return values */
 #define RVAL_DECIMAL	000	/* decimal format */
 #define RVAL_HEX	001	/* hex format */
diff --git a/desc.c b/desc.c
index db1084d..c4c5a69 100644
--- a/desc.c
+++ b/desc.c
@@ -261,8 +261,6 @@
 }
 #endif
 
-extern const struct xlat open_mode_flags[];
-
 /*
  * low bits of the open(2) flags define access mode,
  * other bits are real flags.
@@ -270,7 +268,6 @@
 static const char *
 sprint_open_modes(mode_t flags)
 {
-	extern const struct xlat open_access_modes[];
 	static char outstr[1024];
 	const char *str = xlookup(open_access_modes, flags & 3);
 	const char *sep = "";
diff --git a/net.c b/net.c
index be88969..b5cf81c 100644
--- a/net.c
+++ b/net.c
@@ -1499,8 +1499,6 @@
 	return sys_accept(tcp);
 }
 
-extern const struct xlat open_mode_flags[];
-
 static int
 do_pipe(struct tcb *tcp, int flags_arg)
 {
diff --git a/process.c b/process.c
index 95c47e1..03cd251 100644
--- a/process.c
+++ b/process.c
@@ -2231,7 +2231,7 @@
 		else if (umove(tcp, tcp->u_arg[2], &si) < 0)
 			tprintf("{???}");
 		else
-			printsiginfo(&si, verbose (tcp));
+			printsiginfo(&si, verbose(tcp));
 		/* options */
 		tprintf(", ");
 		printflags(wait4_options, tcp->u_arg[3], "W???");
@@ -2332,6 +2332,18 @@
 #ifdef PTRACE_SETVRREGS
 	{ PTRACE_SETVRREGS,	"PTRACE_SETVRREGS",	},
 #endif
+#ifdef PTRACE_SETOPTIONS
+	{ PTRACE_SETOPTIONS,	"PTRACE_SETOPTIONS",	},
+#endif
+#ifdef PTRACE_GETEVENTMSG
+	{ PTRACE_GETEVENTMSG,	"PTRACE_GETEVENTMSG",	},
+#endif
+#ifdef PTRACE_GETSIGINFO
+	{ PTRACE_GETSIGINFO,	"PTRACE_GETSIGINFO",	},
+#endif
+#ifdef PTRACE_SETSIGINFO
+	{ PTRACE_SETSIGINFO,	"PTRACE_SETSIGINFO",	},
+#endif
 #ifdef SUNOS4
 	{ PTRACE_READDATA,	"PTRACE_READDATA"	},
 	{ PTRACE_WRITEDATA,	"PTRACE_WRITEDATA"	},
@@ -2361,7 +2373,9 @@
 #endif /* !I386 */
 	{ PTRACE_GETUCODE,	"PTRACE_GETUCODE"	},
 #endif /* SUNOS4 */
+
 #else /* FREEBSD */
+
 	{ PT_TRACE_ME,		"PT_TRACE_ME"		},
 	{ PT_READ_I,		"PT_READ_I"		},
 	{ PT_READ_D,		"PT_READ_D"		},
@@ -2386,9 +2400,35 @@
 };
 
 #ifndef FREEBSD
-#ifndef SUNOS4_KERNEL_ARCH_KLUDGE
-static
-#endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */
+#ifdef PTRACE_SETOPTIONS
+static const struct xlat ptrace_setoptions_flags[] = {
+#ifdef PTRACE_O_TRACESYSGOOD
+	{ PTRACE_O_TRACESYSGOOD,"PTRACE_O_TRACESYSGOOD"	},
+#endif
+#ifdef PTRACE_O_TRACEFORK
+	{ PTRACE_O_TRACEFORK,	"PTRACE_O_TRACEFORK"	},
+#endif
+#ifdef PTRACE_O_TRACEVFORK
+	{ PTRACE_O_TRACEVFORK,	"PTRACE_O_TRACEVFORK"	},
+#endif
+#ifdef PTRACE_O_TRACECLONE
+	{ PTRACE_O_TRACECLONE,	"PTRACE_O_TRACECLONE"	},
+#endif
+#ifdef PTRACE_O_TRACEEXEC
+	{ PTRACE_O_TRACEEXEC,	"PTRACE_O_TRACEEXEC"	},
+#endif
+#ifdef PTRACE_O_TRACEVFORKDONE
+	{ PTRACE_O_TRACEVFORKDONE,"PTRACE_O_TRACEVFORKDONE"},
+#endif
+#ifdef PTRACE_O_TRACEEXIT
+	{ PTRACE_O_TRACEEXIT,	"PTRACE_O_TRACEEXIT"	},
+#endif
+	{ 0,			NULL			},
+};
+#endif
+#endif
+
+#ifndef FREEBSD
 const struct xlat struct_user_offsets[] = {
 #ifdef LINUX
 #if defined(S390) || defined(S390X)
@@ -3192,6 +3232,30 @@
 		case PTRACE_DETACH:
 			printsignal(tcp->u_arg[3]);
 			break;
+#ifdef PTRACE_SETOPTIONS
+		case PTRACE_SETOPTIONS:
+			printflags(ptrace_setoptions_flags, tcp->u_arg[3], "PTRACE_O_???");
+			break;
+#endif
+#ifdef PTRACE_SETSIGINFO
+		case PTRACE_SETSIGINFO: {
+			siginfo_t si;
+			if (!tcp->u_arg[3])
+				tprintf("NULL");
+			else if (syserror(tcp))
+				tprintf("%#lx", tcp->u_arg[3]);
+			else if (umove(tcp, tcp->u_arg[3], &si) < 0)
+				tprintf("{???}");
+			else
+				printsiginfo(&si, verbose(tcp));
+			break;
+		}
+#endif
+#ifdef PTRACE_GETSIGINFO
+		case PTRACE_GETSIGINFO:
+			/* Don't print anything, do it at syscall return. */
+			break;
+#endif
 		default:
 			tprintf("%#lx", tcp->u_arg[3]);
 			break;
@@ -3207,6 +3271,20 @@
 			printnum(tcp, tcp->u_arg[3], "%#lx");
 			break;
 #endif
+#ifdef PTRACE_GETSIGINFO
+		case PTRACE_GETSIGINFO: {
+			siginfo_t si;
+			if (!tcp->u_arg[3])
+				tprintf("NULL");
+			else if (syserror(tcp))
+				tprintf("%#lx", tcp->u_arg[3]);
+			else if (umove(tcp, tcp->u_arg[3], &si) < 0)
+				tprintf("{???}");
+			else
+				printsiginfo(&si, verbose(tcp));
+			break;
+		}
+#endif
 		}
 	}
 #endif /* LINUX */
diff --git a/signal.c b/signal.c
index 05ab30a..963bf0f 100644
--- a/signal.c
+++ b/signal.c
@@ -1967,7 +1967,7 @@
 		if (umove(tcp, tcp->u_arg[2], &si) < 0)
 			tprintf("%#lx", tcp->u_arg[2]);
 		else
-			printsiginfo(&si, verbose (tcp));
+			printsiginfo(&si, verbose(tcp));
 	}
 	return 0;
 }
@@ -1993,7 +1993,7 @@
 			if (umove(tcp, tcp->u_arg[1], &si) < 0)
 				tprintf("%#lx", tcp->u_arg[1]);
 			else
-				printsiginfo(&si, verbose (tcp));
+				printsiginfo(&si, verbose(tcp));
 			/* XXX For now */
 			tprintf(", %#lx", tcp->u_arg[2]);
 			tprintf(", %d", (int) tcp->u_arg[3]);
@@ -2011,8 +2011,6 @@
 	return 0;
 }
 
-extern const struct xlat open_mode_flags[];
-
 static int
 do_signalfd(struct tcb *tcp, int flags_arg)
 {
diff --git a/sock.c b/sock.c
index 5303fa9..670f72b 100644
--- a/sock.c
+++ b/sock.c
@@ -47,8 +47,6 @@
 #endif
 #include <net/if.h>
 
-extern const struct xlat addrfams[];
-
 static const struct xlat iffflags[] = {
 	{ IFF_UP,		"IFF_UP"		},
 	{ IFF_BROADCAST,	"IFF_BROADCAST"		},
diff --git a/strace.c b/strace.c
index 989db1a..57945db 100644
--- a/strace.c
+++ b/strace.c
@@ -2525,8 +2525,10 @@
 				}
 			}
 /* Add more OSes after you verified it works for them. */
-/* PTRACE_SETOPTIONS is not a #define. PT_SETOPTIONS is. */
-#if defined LINUX && defined PT_SETOPTIONS
+/* PTRACE_SETOPTIONS may be an enum, not a #define.
+ * But sometimes we can test for it by checking PT_SETOPTIONS.
+ */
+#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
 # ifndef PTRACE_O_TRACESYSGOOD
 #  define PTRACE_O_TRACESYSGOOD 0x00000001
 # endif
@@ -2557,7 +2559,7 @@
 			goto tracing;
 		}
 
-#if defined LINUX && defined PT_SETOPTIONS
+#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
 		if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
 			/*
 			 * We told ptrace to report SIGTRAP | 0x80 on this process
diff --git a/util.c b/util.c
index f9e2b1d..763ae84 100644
--- a/util.c
+++ b/util.c
@@ -1116,7 +1116,6 @@
 			}
 			is_sun4m = strcmp(name.machine, "sun4m") == 0;
 			if (is_sun4m) {
-				extern const struct xlat struct_user_offsets[];
 				const struct xlat *x;
 
 				for (x = struct_user_offsets; x->str; x++)