Catching up on my mail-backlog, see ChangeLog for details

This commit is contained in:
Wichert Akkerman 1999-08-29 23:15:07 +00:00
parent 5a777663d5
commit 9ce1a63eb2
19 changed files with 701 additions and 99 deletions

View File

@ -34,3 +34,5 @@ porting to new systems:
Ulrich Drepper <drepper@cygnus.com>
Nate Eldredge <nate@cartsys.com>
Jakub Jelinek <jj@ultra.linux.cz>
John Hughes <john@Calva.COM>
Richard Braakman <dark@xs4all.nl>

View File

@ -1,7 +1,28 @@
Mon Aug 30 00:53:57 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
* Merge patch from Daniel Jacobowitz: KERN_JAVA_* and KERN_SECURELVL aren't
defined for all kernelversions
* Add strace-graph
Thu Aug 19 13:10:15 CEST 1999 Jakub Jelinek <jj@ultra.linux.cz>
* linux/sparc/syscall.h: Declare create_module/init_module.
* configure.in: Allow compilation in a different directory
than the source one.
* signal.c: Use asm/reg.h and struct regs instead of pt_regs
so that we don't depend on asm/ptrace.h which clashes with
glibc sys/ptrace.h.
* util.c: Likewise.
* syscall.c: Likewise.
Wed Aug 4 18:01:50 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
* Syscall 94 on Linux alpha is sys_poll
Sun Jul 25 14:38:33 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
* Merge in UnixWare patches from John Hughes <john@Calva.COM>
Thu Jul 15 23:00:32 CEST 1999 Wichert Akkerman <wakkerma@debian.org>
* Merge patch from Maciej W. Rozycki <macro@ds2.pg.gda.pl>:

View File

@ -59,6 +59,7 @@ strace: $(OBJ)
install: all
$(INSTALL_PROGRAM) strace $(bindir)/strace
$(INSTALL_PROGRAM) strace-graph $(bindir)/strace-graph
$(INSTALL_DATA) $(srcdir)/strace.1 $(man1dir)/strace$(man1ext)
clean: clean-local

View File

@ -9,4 +9,12 @@ lot of processes at once.
There is no thread support but it wouldn't be very difficult to add it.
Rick Sladkey <jrs@world.std.com>
There is currently no configure-support yet for UnixWare system. To compile
on UnixWare 2.1 you need to add the following to config.h yourself:
#define SVR4_MP 1
#define UNIXWARE 2
#define HAVE_POLLABLE_PROCFS 1
Wichert Akkerman <wakkerma@debian.org>

1
TODO
View File

@ -5,6 +5,7 @@ replace printargs with something that reads a configuration-file
rename functions that are used for general things:
sys_chdir -> general_1stringarg
generate syscallent.h from the kernel sources
add IPv6 support
-- old entries from jrs

View File

@ -125,9 +125,12 @@ AC_TYPE_GETGROUPS
AC_HEADER_MAJOR
AC_SIG_ATOMIC_T
AC_CHECK_LIB(nsl, main)
AC_CHECK_FUNCS(sigaction strerror strsignal pread sys_siglist _sys_siglist getdents mctl putpmsg prctl sendmsg)
AC_CHECK_FUNCS(sigaction strerror strsignal pread sys_siglist _sys_siglist getdents mctl putpmsg prctl sendmsg inet_ntop)
AC_CHECK_HEADERS(sys/reg.h sys/filio.h sys/acl.h sys/asynch.h sys/door.h sys/stream.h sys/tiuser.h sys/sysconfig.h asm/sigcontext.h ioctls.h sys/ioctl.h sys/ptrace.h termio.h)
AC_DECL_SYS_ERRLIST
AC_DECL_SYS_SIGLIST
AC_DECL__SYS_SIGLIST
if test ! -d $osarch; then
mkdir -p $osarch
fi
AC_OUTPUT(Makefile $osarch/Makefile)

44
defs.h
View File

@ -77,6 +77,9 @@
#ifdef SVR4
#include <sys/procfs.h>
#ifdef SVR4_MP
#include <sys/uio.h>
#endif
#else /* !SVR4 */
#if defined(LINUXSPARC) && defined(__GLIBC__)
#include <sys/ptrace.h>
@ -131,6 +134,41 @@ extern int ptrace();
#define SUPPORTED_PERSONALITIES 2
#endif /* LINUXSPARC */
#ifdef SVR4
#ifdef SVR4_MP
extern int mp_ioctl (int f, int c, void *a, int s);
#define IOCTL(f,c,a) mp_ioctl (f, c, a, sizeof *a)
#define IOCTL_STATUS(t) \
pread (t->pfd_stat, &t->status, sizeof t->status, 0)
#define IOCTL_WSTOP(t) \
(IOCTL (t->pfd, PCWSTOP, NULL) < 0 ? -1 : \
IOCTL_STATUS (t))
#define PR_WHY pr_lwp.pr_why
#define PR_WHAT pr_lwp.pr_what
#define PR_REG pr_lwp.pr_context.uc_mcontext.gregs
#define PR_FLAGS pr_lwp.pr_flags
#define PIOCSTIP PCSTOP
#define PIOCSET PCSET
#define PIOCRESET PCRESET
#define PIOCSTRACE PCSTRACE
#define PIOCSFAULT PCSFAULT
#define PIOCWSTOP PCWSTOP
#define PIOCSTOP PCSTOP
#define PIOCSENTRY PCSENTRY
#define PIOCSEXIT PCSEXIT
#define PIOCRUN PCRUN
#else
#define IOCTL ioctl
#define IOCTL_STATUS(t) ioctl (t->pfd, PIOCSTATUS, &t->status)
#define IOCTL_WSTOP(t) ioctl (t->pfd, PIOCWSTOP, &t->status)
#define PR_WHY pr_why
#define PR_WHAT pr_what
#define PR_REG pr_reg
#define PR_FLAGS pr_flags
#endif
#endif
/* Trace Control Block */
struct tcb {
short flags; /* See below for TCB_ values */
@ -154,8 +192,14 @@ struct tcb {
long inst[2]; /* Instructions on above */
int pfd; /* proc file descriptor */
#ifdef SVR4
#ifdef SVR4_MP
int pfd_stat;
int pfd_as;
pstatus_t status;
#else
prstatus_t status; /* procfs status structure */
#endif
#endif
};
/* TCB flags */

10
io.c
View File

@ -152,9 +152,14 @@ struct tcb *tcp;
tprintf("%#lx", tcp->u_arg[1]);
else
printstr(tcp, tcp->u_arg[1], tcp->u_rval);
#if UNIXWARE
/* off_t is signed int */
tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]);
#else
tprintf(", %lu, %llu", tcp->u_arg[2],
(((unsigned long long) tcp->u_arg[4]) << 32
| tcp->u_arg[3]));
#endif
}
return 0;
}
@ -166,9 +171,14 @@ struct tcb *tcp;
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
#if UNIXWARE
/* off_t is signed int */
tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]);
#else
tprintf(", %lu, %llu", tcp->u_arg[2],
(((unsigned long long) tcp->u_arg[4]) << 32
| tcp->u_arg[3]));
#endif
}
return 0;
}

View File

@ -108,8 +108,10 @@ long code, arg;
#endif /* !LINUX */
return sock_ioctl(tcp, code, arg);
#ifdef SVR4
#ifndef SVR4_MP
case 'q':
return proc_ioctl(tcp, code, arg);
#endif
#endif /* SVR4 */
#ifdef HAVE_SYS_STREAM_H
case 'S':

View File

@ -99,6 +99,7 @@ int sys_sigaltstack(), sys_rt_sigprocmask(), sys_rt_sigaction();
int sys_rt_sigpending(), sys_rt_sigsuspend(), sys_rt_sigqueueinfo();
int sys_rt_sigtimedwait(), sys_prctl(), sys_poll();
int sys_sendfile(), sys_query_module(), sys_capget(), sys_capset();
int sys_create_module(), sys_init_module();
int sys_umask(); /* XXX */

17
net.c
View File

@ -311,6 +311,10 @@ long addr;
struct sockaddr sa;
struct sockaddr_in *sin = (struct sockaddr_in *) &sa;
struct sockaddr_un sau;
#ifdef HAVE_INET_NTOP
struct sockaddr_in6 sa6;
char string_addr[100];
#endif
#ifdef LINUX
struct sockaddr_ipx sipx;
#endif
@ -340,6 +344,19 @@ long addr;
tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")}",
ntohs(sin->sin_port), inet_ntoa(sin->sin_addr));
break;
#ifdef HAVE_INET_NTOP
case AF_INET6:
if (umove(tcp, addr, &sa6) < 0)
tprintf("{sin6_family=AF_INET6, ...}");
else
{
tprintf("{sin6_family=AF_INET6, ");
inet_ntop(AF_INET6, &sa6.sin6_addr, string_addr, sizeof(string_addr));
tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=htonl(%u)",
ntohs(sa6.sin6_port), string_addr, ntohl(sa6.sin6_flowinfo));
}
break;
#endif
#if defined(AF_IPX) && defined(linux)
case AF_IPX:
if (umove(tcp, addr, &sipx)<0)

2
proc.c
View File

@ -30,6 +30,7 @@
#include "defs.h"
#ifdef SVR4
#ifndef SVR4_MP
static struct xlat proc_status_flags[] = {
{ PR_STOPPED, "PR_STOPPED" },
@ -182,5 +183,6 @@ int code, arg;
}
}
#endif /* SVR4_MP */
#endif /* SVR4 */

View File

@ -54,8 +54,9 @@
#ifdef HAVE_ASM_SIGCONTEXT_H
#include <asm/sigcontext.h>
#ifdef SPARC
#include <asm/reg.h>
typedef struct {
struct pt_regs si_regs;
struct regs si_regs;
int si_mask;
} m_siginfo_t;
#endif
@ -227,6 +228,7 @@ int sig;
}
}
#ifndef UNIXWARE
static void
long_to_sigset(l, s)
long l;
@ -235,6 +237,7 @@ sigset_t *s;
sigemptyset(s);
*(long *)s = l;
}
#endif
static int
copy_sigset_len(tcp, addr, s, len)
@ -778,18 +781,16 @@ struct tcb *tcp;
#else
#ifdef SPARC
long i1;
struct pt_regs regs;
struct regs regs;
m_siginfo_t si;
if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
perror("sigreturn: PTRACE_GETREGS ");
return 0;
}
memmove (&regs.u_regs [1], &regs.u_regs [0],
sizeof (regs.u_regs) - sizeof (regs.u_regs [0]));
if(entering(tcp)) {
tcp->u_arg[0] = 0;
i1 = regs.u_regs[UREG_I1];
i1 = regs.r_o1;
if(umove(tcp, i1, &si) < 0) {
perror("sigreturn: umove ");
return 0;

317
strace-graph Executable file
View File

@ -0,0 +1,317 @@
#!/usr/bin/perl
# This script processes strace -f output. It displays a graph of invoked
# subprocesses, and is useful for finding out what complex commands do.
# You will probably want to invoke strace with -q as well, and with
# -s 100 to get complete filenames.
# The script can also handle the output with strace -t, -tt, or -ttt.
# It will add elapsed time for each process in that case.
# This script is Copyright (C) 1998 by Richard Braakman <dark@xs4all.nl>.
# It is distributed under the GNU General Public License version 2 or,
# at your option, any later version published by the Free Software Foundation.
my %unfinished;
# Scales for strace slowdown. Make configurable!
my $scale_factor = 3.5;
while (<>) {
my ($pid, $call, $args, $result, $time);
chop;
s/^(\d+)\s+//;
$pid = $1;
if (s/^(\d\d):(\d\d):(\d\d)(?:\.(\d\d\d\d\d\d))? //) {
$time = $1 * 3600 + $2 * 60 + $3;
if (defined $4) {
$time = $time + $4 / 1000000;
$floatform = 1;
}
} elsif (s/^(\d+)\.(\d\d\d\d\d\d) //) {
$time = $1 + ($2 / 1000000);
$floatform = 1;
}
if (s/ <unfinished ...>$//) {
$unfinished{$pid} = $_;
next;
}
if (s/^<... \S+ resumed> //) {
unless (exists $unfinished{$pid}) {
print STDERR "$0: $ARGV: cannot find start of resumed call on line $.";
next;
}
$_ = $unfinished{$pid} . $_;
delete $unfinished{$pid};
}
if (/^--- SIG(\S+) \(.*\) ---$/) {
# $pid received signal $1
# currently we don't do anything with this
next;
}
if (/^\+\+\+ killed by SIG(\S+) \+\+\+$/) {
# $pid received signal $1
handle_killed($pid, $time);
next;
}
($call, $args, $result) = /(\S+)\((.*)\)\s+= (.*)$/;
unless (defined $result) {
print STDERR "$0: $ARGV: $.: cannot parse line.\n";
next;
}
handle_trace($pid, $call, $args, $result, $time);
}
display_trace();
exit 0;
sub parse_str {
my ($in) = @_;
my $result = "";
while (1) {
if ($in =~ s/^\\(.)//) {
$result .= $1;
} elsif ($in =~ s/^\"//) {
if ($in =~ s/^\.\.\.//) {
return ("$result...", $in);
}
return ($result, $in);
} elsif ($in =~ s/([^\\\"]*)//) {
$result .= $1;
} else {
return (undef, $in);
}
}
}
sub parse_one {
my ($in) = @_;
if ($in =~ s/^\"//) {
($tmp, $in) = parse_str($in);
if (not defined $tmp) {
print STDERR "$0: $ARGV: $.: cannot parse string.\n";
return (undef, $in);
}
return ($tmp, $in);
} elsif ($in =~ s/^0x(\x+)//) {
return (hex $1, $in);
} elsif ($in =~ s/^(\d+)//) {
return (int $1, $in);
} else {
print STDERR "$0: $ARGV: $.: unrecognized element.\n";
return (undef, $in);
}
}
sub parseargs {
my ($in) = @_;
my @args = ();
my $tmp;
while (length $in) {
if ($in =~ s/^\[//) {
my @subarr = ();
if ($in =~ s,^/\* (\d+) vars \*/\],,) {
push @args, $1;
} else {
while ($in !~ s/^\]//) {
($tmp, $in) = parse_one($in);
defined $tmp or return undef;
push @subarr, $tmp;
unless ($in =~ /^\]/ or $in =~ s/^, //) {
print STDERR "$0: $ARGV: $.: missing comma in array.\n";
return undef;
}
if ($in =~ s/^\.\.\.//) {
push @subarr, "...";
}
}
push @args, \@subarr;
}
} elsif ($in =~ s/^\{//) {
my %subhash = ();
while ($in !~ s/^\}//) {
my $key;
unless ($in =~ s/^(\w+)=//) {
print STDERR "$0: $ARGV: $.: struct field expected.\n";
return undef;
}
$key = $1;
($tmp, $in) = parse_one($in);
defined $tmp or return undef;
$subhash{$key} = $tmp;
unless ($in =~ s/, //) {
print STDERR "$0: $ARGV: $.: missing comma in struct.\n";
return undef;
}
}
push @args, \%subhash;
} else {
($tmp, $in) = parse_one($in);
defined $tmp or return undef;
push @args, $tmp;
}
unless (length($in) == 0 or $in =~ s/^, //) {
print STDERR "$0: $ARGV: $.: missing comma.\n";
return undef;
}
}
return @args;
}
my $depth = "";
# process info, indexed by pid.
# fields:
# parent pid number
# seq forks and execs for this pid, in sequence (array)
# filename and argv (from latest exec)
# basename (derived from filename)
# argv[0] is modified to add the basename if it differs from the 0th argument.
my %pr;
sub handle_trace {
my ($pid, $call, $args, $result, $time) = @_;
my $p;
if (defined $time and not defined $pr{$pid}{start}) {
$pr{$pid}{start} = $time;
}
if ($call eq 'execve') {
return if $result != 0;
my ($filename, $argv) = parseargs($args);
($basename) = $filename =~ m/([^\/]*)$/;
if ($basename ne $$argv[0]) {
$$argv[0] = "$basename($$argv[0])";
}
my $seq = $pr{$pid}{seq};
$seq = [] if not defined $seq;
push @$seq, ['EXEC', $filename, $argv];
$pr{$pid}{seq} = $seq;
} elsif ($call eq 'fork') {
return if $result == 0;
my $seq = $pr{$pid}{seq};
$seq = [] if not defined $seq;
push @$seq, ['FORK', $result];
$pr{$pid}{seq} = $seq;
$pr{$result}{parent} = $pid;
} elsif ($call eq '_exit') {
$pr{$pid}{end} = $time if defined $time;
}
}
sub handle_killed {
my ($pid, $time) = @_;
$pr{$pid}{end} = $time if defined $time;
}
sub straight_seq {
my ($pid) = @_;
my $seq = $pr{$pid}{seq};
for $elem (@$seq) {
if ($$elem[0] eq 'EXEC') {
my $argv = $$elem[2];
print "$$elem[0] $$elem[1] @$argv\n";
} elsif ($$elem[0] eq 'FORK') {
print "$$elem[0] $$elem[1]\n";
} else {
print "$$elem[0]\n";
}
}
}
sub first_exec {
my ($pid) = @_;
my $seq = $pr{$pid}{seq};
for $elem (@$seq) {
if ($$elem[0] eq 'EXEC') {
return $elem;
}
}
return undef;
}
sub display_pid_trace {
my ($pid, $lead) = @_;
my $i = 0;
my @seq = @{$pr{$pid}{seq}};
my $elapsed;
if (not defined first_exec($pid)) {
unshift @seq, ['EXEC', '', ['(anon)'] ];
}
if (defined $pr{$pid}{start} and defined $pr{$pid}{end}) {
$elapsed = $pr{$pid}{end} - $pr{$pid}{start};
$elapsed /= $scale_factor;
if ($floatform) {
$elapsed = sprintf("%0.02f", $elapsed);
} else {
$elapsed = int $elapsed;
}
}
for $elem (@seq) {
$i++;
if ($$elem[0] eq 'EXEC') {
my $argv = $$elem[2];
if (defined $elapsed) {
print "$lead [$elapsed] @$argv\n";
undef $elapsed;
} else {
print "$lead @$argv\n";
}
} elsif ($$elem[0] eq 'FORK') {
if ($i == 1) {
if ($lead =~ /-$/) {
display_pid_trace($$elem[1], "$lead--+--");
} else {
display_pid_trace($$elem[1], "$lead +--");
}
} elsif ($i == @seq) {
display_pid_trace($$elem[1], "$lead `--");
} else {
display_pid_trace($$elem[1], "$lead +--");
}
}
if ($i == 1) {
$lead =~ s/\`--/ /g;
$lead =~ s/-/ /g;
$lead =~ s/\+/|/g;
}
}
}
sub display_trace {
my ($startpid) = @_;
$startpid = (keys %pr)[0];
while ($pr{$startpid}{parent}) {
$startpid = $pr{$startpid}{parent};
}
display_pid_trace($startpid, "");
}

174
strace.c
View File

@ -45,6 +45,9 @@
#ifdef SVR4
#include <sys/stropts.h>
#include <poll.h>
#ifdef SVR4_MP
#include <sys/uio.h>
#endif
#endif
int debug = 0, followfork = 0, followvfork = 0, interactive = 0;
@ -105,6 +108,11 @@ static int proc_poll_pipe[2] = { -1, -1 };
#endif /* !HAVE_POLLABLE_PROCFS */
#ifdef SVR4_MP
#define POLLWANT POLLWRNORM
#else
#define POLLWANT POLLPRI
#endif
#endif /* SVR4 */
static void
@ -559,7 +567,6 @@ int pid;
}
#ifdef SVR4
int
proc_open(tcp, attaching)
struct tcb *tcp;
@ -570,39 +577,17 @@ int attaching;
sysset_t sc_enter, sc_exit;
sigset_t signals;
fltset_t faults;
#ifndef MIPS
prrun_t run;
#endif
#ifndef HAVE_POLLABLE_PROCFS
static int last_pfd;
#endif
/* Open the process pseudo-file in /proc. */
sprintf(proc, "/proc/%d", tcp->pid);
if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
#ifdef SVR4_MP
/* Open the process pseudo-files in /proc. */
sprintf(proc, "/proc/%d/ctl", tcp->pid);
if ((tcp->pfd = open(proc, O_WRONLY|O_EXCL)) < 0) {
perror("strace: open(\"/proc/...\", ...)");
return -1;
}
rebuild_pollv();
if (!attaching) {
/*
* Wait for the child to pause. Because of a race
* condition we have to poll for the event.
*/
for (;;) {
if (ioctl(tcp->pfd, PIOCSTATUS, &tcp->status) < 0) {
perror("strace: PIOCSTATUS");
return -1;
}
if (tcp->status.pr_flags & PR_ASLEEP)
break;
}
}
/* Stop the process so that we own the stop. */
if (ioctl(tcp->pfd, PIOCSTOP, &tcp->status) < 0) {
perror("strace: PIOCSTOP");
return -1;
}
if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
perror("F_GETFD");
return -1;
@ -611,16 +596,78 @@ int attaching;
perror("F_SETFD");
return -1;
}
sprintf(proc, "/proc/%d/status", tcp->pid);
if ((tcp->pfd_stat = open(proc, O_RDONLY|O_EXCL)) < 0) {
perror("strace: open(\"/proc/...\", ...)");
return -1;
}
if ((arg = fcntl(tcp->pfd_stat, F_GETFD)) < 0) {
perror("F_GETFD");
return -1;
}
if (fcntl(tcp->pfd_stat, F_SETFD, arg|FD_CLOEXEC) < 0) {
perror("F_SETFD");
return -1;
}
sprintf(proc, "/proc/%d/as", tcp->pid);
if ((tcp->pfd_as = open(proc, O_RDONLY|O_EXCL)) < 0) {
perror("strace: open(\"/proc/...\", ...)");
return -1;
}
if ((arg = fcntl(tcp->pfd_as, F_GETFD)) < 0) {
perror("F_GETFD");
return -1;
}
if (fcntl(tcp->pfd_as, F_SETFD, arg|FD_CLOEXEC) < 0) {
perror("F_SETFD");
return -1;
}
#else
/* Open the process pseudo-file in /proc. */
sprintf(proc, "/proc/%d", tcp->pid);
if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
perror("strace: open(\"/proc/...\", ...)");
return -1;
}
if ((arg = fcntl(tcp->pfd, F_GETFD)) < 0) {
perror("F_GETFD");
return -1;
}
if (fcntl(tcp->pfd, F_SETFD, arg|FD_CLOEXEC) < 0) {
perror("F_SETFD");
return -1;
}
#endif
rebuild_pollv();
if (!attaching) {
/*
* Wait for the child to pause. Because of a race
* condition we have to poll for the event.
*/
for (;;) {
if (IOCTL_STATUS (tcp) < 0) {
perror("strace: PIOCSTATUS");
return -1;
}
if (tcp->status.PR_FLAGS & PR_ASLEEP)
break;
}
}
/* Stop the process so that we own the stop. */
if (IOCTL(tcp->pfd, PIOCSTOP, NULL) < 0) {
perror("strace: PIOCSTOP");
return -1;
}
#ifdef PIOCSET
/* Set Run-on-Last-Close. */
arg = PR_RLC;
if (ioctl(tcp->pfd, PIOCSET, &arg) < 0) {
if (IOCTL(tcp->pfd, PIOCSET, &arg) < 0) {
perror("PIOCSET PR_RLC");
return -1;
}
/* Set or Reset Inherit-on-Fork. */
arg = PR_FORK;
if (ioctl(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
if (IOCTL(tcp->pfd, followfork ? PIOCSET : PIOCRESET, &arg) < 0) {
perror("PIOC{SET,RESET} PR_FORK");
return -1;
}
@ -636,25 +683,25 @@ int attaching;
#endif /* !PIOCSET */
/* Enable all syscall entries. */
prfillset(&sc_enter);
if (ioctl(tcp->pfd, PIOCSENTRY, &sc_enter) < 0) {
if (IOCTL(tcp->pfd, PIOCSENTRY, &sc_enter) < 0) {
perror("PIOCSENTRY");
return -1;
}
/* Enable all syscall exits. */
prfillset(&sc_exit);
if (ioctl(tcp->pfd, PIOCSEXIT, &sc_exit) < 0) {
if (IOCTL(tcp->pfd, PIOCSEXIT, &sc_exit) < 0) {
perror("PIOSEXIT");
return -1;
}
/* Enable all signals. */
prfillset(&signals);
if (ioctl(tcp->pfd, PIOCSTRACE, &signals) < 0) {
if (IOCTL(tcp->pfd, PIOCSTRACE, &signals) < 0) {
perror("PIOCSTRACE");
return -1;
}
/* Enable all faults. */
prfillset(&faults);
if (ioctl(tcp->pfd, PIOCSFAULT, &faults) < 0) {
if (IOCTL(tcp->pfd, PIOCSFAULT, &faults) < 0) {
perror("PIOCSFAULT");
return -1;
}
@ -667,29 +714,30 @@ int attaching;
kill(tcp->pid, SIGINT);
#else /* !MIPS */
/* The child is in a pause(), abort it. */
run.pr_flags = PRSABORT;
if (ioctl(tcp->pfd, PIOCRUN, &run) < 0) {
arg = PRSABORT;
if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
perror("PIOCRUN");
return -1;
}
#endif /* !MIPS */
for (;;) {
/* Wait for the child to do something. */
if (ioctl(tcp->pfd, PIOCWSTOP, &tcp->status) < 0) {
if (IOCTL_WSTOP (tcp) < 0) {
perror("PIOCWSTOP");
return -1;
}
if (tcp->status.pr_why == PR_SYSENTRY) {
if (tcp->status.PR_WHY == PR_SYSENTRY) {
#ifdef HAVE_PR_SYSCALL
int scno = tcp->status.pr_syscall;
#else /* !HAVE_PR_SYSCALL */
int scno = tcp->status.pr_what;
int scno = tcp->status.PR_WHAT;
#endif /* !HAVE_PR_SYSCALL */
if (scno == SYS_execve)
break;
}
/* Set it running: maybe execve will be next. */
if (ioctl(tcp->pfd, PIOCRUN, NULL) < 0) {
arg = 0;
if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
perror("PIOCRUN");
return -1;
}
@ -1012,7 +1060,7 @@ rebuild_pollv()
if (!(tcp->flags & TCB_INUSE))
continue;
pollv[j].fd = tcp->pfd;
pollv[j].events = POLLPRI;
pollv[j].events = POLLWANT;
j++;
}
if (j != nprocs) {
@ -1126,7 +1174,8 @@ int pfd;
pollinfo.fd = pfd;
pollinfo.pid = getpid();
for (;;) {
if (ioctl(pfd, PIOCWSTOP, NULL) < 0) {
if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
{
switch (errno) {
case EINTR:
continue;
@ -1142,7 +1191,7 @@ int pfd;
write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
_exit(0);
}
pollinfo.revents = POLLPRI;
pollinfo.revents = POLLWANT;
write(proc_poll_pipe[1], &pollinfo, sizeof(pollinfo));
sigsuspend(&empty_set);
}
@ -1159,7 +1208,7 @@ choose_pfd()
static int last;
if (followfork < 2 &&
last < nprocs && (pollv[last].revents & POLLPRI)) {
last < nprocs && (pollv[last].revents & POLLWANT)) {
/*
* The previous process is ready to run again. We'll
* let it do so if it is currently in a syscall. This
@ -1182,7 +1231,7 @@ choose_pfd()
droptcb(tcp);
return -1;
}
if (pollv[j].revents & POLLPRI) {
if (pollv[j].revents & POLLWANT) {
last = j;
return pollv[j].fd;
}
@ -1198,6 +1247,7 @@ trace()
int pfd;
int what;
int ioctl_result = 0, ioctl_errno = 0;
long arg;
for (;;) {
if (interactive)
@ -1249,8 +1299,7 @@ trace()
}
/* Get the status of the process. */
if (!interrupted) {
ioctl_result = ioctl(tcp->pfd, PIOCWSTOP,
&tcp->status);
ioctl_result = IOCTL_WSTOP (tcp);
ioctl_errno = errno;
#ifndef HAVE_POLLABLE_PROCFS
if (proc_poll_pipe[0] != -1) {
@ -1297,11 +1346,11 @@ trace()
tcp->stime = stime;
}
what = tcp->status.pr_what;
switch (tcp->status.pr_why) {
what = tcp->status.PR_WHAT;
switch (tcp->status.PR_WHY) {
case PR_REQUESTED:
if (tcp->status.pr_flags & PR_ASLEEP) {
tcp->status.pr_why = PR_SYSENTRY;
if (tcp->status.PR_FLAGS & PR_ASLEEP) {
tcp->status.PR_WHY = PR_SYSENTRY;
if (trace_syscall(tcp) < 0) {
fprintf(stderr, "syscall trouble\n");
exit(1);
@ -1331,11 +1380,12 @@ trace()
}
break;
default:
fprintf(stderr, "odd stop %d\n", tcp->status.pr_why);
fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
exit(1);
break;
}
if (ioctl(tcp->pfd, PIOCRUN, NULL) < 0) {
arg = 0;
if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
perror("PIOCRUN");
exit(1);
}
@ -1656,3 +1706,23 @@ struct tcb *tcp;
tprintf("\n");
tcp_last = NULL;
}
#ifdef SVR4_MP
int mp_ioctl (int fd, int cmd, void *arg, int size) {
struct iovec iov[2];
int n = 1;
iov[0].iov_base = &cmd;
iov[0].iov_len = sizeof cmd;
if (arg) {
++n;
iov[1].iov_base = arg;
iov[1].iov_len = size;
}
return writev (fd, iov, n);
}
#endif

View File

@ -221,7 +221,7 @@
{ -1, 0, sys_swapctl, "swapctl" }, /* 167 */
{ -1, 0, sys_getcontext, "getcontext" }, /* 168 */
{ -1, 0, sys_setcontext, "setcontext" }, /* 169 */
{ -1, TP, sys_waitsys, "waitid" }, /* 170 */
{ -1, TP, sys_waitid, "waitid" }, /* 170 */
{ -1, TS, sys_sigstack, "sigstack" }, /* 171 */
{ -1, TS, sys_sigaltstack, "sigaltstack" }, /* 172 */
{ -1, TS, sys_sigsendset, "sigsendset" }, /* 173 */
@ -322,7 +322,11 @@
{ -1, 0, sys_fstatvfs, "fstatvfs" }, /* 104 */
{ -1, 0, printargs, "SYS_105" }, /* 105 */
{ -1, 0, sys_nfssys, "nfssys" }, /* 106 */
#if UNIXWARE
{ -1, TP, sys_waitsys, "waitsys" }, /* 107 */
#else
{ -1, TP, sys_waitid, "waitid" }, /* 107 */
#endif
{ -1, 0, sys_sigsendsys, "sigsendsys" }, /* 108 */
{ -1, 0, sys_hrtsys, "hrtsys" }, /* 109 */
{ -1, 0, sys_acancel, "acancel" }, /* 110 */
@ -356,6 +360,77 @@
{ -1, 0, sys_adjtime, "adjtime" }, /* 138 */
{ -1, 0, sys_sysinfo, "sysinfo" }, /* 139 */
{ -1, 0, printargs, "SYS_140" }, /* 140 */
#if UNIXWARE >= 2
{ -1, 0, sys_seteuid, "seteuid" }, /* 141 */
{ -1, 0, printargs, "SYS_142" }, /* 142 */
{ -1, 0, printargs, "keyctl" }, /* 143 */
{ -1, 0, printargs, "secsys" }, /* 144 */
{ -1, 0, printargs, "filepriv" }, /* 145 */
{ -1, 0, printargs, "procpriv" }, /* 146 */
{ -1, 0, printargs, "devstat" }, /* 147 */
{ -1, 0, printargs, "aclipc" }, /* 148 */
{ -1, 0, printargs, "fdevstat" }, /* 149 */
{ -1, 0, printargs, "flvlfile" }, /* 150 */
{ -1, 0, printargs, "lvlfile" }, /* 151 */
{ -1, 0, printargs, "SYS_152" }, /* 152 */
{ -1, 0, printargs, "lvlequal" }, /* 153 */
{ -1, 0, printargs, "lvlproc" }, /* 154 */
{ -1, 0, printargs, "SYS_155" }, /* 155 */
{ -1, 0, printargs, "lvlipc" }, /* 156 */
{ -1, 0, printargs, "acl" }, /* 157 */
{ -1, 0, printargs, "auditevt" }, /* 158 */
{ -1, 0, printargs, "auditctl" }, /* 159 */
{ -1, 0, printargs, "auditdmp" }, /* 160 */
{ -1, 0, printargs, "auditlog" }, /* 161 */
{ -1, 0, printargs, "auditbuf" }, /* 162 */
{ -1, 0, printargs, "lvldom" }, /* 163 */
{ -1, 0, printargs, "lvlvfs" }, /* 164 */
{ -1, 0, printargs, "mkmld" }, /* 165 */
{ -1, 0, printargs, "mldmode" }, /* 166 */
{ -1, 0, printargs, "secadvise" }, /* 167 */
{ -1, 0, printargs, "online" }, /* 168 */
{ -1, 0, sys_setitimer, "setitimer" }, /* 169 */
{ -1, 0, sys_getitimer, "getitimer" }, /* 170 */
{ -1, 0, sys_gettimeofday, "gettimeofday" }, /* 171 */
{ -1, 0, printargs, "settimeofday" }, /* 172 */
{ -1, 0, sys_lwp_create, "lwpcreate" }, /* 173 */
{ -1, 0, sys_lwp_exit, "lwpexit" }, /* 174 */
{ -1, 0, sys_lwp_wait, "lwpwait" }, /* 175 */
{ -1, 0, sys_lwp_self, "lwpself" }, /* 176 */
{ -1, 0, printargs, "lwpinfo" }, /* 177 */
{ -1, 0, printargs, "lwpprivate" }, /* 178 */
{ -1, 0, sys_processor_bind, "processor_bind"}, /* 179 */
{ -1, 0, printargs, "processor_exbind"}, /* 180 */
{ -1, 0, printargs, "SYS_181" }, /* 181 */
{ -1, 0, printargs, "SYS_182" }, /* 182 */
{ -1, 0, printargs, "prepblock" }, /* 183 */
{ -1, 0, printargs, "block" }, /* 184 */
{ -1, 0, printargs, "rdblock" }, /* 185 */
{ -1, 0, printargs, "unblock" }, /* 186 */
{ -1, 0, printargs, "cancelblock" }, /* 187 */
{ -1, 0, printargs, "SYS_188" }, /* 188 */
{ -1, 0, sys_pread, "pread" }, /* 189 */
{ -1, 0, sys_pwrite, "pwrite" }, /* 190 */
{ -1, 0, printargs, "truncate" }, /* 191 */
{ -1, 0, printargs, "ftruncate" }, /* 192 */
{ -1, 0, printargs, "lwpkill" }, /* 193 */
{ -1, 0, printargs, "sigwait" }, /* 194 */
{ -1, 0, printargs, "fork1" }, /* 195 */
{ -1, 0, printargs, "forkall" }, /* 196 */
{ -1, 0, printargs, "modload" }, /* 197 */
{ -1, 0, printargs, "moduload" }, /* 198 */
{ -1, 0, printargs, "modpath" }, /* 199 */
{ -1, 0, printargs, "modstat" }, /* 200 */
{ -1, 0, printargs, "modadm" }, /* 201 */
{ -1, 0, printargs, "getksym" }, /* 202 */
{ -1, 0, printargs, "lwpsuspend" }, /* 203 */
{ -1, 0, printargs, "lwpcontinue" }, /* 204 */
{ -1, 0, printargs, "priocntllst" }, /* 205 */
{ -1, 0, printargs, "sleep" }, /* 206 */
{ -1, 0, printargs, "lwp_sema_wait" }, /* 207 */
{ -1, 0, printargs, "lwp_sema_post" }, /* 208 */
{ -1, 0, printargs, "lwp_sema_trywait"}, /* 209 */
#else
{ -1, 0, sys_seteuid, "seteuid" }, /* 141 */
{ -1, 0, sys_vtrace, "vtrace" }, /* 142 */
{ -1, TP, sys_fork1, "fork1" }, /* 143 */
@ -437,6 +512,7 @@
{ -1, 0, printargs, "SYS_207" }, /* 207 */
{ -1, 0, printargs, "SYS_208" }, /* 208 */
{ -1, 0, printargs, "SYS_209" }, /* 209 */
#endif
{ -1, 0, printargs, "SYS_210" }, /* 210 */
{ -1, 0, printargs, "SYS_211" }, /* 211 */
{ -1, 0, printargs, "SYS_212" }, /* 212 */

View File

@ -38,6 +38,10 @@
#include <sys/syscall.h>
#include <sys/param.h>
#if defined(LINUX) && defined(SPARC)
#include <asm/reg.h>
#endif
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
# define PTRACE_PEEKUSR PTRACE_PEEKUSER
@ -579,7 +583,7 @@ struct tcb *tcp;
long r0;
long a3;
#elif defined (SPARC)
struct pt_regs regs;
struct regs regs;
unsigned long trap;
#endif
#endif /* LINUX */
@ -650,14 +654,11 @@ struct tcb *tcp;
if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
return -1;
memmove (&regs.u_regs [1], &regs.u_regs [0],
sizeof (regs.u_regs) - sizeof (regs.u_regs [0]));
/* If we are entering, then disassemble the syscall trap. */
if (!(tcp->flags & TCB_INSYSCALL)) {
/* Retrieve the syscall trap instruction. */
errno = 0;
trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.pc,0);
trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
if (errno)
return -1;
@ -693,7 +694,7 @@ struct tcb *tcp;
tcp->flags &= ~TCB_WAITEXECVE;
return 0;
}
fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.pc);
fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
return -1;
}
@ -701,10 +702,10 @@ struct tcb *tcp;
if (trap == 0x91d02027)
scno = 156;
else
scno = regs.u_regs[UREG_G1];
scno = regs.r_g1;
if (scno == 0) {
scno = regs.u_regs[UREG_I0];
memmove (&regs.u_regs[UREG_I0], &regs.u_regs[UREG_I1], 7*sizeof(regs.u_regs[0]));
scno = regs.r_o0;
memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
}
}
#endif
@ -717,10 +718,10 @@ struct tcb *tcp;
#ifdef HAVE_PR_SYSCALL
scno = tcp->status.pr_syscall;
#else /* !HAVE_PR_SYSCALL */
scno = tcp->status.pr_what;
scno = tcp->status.PR_WHAT;
#endif /* !HAVE_PR_SYSCALL */
if (!(tcp->flags & TCB_INSYSCALL)) {
if (tcp->status.pr_why != PR_SYSENTRY) {
if (tcp->status.PR_WHY != PR_SYSENTRY) {
if (
scno == SYS_fork
#ifdef SYS_vfork
@ -728,9 +729,9 @@ struct tcb *tcp;
#endif /* SYS_vfork */
) {
/* We are returning in the child, fake it. */
tcp->status.pr_why = PR_SYSENTRY;
tcp->status.PR_WHY = PR_SYSENTRY;
trace_syscall(tcp);
tcp->status.pr_why = PR_SYSEXIT;
tcp->status.PR_WHY = PR_SYSEXIT;
}
else {
fprintf(stderr, "syscall: missing entry\n");
@ -739,7 +740,7 @@ struct tcb *tcp;
}
}
else {
if (tcp->status.pr_why != PR_SYSEXIT) {
if (tcp->status.PR_WHY != PR_SYSEXIT) {
fprintf(stderr, "syscall: missing exit\n");
tcp->flags &= ~TCB_INSYSCALL;
}
@ -858,12 +859,12 @@ struct tcb *tcp;
}
#else /* !ALPHA */
#ifdef SPARC
if (regs.psr & PSR_C) {
if (regs.r_psr & PSR_C) {
tcp->u_rval = -1;
u_error = regs.u_regs[UREG_I0];
u_error = regs.r_o0;
}
else {
tcp->u_rval = regs.u_regs[UREG_I0];
tcp->u_rval = regs.r_o0;
u_error = 0;
}
#endif /* SPARC */
@ -897,12 +898,12 @@ struct tcb *tcp;
#endif /* SPARC */
#ifdef I386
/* Wanna know how to kill an hour single-stepping? */
if (tcp->status.pr_reg[EFL] & 0x1) {
if (tcp->status.PR_REG[EFL] & 0x1) {
tcp->u_rval = -1;
u_error = tcp->status.pr_reg[EAX];
u_error = tcp->status.PR_REG[EAX];
}
else {
tcp->u_rval = tcp->status.pr_reg[EAX];
tcp->u_rval = tcp->status.PR_REG[EAX];
u_error = 0;
}
#endif /* I386 */
@ -1074,12 +1075,11 @@ struct tcb *tcp;
}
#elif defined (SPARC)
{
int i, offset;
int i;
offset = UREG_I0;
tcp->u_nargs = sysent[tcp->scno].nargs;
for (i = 0; i < tcp->u_nargs; i++)
tcp->u_arg[i] = regs.u_regs[offset + i];
tcp->u_arg[i] = *((&regs.r_o0) + i);
}
#else
{
@ -1141,8 +1141,12 @@ struct tcb *tcp;
if (sysent[tcp->scno].nargs != -1)
tcp->u_nargs = sysent[tcp->scno].nargs;
else
#if UNIXWARE >= 2
tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
#else
tcp->u_nargs = 5;
umoven(tcp, tcp->status.pr_reg[UESP] + 4,
#endif
umoven(tcp, tcp->status.PR_REG[UESP] + 4,
tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
#endif /* I386 */
#endif /* !HAVE_PR_SYSCALL */
@ -1292,10 +1296,10 @@ struct tcb *tcp;
#ifdef LINUX
#ifdef SPARC
struct pt_regs regs;
struct regs regs;
if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
return -1;
val = regs.u_regs[UREG_I1];
val = regs.r_o1;
#endif /* SPARC */
#endif /* LINUX */
@ -1306,13 +1310,13 @@ struct tcb *tcp;
#ifdef SVR4
#ifdef SPARC
val = tcp->status.pr_reg[R_O1];
val = tcp->status.PR_REG[R_O1];
#endif /* SPARC */
#ifdef I386
val = tcp->status.pr_reg[EDX];
val = tcp->status.PR_REG[EDX];
#endif /* I386 */
#ifdef MIPS
val = tcp->status.pr_reg[CTX_V1];
val = tcp->status.PR_REG[CTX_V1];
#endif /* MIPS */
#endif /* SVR4 */

View File

@ -1279,11 +1279,19 @@ static struct xlat sysctl_kern[] = {
{ KERN_PROF, "KERN_PROF" },
{ KERN_NODENAME, "KERN_NODENAME" },
{ KERN_DOMAINNAME, "KERN_DOMAINNAME" },
#ifdef KERN_SECURELVL
{ KERN_SECURELVL, "KERN_SECURELVL" },
#endif
{ KERN_PANIC, "KERN_PANIC" },
#ifdef KERN_REALROOTDEV
{ KERN_REALROOTDEV, "KERN_REALROOTDEV" },
#endif
#ifdef KERN_JAVA_INTERPRETER
{ KERN_JAVA_INTERPRETER, "KERN_JAVA_INTERPRETER" },
#endif
#ifdef KERN_JAVA_APPLETVIEWER
{ KERN_JAVA_APPLETVIEWER, "KERN_JAVA_APPLETVIEWER" },
#endif
{ KERN_SPARC_REBOOT, "KERN_SPARC_REBOOT" },
{ KERN_CTLALTDEL, "KERN_CTLALTDEL" },
{ KERN_PRINTK, "KERN_PRINTK" },
@ -1562,8 +1570,13 @@ struct tcb *tcp;
&& ((name[0] == CTL_KERN
&& (name[1] == KERN_OSRELEASE
|| name[1] == KERN_OSTYPE
#ifdef KERN_JAVA_INTERPRETER
|| name[1] == KERN_JAVA_INTERPRETER
|| name[1] == KERN_JAVA_APPLETVIEWER)))) {
#endif
#ifdef KERN_JAVA_APPLETVIEWER
|| name[1] == KERN_JAVA_APPLETVIEWER
#endif
)))) {
printpath(tcp, (size_t)info.oldval);
tprintf(", %d, ", oldlen);
if (info.newval == 0)

27
util.c
View File

@ -57,7 +57,11 @@
#include <sys/utsname.h>
#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */
#if defined(LINUX) && defined(SPARC) && !defined(__GLIBC__)
#if defined(LINUX) && defined(SPARC)
#include <asm/reg.h>
#if !defined(__GLIBC__)
#include <linux/unistd.h>
@ -95,6 +99,8 @@ static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,
#endif
#endif
/* macros */
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
@ -618,6 +624,10 @@ char *laddr;
#endif /* SUNOS4 */
#ifdef SVR4
#ifdef SVR4_MP
if (pread(tcp->pfd_as, laddr, len, addr) == -1)
return -1;
#else
/*
* We would like to use pread preferentially for speed
* but even though SGI has it in their library, it no longer works.
@ -633,6 +643,7 @@ char *laddr;
if (read(tcp->pfd, laddr, len) == -1)
return -1;
#endif /* !HAVE_PREAD */
#endif /* SVR4_MP */
#endif /* SVR4 */
return 0;
@ -878,10 +889,10 @@ struct tcb *tcp;
return -1;
#else /* !ALPHA */
#ifdef SPARC
struct pt_regs regs;
struct regs regs;
if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
return -1;
pc = regs.pc;
pc = regs.r_pc;
#endif /* SPARC */
#endif /* ALPHA */
#endif /* !M68K */
@ -955,12 +966,12 @@ struct tcb *tcp;
tprintf("[%08lx] ", pc);
#else /* !ALPHA */
#ifdef SPARC
struct pt_regs regs;
struct regs regs;
if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0) {
tprintf("[????????] ");
return;
}
tprintf("[%08lx] ", regs.pc);
tprintf("[%08lx] ", regs.r_pc);
#endif /* SPARC */
#endif /* ALPHA */
#endif /* !M68K */
@ -997,7 +1008,7 @@ struct tcb *tcp;
#ifdef SPARC
/* We simply use the SunOS breakpoint code. */
struct pt_regs regs;
struct regs regs;
#define LOOPA 0x30800000 /* ba,a 0 */
if (tcp->flags & TCB_BPTSET) {
@ -1008,9 +1019,7 @@ struct tcb *tcp;
perror("setbpt: ptrace(PTRACE_GETREGS, ...)");
return -1;
}
memmove (&regs.u_regs [1], &regs.u_regs [0],
sizeof (regs.u_regs) - sizeof (regs.u_regs [0]));
tcp->baddr = regs.u_regs[UREG_I7] + 8;
tcp->baddr = regs.r_o7 + 8;
errno = 0;
tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);
if(errno) {