truss: Add support for utrace(2).
This uses the kdump(1) utrace support code directly until a common library is created. This allows malloc(3) tracing with MALLOC_CONF=utrace:true and rtld tracing with LD_UTRACE=1. Unknown utrace(2) data is just printed as hex. PR: 43819 [inspired by] Reviewed by: jhb MFC after: 2 weeks Relnotes: yes Differential Revision: https://reviews.freebsd.org/D3819
This commit is contained in:
parent
a6fe4c02d6
commit
195aef9962
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288957
@ -28,7 +28,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd November 1, 2014
|
.Dd October 5, 2015
|
||||||
.Dt UTRACE 2
|
.Dt UTRACE 2
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -70,7 +70,8 @@ support
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr kdump 1 ,
|
.Xr kdump 1 ,
|
||||||
.Xr ktrace 1 ,
|
.Xr ktrace 1 ,
|
||||||
.Xr ktrace 2
|
.Xr ktrace 2 ,
|
||||||
|
.Xr truss 1
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Fn utrace
|
.Fn utrace
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
.PATH: ${.CURDIR}/../ktrace
|
.PATH: ${.CURDIR}/../ktrace
|
||||||
|
|
||||||
PROG= kdump
|
PROG= kdump
|
||||||
SRCS= kdump_subr.c kdump.c ioctl.c subr.c
|
SRCS= kdump_subr.c kdump.c ioctl.c subr.c utrace.c
|
||||||
DPSRCS= kdump_subr.h
|
DPSRCS= kdump_subr.h
|
||||||
CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I.
|
CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I.
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ extern int errno;
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -117,6 +116,7 @@ void ktrfaultend(struct ktr_faultend *);
|
|||||||
void limitfd(int fd);
|
void limitfd(int fd);
|
||||||
void usage(void);
|
void usage(void);
|
||||||
void ioctlname(unsigned long, int);
|
void ioctlname(unsigned long, int);
|
||||||
|
int kdump_print_utrace(FILE *, void *, size_t, int);
|
||||||
|
|
||||||
#define TIMESTAMP_NONE 0x0
|
#define TIMESTAMP_NONE 0x0
|
||||||
#define TIMESTAMP_ABSOLUTE 0x1
|
#define TIMESTAMP_ABSOLUTE 0x1
|
||||||
@ -1536,151 +1536,13 @@ ktrcsw(struct ktr_csw *cs)
|
|||||||
cs->user ? "user" : "kernel", cs->wmesg);
|
cs->user ? "user" : "kernel", cs->wmesg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define UTRACE_DLOPEN_START 1
|
|
||||||
#define UTRACE_DLOPEN_STOP 2
|
|
||||||
#define UTRACE_DLCLOSE_START 3
|
|
||||||
#define UTRACE_DLCLOSE_STOP 4
|
|
||||||
#define UTRACE_LOAD_OBJECT 5
|
|
||||||
#define UTRACE_UNLOAD_OBJECT 6
|
|
||||||
#define UTRACE_ADD_RUNDEP 7
|
|
||||||
#define UTRACE_PRELOAD_FINISHED 8
|
|
||||||
#define UTRACE_INIT_CALL 9
|
|
||||||
#define UTRACE_FINI_CALL 10
|
|
||||||
#define UTRACE_DLSYM_START 11
|
|
||||||
#define UTRACE_DLSYM_STOP 12
|
|
||||||
|
|
||||||
struct utrace_rtld {
|
|
||||||
char sig[4]; /* 'RTLD' */
|
|
||||||
int event;
|
|
||||||
void *handle;
|
|
||||||
void *mapbase;
|
|
||||||
size_t mapsize;
|
|
||||||
int refcnt;
|
|
||||||
char name[MAXPATHLEN];
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
ktruser_rtld(int len, void *p)
|
|
||||||
{
|
|
||||||
struct utrace_rtld *ut = p;
|
|
||||||
unsigned char *cp;
|
|
||||||
void *parent;
|
|
||||||
int mode;
|
|
||||||
|
|
||||||
switch (ut->event) {
|
|
||||||
case UTRACE_DLOPEN_START:
|
|
||||||
mode = ut->refcnt;
|
|
||||||
printf("dlopen(%s, ", ut->name);
|
|
||||||
switch (mode & RTLD_MODEMASK) {
|
|
||||||
case RTLD_NOW:
|
|
||||||
printf("RTLD_NOW");
|
|
||||||
break;
|
|
||||||
case RTLD_LAZY:
|
|
||||||
printf("RTLD_LAZY");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("%#x", mode & RTLD_MODEMASK);
|
|
||||||
}
|
|
||||||
if (mode & RTLD_GLOBAL)
|
|
||||||
printf(" | RTLD_GLOBAL");
|
|
||||||
if (mode & RTLD_TRACE)
|
|
||||||
printf(" | RTLD_TRACE");
|
|
||||||
if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
|
|
||||||
printf(" | %#x", mode &
|
|
||||||
~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
|
|
||||||
printf(")\n");
|
|
||||||
break;
|
|
||||||
case UTRACE_DLOPEN_STOP:
|
|
||||||
printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
|
|
||||||
ut->refcnt);
|
|
||||||
break;
|
|
||||||
case UTRACE_DLCLOSE_START:
|
|
||||||
printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
|
|
||||||
ut->refcnt);
|
|
||||||
break;
|
|
||||||
case UTRACE_DLCLOSE_STOP:
|
|
||||||
printf("dlclose(%p) finished\n", ut->handle);
|
|
||||||
break;
|
|
||||||
case UTRACE_LOAD_OBJECT:
|
|
||||||
printf("RTLD: loaded %p @ %p - %p (%s)\n", ut->handle,
|
|
||||||
ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
|
|
||||||
ut->name);
|
|
||||||
break;
|
|
||||||
case UTRACE_UNLOAD_OBJECT:
|
|
||||||
printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
|
|
||||||
ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
|
|
||||||
ut->name);
|
|
||||||
break;
|
|
||||||
case UTRACE_ADD_RUNDEP:
|
|
||||||
parent = ut->mapbase;
|
|
||||||
printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
|
|
||||||
ut->handle, ut->name, ut->refcnt);
|
|
||||||
break;
|
|
||||||
case UTRACE_PRELOAD_FINISHED:
|
|
||||||
printf("RTLD: LD_PRELOAD finished\n");
|
|
||||||
break;
|
|
||||||
case UTRACE_INIT_CALL:
|
|
||||||
printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
|
|
||||||
ut->name);
|
|
||||||
break;
|
|
||||||
case UTRACE_FINI_CALL:
|
|
||||||
printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
|
|
||||||
ut->name);
|
|
||||||
break;
|
|
||||||
case UTRACE_DLSYM_START:
|
|
||||||
printf("RTLD: dlsym(%p, %s)\n", ut->handle, ut->name);
|
|
||||||
break;
|
|
||||||
case UTRACE_DLSYM_STOP:
|
|
||||||
printf("RTLD: %p = dlsym(%p, %s)\n", ut->mapbase, ut->handle,
|
|
||||||
ut->name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cp = p;
|
|
||||||
cp += 4;
|
|
||||||
len -= 4;
|
|
||||||
printf("RTLD: %d ", len);
|
|
||||||
while (len--)
|
|
||||||
if (decimal)
|
|
||||||
printf(" %d", *cp++);
|
|
||||||
else
|
|
||||||
printf(" %02x", *cp++);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct utrace_malloc {
|
|
||||||
void *p;
|
|
||||||
size_t s;
|
|
||||||
void *r;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
ktruser_malloc(void *p)
|
|
||||||
{
|
|
||||||
struct utrace_malloc *ut = p;
|
|
||||||
|
|
||||||
if (ut->p == (void *)(intptr_t)(-1))
|
|
||||||
printf("malloc_init()\n");
|
|
||||||
else if (ut->s == 0)
|
|
||||||
printf("free(%p)\n", ut->p);
|
|
||||||
else if (ut->p == NULL)
|
|
||||||
printf("%p = malloc(%zu)\n", ut->r, ut->s);
|
|
||||||
else
|
|
||||||
printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ktruser(int len, void *p)
|
ktruser(int len, void *p)
|
||||||
{
|
{
|
||||||
unsigned char *cp;
|
unsigned char *cp;
|
||||||
|
|
||||||
if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
|
if (kdump_print_utrace(stdout, p, len, decimal)) {
|
||||||
ktruser_rtld(len, p);
|
printf("\n");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == sizeof(struct utrace_malloc)) {
|
|
||||||
ktruser_malloc(p);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
187
usr.bin/kdump/utrace.c
Normal file
187
usr.bin/kdump/utrace.c
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1988, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
int kdump_print_utrace(FILE *, void *, size_t, int);
|
||||||
|
|
||||||
|
#define UTRACE_DLOPEN_START 1
|
||||||
|
#define UTRACE_DLOPEN_STOP 2
|
||||||
|
#define UTRACE_DLCLOSE_START 3
|
||||||
|
#define UTRACE_DLCLOSE_STOP 4
|
||||||
|
#define UTRACE_LOAD_OBJECT 5
|
||||||
|
#define UTRACE_UNLOAD_OBJECT 6
|
||||||
|
#define UTRACE_ADD_RUNDEP 7
|
||||||
|
#define UTRACE_PRELOAD_FINISHED 8
|
||||||
|
#define UTRACE_INIT_CALL 9
|
||||||
|
#define UTRACE_FINI_CALL 10
|
||||||
|
#define UTRACE_DLSYM_START 11
|
||||||
|
#define UTRACE_DLSYM_STOP 12
|
||||||
|
|
||||||
|
struct utrace_rtld {
|
||||||
|
char sig[4]; /* 'RTLD' */
|
||||||
|
int event;
|
||||||
|
void *handle;
|
||||||
|
void *mapbase;
|
||||||
|
size_t mapsize;
|
||||||
|
int refcnt;
|
||||||
|
char name[MAXPATHLEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_utrace_rtld(FILE *fp, void *p, size_t len, int decimal)
|
||||||
|
{
|
||||||
|
struct utrace_rtld *ut = p;
|
||||||
|
unsigned char *cp;
|
||||||
|
void *parent;
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
switch (ut->event) {
|
||||||
|
case UTRACE_DLOPEN_START:
|
||||||
|
mode = ut->refcnt;
|
||||||
|
fprintf(fp, "dlopen(%s, ", ut->name);
|
||||||
|
switch (mode & RTLD_MODEMASK) {
|
||||||
|
case RTLD_NOW:
|
||||||
|
fprintf(fp, "RTLD_NOW");
|
||||||
|
break;
|
||||||
|
case RTLD_LAZY:
|
||||||
|
fprintf(fp, "RTLD_LAZY");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(fp, "%#x", mode & RTLD_MODEMASK);
|
||||||
|
}
|
||||||
|
if (mode & RTLD_GLOBAL)
|
||||||
|
fprintf(fp, " | RTLD_GLOBAL");
|
||||||
|
if (mode & RTLD_TRACE)
|
||||||
|
fprintf(fp, " | RTLD_TRACE");
|
||||||
|
if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
|
||||||
|
fprintf(fp, " | %#x", mode &
|
||||||
|
~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
|
||||||
|
fprintf(fp, ")");
|
||||||
|
break;
|
||||||
|
case UTRACE_DLOPEN_STOP:
|
||||||
|
fprintf(fp, "%p = dlopen(%s) ref %d", ut->handle, ut->name,
|
||||||
|
ut->refcnt);
|
||||||
|
break;
|
||||||
|
case UTRACE_DLCLOSE_START:
|
||||||
|
fprintf(fp, "dlclose(%p) (%s, %d)", ut->handle, ut->name,
|
||||||
|
ut->refcnt);
|
||||||
|
break;
|
||||||
|
case UTRACE_DLCLOSE_STOP:
|
||||||
|
fprintf(fp, "dlclose(%p) finished", ut->handle);
|
||||||
|
break;
|
||||||
|
case UTRACE_LOAD_OBJECT:
|
||||||
|
fprintf(fp, "RTLD: loaded %p @ %p - %p (%s)", ut->handle,
|
||||||
|
ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
|
||||||
|
ut->name);
|
||||||
|
break;
|
||||||
|
case UTRACE_UNLOAD_OBJECT:
|
||||||
|
fprintf(fp, "RTLD: unloaded %p @ %p - %p (%s)", ut->handle,
|
||||||
|
ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
|
||||||
|
ut->name);
|
||||||
|
break;
|
||||||
|
case UTRACE_ADD_RUNDEP:
|
||||||
|
parent = ut->mapbase;
|
||||||
|
fprintf(fp, "RTLD: %p now depends on %p (%s, %d)", parent,
|
||||||
|
ut->handle, ut->name, ut->refcnt);
|
||||||
|
break;
|
||||||
|
case UTRACE_PRELOAD_FINISHED:
|
||||||
|
fprintf(fp, "RTLD: LD_PRELOAD finished");
|
||||||
|
break;
|
||||||
|
case UTRACE_INIT_CALL:
|
||||||
|
fprintf(fp, "RTLD: init %p for %p (%s)", ut->mapbase, ut->handle,
|
||||||
|
ut->name);
|
||||||
|
break;
|
||||||
|
case UTRACE_FINI_CALL:
|
||||||
|
fprintf(fp, "RTLD: fini %p for %p (%s)", ut->mapbase, ut->handle,
|
||||||
|
ut->name);
|
||||||
|
break;
|
||||||
|
case UTRACE_DLSYM_START:
|
||||||
|
fprintf(fp, "RTLD: dlsym(%p, %s)", ut->handle, ut->name);
|
||||||
|
break;
|
||||||
|
case UTRACE_DLSYM_STOP:
|
||||||
|
fprintf(fp, "RTLD: %p = dlsym(%p, %s)", ut->mapbase, ut->handle,
|
||||||
|
ut->name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cp = p;
|
||||||
|
cp += 4;
|
||||||
|
len -= 4;
|
||||||
|
fprintf(fp, "RTLD: %zu ", len);
|
||||||
|
while (len--)
|
||||||
|
if (decimal)
|
||||||
|
fprintf(fp, " %d", *cp++);
|
||||||
|
else
|
||||||
|
fprintf(fp, " %02x", *cp++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct utrace_malloc {
|
||||||
|
void *p;
|
||||||
|
size_t s;
|
||||||
|
void *r;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_utrace_malloc(FILE *fp, void *p)
|
||||||
|
{
|
||||||
|
struct utrace_malloc *ut = p;
|
||||||
|
|
||||||
|
if (ut->p == (void *)(intptr_t)(-1))
|
||||||
|
fprintf(fp, "malloc_init()");
|
||||||
|
else if (ut->s == 0)
|
||||||
|
fprintf(fp, "free(%p)", ut->p);
|
||||||
|
else if (ut->p == NULL)
|
||||||
|
fprintf(fp, "%p = malloc(%zu)", ut->r, ut->s);
|
||||||
|
else
|
||||||
|
fprintf(fp, "%p = realloc(%p, %zu)", ut->r, ut->p, ut->s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kdump_print_utrace(FILE *fp, void *p, size_t len, int decimal)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
|
||||||
|
print_utrace_rtld(fp, p, len, decimal);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == sizeof(struct utrace_malloc)) {
|
||||||
|
print_utrace_malloc(fp, p);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
@ -10,6 +10,9 @@ SRCS+= ${MACHINE_ARCH}-fbsd.c
|
|||||||
SRCS+= ${MACHINE_CPUARCH}-fbsd.c
|
SRCS+= ${MACHINE_CPUARCH}-fbsd.c
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR:H}/kdump
|
||||||
|
SRCS+= utrace.c
|
||||||
|
|
||||||
CFLAGS+= -I${.CURDIR} -I.
|
CFLAGS+= -I${.CURDIR} -I.
|
||||||
CLEANFILES= syscalls.master syscalls.h ioctl.c
|
CLEANFILES= syscalls.master syscalls.h ioctl.c
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* Sigprocmask -- the first argument to sigprocmask(). Prints the name.
|
* Sigprocmask -- the first argument to sigprocmask(). Prints the name.
|
||||||
* Kevent -- a pointer to an array of struct kevents. Prints all elements.
|
* Kevent -- a pointer to an array of struct kevents. Prints all elements.
|
||||||
* Pathconf -- the 2nd argument of pathconf().
|
* Pathconf -- the 2nd argument of pathconf().
|
||||||
|
* Utrace -- utrace(2) buffer.
|
||||||
*
|
*
|
||||||
* In addition, the pointer types (String, Ptr) may have OUT masked in --
|
* 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
|
* this means that the data is set on *return* from the system call -- or
|
||||||
@ -43,7 +44,7 @@ enum Argtype { None = 1, Hex, Octal, Int, LongHex, Name, Ptr, Stat, Ioctl, Quad,
|
|||||||
Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2,
|
Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2,
|
||||||
Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl,
|
Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl,
|
||||||
LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode, Long,
|
LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode, Long,
|
||||||
Sysarch, ExecArgs, ExecEnv, PipeFds, QuadHex };
|
Sysarch, ExecArgs, ExecEnv, PipeFds, QuadHex, Utrace };
|
||||||
|
|
||||||
#define ARG_MASK 0xff
|
#define ARG_MASK 0xff
|
||||||
#define OUT 0x100
|
#define OUT 0x100
|
||||||
|
@ -72,6 +72,9 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
|
/* usr.bin/kdump/utrace.c */
|
||||||
|
int kdump_print_utrace(FILE *, void *, size_t, int);
|
||||||
|
|
||||||
/* 64-bit alignment on 32-bit platforms. */
|
/* 64-bit alignment on 32-bit platforms. */
|
||||||
#if !defined(__LP64__) && defined(__powerpc__)
|
#if !defined(__LP64__) && defined(__powerpc__)
|
||||||
#define QUAD_ALIGN 1
|
#define QUAD_ALIGN 1
|
||||||
@ -342,6 +345,8 @@ static struct syscall decoded_syscalls[] = {
|
|||||||
{ Atflags, 3 } } },
|
{ Atflags, 3 } } },
|
||||||
{ .name = "utimes", .ret_type = 1, .nargs = 2,
|
{ .name = "utimes", .ret_type = 1, .nargs = 2,
|
||||||
.args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
|
.args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
|
||||||
|
{ .name = "utrace", .ret_type = 1, .nargs = 1,
|
||||||
|
.args = { { Utrace, 0 } } },
|
||||||
{ .name = "wait4", .ret_type = 1, .nargs = 4,
|
{ .name = "wait4", .ret_type = 1, .nargs = 4,
|
||||||
.args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
|
.args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
|
||||||
{ Rusage | OUT, 3 } } },
|
{ Rusage | OUT, 3 } } },
|
||||||
@ -860,6 +865,24 @@ print_kevent(FILE *fp, struct kevent *ke, int input)
|
|||||||
fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
|
fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_utrace(FILE *fp, void *utrace_addr, size_t len)
|
||||||
|
{
|
||||||
|
unsigned char *utrace_buffer;
|
||||||
|
|
||||||
|
fprintf(fp, "{ ");
|
||||||
|
if (kdump_print_utrace(fp, utrace_addr, len, 0)) {
|
||||||
|
fprintf(fp, " }");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utrace_buffer = utrace_addr;
|
||||||
|
fprintf(fp, "%zu:", len);
|
||||||
|
while (len--)
|
||||||
|
fprintf(fp, " %02x", *utrace_buffer++);
|
||||||
|
fprintf(fp, " }");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Converts a syscall argument into a string. Said string is
|
* Converts a syscall argument into a string. Said string is
|
||||||
* allocated via malloc(), so needs to be free()'d. sc is
|
* allocated via malloc(), so needs to be free()'d. sc is
|
||||||
@ -1601,6 +1624,20 @@ print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
|
|||||||
fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
|
fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]);
|
||||||
retval[0] = 0;
|
retval[0] = 0;
|
||||||
break;
|
break;
|
||||||
|
case Utrace: {
|
||||||
|
size_t len;
|
||||||
|
void *utrace_addr;
|
||||||
|
|
||||||
|
len = args[sc->offset + 1];
|
||||||
|
utrace_addr = calloc(1, len);
|
||||||
|
if (get_struct(pid, (void *)args[sc->offset],
|
||||||
|
(void *)utrace_addr, len) != -1)
|
||||||
|
print_utrace(fp, utrace_addr, len);
|
||||||
|
else
|
||||||
|
fprintf(fp, "0x%lx", args[sc->offset]);
|
||||||
|
free(utrace_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
|
errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd May 12, 2009
|
.Dd October 5, 2015
|
||||||
.Dt TRUSS 1
|
.Dt TRUSS 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -95,7 +95,8 @@ options are mutually exclusive.)
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr kdump 1 ,
|
.Xr kdump 1 ,
|
||||||
.Xr ktrace 1 ,
|
.Xr ktrace 1 ,
|
||||||
.Xr ptrace 2
|
.Xr ptrace 2 ,
|
||||||
|
.Xr utrace 2
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
Loading…
Reference in New Issue
Block a user