freebsd-dev/usr.bin/truss/syscall.h
John Baldwin 2b75c8ad3d Several changes to truss.
- Refactor the interface between the ABI-independent code and the
  ABI-specific backends.  The backends now provide smaller hooks to
  fetch system call arguments and return values.  The rest of the
  system call entry and exit handling that was previously duplicated
  among all the backends has been moved to one place.
- Merge the loop when waiting for an event with the loop for handling stops.
  This also means not emulating a procfs-like interface on top of ptrace().
  Instead, use a single event loop that fetches process events via waitid().
  Among other things this allows us to report the full 32-bit exit value.
- Use PT_FOLLOW_FORK to follow new child processes instead of forking a new
  truss process for each new child.  This allows one truss process to monitor
  a tree of processes and truss -c should now display one total for the
  entire tree instead of separate summaries per process.
- Use the recently added fields to ptrace_lwpinfo to determine the current
  system call number and argument count.  The latter is especially useful
  and fixes a regression since the conversion from procfs.  truss now
  generally prints the correct number of arguments for most system calls
  rather than printing extra arguments for any call not listed in the
  table in syscalls.c.
- Actually check the new ABI when processes call exec.  The comments claimed
  that this happened but it was not being done (perhaps this was another
  regression in the conversion to ptrace()).  If the new ABI after exec
  is not supported, truss detaches from the process.  If truss does not
  support the ABI for a newly executed process the process is killed
  before it returns from exec.
- Along with the refactor, teach the various ABI-specific backends to
  fetch both return values, not just the first.  Use this to properly
  report the full 64-bit return value from lseek().  In addition, the
  handler for "pipe" now pulls the pair of descriptors out of the
  return values (which is the true kernel system call interface) but
  displays them as an argument (which matches the interface exported by
  libc).
- Each ABI handler adds entries to a linker set rather than requiring
  a statically defined table of handlers in main.c.
- The arm and mips system call fetching code was changed to follow the
  same pattern as amd64 (and the in-kernel handler) of fetching register
  arguments first and then reading any remaining arguments from the
  stack.  This should fix indirect system call arguments on at least
  arm.
- The mipsn32 and n64 ABIs will now look for arguments in A4 through A7.
- Use register %ebp for the 6th system call argument for Linux/i386 ABIs
  to match the in-kernel argument fetch code.
- For powerpc binaries on a powerpc64 system, fetch the extra arguments
  on the stack as 32-bit values that are then copied into the 64-bit
  argument array instead of reading the 32-bit values directly into the
  64-bit array.

Reviewed by:	kib (earlier version)
Tested on:	amd64 (FreeBSD/amd64 & i386), i386, arm (earlier version)
Tested on:	powerpc64 (FreeBSD/powerpc64 & powerpc)
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D3575
2015-09-30 19:13:32 +00:00

114 lines
4.1 KiB
C

/*
* See i386-fbsd.c for copyright and license terms.
*
* System call arguments come in several flavours:
* Hex -- values that should be printed in hex (addresses)
* Octal -- Same as above, but octal
* Int -- normal integer values (file descriptors, for example)
* LongHex -- long value that should be printed in hex
* Name -- pointer to a NULL-terminated string.
* BinString -- pointer to an array of chars, printed via strvisx().
* Ptr -- pointer to some unspecified structure. Just print as hex for now.
* Stat -- a pointer to a stat buffer. Prints a couple fields.
* Ioctl -- an ioctl command. Woefully limited.
* Quad -- a double-word value. e.g., lseek(int, offset_t, int)
* Signal -- a signal number. Prints the signal name (SIGxxx)
* Sockaddr -- a pointer to a struct sockaddr. Prints symbolic AF, and IP:Port
* StringArray -- a pointer to an array of string pointers.
* Timespec -- a pointer to a struct timespec. Prints both elements.
* Timeval -- a pointer to a struct timeval. Prints both elements.
* Timeval2 -- a pointer to two struct timevals. Prints both elements of both.
* Itimerval -- a pointer to a struct itimerval. Prints all elements.
* Pollfd -- a pointer to an array of struct pollfd. Prints .fd and .events.
* Fd_set -- a pointer to an array of fd_set. Prints the fds that are set.
* Sigaction -- a pointer to a struct sigaction. Prints all elements.
* Sigset -- a pointer to a sigset_t. Prints the signals that are set.
* Sigprocmask -- the first argument to sigprocmask(). Prints the name.
* Kevent -- a pointer to an array of struct kevents. Prints all elements.
* Pathconf -- the 2nd argument of pathconf().
*
* In addition, the pointer types (String, Ptr) may have OUT masked in --
* this means that the data is set on *return* from the system call -- or
* IN (meaning that the data is passed *into* the system call).
*/
/*
* $FreeBSD$
*/
enum Argtype { None = 1, Hex, Octal, Int, LongHex, Name, Ptr, Stat, Ioctl, Quad,
Signal, Sockaddr, StringArray, Timespec, Timeval, Itimerval, Pollfd,
Fd_set, Sigaction, Fcntl, Mprot, Mmapflags, Whence, Readlinkres,
Sigset, Sigprocmask, Kevent, Sockdomain, Socktype, Open,
Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2,
Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl,
LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode, Long,
Sysarch, ExecArgs, ExecEnv, PipeFds };
#define ARG_MASK 0xff
#define OUT 0x100
#define IN /*0x20*/0
struct syscall_args {
enum Argtype type;
int offset;
};
struct syscall {
const char *name;
u_int ret_type; /* 0, 1, or 2 return values */
u_int nargs; /* actual number of meaningful arguments */
/* Hopefully, no syscalls with > 10 args */
struct syscall_args args[10];
struct timespec time; /* Time spent for this call */
int ncalls; /* Number of calls */
int nerror; /* Number of calls that returned with error */
};
struct syscall *get_syscall(const char*);
char *print_arg(struct syscall_args *, unsigned long*, long *, struct trussinfo *);
/*
* Linux Socket defines
*/
#define LINUX_SOCKET 1
#define LINUX_BIND 2
#define LINUX_CONNECT 3
#define LINUX_LISTEN 4
#define LINUX_ACCEPT 5
#define LINUX_GETSOCKNAME 6
#define LINUX_GETPEERNAME 7
#define LINUX_SOCKETPAIR 8
#define LINUX_SEND 9
#define LINUX_RECV 10
#define LINUX_SENDTO 11
#define LINUX_RECVFROM 12
#define LINUX_SHUTDOWN 13
#define LINUX_SETSOCKOPT 14
#define LINUX_GETSOCKOPT 15
#define LINUX_SENDMSG 16
#define LINUX_RECVMSG 17
#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
0 : sizeof(register_t) - sizeof(t))
#if BYTE_ORDER == LITTLE_ENDIAN
#define PADL_(t) 0
#define PADR_(t) PAD_(t)
#else
#define PADL_(t) PAD_(t)
#define PADR_(t) 0
#endif
typedef int l_int;
typedef uint32_t l_ulong;
struct linux_socketcall_args {
char what_l_[PADL_(l_int)]; l_int what; char what_r_[PADR_(l_int)];
char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)];
};
void print_syscall(struct trussinfo *, const char *, int, char **);
void print_syscall_ret(struct trussinfo *, const char *, int, char **, int,
long *, struct syscall *);
void print_summary(struct trussinfo *trussinfo);