Subject: bin/1545: self-contained ktrace files
To: None <gnats-bugs@gnats.netbsd.org>
From: Niklas Hallqvist <niklas@appli.se>
List: netbsd-bugs
Date: 09/29/1995 14:31:17
>Number: 1545
>Category: bin
>Synopsis: Ktrace doesn't produce self-contained output files
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Fri Sep 29 15:50:01 1995
>Last-Modified:
>Originator: Niklas Hallqvist
>Organization:
Applitron Datasystem AB
>Release: 950907
>Environment:
System: NetBSD nettan.appli.se 1.0A NetBSD 1.0A (NETTAN) #13: Fri Aug 25 11:45:40 PDT 1995 niklas@nettan.appli.se:/u6/NetBSD/src/sys/arch/i386/compile/NETTAN i386
>Description:
Today ktrace/kdump doesn't know anything about what emulations
and options are used in a kernel which is traced. This leads
to things like "unimplemented syscalls" in the trace output.
Another problem is when moving around trace files to machines which
aren't based on equal kernel sources. Emulations/syscall sets may
vary over time, so kdump may produce confusing results.
>How-To-Repeat:
Ktrace a Linux (or other new emulation) binary on a current system
move the ktrace.out to an older system and kdump it. Ktrace a SVR4
binary using SYSV IPC (shared mem etc) and kdump it, watch for
"unimplemented" in the output, even when the kernel has it enabled.
>Fix:
The patchfile below changes the kernel to keep track of the syscall
sets for each emulation and makes them exportable to userlevel via
the sysctl interface. Also new versions of sysctl, ktrace and kdump
are there to use this kernel feature. Besides ktrace puts the syscall
tables in the output file unless appending, so kdump can use them for
printing purposes. If kdump gets an old trace file it will work as
before. A magic entry is also contributed for file(1) to recognize
our new ktrace file format.
*** old-NetBSD/src/lib/libc/gen/sysctl.3
--- NetBSD/src/lib/libc/gen/sysctl.3
***************
*** 223,230 ****
privilege may change the value.
The types of data currently available are process information,
system vnodes, the open file entries, routing table entries,
! virtual memory statistics, load average history, and clock rate
! information.
.Bl -column "KERNXCHOWNXRESTRICTEDXXX" "struct clockrateXXX" -offset indent
.It Sy Pa Second level name Type Changeable
.It KERN\_ARGMAX integer no
--- 223,230 ----
privilege may change the value.
The types of data currently available are process information,
system vnodes, the open file entries, routing table entries,
! virtual memory statistics, load average history, clock rate
! information and emulation information.
.Bl -column "KERNXCHOWNXRESTRICTEDXXX" "struct clockrateXXX" -offset indent
.It Sy Pa Second level name Type Changeable
.It KERN\_ARGMAX integer no
***************
*** 232,237 ****
--- 232,238 ----
.It KERN\_CHOWN\_RESTRICTED integer no
.It KERN\_CLOCKRATE struct clockinfo no
.It KERN\_DOMAINNAME string yes
+ .It KERN\_EMUL node not applicable
.It KERN\_FILE struct file no
.It KERN\_HOSTID integer yes
.It KERN\_HOSTNAME string yes
***************
*** 244,249 ****
--- 245,251 ----
.It KERN\_MAX\_CANON integer no
.It KERN\_MAX\_INPUT integer no
.It KERN\_NAME\_MAX integer no
+ .It KERN\_NEMUL integer no
.It KERN\_NGROUPS integer no
.It KERN\_NO\_TRUNC integer no
.It KERN\_OSRELEASE string no
***************
*** 284,289 ****
--- 286,313 ----
skew rate.
.It Li KERN_DOMAINNAME
Get or set the YP domain name.
+ .It Li KERN_EMUL
+ Return emulation information about the kernel.
+ The third level name is the offset into the emulsw table and the fourth
+ level names are detailed below.
+ No values in this hierachy is changeable.
+ .Bl -column "KERNXEMULXMAXSYSCALLXXX" -offset indent
+ .It Sy Pa Fourth level name Type
+ .It KERN\_EMUL\_NAME string
+ .It KERN\_EMUL\_MAXSYSCALL integer
+ .It KERN\_EMUL\_SYSCALL node
+ .El
+ .Pp
+ The variables are as follows:
+ .Bl -tag -width "123456"
+ .It Li KERN_EMUL_NAME
+ Returns the name of the emulation.
+ .It Li KERN_EMUL_MAXSYSCALL
+ Returns the number of system calls in this emulation.
+ .It Li KERN_EMUL_SYSCALL
+ Returns the individual system call names.
+ The fifth level name is the system call number.
+ .El
.It Li KERN_FILE
Return the entire file table.
The returned data consists of a single
***************
*** 314,319 ****
--- 338,345 ----
a terminal input queue.
.It Li KERN_NAME_MAX
The maximum number of bytes in a file name.
+ .It Li KERN_NEMUL
+ The number of entries in the emulsw table.
.It Li KERN_NGROUPS
The maximum number of supplemental groups.
.It Li KERN_NO_TRUNC
*** old-NetBSD/src/sys/conf/files
--- NetBSD/src/sys/conf/files
***************
*** 71,76 ****
--- 71,77 ----
file isofs/cd9660/cd9660_util.c cd9660
file isofs/cd9660/cd9660_vfsops.c cd9660
file isofs/cd9660/cd9660_vnops.c cd9660
+ file kern/emul_conf.c
file kern/exec_aout.c
file kern/exec_conf.c
file kern/exec_ecoff.c compat_ultrix compat_osf1
***************
*** 108,114 ****
file kern/sys_generic.c
file kern/sys_process.c
file kern/sys_socket.c
! file kern/syscalls.c syscall_debug
file kern/sysv_ipc.c sysvshm sysvsem sysvmsg
file kern/sysv_msg.c sysvmsg
file kern/sysv_sem.c sysvsem
--- 109,115 ----
file kern/sys_generic.c
file kern/sys_process.c
file kern/sys_socket.c
! file kern/syscalls.c
file kern/sysv_ipc.c sysvshm sysvsem sysvmsg
file kern/sysv_msg.c sysvmsg
file kern/sysv_sem.c sysvsem
*** old-NetBSD/src/sys/conf/files.oldconf
--- NetBSD/src/sys/conf/files.oldconf
***************
*** 64,70 ****
kern/sys_generic.c standard
kern/sys_process.c standard
kern/sys_socket.c standard
! kern/syscalls.c optional syscall_debug
kern/sysv_ipc.c optional sysvmsg or sysvsem or sysvshm
kern/sysv_msg.c optional sysvmsg
kern/sysv_sem.c optional sysvsem
--- 64,70 ----
kern/sys_generic.c standard
kern/sys_process.c standard
kern/sys_socket.c standard
! kern/syscalls.c standard
kern/sysv_ipc.c optional sysvmsg or sysvsem or sysvshm
kern/sysv_msg.c optional sysvmsg
kern/sysv_sem.c optional sysvsem
*** /dev/null
--- NetBSD/src/sys/kern/emul_conf.c
***************
*** 0 ****
--- 1,113 ----
+ /* $NetBSD: emul_conf.c,v 1.1 1995/08/26 11:00:47 niklas Exp $ */
+
+ /*
+ * Copyright (c) 1995 Niklas Hallqvist
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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/param.h>
+ #include <sys/emul.h>
+ #include <sys/syscall.h>
+ #ifdef COMPAT_HPUX
+ #include <compat/hpux/hpux_syscall.h>
+ #endif
+ #ifdef COMPAT_IBCS2
+ #include <compat/ibcs2/ibcs2_syscall.h>
+ #endif
+ #ifdef COMPAT_LINUX
+ #include <compat/linux/linux_syscall.h>
+ #endif
+ #ifdef COMPAT_HPUX
+ #include <compat/osf1/osf1_syscall.h>
+ #endif
+ #ifdef COMPAT_SUNOS
+ #include <compat/sunos/sunos_syscall.h>
+ #endif
+ #ifdef COMPAT_SVR4
+ #include <compat/svr4/svr4_syscall.h>
+ #endif
+ #ifdef COMPAT_ULTRIX
+ #include <compat/ultrix/ultrix_syscall.h>
+ #endif
+
+ extern char *syscallnames[];
+ #ifdef COMPAT_HPUX
+ extern char *hpux_syscalls[];
+ #endif
+ #ifdef COMPAT_IBCS2
+ extern char *ibcs2_syscalls[];
+ #endif
+ #ifdef COMPAT_LINUX
+ extern char *linux_syscalls[];
+ #endif
+ #ifdef COMPAT_HPUX
+ extern char *osf1_syscalls[];
+ #endif
+ #ifdef COMPAT_SUNOS
+ extern char *sunos_syscalls[];
+ #endif
+ #ifdef COMPAT_SVR4
+ extern char *svr4_syscalls[];
+ #endif
+ #ifdef COMPAT_ULTRIX
+ extern char *ultrix_syscalls[];
+ #endif
+
+ struct emulsw emulsw[] = {
+ { "netbsd", SYS_MAXSYSCALL, syscallnames, },
+ #ifdef COMPAT_HPUX
+ { "hpux", HPUX_SYS_MAXSYSCALL, hpux_syscalls, },
+ #endif
+ #ifdef COMPAT_IBCS2
+ { "ibcs2", IBCS2_SYS_MAXSYSCALL, ibcs2_syscalls, },
+ #endif
+ #ifdef COMPAT_LINUX
+ { "linux", LINUX_SYS_MAXSYSCALL, linux_syscalls, },
+ #endif
+ #ifdef COMPAT_HPUX
+ { "osf1", OSF1_SYS_MAXSYSCALL, osf1_syscalls, },
+ #endif
+ #ifdef COMPAT_SUNOS
+ { "sunos", SUNOS_SYS_MAXSYSCALL, sunos_syscalls, },
+ #endif
+ #ifdef COMPAT_SVR4
+ { "svr4", SVR4_SYS_MAXSYSCALL, svr4_syscalls, },
+ #endif
+ #ifdef COMPAT_ULTRIX
+ { "ultrix", ULTRIX_SYS_MAXSYSCALL, ultrix_syscalls, },
+ #endif
+ #ifdef LKM
+ { "", 0, NULL, }, /* entries for LKMs */
+ { "", 0, NULL, },
+ { "", 0, NULL, },
+ { "", 0, NULL, },
+ { "", 0, NULL, },
+ #endif
+ };
+
+ int nemuls = sizeof(emulsw) / sizeof(*emulsw);
*** old-NetBSD/src/sys/kern/init_main.c
--- NetBSD/src/sys/kern/init_main.c
***************
*** 102,110 ****
#endif
extern char sigcode[], esigcode[];
- #ifdef SYSCALL_DEBUG
extern char *syscallnames[];
- #endif
struct emul emul_netbsd = {
"netbsd",
--- 102,108 ----
***************
*** 113,123 ****
SYS_syscall,
SYS_MAXSYSCALL,
sysent,
- #ifdef SYSCALL_DEBUG
syscallnames,
- #else
- NULL,
- #endif
0,
copyargs,
setregs,
--- 111,117 ----
*** old-NetBSD/src/sys/kern/init_sysent.c
--- NetBSD/src/sys/kern/init_sysent.c
***************
*** 950,953 ****
nosys }, /* 231 = unimplemented shmget */
#endif
};
-
--- 950,952 ----
*** old-NetBSD/src/sys/kern/kern_sysctl.c
--- NetBSD/src/sys/kern/kern_sysctl.c
***************
*** 57,63 ****
--- 57,65 ----
#include <vm/vm.h>
#include <sys/sysctl.h>
+ #include <sys/emul.h>
#include <sys/mount.h>
+ #include <sys/syscall.h>
#include <sys/syscallargs.h>
sysctlfn kern_sysctl;
***************
*** 205,212 ****
int error, level, inthostid;
extern char ostype[], osrelease[], version[];
! /* all sysctl names at this level are terminal */
! if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
return (ENOTDIR); /* overloaded */
switch (name[0]) {
--- 207,218 ----
int error, level, inthostid;
extern char ostype[], osrelease[], version[];
! /*
! * all sysctl names at this level are terminal except for "proc",
! * "prof" & "syscall"
! */
! if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF ||
! name[0] == KERN_EMUL))
return (ENOTDIR); /* overloaded */
switch (name[0]) {
***************
*** 284,289 ****
--- 290,300 ----
return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
case KERN_RAWPARTITION:
return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
+ case KERN_NEMULS:
+ return (sysctl_rdint(oldp, oldlenp, newp, nemuls));
+ case KERN_EMUL:
+ return (sysctl_doemul(name + 1, namelen - 1, oldp, oldlenp,
+ newp));
default:
return (EOPNOTSUPP);
}
***************
*** 590,596 ****
int error = 0;
if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
! return (EINVAL);
p = allproc.lh_first;
doingzomb = 0;
again:
--- 601,607 ----
int error = 0;
if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
! return (ENOTDIR);
p = allproc.lh_first;
doingzomb = 0;
again:
***************
*** 719,721 ****
--- 730,775 ----
ep->e_xccount = ep->e_xswrss = 0;
}
+ /*
+ * Get emulation info
+ */
+ sysctl_doemul(name, namelen, where, sizep, newp)
+ int *name;
+ u_int namelen;
+ char *where;
+ size_t *sizep;
+ void *newp;
+ {
+ char **names;
+
+ /*
+ * This level holds emulation/var pairs only except for the syscall
+ * table which holds an index as well.
+ */
+ if ((namelen != 2 || name[1] == KERN_EMUL_SYSCALL) &&
+ (namelen != 3 || name[1] != KERN_EMUL_SYSCALL))
+ return (ENOTDIR);
+ /* Check for valid emulations */
+ if (name[0] < 0 || name[0] >= nemuls)
+ return (EOPNOTSUPP);
+ switch (name[1]) {
+ case KERN_EMUL_NAME:
+ return (sysctl_rdstring(where, sizep, newp,
+ emulsw[name[0]].em_name));
+ break;
+ case KERN_EMUL_MAXSYSCALL:
+ return (sysctl_rdint(where, sizep, newp,
+ emulsw[name[0]].em_maxsyscall));
+ break;
+ case KERN_EMUL_SYSCALL:
+ /* Check to see we're inside the syscallnames array */
+ if (name[2] < 0 || name[2] >= emulsw[name[0]].em_maxsyscall)
+ return (EOPNOTSUPP);
+ names = emulsw[name[0]].em_syscallnames;
+ return (sysctl_rdstring (where, sizep, newp,
+ names == NULL ? "" : names[name[2]]));
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ }
*** /dev/null
--- NetBSD/src/sys/sys/emul.h
***************
*** 0 ****
--- 1,40 ----
+ /* $NetBSD: emul.h,v 1.1 1995/08/27 23:30:47 niklas Exp $ */
+
+ /*
+ * Copyright (c) 1995 Niklas Hallqvist
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+ struct emulsw {
+ char *em_name;
+ int em_maxsyscall;
+ char **em_syscallnames;
+ };
+
+ extern struct emulsw emulsw[];
+ extern int nemuls;
*** old-NetBSD/src/sys/sys/sysctl.h
--- NetBSD/src/sys/sys/sysctl.h
***************
*** 132,138 ****
#define KERN_DOMAINNAME 22 /* string: (YP) domainname */
#define KERN_MAXPARTITIONS 23 /* int: number of partitions/disk */
#define KERN_RAWPARTITION 24 /* int: raw partition number */
! #define KERN_MAXID 25 /* number of valid kern ids */
#define CTL_KERN_NAMES { \
{ 0, 0 }, \
--- 132,140 ----
#define KERN_DOMAINNAME 22 /* string: (YP) domainname */
#define KERN_MAXPARTITIONS 23 /* int: number of partitions/disk */
#define KERN_RAWPARTITION 24 /* int: raw partition number */
! #define KERN_NEMULS 25 /* int: emulation table size */
! #define KERN_EMUL 26 /* node: emulation info */
! #define KERN_MAXID 27 /* number of valid kern ids */
#define CTL_KERN_NAMES { \
{ 0, 0 }, \
***************
*** 160,165 ****
--- 162,169 ----
{ "domainname", CTLTYPE_STRING }, \
{ "maxpartitions", CTLTYPE_INT }, \
{ "rawpartition", CTLTYPE_INT }, \
+ { "nemuls", CTLTYPE_INT }, \
+ { "emul", CTLTYPE_NODE }, \
}
/*
***************
*** 203,208 ****
--- 207,226 ----
long e_spare[4];
} kp_eproc;
};
+
+ /*
+ * KERN_EMUL identifiers
+ */
+ #define KERN_EMUL_NAME 0 /* string: emulation name */
+ #define KERN_EMUL_MAXSYSCALL 1 /* int: maximum syscall# + 1 */
+ #define KERN_EMUL_SYSCALL 2 /* node: syscall table */
+ #define KERN_EMUL_MAXID 3
+
+ #define KERN_EMUL_NAMES { \
+ { "name", CTLTYPE_STRING }, \
+ { "maxsyscall", CTLTYPE_INT }, \
+ { "syscall", CTLTYPE_NODE }, \
+ }
/*
* CTL_HW identifiers
*** old-NetBSD/src/sys/sys/systm.h
--- NetBSD/src/sys/sys/systm.h
***************
*** 98,104 ****
short sy_argsize; /* total size of arguments */
int (*sy_call)(); /* implementing function */
} sysent[];
- extern int nsysent;
#define SCARG(p,k) ((p)->k.datum) /* get arg from args pointer */
extern int boothowto; /* reboot flags, from console subsystem */
--- 98,103 ----
*** /dev/null
--- NetBSD/src/usr.bin/file/magdir/ktrace
***************
*** 0 ****
--- 1,5 ----
+
+ #------------------------------------------------------------------------------
+ # archive: file(1) magic for ktrace files
+ #
+ 0 long 0x3ace0100 ktrace(1) dump version 1.0
*** old-NetBSD/src/usr.bin/kdump/kdump.c
--- NetBSD/src/usr.bin/kdump/kdump.c
***************
*** 51,56 ****
--- 51,58 ----
#include <sys/ktrace.h>
#include <sys/ioctl.h>
#include <sys/ptrace.h>
+ #include <sys/syscall.h>
+ #include <sys/sysctl.h>
#define _KERNEL
#include <sys/errno.h>
#undef _KERNEL
***************
*** 94,105 ****
#undef KTRACE
struct emulation {
! char *name; /* Emulation name */
char **sysnames; /* Array of system call names */
! int nsysnames; /* Number of */
};
! static struct emulation emulations[] = {
{ "netbsd", syscallnames, SYS_MAXSYSCALL },
{ "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL },
{ "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL },
--- 96,107 ----
#undef KTRACE
struct emulation {
! char *name; /* Emulation name */
char **sysnames; /* Array of system call names */
! int nsysnames; /* Number of system calls */
};
! static struct emulation static_emulations[] = {
{ "netbsd", syscallnames, SYS_MAXSYSCALL },
{ "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL },
{ "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL },
***************
*** 111,118 ****
--- 113,142 ----
{ NULL, NULL, NULL }
};
+ int nemul;
+ static struct emulation *emul = static_emulations;
+
+ struct emulation_map {
+ struct emulation_map *em_link;
+ pid_t em_pid;
+ struct emulation *em_emulation;
+ };
+
+ /* Forward decls. */
+ struct emulation *emulation_from_name __P((char *name));
+ struct emulation *emulation_from_pid __P((pid_t pid));
+ void bind_emulation_to_pid __P((struct emulation *, pid_t));
+ void get_emulations __P((FILE *, char *));
+
+ /* A mapping between pids and emulations currently in charge. */
+ struct emulation_map *current_emulations;
+
+ /* The current emulation (cache during a single trace event). */
struct emulation *current;
+ /* The default emulation, if nothing else is known. */
+ struct emulation *default_emulation;
+
static char *ptrace_ops[] = {
"PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
***************
*** 128,140 ****
int ch, ktrlen, size;
register void *m;
int trpoints = ALL_POINTS;
! current = &emulations[0]; /* NetBSD */
while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
switch (ch) {
case 'e':
! setemul(optarg);
break;
case 'f':
tracefile = optarg;
--- 152,165 ----
int ch, ktrlen, size;
register void *m;
int trpoints = ALL_POINTS;
+ char *default_emulation_name;
! default_emulation_name = "netbsd";
while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
switch (ch) {
case 'e':
! default_emulation_name = optarg;
break;
case 'f':
tracefile = optarg;
***************
*** 176,182 ****
--- 201,210 ----
errx(1, "%s", strerror(ENOMEM));
if (!freopen(tracefile, "r", stdin))
err(1, "%s", tracefile);
+ get_emulations(stdin, tracefile);
+ default_emulation = emulation_from_name(default_emulation_name);
while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
+ current = emulation_from_pid(ktr_header.ktr_pid);
if (trpoints & (1<<ktr_header.ktr_type))
dumpheader(&ktr_header);
if ((ktrlen = ktr_header.ktr_len) < 0)
***************
*** 211,217 ****
ktrcsw((struct ktr_csw *)m);
break;
case KTR_EMUL:
! ktremul(m, ktrlen);
break;
}
if (tail)
--- 239,245 ----
ktrcsw((struct ktr_csw *)m);
break;
case KTR_EMUL:
! ktremul(m, ktrlen, ktr_header.ktr_pid);
break;
}
if (tail)
***************
*** 381,388 ****
(void)printf("\"%.*s\"\n", len, cp);
}
! ktremul(cp, len)
char *cp;
{
char name[1024];
--- 409,417 ----
(void)printf("\"%.*s\"\n", len, cp);
}
! ktremul(cp, len, pid)
char *cp;
+ pid_t pid;
{
char name[1024];
***************
*** 393,399 ****
name[len] = '\0';
(void)printf("\"%s\"\n", name);
! setemul(name);
}
ktrgenio(ktr, len)
--- 422,428 ----
name[len] = '\0';
(void)printf("\"%s\"\n", name);
! bind_emulation_to_pid(emulation_from_name(name), pid);
}
ktrgenio(ktr, len)
***************
*** 484,497 ****
exit(1);
}
! setemul(name)
char *name;
{
int i;
! for (i = 0; emulations[i].name != NULL; i++)
! if (strcmp(emulations[i].name, name) == 0) {
! current = &emulations[i];
return;
}
! warnx("Emulation `%s' unknown", name);
}
--- 513,618 ----
exit(1);
}
! struct emulation *
! emulation_from_name(name)
char *name;
{
int i;
!
! for (i = 0; i < nemul; i++)
! if (eqs(emul[i].name, name))
! return emul + i;
! warnx("Emulation `%s' unknown, using default `%s'", name,
! default_emulation->name);
! return default_emulation;
! }
!
! struct emulation *
! emulation_from_pid(pid)
! pid_t pid;
! {
! struct emulation_map *entry;
!
! for (entry = current_emulations; entry; entry = entry->em_link)
! if (entry->em_pid == pid)
! return entry->em_emulation;
! return default_emulation;
! }
!
! void
! bind_emulation_to_pid(emulation, pid)
! struct emulation *emulation;
! pid_t pid;
! {
! struct emulation_map *entry;
!
! for (entry = current_emulations; entry; entry = entry->em_link)
! if (entry->em_pid == pid) {
! entry->em_emulation = emulation;
return;
}
! entry = current_emulations;
! current_emulations =
! (struct emulation_map *)malloc(sizeof(struct emulation_map));
! if (current_emulations == NULL)
! errx(1, "%s", strerror(ENOMEM));
! current_emulations->em_link = entry;
! current_emulations->em_pid = pid;
! current_emulations->em_emulation = emulation;
! }
!
! int
! get_int(f, tracefile)
! FILE *f;
! char *tracefile;
! {
! int i;
!
! if (fread(&i, sizeof(i), 1, f) != 1)
! err(1, "%s", tracefile);
! return i;
! }
!
! void
! get_emulations(f, tracefile)
! FILE *f;
! char *tracefile;
! {
! fpos_t start;
! int i;
! int j;
! int len;
!
! if (fgetpos(f, &start))
! err(1, "%s", tracefile);
! if (get_int(f, tracefile) != KTRACE_MAGIC) {
! fsetpos(f, &start);
! return;
! }
! nemul = get_int(f, tracefile);
! emul = (struct emulation *)malloc(nemul * sizeof(*emul));
! if (emul == NULL)
! errx(1, "%s", strerror(ENOMEM));
! for (i = 0; i < nemul; i++) {
! len = get_int(f, tracefile);
! emul[i].name = malloc(len + 1);
! if (emul[i].name == NULL)
! errx(1, "%s", strerror(ENOMEM));
! if (fread(emul[i].name, sizeof(char), len, f) != len)
! err(1, "%s", tracefile);
! emul[i].nsysnames = get_int(f, tracefile);
! emul[i].sysnames = (char **)malloc(emul[i].nsysnames *
! sizeof(*emul[i].sysnames));
! if (emul[i].sysnames == NULL)
! errx(1, "%s", strerror(ENOMEM));
! for (j = 0; j < emul[i].nsysnames; j++) {
! len = get_int(f, tracefile);
! emul[i].sysnames[j] = malloc(len + 1);
! if (emul[i].sysnames[j] == NULL)
! errx(1, "%s", strerror(ENOMEM));
! if (fread(emul[i].sysnames[j], sizeof(char), len, f) !=
! len)
! err(1, "%s", tracefile);
! }
! }
}
*** old-NetBSD/src/usr.bin/ktrace/ktrace.c
--- NetBSD/src/usr.bin/ktrace/ktrace.c
***************
*** 53,67 ****
--- 53,71 ----
#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/ktrace.h>
+ #include <sys/sysctl.h>
#include <err.h>
#include <stdio.h>
+ #include <stdlib.h>
#include <unistd.h>
#include "ktrace.h"
void no_ktrace __P((int));
void usage __P((void));
+ void dump_int __P((FILE *, char *, int));
+ void dump_sysctls __P((int, char *));
main(argc, argv)
int argc;
***************
*** 140,145 ****
--- 144,151 ----
if ((fd = open(tracefile, O_CREAT | O_WRONLY | (append ? 0 : O_TRUNC),
DEFFILEMODE)) < 0)
err(1, tracefile);
+ if (!append)
+ dump_sysctls(fd, tracefile);
(void)close(fd);
if (*argv) {
***************
*** 184,187 ****
--- 190,309 ----
(void)fprintf(stderr,
"error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'options KTRACE'\n");
exit(1);
+ }
+
+ void
+ dump_int(f, tracefile, i)
+ FILE *f;
+ char *tracefile;
+ int i;
+ {
+ /* Should we store this in arch-independent format? */
+ if (fwrite(&i, sizeof(i), 1, f) != 1) {
+ unlink(tracefile);
+ err(1, "%s", tracefile);
+ }
+ }
+
+ void
+ dump_sysctls(fd, tracefile)
+ int fd;
+ char *tracefile;
+ {
+ FILE *f;
+ int mib[5];
+ int len;
+ int i;
+ int j;
+ int nemuls;
+ int size;
+ struct emul {
+ char *name;
+ int nsyscalls;
+ char **syscall;
+ } *emul;
+
+ f = fdopen(fd, "w");
+ if (f == NULL)
+ err(1, "%d", tracefile);
+
+ /* Number of emulations */
+ len = 0;
+ mib[len++] = CTL_KERN;
+ mib[len++] = KERN_NEMULS;
+ size = sizeof(nemuls);
+ if (sysctl(mib, len, &nemuls, &size, NULL, 0) < 0)
+ return;
+
+ /* Emulation table */
+ emul = (struct emul *)malloc(nemuls * sizeof(*emul));
+ if (emul == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ for (i = 0; i < nemuls; i++) {
+ /* Emulation name */
+ len = 0;
+ mib[len++] = CTL_KERN;
+ mib[len++] = KERN_EMUL;
+ mib[len++] = i;
+ mib[len++] = KERN_EMUL_NAME;
+ if (sysctl(mib, len, NULL, &size, NULL, 0) < 0)
+ return;
+ emul[i].name = malloc(size);
+ if (emul[i].name == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ if (sysctl(mib, len, emul[i].name, &size, NULL, 0) < 0)
+ return;
+
+ /* Number of syscalls */
+ len = 0;
+ mib[len++] = CTL_KERN;
+ mib[len++] = KERN_EMUL;
+ mib[len++] = i;
+ mib[len++] = KERN_EMUL_MAXSYSCALL;
+ size = sizeof(emul[i].nsyscalls);
+ if (sysctl(mib, len, &emul[i].nsyscalls, &size, NULL, 0) < 0)
+ return;
+
+ /* Syscalls */
+ emul[i].syscall = (char **)malloc(emul[i].nsyscalls *
+ sizeof(*emul[i].syscall));
+ if (emul[i].syscall == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ for (j = 0; j < emul[i].nsyscalls; j++) {
+ len = 0;
+ mib[len++] = CTL_KERN;
+ mib[len++] = KERN_EMUL;
+ mib[len++] = i;
+ mib[len++] = KERN_EMUL_SYSCALL;
+ mib[len++] = j;
+ if (sysctl(mib, len, NULL, &size, NULL, 0) < 0)
+ return;
+ emul[i].syscall[j] = malloc(size);
+ if (emul[i].syscall[j] == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ if (sysctl(mib, len, emul[i].syscall[j], &size, NULL,
+ 0) < 0)
+ return;
+ }
+ }
+
+ /* Ok all info we need got extracted, now dump it. */
+ dump_int(f, tracefile, KTRACE_MAGIC);
+ dump_int(f, tracefile, nemuls);
+ for (i = 0; i < nemuls; i++) {
+ dump_int(f, tracefile, strlen(emul[i].name));
+ if (fputs(emul[i].name, f) == EOF) {
+ unlink(tracefile);
+ err(1, "%s", tracefile);
+ }
+ dump_int(f, tracefile, emul[i].nsyscalls);
+ for (j = 0; j < emul[i].nsyscalls; j++) {
+ dump_int(f, tracefile, strlen(emul[i].syscall[j]));
+ if (fputs(emul[i].syscall[j], f) == EOF) {
+ unlink(tracefile);
+ err(1, "%s", tracefile);
+ }
+ }
+ }
+ fclose(f);
}
*** old-NetBSD/src/usr.bin/ktrace/ktrace.h
--- NetBSD/src/usr.bin/ktrace/ktrace.h
***************
*** 40,42 ****
--- 40,44 ----
#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
#define DEF_TRACEFILE "ktrace.out"
+
+ #define KTRACE_MAGIC 0x3ace0100
*** old-NetBSD/src/usr.sbin/sysctl/sysctl.c
--- NetBSD/src/usr.sbin/sysctl/sysctl.c
***************
*** 269,274 ****
--- 269,277 ----
case KERN_BOOTTIME:
special |= BOOTTIME;
break;
+ case KERN_EMUL:
+ sysctl_emul(mib, &len, &type, &bufp, string);
+ break;
}
break;
***************
*** 573,576 ****
--- 576,613 ----
"sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
"sysctl [-n] -a", "sysctl [-n] -A");
exit(1);
+ }
+
+ struct ctlname emulname[] = KERN_EMUL_NAMES;
+ struct list emullist = { emulname, KERN_EMUL_MAXID };
+
+ sysctl_emul(mib, lenp, typep, bufpp, string)
+ int *mib;
+ int *lenp;
+ int *typep;
+ char **bufpp;
+ char *string;
+ {
+ char *emulp;
+ char *syscallp;
+ int indx;
+
+ emulp = strsep (bufpp, ".");
+ if ((indx = findname(string, "fourth", bufpp, &emullist)) == -1)
+ return;
+ mib[(*lenp)++] = atoi(emulp);
+ mib[(*lenp)++] = indx;
+ switch (indx) {
+ case KERN_EMUL_NAME:
+ case KERN_EMUL_MAXSYSCALL:
+ *typep = emulname[indx].ctl_type;
+ break;
+ case KERN_EMUL_SYSCALL:
+ syscallp = strsep (bufpp, ".");
+ if (syscallp)
+ mib[(*lenp)++] = atoi(syscallp);
+ *typep = CTLTYPE_STRING;
+ break;
+ default:
+ }
}
>Audit-Trail:
>Unformatted: