freebsd-dev/usr.bin/truss/syscalls.c

207 lines
4.5 KiB
C
Raw Normal View History

1997-12-06 05:23:12 +00:00
/*
* This file has routines used to print out system calls and their
* arguments.
*/
/*
* $Id: syscalls.c,v 1.1 1997/12/06 05:23:10 sef Exp $
1997-12-06 05:23:12 +00:00
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "syscall.h"
/*
* This should probably be in its own file.
*/
struct syscall syscalls[] = {
{ "readlink", 1, 3,
{ { String, 0 } , { String | OUT, 1 }, { Int, 2 }}},
{ "lseek", 2, 3,
{ { Int, 0 }, {Quad, 2 }, { Int, 4 }}},
{ "mmap", 2, 6,
{ { Hex, 0 }, {Int, 1}, {Hex, 2}, {Hex, 3}, {Int, 4}, {Quad, 6}}},
{ "open", 1, 3,
{ { String | IN, 0} , { Int, 1}, {Octal, 2}}},
{ "linux_open", 1, 3,
{ { String, 0 }, { Int, 1}, { Octal, 2 }}},
{ "close", 1, 1, { { Int, 0 } } },
{ "fstat", 1, 2,
{ { Int, 0}, {Ptr | OUT , 1 }}},
{ "stat", 1, 2,
{ { String | IN, 0 }, { Ptr | OUT, 1 }}},
{ "linux_newstat", 1, 2,
{ { String | IN, 0 }, { Ptr | OUT, 1 }}},
{ "linux_newfstat", 1, 2,
{ { Int, 0 }, { Ptr | OUT, 1 }}},
{ "write", 1, 3,
{ { Int, 0}, { Ptr | IN, 1 }, { Int, 2 }}},
{ "ioctl", 1, 3,
{ { Int, 0}, { Ioctl, 1 }, { Hex, 2 }}},
1997-12-06 05:23:12 +00:00
{ "break", 1, 1, { { Hex, 0 }}},
{ "exit", 0, 1, { { Hex, 0 }}},
{ 0, 0, 0, { 0, 0 } },
};
/*
* If/when the list gets big, it might be desirable to do it
* as a hash table or binary search.
*/
struct syscall *
get_syscall(const char *name) {
struct syscall *sc = syscalls;
while (sc->name) {
if (!strcmp(name, sc->name))
return sc;
sc++;
}
return NULL;
}
/*
* get_string
* Copy a string from the process. Note that it is
* expected to be a C string, but if max is set, it will
* only get that much.
*/
char *
get_string(int procfd, void *offset, int max) {
char *buf, *tmp;
int size, len, c;
FILE *p;
if ((p = fdopen(procfd, "r")) == NULL) {
perror("fdopen");
exit(1);
}
buf = malloc( size = (max ? max : 64 ) );
len = 0;
fseek(p, (long)offset, SEEK_SET);
while ((c = fgetc(p)) != EOF) {
buf[len++] = c;
if (c == 0 || len == max) {
buf[len] = 0;
break;
}
if (len == size) {
char *tmp = buf;
tmp = realloc(buf, size+64);
if (tmp == NULL) {
buf[len] = 0;
return buf;
}
size += 64;
}
}
return buf;
}
/*
* Gag. This is really unportable. Multiplication is more portable.
* But slower, from the code I saw.
*/
static long long
make_quad(unsigned long p1, unsigned long p2) {
union {
long long ll;
unsigned long l[2];
} t;
t.l[0] = p1;
t.l[1] = p2;
return t.ll;
}
/*
* print_arg
* Converts a syscall argument into a string. Said string is
* allocated via malloc(), so needs to be free()'d. The file
* descriptor is for the process' memory (via /proc), and is used
* to get any data (where the argument is a pointer). sc is
* a pointer to the syscall description (see above); args is
* an array of all of the system call arguments.
*/
char *
print_arg(int fd, struct syscall_args *sc, unsigned long *args) {
char *tmp;
switch (sc->type & ARG_MASK) {
case Hex:
tmp = malloc(12);
sprintf(tmp, "0x%x", args[sc->offset]);
break;
case Octal:
tmp = malloc(13);
sprintf(tmp, "0%o", args[sc->offset]);
break;
case Int:
tmp = malloc(12);
sprintf(tmp, "%d", args[sc->offset]);
break;
case String:
{
char *tmp2;
tmp2 = get_string(fd, (void*)args[sc->offset], 0);
tmp = malloc(strlen(tmp2) + 3);
sprintf(tmp, "\"%s\"", tmp2);
free(tmp2);
}
break;
case Quad:
{
unsigned long long t;
unsigned long l1, l2;
l1 = args[sc->offset];
l2 = args[sc->offset+1];
t = make_quad(l1, l2);
tmp = malloc(24);
sprintf(tmp, "0x%qx", t);
break;
}
case Ptr:
tmp = malloc(12);
sprintf(tmp, "0x%x", args[sc->offset]);
break;
case Ioctl:
{
char *temp = ioctlname(args[sc->offset]);
if (temp)
tmp = strdup(temp);
else {
tmp = malloc(12);
sprintf(tmp, "0x%x", args[sc->offset]);
}
}
1997-12-06 05:23:12 +00:00
}
return tmp;
}
/*
* print_syscall
* Print (to outfile) the system call and its arguments. Note that
* nargs is the number of arguments (not the number of words; this is
* potentially confusing, I know).
*/
void
print_syscall(FILE *outfile, const char *name, int nargs, char **s_args) {
int i;
fprintf(outfile, "syscall %s(", name);
for (i = 0; i < nargs; i++) {
if (s_args[i])
fprintf(outfile, "%s", s_args[i]);
else
fprintf(outfile, "<missing argument>");
fprintf(outfile, "%s", i < (nargs - 1) ? "," : "");
}
fprintf(outfile, ")\n\t");
}