From 8459d7254751dbe55e98bb49dd51e1796df2bb0d Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 24 Feb 2011 00:26:03 +0000 Subject: [PATCH] system_cmds-541.tar.gz --- Makefile | 6 +- ac.tproj/Makefile | 2 +- accton.tproj/Makefile | 2 +- arch.tproj/Makefile | 2 +- arch.tproj/arch.1 | 52 +- arch.tproj/arch.m | 257 +- at.tproj/Makefile | 2 +- atrun.tproj/Makefile | 2 +- bootlog.tproj/Makefile | 14 - bootlog.tproj/bootlog.8 | 41 - bootlog.tproj/bootlog.c | 92 - bootlog.tproj/com.apple.bootlog.plist | 16 - chkpasswd.tproj/Makefile | 4 +- chkpasswd.tproj/file_passwd.c | 8 +- chpass.tproj/Makefile | 4 +- chpass.tproj/chpass.c | 6 +- chpass.tproj/open_directory.c | 79 +- dirhelper.tproj/Makefile | 5 +- dirhelper.tproj/dirhelper.c | 150 +- dmesg.tproj/Makefile | 2 +- dynamic_pager.tproj/Makefile | 6 +- dynamic_pager.tproj/dynamic_pager.c | 207 +- fs_usage.tproj/Makefile | 2 +- fs_usage.tproj/fs_usage.1 | 34 +- fs_usage.tproj/fs_usage.c | 2771 +++++++++-------- getconf.tproj/Makefile | 2 +- getconf.tproj/sysconf.gperf | 2 +- getty.tproj/Makefile | 2 +- getty.tproj/chat.c | 2 +- hostinfo.tproj/Makefile | 2 +- iostat.tproj/Makefile | 2 +- iostat.tproj/iostat.c | 6 +- latency.tproj/Makefile | 2 +- latency.tproj/latency.1 | 37 +- latency.tproj/latency.c | 4135 ++++++++++++++----------- login.tproj/Makefile | 7 +- login.tproj/login.c | 145 +- login.tproj/login.h | 2 +- login.tproj/login.pam | 11 - login.tproj/login_audit.c | 65 +- login.tproj/pam.d/login | 12 + login.tproj/pam.d/login.term | 4 + makekey.tproj/Makefile | 2 +- mean.tproj/mean.c | 101 +- mkfile.tproj/Makefile | 2 +- newgrp.tproj/Makefile | 2 +- nologin.tproj/Makefile | 2 +- nvram.tproj/Makefile | 2 +- nvram.tproj/nvram.c | 9 +- passwd.tproj/Makefile | 7 +- passwd.tproj/file_passwd.c | 537 +--- passwd.tproj/od_passwd.c | 98 +- passwd.tproj/passwd.c | 5 - passwd.tproj/stringops.c | 244 -- passwd.tproj/stringops.h | 39 - pwd_mkdb.tproj/Makefile | 2 +- pwd_mkdb.tproj/pwd_mkdb.c | 4 +- reboot.tproj/Makefile | 2 +- sa.tproj/Makefile | 2 +- sadc.tproj/Makefile | 2 +- sadc.tproj/sadc.c | 2 +- sar.tproj/Makefile | 2 +- sc_usage.tproj/Makefile | 7 +- sc_usage.tproj/trace.codes | 1507 --------- shutdown.tproj/Makefile | 2 +- sync.tproj/Makefile | 2 +- sysctl.tproj/Makefile | 2 +- sysctl.tproj/sysctl.c | 136 +- trace.tproj/Makefile | 14 + trace.tproj/trace.1 | 60 + trace.tproj/trace.c | 2240 ++++++++++++++ vifs.tproj/Makefile | 2 +- vipw.tproj/Makefile | 2 +- vm_stat.tproj/Makefile | 2 +- zdump.tproj/Makefile | 2 +- zic.tproj/Makefile | 2 +- zprint.tproj/Makefile | 2 +- zprint.tproj/zprint.1 | 22 +- zprint.tproj/zprint.c | 454 ++- 79 files changed, 7457 insertions(+), 6271 deletions(-) delete mode 100644 bootlog.tproj/Makefile delete mode 100644 bootlog.tproj/bootlog.8 delete mode 100644 bootlog.tproj/bootlog.c delete mode 100644 bootlog.tproj/com.apple.bootlog.plist delete mode 100644 login.tproj/login.pam create mode 100644 login.tproj/pam.d/login create mode 100644 login.tproj/pam.d/login.term delete mode 100644 passwd.tproj/stringops.c delete mode 100644 passwd.tproj/stringops.h delete mode 100644 sc_usage.tproj/trace.codes create mode 100644 trace.tproj/Makefile create mode 100644 trace.tproj/trace.1 create mode 100644 trace.tproj/trace.c diff --git a/Makefile b/Makefile index ff782bf..a22f7b9 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,13 @@ Project = system_cmds Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) -SubProjects = ac.tproj accton.tproj arch.tproj bootlog.tproj \ +SubProjects = ac.tproj accton.tproj arch.tproj \ dmesg.tproj dp_notify_lib dynamic_pager.tproj fs_usage.tproj \ getconf.tproj getty.tproj hostinfo.tproj iostat.tproj \ latency.tproj login.tproj makekey.tproj mkfile.tproj \ newgrp.tproj nologin.tproj nvram.tproj pagesize.tproj \ passwd.tproj pwd_mkdb.tproj reboot.tproj sa.tproj sadc.tproj \ - sar.tproj sc_usage.tproj sync.tproj sysctl.tproj \ + sar.tproj sc_usage.tproj sync.tproj sysctl.tproj trace.tproj \ vipw.tproj vifs.tproj vm_stat.tproj zdump.tproj zic.tproj \ zprint.tproj @@ -19,6 +19,4 @@ else SubProjects += mean.tproj endif -Extra_LD_Flags += -lcurses -lutil - include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/ac.tproj/Makefile b/ac.tproj/Makefile index 3977061..77e166a 100644 --- a/ac.tproj/Makefile +++ b/ac.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = ac.c MANPAGES = ac.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/accton.tproj/Makefile b/accton.tproj/Makefile index 6a0e9a1..5e5d34e 100644 --- a/accton.tproj/Makefile +++ b/accton.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = accton.c MANPAGES = accton.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -D__FBSDID=__RCSID Extra_LD_Flags = -dead_strip diff --git a/arch.tproj/Makefile b/arch.tproj/Makefile index 7b0f0ea..b0d2eca 100644 --- a/arch.tproj/Makefile +++ b/arch.tproj/Makefile @@ -6,7 +6,7 @@ Extra_Frameworks = -framework Foundation MANPAGES = arch.1 machine.1 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_CC_Flags += -DARCH_PROG=\"arch\" -DMACHINE_PROG=\"machine\" diff --git a/arch.tproj/arch.1 b/arch.tproj/arch.1 index 2d12478..909bac5 100644 --- a/arch.tproj/arch.1 +++ b/arch.tproj/arch.1 @@ -31,7 +31,7 @@ .\" Modifications made 8/20/97 (c) Apple Computer, Inc. .\" Modifications made 11/12/06 (c) Apple Computer, Inc. -.Dd November 12, 2006 +.Dd July 8, 2010 .Dt ARCH 1 .Os "Mac OS X" .Sh NAME @@ -40,10 +40,15 @@ .Sh SYNOPSIS .Nm arch .Nm arch -.Op Fl h +.Op Fl 32 +.Op Fl 64 .Oo .Oo Fl Ns Ar arch_name | Fl arch Ar arch_name Oc Ns ... .Oc +.Op Fl c +.Oo Fl d Ar envname Oc Ns ... +.Oo Fl e Ar envname=value Oc Ns ... +.Op Fl h .Ar prog .Op Ar args No ... .Sh DESCRIPTION @@ -76,19 +81,11 @@ The most common use is to select the 32-bit architecture on a 64-bit processor, even if a 64-bit architecture is available. .Pp The -.Fl h -option prints a usage message and exits. -.Pp -The .Ar arch_name argument must be one of the currently supported architectures: .Bl -tag -width x86_64 -offset indent .It i386 32-bit intel -.It ppc -32-bit powerpc -.It ppc64 -64-bit powerpc .It x86_64 64-bit intel .El @@ -102,6 +99,25 @@ If more than one architecture is specified, the operating system will try each one in order, skipping an architecture that is not supported on the current processor, or is unavailable in the universal binary. .Pp +The other options are: +.Bl -tag -width ".Fl e Ar envname=value" +.It Fl 32 +Add the native 32-bit architecture to the list of architectures. +.It Fl 64 +Add the native 64-bit architecture to the list of architectures. +.It Fl c +Clears the environment that will be passed to the command to be run. +.It Fl d Ar envname +Deletes the named environment variable from the environment that will be passed +to the command to be run. +.It Fl e Ar envname=value +Assigns the given value to the named environment variable in the environment +that will be passed to the command to be run. +Any existing environment variable with the same name will be replaced. +.It Fl h +Prints a usage message and exits. +.El +.Pp The .Ar prog argument is the command to run, followed by any arguments to pass to the @@ -141,13 +157,7 @@ On an intel processor: 1234 .Ed .Pp -shows the intel little endian byte order, while: -.Bd -literal -offset indent -% arch -ppc perl -MConfig -e 'printf "%s\\n", $Config{byteorder}' -4321 -.Ed -.Pp -runs the powerpc architecture, and displays big endian byte order. +shows the intel little endian byte order. .Ss Making links to the arch command When a link is made to .Nm arch @@ -199,17 +209,17 @@ If not specified as a second field in a specifier, the executable path will be looked up in the corresponding property list file. .Ss Example ARCHPREFERENCE Values .Bl -tag -width " " -.It ppc,i386,ppc64,x86_64 +.It i386,x86_64 A specifier that matches any name. -.It foo:ppc,i386,ppc64,x86_64 +.It foo:i386,x86_64 A specifier that matches the program named .Nm foo (the full executable path is in the .Pa foo.plist file). -.It foo:/op/bin/boo:ppc,i386,ppc64,x86_64 +.It foo:/op/bin/boo:i386,x86_64 A specifier with all fields specified. -.It baz:ppc,i386;i386,ppc +.It baz:i386;x86_64 A specifier for .Nm baz and a second specifier that would match any other name. diff --git a/arch.tproj/arch.m b/arch.tproj/arch.m index be4b58e..b36277a 100644 --- a/arch.tproj/arch.m +++ b/arch.tproj/arch.m @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -65,18 +66,69 @@ typedef struct { } CPU; typedef struct { - char *str; - int i; -} StrInt; + const char *arch; + int cpu; +} CPUTypes; -static StrInt initArches[] = { +static const CPUTypes initArches[] = { +#if defined(__i386__) || defined(__x86_64__) {"i386", CPU_TYPE_I386}, - {"ppc", CPU_TYPE_POWERPC}, - {"ppc64", CPU_TYPE_POWERPC64}, {"x86_64", CPU_TYPE_X86_64}, - {NULL, 0} +#elif defined(__arm__) + {"arm", CPU_TYPE_ARM}, +#else +#error "Unsupported architecture" +#endif + {NULL, 0} // sentinel }; +/* + * ignore contains architectures supported by previous releases, but + * now unsupported. The seen field will be set to true if the corresponding + * architecture was specified. + */ + +typedef struct { + const char *arch; + bool seen; +} Ignore; + +static Ignore ignore[] = { +#if defined(__i386__) || defined(__x86_64__) + {"ppc", false}, + {"ppc64", false}, +#endif + {NULL, false} // sentinel +}; + +/* The total number of architectures specified */ +static int archCount = 0; + +/* environment SPI */ +char **_copyenv(char **env); +int _setenvp(const char *name, const char *value, int rewrite, char ***envp, void *state); +int _unsetenvp(const char *name, char ***envp, void *state); + +/* copy of environment */ +char **envCopy = NULL; +extern char **environ; + +/* + * The native 32 and 64-bit architectures (this is relative to the architecture + * the arch command is running. NULL means unsupported. + */ +#if defined(__i386__) || defined(__x86_64__) +#define NATIVE_32 "i386" +#define NATIVE_64 "x86_64" +#elif defined(__arm__) +#define NATIVE_32 "arm" +#define NATIVE_64 NULL +#else +#error "Unsupported architecture" +#endif +bool native32seen = false; +bool native64seen = false; + /* * arch - perform the original behavior of the arch and machine commands. * The archcmd flag is non-zero for the arch command, zero for the machine @@ -99,20 +151,43 @@ arch(int archcmd) } /* - * spawnIt - run the posix_spawn command. count is the number of CPU types - * in the prefs array. pflag is non-zero to call posix_spawnp; zero means to - * call posix_spawn. str is the name/path to pass to posix_spawn{,p}, and - * argv and environ are the argument and environment arrays to pass. This - * routine never returns. + * spawnIt - run the posix_spawn command. cpu is the auto-sizing CPU structure. + * pflag is non-zero to call posix_spawnp; zero means to call posix_spawn. + * str is the name/path to pass to posix_spawn{,p}, and argv are + * the argument arrays to pass. This routine never returns. */ static void __dead2 -spawnIt(int count, cpu_type_t *prefs, int pflag, const char *str, char **argv, char **environ) +spawnIt(CPU *cpu, int pflag, const char *str, char **argv) { - posix_spawnattr_t attr; pid_t pid; int ret; size_t copied; + const Ignore *ip; + int count = CPUCOUNT(cpu); + cpu_type_t *prefs = cpu->buf; + + if(count == 0) { + if(archCount == 0) // shouldn't happen + errx(1, "spawnIt called with no architectures specified"); + for(ip = ignore; ip->arch; ip++) { + if(ip->seen) + warnx("Unsupported architecture: %s", ip->arch); + } + if(native32seen) + warnx("Unsupported native 32-bit architecture"); + if(native64seen) + warnx("Unsupported native 64-bit architecture"); + exit(1); + } + for(ip = ignore; ip->arch; ip++) { + if(ip->seen) + fprintf(stderr, "warning: unsupported architecture: %s\n", ip->arch); + } + if(native32seen) + fprintf(stderr, "warning: unsupported native 32-bit architecture\n"); + if(native64seen) + fprintf(stderr, "warning: unsupported native 64-bit architecture\n"); if((ret = posix_spawnattr_init(&attr)) != 0) errc(1, ret, "posix_spawnattr_init"); @@ -124,9 +199,9 @@ spawnIt(int count, cpu_type_t *prefs, int pflag, const char *str, char **argv, c if(copied != count) errx(1, "posix_spawnattr_setbinpref_np only copied %d of %d", (int)copied, count); if(pflag) - ret = posix_spawnp(&pid, str, NULL, &attr, argv, environ); + ret = posix_spawnp(&pid, str, NULL, &attr, argv, envCopy ? envCopy : environ); else - ret = posix_spawn(&pid, str, NULL, &attr, argv, environ); + ret = posix_spawn(&pid, str, NULL, &attr, argv, envCopy ? envCopy : environ); errc(1, ret, "posix_spawn%s: %s", (pflag ? "p" : ""), str); } @@ -152,6 +227,11 @@ initCPU(CPU *cpu) static void addCPU(CPU *cpu, int n) { + archCount++; + if(n <= 0) { // ignore values + ignore[-n].seen = true; // negate to get real index + return; + } if(cpu->ptr >= cpu->end) { cpu_type_t *new = realloc(cpu->buf, (cpu->end - cpu->buf + CPUDELTA) * sizeof(cpu_type_t)); if(!new) @@ -235,7 +315,7 @@ useEnv(CPU *cpu, const char *name, char **execpath) continue; /* no cpu list, so skip */ /* if the name matches, or there is no name, process the cpus */ if(!*n || strcmp(n, cp) == 0) { - if(CPUCOUNT(cpu) <= 0) { /* only if we don't already have cpu types */ + if(archCount <= 0) { /* only if we haven't processed architectures */ char *t; while((t = strsep(&blk, ",")) != NULL) addCPUbyname(cpu, t); @@ -244,7 +324,7 @@ useEnv(CPU *cpu, const char *name, char **execpath) break; } } else { /* no colons at all, so process as default */ - if(CPUCOUNT(cpu) <= 0) { /* only if we don't already have cpu types */ + if(archCount <= 0) { /* only if we haven't processed architectures */ blk = n; while((n = strsep(&blk, ",")) != NULL) addCPUbyname(cpu, n); @@ -255,7 +335,7 @@ useEnv(CPU *cpu, const char *name, char **execpath) } if(cpu->errs) /* errors during addCPUbyname are fatal */ exit(1); - return CPUCOUNT(cpu); /* return count of cpus */ + return archCount; /* return count of architectures */ } /* @@ -268,7 +348,7 @@ useEnv(CPU *cpu, const char *name, char **execpath) * This routine never returns. */ static void __dead2 -spawnFromPreferences(CPU *cpu, int needexecpath, char **argv, char **environ) +spawnFromPreferences(CPU *cpu, int needexecpath, char **argv) { char *epath = NULL; int count; @@ -284,10 +364,10 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv, char **environ) if((count = useEnv(cpu, prog, &epath)) > 0) { /* if we were called as arch, use posix_spawnp */ if(!needexecpath) - spawnIt(count, cpu->buf, 1, (epath ? epath : *argv), argv, environ); + spawnIt(cpu, 1, (epath ? epath : *argv), argv); /* otherwise, if we have the executable path, call posix_spawn */ if(epath) - spawnIt(count, cpu->buf, 0, epath, argv, environ); + spawnIt(cpu, 0, epath, argv); } /* pathArray is use to build the .plist file path for each domain */ @@ -365,7 +445,7 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv, char **environ) warnx("%s: no entries in %s", [path UTF8String], [KeyPrefOrder UTF8String]); errs++; } else { - /* finally but the cpu type array */ + /* finally build the cpu type array */ for(i = 0; i < count; i++) { id a = [(NSArray *)p objectAtIndex: i]; NSNumber *n; @@ -385,7 +465,7 @@ spawnFromPreferences(CPU *cpu, int needexecpath, char **argv, char **environ) exit(1); /* call posix_spawn */ - spawnIt(count, cpu->buf, 0, [execpath fileSystemRepresentation], argv, environ); + spawnIt(cpu, 0, [execpath fileSystemRepresentation], argv); } static void __dead2 @@ -394,10 +474,13 @@ usage(int ret) fprintf(stderr, "Usage: %s\n" " Display the machine's architecture type\n" - "Usage: %s [-h] [[-arch_name | -arch arch_name] ...] prog [arg ...]\n" + "Usage: %s {-arch_name | -arch arch_name} ... [-c] [-d envname] ... [-e envname=value] ... [-h] prog [arg ...]\n" " Run prog with any arguments, using the given architecture\n" " order. If no architectures are specified, use the\n" " ARCHPREFERENCE environment variable, or a property list file.\n" + " -c will clear out all environment variables before running prog.\n" + " -d will delete the given environment variable before running prog.\n" + " -e will add the given environment variable/value before running prog.\n" " -h will print usage message and exit.\n", ARCH_PROG, ARCH_PROG); exit(ret); @@ -481,23 +564,89 @@ wrapped(const char *name) * If no commandline cpu names are given, the environment variable * ARCHPREFERENCE is used. This routine never returns. */ + +#define MATCHARG(a,m) ({ \ + const char *arg = *(a); \ + if(arg[1] == '-') arg++; \ + strcmp(arg, (m)) == 0; \ +}) + +#define MATCHARGWITHVALUE(a,m,n,e) ({ \ + const char *ret = NULL; \ + const char *arg = *(a); \ + if(arg[1] == '-') arg++; \ + if(strcmp(arg, (m)) == 0) { \ + if(*++(a) == NULL) { \ + warnx(e); \ + usage(1); \ + } \ + ret = *(a); \ + } else if(strncmp(arg, (m), (n)) == 0 && arg[n] == '=') { \ + ret = arg + (n) + 1; \ + } \ + ret; \ +}) + +#define MAKEENVCOPY(e) \ + if(!envCopy) { \ + envCopy = _copyenv(environ); \ + if(envCopy == NULL) \ + errx(1, (e)); \ + } + static void __dead2 -spawnFromArgs(CPU *cpu, char **argv, char **environ) +spawnFromArgs(CPU *cpu, char **argv) { - char *ap; + const char *ap, *ret; - /* process cpu options */ + /* process arguments */ for(argv++; *argv && **argv == '-'; argv++) { - if(strcmp(*argv, "-arch") == 0) { - if(*++argv == NULL) { - warnx("-arch without architecture"); + if((ret = MATCHARGWITHVALUE(argv, "-arch", 5, "-arch without architecture"))) { + ap = ret; + } else if(MATCHARG(argv, "-32")) { + ap = NATIVE_32; + if(!ap) { + native32seen = true; + archCount++; + continue; + } + } else if(MATCHARG(argv, "-64")) { + ap = NATIVE_64; + if(!ap) { + native64seen = true; + archCount++; + continue; + } + } else if(MATCHARG(argv, "-c")) { + free(envCopy); + envCopy = _copyenv(NULL); // create empty environment + if(!envCopy) + errx(1, "Out of memory processing -c"); + continue; + } else if((ret = MATCHARGWITHVALUE(argv, "-d", 2, "-d without envname"))) { + MAKEENVCOPY("Out of memory processing -d"); + _unsetenvp(ret, &envCopy, NULL); + continue; + } else if((ret = MATCHARGWITHVALUE(argv, "-e", 2, "-e without envname=value"))) { + MAKEENVCOPY("Out of memory processing -e"); + const char *cp = strchr(ret, '='); + if(!cp) { + warnx("-e %s: no equal sign", ret); usage(1); } - ap = *argv; - } else if(strcmp(*argv, "-h") == 0) { + cp++; // skip to value + /* + * _setenvp() only uses the name before any equal sign found in + * the first argument. + */ + _setenvp(ret, cp, 1, &envCopy, NULL); + continue; + } else if(MATCHARG(argv, "-h")) { usage(0); - } else + } else { ap = *argv + 1; + if(*ap == '-') ap++; + } addCPUbyname(cpu, ap); } if(cpu->errs) @@ -513,14 +662,13 @@ spawnFromArgs(CPU *cpu, char **argv, char **environ) * If we don't have any architecutures, try ARCHPREFERENCE and plist * files. */ - int count = CPUCOUNT(cpu); - if(count <= 0 || needexecpath) - spawnFromPreferences(cpu, needexecpath, argv, environ); /* doesn't return */ + if(archCount <= 0 || needexecpath) + spawnFromPreferences(cpu, needexecpath, argv); /* doesn't return */ /* * Call posix_spawnp on the program name. */ - spawnIt(count, cpu->buf, 1, *argv, argv, environ); + spawnIt(cpu, 1, *argv, argv); } /* @@ -533,14 +681,29 @@ init(CPU *cpu) ArchDict = [NSMutableDictionary dictionaryWithCapacity: 4]; if(!ArchDict) errx(1, "Can't create NSMutableDictionary"); - StrInt *sp; - for(sp = initArches; sp->str; sp++) { - NSString *s = [NSString stringWithUTF8String: sp->str]; + const CPUTypes *cp; + for(cp = initArches; cp->arch; cp++) { + NSString *s = [NSString stringWithUTF8String: cp->arch]; + if(!s) + errx(1, "Can't create NSString for %s", cp->arch); + NSNumber *n = [NSNumber numberWithInt: cp->cpu]; + if(!n) + errx(1, "Can't create NSNumber for %s", cp->arch); + [ArchDict setObject: n forKey: s]; + } + /* + * The valid architecture numbers above are one or greater. The ignore + * values are the negative of the index in the ignore array. + */ + const Ignore *ip; + int i; + for(ip = ignore, i = 0; ip->arch; ip++, i--) { // i is negative of index + NSString *s = [NSString stringWithUTF8String: ip->arch]; if(!s) - errx(1, "Can't create NSString for %s", sp->str); - NSNumber *n = [NSNumber numberWithInt: sp->i]; + errx(1, "Can't create NSString for %s", ip->arch); + NSNumber *n = [NSNumber numberWithInt: i]; if(!n) - errx(1, "Can't create NSNumber for %s", sp->str); + errx(1, "Can't create NSNumber for %s", ip->arch); [ArchDict setObject: n forKey: s]; } initCPU(cpu); @@ -548,7 +711,7 @@ init(CPU *cpu) /* the main() routine */ int -main(int argc, char **argv, char **environ) +main(int argc, char **argv) { const char *prog = getprogname(); int my_name_is_arch; @@ -568,9 +731,9 @@ main(int argc, char **argv, char **environ) init(&cpu); /* initialize */ if(my_name_is_arch) - spawnFromArgs(&cpu, argv, environ); + spawnFromArgs(&cpu, argv); else - spawnFromPreferences(&cpu, 1, argv, environ); + spawnFromPreferences(&cpu, 1, argv); /* should never get here */ [pool release]; errx(1, "returned from spawn"); diff --git a/at.tproj/Makefile b/at.tproj/Makefile index 2704d3a..460fd57 100644 --- a/at.tproj/Makefile +++ b/at.tproj/Makefile @@ -7,7 +7,7 @@ MANPAGES = at.1 PROJECT_HEADERS = privs.h pathnames.h -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -D__FBSDID=__RCSID -DDAEMON_UID=1 -DDAEMON_GID=1 \ -DDEFAULT_AT_QUEUE='a' -DDEFAULT_BATCH_QUEUE='b' \ -DPERM_PATH=\"/usr/lib/cron/\" \ diff --git a/atrun.tproj/Makefile b/atrun.tproj/Makefile index 2d9ea9d..8ad9eab 100644 --- a/atrun.tproj/Makefile +++ b/atrun.tproj/Makefile @@ -6,7 +6,7 @@ CFILES = atrun.c MANPAGES = atrun.8 LAUNCHD_PLISTS = com.apple.atrun.plist -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -DDAEMON_UID=1 -DDAEMON_GID=1 -I../at.tproj Extra_LD_Flags = -dead_strip diff --git a/bootlog.tproj/Makefile b/bootlog.tproj/Makefile deleted file mode 100644 index 2cb67d9..0000000 --- a/bootlog.tproj/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -Project = bootlog -Install_Dir = /usr/libexec - -CFILES = bootlog.c -MANPAGES = bootlog.8 -LAUNCHD_PLISTS = com.apple.bootlog.plist - -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic -Extra_LD_Flags = -dead_strip - -include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make - -after_install: - plutil -convert binary1 "$(DSTROOT)/System/Library/LaunchDaemons/$(LAUNCHD_PLISTS)" diff --git a/bootlog.tproj/bootlog.8 b/bootlog.tproj/bootlog.8 deleted file mode 100644 index ae14b71..0000000 --- a/bootlog.tproj/bootlog.8 +++ /dev/null @@ -1,41 +0,0 @@ -.\" -.\" Copyright (c) 2006 Apple Computer, Inc. All rights reserved. -.\" -.\" @APPLE_LICENSE_HEADER_START@ -.\" -.\" This file contains Original Code and/or Modifications of Original Code -.\" as defined in and that are subject to the Apple Public Source License -.\" Version 2.0 (the 'License'). You may not use this file except in -.\" compliance with the License. Please obtain a copy of the License at -.\" http://www.opensource.apple.com/apsl/ and read it before using this -.\" file. -.\" -.\" The Original Code and all software distributed under the License are -.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER -.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. -.\" Please see the License for the specific language governing rights and -.\" limitations under the License. -.\" -.\" @APPLE_LICENSE_HEADER_END@ -.\" -.Dd Dec 15, 2006 -.Dt BOOTLOG 8 -.Sh NAME -.Nm bootlog -.Nd log a utmpx boot record -.\" -.Sh SYOPSIS -.Nm bootlog -.Sh DESCRIPTION -The -.Nm bootlog -command simply creates a -.Xr utmpx 5 -boot record at boot time. -It is run by -.Xr launchd 8 . -.Sh SEE ALSO -.Xr utmpx 5 , -.Xr launchd 8 diff --git a/bootlog.tproj/bootlog.c b/bootlog.tproj/bootlog.c deleted file mode 100644 index b7ab68d..0000000 --- a/bootlog.tproj/bootlog.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _PATH_ASL_IN "/var/run/asl_input" - -#define REPEAT 100 -#define SLEEP 2 - -static void -asl_running(void) -{ - int sock, i; - struct sockaddr_un server; - socklen_t len; - int status; - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - exit(1); - - memset(&server, 0, sizeof(struct sockaddr_un)); - server.sun_family = AF_UNIX; - - strcpy(server.sun_path, _PATH_ASL_IN); - server.sun_len = strlen(server.sun_path) + 1; - len = sizeof(server.sun_len) + sizeof(server.sun_family) + server.sun_len; - - i = REPEAT; - for(;;) { - status = connect(sock, (const struct sockaddr *)&server, len); - if (status >= 0) - break; - if(--i <= 0) - exit(1); - sleep(SLEEP); - } - - close(sock); -} - -int -main() -{ - int mib[2] = {CTL_KERN, KERN_BOOTTIME}; - struct utmpx utx; - size_t len; - - bzero(&utx, sizeof(utx)); - utx.ut_type = BOOT_TIME; - utx.ut_pid = 1; // on behalf of launchd - - /* get the boot time */ - len = sizeof(struct timeval); - if(sysctl(mib, 2, &utx.ut_tv, &len, NULL, 0) < 0) - gettimeofday(&utx.ut_tv, NULL); /* fallback to now */ - - /* wait for asl before logging */ - asl_running(); - pututxline(&utx); - return 0; -} diff --git a/bootlog.tproj/com.apple.bootlog.plist b/bootlog.tproj/com.apple.bootlog.plist deleted file mode 100644 index 40579f8..0000000 --- a/bootlog.tproj/com.apple.bootlog.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - Label - com.apple.bootlog - ProgramArguments - - /usr/libexec/bootlog - - RunAtLoad - - LaunchOnlyOnce - - - diff --git a/chkpasswd.tproj/Makefile b/chkpasswd.tproj/Makefile index 6c8926e..f9f594b 100644 --- a/chkpasswd.tproj/Makefile +++ b/chkpasswd.tproj/Makefile @@ -5,14 +5,14 @@ CFILES = od_passwd.c nis_passwd.c file_passwd.c pam_passwd.c passwd.c\ stringops.c MANPAGES = chkpasswd.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_Frameworks = -framework CoreFoundation -framework OpenDirectory -lpam include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make -Install_Program_Mode = 04555 +Install_Program_Mode = 00555 after_install: $(INSTALL_DIRECTORY) "$(DSTROOT)"/private/etc/pam.d diff --git a/chkpasswd.tproj/file_passwd.c b/chkpasswd.tproj/file_passwd.c index 56e7a00..24d4913 100644 --- a/chkpasswd.tproj/file_passwd.c +++ b/chkpasswd.tproj/file_passwd.c @@ -39,7 +39,7 @@ extern void checkpasswd(char *, char *); char * -getline(FILE *fp) +_getline(FILE *fp) { static char s[BUFSIZE]; int len; @@ -115,7 +115,7 @@ find_user(char *uname, FILE *fp) rewind(fp); - while (NULL != (line = getline(fp))) + while (NULL != (line = _getline(fp))) { if (line[0] == '#') continue; pw = parse_user(line); @@ -172,7 +172,7 @@ rewrite_file(char *pwname, FILE *fp, struct passwd *newpw) rewind(fp); - while (NULL != (line = getline(fp))) + while (NULL != (line = _getline(fp))) { if (line[0] == '#') { @@ -232,7 +232,7 @@ rewrite_file(char *pwname, FILE *fp, struct passwd *newpw) exit(1); } - while (NULL != (line = getline(tfp))) + while (NULL != (line = _getline(tfp))) { fprintf(fp, "%s", line); if (line[0] != '#') fprintf(fp, "\n"); diff --git a/chpass.tproj/Makefile b/chpass.tproj/Makefile index c2cca60..b446cd3 100644 --- a/chpass.tproj/Makefile +++ b/chpass.tproj/Makefile @@ -6,7 +6,7 @@ CFILES = chpass.c edit.c field.c pw_copy.c table.c util.c \ open_directory.c MANPAGES = chpass.1 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_CC_Flags += -DOPEN_DIRECTORY -fconstant-cfstrings \ -I../pwd_mkdb.tproj -I../vipw.tproj Extra_LD_Flags = -dead_strip @@ -15,7 +15,7 @@ Extra_Frameworks = -framework OpenDirectory -framework CoreFoundation include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make -Install_Program_Mode = 04555 +Install_Program_Mode = 00555 after_install: $(LN) -sf chpass.1 $(DSTROOT)/usr/share/man/man1/chfn.1 diff --git a/chpass.tproj/chpass.c b/chpass.tproj/chpass.c index 8195e2c..44f37d5 100644 --- a/chpass.tproj/chpass.c +++ b/chpass.tproj/chpass.c @@ -123,6 +123,7 @@ main(int argc, char *argv[]) struct passwd *old_pw, *pw; int ch, tfd; char tfn[MAXPATHLEN]; + char *tmpdir; #endif char *arg = NULL; uid_t uid; @@ -331,7 +332,10 @@ main(int argc, char *argv[]) if (op == EDITENTRY) { #ifdef OPEN_DIRECTORY setrestricted(attrs_orig); - snprintf(tfn, sizeof(tfn), "/etc/%s.XXXXXX", progname); + tmpdir = getenv("TMPDIR"); + if (!tmpdir) + tmpdir = P_tmpdir; // defined in the system headers, defaults to /tmp + snprintf(tfn, sizeof(tfn), "%s/%s.XXXXXX", tmpdir, progname); if ((tfd = mkstemp(tfn)) == -1) err(1, "%s", tfn); attrs = (CFMutableDictionaryRef)edit(tfn, attrs_orig); diff --git a/chpass.tproj/open_directory.c b/chpass.tproj/open_directory.c index 9627ad3..5f9392b 100644 --- a/chpass.tproj/open_directory.c +++ b/chpass.tproj/open_directory.c @@ -61,11 +61,13 @@ prompt_passwd(CFStringRef user) { CFStringRef result = NULL; CFStringRef prompt = CFStringCreateWithFormat(NULL, NULL, CFSTR("Password for %@: "), user); - char buf[128]; - CFStringGetCString(prompt, buf, sizeof(buf), kCFStringEncodingUTF8); + size_t prompt_size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(prompt), kCFStringEncodingUTF8); + char* buf = malloc(prompt_size); + CFStringGetCString(prompt, buf, prompt_size, kCFStringEncodingUTF8); char* pass = getpass(buf); result = CFStringCreateWithCString(NULL, pass, kCFStringEncodingUTF8); memset(pass, 0, strlen(pass)); + free(buf); CFRelease(prompt); return result; } @@ -88,93 +90,24 @@ show_error(CFErrorRef error) { } } -static int -is_singleuser(void) { - uint32_t su = 0; - size_t susz = sizeof(su); - if (sysctlbyname("kern.singleuser", &su, &susz, NULL, 0) != 0) { - return 0; - } else { - return (int)su; - } -} - -static int -load_DirectoryServicesLocal() { - const char* launchctl = "/bin/launchctl"; - const char* plist = "/System/Library/LaunchDaemons/com.apple.DirectoryServicesLocal.plist"; - - pid_t pid = fork(); - int status, res; - switch (pid) { - case -1: // ERROR - perror("launchctl"); - return 0; - case 0: // CHILD - execl(launchctl, launchctl, "load", plist, NULL); - /* NOT REACHED */ - perror("launchctl"); - exit(1); - break; - default: // PARENT - do { - res = waitpid(pid, &status, 0); - } while (res == -1 && errno == EINTR); - if (res == -1) { - perror("launchctl"); - return 0; - } - break; - } - return (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS)); -} - ODRecordRef odGetUser(CFStringRef location, CFStringRef authname, CFStringRef user, CFDictionaryRef* attrs) { - ODSessionRef session = NULL; ODNodeRef node = NULL; ODRecordRef rec = NULL; CFErrorRef error = NULL; assert(attrs); - /* - * Connect to DS server - */ - session = ODSessionCreate(NULL, NULL, &error); - if ( !session && error && CFErrorGetCode(error) == kODErrorSessionDaemonNotRunning ) { - /* - * In single-user mode, attempt to load the local DS daemon. - */ - if (is_singleuser() && load_DirectoryServicesLocal()) { - CFTypeRef keys[] = { kODSessionLocalPath }; - CFTypeRef vals[] = { CFSTR("/var/db/dslocal") }; - CFDictionaryRef opts = CFDictionaryCreate(NULL, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (opts) { - session = ODSessionCreate(NULL, opts, &error); - CFRelease(opts); - } - - if (!location) { - location = CFRetain(CFSTR("/Local/Default")); - } - } else { - show_error(error); - return NULL; - } - } - /* * Open the specified node, or perform a search. * Copy the record and put the record's location into DSPath. */ if (location) { - node = ODNodeCreateWithName(NULL, session, location, &error); + node = ODNodeCreateWithName(NULL, kODSessionDefault, location, &error); } else { - node = ODNodeCreateWithNodeType(NULL, session, kODNodeTypeAuthentication, &error); + node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODNodeTypeAuthentication, &error); } - if (session) CFRelease(session); if (node) { CFTypeRef vals[] = { kODAttributeTypeStandardOnly }; CFArrayRef desiredAttrs = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks); diff --git a/dirhelper.tproj/Makefile b/dirhelper.tproj/Makefile index bb05ae4..a0e23f9 100644 --- a/dirhelper.tproj/Makefile +++ b/dirhelper.tproj/Makefile @@ -3,14 +3,15 @@ Install_Dir = /usr/libexec CFILES = dirhelper.c SERVERDEFS = /usr/local/include/dirhelper.defs +USERDEFS = $(SERVERDEFS) MANPAGES = dirhelper.8 LAUNCHD_PLISTS = com.apple.bsd.dirhelper.plist -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_CC_Flags += -D__MigTypeCheck=1 Extra_LD_Flags = -dead_strip Extra_LD_Flags += -lbsm -#CFLAGS = -g -mdynamic-no-pic -Os -Wall -Wextra -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror -D__MigTypeCheck=1 $(RC_CFLAGS) -I $(OBJDIR) +#CFLAGS = -g -Os -Wall -Wextra -Wshadow -Wmissing-prototypes -Wmissing-declarations -Werror -D__MigTypeCheck=1 $(RC_CFLAGS) -I $(OBJDIR) include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/dirhelper.tproj/dirhelper.c b/dirhelper.tproj/dirhelper.c index d6dff17..d0fcc72 100644 --- a/dirhelper.tproj/dirhelper.c +++ b/dirhelper.tproj/dirhelper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2007 Apple Inc. All rights reserved. + * Copyright (c) 2006-2007, 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,16 @@ #include #include +#include "dirhelper.h" #include "dirhelper_server.h" +/* + * Uncomment the next line to define BOOTDEBUG, which will write timing + * info for clean_directories() to a file, /Debug. + */ +//#define BOOTDEBUG +#ifdef BOOTDEBUG +#include +#endif //BOOTDEBUG // globals for idle exit struct idle_globals { @@ -56,12 +66,19 @@ struct idle_globals { struct idle_globals idle_globals; +// argument structure for clean_thread +struct clean_args { + const char** dirs; + int machineBoot; +}; + void* idle_thread(void* param __attribute__((unused))); -int file_check(const char* path, int mode, int uid, int gid); -#define is_file(x) file_check((x), S_IFREG, -1, -1) -#define is_directory(x) file_check((x), S_IFDIR, -1, -1) -#define is_root_wheel_directory(x) file_check((x), S_IFDIR, 0, 0) +int file_check(const char* path, int mode, int uid, int gid, uid_t* owner, gid_t* group); +#define is_file(x) file_check((x), S_IFREG, -1, -1, NULL, NULL) +#define is_directory(x) file_check((x), S_IFDIR, -1, -1, NULL, NULL) +#define is_directory_get_owner_group(x,o,g) file_check((x), S_IFDIR, -1, -1, (o), (g)) +#define is_root_wheel_directory(x) file_check((x), S_IFDIR, 0, 0, NULL, NULL) int is_safeboot(void); @@ -105,6 +122,11 @@ do___dirhelper_create_user_local( "__user_local_dirname: %s", strerror(errno)); break; } + + // All dirhelper directories are now at the same level, so + // we need to remove the DIRHELPER_TOP_STR suffix to get the + // parent directory. + path[strlen(path) - (sizeof(DIRHELPER_TOP_STR) - 1)] = 0; // // 1. Starting with VAR_FOLDERS_PATH, make each subdirectory @@ -167,7 +189,7 @@ idle_thread(void* param __attribute__((unused))) { return NULL; } -// If when == 0, all files are removed. Otherwise, only regular files older than when. +// If when == 0, all files are removed. Otherwise, only regular files that were both created _and_ last modified before `when`. void clean_files_older_than(const char* path, time_t when) { FTS* fts; @@ -181,23 +203,22 @@ clean_files_older_than(const char* path, time_t when) { switch(ent->fts_info) { case FTS_F: case FTS_DEFAULT: - // Unlink the file if it has not been accessed since - // the specified time. Obtain an exclusive lock so - // that we can avoid a race with other processes - // attempting to open the file. if (when == 0) { #if DEBUG asl_log(NULL, NULL, ASL_LEVEL_ALERT, "unlink(" VAR_FOLDERS_PATH "%s)", ent->fts_path); #endif (void)unlink(ent->fts_path); - } else if (S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_atime < when) { + } else if (S_ISREG(ent->fts_statp->st_mode) && (ent->fts_statp->st_birthtime < when) && (ent->fts_statp->st_atime < when)) { int fd = open(ent->fts_path, O_RDONLY | O_NONBLOCK); if (fd != -1) { + // Obtain an exclusive lock so + // that we can avoid a race with other processes + // attempting to open or modify the file. int res = flock(fd, LOCK_EX | LOCK_NB); if (res == 0) { struct stat sb; res = fstat(fd, &sb); - if (res == 0 && sb.st_atime < when) { + if ((res == 0) && (sb.st_birthtime < when) && (sb.st_atime < when)) { #if DEBUG asl_log(NULL, NULL, ASL_LEVEL_ALERT, "unlink(" VAR_FOLDERS_PATH "%s)", ent->fts_path); #endif @@ -245,13 +266,17 @@ clean_files_older_than(const char* path, time_t when) { } int -file_check(const char* path, int mode, int uid, int gid) { +file_check(const char* path, int mode, int uid, int gid, uid_t* owner, gid_t* group) { int check = 1; struct stat sb; if (lstat(path, &sb) == 0) { check = check && ((sb.st_mode & S_IFMT) == mode); check = check && ((sb.st_uid == (uid_t)uid) || uid == -1); check = check && ((sb.st_gid == (gid_t)gid) || gid == -1); + if (check) { + if (owner) *owner = sb.st_uid; + if (group) *group = sb.st_gid; + } } else { if (errno != ENOENT) { /* This will print a shorter path after chroot() */ @@ -274,13 +299,14 @@ is_safeboot(void) { } } -void -clean_directories(const char* dirs[], int machineBoot) { +void * +clean_thread(void *a) { + struct clean_args* args = (struct clean_args*)a; DIR* d; time_t when = 0; int i; - if (!machineBoot) { + if (!args->machineBoot) { struct timeval now; long days = 3; const char* str = getenv("CLEAN_FILES_OLDER_THAN_DAYS"); @@ -288,8 +314,8 @@ clean_directories(const char* dirs[], int machineBoot) { days = strtol(str, NULL, 0); } (void)gettimeofday(&now, NULL); - for (i = 0; dirs[i]; i++) - asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s older than %ld days", dirs[i], days); + for (i = 0; args->dirs[i]; i++) + asl_log(NULL, NULL, ASL_LEVEL_INFO, "Cleaning %s older than %ld days", args->dirs[i], days); when = now.tv_sec - (days * 60 * 60 * 24); } @@ -299,18 +325,19 @@ clean_directories(const char* dirs[], int machineBoot) { size_t len = sizeof(boottime); if (sysctlbyname("kern.boottime", &boottime, &len, NULL, 0) == -1) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", "sysctl kern.boottime", strerror(errno)); - return; + return NULL; } if (!is_root_wheel_directory(VAR_FOLDERS_PATH)) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", VAR_FOLDERS_PATH, "invalid ownership"); - return; + return NULL; } if (chroot(VAR_FOLDERS_PATH)) { asl_log(NULL, NULL, ASL_LEVEL_ERR, "chroot(%s) failed: %s", VAR_FOLDERS_PATH, strerror(errno)); } + chdir("/"); if ((d = opendir("/"))) { struct dirent* e; char path[PATH_MAX]; @@ -327,18 +354,34 @@ clean_directories(const char* dirs[], int machineBoot) { // /var/folders/*/* while ((e2 = readdir(d2))) { - char temporary_items[PATH_MAX]; + char dirbuf[PATH_MAX]; + uid_t owner; + gid_t group; if (strcmp(e2->d_name, ".") == 0 || strcmp(e2->d_name, "..") == 0) continue; - for (i = 0; dirs[i]; i++) { - const char *name = dirs[i]; - snprintf(temporary_items, sizeof(temporary_items), + snprintf(dirbuf, sizeof(dirbuf), + "%s/%s", path, e2->d_name); + if (!is_directory_get_owner_group(dirbuf, &owner, &group)) continue; + if (pthread_setugid_np(owner, group) != 0) { + asl_log(NULL, NULL, ASL_LEVEL_ERR, + "skipping %s: pthread_setugid_np(%u, %u): %s", + dirbuf, owner, group, strerror(errno)); + continue; + } + for (i = 0; args->dirs[i]; i++) { + const char *name = args->dirs[i]; + snprintf(dirbuf, sizeof(dirbuf), "%s/%s/%s", path, e2->d_name, name); - if (is_directory(temporary_items)) { + if (is_directory(dirbuf)) { // at boot time we clean all files, // otherwise only clean regular files. - clean_files_older_than(temporary_items, when); + clean_files_older_than(dirbuf, when); } } + if (pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE) != 0) { + asl_log(NULL, NULL, ASL_LEVEL_ERR, + "%s: pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE): %s", + dirbuf, strerror(errno)); + } } closedir(d2); } else { @@ -351,6 +394,48 @@ clean_directories(const char* dirs[], int machineBoot) { } else { asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s: %s", VAR_FOLDERS_PATH, strerror(errno)); } + return NULL; +} + +void +clean_directories(const char* dirs[], int machineBoot) { + struct clean_args args; + pthread_t t; + int ret; +#ifdef BOOTDEBUG + double ratio; + struct mach_timebase_info info; + uint64_t begin, end; + FILE *debug; + + mach_timebase_info(&info); + ratio = (double)info.numer / ((double)info.denom * NSEC_PER_SEC); + begin = mach_absolute_time(); + if((debug = fopen("/Debug", "a")) != NULL) { + fprintf(debug, "clean_directories: machineBoot=%d\n", machineBoot); + } +#endif //BOOTDEBUG + + args.dirs = dirs; + args.machineBoot = machineBoot; + ret = pthread_create(&t, NULL, clean_thread, &args); + if (ret == 0) { + ret = pthread_join(t, NULL); + if (ret) { + asl_log(NULL, NULL, ASL_LEVEL_ERR, "clean_directories: pthread_join: %s", + strerror(ret)); + } + } else { + asl_log(NULL, NULL, ASL_LEVEL_ERR, "clean_directories: pthread_create: %s", + strerror(ret)); + } +#ifdef BOOTDEBUG + end = mach_absolute_time(); + if(debug) { + fprintf(debug, "clean_directories: %f secs\n", ratio * (end - begin)); + fclose(debug); + } +#endif //BOOTDEBUG } int @@ -359,6 +444,19 @@ main(int argc, char* argv[]) { kern_return_t kr; long idle_timeout = 30; // default 30 second timeout +#ifdef BOOTDEBUG + { + FILE *debug; + int i; + if((debug = fopen("/Debug", "a")) != NULL) { + for(i = 0; i < argc; i++) { + fprintf(debug, " %s", argv[i]); + } + fputc('\n', debug); + fclose(debug); + } + } +#endif //BOOTDEBUG // Clean up TemporaryItems directory when launched at boot. // It is safe to clean all file types at this time. if (argc > 1 && strcmp(argv[1], "-machineBoot") == 0) { diff --git a/dmesg.tproj/Makefile b/dmesg.tproj/Makefile index 7ab0dcf..c2b646b 100644 --- a/dmesg.tproj/Makefile +++ b/dmesg.tproj/Makefile @@ -5,7 +5,7 @@ CFILES = dmesg.c MANPAGES = dmesg.8 MAKEFILE = tool.make -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_LD_Flags += -lproc diff --git a/dynamic_pager.tproj/Makefile b/dynamic_pager.tproj/Makefile index 8ac4c66..ad26fb0 100644 --- a/dynamic_pager.tproj/Makefile +++ b/dynamic_pager.tproj/Makefile @@ -8,12 +8,12 @@ USERDEFS = backing_store_alerts.defs MANPAGES = dynamic_pager.8 LAUNCHD_PLISTS = com.apple.dynamic_pager.plist -Extra_CC_Flags = -mdynamic-no-pic -Wall -Werror +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_CC_Flags += -DNO_DIRECT_RPC -Extra_Frameworks += -framework CoreFoundation -framework IOKit +Extra_Frameworks += -framework CoreFoundation -framework SystemConfiguration Extra_MIG_Flags = -R -untyped -DNO_DIRECT_RPC include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make @@ -27,7 +27,7 @@ endif after_install: ifeq "$(Embedded)" "YES" /usr/libexec/PlistBuddy -x \ - -c "Add :Disabled bool true" \ + -c "Add :LaunchOnlyOnce bool true" \ "$(DSTROOT)/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist" endif plutil -convert binary1 "$(DSTROOT)/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist" diff --git a/dynamic_pager.tproj/dynamic_pager.c b/dynamic_pager.tproj/dynamic_pager.c index b44878f..8352791 100644 --- a/dynamic_pager.tproj/dynamic_pager.c +++ b/dynamic_pager.tproj/dynamic_pager.c @@ -32,8 +32,6 @@ #include #include -#include -#include #include #include @@ -41,7 +39,6 @@ #include #include - /* * HI_WATER_DEFAULT set to this funny value to * match the size that the low space application @@ -54,6 +51,22 @@ #define MAX_LIMITS 8 +#if TARGET_OS_EMBEDDED + +#include + +#define USE_SYSTEMCONFIGURATION_PRIVATE_HEADERS 1 +#include + +enum { + VM_PAGING_MODE_DISABLED = 0, + VM_PAGING_MODE_FREEZE, + VM_PAGING_MODE_DYNAMIC +}; + +#define VM_FREEZE_SYSCTL "vm.freeze_enabled" +#define FREEZE_FIXED_SWAP_SIZE (128 * 1024 * 1024) +#endif struct limit { unsigned int size; @@ -238,7 +251,14 @@ default_pager_space_alert(alert_port, flags) if (fd == -1) { /* force error recovery below */ error = -1; - } else { + } +#if TARGET_OS_EMBEDDED + else { + error = fcntl(fd, F_SETPROTECTIONCLASS, PROTECTION_CLASS_F); + } +#endif + + if(!error) { error = fcntl(fd, F_SETSIZE, &filesize); if(error) { error = ftruncate(fd, filesize); @@ -409,6 +429,16 @@ paging_setup(flags, size, priority, low, high, encrypted) exit(EXIT_FAILURE); } +#if TARGET_OS_EMBEDDED + error = fcntl(fd, F_SETPROTECTIONCLASS, PROTECTION_CLASS_F); + if (error == -1) { + fprintf(stderr, "dynamic_pager: cannot set file protection class!\n"); + unlink(subfile); + close(fd); + exit(EXIT_FAILURE); + } +#endif + error = fcntl(fd, F_SETSIZE, &filesize); if(error) { error = ftruncate(fd, filesize); @@ -483,8 +513,8 @@ clean_swap_directory(const char *path) closedir(dir); } -#define VM_PREFS_PLIST "/Library/Preferences/com.apple.virtualMemory.plist" -#define VM_PREFS_ENCRYPT_SWAP_KEY "UseEncryptedSwap" +#define VM_PREFS_PLIST "/Library/Preferences/com.apple.virtualMemory.plist" +#define VM_PREFS_DISABLE_ENCRYPT_SWAP_KEY "DisableEncryptedSwap" static boolean_t should_encrypt_swap(void) @@ -495,12 +525,9 @@ should_encrypt_swap(void) CFDataRef resourceData; SInt32 errorCode; CFURLRef fileURL; - CFTypeRef value; - boolean_t should_encrypt; - boolean_t explicit_value; - - explicit_value = false; - should_encrypt = true; + CFTypeRef disable_encrypted_swap; + boolean_t should_encrypt = TRUE; + boolean_t explicit_value = FALSE; fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)VM_PREFS_PLIST, strlen(VM_PREFS_PLIST), false); if (fileURL == NULL) { @@ -525,18 +552,18 @@ should_encrypt_swap(void) propertyListType = CFGetTypeID(propertyList); if (propertyListType == CFDictionaryGetTypeID()) { - value = (CFTypeRef) CFDictionaryGetValue((CFDictionaryRef) propertyList, CFSTR(VM_PREFS_ENCRYPT_SWAP_KEY)); - if (value == NULL) { - /* no value: use the default value */ - } else if (CFGetTypeID(value) != CFBooleanGetTypeID()) { + disable_encrypted_swap = (CFTypeRef) CFDictionaryGetValue((CFDictionaryRef) propertyList, CFSTR(VM_PREFS_DISABLE_ENCRYPT_SWAP_KEY)); + if (disable_encrypted_swap == NULL) { + /* no value: use the default value i.e. encrypted swap ON */ + } else if (CFGetTypeID(disable_encrypted_swap) != CFBooleanGetTypeID()) { fprintf(stderr, "%s: wrong type for key \"%s\"\n", - getprogname(), VM_PREFS_ENCRYPT_SWAP_KEY); + getprogname(), VM_PREFS_DISABLE_ENCRYPT_SWAP_KEY); /* bogus value, assume it's "true" for safety's sake */ - should_encrypt = true; - explicit_value = true; + should_encrypt = TRUE; + explicit_value = TRUE; } else { - should_encrypt = CFBooleanGetValue((CFBooleanRef)value); - explicit_value = true; + should_encrypt = CFBooleanGetValue((CFBooleanRef)disable_encrypted_swap) ? FALSE : TRUE; + explicit_value = TRUE; } } else { @@ -549,19 +576,43 @@ done: if (! explicit_value) { #if TARGET_OS_EMBEDDED should_encrypt = FALSE; -#else - /* by default, encrypt swap on laptops only */ - /* - * Look for battery power source. - */ - should_encrypt = (kCFBooleanTrue == IOPSPowerSourceSupported(NULL, CFSTR(kIOPMBatteryPowerKey))); - /*fprintf(stderr, "dynamic_pager: battery power source: %d\n", should_encrypt);*/ #endif } return should_encrypt; } +#if TARGET_OS_EMBEDDED + +#define VM_PREFS_PAGING_MODE_PLIST "com.apple.virtualMemoryMode.plist" +#define VM_PREFS_PAGING_MODE_KEY "Mode" + +static uint32_t +get_paging_mode(void) +{ + SCPreferencesRef paging_prefs; + uint32_t paging_mode; + + paging_mode = VM_PAGING_MODE_FREEZE; /* default */ + + paging_prefs = SCPreferencesCreate(NULL, CFSTR("dynamic_pager"), CFSTR(VM_PREFS_PAGING_MODE_PLIST)); + if (paging_prefs) { + CFNumberRef value; + + value = SCPreferencesGetValue(paging_prefs, CFSTR(VM_PREFS_PAGING_MODE_KEY)); + + if (value && (CFGetTypeID( value ) == CFNumberGetTypeID() ) ) { + CFNumberGetValue((CFNumberRef)value, kCFNumberIntType, &paging_mode); + } + + CFRelease(paging_prefs); + } + + return paging_mode; +} + +#endif + int main(int argc, char **argv) { @@ -571,6 +622,14 @@ main(int argc, char **argv) int ch; int variable_sized = 1,flags=0; boolean_t encrypted_swap; + static char tmp[1024]; + struct statfs sfs; + char *q; +#if TARGET_OS_EMBEDDED + int err; + uint32_t paging_mode; + size_t paging_mode_length; +#endif /* setlinebuf(stdout); @@ -630,10 +689,62 @@ retry: } } + /* + * get rid of the filename at the end of the swap file specification + * we only want the portion of the pathname that should already exist + */ + strcpy(tmp, fileroot); + if ((q = strrchr(tmp, '/'))) + *q = 0; + + /* + * Remove all files in the swap directory. + */ + clean_swap_directory(tmp); + +#if TARGET_OS_EMBEDDED + paging_mode = get_paging_mode(); + paging_mode_length = sizeof(paging_mode); + + switch (paging_mode) { + case VM_PAGING_MODE_DISABLED: + /* Paging disabled; nothing to do here so exit */ + exit(EXIT_SUCCESS); + + case VM_PAGING_MODE_FREEZE: + /* Freeze mode; one swap file of fixed size, so enable and override defaults if set */ + err = sysctlbyname(VM_FREEZE_SYSCTL, NULL, 0, &paging_mode, paging_mode_length); + if (err < 0) { + (void)fprintf(stderr, "dynamic_pager: cannot set %s\n", VM_FREEZE_SYSCTL); + exit(EXIT_FAILURE); + } + variable_sized = 0; + limits[0].size = FREEZE_FIXED_SWAP_SIZE; + break; + + case VM_PAGING_MODE_DYNAMIC: + /* Dynamic paging selected; proceed normally */ + break; + + default: + /* Invalid option */ + (void)fprintf(stderr, "dynamic_pager: invalid paging_mode %d\n", paging_mode); + exit(EXIT_FAILURE); + } +#endif + + if (statfs(tmp, &sfs) == -1) { + /* + * Setup the swap directory. + */ + if (mkdir(tmp, 0755) == -1) { + (void)fprintf(stderr, "dynamic_pager: cannot create swap directory %s\n", tmp); + exit(EXIT_FAILURE); + } + } + chown(tmp, 0, 0); + if (variable_sized) { - static char tmp[1024]; - struct statfs sfs; - char *q; int i; int mib[4]; size_t len; @@ -663,37 +774,13 @@ retry: * an additional swap file when it really isn't necessary */ - /* - * get rid of the filename at the end of the swap file specification - * we only want the portion of the pathname that should already exist - */ - strcpy(tmp, fileroot); - if ((q = strrchr(tmp, '/'))) - *q = 0; - - /* - * Remove all files in the swap directory. - */ - clean_swap_directory(tmp); - - if (statfs(tmp, &sfs) == -1) { + if (statfs(tmp, &sfs) == -1) { /* - * Setup the swap directory. + * We really can't get filesystem status, + * so let's not limit the swap files... */ - if (mkdir(tmp, 0755) == -1) { - (void)fprintf(stderr, "dynamic_pager: cannot create swap directory %s\n", tmp); - exit(EXIT_FAILURE); - } - chown(tmp, 0, 0); - - if (statfs(tmp, &sfs) == -1) { - /* - * We really can't get filesystem status, - * so let's not limit the swap files... - */ - fs_limit = (u_int64_t) -1; - } - } + fs_limit = (u_int64_t) -1; + } if (fs_limit != (u_int64_t) -1) { /* diff --git a/fs_usage.tproj/Makefile b/fs_usage.tproj/Makefile index 0c3f358..8d51d04 100644 --- a/fs_usage.tproj/Makefile +++ b/fs_usage.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = fs_usage.c MANPAGES = fs_usage.1 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip -lutil Extra_CC_Flags += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ diff --git a/fs_usage.tproj/fs_usage.1 b/fs_usage.tproj/fs_usage.1 index 6c39c7c..f6dae97 100644 --- a/fs_usage.tproj/fs_usage.1 +++ b/fs_usage.tproj/fs_usage.1 @@ -57,10 +57,16 @@ By default no output filtering occurs. The supported modes are: .Pp .Pa network -Only network related output is displayed. +Only network related events are displayed. .Pp .Pa filesys -Only file system related output is displayed. +Only file system related events are displayed. +.Pp +.Pa exec +Only exec and spawn events are displayed. +.Pp +.Pa pathname +Only pathname related events are displayed. .Pp .Pa cachehit In addition, display CACHE_HIT output. @@ -71,6 +77,25 @@ Specifying the option forces a wider, more detailed output, regardless of the window size. .\" ========== +.It Fl R Ar raw_file +Specifies a raw trace file to process. +.\" ========== +.It Fl S Ar start_time +If +.Fl R +is selected, specifies the start time in microseconds to +begin processing entries from the raw trace file. Entries +with timestamps before the specified start time will be +skipped. +.\" ========== +.It Fl E Ar end_time +If +.Fl R +is selected, specifies the ending time in microseconds to +stop processing entries from the raw trace file. Entries +with timestamps beyond the specified ending time will be +skipped. +.\" ========== .It pid | cmd The sampled data can be limited to a list of process ids or commands. When a command name is given, all processes with that name will be sampled. @@ -98,7 +123,7 @@ The data columns displayed are as follows: .Pp .It TIMESTAMP TOD when call occurred. -Wide mode will have millisecond granularity. +Wide mode will have microsecond granularity. .It CALL The name of the network or filesystem related call, page-in, page-out, or physical disk access. @@ -133,7 +158,8 @@ after the elapsed time indicates the process was scheduled out during this file activity. In this case, the elapsed time includes the wait time. .It PROCESS NAME -The process that made the system call. +The process that made the system call. Wide mode will append the +thread id to the process name (i.e Mail.nnn). .El .Pp .Sh SAMPLE USAGE diff --git a/fs_usage.tproj/fs_usage.c b/fs_usage.tproj/fs_usage.c index f9e02c1..7ed62cc 100644 --- a/fs_usage.tproj/fs_usage.c +++ b/fs_usage.tproj/fs_usage.c @@ -23,11 +23,9 @@ */ /* -cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c +cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -o fs_usage fs_usage.c */ -#define Default_DELAY 1 /* default delay interval */ - #include #include #include @@ -37,16 +35,20 @@ cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c #include #include #include +#include +#include +#include +#include +#include #include #include #include - -#include -#include #include #include #include +#include +#include #ifndef KERNEL_PRIVATE #define KERNEL_PRIVATE @@ -56,19 +58,29 @@ cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c #include #endif /*KERNEL_PRIVATE*/ -#include -#include -#include #import #import -#include -#include + + #define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */ #define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */ #define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */ +#ifndef RAW_VERSION1 +typedef struct { + int version_no; + int thread_count; + uint64_t TOD_secs; + uint32_t TOD_usecs; +} RAW_header; + +#define RAW_VERSION0 0x55aa0000 +#define RAW_VERSION1 0x55aa0101 +#endif + + #define MAXINDEX 2048 typedef struct LibraryRange { @@ -110,25 +122,29 @@ typedef struct LibraryInfo { LibraryInfo frameworkInfo[MAXINDEX]; int numFrameworks = 0; -void lookup_name(uint64_t user_addr, char **type, char **name); - /* - MAXCOLS controls when extra data kicks in. - MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path. - If NUMPARMS changes to match the kernel, it will automatically - get reflected in the -w mode output. -*/ + * MAXCOLS controls when extra data kicks in. + * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path. + * If NUMPARMS changes to match the kernel, it will automatically + * get reflected in the -w mode output. + */ #define NUMPARMS 23 #define PATHLENGTH (NUMPARMS*sizeof(uintptr_t)) + #define MAXCOLS 132 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80) #define MAXWIDTH MAX_WIDE_MODE_COLS + 64 + +typedef struct th_info *th_info_t; + struct th_info { - int my_index; - int in_filemgr; + th_info_t next; uintptr_t thread; + uintptr_t child_thread; + + int in_filemgr; int pid; int type; int arg1; @@ -139,33 +155,46 @@ struct th_info { int arg6; int arg7; int arg8; - uintptr_t child_thread; int waited; double stime; uintptr_t *pathptr; - uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */ + uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */ + uintptr_t pathname2[NUMPARMS + 1]; /* add room for null terminator */ +}; + + +typedef struct threadmap * threadmap_t; + +struct threadmap { + threadmap_t tm_next; + + uintptr_t tm_thread; + unsigned int tm_setsize; /* this is a bit count */ + unsigned long *tm_setptr; /* file descripter bitmap */ + char tm_command[MAXCOMLEN + 1]; }; -#define MAX_THREADS 1024 -struct th_info th_state[MAX_THREADS]; -kd_threadmap *last_map = NULL; -int last_thread = 0; -int map_is_the_same = 0; +#define HASH_SIZE 1024 +#define HASH_MASK 1023 + +th_info_t th_info_hash[HASH_SIZE]; +th_info_t th_info_freelist; + +threadmap_t threadmap_hash[HASH_SIZE]; +threadmap_t threadmap_freelist; + int filemgr_in_progress = 0; -int execs_in_progress = 0; -int cur_start = 0; -int cur_max = 0; int need_new_map = 1; int bias_secs = 0; long last_time; int wideflag = 0; int columns = 0; -int select_pid_mode = 0; /* Flag set indicates that output is restricted - to selected pids or commands */ int one_good_pid = 0; /* Used to fail gracefully when bad pids given */ +int select_pid_mode = 0; /* Flag set indicates that output is restricted + to selected pids or commands */ char *arguments = 0; int argmax = 0; @@ -190,6 +219,7 @@ int usleep_ms = USLEEP_MIN; int filter_mode = CACHEHIT_FILTER; #define NFS_DEV -1 +#define CS_DEV -2 struct diskrec { struct diskrec *next; @@ -218,30 +248,53 @@ struct diskio *free_diskios = NULL; struct diskio *busy_diskios = NULL; - struct diskio *insert_diskio(); struct diskio *complete_diskio(); void free_diskio(); void print_diskio(); + +int check_filter_mode(struct th_info *, int, int, int, char *); void format_print(struct th_info *, char *, uintptr_t, int, int, int, int, int, int, double, double, int, char *, struct diskio *); -void enter_syscall_now(uintptr_t, int, kd_buf *, char *, double); -void enter_syscall(uintptr_t, int, kd_buf *, char *, double); -void exit_syscall(char *, uintptr_t, int, int, int, int, int, int, double); -void extend_syscall(uintptr_t, int, kd_buf *); -char *find_disk_name(); +void enter_event_now(uintptr_t, int, kd_buf *, char *, double); +void enter_event(uintptr_t, int, kd_buf *, char *, double); +void exit_event(char *, uintptr_t, int, int, int, int, int, int, double); +void extend_syscall(uintptr_t, int, kd_buf *); + +char *generate_cs_disk_name(int, char *s); +char *find_disk_name(int); void cache_disk_names(); void recache_disk_names(); + +void lookup_name(uint64_t user_addr, char **type, char **name); int ReadSharedCacheMap(const char *, LibraryRange *, char *); void SortFrameworkAddresses(); -void mark_thread_waited(uintptr_t); -int check_filter_mode(struct th_info *, int, int, int, char *); -void fs_usage_fd_set(unsigned int, unsigned int); -int fs_usage_fd_isset(unsigned int, unsigned int); -void fs_usage_fd_clear(unsigned int, unsigned int); + +void fs_usage_fd_set(uintptr_t, unsigned int); +int fs_usage_fd_isset(uintptr_t, unsigned int); +void fs_usage_fd_clear(uintptr_t, unsigned int); + void init_arguments_buffer(); int get_real_command_name(int, char *, int); + +void delete_all_events(); +void delete_event(th_info_t); +th_info_t add_event(uintptr_t, int); +th_info_t find_event(uintptr_t, int); +void mark_thread_waited(uintptr_t); + +void read_command_map(); +void delete_all_map_entries(); void create_map_entry(uintptr_t, int, char *); -void kill_thread_map(uintptr_t); +void delete_map_entry(uintptr_t); +threadmap_t find_map_entry(uintptr_t); + +void getdivisor(); +void argtopid(); +void set_remove(); +void set_pidcheck(); +void set_pidexclude(); +int quit(); + #define CLASS_MASK 0xff000000 #define CSC_MASK 0xffff0000 @@ -259,39 +312,46 @@ void kill_thread_map(uintptr_t); #define MACH_stkhandoff 0x01400008 #define MACH_idle 0x01400024 #define VFS_LOOKUP 0x03010090 -#define BSC_exit 0x040C0004 +#define BSC_thread_terminate 0x040c05a4 + +#define Throttled 0x3010184 #define SPEC_ioctl 0x3060000 +#define proc_exit 0x4010004 #define P_DISKIO 0x03020000 #define P_DISKIO_DONE 0x03020004 +#define P_DISKIO_TYPE 0x03020068 #define P_DISKIO_MASK (CSC_MASK | 0x4) +#define P_DISKIO_READ 0x00000008 +#define P_DISKIO_ASYNC 0x00000010 +#define P_DISKIO_META 0x00000020 +#define P_DISKIO_PAGING 0x00000040 +#define P_DISKIO_THROTTLE 0x00000080 +#define P_DISKIO_PASSIVE 0x00000100 + #define P_WrData 0x03020000 #define P_RdData 0x03020008 #define P_WrMeta 0x03020020 #define P_RdMeta 0x03020028 #define P_PgOut 0x03020040 #define P_PgIn 0x03020048 -#define P_WrDataAsync 0x03020010 -#define P_RdDataAsync 0x03020018 -#define P_WrMetaAsync 0x03020030 -#define P_RdMetaAsync 0x03020038 -#define P_PgOutAsync 0x03020050 -#define P_PgInAsync 0x03020058 - -#define P_WrDataDone 0x03020004 -#define P_RdDataDone 0x0302000C -#define P_WrMetaDone 0x03020024 -#define P_RdMetaDone 0x0302002C -#define P_PgOutDone 0x03020044 -#define P_PgInDone 0x0302004C -#define P_WrDataAsyncDone 0x03020014 -#define P_RdDataAsyncDone 0x0302001C -#define P_WrMetaAsyncDone 0x03020034 -#define P_RdMetaAsyncDone 0x0302003C -#define P_PgOutAsyncDone 0x03020054 -#define P_PgInAsyncDone 0x0302005C + +#define P_CS_ReadChunk 0x0a000200 +#define P_CS_ReadChunkDone 0x0a000280 +#define P_CS_WriteChunk 0x0a000210 +#define P_CS_WriteChunkDone 0x0a000290 + +#define P_CS_Originated_Read 0x0a000500 +#define P_CS_Originated_ReadDone 0x0a000580 +#define P_CS_Originated_Write 0x0a000510 +#define P_CS_Originated_WriteDone 0x0a000590 +#define P_CS_MetaRead 0x0a000900 +#define P_CS_MetaReadDone 0x0a000980 +#define P_CS_MetaWrite 0x0a000910 +#define P_CS_MetaWriteDone 0x0a000990 +#define P_CS_SYNC_DISK 0x0a008000 #define MSC_map_fd 0x010c00ac @@ -312,6 +372,7 @@ void kill_thread_map(uintptr_t); #define BSC_sendto 0x040C0214 #define BSC_socketpair 0x040C021C +#define BSC_exit 0x040C0004 #define BSC_read 0x040C000C #define BSC_write 0x040C0010 #define BSC_open 0x040C0014 @@ -353,7 +414,9 @@ void kill_thread_map(uintptr_t); #define BSC_pread 0x040C0264 #define BSC_pwrite 0x040C0268 #define BSC_statfs 0x040C0274 -#define BSC_fstatfs 0x040C0278 +#define BSC_fstatfs 0x040C0278 +#define BSC_unmount 0x040C027C +#define BSC_mount 0x040C029C #define BSC_stat 0x040C02F0 #define BSC_fstat 0x040C02F4 #define BSC_lstat 0x040C02F8 @@ -386,6 +449,7 @@ void kill_thread_map(uintptr_t); #define BSC_listxattr 0x040C03C0 #define BSC_flistxattr 0x040C03C4 #define BSC_fsctl 0x040C03C8 +#define BSC_posix_spawn 0x040C03D0 #define BSC_open_extended 0x040C0454 #define BSC_stat_extended 0x040C045C #define BSC_lstat_extended 0x040C0460 @@ -553,6 +617,10 @@ void kill_thread_map(uintptr_t); #define FMT_UMASK 32 #define FMT_SENDFILE 33 #define FMT_SPEC_IOCTL 34 +#define FMT_MOUNT 35 +#define FMT_UNMOUNT 36 +#define FMT_DISKIO_CS 37 +#define FMT_SYNC_DISK_CS 38 #define MAX_BSD_SYSCALL 512 @@ -604,7 +672,9 @@ int bsd_syscall_types[] = { BSC_revoke, BSC_symlink, BSC_readlink, + BSC_exit, BSC_execve, + BSC_posix_spawn, BSC_umask, BSC_chroot, BSC_dup2, @@ -631,6 +701,8 @@ int bsd_syscall_types[] = { BSC_stat, BSC_fstat, BSC_lstat, + BSC_mount, + BSC_unmount, BSC_pathconf, BSC_fpathconf, BSC_getdirentries, @@ -794,8 +866,6 @@ int exclude_default_pids = 1; struct kinfo_proc *kp_buffer = 0; int kp_nentries = 0; -int num_cpus; - #define EVENT_BASE 60000 int num_events = EVENT_BASE; @@ -812,8 +882,6 @@ char *my_buffer; kbufinfo_t bufinfo = {0, 0, 0, 0, 0}; -int total_threads = 0; -kd_threadmap *mapptr = 0; /* pointer to list of threads */ /* defines for tracking file descriptor state */ #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per @@ -822,24 +890,19 @@ kd_threadmap *mapptr = 0; /* pointer to list of threads */ #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8) #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long)) -typedef struct { - unsigned int fd_valid; /* set if this is a valid entry */ - uintptr_t fd_thread; - unsigned int fd_setsize; /* this is a bit count */ - unsigned long *fd_setptr; /* file descripter bitmap */ -} fd_threadmap; - -fd_threadmap *fdmapptr = 0; /* pointer to list of threads for fd tracking */ - int trace_enabled = 0; int set_remove_flag = 1; char *RAW_file = (char *)0; int RAW_flag = 0; int RAW_fd = 0; + +uint64_t sample_TOD_secs; +uint32_t sample_TOD_usecs; + double bias_now = 0.0; double start_time = 0.0; -double end_time = 99999999999.9; +double end_time = 999999999999.9; void set_numbufs(); @@ -877,6 +940,28 @@ void leave() /* exit under normal conditions -- INT handler */ } +int +quit(s) +char *s; +{ + if (trace_enabled) + set_enable(0); + + /* + * This flag is turned off when calling + * quit() due to a set_remove() failure. + */ + if (set_remove_flag) + set_remove(); + + fprintf(stderr, "fs_usage: "); + if (s) + fprintf(stderr, "%s", s); + + exit(1); +} + + void get_screenwidth() { struct winsize size; @@ -900,10 +985,21 @@ void sigwinch() get_screenwidth(); } + +void getdivisor() +{ + struct mach_timebase_info mti; + + mach_timebase_info(&mti); + + divisor = ((double)mti.denom / (double)mti.numer) * 1000; +} + + int exit_usage(char *myname) { - fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname); + fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [-R rawfile [-S start_time] [-E end_time]] [pid | cmd [pid | cmd]....]\n", myname); fprintf(stderr, " -e exclude the specified list of pids from the sample\n"); fprintf(stderr, " and exclude fs_usage by default\n"); fprintf(stderr, " -w force wider, detailed, output\n"); @@ -913,6 +1009,9 @@ exit_usage(char *myname) { fprintf(stderr, " mode = \"pathname\" Show only pathname related output\n"); fprintf(stderr, " mode = \"exec\" Show only execs\n"); fprintf(stderr, " mode = \"cachehit\" In addition, show cachehits\n"); + fprintf(stderr, " -R specifies a raw trace file to process\n"); + fprintf(stderr, " -S if -R is specified, selects a start point in microseconds\n"); + fprintf(stderr, " -E if -R is specified, selects an end point in microseconds\n"); fprintf(stderr, " pid selects process(s) to sample\n"); fprintf(stderr, " cmd selects process(s) matching command string to sample\n"); fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS); @@ -937,8 +1036,6 @@ void init_tables(void) int type; int code; - for (i = 0; i < MAX_THREADS; i++) - th_state[i].my_index = i; for (i = 0; i < MAX_BSD_SYSCALL; i++) { bsd_syscalls[i].sc_name = NULL; @@ -1061,11 +1158,29 @@ void init_tables(void) case BSC_stat64_extended: bsd_syscalls[code].sc_name = "stat_extended64"; break; - + + case BSC_mount: + bsd_syscalls[code].sc_name = "mount"; + bsd_syscalls[code].sc_format = FMT_MOUNT; + break; + + case BSC_unmount: + bsd_syscalls[code].sc_name = "unmount"; + bsd_syscalls[code].sc_format = FMT_UNMOUNT; + break; + + case BSC_exit: + bsd_syscalls[code].sc_name = "exit"; + break; + case BSC_execve: bsd_syscalls[code].sc_name = "execve"; break; + case BSC_posix_spawn: + bsd_syscalls[code].sc_name = "posix_spawn"; + break; + case BSC_load_shared_file: bsd_syscalls[code].sc_name = "load_sf"; break; @@ -1806,29 +1921,21 @@ main(argc, argv) char *myname = "fs_usage"; int i; char ch; - struct sigaction osa; - void getdivisor(); - void argtopid(); - void set_remove(); - void set_pidcheck(); - void set_pidexclude(); - int quit(); if (0 != reexec_to_match_kernel()) { - fprintf(stderr, "Could not re-execute: %d\n", errno); - exit(1); + fprintf(stderr, "Could not re-execute: %d\n", errno); + exit(1); } - get_screenwidth(); - /* get our name */ + /* + * get our name + */ if (argc > 0) { - if ((myname = rindex(argv[0], '/')) == 0) { + if ((myname = rindex(argv[0], '/')) == 0) myname = argv[0]; - } - else { + else myname++; - } } while ((ch = getopt(argc, argv, "ewf:R:S:E:")) != EOF) { @@ -1892,47 +1999,49 @@ main(argc, argv) * case below where exclude_pids is later set and the fs_usage PID * needs to make it into pids[] */ - if (exclude_pids || (!exclude_pids && argc == 0)) - { - if (num_of_pids < (MAX_PIDS - 1)) - pids[num_of_pids++] = getpid(); - } + if (exclude_pids || (!exclude_pids && argc == 0)) { + if (num_of_pids < (MAX_PIDS - 1)) + pids[num_of_pids++] = getpid(); + } - /* If we process any list of pids/cmds, then turn off the defaults */ + /* + * If we process any list of pids/cmds, then turn off the defaults + */ if (argc > 0) - exclude_default_pids = 0; + exclude_default_pids = 0; while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) { - select_pid_mode++; - argtopid(argv[0]); - argc--; - argv++; + select_pid_mode++; + argtopid(argv[0]); + argc--; + argv++; + } + /* + * Exclude a set of default pids + */ + if (exclude_default_pids) { + argtopid("Terminal"); + argtopid("telnetd"); + argtopid("telnet"); + argtopid("sshd"); + argtopid("rlogind"); + argtopid("tcsh"); + argtopid("csh"); + argtopid("sh"); + exclude_pids = 1; } - - /* Exclude a set of default pids */ - if (exclude_default_pids) - { - argtopid("Terminal"); - argtopid("telnetd"); - argtopid("telnet"); - argtopid("sshd"); - argtopid("rlogind"); - argtopid("tcsh"); - argtopid("csh"); - argtopid("sh"); - exclude_pids = 1; - } - #if 0 - for (i = 0; i < num_of_pids; i++) - { - if (exclude_pids) - fprintf(stderr, "exclude pid %d\n", pids[i]); - else - fprintf(stderr, "pid %d\n", pids[i]); - } + for (i = 0; i < num_of_pids; i++) { + if (exclude_pids) + fprintf(stderr, "exclude pid %d\n", pids[i]); + else + fprintf(stderr, "pid %d\n", pids[i]); + } #endif if (!RAW_flag) { + struct sigaction osa; + int num_cpus; + size_t len; /* set up signal handlers */ signal(SIGINT, leave); @@ -1943,13 +2052,14 @@ main(argc, argv) if (osa.sa_handler == SIG_DFL) signal(SIGHUP, leave); signal(SIGTERM, leave); - - /* grab the number of cpus */ - size_t len; + /* + * grab the number of cpus + */ mib[0] = CTL_HW; mib[1] = HW_NCPU; mib[2] = 0; len = sizeof(num_cpus); + sysctl(mib, 2, &num_cpus, &len, NULL, 0); num_events = EVENT_BASE * num_cpus; } @@ -1981,26 +2091,25 @@ main(argc, argv) for (i = 0; i < num_of_pids; i++) set_pidexclude(pids[i], 1); } - - if (select_pid_mode && !one_good_pid) - { + if (select_pid_mode && !one_good_pid) { /* - An attempt to restrict output to a given - pid or command has failed. Exit gracefully - */ + * An attempt to restrict output to a given + * pid or command has failed. Exit gracefully + */ set_remove(); exit_usage(myname); } - set_enable(1); + init_arguments_buffer(); } getdivisor(); init_tables(); - /* main loop */ - + /* + * main loop + */ while (1) { if (!RAW_flag) usleep(1000 * usleep_ms); @@ -2011,12 +2120,12 @@ main(argc, argv) } } + void find_proc_names() { size_t bufSize = 0; - struct kinfo_proc *kp; - int quit(); + struct kinfo_proc *kp; mib[0] = CTL_KERN; mib[1] = KERN_PROC; @@ -2026,8 +2135,8 @@ find_proc_names() if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) quit("trace facility failure, KERN_PROC_ALL\n"); - if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0) - quit("can't allocate memory for proc buffer\n"); + if ((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0) + quit("can't allocate memory for proc buffer\n"); if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0) quit("trace facility failure, KERN_PROC_ALL\n"); @@ -2037,75 +2146,6 @@ find_proc_names() } -void destroy_thread(struct th_info *ti) { - - ti->child_thread = 0; - ti->thread = 0; - ti->pid = 0; - - if (ti->my_index < cur_start) - cur_start = ti->my_index; - - if (ti->my_index == cur_max) { - while (ti >= &th_state[0]) { - if (ti->thread) - break; - ti--; - } - cur_max = ti->my_index; - } -} - - -struct th_info *find_empty(void) { - struct th_info *ti; - - for (ti = &th_state[cur_start]; ti < &th_state[MAX_THREADS]; ti++, cur_start++) { - if (ti->thread == 0) { - if (cur_start > cur_max) - cur_max = cur_start; - cur_start++; - - return (ti); - } - } - return ((struct th_info *)0); - -} - - -struct th_info *find_thread(uintptr_t thread, int type) { - struct th_info *ti; - - for (ti = &th_state[0]; ti <= &th_state[cur_max]; ti++) { - if (ti->thread == thread) { - if (type == ti->type) - return(ti); - if (ti->in_filemgr) { - if (type == -1) - return(ti); - continue; - } - if (type == 0) - return(ti); - } - } - return ((struct th_info *)0); -} - - -void -mark_thread_waited(uintptr_t thread) { - struct th_info *ti; - - for (ti = th_state; ti <= &th_state[cur_max]; ti++) { - if (ti->thread == thread) { - ti->waited = 1; - } - } -} - - void set_enable(int val) { @@ -2115,13 +2155,14 @@ set_enable(int val) mib[3] = val; mib[4] = 0; mib[5] = 0; /* no flags */ + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) quit("trace facility failure, KERN_KDENABLE\n"); if (val) - trace_enabled = 1; + trace_enabled = 1; else - trace_enabled = 0; + trace_enabled = 0; } void @@ -2133,6 +2174,7 @@ set_numbufs(int nbufs) mib[3] = nbufs; mib[4] = 0; mib[5] = 0; /* no flags */ + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) quit("trace facility failure, KERN_KDSETBUF\n"); @@ -2142,6 +2184,7 @@ set_numbufs(int nbufs) mib[3] = 0; mib[4] = 0; mib[5] = 0; /* no flags */ + if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) quit("trace facility failure, KERN_KDSETUP\n"); } @@ -2165,16 +2208,14 @@ set_pidcheck(int pid, int on_off) if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) { if (on_off == 1) fprintf(stderr, "pid %d does not exist\n", pid); - } - else { - one_good_pid++; - } + } else + one_good_pid++; } /* - on_off == 0 turns off pid exclusion - on_off == 1 turns on pid exclusion -*/ + * on_off == 0 turns off pid exclusion + * on_off == 1 turns on pid exclusion + */ void set_pidexclude(int pid, int on_off) { @@ -2226,15 +2267,15 @@ set_remove() mib[3] = 0; mib[4] = 0; mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - { - set_remove_flag = 0; - - if (errno == EBUSY) - quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n"); - else - quit("trace facility failure, KERN_KDREMOVE\n"); - } + + if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) { + set_remove_flag = 0; + + if (errno == EBUSY) + quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n"); + else + quit("trace facility failure, KERN_KDREMOVE\n"); + } } void @@ -2245,6 +2286,7 @@ set_init() kr.value1 = 0; kr.value2 = -1; needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; mib[2] = KERN_KDSETREG; @@ -2273,21 +2315,19 @@ sample_sc() int i, count; size_t needed; uint32_t my_buffer_size = 0; - void read_command_map(); - void create_map_entry(); - if (!RAW_flag) { - /* Get kernel buffer information */ + if (!RAW_flag) get_bufinfo(&bufinfo); - } else { + else my_buffer_size = num_events * sizeof(kd_buf); - } + if (need_new_map) { read_command_map(); need_new_map = 0; } if (!RAW_flag) { needed = bufinfo.nkdbufs * sizeof(kd_buf); + mib[0] = CTL_KERN; mib[1] = KERN_KDEBUG; mib[2] = KERN_KDREADTR; @@ -2313,16 +2353,9 @@ sample_sc() if (bufinfo.flags & KDBG_WRAPPED) { fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count); - for (i = 0; i <= cur_max; i++) { - th_state[i].thread = 0; - th_state[i].pid = 0; - th_state[i].pathptr = (uintptr_t *)NULL; - th_state[i].pathname[0] = 0; - } - cur_max = 0; - cur_start = 0; + delete_all_events(); + need_new_map = 1; - map_is_the_same = 0; set_enable(0); set_enable(1); @@ -2348,7 +2381,7 @@ sample_sc() long long l_usecs; int secs; long curr_time; - struct th_info *ti; + th_info_t ti; struct diskio *dio; @@ -2358,19 +2391,19 @@ sample_sc() now = kdbg_get_timestamp(&kd[i]); - if (i == 0 && !RAW_flag) - { - curr_time = time((long *)0); - /* - * Compute bias seconds after each trace buffer read. - * This helps resync timestamps with the system clock - * in the event of a system sleep. - */ - if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) { - l_usecs = (long long)(now / divisor); - secs = l_usecs / 1000000; - bias_secs = curr_time - secs; - } + if (i == 0 && !RAW_flag) { + + curr_time = time((long *)0); + /* + * Compute bias seconds after each trace buffer read. + * This helps resync timestamps with the system clock + * in the event of a system sleep. + */ + if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) { + l_usecs = (long long)(now / divisor); + secs = l_usecs / 1000000; + bias_secs = curr_time - secs; + } } if (RAW_flag && bias_now == 0.0) bias_now = now; @@ -2386,60 +2419,89 @@ sample_sc() } continue; } - switch (type) { - case TRACE_DATA_NEWTHREAD: - - if ((ti = find_empty()) == NULL) - continue; + case P_CS_ReadChunk: + case P_CS_WriteChunk: + case P_CS_MetaRead: + case P_CS_MetaWrite: + insert_diskio(type, kd[i].arg2, kd[i].arg1, kd[i].arg3, kd[i].arg4, thread, (double)now); + continue; + + case P_CS_Originated_Read: + case P_CS_Originated_Write: + insert_diskio(type, kd[i].arg2, CS_DEV, kd[i].arg3, kd[i].arg4, thread, (double)now); + continue; + + case P_CS_ReadChunkDone: + case P_CS_WriteChunkDone: + case P_CS_Originated_ReadDone: + case P_CS_Originated_WriteDone: + case P_CS_MetaReadDone: + case P_CS_MetaWriteDone: + if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) { + print_diskio(dio); + free_diskio(dio); + } + continue; - ti->thread = thread; - ti->child_thread = kd[i].arg1; - ti->pid = kd[i].arg2; + case TRACE_DATA_NEWTHREAD: + if (kd[i].arg1) { + if ((ti = add_event(thread, TRACE_DATA_NEWTHREAD)) == NULL) + continue; + ti->child_thread = kd[i].arg1; + ti->pid = kd[i].arg2; + } continue; case TRACE_STRING_NEWTHREAD: - if ((ti = find_thread(thread, 0)) == (struct th_info *)0) + if ((ti = find_event(thread, TRACE_DATA_NEWTHREAD)) == (struct th_info *)0) continue; - if (ti->child_thread == 0) - continue; - create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1); - destroy_thread(ti); + create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1); + delete_event(ti); continue; case TRACE_DATA_EXEC: - - if ((ti = find_empty()) == NULL) + if ((ti = add_event(thread, TRACE_DATA_EXEC)) == NULL) continue; - ti->thread = thread; ti->pid = kd[i].arg1; continue; case TRACE_STRING_EXEC: - if ((ti = find_thread(thread, 0)) == (struct th_info *)0) - { - /* this is for backwards compatibility */ - create_map_entry(thread, 0, (char *)&kd[i].arg1); - } - else - { - create_map_entry(thread, ti->pid, (char *)&kd[i].arg1); + if ((ti = find_event(thread, BSC_execve))) { + if (ti->pathname[0]) + exit_event("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now); - destroy_thread(ti); + } else if ((ti = find_event(thread, BSC_posix_spawn))) { + if (ti->pathname[0]) + exit_event("posix_spawn", thread, BSC_posix_spawn, 0, 0, 0, 0, FMT_DEFAULT, (double)now); } + if ((ti = find_event(thread, TRACE_DATA_EXEC)) == (struct th_info *)0) + continue; + + create_map_entry(thread, ti->pid, (char *)&kd[i].arg1); + + delete_event(ti); + continue; + + case BSC_thread_terminate: + delete_map_entry(thread); continue; case BSC_exit: - kill_thread_map(thread); continue; + case proc_exit: + kd[i].arg1 = kd[i].arg2 >> 8; + type = BSC_exit; + break; + case BSC_mmap: if (kd[i].arg4 & MAP_ANON) - continue; + continue; break; case MACH_idle: @@ -2449,11 +2511,16 @@ sample_sc() continue; case VFS_LOOKUP: - if ((ti = find_thread(thread, 0)) == (struct th_info *)0) + if ((ti = find_event(thread, 0)) == (struct th_info *)0) continue; - if (ti->pathptr == NULL) { - sargptr = ti->pathname; + if (debugid & DBG_FUNC_START) { + if (ti->pathname2[0]) + continue; + if (ti->pathname[0] == 0) + sargptr = ti->pathname; + else + sargptr = ti->pathname2; *sargptr++ = kd[i].arg2; *sargptr++ = kd[i].arg3; *sargptr++ = kd[i].arg4; @@ -2461,6 +2528,7 @@ sample_sc() * NULL terminate the 'string' */ *sargptr = 0; + ti->pathptr = sargptr; } else { sargptr = ti->pathptr; @@ -2468,21 +2536,17 @@ sample_sc() /* * We don't want to overrun our pathname buffer if the * kernel sends us more VFS_LOOKUP entries than we can - * handle. - */ - if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname[NUMPARMS]) { - continue; - } - - /* - * We need to detect consecutive vfslookup entries. - * So, if we get here and find a START entry, - * fake the pathptr so we can bypass all further - * vfslookup entries. + * handle and we only handle 2 pathname lookups for + * a given system call */ - if (debugid & DBG_FUNC_START) { - ti->pathptr = &ti->pathname[NUMPARMS]; - continue; + if (sargptr == 0) + continue; + if (ti->pathname2[0]) { + if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname2[NUMPARMS]) + continue; + } else { + if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname[NUMPARMS]) + continue; } *sargptr++ = kd[i].arg1; *sargptr++ = kd[i].arg2; @@ -2492,7 +2556,14 @@ sample_sc() * NULL terminate the 'string' */ *sargptr = 0; - ti->pathptr = sargptr; + + if (debugid & DBG_FUNC_END) { + if (ti->pathname2[0]) + ti->pathptr = 0; + else + ti->pathptr = ti->pathname2; + } else + ti->pathptr = sargptr; } continue; } @@ -2512,237 +2583,210 @@ sample_sc() } else p = NULL; - enter_syscall(thread, type, &kd[i], p, (double)now); + enter_event(thread, type, &kd[i], p, (double)now); continue; } switch (type) { - case SPEC_ioctl: - if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE) - exit_syscall("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_SPEC_IOCTL, (double)now); - else { - if ((ti = find_thread(thread, type))) { - destroy_thread(ti); - } - } - continue; - - case MACH_pageout: - if (kd[i].arg2) - exit_syscall("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); - else - exit_syscall("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); - continue; - - case MACH_vmfault: - if (kd[i].arg4 == DBG_PAGEIN_FAULT) - exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); - else if (kd[i].arg4 == DBG_PAGEINV_FAULT) - exit_syscall("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); - else if (kd[i].arg4 == DBG_PAGEIND_FAULT) - exit_syscall("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); - else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT) - exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now); - else { - if ((ti = find_thread(thread, type))) { - destroy_thread(ti); - } - } - continue; - - case MSC_map_fd: - exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now); - continue; + case Throttled: + exit_event(" THROTTLED", thread, type, 0, 0, 0, 0, FMT_DEFAULT, (double)now); + continue; + + case P_CS_SYNC_DISK: + exit_event(" SyncCacheCS", thread, type, kd[i].arg1, 0, 0, 0, FMT_SYNC_DISK_CS, (double)now); + continue; + + case SPEC_ioctl: + if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE) + exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_SPEC_IOCTL, (double)now); + else { + if ((ti = find_event(thread, type))) + delete_event(ti); + } + continue; + + case MACH_pageout: + if (kd[i].arg2) + exit_event("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); + else + exit_event("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now); + continue; + + case MACH_vmfault: + if (kd[i].arg4 == DBG_PAGEIN_FAULT) + exit_event("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); + else if (kd[i].arg4 == DBG_PAGEINV_FAULT) + exit_event("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); + else if (kd[i].arg4 == DBG_PAGEIND_FAULT) + exit_event("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now); + else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT) + exit_event("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now); + else { + if ((ti = find_event(thread, type))) + delete_event(ti); + } + continue; + + case MSC_map_fd: + exit_event("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now); + continue; - case BSC_mmap_extended: - case BSC_mmap_extended2: - case BSC_msync_extended: - case BSC_pread_extended: - case BSC_pwrite_extended: - extend_syscall(thread, type, &kd[i]); - continue; + case BSC_mmap_extended: + case BSC_mmap_extended2: + case BSC_msync_extended: + case BSC_pread_extended: + case BSC_pwrite_extended: + extend_syscall(thread, type, &kd[i]); + continue; } if ((type & CSC_MASK) == BSC_BASE) { - index = BSC_INDEX(type); - - if (index >= MAX_BSD_SYSCALL) - continue; - - if (bsd_syscalls[index].sc_name == NULL) + if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL) continue; - if (type == BSC_execve) - execs_in_progress--; - - exit_syscall(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, - bsd_syscalls[index].sc_format, (double)now); - - continue; - } + if (bsd_syscalls[index].sc_name) { + exit_event(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, + bsd_syscalls[index].sc_format, (double)now); - if ((type & CLASS_MASK) == FILEMGR_BASE) { + if (type == BSC_exit) + delete_map_entry(thread); + } + } else if ((type & CLASS_MASK) == FILEMGR_BASE) { - index = filemgr_index(type); - - if (index >= MAX_FILEMGR) - continue; - - if (filemgr_calls[index].fm_name == NULL) + if ((index = filemgr_index(type)) >= MAX_FILEMGR) continue; - exit_syscall(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, - FMT_DEFAULT, (double)now); + if (filemgr_calls[index].fm_name) { + exit_event(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, + FMT_DEFAULT, (double)now); + } } } fflush(0); } - - void -enter_syscall_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now) +enter_event_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now) { - struct th_info *ti; - int secs; - int usecs; - long long l_usecs; - long curr_time; - kd_threadmap *map; - kd_threadmap *find_thread_map(); - int clen = 0; - int tsclen = 0; - int nmclen = 0; - int argsclen = 0; - char buf[MAXWIDTH]; - - if (execs_in_progress) { - if ((ti = find_thread(thread, BSC_execve))) { - if (ti->pathptr) { - exit_syscall("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now); - execs_in_progress--; - } - } - } - if ((ti = find_empty()) == NULL) - return; - - if ((type & CLASS_MASK) == FILEMGR_BASE && - (!RAW_flag || (now >= start_time && now <= end_time))) { - - filemgr_in_progress++; - ti->in_filemgr = 1; - - if (RAW_flag) { - l_usecs = (long long)((now - bias_now) / divisor); - l_usecs += ((long long)8 * (long long)3600 * (long long)1000000); - } else - l_usecs = (long long)(now / divisor); - secs = l_usecs / 1000000; - curr_time = bias_secs + secs; - - sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11])); - tsclen = strlen(buf); - - if (columns > MAXCOLS || wideflag) { - usecs = l_usecs - (long long)((long long)secs * 1000000); - sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000); - tsclen = strlen(buf); - } + th_info_t ti; + threadmap_t tme; + int secs; + int usecs; + long long l_usecs; + long curr_time; + int clen = 0; + int tsclen = 0; + int nmclen = 0; + int argsclen = 0; + char buf[MAXWIDTH]; - /* - * Print timestamp column - */ - printf("%s", buf); + if ((ti = add_event(thread, type)) == NULL) + return; - map = find_thread_map(thread); - if (map) { - sprintf(buf, " %-25.25s ", name); - nmclen = strlen(buf); - printf("%s", buf); + ti->stime = now; + ti->arg1 = kd->arg1; + ti->arg2 = kd->arg2; + ti->arg3 = kd->arg3; + ti->arg4 = kd->arg4; - sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); - argsclen = strlen(buf); - - /* - * Calculate white space out to command - */ - if (columns > MAXCOLS || wideflag) { - clen = columns - (tsclen + nmclen + argsclen + 20); - } else - clen = columns - (tsclen + nmclen + argsclen + 12); - - if (clen > 0) { - printf("%s", buf); /* print the kdargs */ - memset(buf, ' ', clen); - buf[clen] = '\0'; - printf("%s", buf); - } - else if ((argsclen + clen) > 0) { - /* - * no room so wipe out the kdargs - */ - memset(buf, ' ', (argsclen + clen)); - buf[argsclen + clen] = '\0'; - printf("%s", buf); - } - if (columns > MAXCOLS || wideflag) - printf("%-20.20s\n", map->command); - else - printf("%-12.12s\n", map->command); - } else - printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); - } - ti->thread = thread; - ti->waited = 0; - ti->type = type; - ti->stime = now; - ti->arg1 = kd->arg1; - ti->arg2 = kd->arg2; - ti->arg3 = kd->arg3; - ti->arg4 = kd->arg4; - ti->pathptr = (uintptr_t *)NULL; - ti->pathname[0] = 0; -} + if ((type & CLASS_MASK) == FILEMGR_BASE && + (!RAW_flag || (now >= start_time && now <= end_time))) { + filemgr_in_progress++; + ti->in_filemgr = 1; -void -enter_syscall(uintptr_t thread, int type, kd_buf *kd, char *name, double now) -{ - int index; + if (RAW_flag) { + l_usecs = (long long)((now - bias_now) / divisor); + l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs; + } else + l_usecs = (long long)(now / divisor); + secs = l_usecs / 1000000; + curr_time = bias_secs + secs; + + sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11])); + tsclen = strlen(buf); - if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd || type == SPEC_ioctl) { - enter_syscall_now(thread, type, kd, name, now); - return; - } - if ((type & CSC_MASK) == BSC_BASE) { + if (columns > MAXCOLS || wideflag) { + usecs = l_usecs - (long long)((long long)secs * 1000000); + sprintf(&buf[tsclen], ".%06ld", (long)usecs); + tsclen = strlen(buf); + } - index = BSC_INDEX(type); + /* + * Print timestamp column + */ + printf("%s", buf); - if (index >= MAX_BSD_SYSCALL) - return; + tme = find_map_entry(thread); + if (tme) { + sprintf(buf, " %-25.25s ", name); + nmclen = strlen(buf); + printf("%s", buf); - if (type == BSC_execve) - execs_in_progress++; + sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); + argsclen = strlen(buf); + + /* + * Calculate white space out to command + */ + if (columns > MAXCOLS || wideflag) { + clen = columns - (tsclen + nmclen + argsclen + 20 + 11); + } else + clen = columns - (tsclen + nmclen + argsclen + 12); - if (bsd_syscalls[index].sc_name) - enter_syscall_now(thread, type, kd, name, now); + if (clen > 0) { + printf("%s", buf); /* print the kdargs */ + memset(buf, ' ', clen); + buf[clen] = '\0'; + printf("%s", buf); + } + else if ((argsclen + clen) > 0) { + /* + * no room so wipe out the kdargs + */ + memset(buf, ' ', (argsclen + clen)); + buf[argsclen + clen] = '\0'; + printf("%s", buf); + } + if (columns > MAXCOLS || wideflag) + printf("%s.%d\n", tme->tm_command, (int)thread); + else + printf("%-12.12s\n", tme->tm_command); + } else + printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4); + } +} - return; - } - if ((type & CLASS_MASK) == FILEMGR_BASE) { - index = filemgr_index(type); +void +enter_event(uintptr_t thread, int type, kd_buf *kd, char *name, double now) +{ + int index; + + if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd || type == SPEC_ioctl || type == Throttled || type == P_CS_SYNC_DISK) { + enter_event_now(thread, type, kd, name, now); + return; + } + if ((type & CSC_MASK) == BSC_BASE) { - if (index >= MAX_FILEMGR) - return; + if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL) + return; + + if (bsd_syscalls[index].sc_name) + enter_event_now(thread, type, kd, name, now); + return; + } + if ((type & CLASS_MASK) == FILEMGR_BASE) { + + if ((index = filemgr_index(type)) >= MAX_FILEMGR) + return; - if (filemgr_calls[index].fm_name) - enter_syscall_now(thread, type, kd, name, now); - } + if (filemgr_calls[index].fm_name) + enter_event_now(thread, type, kd, name, now); + } } /* @@ -2756,66 +2800,66 @@ enter_syscall(uintptr_t thread, int type, kd_buf *kd, char *name, double now) void extend_syscall(uintptr_t thread, int type, kd_buf *kd) { - struct th_info *ti; - - switch (type) { - case BSC_mmap_extended: - if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0) - return; - ti->arg8 = ti->arg3; /* save protection */ - ti->arg1 = kd->arg1; /* the fd */ - ti->arg3 = kd->arg2; /* bottom half address */ - ti->arg5 = kd->arg3; /* bottom half size */ - break; - case BSC_mmap_extended2: - if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0) - return; - ti->arg2 = kd->arg1; /* top half address */ - ti->arg4 = kd->arg2; /* top half size */ - ti->arg6 = kd->arg3; /* top half file offset */ - ti->arg7 = kd->arg4; /* bottom half file offset */ - break; - case BSC_msync_extended: - if ((ti = find_thread(thread, BSC_msync)) == (struct th_info *)0) { - if ((ti = find_thread(thread, BSC_msync_nocancel)) == (struct th_info *)0) - return; - } - ti->arg4 = kd->arg1; /* top half address */ - ti->arg5 = kd->arg2; /* top half size */ - break; - case BSC_pread_extended: - if ((ti = find_thread(thread, BSC_pread)) == (struct th_info *)0) { - if ((ti = find_thread(thread, BSC_pread_nocancel)) == (struct th_info *)0) - return; - } - ti->arg1 = kd->arg1; /* the fd */ - ti->arg2 = kd->arg2; /* nbytes */ - ti->arg3 = kd->arg3; /* top half offset */ - ti->arg4 = kd->arg4; /* bottom half offset */ - break; - case BSC_pwrite_extended: - if ((ti = find_thread(thread, BSC_pwrite)) == (struct th_info *)0) { - if ((ti = find_thread(thread, BSC_pwrite_nocancel)) == (struct th_info *)0) - return; - } - ti->arg1 = kd->arg1; /* the fd */ - ti->arg2 = kd->arg2; /* nbytes */ - ti->arg3 = kd->arg3; /* top half offset */ - ti->arg4 = kd->arg4; /* bottom half offset */ - break; - default: - return; + th_info_t ti; + + switch (type) { + case BSC_mmap_extended: + if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0) + return; + ti->arg8 = ti->arg3; /* save protection */ + ti->arg1 = kd->arg1; /* the fd */ + ti->arg3 = kd->arg2; /* bottom half address */ + ti->arg5 = kd->arg3; /* bottom half size */ + break; + case BSC_mmap_extended2: + if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0) + return; + ti->arg2 = kd->arg1; /* top half address */ + ti->arg4 = kd->arg2; /* top half size */ + ti->arg6 = kd->arg3; /* top half file offset */ + ti->arg7 = kd->arg4; /* bottom half file offset */ + break; + case BSC_msync_extended: + if ((ti = find_event(thread, BSC_msync)) == (struct th_info *)0) { + if ((ti = find_event(thread, BSC_msync_nocancel)) == (struct th_info *)0) + return; + } + ti->arg4 = kd->arg1; /* top half address */ + ti->arg5 = kd->arg2; /* top half size */ + break; + case BSC_pread_extended: + if ((ti = find_event(thread, BSC_pread)) == (struct th_info *)0) { + if ((ti = find_event(thread, BSC_pread_nocancel)) == (struct th_info *)0) + return; + } + ti->arg1 = kd->arg1; /* the fd */ + ti->arg2 = kd->arg2; /* nbytes */ + ti->arg3 = kd->arg3; /* top half offset */ + ti->arg4 = kd->arg4; /* bottom half offset */ + break; + case BSC_pwrite_extended: + if ((ti = find_event(thread, BSC_pwrite)) == (struct th_info *)0) { + if ((ti = find_event(thread, BSC_pwrite_nocancel)) == (struct th_info *)0) + return; + } + ti->arg1 = kd->arg1; /* the fd */ + ti->arg2 = kd->arg2; /* nbytes */ + ti->arg3 = kd->arg3; /* top half offset */ + ti->arg4 = kd->arg4; /* bottom half offset */ + break; + default: + return; } } void -exit_syscall(char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4, - int format, double now) +exit_event(char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4, + int format, double now) { - struct th_info *ti; + th_info_t ti; - if ((ti = find_thread(thread, type)) == (struct th_info *)0) + if ((ti = find_event(thread, type)) == (struct th_info *)0) return; if (check_filter_mode(ti, type, arg1, arg2, sc_name)) @@ -2827,7 +2871,7 @@ exit_syscall(char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int if (filemgr_in_progress > 0) filemgr_in_progress--; } - destroy_thread(ti); + delete_event(ti); } @@ -2891,8 +2935,6 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int long long l_usecs; long curr_time; char *command_name; - kd_threadmap *map; - kd_threadmap *find_thread_map(); int in_filemgr = 0; int len = 0; int clen = 0; @@ -2905,21 +2947,21 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int char *p1; char *p2; char buf[MAXWIDTH]; + char cs_diskname[32]; command_name = ""; - int need_msec_update = 0; static char timestamp[32]; static int last_timestamp = -1; static int timestamp_len = 0; - static int last_msec = 0; - if (RAW_flag) { l_usecs = (long long)((now - bias_now) / divisor); if ((double)l_usecs < start_time || (double)l_usecs > end_time) return; - l_usecs += ((long long)8 * (long long)3600 * (long long)1000000); - } else + + l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs; + } + else l_usecs = (long long)(now / divisor); secs = l_usecs / 1000000; curr_time = bias_secs + secs; @@ -2929,43 +2971,31 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int if (dio) command_name = dio->issuing_command; else { - if (map_is_the_same && thread == last_thread) - map = last_map; - else { - if ((map = find_thread_map(thread))) { - last_map = map; - last_thread = thread; - map_is_the_same = 1; - } - } - if (map) - command_name = map->command; + threadmap_t tme; + + if ((tme = find_map_entry(thread))) + command_name = tme->tm_command; } if (last_timestamp != curr_time) { timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11])); last_timestamp = curr_time; - need_msec_update = 1; } if (columns > MAXCOLS || wideflag) { - int msec; + int usec; tlen = timestamp_len; nopadding = 0; - msec = (l_usecs - (long long)((long long)secs * 1000000)) / 1000; + usec = (l_usecs - (long long)((long long)secs * 1000000)); - if (msec != last_msec || need_msec_update) { - sprintf(×tamp[tlen], ".%03ld", (long)msec); - last_msec = msec; - } - tlen += 4; + sprintf(×tamp[tlen], ".%06ld", (long)usec); + tlen += 7; timestamp[tlen] = '\0'; if (filemgr_in_progress) { if (class != FILEMGR_CLASS) { - if (find_thread(thread, -1)) { + if (find_event(thread, -1)) in_filemgr = 1; - } } } } else @@ -3065,6 +3095,24 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, find_disk_name(dio->dev)); break; + case FMT_DISKIO_CS: + /* + * physical disk I/O + */ + if (dio->io_errno) + clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno); + else + clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, &cs_diskname[0])); + break; + + case FMT_SYNC_DISK_CS: + /* + * physical disk sync cache + */ + clen += printf(" /dev/%s", generate_cs_disk_name(arg1, &cs_diskname[0])); + + break; + case FMT_MSYNC: { /* @@ -3408,9 +3456,9 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int buf[mlen++] = '>'; buf[mlen] = '\0'; - if (mlen < 21) { - memset(&buf[mlen], ' ', 21 - mlen); - mlen = 21; + if (mlen < 19) { + memset(&buf[mlen], ' ', 19 - mlen); + mlen = 19; } clen += printf("%s", buf); @@ -3484,6 +3532,35 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int break; } + case FMT_MOUNT: + { + if (arg1) + clen += printf(" [%3d] ", arg1, ti->arg3); + else + clen += printf(" ", ti->arg3); + + nopadding = 1; + break; + } + + case FMT_UNMOUNT: + { + char *mountflag; + + if (ti->arg2 & MNT_FORCE) + mountflag = ""; + else + mountflag = ""; + + if (arg1) + clen += printf(" [%3d] %s ", arg1, mountflag); + else + clen += printf(" %s ", mountflag); + + nopadding = 1; + break; + } + case FMT_OPEN: { /* @@ -3691,7 +3768,7 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int * Calculate space available to print pathname */ if (columns > MAXCOLS || wideflag) - clen = columns - (clen + 14 + 20); + clen = columns - (clen + 14 + 20 + 11); else clen = columns - (clen + 14 + 12); @@ -3700,9 +3777,18 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int if (framework_name) len = sprintf(&buf[0], " %s %s ", framework_type, framework_name); - else if (*pathname != '\0') + else if (*pathname != '\0') { len = sprintf(&buf[0], " %s ", pathname); - else + + if (format == FMT_MOUNT && ti->pathname2[0]) { + int len2; + + memset(&buf[len], ' ', 2); + + len2 = sprintf(&buf[len+2], " %s ", (char *)ti->pathname2); + len = len + 2 + len2; + } + } else len = 0; if (clen > len) { @@ -3751,349 +3837,412 @@ format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int p2 = " "; if (columns > MAXCOLS || wideflag) - printf("%s%s %3ld.%06ld%s %-20.20s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name); + printf("%s%s %3ld.%06ld%s %s.%d\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name, (int)thread); else printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name); } -int -quit(s) -char *s; -{ - if (trace_enabled) - set_enable(0); - /* - * This flag is turned off when calling - * quit() due to a set_remove() failure. - */ - if (set_remove_flag) - set_remove(); +void +delete_event(th_info_t ti_to_delete) { + th_info_t ti; + th_info_t ti_prev; + int hashid; + + hashid = ti_to_delete->thread & HASH_MASK; + + if ((ti = th_info_hash[hashid])) { + if (ti == ti_to_delete) + th_info_hash[hashid] = ti->next; + else { + ti_prev = ti; + + for (ti = ti->next; ti; ti = ti->next) { + if (ti == ti_to_delete) { + ti_prev->next = ti->next; + break; + } + ti_prev = ti; + } + } + if (ti) { + ti->next = th_info_freelist; + th_info_freelist = ti; + } + } +} - fprintf(stderr, "fs_usage: "); - if (s) - fprintf(stderr, "%s", s); +th_info_t +add_event(uintptr_t thread, int type) { + th_info_t ti; + int hashid; - exit(1); + if ((ti = th_info_freelist)) + th_info_freelist = ti->next; + else + ti = (th_info_t)malloc(sizeof(struct th_info)); + + hashid = thread & HASH_MASK; + + ti->next = th_info_hash[hashid]; + th_info_hash[hashid] = ti; + + ti->thread = thread; + ti->type = type; + + ti->waited = 0; + ti->in_filemgr = 0; + ti->pathptr = ti->pathname; + ti->pathname[0] = 0; + ti->pathname2[0] = 0; + + return (ti); } +th_info_t +find_event(uintptr_t thread, int type) { + th_info_t ti; + int hashid; -void getdivisor() -{ - struct mach_timebase_info mti; + hashid = thread & HASH_MASK; - mach_timebase_info(&mti); + for (ti = th_info_hash[hashid]; ti; ti = ti->next) { + if (ti->thread == thread) { + if (type == ti->type) + return (ti); + if (ti->in_filemgr) { + if (type == -1) + return (ti); + continue; + } + if (type == 0) + return (ti); + } + } + return ((th_info_t) 0); +} - divisor = ((double)mti.denom / (double)mti.numer) * 1000; +void +delete_all_events() { + th_info_t ti = 0; + th_info_t ti_next = 0; + int i; + + for (i = 0; i < HASH_SIZE; i++) { + + for (ti = th_info_hash[i]; ti; ti = ti_next) { + ti_next = ti->next; + ti->next = th_info_freelist; + th_info_freelist = ti; + } + th_info_hash[i] = 0; + } +} + + +void +mark_thread_waited(uintptr_t thread) { + th_info_t ti; + int hashid; + + hashid = thread & HASH_MASK; + + for (ti = th_info_hash[hashid]; ti; ti = ti->next) { + if (ti->thread == thread) + ti->waited = 1; + } } void read_command_map() { - size_t size; - int i; - int prev_total_threads; - int mib[6]; - - if (mapptr) { - free(mapptr); - mapptr = 0; - } - - prev_total_threads = total_threads; - - if (!RAW_flag) { - - total_threads = bufinfo.nkdthreads; - size = bufinfo.nkdthreads * sizeof(kd_threadmap); - - if (size) - { - if ((mapptr = (kd_threadmap *) malloc(size))) - { - bzero (mapptr, size); - - /* Now read the threadmap */ - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDTHRMAP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) - { - /* This is not fatal -- just means I cant map command strings */ - free(mapptr); - mapptr = 0; - } - } - } - } else { - uint32_t count_of_names; + size_t size; + int i; + int total_threads = 0; + kd_threadmap *mapptr = 0; - RAW_fd = open(RAW_file, O_RDONLY); + delete_all_map_entries(); - if (RAW_fd < 0) { - perror("Can't open RAW file"); - exit(1); - } - if (read(RAW_fd, &count_of_names, sizeof(uint32_t)) != sizeof(uint32_t)) { - perror("read of RAW file failed"); - exit(2); - } - total_threads = count_of_names; - size = count_of_names * sizeof(kd_threadmap); - - if (size) - { - if ((mapptr = (kd_threadmap *) malloc(size))) - { - bzero (mapptr, size); + if (!RAW_flag) { - if (read(RAW_fd, mapptr, size) != size) { + total_threads = bufinfo.nkdthreads; + size = bufinfo.nkdthreads * sizeof(kd_threadmap); + + if (size) { + if ((mapptr = (kd_threadmap *) malloc(size))) { + int mib[6]; + + bzero (mapptr, size); + /* + * Now read the threadmap + */ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDTHRMAP; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; /* no flags */ + + if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) { + /* + * This is not fatal -- just means I cant map command strings + */ + free(mapptr); + return; + } + } + } + } else { + RAW_header header; + off_t offset; - free(mapptr); - mapptr = 0; - } - } - } - } - if (mapptr && (filter_mode & (NETWORK_FILTER | FILESYS_FILTER))) - { - if (fdmapptr) - { - /* We accept the fact that we lose file descriptor state if the - kd_buffer wraps */ - for (i = 0; i < prev_total_threads; i++) - { - if (fdmapptr[i].fd_setptr) - free (fdmapptr[i].fd_setptr); - } - free(fdmapptr); - fdmapptr = 0; - } + RAW_fd = open(RAW_file, O_RDONLY); - size = total_threads * sizeof(fd_threadmap); - if ((fdmapptr = (fd_threadmap *) malloc(size))) - { - bzero (fdmapptr, size); - /* reinitialize file descriptor state map */ - for (i = 0; i < total_threads; i++) - { - fdmapptr[i].fd_thread = mapptr[i].thread; - fdmapptr[i].fd_valid = mapptr[i].valid; - fdmapptr[i].fd_setsize = 0; - fdmapptr[i].fd_setptr = 0; - } + if (RAW_fd < 0) { + perror("Can't open RAW file"); + exit(1); + } + if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) { + perror("read failed"); + exit(2); + } + if (header.version_no != RAW_VERSION1) { + header.version_no = RAW_VERSION0; + header.TOD_secs = time((long *)0); + header.TOD_usecs = 0; + + lseek(RAW_fd, (off_t)0, SEEK_SET); + + if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) { + perror("read failed"); + exit(2); + } + } + sample_TOD_secs = header.TOD_secs; + sample_TOD_usecs = header.TOD_usecs; + + total_threads = header.thread_count; + size = total_threads * sizeof(kd_threadmap); + + if (size) { + if ((mapptr = (kd_threadmap *) malloc(size))) { + bzero (mapptr, size); + + if (read(RAW_fd, mapptr, size) != size) { + free(mapptr); + return; + } + } + } + if (header.version_no != RAW_VERSION0) { + offset = lseek(RAW_fd, (off_t)0, SEEK_CUR); + offset = (offset + (4095)) & ~4095; + + lseek(RAW_fd, offset, SEEK_SET); + } } - } + for (i = 0; i < total_threads; i++) + create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]); - /* Resolve any LaunchCFMApp command names */ - if (mapptr && arguments) - { - for (i=0; i < total_threads; i++) - { - int pid; + free(mapptr); +} - pid = mapptr[i].valid; - - if (pid == 0 || pid == 1) - continue; - else if (!strncmp(mapptr[i].command,"LaunchCFMA", 10)) - { - (void)get_real_command_name(pid, mapptr[i].command, sizeof(mapptr[i].command)); - } + +void delete_all_map_entries() +{ + threadmap_t tme = 0; + threadmap_t tme_next = 0; + int i; + + for (i = 0; i < HASH_SIZE; i++) { + + for (tme = threadmap_hash[i]; tme; tme = tme_next) { + if (tme->tm_setptr) + free(tme->tm_setptr); + tme_next = tme->tm_next; + tme->tm_next = threadmap_freelist; + threadmap_freelist = tme; + } + threadmap_hash[i] = 0; } - } } void create_map_entry(uintptr_t thread, int pid, char *command) { - int i, n; - kd_threadmap *map; - fd_threadmap *fdmap = 0; - - if (!mapptr) - return; - - for (i = 0, map = 0; !map && i < total_threads; i++) - { - if (mapptr[i].thread == thread ) - { - map = &mapptr[i]; /* Reuse this entry, the thread has been - * reassigned */ - if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr) - { - fdmap = &fdmapptr[i]; - if (fdmap->fd_thread != thread) /* This shouldn't happen */ - fdmap = (fd_threadmap *)0; - } - } - } - - if (!map) /* look for invalid entries that I can reuse*/ - { - for (i = 0, map = 0; !map && i < total_threads; i++) - { - if (mapptr[i].valid == 0 ) - map = &mapptr[i]; /* Reuse this invalid entry */ - if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr) - { - fdmap = &fdmapptr[i]; - } - } - } - - if (!map) - { - /* - * If reach here, then this is a new thread and - * there are no invalid entries to reuse - * Double the size of the thread map table. - */ - n = total_threads * 2; - mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap)); - bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap)); - map = &mapptr[total_threads]; - - if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr) - { - fdmapptr = (fd_threadmap *)realloc(fdmapptr, n * sizeof(fd_threadmap)); - bzero(&fdmapptr[total_threads], total_threads*sizeof(fd_threadmap)); - fdmap = &fdmapptr[total_threads]; - } - - total_threads = n; - } - - map->valid = 1; - map->thread = thread; - /* - * The trace entry that returns the command name will hold - * at most, MAXCOMLEN chars, and in that case, is not - * guaranteed to be null terminated. - */ - (void)strncpy (map->command, command, MAXCOMLEN); - map->command[MAXCOMLEN] = '\0'; - - if (fdmap) - { - fdmap->fd_valid = 1; - fdmap->fd_thread = thread; - if (fdmap->fd_setptr) - { - free(fdmap->fd_setptr); - fdmap->fd_setptr = (unsigned long *)0; + threadmap_t tme; + int hashid; + + if ((tme = threadmap_freelist)) + threadmap_freelist = tme->tm_next; + else + tme = (threadmap_t)malloc(sizeof(struct threadmap)); + + tme->tm_thread = thread; + tme->tm_setsize = 0; + tme->tm_setptr = 0; + + (void)strncpy (tme->tm_command, command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; + + hashid = thread & HASH_MASK; + + tme->tm_next = threadmap_hash[hashid]; + threadmap_hash[hashid] = tme; + + if (pid != 0 && pid != 1) { + if (!strncmp(command, "LaunchCFMA", 10)) + (void)get_real_command_name(pid, tme->tm_command, MAXCOMLEN); } - fdmap->fd_setsize = 0; - } +} + + +threadmap_t +find_map_entry(uintptr_t thread) +{ + threadmap_t tme; + int hashid; - if (pid == 0 || pid == 1) - return; - else if (!strncmp(map->command, "LaunchCFMA", 10)) - (void)get_real_command_name(pid, map->command, sizeof(map->command)); + hashid = thread & HASH_MASK; + + for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) { + if (tme->tm_thread == thread) + return (tme); + } + return (0); } -kd_threadmap *find_thread_map(uintptr_t thread) +void +delete_map_entry(uintptr_t thread) { - int i; - kd_threadmap *map; - - if (!mapptr) - return((kd_threadmap *)0); - - for (i = 0; i < total_threads; i++) - { - map = &mapptr[i]; - if (map->valid && (map->thread == thread)) - { - return(map); + threadmap_t tme = 0; + threadmap_t tme_prev; + int hashid; + + hashid = thread & HASH_MASK; + + if ((tme = threadmap_hash[hashid])) { + if (tme->tm_thread == thread) + threadmap_hash[hashid] = tme->tm_next; + else { + tme_prev = tme; + + for (tme = tme->tm_next; tme; tme = tme->tm_next) { + if (tme->tm_thread == thread) { + tme_prev->tm_next = tme->tm_next; + break; + } + tme_prev = tme; + } + } + if (tme) { + if (tme->tm_setptr) + free(tme->tm_setptr); + + tme->tm_next = threadmap_freelist; + threadmap_freelist = tme; + } } - } - return ((kd_threadmap *)0); } -fd_threadmap *find_fd_thread_map(uintptr_t thread) + +void +fs_usage_fd_set(uintptr_t thread, unsigned int fd) { - int i; - fd_threadmap *fdmap = 0; - - if (!fdmapptr) - return((fd_threadmap *)0); - - for (i = 0; i < total_threads; i++) - { - fdmap = &fdmapptr[i]; - if (fdmap->fd_valid && (fdmap->fd_thread == thread)) - { - return(fdmap); + threadmap_t tme; + + if ((tme = find_map_entry(thread)) == 0) + return; + /* + * If the map is not allocated, then now is the time + */ + if (tme->tm_setptr == (unsigned long *)0) { + if ((tme->tm_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))) == 0) + return; + + tme->tm_setsize = FS_USAGE_FD_SETSIZE; + bzero(tme->tm_setptr, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))); } - } - return ((fd_threadmap *)0); + /* + * If the map is not big enough, then reallocate it + */ + while (tme->tm_setsize <= fd) { + int n; + + n = tme->tm_setsize * 2; + tme->tm_setptr = (unsigned long *)realloc(tme->tm_setptr, (FS_USAGE_NFDBYTES(n))); + + bzero(&tme->tm_setptr[(tme->tm_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(tme->tm_setsize))); + tme->tm_setsize = n; + } + /* + * set the bit + */ + tme->tm_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS)); } +/* + * Return values: + * 0 : File Descriptor bit is not set + * 1 : File Descriptor bit is set + */ +int +fs_usage_fd_isset(uintptr_t thread, unsigned int fd) +{ + threadmap_t tme; + int ret = 0; + + if ((tme = find_map_entry(thread))) { + if (tme->tm_setptr && fd < tme->tm_setsize) + ret = tme->tm_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS)); + } + return (ret); +} + + void -kill_thread_map(uintptr_t thread) +fs_usage_fd_clear(uintptr_t thread, unsigned int fd) { - kd_threadmap *map; - fd_threadmap *fdmap; - - if (thread == last_thread) - map_is_the_same = 0; - - if ((map = find_thread_map(thread))) { - map->valid = 0; - map->thread = 0; - map->command[0] = '\0'; - } - - if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER))) - { - if ((fdmap = find_fd_thread_map(thread))) - { - fdmap->fd_valid = 0; - fdmap->fd_thread = 0; - if (fdmap->fd_setptr) - { - free (fdmap->fd_setptr); - fdmap->fd_setptr = (unsigned long *)0; - } - fdmap->fd_setsize = 0; - } - } + threadmap_t tme; + + if ((tme = find_map_entry(thread))) { + if (tme->tm_setptr && fd < tme->tm_setsize) + tme->tm_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS)); + } } + + void -argtopid(str) - char *str; +argtopid(char *str) { char *cp; int ret; int i; ret = (int)strtol(str, &cp, 10); + if (cp == str || *cp) { - /* Assume this is a command string and find matching pids */ + /* + * Assume this is a command string and find matching pids + */ if (!kp_buffer) find_proc_names(); - for (i=0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) { - if(kp_buffer[i].kp_proc.p_stat == 0) - continue; - else { - if(!strncmp(str, kp_buffer[i].kp_proc.p_comm, - sizeof(kp_buffer[i].kp_proc.p_comm) -1)) - pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid; - } + for (i = 0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) { + if (kp_buffer[i].kp_proc.p_stat == 0) + continue; + else { + if (!strncmp(str, kp_buffer[i].kp_proc.p_comm, + sizeof(kp_buffer[i].kp_proc.p_comm) -1)) + pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid; + } } } else if (num_of_pids < (MAX_PIDS - 1)) pids[num_of_pids++] = ret; - - return; } @@ -4116,11 +4265,10 @@ lookup_name(uint64_t user_addr, char **type, char **name) last = numFrameworks; for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) { - if (user_addr > frameworkInfo[i].e_address) { + if (user_addr > frameworkInfo[i].e_address) start = i+1; - } else { + else last = i; - } } if (start < numFrameworks && user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) { @@ -4137,28 +4285,30 @@ lookup_name(uint64_t user_addr, char **type, char **name) */ static int compareFrameworkAddress(const void *aa, const void *bb) { - LibraryInfo *a = (LibraryInfo *)aa; - LibraryInfo *b = (LibraryInfo *)bb; + LibraryInfo *a = (LibraryInfo *)aa; + LibraryInfo *b = (LibraryInfo *)bb; - if (a->b_address < b->b_address) return -1; - if (a->b_address == b->b_address) return 0; - return 1; + if (a->b_address < b->b_address) return -1; + if (a->b_address == b->b_address) return 0; + return 1; } int scanline(char *inputstring, char **argv, int maxtokens) { - int n = 0; - char **ap = argv, *p, *val; - - for (p = inputstring; n < maxtokens && p != NULL; ) - { - while ((val = strsep(&p, " \t")) != NULL && *val == '\0'); - *ap++ = val; - n++; - } - *ap = 0; - return n; + int n = 0; + char **ap = argv, *p, *val; + + for (p = inputstring; n < maxtokens && p != NULL; ) { + + while ((val = strsep(&p, " \t")) != NULL && *val == '\0'); + + *ap++ = val; + n++; + } + *ap = 0; + + return n; } @@ -4182,9 +4332,8 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) lr->e_address = 0; if ((fd = fopen(path, "r")) == 0) - { return 0; - } + while (fgets(buf, 1023, fd)) { if (strncmp(buf, "mapping", 7)) break; @@ -4202,10 +4351,10 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) /* * There is a ".": name is whatever is between the "/" around the "." */ - while ( *substring != '/') { /* find "/" before "." */ + while ( *substring != '/') /* find "/" before "." */ substring--; - } substring++; + strncpy(frameworkName, substring, 256); /* copy path from "/" */ frameworkName[255] = 0; substring = frameworkName; @@ -4222,8 +4371,7 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) ptr = buf; substring = ptr; - while (*ptr) - { + while (*ptr) { if (*ptr == '/') substring = ptr + 1; ptr++; @@ -4234,8 +4382,7 @@ int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name) fnp = (char *)malloc(strlen(frameworkName) + 1); strcpy(fnp, frameworkName); - while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) - { + while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) { /* * Get rid of EOL */ @@ -4321,163 +4468,214 @@ SortFrameworkAddresses() struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime) { - register struct diskio *dio; - register kd_threadmap *map; - - if ((dio = free_diskios)) - free_diskios = dio->next; - else { - if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL) - return (NULL); - } - dio->prev = NULL; + struct diskio *dio; + threadmap_t tme; - dio->type = type; - dio->bp = bp; - dio->dev = dev; - dio->blkno = blkno; - dio->iosize = io_size; - dio->issued_time = curtime; - dio->issuing_thread = thread; + if ((dio = free_diskios)) + free_diskios = dio->next; + else { + if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL) + return (NULL); + } + dio->prev = NULL; - if ((map = find_thread_map(thread))) - { - strncpy(dio->issuing_command, map->command, MAXCOMLEN); - dio->issuing_command[MAXCOMLEN-1] = '\0'; - } - else - strcpy(dio->issuing_command, ""); + dio->type = type; + dio->bp = bp; + dio->dev = dev; + dio->blkno = blkno; + dio->iosize = io_size; + dio->issued_time = curtime; + dio->issuing_thread = thread; + + if ((tme = find_map_entry(thread))) { + strncpy(dio->issuing_command, tme->tm_command, MAXCOMLEN); + dio->issuing_command[MAXCOMLEN-1] = '\0'; + } else + strcpy(dio->issuing_command, ""); - dio->next = busy_diskios; - if (dio->next) - dio->next->prev = dio; - busy_diskios = dio; + dio->next = busy_diskios; + if (dio->next) + dio->next->prev = dio; + busy_diskios = dio; - return (dio); + return (dio); } struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime) { - register struct diskio *dio; + struct diskio *dio; - for (dio = busy_diskios; dio; dio = dio->next) { - if (dio->bp == bp) { - - if (dio == busy_diskios) { - if ((busy_diskios = dio->next)) - dio->next->prev = NULL; - } else { - if (dio->next) - dio->next->prev = dio->prev; - dio->prev->next = dio->next; - } - dio->iosize -= resid; - dio->io_errno = io_errno; - dio->completed_time = curtime; - dio->completion_thread = thread; + for (dio = busy_diskios; dio; dio = dio->next) { + + if (dio->bp == bp) { + if (dio == busy_diskios) { + if ((busy_diskios = dio->next)) + dio->next->prev = NULL; + } else { + if (dio->next) + dio->next->prev = dio->prev; + dio->prev->next = dio->next; + } + dio->iosize -= resid; + dio->io_errno = io_errno; + dio->completed_time = curtime; + dio->completion_thread = thread; - return (dio); - } - } - return ((struct diskio *)0); + return (dio); + } + } + return ((struct diskio *)0); } void free_diskio(struct diskio *dio) { - dio->next = free_diskios; - free_diskios = dio; + dio->next = free_diskios; + free_diskios = dio; } void print_diskio(struct diskio *dio) { - register char *p; - - switch (dio->type) { - - case P_RdMeta: - p = " RdMeta"; - break; - case P_WrMeta: - p = " WrMeta"; - break; - case P_RdData: - p = " RdData"; - break; - case P_WrData: - p = " WrData"; - break; - case P_PgIn: - p = " PgIn"; - break; - case P_PgOut: - p = " PgOut"; - break; - case P_RdMetaAsync: - p = " RdMeta[async]"; - break; - case P_WrMetaAsync: - p = " WrMeta[async]"; - break; - case P_RdDataAsync: - p = " RdData[async]"; - break; - case P_WrDataAsync: - p = " WrData[async]"; - break; - case P_PgInAsync: - p = " PgIn[async]"; - break; - case P_PgOutAsync: - p = " PgOut[async]"; - break; - default: - p = " "; - break; - } - if (check_filter_mode(NULL, dio->type, 0, 0, p)) - format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 0, FMT_DISKIO, dio->completed_time, dio->issued_time, 1, "", dio); + char *p = NULL; + int len = 0; + int type; + int format = FMT_DISKIO; + char buf[64]; + + type = dio->type; + + + if (type == P_CS_ReadChunk || type == P_CS_WriteChunk || type == P_CS_Originated_Read || + type == P_CS_Originated_Write || type == P_CS_MetaRead || type == P_CS_MetaWrite) { + + switch (type) { + + case P_CS_ReadChunk: + p = " RdChunkCS"; + len = 13; + format = FMT_DISKIO_CS; + break; + case P_CS_WriteChunk: + p = " WrChunkCS"; + len = 13; + format = FMT_DISKIO_CS; + break; + case P_CS_MetaRead: + p = " RdMetaCS"; + len = 10; + format = FMT_DISKIO_CS; + break; + case P_CS_MetaWrite: + p = " WrMetaCS"; + len = 10; + format = FMT_DISKIO_CS; + break; + case P_CS_Originated_Read: + p = " RdDataCS"; + len = 10; + break; + case P_CS_Originated_Write: + p = " WrDataCS"; + len = 10; + break; + } + strncpy(buf, p, len); + } else { + + switch (type & P_DISKIO_TYPE) { + + case P_RdMeta: + p = " RdMeta"; + len = 8; + break; + case P_WrMeta: + p = " WrMeta"; + len = 8; + break; + case P_RdData: + p = " RdData"; + len = 8; + break; + case P_WrData: + p = " WrData"; + len = 8; + break; + case P_PgIn: + p = " PgIn"; + len = 6; + break; + case P_PgOut: + p = " PgOut"; + len = 7; + break; + default: + p = " "; + len = 2; + break; + } + strncpy(buf, p, len); + + if (type & (P_DISKIO_ASYNC | P_DISKIO_THROTTLE | P_DISKIO_PASSIVE)) { + buf[len++] = '['; + + if (type & P_DISKIO_ASYNC) { + memcpy(&buf[len], "async", 5); + len += 5; + } + if (type & P_DISKIO_THROTTLE) + buf[len++] = 'T'; + else if (type & P_DISKIO_PASSIVE) + buf[len++] = 'P'; + + buf[len++] = ']'; + } + } + buf[len] = 0; + + if (check_filter_mode(NULL, type, 0, 0, buf)) + format_print(NULL, buf, dio->issuing_thread, type, 0, 0, 0, 0, format, dio->completed_time, dio->issued_time, 1, "", dio); } void cache_disk_names() { - struct stat st; - DIR *dirp = NULL; - struct dirent *dir; - struct diskrec *dnp; + struct stat st; + DIR *dirp = NULL; + struct dirent *dir; + struct diskrec *dnp; - if ((dirp = opendir("/dev")) == NULL) - return; + if ((dirp = opendir("/dev")) == NULL) + return; - while ((dir = readdir(dirp)) != NULL) { - char nbuf[MAXPATHLEN]; + while ((dir = readdir(dirp)) != NULL) { + char nbuf[MAXPATHLEN]; - if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4)) - continue; - snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name); + if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4)) + continue; + + snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name); - if (stat(nbuf, &st) < 0) - continue; + if (stat(nbuf, &st) < 0) + continue; - if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL) - continue; + if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL) + continue; - if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) { - free(dnp); - continue; - } - strncpy(dnp->diskname, dir->d_name, dir->d_namlen); - dnp->diskname[dir->d_namlen] = 0; - dnp->dev = st.st_rdev; + if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) { + free(dnp); + continue; + } + strncpy(dnp->diskname, dir->d_name, dir->d_namlen); + dnp->diskname[dir->d_namlen] = 0; + dnp->dev = st.st_rdev; - dnp->next = disk_list; - disk_list = dnp; - } - (void) closedir(dirp); + dnp->next = disk_list; + disk_list = dnp; + } + (void) closedir(dirp); } @@ -4499,110 +4697,38 @@ void recache_disk_names() char *find_disk_name(int dev) { - struct diskrec *dnp; - int i; + struct diskrec *dnp; + int i; - if (dev == NFS_DEV) - return ("NFS"); + if (dev == NFS_DEV) + return ("NFS"); - for (i = 0; i < 2; i++) { - for (dnp = disk_list; dnp; dnp = dnp->next) { - if (dnp->dev == dev) - return (dnp->diskname); - } - recache_disk_names(); - } - return ("NOTFOUND"); -} - -void -fs_usage_fd_set(thread, fd) - unsigned int thread; - unsigned int fd; -{ - int n; - fd_threadmap *fdmap; - - if(!(fdmap = find_fd_thread_map(thread))) - return; - - /* If the map is not allocated, then now is the time */ - if (fdmap->fd_setptr == (unsigned long *)0) - { - fdmap->fd_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)); - if (fdmap->fd_setptr) - { - fdmap->fd_setsize = FS_USAGE_FD_SETSIZE; - bzero(fdmap->fd_setptr,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))); + if (dev == CS_DEV) + return ("CS"); + + for (i = 0; i < 2; i++) { + for (dnp = disk_list; dnp; dnp = dnp->next) { + if (dnp->dev == dev) + return (dnp->diskname); + } + recache_disk_names(); } - else - return; - } - - /* If the map is not big enough, then reallocate it */ - while (fdmap->fd_setsize <= fd) - { - fprintf(stderr, "reallocating bitmap for threadid %d, fd = %d, setsize = %d\n", - thread, fd, fdmap->fd_setsize); - n = fdmap->fd_setsize * 2; - fdmap->fd_setptr = (unsigned long *)realloc(fdmap->fd_setptr, (FS_USAGE_NFDBYTES(n))); - bzero(&fdmap->fd_setptr[(fdmap->fd_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(fdmap->fd_setsize))); - fdmap->fd_setsize = n; - } - - /* set the bit */ - fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS)); - - return; + return ("NOTFOUND"); } -/* - Return values: - 0 : File Descriptor bit is not set - 1 : File Descriptor bit is set -*/ - -int -fs_usage_fd_isset(thread, fd) - unsigned int thread; - unsigned int fd; -{ - int ret = 0; - fd_threadmap *fdmap; - - if(!(fdmap = find_fd_thread_map(thread))) - return(ret); - if (fdmap->fd_setptr == (unsigned long *)0) - return (ret); - - if (fd < fdmap->fd_setsize) - ret = fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS)); - - return (ret); -} - -void -fs_usage_fd_clear(thread, fd) - unsigned int thread; - unsigned int fd; +char *generate_cs_disk_name(int dev, char *s) { - fd_threadmap *map; - - if (!(map = find_fd_thread_map(thread))) - return; - - if (map->fd_setptr == (unsigned long *)0) - return; + if (dev == -1) + return ("UNKNOWN"); + + sprintf(s, "disk%ds%d", (dev >> 16) & 0xffff, dev & 0xffff); - /* clear the bit */ - if (fd < map->fd_setsize) - map->fd_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS)); - - return; + return (s); } + /* * ret = 1 means print the entry * ret = 0 means don't print the entry @@ -4610,136 +4736,142 @@ fs_usage_fd_clear(thread, fd) int check_filter_mode(struct th_info * ti, int type, int error, int retval, char *sc_name) { - int ret = 0; - int network_fd_isset = 0; - unsigned int fd; - - if (filter_mode == DEFAULT_DO_NOT_FILTER) - return(1); - - if (sc_name[0] == 'C' && !strcmp (sc_name, "CACHE_HIT")) { - if (filter_mode & CACHEHIT_FILTER) - /* Do not print if cachehit filter is set */ - return(0); - return(1); - } + int ret = 0; + int network_fd_isset = 0; + unsigned int fd; + + if (filter_mode == DEFAULT_DO_NOT_FILTER) + return(1); + + if (sc_name[0] == 'C' && !strcmp (sc_name, "CACHE_HIT")) { + if (filter_mode & CACHEHIT_FILTER) + /* Do not print if cachehit filter is set */ + return(0); + return(1); + } - if (filter_mode & EXEC_FILTER) - { - if (type == BSC_execve) - return(1); - return(0); - } + if (filter_mode & EXEC_FILTER) { + if (type == BSC_execve || type == BSC_posix_spawn) + return(1); + return(0); + } - if (filter_mode & PATHNAME_FILTER) - { + if (filter_mode & PATHNAME_FILTER) { if (ti && ti->pathname[0]) return(1); if (type == BSC_close || type == BSC_close_nocancel) return(1); return(0); - } + } - if ( !(filter_mode & (FILESYS_FILTER | NETWORK_FILTER))) - return(1); + if ( !(filter_mode & (FILESYS_FILTER | NETWORK_FILTER))) + return(1); - - if (ti == (struct th_info *)0) - { - if (filter_mode & FILESYS_FILTER) - ret = 1; - else - ret = 0; - return(ret); - } - - switch (type) { - case BSC_close: - case BSC_close_nocancel: - fd = ti->arg1; - network_fd_isset = fs_usage_fd_isset(ti->thread, fd); - if (error == 0) - { - fs_usage_fd_clear(ti->thread,fd); + if (ti == (struct th_info *)0) { + if (filter_mode & FILESYS_FILTER) + return(1); + return(0); } - - if (network_fd_isset) - { + + switch (type) { + + case BSC_close: + case BSC_close_nocancel: + fd = ti->arg1; + network_fd_isset = fs_usage_fd_isset(ti->thread, fd); + + if (error == 0) + fs_usage_fd_clear(ti->thread,fd); + + if (network_fd_isset) { + if (filter_mode & NETWORK_FILTER) + ret = 1; + } else if (filter_mode & FILESYS_FILTER) + ret = 1; + break; + + case BSC_read: + case BSC_write: + case BSC_read_nocancel: + case BSC_write_nocancel: + /* + * we don't care about error in these cases + */ + fd = ti->arg1; + network_fd_isset = fs_usage_fd_isset(ti->thread, fd); + + if (network_fd_isset) { + if (filter_mode & NETWORK_FILTER) + ret = 1; + } else if (filter_mode & FILESYS_FILTER) + ret = 1; + break; + + case BSC_accept: + case BSC_accept_nocancel: + case BSC_socket: + fd = retval; + + if (error == 0) + fs_usage_fd_set(ti->thread, fd); if (filter_mode & NETWORK_FILTER) - ret = 1; - } - else if (filter_mode & FILESYS_FILTER) - ret = 1; - break; - case BSC_read: - case BSC_write: - case BSC_read_nocancel: - case BSC_write_nocancel: - /* we don't care about error in this case */ - fd = ti->arg1; - network_fd_isset = fs_usage_fd_isset(ti->thread, fd); - if (network_fd_isset) - { + ret = 1; + break; + + case BSC_recvfrom: + case BSC_sendto: + case BSC_recvmsg: + case BSC_sendmsg: + case BSC_connect: + case BSC_bind: + case BSC_listen: + case BSC_sendto_nocancel: + case BSC_recvfrom_nocancel: + case BSC_recvmsg_nocancel: + case BSC_sendmsg_nocancel: + case BSC_connect_nocancel: + fd = ti->arg1; + + if (error == 0) + fs_usage_fd_set(ti->thread, fd); if (filter_mode & NETWORK_FILTER) - ret = 1; - } - else if (filter_mode & FILESYS_FILTER) - ret = 1; - break; - case BSC_accept: - case BSC_accept_nocancel: - case BSC_socket: - fd = retval; - if (error == 0) - fs_usage_fd_set(ti->thread, fd); - if (filter_mode & NETWORK_FILTER) - ret = 1; - break; - case BSC_recvfrom: - case BSC_sendto: - case BSC_recvmsg: - case BSC_sendmsg: - case BSC_connect: - case BSC_bind: - case BSC_listen: - case BSC_sendto_nocancel: - case BSC_recvfrom_nocancel: - case BSC_recvmsg_nocancel: - case BSC_sendmsg_nocancel: - case BSC_connect_nocancel: - fd = ti->arg1; - if (error == 0) - fs_usage_fd_set(ti->thread, fd); - if (filter_mode & NETWORK_FILTER) - ret = 1; - break; - case BSC_select: - case BSC_select_nocancel: - case BSC_socketpair: - /* Cannot determine info about file descriptors */ - if (filter_mode & NETWORK_FILTER) - ret = 1; - break; - case BSC_dup: - case BSC_dup2: - ret=0; /* We track these cases for fd state only */ - fd = ti->arg1; /* oldd */ - network_fd_isset = fs_usage_fd_isset(ti->thread, fd); - if (error == 0 && network_fd_isset) - { - /* then we are duping a socket descriptor */ - fd = retval; /* the new fd */ - fs_usage_fd_set(ti->thread, fd); - } - break; + ret = 1; + break; + + case BSC_select: + case BSC_select_nocancel: + case BSC_socketpair: + /* + * Cannot determine info about file descriptors + */ + if (filter_mode & NETWORK_FILTER) + ret = 1; + break; + + case BSC_dup: + case BSC_dup2: + /* + * We track these cases for fd state only + */ + fd = ti->arg1; + network_fd_isset = fs_usage_fd_isset(ti->thread, fd); + + if (error == 0 && network_fd_isset) { + /* + * then we are duping a socket descriptor + */ + fd = retval; /* the new fd */ + fs_usage_fd_set(ti->thread, fd); + } + break; - default: - if (filter_mode & FILESYS_FILTER) - ret = 1; - break; - } + default: + if (filter_mode & FILESYS_FILTER) + ret = 1; + break; + } - return(ret); + return(ret); } /* @@ -4752,110 +4884,113 @@ check_filter_mode(struct th_info * ti, int type, int error, int retval, char *sc void init_arguments_buffer() { + int mib[2]; + size_t size; - int mib[2]; - size_t size; - - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - size = sizeof(argmax); - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) - return; + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + size = sizeof(argmax); + if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) + return; #if 1 - /* Hack to avoid kernel bug. */ - if (argmax > 8192) { - argmax = 8192; - } + /* Hack to avoid kernel bug. */ + if (argmax > 8192) { + argmax = 8192; + } #endif - - arguments = (char *)malloc(argmax); - - return; + arguments = (char *)malloc(argmax); } int get_real_command_name(int pid, char *cbuf, int csize) { - /* - * Get command and arguments. - */ - char *cp; - int mib[4]; - char *command_beg, *command, *command_end; - - if (cbuf == NULL) { - return(0); - } - - if (arguments) - bzero(arguments, argmax); - else - return(0); - - /* - * A sysctl() is made to find out the full path that the command - * was called with. - */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - mib[3] = 0; - - if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) { - return(0); - } - - /* Skip the saved exec_path. */ - for (cp = arguments; cp < &arguments[argmax]; cp++) { - if (*cp == '\0') { - /* End of exec_path reached. */ - break; - } - } - if (cp == &arguments[argmax]) { - return(0); - } - - /* Skip trailing '\0' characters. */ - for (; cp < &arguments[argmax]; cp++) { - if (*cp != '\0') { - /* Beginning of first argument reached. */ - break; + /* + * Get command and arguments. + */ + char *cp; + int mib[4]; + char *command_beg, *command, *command_end; + + if (cbuf == NULL) + return(0); + + if (arguments) + bzero(arguments, argmax); + else + return(0); + + /* + * A sysctl() is made to find out the full path that the command + * was called with. + */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = pid; + mib[3] = 0; + + if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) + return(0); + + /* + * Skip the saved exec_path + */ + for (cp = arguments; cp < &arguments[argmax]; cp++) { + if (*cp == '\0') { + /* + * End of exec_path reached + */ + break; + } } - } - if (cp == &arguments[argmax]) { - return(0); - } - command_beg = cp; - - /* - * Make sure that the command is '\0'-terminated. This protects - * against malicious programs; under normal operation this never - * ends up being a problem.. - */ - for (; cp < &arguments[argmax]; cp++) { - if (*cp == '\0') { - /* End of first argument reached. */ - break; + if (cp == &arguments[argmax]) + return(0); + + /* + * Skip trailing '\0' characters + */ + for (; cp < &arguments[argmax]; cp++) { + if (*cp != '\0') { + /* + * Beginning of first argument reached + */ + break; + } } - } - if (cp == &arguments[argmax]) { - return(0); - } - command_end = command = cp; - - /* Get the basename of command. */ - for (command--; command >= command_beg; command--) { - if (*command == '/') { - command++; - break; + if (cp == &arguments[argmax]) + return(0); + + command_beg = cp; + /* + * Make sure that the command is '\0'-terminated. This protects + * against malicious programs; under normal operation this never + * ends up being a problem.. + */ + for (; cp < &arguments[argmax]; cp++) { + if (*cp == '\0') { + /* + * End of first argument reached + */ + break; + } } - } + if (cp == &arguments[argmax]) + return(0); + + command_end = command = cp; - (void) strncpy(cbuf, (char *)command, csize); - cbuf[csize-1] = '\0'; + /* + * Get the basename of command + */ + for (command--; command >= command_beg; command--) { + if (*command == '/') { + command++; + break; + } + } + (void) strncpy(cbuf, (char *)command, csize); + cbuf[csize-1] = '\0'; - return(1); + return(1); } diff --git a/getconf.tproj/Makefile b/getconf.tproj/Makefile index aa855d9..dee18c1 100644 --- a/getconf.tproj/Makefile +++ b/getconf.tproj/Makefile @@ -9,7 +9,7 @@ CFILES = getconf.c \ $(OBJROOT)/$(Project)/sysconf.c MANPAGES = getconf.1 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -include _fbsd_compat.h -DAPPLE_GETCONF_UNDERSCORE \ -DAPPLE_GETCONF_SPEC -I. Extra_LD_Flags = -dead_strip diff --git a/getconf.tproj/sysconf.gperf b/getconf.tproj/sysconf.gperf index 95283a8..9bc3866 100644 --- a/getconf.tproj/sysconf.gperf +++ b/getconf.tproj/sysconf.gperf @@ -74,7 +74,7 @@ _POSIX2_FORT_DEV, _SC_2_FORT_DEV _POSIX2_FORT_RUN, _SC_2_FORT_RUN _POSIX2_LOCALEDEF, _SC_2_LOCALEDEF _POSIX2_PBS, _SC_PBS -_POSIX2_PBS_ACCOUNTING, _SC_PBS_ACCOUNTING, +_POSIX2_PBS_ACCOUNTING, _SC_PBS_ACCOUNTING _POSIX2_PBS_CHECKPOINT, _SC_PBS_CHECKPOINT _POSIX2_PBS_LOCATE, _SC_PBS_LOCATE _POSIX2_PBS_MESSAGE, _SC_PBS_MESSAGE diff --git a/getty.tproj/Makefile b/getty.tproj/Makefile index fe7ba77..e48d4aa 100644 --- a/getty.tproj/Makefile +++ b/getty.tproj/Makefile @@ -10,7 +10,7 @@ ifeq ($(Embedded),YES) LAUNCHD_PLISTS = com.apple.getty.plist endif -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/getty.tproj/chat.c b/getty.tproj/chat.c index 147ef84..9094722 100644 --- a/getty.tproj/chat.c +++ b/getty.tproj/chat.c @@ -390,7 +390,7 @@ chat_send(char const *str) { int r = 0; - if (chat_debug && CHATDEBUG_SEND) + if (chat_debug & CHATDEBUG_SEND) syslog(LOG_DEBUG, "chat_send '%s'", cleanstr(str, strlen(str))); if (*str) { diff --git a/hostinfo.tproj/Makefile b/hostinfo.tproj/Makefile index 2b6dcc4..376371d 100644 --- a/hostinfo.tproj/Makefile +++ b/hostinfo.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = hostinfo.c MANPAGES = hostinfo.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/iostat.tproj/Makefile b/iostat.tproj/Makefile index b6a5ca7..7a696b6 100644 --- a/iostat.tproj/Makefile +++ b/iostat.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = iostat.c MANPAGES = iostat.8 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_LD_Flags = -dead_strip Extra_Frameworks = -framework CoreFoundation -framework IOKit diff --git a/iostat.tproj/iostat.c b/iostat.tproj/iostat.c index 2713ef4..643df3d 100644 --- a/iostat.tproj/iostat.c +++ b/iostat.tproj/iostat.c @@ -329,7 +329,7 @@ main(int argc, char **argv) if (isdigit(**argv)) break; if (record_one_device(*argv)) - errx(1, "can't record '%s' for monitoring"); + errx(1, "can't record '%s' for monitoring", *argv); num_devices_specified++; } if (nflag == 0 && maxshowdevs < num_devices_specified) @@ -865,7 +865,7 @@ static void remove_drivelist(void* context, io_iterator_t drivelist) name = (CFStringRef)CFDictionaryGetValue(properties, CFSTR(kIOBSDNameKey)); - if (name && CFStringGetCString(name, bsdname, MAXDRIVENAME, CFStringGetSystemEncoding())) { + if (name && CFStringGetCString(name, bsdname, MAXDRIVENAME, kCFStringEncodingUTF8)) { int i; for (i = 0; i < num_devices; ++i) { if (strcmp(bsdname,drivestat[i].name) == 0) { @@ -958,7 +958,7 @@ record_device(io_registry_entry_t drive) CFSTR(kIOBSDNameKey)); if (name) CFStringGetCString(name, drivestat[num_devices].name, - MAXDRIVENAME, CFStringGetSystemEncoding()); + MAXDRIVENAME, kCFStringEncodingUTF8); else { errx(1, "device does not have a BSD name"); } diff --git a/latency.tproj/Makefile b/latency.tproj/Makefile index a8377fa..2576afd 100644 --- a/latency.tproj/Makefile +++ b/latency.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = latency.c MANPAGES = latency.1 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_LD_Flags = -dead_strip Extra_LD_Flags += -lcurses -lutil diff --git a/latency.tproj/latency.1 b/latency.tproj/latency.1 index debed8b..564eb90 100644 --- a/latency.tproj/latency.1 +++ b/latency.tproj/latency.1 @@ -8,14 +8,14 @@ .Nd monitors scheduling and interrupt latency .Sh SYNOPSIS .Nm latency -.Op Fl rt +.Op Fl p .Op Fl h -.Op Fl c Ar code_file -.Op Fl l Ar log_file +.Op Fl m .Op Fl st Ar threshold .Op Fl it Ar threshold -.Op Fl s Ar sleep_in_usecs -.Op Fl d Ar decrementer_in_usecs +.Op Fl c Ar code_file +.Op Fl l Ar log_file +.Op Fl R Ar raw_file .Op Fl n Ar kernel .Sh DESCRIPTION The @@ -35,9 +35,11 @@ that contains the mappings for the system calls. This option overrides the default location of the system call code file, which is found in /usr/share/misc/trace.codes. .\" ========== -.It Fl d Ar decrementer_in_usecs -Sets the decrementer, using a value expressed in microseconds. -On exit, the decrementer is set back to the system default value. +.It Fl h +Display high resolution interrupt latencies and write them to latencies.csv (truncate existing file) upon exit. +.\" ========== +.It Fl m +Display per-CPU interrupt latency statistics. .\" ========== .It Fl it Ar threshold Set the interrupt latency threshold, @@ -56,21 +58,16 @@ By default, acts on the default /mach_kernel. This option allows you to specify an alternate booted kernel. .\" ========== -.It Fl rt -Sets the real-time scheduling policy. -Default policy is timeshare. -.\" ========== -.It Fl h -Display high resolution interrupt latencies and write them to latencies.csv (truncate existing file) upon exit. -.\" ========== -.It Fl s Ar sleep_in_usecs -Sets the timer, taking an argument expressed in microseconds. -The default timer is set to 1000 microseconds. +.It Fl p Ar priority +Specifies the priority level to observe scheduler latencies for. .\" ========== .It Fl st Ar threshold Set the scheduler latency threshold in microseconds. If latency exceeds this, and a log file has been specified, a record of what occurred during this time is recorded. +.\" ========== +.It Fl R Ar raw_file +Specifies a raw trace file to use as input. .El .Pp The data columns displayed are as follows: @@ -87,11 +84,11 @@ utility is also SIGWINCH savvy, so adjusting your window geometry will change the list of delay values displayed. .Sh SAMPLE USAGE .Pp -latency -rt -st 20000 -it 1000 -l /var/tmp/latency.log +latency -p 97 -st 20000 -it 1000 -l /var/tmp/latency.log .Pp The .Nm latency -utility will set the realtime scheduling policy. +utility will watch threads with priority 97 for scheduling latencies. The threshold for the scheduler is set to 20000 microseconds. The threshold for interrupts is set to 1000 microseconds. Latencies that exceed these thresholds will be logged in /var/tmp/latency.log. diff --git a/latency.tproj/latency.c b/latency.tproj/latency.c index 65b3c9b..a731d4a 100644 --- a/latency.tproj/latency.c +++ b/latency.tproj/latency.c @@ -1,30 +1,28 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ - /* - cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o latency latency.c -lncurses + cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -o latency latency.c -lncurses -lutil */ #include @@ -36,14 +34,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include - -#include -#include -#include +#include #include #ifndef KERNEL_PRIVATE @@ -54,13 +55,6 @@ #include #endif /*KERNEL_PRIVATE*/ -#include - -#include -#include -#include - -#include #include #include #include @@ -70,10 +64,6 @@ #include -extern mach_port_t clock_port; - -#define KERN_KDPIDEX 14 - int s_usec_10_bins[10]; int s_usec_100_bins[10]; @@ -83,122 +73,226 @@ int s_too_slow; int s_max_latency; int s_min_latency = 0; long long s_total_latency = 0; -int s_total_samples; +int s_total_samples = 0; long s_thresh_hold; int s_exceeded_threshold = 0; -int i_usec_10_bins[10]; -int i_usec_100_bins[10]; -int i_msec_1_bins[10]; -int i_msec_10_bins[5]; -int i_too_slow; -int i_max_latency; -int i_min_latency = 0; -long long i_total_latency = 0; -int i_total_samples; + +#define N_HIGH_RES_BINS 500 +int use_high_res_bins = false; + +struct i_latencies { + int i_usec_10_bins[10]; + int i_usec_100_bins[10]; + int i_msec_1_bins[10]; + int i_msec_10_bins[5]; + int i_too_slow; + int i_max_latency; + int i_min_latency; + int i_total_samples; + int i_total; + int i_exceeded_threshold; + uint64_t i_total_latency; +}; + +struct i_latencies *i_lat; +boolean_t i_latency_per_cpu = FALSE; + +int i_high_res_bins[N_HIGH_RES_BINS]; + long i_thresh_hold; -int i_exceeded_threshold = 0; + +int watch_priority = 97; long start_time; long curr_time; long refresh_time; -char *policy_name; -int my_policy; -int my_pri = -1; -int num_of_usecs_to_sleep = 1000; - -#define N_HIGH_RES_BINS 500 -int use_high_res_bins = false; -int i_high_res_bins[N_HIGH_RES_BINS]; -int i_highest_latency = 0; -char *kernelpath = (char *)0; -char *code_file = (char *)0; +char *kernelpath = NULL; typedef struct { - u_long k_sym_addr; /* kernel symbol address from nm */ - u_int k_sym_len; /* length of kernel symbol string */ - char *k_sym_name; /* kernel symbol string from nm */ + void *k_sym_addr; /* kernel symbol address from nm */ + u_int k_sym_len; /* length of kernel symbol string */ + char *k_sym_name; /* kernel symbol string from nm */ } kern_sym_t; -kern_sym_t *kern_sym_tbl; /* pointer to the nm table */ -int kern_sym_count; /* number of entries in nm table */ -char pcstring[128]; +kern_sym_t *kern_sym_tbl; /* pointer to the nm table */ +int kern_sym_count; /* number of entries in nm table */ + + -#define UNKNOWN "Can't find symbol name" +#define MAX_ENTRIES 4096 +struct ct { + int type; + char name[32]; +} codes_tab[MAX_ENTRIES]; +char *code_file = NULL; +int num_of_codes = 0; -double divisor; -int gotSIGWINCH = 0; -int trace_enabled = 0; -struct host_basic_info hi; +double divisor; +sig_atomic_t gotSIGWINCH = 0; +int trace_enabled = 0; +int need_new_map = 1; +int set_remove_flag = 1; /* By default, remove trace buffer */ -#define SAMPLE_SIZE 300000 +int RAW_flag = 0; +int RAW_fd = 0; -int mib[6]; -size_t needed; -char *my_buffer; +uint64_t first_now = 0; +uint64_t last_now = 0; +int first_read = 1; + + +#define SAMPLE_TIME_USECS 50000 +#define SAMPLE_SIZE 300000 +#define MAX_LOG_COUNT 30 /* limits the number of entries dumped in log_decrementer */ kbufinfo_t bufinfo = {0, 0, 0}; -FILE *log_fp = (FILE *)0; -int num_of_codes = 0; -int need_new_map = 0; -int total_threads = 0; -kd_threadmap *mapptr = 0; +FILE *log_fp = NULL; -#define MAX_ENTRIES 4096 -struct ct { - int type; - char name[32]; -} codes_tab[MAX_ENTRIES]; +uint64_t sample_TOD_secs; +uint32_t sample_TOD_usecs; + +int sample_generation = 0; +int num_i_latency_cpus = 1; +int num_cpus; +char *my_buffer; +int num_entries; + +kd_buf **last_decrementer_kd; /* last DECR_TRAP per cpu */ #define NUMPARMS 23 -struct th_info { - uintptr_t thread; - int type; - uintptr_t child_thread; - int arg1; - double stime; - long *pathptr; - long pathname[NUMPARMS + 1]; +typedef struct event *event_t; + +struct event { + event_t ev_next; + + uintptr_t ev_thread; + uint32_t ev_type; + uint64_t ev_timestamp; +}; + + +typedef struct lookup *lookup_t; + +struct lookup { + lookup_t lk_next; + + uintptr_t lk_thread; + uintptr_t lk_dvp; + long *lk_pathptr; + long lk_pathname[NUMPARMS + 1]; +}; + + +typedef struct threadmap *threadmap_t; + +struct threadmap { + threadmap_t tm_next; + + uintptr_t tm_thread; + uintptr_t tm_pthread; + char tm_command[MAXCOMLEN + 1]; + char tm_orig_command[MAXCOMLEN + 1]; +}; + + +typedef struct threadrun *threadrun_t; + +struct threadrun { + threadrun_t tr_next; + + uintptr_t tr_thread; + kd_buf *tr_entry; + uint64_t tr_timestamp; +}; + + +typedef struct thread_entry *thread_entry_t; + +struct thread_entry { + thread_entry_t te_next; + + uintptr_t te_thread; }; + + +#define HASH_SIZE 1024 +#define HASH_MASK 1023 + +event_t event_hash[HASH_SIZE]; +lookup_t lookup_hash[HASH_SIZE]; +threadmap_t threadmap_hash[HASH_SIZE]; +threadrun_t threadrun_hash[HASH_SIZE]; + +event_t event_freelist; +lookup_t lookup_freelist; +threadrun_t threadrun_freelist; +threadmap_t threadmap_freelist; +threadmap_t threadmap_temp; + +thread_entry_t thread_entry_freelist; +thread_entry_t thread_delete_list; +thread_entry_t thread_reset_list; +thread_entry_t thread_event_list; +thread_entry_t thread_lookup_list; +thread_entry_t thread_run_list; + + +#ifndef RAW_VERSION1 +typedef struct { + int version_no; + int thread_count; + uint64_t TOD_secs; + uint32_t TOD_usecs; +} RAW_header; + +#define RAW_VERSION0 0x55aa0000 +#define RAW_VERSION1 0x55aa0101 +#endif + -#define MAX_THREADS 512 -struct th_info th_state[MAX_THREADS]; +#define USER_MODE 0 +#define KERNEL_MODE 1 -int cur_max = 0; -#define TRACE_DATA_NEWTHREAD 0x07000004 -#define TRACE_STRING_NEWTHREAD 0x07010004 -#define TRACE_STRING_EXEC 0x07010008 +#define TRACE_DATA_NEWTHREAD 0x07000004 +#define TRACE_STRING_NEWTHREAD 0x07010004 +#define TRACE_STRING_EXEC 0x07010008 -#define INTERRUPT 0x01050000 -#define DECR_TRAP 0x01090000 -#define DECR_SET 0x01090004 -#define MACH_vmfault 0x01300008 -#define MACH_sched 0x01400000 -#define MACH_stkhandoff 0x01400008 -#define VFS_LOOKUP 0x03010090 -#define BSC_exit 0x040C0004 -#define IES_action 0x050b0018 -#define IES_filter 0x050b001c -#define TES_action 0x050c0010 -#define CQ_action 0x050d0018 +#define INTERRUPT 0x01050000 +#define DECR_TRAP 0x01090000 +#define DECR_SET 0x01090004 +#define MACH_vmfault 0x01300008 +#define MACH_sched 0x01400000 +#define MACH_stkhandoff 0x01400008 +#define MACH_makerunnable 0x01400018 +#define MACH_idle 0x01400024 +#define VFS_LOOKUP 0x03010090 +#define IES_action 0x050b0018 +#define IES_filter 0x050b001c +#define TES_action 0x050c0010 +#define CQ_action 0x050d0018 +#define CPUPM_CPUSTER_RUNCOUNT 0x05310144 +#define BSC_exit 0x040C0004 +#define BSC_thread_terminate 0x040c05a4 -#define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END) -#define DBG_FUNC_MASK 0xfffffffc +#define DBG_FUNC_MASK ~(DBG_FUNC_START | DBG_FUNC_END) #define CPU_NUMBER(kp) kdbg_get_cpu(kp) +#define EMPTYSTRING "" -char *fault_name[9] = { - "", + +const char *fault_name[] = { + "", "ZeroFill", "PageIn", "COW", @@ -209,296 +303,256 @@ char *fault_name[9] = { "PageInAnon" }; -char *pc_to_string(); -static kern_return_t set_time_constraint_policy(void); -static kern_return_t set_standard_policy(void); - -int decrementer_val = 0; /* Value used to reset decrementer */ -int set_remove_flag = 1; /* By default, remove trace buffer */ - -kd_buf **last_decrementer_kd; /* last DECR_TRAP per cpu */ -#define MAX_LOG_COUNT 30 /* limits the number of entries dumped in log_decrementer */ +const char *sched_reasons[] = { + "N", + "P", + "Q", + "?", + "u", + "U", + "?", + "?", + "H", + "?", + "?", + "?", + "?", + "?", + "?", + "?", + "Y" +}; -int -quit(s) -char *s; +#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(*x))) +#define MAX_REASON ARRAYSIZE(sched_reasons) + +static double handle_decrementer(kd_buf *, int); +static kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency); +static void read_command_map(void); +static void enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info); +static void exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info); +static void print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd_note); +static void log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf *kd_note); +static char *find_code(int); +static void pc_to_string(char *pcstring, uintptr_t pc, int max_len, int mode); +static void getdivisor(void); +static int sample_sc(void); +static void init_code_file(void); +static void do_kernel_nm(void); +static void open_logfile(const char*); +static int binary_search(kern_sym_t *list, int low, int high, uintptr_t addr); + +static void create_map_entry(uintptr_t, char *); +static void check_for_thread_update(uintptr_t thread, int debugid_base, kd_buf *kbufp, char **command); +static void log_scheduler(kd_buf *kd_start, kd_buf *kd_stop, kd_buf *end_of_sample, double s_latency, uintptr_t thread); +static int check_for_scheduler_latency(int type, uintptr_t *thread, uint64_t now, kd_buf *kd, kd_buf **kd_start, double *latency); +static void open_rawfile(const char *path); + +static void screen_update(FILE *); + +static void set_enable(int); +static void set_remove(void); + +static int +quit(char *s) { - void set_enable(); - void set_rtcdec(); - void set_remove(); - - if (trace_enabled) - set_enable(0); - - /* - This flag is turned off when calling - quit() due to a set_remove() failure. - */ - if (set_remove_flag) - set_remove(); - - if (decrementer_val) - set_rtcdec(0); - - printf("latency: "); - if (s) + if (!RAW_flag) { + if (trace_enabled) { + set_enable(0); + } + /* + * This flag is turned off when calling + * quit() due to a set_remove() failure. + */ + if (set_remove_flag) { + set_remove(); + } + } + printf("latency: "); + if (s) { printf("%s", s); - + } exit(1); } void set_enable(int val) { - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDENABLE; /* protocol */ - mib[3] = val; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDENABLE\n"); + int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDENABLE, val }; + size_t needed; + + if (sysctl(mib, ARRAYSIZE(mib), NULL, &needed, NULL, 0) < 0) { + quit("trace facility failure, KERN_KDENABLE\n"); + } } void set_numbufs(int nbufs) { - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETBUF; - mib[3] = nbufs; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETBUF\n"); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETUP\n"); + int mib1[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSETBUF, nbufs }; + int mib2[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSETUP }; + size_t needed; + if (sysctl(mib1, ARRAYSIZE(mib1), NULL, &needed, NULL, 0) < 0) { + quit("trace facility failure, KERN_KDSETBUF\n"); + } + if (sysctl(mib2, ARRAYSIZE(mib2), NULL, &needed, NULL, 0) < 0) { + quit("trace facility failure, KERN_KDSETUP\n"); + } } void set_pidexclude(int pid, int on_off) { - kd_regtype kr; - - kr.type = KDBG_TYPENONE; - kr.value1 = pid; - kr.value2 = on_off; - needed = sizeof(kd_regtype); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDPIDEX; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; - - sysctl(mib, 3, &kr, &needed, NULL, 0); -} + int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDPIDEX }; + size_t needed = sizeof(kd_regtype); -void set_rtcdec(decval) -int decval; -{kd_regtype kr; - int ret; - extern int errno; - - kr.type = KDBG_TYPENONE; - kr.value1 = decval; - needed = sizeof(kd_regtype); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETRTCDEC; /* protocol */ - mib[3] = 0; /* wildcard address family */ - mib[4] = 0; - mib[5] = 0; /* no flags */ + kd_regtype kr = { + .type = KDBG_TYPENONE, + .value1 = pid, + .value2 = on_off + }; - errno = 0; - if ((ret=sysctl(mib, 3, &kr, &needed, NULL, 0)) < 0) - { - decrementer_val = 0; - /* ignore this sysctl error if it's not supported */ - if (errno == ENOENT) - return; - else - quit("trace facility failure, KERN_KDSETRTCDEC\n"); - } + sysctl(mib, ARRAYSIZE(mib), &kr, &needed, NULL, 0); } - void get_bufinfo(kbufinfo_t *val) { - needed = sizeof (*val); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDGETBUF; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, val, &needed, 0, 0) < 0) - quit("trace facility failure, KERN_KDGETBUF\n"); - + int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDGETBUF }; + size_t needed = sizeof (*val); + + if (sysctl(mib, ARRAYSIZE(mib), val, &needed, 0, 0) < 0) { + quit("trace facility failure, KERN_KDGETBUF\n"); + } } void -set_remove() +set_remove(void) { - extern int errno; - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREMOVE; /* protocol */ - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ + int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDREMOVE }; + size_t needed; errno = 0; - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - { - set_remove_flag = 0; - if(errno == EBUSY) - quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n"); - else - quit("trace facility failure, KERN_KDREMOVE\n"); - } + if (sysctl(mib, ARRAYSIZE(mib), NULL, &needed, NULL, 0) < 0) { + set_remove_flag = 0; + if (errno == EBUSY) { + quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n"); + } else { + quit("trace facility failure, KERN_KDREMOVE\n"); + } + } } + void -set_init_nologging() +write_high_res_latencies(void) { - /* When we aren't logging, only collect the DECR_TRAP trace points */ - kd_regtype kr; - kr.type = KDBG_VALCHECK; - kr.value1 = DECR_TRAP; - kr.value2 = 0; - kr.value3 = 0; - kr.value4 = 0; - needed = sizeof(kd_regtype); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETREG; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETREG\n"); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETUP\n"); -} + int i; + FILE *f; -void -set_init_logging() -{ kd_regtype kr; - - kr.type = KDBG_RANGETYPE; - kr.value1 = 0; - kr.value2 = -1; - needed = sizeof(kd_regtype); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETREG; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETREG\n"); - - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDSETUP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDSETUP\n"); + if (use_high_res_bins) { + if ((f = fopen("latencies.csv","w"))) { + for (i = 0; i < N_HIGH_RES_BINS; i++) { + fprintf(f, "%d,%d\n", i, i_high_res_bins[i]); + } + fclose(f); + } + } } void -write_high_res_latencies() +sigintr(int signo __attribute__((unused))) { - int i; - FILE *f; - if(use_high_res_bins) - { - f = fopen("latencies.csv","w"); - for(i=0;ii_total; + } + clen = sprintf(tbuf, "%s %10d %9d", s, total, itotal); + + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + if (i_latency_per_cpu == TRUE) { + clen += sprintf(&tbuf[clen], " %9d", il->i_total); + } + + il->i_total = 0; + } + sprintf(&tbuf[clen], "\n"); + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } } + + void screen_update(FILE *fp) { - int i; - int itotal, stotal; - int elapsed_secs; - int elapsed_mins; - int elapsed_hours; + int i; + int cpu; + int clen; + int itotal, stotal; + int elapsed_secs; + int elapsed_mins; + int elapsed_hours; + int min_lat, max_lat; + uint64_t tot_lat; unsigned int average_s_latency; unsigned int average_i_latency; - char tbuf[256]; + struct i_latencies *il; + char tbuf[1024]; - if (fp == (FILE *)0) { - erase(); + if (fp == NULL) { + erase(); move(0, 0); - } else - fprintf(fp,"\n\n===================================================================================================\n"); + } else { + fprintf(fp,"\n\n===================================================================================================\n"); + } /* * Display the current time. * "ctime" always returns a string that looks like this: @@ -509,7 +563,13 @@ screen_update(FILE *fp) * * We want indices 11 thru 18 (length 8). */ - elapsed_secs = curr_time - start_time; + if (RAW_flag) { + curr_time = sample_TOD_secs; + elapsed_secs = ((last_now - first_now) / divisor) / 1000000; + } else { + elapsed_secs = curr_time - start_time; + } + elapsed_hours = elapsed_secs / 3600; elapsed_secs -= elapsed_hours * 3600; elapsed_mins = elapsed_secs / 60; @@ -517,232 +577,331 @@ screen_update(FILE *fp) sprintf(tbuf, "%-19.19s %2ld:%02ld:%02ld\n", &(ctime(&curr_time)[0]), (long)elapsed_hours, (long)elapsed_mins, (long)elapsed_secs); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); - - if (use_high_res_bins) { - sprintf(tbuf, "INTERRUPTS(HIGH RESOLUTION)\n"); - - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); } - if(use_high_res_bins) - { - for(i=0;ii_total_samples; + } + clen = sprintf(tbuf, "\ntotal_samples %10d %9d", s_total_samples, itotal); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + clen += sprintf(&tbuf[clen], " %9d", il->i_total_samples); + } + } + sprintf(&tbuf[clen], "\n"); + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } - for (itotal = 0, stotal = 0, i = 0; i < 10; i++) { - sprintf(tbuf, "delays < %3d usecs %10d %10d\n", (i + 1) * 10, s_usec_10_bins[i], i_usec_10_bins[i]); + for (stotal = 0, i = 0; i < 10; i++) { + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + itotal += il->i_usec_10_bins[i]; + il->i_total += il->i_usec_10_bins[i]; + } + clen = sprintf(tbuf, "\ndelays < %3d usecs %10d %9d", (i + 1) * 10, s_usec_10_bins[i], itotal); stotal += s_usec_10_bins[i]; - itotal += i_usec_10_bins[i]; - } - sprintf(tbuf, "total < 100 usecs %10d %10d\n\n", stotal, itotal); - - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); - + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + clen += sprintf(&tbuf[clen], " %9d", il->i_usec_10_bins[i]); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + } + print_total(fp, "\ntotal < 100 usecs", stotal); - for (itotal = 0, stotal = 0, i = 1; i < 10; i++) { - if (i < 9) - sprintf(tbuf, "delays < %3d usecs %10d %10d\n", (i + 1) * 100, s_usec_100_bins[i], i_usec_100_bins[i]); - else - sprintf(tbuf, "delays < 1 msec %10d %10d\n", s_usec_100_bins[i], i_usec_100_bins[i]); + for (stotal = 0, i = 1; i < 10; i++) { + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + itotal += il->i_usec_100_bins[i]; + il->i_total += il->i_usec_100_bins[i]; + } + if (i < 9) { + clen = sprintf(tbuf, "\ndelays < %3d usecs %10d %9d", (i + 1) * 100, s_usec_100_bins[i], itotal); + } else { + clen = sprintf(tbuf, "\ndelays < 1 msec %10d %9d", s_usec_100_bins[i], itotal); + } stotal += s_usec_100_bins[i]; - itotal += i_usec_100_bins[i]; - } - sprintf(tbuf, "total < 1 msec %10d %10d\n\n", stotal, itotal); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + clen += sprintf(&tbuf[clen], " %9d", il->i_usec_100_bins[i]); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + } + print_total(fp, "\ntotal < 1 msec ", stotal); - for (itotal = 0, stotal = 0, i = 1; i < 10; i++) { - sprintf(tbuf, "delays < %3d msecs %10d %10d\n", (i + 1), s_msec_1_bins[i], i_msec_1_bins[i]); + for (stotal = 0, i = 1; i < 10; i++) { + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + itotal += il->i_msec_1_bins[i]; + il->i_total += il->i_msec_1_bins[i]; + } + clen = sprintf(tbuf, "\ndelays < %3d msecs %10d %9d", (i + 1), s_msec_1_bins[i], itotal); stotal += s_msec_1_bins[i]; - itotal += i_msec_1_bins[i]; - } - sprintf(tbuf, "total < 10 msecs %10d %10d\n\n", stotal, itotal); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + clen += sprintf(&tbuf[clen], " %9d", il->i_msec_1_bins[i]); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + } + print_total(fp, "\ntotal < 10 msecs", stotal); + for (stotal = 0, i = 1; i < 5; i++) { + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + itotal += il->i_msec_10_bins[i]; + il->i_total += il->i_msec_10_bins[i]; + } + clen = sprintf(tbuf, "\ndelays < %3d msecs %10d %9d", (i + 1)*10, s_msec_10_bins[i], itotal); - for (itotal = 0, stotal = 0, i = 1; i < 5; i++) { - sprintf(tbuf, "delays < %3d msecs %10d %10d\n", (i + 1)*10, s_msec_10_bins[i], i_msec_10_bins[i]); + stotal += s_msec_10_bins[i]; - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; - stotal += s_msec_10_bins[i]; - itotal += i_msec_10_bins[i]; + clen += sprintf(&tbuf[clen], " %9d", il->i_msec_10_bins[i]); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } } - sprintf(tbuf, "total < 50 msecs %10d %10d\n\n", stotal, itotal); - - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + print_total(fp, "\ntotal < 50 msecs", stotal); - sprintf(tbuf, "delays > 50 msecs %10d %10d\n", s_too_slow, i_too_slow); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + itotal += il->i_too_slow; + } + clen = sprintf(tbuf, "\ndelays > 50 msecs %10d %9d", s_too_slow, itotal); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + clen += sprintf(&tbuf[clen], " %9d", il->i_too_slow); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; - sprintf(tbuf, "\nminimum latency(usecs) %7d %7d\n", s_min_latency, i_min_latency); + if (cpu == 0 || (il->i_min_latency < min_lat)) { + min_lat = il->i_min_latency; + } + } + clen = sprintf(tbuf, "\n\nminimum latency(usecs) %7d %9d", s_min_latency, min_lat); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + clen += sprintf(&tbuf[clen], " %9d", il->i_min_latency); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } - sprintf(tbuf, "maximum latency(usecs) %7d %7d\n", s_max_latency, i_max_latency); - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; - if (s_total_samples) - average_s_latency = (unsigned int)(s_total_latency/s_total_samples); - else - average_s_latency = 0; + if (cpu == 0 || (il->i_max_latency > max_lat)) { + max_lat = il->i_max_latency; + } + } + clen = sprintf(tbuf, "\nmaximum latency(usecs) %7d %9d", s_max_latency, max_lat); - if (i_total_samples) - average_i_latency = (unsigned int)(i_total_latency/i_total_samples); - else - average_i_latency = 0; + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + clen += sprintf(&tbuf[clen], " %9d", il->i_max_latency); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + + if (s_total_samples) { + average_s_latency = (unsigned int)(s_total_latency/s_total_samples); + } else { + average_s_latency = 0; + } - sprintf(tbuf, "average latency(usecs) %7d %7d\n", average_s_latency, average_i_latency); + for (itotal = 0, tot_lat = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + itotal += il->i_total_samples; + tot_lat += il->i_total_latency; + } + if (itotal) { + average_i_latency = (unsigned)(tot_lat/itotal); + } else { + average_i_latency = 0; + } - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + clen = sprintf(tbuf, "\naverage latency(usecs) %7d %9d", average_s_latency, average_i_latency); - sprintf(tbuf, "exceeded threshold %7d %7d\n", s_exceeded_threshold, i_exceeded_threshold); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + if (il->i_total_samples) { + average_i_latency = (unsigned int)(il->i_total_latency/il->i_total_samples); + } else { + average_i_latency = 0; + } - if (fp) - fprintf(fp, "%s", tbuf); - else - printw(tbuf); + clen += sprintf(&tbuf[clen], " %9d", average_i_latency); + } + } + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + + for (itotal = 0, cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + itotal += il->i_exceeded_threshold; + } + clen = sprintf(tbuf, "\nexceeded threshold %7d %9d", s_exceeded_threshold, itotal); - if (fp == (FILE *)0) - refresh(); - else - fflush(fp); + if (i_latency_per_cpu == TRUE) { + for (cpu = 0; cpu < num_i_latency_cpus; cpu++) { + il = &i_lat[cpu]; + + clen += sprintf(&tbuf[clen], " %9d", il->i_exceeded_threshold); + } + } + sprintf(&tbuf[clen], "\n"); + + if (fp) { + fprintf(fp, "%s", tbuf); + } else { + printw(tbuf); + } + + if (fp == NULL) { + refresh(); + } else { + fflush(fp); + } } int -exit_usage() +exit_usage(void) { - - fprintf(stderr, "Usage: latency [-rt] [-h] [-c codefile] [-l logfile] [-st threshold]\n"); - -#if defined (__i386__) - fprintf(stderr, " [-it threshold] [-s sleep_in_usecs] [-n kernel]\n\n"); -#else - fprintf(stderr, " [-it threshold] [-s sleep_in_usecs]\n"); - fprintf(stderr, " [-d decrementer_in_usecs] [-n kernel]\n\n"); -#endif - - - fprintf(stderr, " -rt Set realtime scheduling policy. Default is timeshare.\n"); + fprintf(stderr, "Usage: latency [-p priority] [-h] [-m] [-st threshold] [-it threshold]\n"); + fprintf(stderr, " [-c codefile] [-l logfile] [-R rawfile] [-n kernel]\n\n"); + + fprintf(stderr, " -p specify scheduling priority to watch... default is realtime\n"); fprintf(stderr, " -h Display high resolution interrupt latencies and write them to latencies.csv (truncate existing file) upon exit.\n"); - fprintf(stderr, " -c specify name of codes file\n"); - fprintf(stderr, " -l specify name of file to log trace entries to when threshold is exceeded\n"); fprintf(stderr, " -st set scheduler latency threshold in microseconds... if latency exceeds this, then log trace\n"); + fprintf(stderr, " -m specify per-CPU interrupt latency reporting\n"); fprintf(stderr, " -it set interrupt latency threshold in microseconds... if latency exceeds this, then log trace\n"); - fprintf(stderr, " -s set sleep time in microseconds\n"); -#if !defined (__i386__) - fprintf(stderr, " -d set decrementer in microseconds.\n"); -#endif - fprintf(stderr, " -n specify kernel, default is /mach_kernel\n"); + fprintf(stderr, " -c specify name of codes file... default is /usr/share/misc/trace.codes\n"); + fprintf(stderr, " -l specify name of file to log trace entries to when the specified threshold is exceeded\n"); + fprintf(stderr, " -R specify name of raw trace file to process\n"); + fprintf(stderr, " -n specify kernel... default is /mach_kernel\n"); fprintf(stderr, "\nlatency must be run as root\n\n"); @@ -753,1399 +912,1629 @@ exit_usage() int main(int argc, char *argv[]) { - uint64_t start, stop; - uint64_t timestamp1; - uint64_t timestamp2; - uint64_t adeadline, adelay; - double fdelay; - int elapsed_usecs; - double nanosecs_to_sleep; - int loop_cnt, sample_sc_now; - int decrementer_usec = 0; - kern_return_t ret; - unsigned int size; - host_name_port_t host; - void getdivisor(); - void sample_sc(); - void init_code_file(); - void do_kernel_nm(); - void open_logfile(); - if (0 != reexec_to_match_kernel()) { fprintf(stderr, "Could not re-execute: %d\n", errno); exit(1); } + while (argc > 1) { - my_policy = THREAD_STANDARD_POLICY; - policy_name = "TIMESHARE"; + if (strcmp(argv[1], "-R") == 0) { + argc--; + argv++; - while (argc > 1) { - if (strcmp(argv[1], "-rt") == 0) { - my_policy = THREAD_TIME_CONSTRAINT_POLICY; /* the real time band */ - policy_name = "REALTIME"; + if (argc > 1) { + open_rawfile(argv[1]); + } else { + exit_usage(); + } + RAW_flag = 1; + + } else if (strcmp(argv[1], "-p") == 0) { + argc--; + argv++; + + if (argc > 1) { + watch_priority = atoi(argv[1]); + } else { + exit_usage(); + } } else if (strcmp(argv[1], "-st") == 0) { argc--; argv++; - if (argc > 1) - s_thresh_hold = atoi(argv[1]); - else - exit_usage(); - + if (argc > 1) { + s_thresh_hold = atoi(argv[1]); + } else { + exit_usage(); + } } else if (strcmp(argv[1], "-it") == 0) { argc--; argv++; - if (argc > 1) - i_thresh_hold = atoi(argv[1]); - else - exit_usage(); + if (argc > 1) { + i_thresh_hold = atoi(argv[1]); + } else { + exit_usage(); + } } else if (strcmp(argv[1], "-c") == 0) { argc--; argv++; - if (argc > 1) - code_file = argv[1]; - else - exit_usage(); + if (argc > 1) { + code_file = argv[1]; + } else { + exit_usage(); + } } else if (strcmp(argv[1], "-l") == 0) { argc--; argv++; - if (argc > 1) - open_logfile(argv[1]); - else - exit_usage(); - - } else if (strcmp(argv[1], "-s") == 0) { + if (argc > 1) { + open_logfile(argv[1]); + } else { + exit_usage(); + } + } else if (strcmp(argv[1], "-n") == 0) { argc--; argv++; - if (argc > 1) - num_of_usecs_to_sleep = atoi(argv[1]); - else - exit_usage(); - } - else if (strcmp(argv[1], "-d") == 0) { - argc--; - argv++; + if (argc > 1) { + kernelpath = argv[1]; + } else { + exit_usage(); + } + } else if (strcmp(argv[1], "-h") == 0) { + use_high_res_bins = TRUE; - if (argc > 1) - decrementer_usec = atoi(argv[1]); - else - exit_usage(); -#if defined(__i386__) - /* ignore this option - setting the decrementer has no effect */ - decrementer_usec = 0; -#endif - } - else if (strcmp(argv[1], "-n") == 0) { - argc--; - argv++; + } else if (strcmp(argv[1], "-m") == 0) { + i_latency_per_cpu = TRUE; - if (argc > 1) - kernelpath = argv[1]; - else - exit_usage(); - } else if (strcmp(argv[1], "-h") == 0) { - use_high_res_bins = true; - } else + } else { exit_usage(); + } argc--; argv++; } + if (!RAW_flag) { + if (geteuid() != 0) { + printf("'latency' must be run as root...\n"); + exit(1); + } + } + if (kernelpath == NULL) { + kernelpath = "/mach_kernel"; + } - if ( geteuid() != 0 ) { - printf("'latency' must be run as root...\n"); - exit(1); - } - - if (kernelpath == (char *) 0) - kernelpath = "/mach_kernel"; - - if (code_file == (char *) 0) - code_file = "/usr/share/misc/trace.codes"; + if (code_file == NULL) { + code_file = "/usr/share/misc/trace.codes"; + } do_kernel_nm(); - sample_sc_now = 25000 / num_of_usecs_to_sleep; - getdivisor(); - decrementer_val = decrementer_usec * divisor; - - /* get the cpu countfor the DECR_TRAP array */ - host = mach_host_self(); - size = sizeof(hi)/sizeof(int); - ret = host_info(host, HOST_BASIC_INFO, (host_info_t)&hi, &size); - if (ret != KERN_SUCCESS) { - mach_error(argv[0], ret); - exit(EXIT_FAILURE); - } - - if ((last_decrementer_kd = (kd_buf **)malloc(hi.max_cpus * sizeof(kd_buf *))) == (kd_buf **)0) - quit("can't allocate memory for decrementer tracing info\n"); - - nanosecs_to_sleep = (double)(num_of_usecs_to_sleep * 1000); - fdelay = nanosecs_to_sleep * (divisor /1000); - adelay = (uint64_t)fdelay; init_code_file(); - /* - When the decrementer isn't set in the options, - decval will be zero and this call will reset - the system default ... - */ - set_rtcdec(decrementer_val); - - if (initscr() == (WINDOW *) 0) - { - printf("Unrecognized TERM type, try vt100\n"); - exit(1); - } - - clear(); - refresh(); - signal(SIGWINCH, sigwinch); - signal(SIGINT, sigintr); - signal(SIGQUIT, leave); - signal(SIGTERM, leave); - signal(SIGHUP, leave); - - - if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0) - quit("can't allocate memory for tracing info\n"); - set_remove(); - set_numbufs(SAMPLE_SIZE); - set_enable(0); - if(log_fp) - set_init_logging(); - else - set_init_nologging(); - set_pidexclude(getpid(), 1); - set_enable(1); - trace_enabled = 1; - need_new_map = 1; - - loop_cnt = 0; - start_time = time((long *)0); - refresh_time = start_time; - - if (my_policy == THREAD_TIME_CONSTRAINT_POLICY) - { - /* the realtime band */ - if(set_time_constraint_policy() != KERN_SUCCESS) - quit("Failed to set realtime policy.\n"); - } - - for (;;) { - curr_time = time((long *)0); - - if (curr_time >= refresh_time) { - if (my_policy == THREAD_TIME_CONSTRAINT_POLICY) - { - /* set standard timeshare policy during screen update */ - if(set_standard_policy() != KERN_SUCCESS) - quit("Failed to set standard policy.\n"); - } - screen_update((FILE *)0); - if (my_policy == THREAD_TIME_CONSTRAINT_POLICY) - { - /* set back to realtime band */ - if(set_time_constraint_policy() != KERN_SUCCESS) - quit("Failed to set time_constraint policy.\n"); - } - refresh_time = curr_time + 1; - } - - timestamp1 = mach_absolute_time(); - adeadline = timestamp1 + adelay; - mach_wait_until(adeadline); - timestamp2 = mach_absolute_time(); - - start = timestamp1; - - stop = timestamp2; - - elapsed_usecs = (int)(((double)(stop - start)) / divisor); - - if ((elapsed_usecs -= num_of_usecs_to_sleep) <= 0) - continue; - - if (elapsed_usecs < 100) - s_usec_10_bins[elapsed_usecs/10]++; - if (elapsed_usecs < 1000) - s_usec_100_bins[elapsed_usecs/100]++; - else if (elapsed_usecs < 10000) - s_msec_1_bins[elapsed_usecs/1000]++; - else if (elapsed_usecs < 50000) - s_msec_10_bins[elapsed_usecs/10000]++; - else - s_too_slow++; - - if (elapsed_usecs > s_max_latency) - s_max_latency = elapsed_usecs; - if (elapsed_usecs < s_min_latency || s_total_samples == 0) - s_min_latency = elapsed_usecs; - s_total_latency += elapsed_usecs; - s_total_samples++; - - if (s_thresh_hold && elapsed_usecs > s_thresh_hold) - s_exceeded_threshold++; - loop_cnt++; - - if (log_fp && s_thresh_hold && elapsed_usecs > s_thresh_hold) - sample_sc(start, stop); - else { - if (loop_cnt >= sample_sc_now) { - sample_sc((long long)0, (long long)0); - loop_cnt = 0; - } + if (!RAW_flag) { + if (initscr() == NULL) { + printf("Unrecognized TERM type, try vt100\n"); + exit(1); } - if (gotSIGWINCH) { - /* - No need to check for initscr error return. - We won't get here if it fails on the first call. - */ - endwin(); - clear(); - refresh(); + clear(); + refresh(); - gotSIGWINCH = 0; - } - } -} + signal(SIGWINCH, sigwinch); + signal(SIGINT, sigintr); + signal(SIGQUIT, leave); + signal(SIGTERM, leave); + signal(SIGHUP, leave); + /* + * grab the number of cpus and scale the buffer size + */ + int mib[] = { CTL_HW, HW_NCPU }; + size_t len = sizeof(num_cpus); -void getdivisor() -{ - mach_timebase_info_data_t info; + sysctl(mib, ARRAYSIZE(mib), &num_cpus, &len, NULL, 0); - (void) mach_timebase_info (&info); + set_remove(); + set_numbufs(SAMPLE_SIZE * num_cpus); - divisor = ( (double)info.denom / (double)info.numer) * 1000; + get_bufinfo(&bufinfo); -} + set_enable(0); -/* This is the realtime band */ -static kern_return_t -set_time_constraint_policy() -{ - kern_return_t result; - thread_time_constraint_policy_data_t info; - mach_msg_type_number_t count; - boolean_t get_default; - - get_default = TRUE; - count = THREAD_TIME_CONSTRAINT_POLICY_COUNT; - result = thread_policy_get(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY, - (thread_policy_t)&info, &count, &get_default); - if (result != KERN_SUCCESS) - return (result); - - result = thread_policy_set(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY, - (thread_policy_t)&info, THREAD_TIME_CONSTRAINT_POLICY_COUNT); - - return (result); -} + set_pidexclude(getpid(), 1); + set_enable(1); -/* This is the timeshare mode */ -static kern_return_t -set_standard_policy() -{ - kern_return_t result; - thread_standard_policy_data_t info; - mach_msg_type_number_t count; - boolean_t get_default; - - get_default = TRUE; - count = THREAD_STANDARD_POLICY_COUNT; - result = thread_policy_get(mach_thread_self(), THREAD_STANDARD_POLICY, - (thread_policy_t)&info, &count, &get_default); - if (result != KERN_SUCCESS) - return (result); - - result = thread_policy_set(mach_thread_self(), THREAD_STANDARD_POLICY, - (thread_policy_t)&info, THREAD_STANDARD_POLICY_COUNT); - - return (result); -} + num_entries = bufinfo.nkdbufs; + } else { + num_entries = 50000; + num_cpus = 128; + } - -void read_command_map() -{ - size_t size; - int mib[6]; - - if (mapptr) { - free(mapptr); - mapptr = 0; - } - total_threads = bufinfo.nkdthreads; - size = bufinfo.nkdthreads * sizeof(kd_threadmap); - if (size) - { - if ((mapptr = (kd_threadmap *) malloc(size))) - bzero (mapptr, size); - else - { - printf("Thread map is not initialized -- this is not fatal\n"); - return; - } - } - - /* Now read the threadmap */ - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDTHRMAP; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) - { - /* This is not fatal -- just means I cant map command strings */ - - printf("Can't read the thread map -- this is not fatal\n"); - free(mapptr); - mapptr = 0; - return; - } - return; -} + if ((my_buffer = malloc(num_entries * sizeof(kd_buf))) == NULL) { + quit("can't allocate memory for tracing info\n"); + } + if ((last_decrementer_kd = (kd_buf **)malloc(num_cpus * sizeof(kd_buf *))) == NULL) { + quit("can't allocate memory for decrementer tracing info\n"); + } -void create_map_entry(uintptr_t thread, char *command) -{ - int i, n; - kd_threadmap *map; - - if (!mapptr) - return; - - for (i = 0, map = 0; !map && i < total_threads; i++) - { - if (mapptr[i].thread == thread ) - map = &mapptr[i]; /* Reuse this entry, the thread has been reassigned */ - } - - if (!map) /* look for invalid entries that I can reuse*/ - { - for (i = 0, map = 0; !map && i < total_threads; i++) - { - if (mapptr[i].valid == 0 ) - map = &mapptr[i]; /* Reuse this invalid entry */ - } - } - - if (!map) - { - /* If reach here, then this is a new thread and - * there are no invalid entries to reuse - * Double the size of the thread map table. - */ + if (i_latency_per_cpu == FALSE) { + num_i_latency_cpus = 1; + } else { + num_i_latency_cpus = num_cpus; + } - n = total_threads * 2; - mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap)); - bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap)); - map = &mapptr[total_threads]; - total_threads = n; -#if 0 - if (log_fp) - fprintf(log_fp, "MAP: increasing thread map to %d entries\n", total_threads); -#endif - } -#if 0 - if (log_fp) - fprintf(log_fp, "MAP: adding thread %x with name %s\n", thread, command); -#endif - map->valid = 1; - map->thread = thread; - /* - The trace entry that returns the command name will hold - at most, MAXCOMLEN chars, and in that case, is not - guaranteed to be null terminated. - */ - (void)strncpy (map->command, command, MAXCOMLEN); - map->command[MAXCOMLEN] = '\0'; -} + if ((i_lat = (struct i_latencies *)malloc(num_i_latency_cpus * sizeof(struct i_latencies))) == NULL) { + quit("can't allocate memory for interrupt latency info\n"); + } + bzero((char *)i_lat, num_i_latency_cpus * sizeof(struct i_latencies)); -kd_threadmap *find_thread_map(uintptr_t thread) -{ - int i; - kd_threadmap *map; + if (RAW_flag) { + while (sample_sc()) { + continue; + } - if (!mapptr) - return((kd_threadmap *)0); + if (log_fp) { + screen_update(log_fp); + } - for (i = 0; i < total_threads; i++) - { - map = &mapptr[i]; - if (map->valid && (map->thread == thread)) - { - return(map); - } - } - return ((kd_threadmap *)0); -} + screen_update(stdout); -void -kill_thread_map(uintptr_t thread) -{ - kd_threadmap *map; + } else { + uint64_t adelay; + double fdelay; + double nanosecs_to_sleep; - if ((map = find_thread_map(thread))) { + nanosecs_to_sleep = (double)(SAMPLE_TIME_USECS * 1000); + fdelay = nanosecs_to_sleep * (divisor /1000); + adelay = (uint64_t)fdelay; -#if 0 - if (log_fp) - fprintf(log_fp, "MAP: deleting thread %x with name %s\n", thread, map->command); -#endif - map->valid = 0; - map->thread = 0; - map->command[0] = '\0'; - } -} + trace_enabled = 1; + start_time = time(NULL); + refresh_time = start_time; -struct th_info *find_thread(uintptr_t thread, int type1, int type2) { - struct th_info *ti; + for (;;) { + curr_time = time(NULL); - for (ti = th_state; ti < &th_state[cur_max]; ti++) { - if (ti->thread == thread) { - if (type1 == 0) - return(ti); - if (type1 == ti->type) - return(ti); - if (type2 == ti->type) - return(ti); - } - } - return ((struct th_info *)0); -} + if (curr_time >= refresh_time) { + screen_update(NULL); + refresh_time = curr_time + 1; + } + mach_wait_until(mach_absolute_time() + adelay); + sample_sc(); -char *find_code(type) -{ - int i; + if (gotSIGWINCH) { + /* + * No need to check for initscr error return. + * We won't get here if it fails on the first call. + */ + endwin(); + clear(); + refresh(); - for (i = 0; i < num_of_codes; i++) { - if (codes_tab[i].type == type) - return(codes_tab[i].name); + gotSIGWINCH = 0; + } + } } - return ((char *)0); } -void sample_sc(uint64_t start, uint64_t stop) + +void +read_command_map(void) { - kd_buf *kd, *last_mach_sched, *start_kd, *end_of_sample; - uint64_t now; - int count, i; - int first_entry = 1; - double timestamp = 0.0; - double last_timestamp = 0.0; - double delta = 0.0; - double start_bias = 0.0; - char command[32]; - void read_command_map(); - - if (log_fp && (my_policy == THREAD_TIME_CONSTRAINT_POLICY)) - { - /* set standard timeshare policy when logging */ - if(set_standard_policy() != KERN_SUCCESS) - quit("Failed to set standard policy.\n"); - } - - /* Get kernel buffer information */ - get_bufinfo(&bufinfo); - - if (need_new_map) { - read_command_map(); - need_new_map = 0; - } - needed = bufinfo.nkdbufs * sizeof(kd_buf); - mib[0] = CTL_KERN; - mib[1] = KERN_KDEBUG; - mib[2] = KERN_KDREADTR; - mib[3] = 0; - mib[4] = 0; - mib[5] = 0; /* no flags */ - - if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0) - quit("trace facility failure, KERN_KDREADTR\n"); - - count = needed; - - if (bufinfo.flags & KDBG_WRAPPED) { - for (i = 0; i < cur_max; i++) { - th_state[i].thread = 0; - th_state[i].type = -1; - th_state[i].pathptr = (long *)NULL; - th_state[i].pathname[0] = 0; + kd_threadmap *mapptr = 0; + int total_threads = 0; + size_t size; + off_t offset; + int i; + RAW_header header = {0}; + + if (RAW_flag) { + if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) { + perror("read failed"); + exit(2); + } + if (header.version_no != RAW_VERSION1) { + header.version_no = RAW_VERSION0; + header.TOD_secs = time(NULL); + header.TOD_usecs = 0; + + lseek(RAW_fd, (off_t)0, SEEK_SET); + + if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) { + perror("read failed"); + exit(2); + } } - cur_max = 0; - need_new_map = 1; + total_threads = header.thread_count; - set_enable(0); - set_enable(1); - - if (log_fp) { - double latency; + sample_TOD_secs = header.TOD_secs; + sample_TOD_usecs = header.TOD_usecs; - latency = (double)(stop - start) / divisor; - latency -= (double)num_of_usecs_to_sleep; + if (total_threads == 0 && header.version_no != RAW_VERSION0) { + offset = lseek(RAW_fd, (off_t)0, SEEK_CUR); + offset = (offset + (4095)) & ~4095; - fprintf(log_fp, "\n\n%-19.19s scheduling latency = %.1fus num_of_traces = %d <<<<<<< trace buffer wrapped >>>>>>>\n\n", - &(ctime(&curr_time)[0]), latency, count); + lseek(RAW_fd, offset, SEEK_SET); } + } else { + total_threads = bufinfo.nkdthreads; } - end_of_sample = &((kd_buf *)my_buffer)[count]; - - /* Always reinitialize the DECR_TRAP array */ - for (i=0; i < hi.max_cpus; i++) - last_decrementer_kd[i] = (kd_buf *)my_buffer; - - last_mach_sched = (kd_buf *)0; - - for (kd = (kd_buf *)my_buffer; kd < end_of_sample; kd++) { - int debugid, thread, cpunum; - int type, clen, mode; - int len; - char *p; - long *sargptr; - kd_buf *cur_kd; - double i_latency = 0.0; - struct th_info *ti; - char command1[32]; - char sched_info[64]; - kd_threadmap *map; - kd_threadmap *find_thread_map(); - double handle_decrementer(); - kd_buf *log_decrementer(); - int check_for_thread_update(); - void enter_syscall(); - void exit_syscall(); - void print_entry(); - - thread = kd->arg5; - cpunum = CPU_NUMBER(kd); - debugid = kd->debugid; - type = kd->debugid & DBG_FUNC_MASK; - - if (check_for_thread_update(thread, type, kd)) - continue; - - if (type == DECR_TRAP) - i_latency = handle_decrementer(kd); - - now = kd->timestamp & KDBG_TIMESTAMP_MASK; + + size = total_threads * sizeof(kd_threadmap); - timestamp = ((double)now) / divisor; - - if (now < start || now > stop) { - if (debugid & DBG_FUNC_START) - enter_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 0); - else if (debugid & DBG_FUNC_END) - exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 0); - else if (type == DECR_TRAP) { - cur_kd = kd; - if (log_fp && i_thresh_hold && (int)i_latency > i_thresh_hold) { - start_kd = last_decrementer_kd[cpunum]; - kd = log_decrementer(start_kd, kd, end_of_sample, i_latency); - if (kd >= end_of_sample) - break; - } - if ((kd->debugid & DBG_FUNC_MASK) == DECR_TRAP) - { - cpunum = CPU_NUMBER(kd); - last_decrementer_kd[cpunum] = kd; - } - else - last_decrementer_kd[cpunum] = cur_kd; - } - continue; + if (size == 0 || ((mapptr = (kd_threadmap *) malloc(size)) == 0)) { + return; + } + bzero (mapptr, size); + + /* + * Now read the threadmap + */ + if (RAW_flag) { + if (read(RAW_fd, mapptr, size) != size) { + printf("Can't read the thread map -- this is not fatal\n"); } - if (first_entry) { - double latency; - char buf1[132]; - char buf2[132]; - - latency = (double)(stop - start) / divisor; - latency -= (double)num_of_usecs_to_sleep; - - if (my_pri == -1) - sprintf(buf2, "default"); - else - sprintf(buf2, "%d", my_pri); - sprintf(buf1, "%-19.19s scheduling latency = %.1fus sleep_request = %dus policy = %s priority = %s", - &(ctime(&curr_time)[0]), latency, num_of_usecs_to_sleep, policy_name, buf2); - clen = strlen(buf1); - memset(buf2, '-', clen); - buf2[clen] = 0; - - if (log_fp) { - fprintf(log_fp, "\n\n%s\n", buf2); - fprintf(log_fp, "%s\n\n", buf1); - fprintf(log_fp, "RelTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu command\n\n"); - } - start_bias = ((double)start) / divisor; - last_timestamp = timestamp; - first_entry = 0; + if (header.version_no != RAW_VERSION0) { + offset = lseek(RAW_fd, (off_t)0, SEEK_CUR); + offset = (offset + (4095)) & ~4095; + + lseek(RAW_fd, offset, SEEK_SET); } - delta = timestamp - last_timestamp; + } else { + int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDTHRMAP}; + if (sysctl(mib, ARRAYSIZE(mib), mapptr, &size, NULL, 0) < 0) { + /* + * This is not fatal -- just means I cant map command strings + */ + printf("Can't read the thread map -- this is not fatal\n"); - if ((map = find_thread_map(thread))) - strcpy(command, map->command); - else - command[0] = 0; + total_threads = 0; + } + } + for (i = 0; i < total_threads; i++) { + create_map_entry(mapptr[i].thread, &mapptr[i].command[0]); + } + free(mapptr); +} - switch (type) { +void +create_map_entry(uintptr_t thread, char *command) +{ + threadmap_t tme; - case CQ_action: - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-59.59s %-8x %d %s\n", - timestamp - start_bias, delta, pc_to_string(kd->arg1, 59, 1) , thread, cpunum, command); - } - last_timestamp = timestamp; - break; + if ((tme = threadmap_freelist)) { + threadmap_freelist = tme->tm_next; + } else { + tme = (threadmap_t)malloc(sizeof(struct threadmap)); + } - case TES_action: - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f\t\tTES_action @ %-58.58s %-8x %d %s\n", - timestamp - start_bias, delta, pc_to_string(kd->arg1, 58, 1) , thread, cpunum, command); - } + tme->tm_thread = thread; - last_timestamp = timestamp; - break; + (void)strncpy (tme->tm_command, command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; + tme->tm_orig_command[0] = '\0'; - case IES_action: - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f\t\tIES_action @ %-58.58s %-8x %d %s\n", - timestamp - start_bias, delta, pc_to_string(kd->arg1, 58, 1) , thread, cpunum, command); - } + int hashid = thread & HASH_MASK; - last_timestamp = timestamp; - break; + tme->tm_next = threadmap_hash[hashid]; + threadmap_hash[hashid] = tme; +} - case IES_filter: - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f\t\tIES_filter @ %-58.58s %-8x %d %s\n", - timestamp - start_bias, delta, pc_to_string(kd->arg1, 58, 1) , thread, cpunum, command); - } +void +delete_thread_entry(uintptr_t thread) +{ + threadmap_t tme; - last_timestamp = timestamp; - break; + int hashid = thread & HASH_MASK; - case DECR_TRAP: - last_decrementer_kd[cpunum] = kd; + if ((tme = threadmap_hash[hashid])) { + if (tme->tm_thread == thread) { + threadmap_hash[hashid] = tme->tm_next; + } else { + threadmap_t tme_prev = tme; - if (i_thresh_hold && (int)i_latency > i_thresh_hold) - p = "*"; - else - p = " "; + for (tme = tme->tm_next; tme; tme = tme->tm_next) { + if (tme->tm_thread == thread) { + tme_prev->tm_next = tme->tm_next; + break; + } + tme_prev = tme; + } + } + if (tme) { + tme->tm_next = threadmap_freelist; + threadmap_freelist = tme; + } + } +} - mode = 1; +void +find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) +{ + threadmap_t tme; + + if ((tme = threadmap_temp)) { + if (tme->tm_pthread == pthread) { + threadmap_temp = tme->tm_next; + } else { + threadmap_t tme_prev = tme; + + for (tme = tme->tm_next; tme; tme = tme->tm_next) { + if (tme->tm_pthread == pthread) { + tme_prev->tm_next = tme->tm_next; + break; + } + tme_prev = tme; + } + } + if (tme) { + (void)strncpy (tme->tm_command, command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; + tme->tm_orig_command[0] = '\0'; + + int hashid = tme->tm_thread & HASH_MASK; + tme->tm_next = threadmap_hash[hashid]; + threadmap_hash[hashid] = tme; + } + } +} - if ((ti = find_thread(kd->arg5, 0, 0))) { - if (ti->type == -1 && strcmp(command, "kernel_task")) - mode = 0; - } +void +create_tmp_map_entry(uintptr_t thread, uintptr_t pthread) +{ + threadmap_t tme; - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-59.59s %-8x %d %s\n", - timestamp - start_bias, delta, i_latency, p, pc_to_string(kd->arg2, 59, mode) , thread, cpunum, command); - } + if ((tme = threadmap_freelist)) { + threadmap_freelist = tme->tm_next; + } else { + tme = malloc(sizeof(struct threadmap)); + } - last_timestamp = timestamp; - break; + tme->tm_thread = thread; + tme->tm_pthread = pthread; + tme->tm_command[0] = '\0'; + tme->tm_orig_command[0] = '\0'; - case DECR_SET: - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f[%.1f] \t%-28.28s %-8x %d %s\n", - timestamp - start_bias, delta, (double)kd->arg1/divisor, "DECR_SET", thread, cpunum, command); - } + tme->tm_next = threadmap_temp; + threadmap_temp = tme; +} - last_timestamp = timestamp; - break; +threadmap_t +find_thread_entry(uintptr_t thread) +{ + threadmap_t tme; - case MACH_sched: - case MACH_stkhandoff: - last_mach_sched = kd; + int hashid = thread & HASH_MASK; - if ((map = find_thread_map(kd->arg2))) - strcpy(command1, map->command); - else - sprintf(command1, "%-8x", kd->arg2); + for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) { + if (tme->tm_thread == thread) { + return tme; + } + } + return 0; +} - if ((ti = find_thread(kd->arg2, 0, 0))) { - if (ti->type == -1 && strcmp(command1, "kernel_task")) - p = "U"; - else - p = "K"; - } else - p = "*"; - memset(sched_info, ' ', sizeof(sched_info)); +void +find_thread_name(uintptr_t thread, char **command) +{ + threadmap_t tme; - sprintf(sched_info, "%14.14s", command); - clen = strlen(sched_info); - sched_info[clen] = ' '; + if ((tme = find_thread_entry(thread))) { + *command = tme->tm_command; + } else { + *command = EMPTYSTRING; + } +} - sprintf(&sched_info[14], " @ pri %3d --> %14.14s", kd->arg3, command1); - clen = strlen(sched_info); - sched_info[clen] = ' '; +void +add_thread_entry_to_list(thread_entry_t *list, uintptr_t thread) +{ + thread_entry_t te; - sprintf(&sched_info[45], " @ pri %3d%s", kd->arg4, p); + if ((te = thread_entry_freelist)) { + thread_entry_freelist = te->te_next; + } else { + te = (thread_entry_t)malloc(sizeof(struct thread_entry)); + } - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s %s %-8x %d\n", - timestamp - start_bias, delta, "MACH_SCHED", sched_info, thread, cpunum); - } + te->te_thread = thread; + te->te_next = *list; + *list = te; +} - last_timestamp = timestamp; - break; +void +exec_thread_entry(uintptr_t thread, char *command) +{ + threadmap_t tme; - case VFS_LOOKUP: - if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) { - if (cur_max >= MAX_THREADS) - continue; - ti = &th_state[cur_max++]; - - ti->thread = thread; - ti->type = -1; - ti->pathptr = (long *)0; - ti->child_thread = 0; - } - while ( (kd < end_of_sample) && ((kd->debugid & DBG_FUNC_MASK) == VFS_LOOKUP)) - { - if (ti->pathptr == NULL) { - ti->arg1 = kd->arg1; - sargptr = ti->pathname; - - *sargptr++ = kd->arg2; - *sargptr++ = kd->arg3; - *sargptr++ = kd->arg4; - /* - * NULL terminate the 'string' - */ - *sargptr = 0; - ti->pathptr = sargptr; + if ((tme = find_thread_entry(thread))) { + if (tme->tm_orig_command[0] == '\0') { + (void)strncpy (tme->tm_orig_command, tme->tm_command, MAXCOMLEN); + tme->tm_orig_command[MAXCOMLEN] = '\0'; + } + (void)strncpy (tme->tm_command, command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; - } else { - sargptr = ti->pathptr; + add_thread_entry_to_list(&thread_reset_list, thread); + } else { + create_map_entry(thread, command); + } +} - /* - We don't want to overrun our pathname buffer if the - kernel sends us more VFS_LOOKUP entries than we can - handle. - */ +void +record_thread_entry_for_gc(uintptr_t thread) +{ + add_thread_entry_to_list(&thread_delete_list, thread); +} - if (sargptr >= &ti->pathname[NUMPARMS]) - { - kd++; - continue; - } - - /* - We need to detect consecutive vfslookup entries. - So, if we get here and find a START entry, - fake the pathptr so we can bypass all further - vfslookup entries. - */ - - if (kd->debugid & DBG_FUNC_START) - { - ti->pathptr = &ti->pathname[NUMPARMS]; - } - else - { - *sargptr++ = kd->arg1; - *sargptr++ = kd->arg2; - *sargptr++ = kd->arg3; - *sargptr++ = kd->arg4; - /* - * NULL terminate the 'string' - */ - *sargptr = 0; +void +gc_thread_entries(void) +{ + thread_entry_t te; + thread_entry_t te_next; + int count = 0; - ti->pathptr = sargptr; - } - } - kd++; - } - p = (char *)ti->pathname; - - kd--; - - /* print the tail end of the pathname */ - len = strlen(p); - if (len > 42) - len -= 42; - else - len = 0; - - if (log_fp) { - fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-42s %-8x %-8x %d %s\n", - timestamp - start_bias, delta, "VFS_LOOKUP", - &p[len], ti->arg1, thread, cpunum, command); - } - - last_timestamp = timestamp; - break; + for (te = thread_delete_list; te; te = te_next) { + delete_thread_entry(te->te_thread); - default: - if (debugid & DBG_FUNC_START) - enter_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1); - else if (debugid & DBG_FUNC_END) - exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1); - else - print_entry(log_fp, kd, thread, type, command, timestamp, delta, start_bias); + te_next = te->te_next; + te->te_next = thread_entry_freelist; + thread_entry_freelist = te; - last_timestamp = timestamp; - break; - } + count++; } - if (last_mach_sched && log_fp) - fprintf(log_fp, "\nblocked by %s @ priority %d\n", command, last_mach_sched->arg3); -#if 0 - if (first_entry == 0 && log_fp) - fprintf(log_fp, "\n start = %qd stop = %qd count = %d now = %qd\n", start, stop, count, now); -#endif - if (log_fp) - fflush(log_fp); - - if (log_fp && (my_policy == THREAD_TIME_CONSTRAINT_POLICY)) - { - /* set back to realtime band */ - if(set_time_constraint_policy() != KERN_SUCCESS) - quit("Failed to set time_constraint policy.\n"); - } + thread_delete_list = 0; } void -enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double timestamp, double delta, double bias, int print_info) +gc_reset_entries(void) { - struct th_info *ti; - int i; - int cpunum; - char *p; - - cpunum = CPU_NUMBER(kd); - - if (print_info && fp) { - if ((p = find_code(type))) { - if (type == INTERRUPT) { - int mode = 1; - - if ((ti = find_thread(kd->arg5, 0, 0))) { - if (ti->type == -1 && strcmp(command, "kernel_task")) - mode = 0; - } - - fprintf(fp, "%9.1f %8.1f\t\tINTERRUPT @ %-59.59s %-8x %d %s\n", - timestamp - bias, delta, pc_to_string(kd->arg2, 59, mode), thread, cpunum, command); - } else if (type == MACH_vmfault) { - fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8x %d %s\n", - timestamp - bias, delta, p, thread, cpunum, command); - } else { - fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8x %-8x %-8x %-8x %-8x %d %s\n", - timestamp - bias, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, - thread, cpunum, command); - } - } else { - fprintf(fp, "%9.1f %8.1f\t\t%-8x %-8x %-8x %-8x %-8x %-8x %d %s\n", - timestamp - bias, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, - thread, cpunum, command); - } - } - if ((ti = find_thread(thread, -1, type)) == (struct th_info *)0) { - if (cur_max >= MAX_THREADS) { - static int do_this_once = 1; - - if (do_this_once) { - for (i = 0; i < cur_max; i++) { - if (!fp) - break; - fprintf(fp, "thread = %x, type = %x\n", - th_state[i].thread, th_state[i].type); - } - do_this_once = 0; - } - return; + thread_entry_t te; + thread_entry_t te_next; + int count = 0; - } - ti = &th_state[cur_max++]; - - ti->thread = thread; - ti->child_thread = 0; - } - if (type != BSC_exit) - ti->type = type; - else - ti->type = -1; - ti->stime = timestamp; - ti->pathptr = (long *)NULL; + for (te = thread_reset_list; te; te = te_next) { + te_next = te->te_next; + te->te_next = thread_entry_freelist; + thread_entry_freelist = te; -#if 0 - if (print_info && fp) - fprintf(fp, "cur_max = %d, ti = %x, type = %x, thread = %x\n", cur_max, ti, ti->type, ti->thread); -#endif + count++; + } + thread_reset_list = 0; } - void -exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double timestamp, double delta, double bias, int print_info) +reset_thread_names(void) { - struct th_info *ti; - int cpunum; - char *p; - uint64_t user_addr; - - cpunum = CPU_NUMBER(kd); + thread_entry_t te; + thread_entry_t te_next; + int count = 0; + + for (te = thread_reset_list; te; te = te_next) { + threadmap_t tme; + + if ((tme = find_thread_entry(te->te_thread))) { + if (tme->tm_orig_command[0]) { + (void)strncpy (tme->tm_command, tme->tm_orig_command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; + tme->tm_orig_command[0] = '\0'; + } + } + te_next = te->te_next; + te->te_next = thread_entry_freelist; + thread_entry_freelist = te; - ti = find_thread(thread, type, type); -#if 0 - if (print_info && fp) - fprintf(fp, "cur_max = %d, ti = %x, type = %x, thread = %x\n", cur_max, ti, type, thread); -#endif - if (print_info && fp) { - if (ti) - fprintf(fp, "%9.1f %8.1f(%.1f) \t", timestamp - bias, delta, timestamp - ti->stime); - else - fprintf(fp, "%9.1f %8.1f() \t", timestamp - bias, delta); - - if ((p = find_code(type))) { - if (type == INTERRUPT) { - fprintf(fp, "INTERRUPT %-8x %d %s\n", thread, cpunum, command); - } else if (type == MACH_vmfault && kd->arg4 <= DBG_PAGEIND_FAULT) { - user_addr = ((uint64_t)kd->arg1 << 32) | (uint32_t)kd->arg2; - - fprintf(fp, "%-28.28s %-10.10s %-16qx %-8x %d %s\n", - p, fault_name[kd->arg4], user_addr, - thread, cpunum, command); - } else { - fprintf(fp, "%-28.28s %-8x %-8x %-8x %d %s\n", - p, kd->arg1, kd->arg2, - thread, cpunum, command); - } - } else { - fprintf(fp, "%-8x %-8x %-8x %-8x %d %s\n", - type, kd->arg1, kd->arg2, - thread, cpunum, command); - } - } - if (ti == (struct th_info *)0) { - if ((ti = find_thread(thread, -1, -1)) == (struct th_info *)0) { - if (cur_max >= MAX_THREADS) - return; - ti = &th_state[cur_max++]; - - ti->thread = thread; - ti->child_thread = 0; - ti->pathptr = (long *)NULL; - } - } - ti->type = -1; + count++; + } + thread_reset_list = 0; } void -print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, double timestamp, double delta, double bias) +delete_all_thread_entries(void) { - char *p; - int cpunum; + threadmap_t tme = 0; + threadmap_t tme_next = 0; + int i; + + for (i = 0; i < HASH_SIZE; i++) { + for (tme = threadmap_hash[i]; tme; tme = tme_next) { + tme_next = tme->tm_next; + tme->tm_next = threadmap_freelist; + threadmap_freelist = tme; + } + threadmap_hash[i] = 0; + } +} - if (!fp) - return; - cpunum = CPU_NUMBER(kd); -#if 0 - fprintf(fp, "cur_max = %d, type = %x, thread = %x, cpunum = %d\n", cur_max, type, thread, cpunum); -#endif - if ((p = find_code(type))) { - fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8x %-8x %-8x %-8x %-8x %d %s\n", - timestamp - bias, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, - thread, cpunum, command); - } else { - fprintf(fp, "%9.1f %8.1f\t\t%-8x %-8x %-8x %-8x %-8x %-8x %d %s\n", - timestamp - bias, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, - thread, cpunum, command); - } -} -int -check_for_thread_update(int thread, int type, kd_buf *kd) + +static void +insert_run_event(uintptr_t thread, kd_buf *kd, uint64_t now) { - struct th_info *ti; - void create_map_entry(); + threadrun_t trp; - switch (type) { + int hashid = thread & HASH_MASK; - case TRACE_DATA_NEWTHREAD: - if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) { - if (cur_max >= MAX_THREADS) - return (1); - ti = &th_state[cur_max++]; + for (trp = threadrun_hash[hashid]; trp; trp = trp->tr_next) { + if (trp->tr_thread == thread) { + break; + } + } + if (trp == NULL) { + if ((trp = threadrun_freelist)) { + threadrun_freelist = trp->tr_next; + } else { + trp = (threadrun_t)malloc(sizeof(struct threadrun)); + } - ti->thread = thread; - ti->type = -1; - ti->pathptr = (long *)NULL; - } - ti->child_thread = kd->arg1; - return (1); + trp->tr_thread = thread; - case TRACE_STRING_NEWTHREAD: - if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) - return (1); - if (ti->child_thread == 0) - return (1); - create_map_entry(ti->child_thread, (char *)&kd->arg1); + trp->tr_next = threadrun_hash[hashid]; + threadrun_hash[hashid] = trp; - ti->child_thread = 0; - return (1); + add_thread_entry_to_list(&thread_run_list, thread); + } + trp->tr_entry = kd; + trp->tr_timestamp = now; +} - case TRACE_STRING_EXEC: - create_map_entry(thread, (char *)&kd->arg1); - return (1); +static threadrun_t +find_run_event(uintptr_t thread) +{ + threadrun_t trp; + int hashid = thread & HASH_MASK; + for (trp = threadrun_hash[hashid]; trp; trp = trp->tr_next) { + if (trp->tr_thread == thread) { + return trp; + } } - return (0); + return 0; } - -kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency) +static void +delete_run_event(uintptr_t thread) { - kd_buf *kd, *kd_start, *kd_stop; - int kd_count; /* Limit the boundary of kd_start */ - double timestamp = 0.0; - double last_timestamp = 0.0; - double delta = 0.0; - double start_bias = 0.0; - int thread, cpunum; - int debugid, type, clen; - int len; - uint64_t now; - struct th_info *ti; - long *sargptr; - char *p; - char command[32]; - char command1[32]; - char sched_info[64]; - char buf1[128]; - char buf2[128]; - kd_threadmap *map; - kd_threadmap *find_thread_map(); - - sprintf(buf1, "%-19.19s interrupt latency = %.1fus", &(ctime(&curr_time)[0]), i_latency); - clen = strlen(buf1); - memset(buf2, '-', clen); - buf2[clen] = 0; - fprintf(log_fp, "\n\n%s\n", buf2); - fprintf(log_fp, "%s\n\n", buf1); + threadrun_t trp = 0; + threadrun_t trp_prev; - fprintf(log_fp, "RelTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu command\n\n"); + int hashid = thread & HASH_MASK; - thread = kd_beg->arg5; - cpunum = CPU_NUMBER(kd_end); + if ((trp = threadrun_hash[hashid])) { + if (trp->tr_thread == thread) { + threadrun_hash[hashid] = trp->tr_next; + } else { + trp_prev = trp; - for (kd_count = 0, kd_start = kd_beg - 1; (kd_start >= (kd_buf *)my_buffer); kd_start--, kd_count++) { - if (kd_count == MAX_LOG_COUNT) - break; + for (trp = trp->tr_next; trp; trp = trp->tr_next) { + if (trp->tr_thread == thread) { + trp_prev->tr_next = trp->tr_next; + break; + } + trp_prev = trp; + } + } + if (trp) { + trp->tr_next = threadrun_freelist; + threadrun_freelist = trp; + } + } +} - if (CPU_NUMBER(kd_start) != cpunum) - continue; - - if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP) - break; +static void +gc_run_events(void) { + thread_entry_t te; + thread_entry_t te_next; + threadrun_t trp; + threadrun_t trp_next; + int count = 0; + + for (te = thread_run_list; te; te = te_next) { + int hashid = te->te_thread & HASH_MASK; + + for (trp = threadrun_hash[hashid]; trp; trp = trp_next) { + trp_next = trp->tr_next; + trp->tr_next = threadrun_freelist; + threadrun_freelist = trp; + count++; + } + threadrun_hash[hashid] = 0; - if (kd_start->arg5 != thread) - break; + te_next = te->te_next; + te->te_next = thread_entry_freelist; + thread_entry_freelist = te; } + thread_run_list = 0; +} - if (kd_start < (kd_buf *)my_buffer) - kd_start = (kd_buf *)my_buffer; - thread = kd_end->arg5; - for (kd_stop = kd_end + 1; kd_stop < end_of_sample; kd_stop++) { - - if ((kd_stop->debugid & DBG_FUNC_MASK) == DECR_TRAP) - break; +static void +insert_start_event(uintptr_t thread, int type, uint64_t now) +{ + event_t evp; - if (CPU_NUMBER(kd_stop) != cpunum) - continue; + int hashid = thread & HASH_MASK; - if (kd_stop->arg5 != thread) - break; + for (evp = event_hash[hashid]; evp; evp = evp->ev_next) { + if (evp->ev_thread == thread && evp->ev_type == type) { + break; + } } + if (evp == NULL) { + if ((evp = event_freelist)) { + event_freelist = evp->ev_next; + } else { + evp = (event_t)malloc(sizeof(struct event)); + } - if (kd_stop >= end_of_sample) - kd_stop = end_of_sample - 1; + evp->ev_thread = thread; + evp->ev_type = type; + + evp->ev_next = event_hash[hashid]; + event_hash[hashid] = evp; + + add_thread_entry_to_list(&thread_event_list, thread); + } + evp->ev_timestamp = now; +} - now = kd_start->timestamp & KDBG_TIMESTAMP_MASK; - timestamp = ((double)now) / divisor; - for (kd = kd_start; kd <= kd_stop; kd++) { - type = kd->debugid & DBG_FUNC_MASK; +static uint64_t +consume_start_event(uintptr_t thread, int type, uint64_t now) +{ + event_t evp; + event_t evp_prev; + uint64_t elapsed = 0; + + int hashid = thread & HASH_MASK; + + if ((evp = event_hash[hashid])) { + if (evp->ev_thread == thread && evp->ev_type == type) { + event_hash[hashid] = evp->ev_next; + } else { + evp_prev = evp; + + for (evp = evp->ev_next; evp; evp = evp->ev_next) { + if (evp->ev_thread == thread && evp->ev_type == type) { + evp_prev->ev_next = evp->ev_next; + break; + } + evp_prev = evp; + } + } + if (evp) { + elapsed = now - evp->ev_timestamp; - if ((ti = find_thread(kd->arg5, type, type))) { - if (ti->stime >= timestamp) - ti->type = -1; + if (now < evp->ev_timestamp) { + printf("consume: now = %qd, timestamp = %qd\n", now, evp->ev_timestamp); + elapsed = 0; + } + evp->ev_next = event_freelist; + event_freelist = evp; } } - for (kd = kd_start; kd <= kd_stop; kd++) { - int mode; + return elapsed; +} - thread = kd->arg5; - cpunum = CPU_NUMBER(kd); - debugid = kd->debugid; - type = kd->debugid & DBG_FUNC_MASK; +static void +gc_start_events(void) +{ + thread_entry_t te; + thread_entry_t te_next; + event_t evp; + event_t evp_next; + int count = 0; + int hashid; + + for (te = thread_event_list; te; te = te_next) { + + hashid = te->te_thread & HASH_MASK; + + for (evp = event_hash[hashid]; evp; evp = evp_next) { + evp_next = evp->ev_next; + evp->ev_next = event_freelist; + event_freelist = evp; + count++; + } + event_hash[hashid] = 0; - now = kd->timestamp & KDBG_TIMESTAMP_MASK; + te_next = te->te_next; + te->te_next = thread_entry_freelist; + thread_entry_freelist = te; + } + thread_event_list = 0; +} + +int +thread_in_user_mode(uintptr_t thread, char *command) +{ + event_t evp; + + if (strcmp(command, "kernel_task") == 0) { + return 0; + } + + int hashid = thread & HASH_MASK; + + for (evp = event_hash[hashid]; evp; evp = evp->ev_next) { + if (evp->ev_thread == thread) { + return 0; + } + } + return 1; +} + + + +static lookup_t +handle_lookup_event(uintptr_t thread, int debugid, kd_buf *kdp) +{ + lookup_t lkp; + boolean_t first_record = FALSE; + + int hashid = thread & HASH_MASK; + + if (debugid & DBG_FUNC_START) { + first_record = TRUE; + } + + for (lkp = lookup_hash[hashid]; lkp; lkp = lkp->lk_next) { + if (lkp->lk_thread == thread) { + break; + } + } + if (lkp == NULL) { + if (first_record == FALSE) { + return 0; + } + + if ((lkp = lookup_freelist)) { + lookup_freelist = lkp->lk_next; + } else { + lkp = (lookup_t)malloc(sizeof(struct lookup)); + } + + lkp->lk_thread = thread; + + lkp->lk_next = lookup_hash[hashid]; + lookup_hash[hashid] = lkp; + + add_thread_entry_to_list(&thread_lookup_list, thread); + } + + if (first_record == TRUE) { + lkp->lk_pathptr = lkp->lk_pathname; + lkp->lk_dvp = kdp->arg1; + } else { + if (lkp->lk_pathptr > &lkp->lk_pathname[NUMPARMS-4]) { + return lkp; + } + *lkp->lk_pathptr++ = kdp->arg1; + } + *lkp->lk_pathptr++ = kdp->arg2; + *lkp->lk_pathptr++ = kdp->arg3; + *lkp->lk_pathptr++ = kdp->arg4; + *lkp->lk_pathptr = 0; + + if (debugid & DBG_FUNC_END) { + return lkp; + } + + return 0; +} + +static void +delete_lookup_event(uintptr_t thread, lookup_t lkp_to_delete) +{ + lookup_t lkp; + lookup_t lkp_prev; + int hashid; + + hashid = thread & HASH_MASK; + + if ((lkp = lookup_hash[hashid])) { + if (lkp == lkp_to_delete) { + lookup_hash[hashid] = lkp->lk_next; + } else { + lkp_prev = lkp; + + for (lkp = lkp->lk_next; lkp; lkp = lkp->lk_next) { + if (lkp == lkp_to_delete) { + lkp_prev->lk_next = lkp->lk_next; + break; + } + lkp_prev = lkp; + } + } + if (lkp) { + lkp->lk_next = lookup_freelist; + lookup_freelist = lkp; + } + } +} + +static void +gc_lookup_events(void) { + thread_entry_t te; + thread_entry_t te_next; + lookup_t lkp; + lookup_t lkp_next; + int count = 0; + int hashid; + + for (te = thread_lookup_list; te; te = te_next) { + hashid = te->te_thread & HASH_MASK; + + for (lkp = lookup_hash[hashid]; lkp; lkp = lkp_next) { + lkp_next = lkp->lk_next; + lkp->lk_next = lookup_freelist; + lookup_freelist = lkp; + count++; + } + lookup_hash[hashid] = 0; + + te_next = te->te_next; + te->te_next = thread_entry_freelist; + thread_entry_freelist = te; + } + thread_lookup_list = 0; +} + +int +sample_sc(void) +{ + kd_buf *kd, *end_of_sample; + int keep_going = 1; + int count, i; + + if (!RAW_flag) { + /* + * Get kernel buffer information + */ + get_bufinfo(&bufinfo); + } + if (need_new_map) { + delete_all_thread_entries(); + read_command_map(); + need_new_map = 0; + } + if (RAW_flag) { + uint32_t bytes_read; + + bytes_read = read(RAW_fd, my_buffer, num_entries * sizeof(kd_buf)); + + if (bytes_read == -1) { + perror("read failed"); + exit(2); + } + count = bytes_read / sizeof(kd_buf); + + if (count != num_entries) { + keep_going = 0; + } + + if (first_read) { + kd = (kd_buf *)my_buffer; + first_now = kd->timestamp & KDBG_TIMESTAMP_MASK; + first_read = 0; + } + + } else { + int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDREADTR }; + size_t needed = bufinfo.nkdbufs * sizeof(kd_buf); + + if (sysctl(mib, ARRAYSIZE(mib), my_buffer, &needed, NULL, 0) < 0) { + quit("trace facility failure, KERN_KDREADTR\n"); + } + + count = needed; + sample_generation++; + + if (bufinfo.flags & KDBG_WRAPPED) { + need_new_map = 1; + + if (log_fp) { + fprintf(log_fp, "\n\n%-19.19s sample = %d <<<<<<< trace buffer wrapped >>>>>>>\n\n", + &(ctime(&curr_time)[0]), sample_generation); + } + set_enable(0); + set_enable(1); + } + } + end_of_sample = &((kd_buf *)my_buffer)[count]; + + /* + * Always reinitialize the DECR_TRAP array + */ + for (i = 0; i < num_cpus; i++) { + last_decrementer_kd[i] = (kd_buf *)my_buffer; + } + + for (kd = (kd_buf *)my_buffer; kd < end_of_sample; kd++) { + kd_buf *kd_start; + uintptr_t thread = kd->arg5; + int type = kd->debugid & DBG_FUNC_MASK; + + (void)check_for_thread_update(thread, type, kd, NULL); + + uint64_t now = kd->timestamp & KDBG_TIMESTAMP_MASK; + last_now = now; + + if (type == DECR_TRAP) { + int cpunum = CPU_NUMBER(kd); + double i_latency = handle_decrementer(kd, cpunum); + + if (log_fp) { + if (i_thresh_hold && (int)i_latency > i_thresh_hold) { + kd_start = last_decrementer_kd[cpunum]; + + log_decrementer(kd_start, kd, end_of_sample, i_latency); + } + last_decrementer_kd[cpunum] = kd; + } + } else { + double s_latency; + if (check_for_scheduler_latency(type, &thread, now, kd, &kd_start, &s_latency)) { + log_scheduler(kd_start, kd, end_of_sample, s_latency, thread); + } + } + } + if (log_fp) { + fflush(log_fp); + } + + gc_thread_entries(); + gc_reset_entries(); + gc_run_events(); + + return keep_going; +} + + + +void +enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info) +{ + char *p; + double timestamp; + double delta; + char pcstring[128]; + + int cpunum = CPU_NUMBER(kd); + + if (print_info && fp) { + timestamp = (double)(now - start_bias) / divisor; + delta = (double)idelta / divisor; + + if ((p = find_code(type))) { + if (type == INTERRUPT) { + int mode; + + if (kd->arg3) { + mode = USER_MODE; + } else { + mode = KERNEL_MODE; + } + + pc_to_string(&pcstring[0], kd->arg2, 58, mode); + + fprintf(fp, "%9.1f %8.1f\t\tINTERRUPT[%2lx] @ %-58.58s %-8x %d %s\n", + timestamp, delta, kd->arg1, &pcstring[0], thread, cpunum, command); + } else if (type == MACH_vmfault) { + fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8x %d %s\n", + timestamp, delta, p, thread, cpunum, command); + } else { + fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8lx %-8lx %-8lx %-8lx %-8x %d %s\n", + timestamp, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, + thread, cpunum, command); + } + } else { + fprintf(fp, "%9.1f %8.1f\t\t%-8x %-8lx %-8lx %-8lx %-8lx %-8x %d %s\n", + timestamp, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, + thread, cpunum, command); + } + } + if (type != BSC_thread_terminate && type != BSC_exit) { + insert_start_event(thread, type, now); + } +} + + +void +exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, int print_info) +{ + char *p; + uint64_t user_addr; + double timestamp; + double delta; + double elapsed_timestamp; + + elapsed_timestamp = (double)consume_start_event(thread, type, now) / divisor; + + if (print_info && fp) { + int cpunum = CPU_NUMBER(kd); + + timestamp = (double)(now - start_bias) / divisor; + delta = (double)idelta / divisor; + + fprintf(fp, "%9.1f %8.1f(%.1f) \t", timestamp, delta, elapsed_timestamp); + + if ((p = find_code(type))) { + if (type == INTERRUPT) { + fprintf(fp, "INTERRUPT %-8x %d %s\n", thread, cpunum, command); + } else if (type == MACH_vmfault && kd->arg4 <= DBG_PAGEIND_FAULT) { + user_addr = ((uint64_t)kd->arg1 << 32) | (uint32_t)kd->arg2; + + fprintf(fp, "%-28.28s %-10.10s %-16qx %-8x %d %s\n", + p, fault_name[kd->arg4], user_addr, + thread, cpunum, command); + } else { + fprintf(fp, "%-28.28s %-8lx %-8lx %-8x %d %s\n", + p, kd->arg1, kd->arg2, + thread, cpunum, command); + } + } else { + fprintf(fp, "%-8x %-8lx %-8lx %-8x %d %s\n", + type, kd->arg1, kd->arg2, + thread, cpunum, command); + } + } +} + + +void +print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd_note) +{ + char *p; + + if (!fp) { + return; + } - timestamp = ((double)now) / divisor; + int cpunum = CPU_NUMBER(kd); - if (kd == kd_start) { - start_bias = timestamp; - last_timestamp = timestamp; + double timestamp = (double)(now - start_bias) / divisor; + double delta = (double)idelta / divisor; + + if ((p = find_code(type))) { + if (kd == kd_note) { + fprintf(fp, "%9.1f %8.1f\t**\t", timestamp, delta); + } else { + fprintf(fp, "%9.1f %8.1f\t\t", timestamp, delta); } - delta = timestamp - last_timestamp; + fprintf(fp, "%-28.28s %-8lx %-8lx %-8lx %-8lx %-8x %d %s\n", + p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, thread, cpunum, command); + } else { + fprintf(fp, "%9.1f %8.1f\t\t%-8x %-8lx %-8lx %-8lx %-8lx %-8x %d %s\n", + timestamp, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, + thread, cpunum, command); + } +} - if ((map = find_thread_map(thread))) - strcpy(command, map->command); - else - command[0] = 0; +void +check_for_thread_update(uintptr_t thread, int debugid_base, kd_buf *kbufp, char **command) +{ + if (debugid_base == TRACE_DATA_NEWTHREAD) { + /* + * Save the create thread data + */ + create_tmp_map_entry(kbufp->arg1, thread); + } else if (debugid_base == TRACE_STRING_NEWTHREAD) { + /* + * process new map entry + */ + find_and_insert_tmp_map_entry(thread, (char *)&kbufp->arg1); + } else if (debugid_base == TRACE_STRING_EXEC) { + exec_thread_entry(thread, (char *)&kbufp->arg1); + } else { + if (debugid_base == BSC_exit || debugid_base == BSC_thread_terminate) { + record_thread_entry_for_gc(thread); + } + if (command) { + find_thread_name(thread, command); + } + } +} - switch (type) { + +void +log_info(uint64_t now, uint64_t idelta, uint64_t start_bias, kd_buf *kd, kd_buf *kd_note) +{ + lookup_t lkp; + int mode; + int reason; + char *p; + char *command; + char *command1; + char command_buf[32]; + char sched_info[64]; + char pcstring[128]; + const char *sched_reason; + double i_latency; + double timestamp; + double delta; + char joe[32]; + + int thread = kd->arg5; + int cpunum = CPU_NUMBER(kd); + int debugid = kd->debugid; + int type = kd->debugid & DBG_FUNC_MASK; + + (void)check_for_thread_update(thread, type, kd, &command); + + if ((type >> 24) == DBG_TRACE) { + if (((type >> 16) & 0xff) != DBG_TRACE_INFO) { + return; + } + } + timestamp = (double)(now - start_bias) / divisor; + delta = (double)idelta / divisor; + + switch (type) { case CQ_action: - fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-59.59s %-8x %d %s\n", - timestamp - start_bias, delta, pc_to_string(kd->arg1, 59, 1) , thread, cpunum, command); + pc_to_string(&pcstring[0], kd->arg1, 62, KERNEL_MODE); - last_timestamp = timestamp; - break; + fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-62.62s %-8x %d %s\n", + timestamp, delta, &pcstring[0], thread, cpunum, command); + break; - case DECR_TRAP: - if ((int)(kd->arg1) >= 0) - i_latency = 0; - else - i_latency = (((double)(-1 - kd->arg1)) / divisor); + case TES_action: + pc_to_string(&pcstring[0], kd->arg1, 61, KERNEL_MODE); + + fprintf(log_fp, "%9.1f %8.1f\t\tTES_action @ %-61.61s %-8x %d %s\n", + timestamp, delta, &pcstring[0], thread, cpunum, command); + break; + + case IES_action: + pc_to_string(&pcstring[0], kd->arg1, 61, KERNEL_MODE); + + fprintf(log_fp, "%9.1f %8.1f\t\tIES_action @ %-61.61s %-8x %d %s\n", + timestamp, delta, &pcstring[0], thread, cpunum, command); + break; + + case IES_filter: + pc_to_string(&pcstring[0], kd->arg1, 61, KERNEL_MODE); - if (i_thresh_hold && (int)i_latency > i_thresh_hold) - p = "*"; - else - p = " "; + fprintf(log_fp, "%9.1f %8.1f\t\tIES_filter @ %-61.61s %-8x %d %s\n", + timestamp, delta, &pcstring[0], thread, cpunum, command); + break; - mode = 1; + case DECR_TRAP: + if ((int)kd->arg1 >= 0) { + i_latency = 0; + } else { + i_latency = (((double)(-1 - kd->arg1)) / divisor); + } - if ((ti = find_thread(kd->arg5, 0, 0))) { - if (ti->type == -1 && strcmp(command, "kernel_task")) - mode = 0; - } - fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-59.59s %-8x %d %s\n", - timestamp - start_bias, delta, i_latency, p, pc_to_string(kd->arg2, 59, mode) , thread, cpunum, command); + if (i_thresh_hold && (int)i_latency > i_thresh_hold) { + p = "*"; + } else { + p = " "; + } - last_timestamp = timestamp; - break; + if (kd->arg3) { + mode = USER_MODE; + } else { + mode = KERNEL_MODE; + } - case DECR_SET: - fprintf(log_fp, "%9.1f %8.1f[%.1f] \t%-28.28s %-8x %d %s\n", - timestamp - start_bias, delta, (double)kd->arg1/divisor, - "DECR_SET", thread, cpunum, command); + pc_to_string(&pcstring[0], kd->arg2, 62, mode); - last_timestamp = timestamp; - break; + fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-62.62s %-8x %d %s\n", + timestamp, delta, i_latency, p, &pcstring[0], thread, cpunum, command); + break; + + case DECR_SET: + fprintf(log_fp, "%9.1f %8.1f[%.1f] \t%-28.28s %-8x %d %s\n", + timestamp, delta, (double)kd->arg1/divisor, "DECR_SET", thread, cpunum, command); + break; case MACH_sched: case MACH_stkhandoff: - if ((map = find_thread_map(kd->arg2))) - strcpy(command1, map->command); - else - sprintf(command1, "%-8x", kd->arg2); - if ((ti = find_thread(kd->arg2, 0, 0))) { - if (ti->type == -1 && strcmp(command1, "kernel_task")) - p = "U"; - else - p = "K"; - } else - p = "*"; - memset(sched_info, ' ', sizeof(sched_info)); - - sprintf(sched_info, "%14.14s", command); - clen = strlen(sched_info); - sched_info[clen] = ' '; + find_thread_name(kd->arg2, &command1); + + if (command1 == EMPTYSTRING) { + command1 = command_buf; + sprintf(command1, "%-8lx", kd->arg2); + } + if (thread_in_user_mode(kd->arg2, command1)) { + p = "U"; + } else { + p = "K"; + } - sprintf(&sched_info[14], " @ pri %3d --> %14.14s", kd->arg3, command1); - clen = strlen(sched_info); - sched_info[clen] = ' '; + reason = kd->arg1; - sprintf(&sched_info[45], " @ pri %3d%s", kd->arg4, p); + if (reason > MAX_REASON) { + sched_reason = "?"; + } else { + sched_reason = sched_reasons[reason]; + } - fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s %s %-8x %d\n", - timestamp - start_bias, delta, "MACH_SCHED", sched_info, thread, cpunum); + if (sched_reason[0] == '?') { + sprintf(joe, "%x", reason); + sched_reason = joe; + } + sprintf(sched_info, "%14.14s @ pri %3lu --> %14.14s @ pri %3lu%s", command, kd->arg3, command1, kd->arg4, p); - last_timestamp = timestamp; - break; + fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s[%s] %s %-8x %d\n", + timestamp, delta, "MACH_SCHED", sched_reason, sched_info, thread, cpunum); + break; case VFS_LOOKUP: - if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) { - if (cur_max >= MAX_THREADS) - continue; - ti = &th_state[cur_max++]; - - ti->thread = thread; - ti->type = -1; - ti->pathptr = (long *)NULL; - ti->child_thread = 0; - } - - while ( (kd <= kd_stop) && (kd->debugid & DBG_FUNC_MASK) == VFS_LOOKUP) - { - if (ti->pathptr == NULL) { - ti->arg1 = kd->arg1; - sargptr = ti->pathname; + if ((lkp = handle_lookup_event(thread, debugid, kd))) { + /* + * print the tail end of the pathname + */ + p = (char *)lkp->lk_pathname; + int clen = strlen(p); + + if (clen > 45) { + clen -= 45; + } else { + clen = 0; + } - *sargptr++ = kd->arg2; - *sargptr++ = kd->arg3; - *sargptr++ = kd->arg4; - /* - * NULL terminate the 'string' - */ - *sargptr = 0; + fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-45s %-8lx %-8x %d %s\n", + timestamp, delta, "VFS_LOOKUP", + &p[clen], lkp->lk_dvp, thread, cpunum, command); - ti->pathptr = sargptr; + delete_lookup_event(thread, lkp); + } + break; + default: + if (debugid & DBG_FUNC_START) { + enter_syscall(log_fp, kd, thread, type, command, now, idelta, start_bias, 1); + } else if (debugid & DBG_FUNC_END) { + exit_syscall(log_fp, kd, thread, type, command, now, idelta, start_bias, 1); } else { - sargptr = ti->pathptr; + print_entry(log_fp, kd, thread, type, command, now, idelta, start_bias, kd_note); + } + break; + } +} + - /* - We don't want to overrun our pathname buffer if the - kernel sends us more VFS_LOOKUP entries than we can - handle. - */ - if (sargptr >= &ti->pathname[NUMPARMS]) - { - kd++; +void +log_range(kd_buf *kd_buffer, kd_buf *kd_start, kd_buf *kd_stop, kd_buf *kd_note, char *buf1) +{ + uint64_t last_timestamp = 0; + uint64_t delta = 0; + uint64_t start_bias = 0; + uint64_t now; + kd_buf *kd; + int clen; + char buf2[128]; + + clen = strlen(buf1); + memset(buf2, '-', clen); + buf2[clen] = 0; + fprintf(log_fp, "\n\n%s\n", buf2); + fprintf(log_fp, "%s\n\n", buf1); + + fprintf(log_fp, "RelTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu command\n\n"); + + reset_thread_names(); + + last_timestamp = kd_start->timestamp & KDBG_TIMESTAMP_MASK; + start_bias = last_timestamp; + + for (kd = kd_buffer; kd <= kd_stop; kd++) { + now = kd->timestamp & KDBG_TIMESTAMP_MASK; + + if (kd >= kd_start) { + delta = now - last_timestamp; + + log_info(now, delta, start_bias, kd, kd_note); + + last_timestamp = now; + } else { + int debugid = kd->debugid; + int thread = kd->arg5; + int type = kd->debugid & DBG_FUNC_MASK; + + if ((type >> 24) == DBG_TRACE) { + if (((type >> 16) & 0xff) != DBG_TRACE_INFO) { + continue; + } + } + if (type == BSC_thread_terminate || type == BSC_exit) { continue; - } - - /* - We need to detect consecutive vfslookup entries. - So, if we get here and find a START entry, - fake the pathptr so we can bypass all further - vfslookup entries. - */ - - if (kd->debugid & DBG_FUNC_START) - { - ti->pathptr = &ti->pathname[NUMPARMS]; - } - else - { - *sargptr++ = kd->arg1; - *sargptr++ = kd->arg2; - *sargptr++ = kd->arg3; - *sargptr++ = kd->arg4; - /* - * NULL terminate the 'string' - */ - *sargptr = 0; + } - ti->pathptr = sargptr; - } + if (debugid & DBG_FUNC_START) { + insert_start_event(thread, type, now); + } else if (debugid & DBG_FUNC_END) { + (void)consume_start_event(thread, type, now); } - kd++; - } - p = (char *)ti->pathname; - - kd--; - /* print the tail end of the pathname */ - len = strlen(p); - if (len > 42) - len -= 42; - else - len = 0; - - fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-42s %-8x %-8x %d %s\n", - timestamp - start_bias, delta, "VFS_LOOKUP", - &p[len], ti->arg1, thread, cpunum, command); - - last_timestamp = timestamp; - break; + } + } + gc_start_events(); + gc_lookup_events(); +} - default: - if (debugid & DBG_FUNC_START) - enter_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1); - else if (debugid & DBG_FUNC_END) - exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1); - else - print_entry(log_fp, kd, thread, type, command, timestamp, delta, start_bias); - last_timestamp = timestamp; - break; +kd_buf * +log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency) +{ + kd_buf *kd_start, *kd_stop; + int kd_count; /* Limit the boundary of kd_start */ + uint64_t now; + double sample_timestamp; + char buf1[128]; + + int thread = kd_beg->arg5; + int cpunum = CPU_NUMBER(kd_end); + + for (kd_count = 0, kd_start = kd_beg - 1; (kd_start >= (kd_buf *)my_buffer); kd_start--, kd_count++) { + if (kd_count == MAX_LOG_COUNT) { + break; + } + + if (CPU_NUMBER(kd_start) != cpunum) { + continue; + } + + if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP) { + break; + } + + if (kd_start->arg5 != thread) { + break; + } + } + if (kd_start < (kd_buf *)my_buffer) { + kd_start = (kd_buf *)my_buffer; + } + + thread = kd_end->arg5; + + for (kd_stop = kd_end + 1; kd_stop < end_of_sample; kd_stop++) { + if (CPU_NUMBER(kd_stop) != cpunum) { + continue; + } + + if ((kd_stop->debugid & DBG_FUNC_MASK) == INTERRUPT) { + break; + } + + if (kd_stop->arg5 != thread) { + break; + } + } + if (kd_stop >= end_of_sample) { + kd_stop = end_of_sample - 1; + } + + if (RAW_flag) { + time_t TOD_secs; + uint64_t TOD_usecs; + + now = kd_start->timestamp & KDBG_TIMESTAMP_MASK; + sample_timestamp = (double)(now - first_now) / divisor; + + TOD_usecs = (uint64_t)sample_timestamp; + TOD_secs = sample_TOD_secs + ((sample_TOD_usecs + TOD_usecs) / 1000000); + + sprintf(buf1, "%-19.19s interrupt latency = %.1fus [timestamp %.1f]", ctime(&TOD_secs), i_latency, sample_timestamp); + } else { + sprintf(buf1, "%-19.19s interrupt latency = %.1fus [sample %d]", &(ctime(&curr_time)[0]), i_latency, sample_generation); + } + + log_range((kd_buf *)my_buffer, kd_start, kd_stop, 0, buf1); + + return kd_stop; +} + + +void +log_scheduler(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double s_latency, uintptr_t thread) +{ + kd_buf *kd_start, *kd_stop; + uint64_t now; + double sample_timestamp; + char buf1[128]; + + int cpunum = CPU_NUMBER(kd_end); + + for (kd_start = kd_beg; (kd_start >= (kd_buf *)my_buffer); kd_start--) { + if (CPU_NUMBER(kd_start) == cpunum) { + break; + } + } + if (kd_start < (kd_buf *)my_buffer) { + kd_start = (kd_buf *)my_buffer; + } + + for (kd_stop = kd_end + 1; kd_stop < end_of_sample; kd_stop++) { + if (kd_stop->arg5 == thread) { + break; + } + } + if (kd_stop >= end_of_sample) { + kd_stop = end_of_sample - 1; + } + + if (RAW_flag) { + time_t TOD_secs; + uint64_t TOD_usecs; + + now = kd_start->timestamp & KDBG_TIMESTAMP_MASK; + sample_timestamp = (double)(now - first_now) / divisor; + + TOD_usecs = (uint64_t)sample_timestamp; + TOD_secs = sample_TOD_secs + ((sample_TOD_usecs + TOD_usecs) / 1000000); + + sprintf(buf1, "%-19.19s priority = %d, scheduling latency = %.1fus [timestamp %.1f]", ctime(&TOD_secs), watch_priority, s_latency, sample_timestamp); + } else { + sprintf(buf1, "%-19.19s priority = %d, scheduling latency = %.1fus [sample %d]", &(ctime(&curr_time)[0]), watch_priority, s_latency, sample_generation); + } + + log_range((kd_buf *)my_buffer, kd_start, kd_stop, kd_beg, buf1); +} + + + +int +check_for_scheduler_latency(int type, uintptr_t *thread, uint64_t now, kd_buf *kd, kd_buf **kd_start, double *latency) +{ + int found_latency = 0; + + if (type == MACH_makerunnable) { + if (watch_priority == kd->arg2) { + insert_run_event(kd->arg1, kd, now); + } + } else if (type == MACH_sched || type == MACH_stkhandoff) { + threadrun_t trp; + + if (type == MACH_sched || type == MACH_stkhandoff) { + *thread = kd->arg2; + } + + if ((trp = find_run_event(*thread))) { + double d_s_latency = (((double)(now - trp->tr_timestamp)) / divisor); + int s_latency = (int)d_s_latency; + + if (s_latency) { + if (s_latency < 100) { + s_usec_10_bins[s_latency/10]++; + } + if (s_latency < 1000) { + s_usec_100_bins[s_latency/100]++; + } else if (s_latency < 10000) { + s_msec_1_bins[s_latency/1000]++; + } else if (s_latency < 50000) { + s_msec_10_bins[s_latency/10000]++; + } else { + s_too_slow++; + } + + if (s_latency > s_max_latency) { + s_max_latency = s_latency; + } + if (s_latency < s_min_latency || s_total_samples == 0) { + s_min_latency = s_latency; + } + s_total_latency += s_latency; + s_total_samples++; + + if (s_thresh_hold && s_latency > s_thresh_hold) { + s_exceeded_threshold++; + + if (log_fp) { + *kd_start = trp->tr_entry; + *latency = d_s_latency; + found_latency = 1; + } + } + } + delete_run_event(*thread); } } - return(kd_stop); + return found_latency; } -double handle_decrementer(kd_buf *kd) +double +handle_decrementer(kd_buf *kd, int cpunum) { - double latency; + struct i_latencies *il; + double latency; long elapsed_usecs; - if ((long)(kd->arg1) >= 0) - latency = 1; - else - latency = (((double)(-1 - kd->arg1)) / divisor); + if (i_latency_per_cpu == FALSE) { + cpunum = 0; + } + + il = &i_lat[cpunum]; + + if ((long)(kd->arg1) >= 0) { + latency = 1; + } else { + latency = (((double)(-1 - kd->arg1)) / divisor); + } elapsed_usecs = (long)latency; - if (elapsed_usecs < 100) - i_usec_10_bins[elapsed_usecs/10]++; - if (elapsed_usecs < 1000) - i_usec_100_bins[elapsed_usecs/100]++; - else if (elapsed_usecs < 10000) - i_msec_1_bins[elapsed_usecs/1000]++; - else if (elapsed_usecs < 50000) - i_msec_10_bins[elapsed_usecs/10000]++; - else - i_too_slow++; - - if(use_high_res_bins && elapsed_usecs < N_HIGH_RES_BINS) { - if(elapsed_usecs > i_highest_latency) - i_highest_latency = elapsed_usecs; - i_high_res_bins[elapsed_usecs]++; - } - - if (i_thresh_hold && elapsed_usecs > i_thresh_hold) - i_exceeded_threshold++; - if (elapsed_usecs > i_max_latency) - i_max_latency = elapsed_usecs; - if (elapsed_usecs < i_min_latency || i_total_samples == 0) - i_min_latency = elapsed_usecs; - i_total_latency += elapsed_usecs; - i_total_samples++; - - return (latency); + if (elapsed_usecs < 100) { + il->i_usec_10_bins[elapsed_usecs/10]++; + } + + if (elapsed_usecs < 1000) { + il->i_usec_100_bins[elapsed_usecs/100]++; + } else if (elapsed_usecs < 10000) { + il->i_msec_1_bins[elapsed_usecs/1000]++; + } else if (elapsed_usecs < 50000) { + il->i_msec_10_bins[elapsed_usecs/10000]++; + } else { + il->i_too_slow++; + } + + if (use_high_res_bins && elapsed_usecs < N_HIGH_RES_BINS) { + i_high_res_bins[elapsed_usecs]++; + } + if (i_thresh_hold && elapsed_usecs > i_thresh_hold) { + il->i_exceeded_threshold++; + } + if (elapsed_usecs > il->i_max_latency) { + il->i_max_latency = elapsed_usecs; + } + if (elapsed_usecs < il->i_min_latency || il->i_total_samples == 0) { + il->i_min_latency = elapsed_usecs; + } + il->i_total_latency += elapsed_usecs; + il->i_total_samples++; + + return latency; } -void init_code_file() + +char * +find_code(int type) +{ + int i; + for (i = 0; i < num_of_codes; i++) { + if (codes_tab[i].type == type) { + return codes_tab[i].name; + } + } + return NULL; +} + + +void +init_code_file(void) { - FILE *fp; - int i, n, code; - char name[128]; + FILE *fp; + int i; - if ((fp = fopen(code_file, "r")) == (FILE *)0) { - if (log_fp) - fprintf(log_fp, "open of %s failed\n", code_file); - return; + if ((fp = fopen(code_file, "r")) == NULL) { + if (log_fp) { + fprintf(log_fp, "open of %s failed\n", code_file); + } + return; } for (i = 0; i < MAX_ENTRIES; i++) { - n = fscanf(fp, "%x%127s\n", &code, name); + int code; + char name[128]; + int n = fscanf(fp, "%x%127s\n", &code, name); if (n == 1 && i == 0) { /* @@ -2153,8 +2542,9 @@ void init_code_file() */ continue; } - if (n != 2) - break; + if (n != 2) { + break; + } strncpy(codes_tab[i].name, name, 32); codes_tab[i].type = code; @@ -2166,203 +2556,228 @@ void init_code_file() void -do_kernel_nm() +do_kernel_nm(void) { - int i, len; - FILE *fp = (FILE *)0; - char tmp_nm_file[128]; - char tmpstr[1024]; - char inchr; - - bzero(tmp_nm_file, 128); - bzero(tmpstr, 1024); - - /* Build the temporary nm file path */ - strcpy(tmp_nm_file,"/tmp/knm.out.XXXXXX"); - if (!mktemp(tmp_nm_file)) { - fprintf(stderr, "Error in mktemp call\n"); - return; - } - - /* Build the nm command and create a tmp file with the output*/ - sprintf (tmpstr, "/usr/bin/nm -f -n -s __TEXT __text %s > %s", - kernelpath, tmp_nm_file); - system(tmpstr); + int i, len; + FILE *fp = NULL; + char tmp_nm_file[128]; + char tmpstr[1024]; + char inchr; + + bzero(tmp_nm_file, 128); + bzero(tmpstr, 1024); + + /* + * Build the temporary nm file path + */ + strcpy(tmp_nm_file,"/tmp/knm.out.XXXXXX"); + + if (!mktemp(tmp_nm_file)) { + fprintf(stderr, "Error in mktemp call\n"); + return; + } + + /* + * Build the nm command and create a tmp file with the output + */ + sprintf (tmpstr, "/usr/bin/nm -f -n -s __TEXT __text %s > %s", + kernelpath, tmp_nm_file); + system(tmpstr); - /* Parse the output from the nm command */ - if ((fp=fopen(tmp_nm_file, "r")) == (FILE *)0) - { - /* Hmmm, let's not treat this as fatal */ - fprintf(stderr, "Failed to open nm symbol file [%s]\n", tmp_nm_file); - return; - } - - /* Count the number of symbols in the nm symbol table */ - kern_sym_count=0; - while ( (inchr = getc(fp)) != -1) - { - if (inchr == '\n') - kern_sym_count++; - } - - rewind(fp); - - /* Malloc the space for symbol table */ - if (kern_sym_count > 0) - { - kern_sym_tbl = (kern_sym_t *)malloc(kern_sym_count * sizeof (kern_sym_t)); - if (!kern_sym_tbl) - { - /* Hmmm, lets not treat this as fatal */ - fprintf(stderr, "Can't allocate memory for kernel symbol table\n"); - } - else - bzero(kern_sym_tbl, (kern_sym_count * sizeof(kern_sym_t))); - } - else - { - /* Hmmm, lets not treat this as fatal */ - fprintf(stderr, "No kernel symbol table \n"); - } - - for (i=0; i 0) { + kern_sym_tbl = malloc(kern_sym_count * sizeof(kern_sym_t)); + + if (!kern_sym_tbl) { + /* + * Hmmm, lets not treat this as fatal + */ + fprintf(stderr, "Can't allocate memory for kernel symbol table\n"); + } else { + bzero(kern_sym_tbl, kern_sym_count * sizeof(kern_sym_t)); + } + } else { + /* + * Hmmm, lets not treat this as fatal + */ + fprintf(stderr, "No kernel symbol table \n"); + } + for (i = 0; i < kern_sym_count; i++) { + bzero(tmpstr, 1024); + + if (fscanf(fp, "%p %c %s", &kern_sym_tbl[i].k_sym_addr, &inchr, tmpstr) != 3) { + break; + } else { + len = strlen(tmpstr); + kern_sym_tbl[i].k_sym_name = malloc(len + 1); + + if (kern_sym_tbl[i].k_sym_name == NULL) { + fprintf(stderr, "Can't allocate memory for symbol name [%s]\n", tmpstr); + kern_sym_tbl[i].k_sym_name = NULL; + len = 0; + } else { + strcpy(kern_sym_tbl[i].k_sym_name, tmpstr); + } + + kern_sym_tbl[i].k_sym_len = len; + } + } + if (i != kern_sym_count) { + /* + * Hmmm, didn't build up entire table from nm + * scrap the entire thing + */ + free(kern_sym_tbl); + kern_sym_tbl = NULL; + kern_sym_count = 0; + } + fclose(fp); + /* + * Remove the temporary nm file + */ + unlink(tmp_nm_file); #if 0 - /* Dump the kernel symbol table */ - for (i=0; i < kern_sym_count; i++) - { - if (kern_sym_tbl[i].k_sym_name) - printf ("[%d] 0x%x %s\n", i, - kern_sym_tbl[i].k_sym_addr, kern_sym_tbl[i].k_sym_name); - else - printf ("[%d] 0x%x %s\n", i, - kern_sym_tbl[i].k_sym_addr, "No symbol name"); - } + /* + * Dump the kernel symbol table + */ + for (i = 0; i < kern_sym_count; i++) { + if (kern_sym_tbl[i].k_sym_name) { + printf ("[%d] %-16p %s\n", i, + kern_sym_tbl[i].k_sym_addr, kern_sym_tbl[i].k_sym_name); + } else { + printf ("[%d] %-16p %s\n", i, + kern_sym_tbl[i].k_sym_addr, "No symbol name"); + } + } #endif } -char * -pc_to_string(unsigned int pc, int max_len, int mode) +void +pc_to_string(char *pcstring, uintptr_t pc, int max_len, int mode) { - int ret; - int len; - - int binary_search(); - - if (mode == 0) - { - sprintf(pcstring, "0x%-8x [usermode addr]", pc); - return(pcstring); - } - - ret=0; - ret = binary_search(kern_sym_tbl, 0, kern_sym_count-1, pc); - - if (ret == -1) - { - sprintf(pcstring, "0x%x", pc); - return(pcstring); - } - else if (kern_sym_tbl[ret].k_sym_name == (char *)0) - { - sprintf(pcstring, "0x%x", pc); - return(pcstring); - } - else - { - if ((len = kern_sym_tbl[ret].k_sym_len) > (max_len - 8)) - len = max_len - 8; - - memcpy(pcstring, kern_sym_tbl[ret].k_sym_name, len); - sprintf(&pcstring[len], "+0x%-5lx", pc - kern_sym_tbl[ret].k_sym_addr); - - return (pcstring); - } + int ret; + int len; + + if (mode == USER_MODE) { + sprintf(pcstring, "%-16lx [usermode addr]", pc); + return; + } + ret = binary_search(kern_sym_tbl, 0, kern_sym_count-1, pc); + + if (ret == -1 || kern_sym_tbl[ret].k_sym_name == NULL) { + sprintf(pcstring, "%-16lx", pc); + return; + } + if ((len = kern_sym_tbl[ret].k_sym_len) > (max_len - 8)) { + len = max_len - 8; + } + + memcpy(pcstring, kern_sym_tbl[ret].k_sym_name, len); + + sprintf(&pcstring[len], "+0x%-5lx", pc - (uintptr_t)kern_sym_tbl[ret].k_sym_addr); } -/* Return -1 if not found, else return index */ -int binary_search(list, low, high, addr) -kern_sym_t *list; -int low, high; -unsigned int addr; +/* + * Return -1 if not found, else return index + */ +int +binary_search(kern_sym_t *list, int low, int high, uintptr_t addr) { - int mid; - - mid = (low + high) / 2; + int mid; - if (low > high) - return (-1); /* failed */ - else if (low + 1 == high) - { - if (list[low].k_sym_addr <= addr && - addr < list[high].k_sym_addr) - { - /* We have a range match */ - return(low); - } - else if (list[high].k_sym_addr <= addr) - { - return(high); - } - else - return(-1); /* Failed */ - } - else if (addr < list[mid].k_sym_addr) - { - return(binary_search (list, low, mid, addr)); - } - else - { - return(binary_search (list, mid, high, addr)); - } + if (kern_sym_count == 0) { + return -1; + } + + if (low > high) { + return -1; /* failed */ + } + + if (low + 1 == high) { + if ((uintptr_t)list[low].k_sym_addr <= addr && addr < (uintptr_t)list[high].k_sym_addr) { + /* + * We have a range match + */ + return low; + } + if ((uintptr_t)list[high].k_sym_addr <= addr) { + return high; + } + /* + * Failed + */ + return -1; + } + mid = (low + high) / 2; + + if (addr < (uintptr_t)list[mid].k_sym_addr) { + return binary_search(list, low, mid, addr); + } + + return binary_search(list, mid, high, addr); } + void -open_logfile(char *path) +open_logfile(const char *path) { - log_fp = fopen(path, "a"); - - if (!log_fp) - { - /* failed to open path */ - fprintf(stderr, "latency: failed to open logfile [%s]\n", path); - exit_usage(); - } + log_fp = fopen(path, "a"); + + if (!log_fp) { + /* + * failed to open path + */ + fprintf(stderr, "latency: failed to open logfile [%s]\n", path); + exit_usage(); + } +} + + +void +open_rawfile(const char *path) +{ + RAW_fd = open(path, O_RDONLY); + + if (RAW_fd == -1) { + /* + * failed to open path + */ + fprintf(stderr, "latency: failed to open RAWfile [%s]\n", path); + exit_usage(); + } +} + + +void +getdivisor(void) +{ + mach_timebase_info_data_t info; + + (void)mach_timebase_info(&info); + + divisor = ((double)info.denom / (double)info.numer) * 1000; } diff --git a/login.tproj/Makefile b/login.tproj/Makefile index 958b2c5..91a1430 100644 --- a/login.tproj/Makefile +++ b/login.tproj/Makefile @@ -8,7 +8,7 @@ MANPAGES = login.1 Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_CC_Flags += -D__FBSDID=__RCSID @@ -27,6 +27,5 @@ Install_Program_Mode = 04555 after_install: $(INSTALL_DIRECTORY) "$(DSTROOT)"/private/etc/pam.d - $(INSTALL_FILE) login.pam "$(DSTROOT)"/private/etc/pam.d/login - sed -e '/pam_launchd.so/d' < login.pam > "$(OBJROOT)"/login.term - $(INSTALL_FILE) "$(OBJROOT)"/login.term "$(DSTROOT)"/private/etc/pam.d/login.term + $(INSTALL_FILE) pam.d/login "$(DSTROOT)"/private/etc/pam.d/login + $(INSTALL_FILE) pam.d/login.term "$(DSTROOT)"/private/etc/pam.d/login.term diff --git a/login.tproj/login.c b/login.tproj/login.c index 2b0d828..259907f 100644 --- a/login.tproj/login.c +++ b/login.tproj/login.c @@ -105,6 +105,8 @@ __FBSDID("$FreeBSD: src/usr.bin/login/login.c,v 1.106 2007/07/04 00:00:40 scf Ex #ifdef USE_BSM_AUDIT #include +#include +#include #include #endif @@ -127,7 +129,7 @@ __FBSDID("$FreeBSD: src/usr.bin/login/login.c,v 1.106 2007/07/04 00:00:40 scf Ex #include "pathnames.h" #ifdef USE_PAM -static int auth_pam(void); +static int auth_pam(int skip_auth); #endif /* USE_PAM */ static void bail(int, int); #ifdef USE_PAM @@ -228,7 +230,7 @@ static struct lastlogx lastlog; #endif /* USE_PAM */ #ifdef USE_BSM_AUDIT -au_tid_t tid; +extern au_tid_addr_t tid; #endif /* USE_BSM_AUDIT */ #endif /* __APPLE__ */ @@ -386,16 +388,19 @@ main(int argc, char *argv[]) #ifdef __APPLE__ #ifdef USE_BSM_AUDIT /* Set the terminal id */ - audit_set_terminal_id(&tid); + au_tid_t old_tid; + audit_set_terminal_id(&old_tid); + tid.at_type = AU_IPv4; + tid.at_addr[0] = old_tid.machine; if (fstat(STDIN_FILENO, &st) < 0) { fprintf(stderr, "login: Unable to stat terminal\n"); au_login_fail("Unable to stat terminal", 1); exit(-1); } if (S_ISCHR(st.st_mode)) { - tid.port = st.st_rdev; + tid.at_port = st.st_rdev; } else { - tid.port = 0; + tid.at_port = 0; } #endif /* USE_BSM_AUDIT */ #endif /* __APPLE__ */ @@ -483,8 +488,11 @@ main(int argc, char *argv[]) */ if (pwd != NULL && fflag && (uid == (uid_t)0 || uid == (uid_t)pwd->pw_uid)) { - /* already authenticated */ +#ifdef USE_PAM + rval = auth_pam(fflag); +#else rval = 0; +#endif /* USE_PAM */ #ifdef USE_BSM_AUDIT auditsuccess = 0; /* opened a terminal window only */ #endif @@ -500,7 +508,7 @@ main(int argc, char *argv[]) fflag = 0; (void)setpriority(PRIO_PROCESS, 0, -4); #ifdef USE_PAM - rval = auth_pam(); + rval = auth_pam(fflag); #else { char* salt = pwd->pw_passwd; @@ -585,7 +593,7 @@ main(int argc, char *argv[]) #ifdef USE_BSM_AUDIT /* Audit successful login. */ if (auditsuccess) - au_login_success(); + au_login_success(fflag); #endif #ifdef LOGIN_CAP @@ -778,12 +786,14 @@ main(int argc, char *argv[]) } #endif /* !__APPLE__ */ #ifdef USE_PAM - pam_err = pam_setcred(pamh, pam_silent|PAM_ESTABLISH_CRED); - if (pam_err != PAM_SUCCESS) { - pam_syslog("pam_setcred()"); - bail(NO_SLEEP_EXIT, 1); + if (!fflag) { + pam_err = pam_setcred(pamh, pam_silent|PAM_ESTABLISH_CRED); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_setcred()"); + bail(NO_SLEEP_EXIT, 1); + } + pam_cred_established = 1; } - pam_cred_established = 1; pam_err = pam_open_session(pamh, pam_silent); if (pam_err != PAM_SUCCESS) { @@ -872,7 +882,6 @@ main(int argc, char *argv[]) (void)setgid(pwd->pw_gid); if (initgroups(username, pwd->pw_gid) == -1) syslog(LOG_ERR, "login: initgroups() failed"); - pwd = getpwnam(username); // 7258548 (void) setuid(rootlogin ? 0 : pwd->pw_uid); #else /* !__APPLE__ */ if (setusercontext(lc, pwd, pwd->pw_uid, @@ -907,7 +916,7 @@ main(int argc, char *argv[]) if (pwd->pw_shell) { (void)setenv("SHELL", pwd->pw_shell, 1); } else { - syslog(LOG_ERR, "pwd->pw_shell not set - exiting", username); + syslog(LOG_ERR, "pwd->pw_shell not set - exiting"); bail(NO_SLEEP_EXIT, 1); } if (pwd->pw_dir) { @@ -964,7 +973,7 @@ main(int argc, char *argv[]) break; } } while (0); -#endif __APPLE__ +#endif /* __APPLE__ */ if (!quietlog) { #ifdef LOGIN_CAP @@ -1058,54 +1067,59 @@ main(int argc, char *argv[]) * fall back to a different authentication mechanism. */ static int -auth_pam(void) +auth_pam(int skip_auth) { const char *tmpl_user; const void *item; int rval; - pam_err = pam_authenticate(pamh, pam_silent); - switch (pam_err) { + rval = 0; + + if (skip_auth == 0) + { + pam_err = pam_authenticate(pamh, pam_silent); + switch (pam_err) { - case PAM_SUCCESS: - /* - * With PAM we support the concept of a "template" - * user. The user enters a login name which is - * authenticated by PAM, usually via a remote service - * such as RADIUS or TACACS+. If authentication - * succeeds, a different but related "template" name - * is used for setting the credentials, shell, and - * home directory. The name the user enters need only - * exist on the remote authentication server, but the - * template name must be present in the local password - * database. - * - * This is supported by two various mechanisms in the - * individual modules. However, from the application's - * point of view, the template user is always passed - * back as a changed value of the PAM_USER item. - */ - pam_err = pam_get_item(pamh, PAM_USER, &item); - if (pam_err == PAM_SUCCESS) { - tmpl_user = (const char *)item; - if (strcmp(username, tmpl_user) != 0) - pwd = getpwnam(tmpl_user); - } else { - pam_syslog("pam_get_item(PAM_USER)"); + case PAM_SUCCESS: + /* + * With PAM we support the concept of a "template" + * user. The user enters a login name which is + * authenticated by PAM, usually via a remote service + * such as RADIUS or TACACS+. If authentication + * succeeds, a different but related "template" name + * is used for setting the credentials, shell, and + * home directory. The name the user enters need only + * exist on the remote authentication server, but the + * template name must be present in the local password + * database. + * + * This is supported by two various mechanisms in the + * individual modules. However, from the application's + * point of view, the template user is always passed + * back as a changed value of the PAM_USER item. + */ + pam_err = pam_get_item(pamh, PAM_USER, &item); + if (pam_err == PAM_SUCCESS) { + tmpl_user = (const char *)item; + if (strcmp(username, tmpl_user) != 0) + pwd = getpwnam(tmpl_user); + } else { + pam_syslog("pam_get_item(PAM_USER)"); + } + rval = 0; + break; + + case PAM_AUTH_ERR: + case PAM_USER_UNKNOWN: + case PAM_MAXTRIES: + rval = 1; + break; + + default: + pam_syslog("pam_authenticate()"); + rval = -1; + break; } - rval = 0; - break; - - case PAM_AUTH_ERR: - case PAM_USER_UNKNOWN: - case PAM_MAXTRIES: - rval = 1; - break; - - default: - pam_syslog("pam_authenticate()"); - rval = -1; - break; } if (rval == 0) { @@ -1114,11 +1128,18 @@ auth_pam(void) case PAM_SUCCESS: break; case PAM_NEW_AUTHTOK_REQD: - pam_err = pam_chauthtok(pamh, - pam_silent|PAM_CHANGE_EXPIRED_AUTHTOK); - if (pam_err != PAM_SUCCESS) { - pam_syslog("pam_chauthtok()"); - rval = 1; + if (skip_auth == 0) + { + pam_err = pam_chauthtok(pamh, + pam_silent|PAM_CHANGE_EXPIRED_AUTHTOK); + if (pam_err != PAM_SUCCESS) { + pam_syslog("pam_chauthtok()"); + rval = 1; + } + } + else + { + pam_syslog("pam_acct_mgmt()"); } break; default: diff --git a/login.tproj/login.h b/login.tproj/login.h index 1d0e72e..fd6d172 100644 --- a/login.tproj/login.h +++ b/login.tproj/login.h @@ -28,7 +28,7 @@ void login_fbtab(char *, uid_t, gid_t); #ifdef USE_BSM_AUDIT -void au_login_success(void); +void au_login_success(int fflag); void au_login_fail(const char *errmsg, int na); void audit_logout(void); #endif diff --git a/login.tproj/login.pam b/login.tproj/login.pam deleted file mode 100644 index 494813a..0000000 --- a/login.tproj/login.pam +++ /dev/null @@ -1,11 +0,0 @@ -# login: auth account password session -auth optional pam_krb5.so -auth optional pam_mount.so -auth sufficient pam_serialnumber.so serverinstall legacy -auth required pam_opendirectory.so -account required pam_nologin.so -account required pam_opendirectory.so -password required pam_deny.so -session required pam_launchd.so -session required pam_uwtmp.so -session optional pam_mount.so diff --git a/login.tproj/login_audit.c b/login.tproj/login_audit.c index 4f6bb9d..6fc37ee 100644 --- a/login.tproj/login_audit.c +++ b/login.tproj/login_audit.c @@ -38,11 +38,13 @@ __FBSDID("$FreeBSD: src/usr.bin/login/login_audit.c,v 1.2 2007/05/07 11:01:36 dw #include #include +#include #include #include #include #include +#include #include #include @@ -51,49 +53,70 @@ __FBSDID("$FreeBSD: src/usr.bin/login/login_audit.c,v 1.2 2007/05/07 11:01:36 dw /* * Audit data */ -static au_tid_t tid; +au_tid_addr_t tid; /* * The following tokens are included in the audit record for a successful * login: header, subject, return. */ void -au_login_success(void) +au_login_success(int fflag) { token_t *tok; int aufd; - au_mask_t aumask; - auditinfo_t auinfo; + auditinfo_addr_t auinfo; uid_t uid = pwd->pw_uid; gid_t gid = pwd->pw_gid; pid_t pid = getpid(); long au_cond; - /* If we are not auditing, don't cut an audit record; just return. */ + /* Determine whether auditing is enabled. */ if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) { if (errno == ENOSYS) return; errx(1, "login: Could not determine audit condition"); } - if (au_cond == AUC_NOAUDIT) - return; - /* Compute and set the user's preselection mask. */ - if (au_user_mask(pwd->pw_name, &aumask) == -1) - errx(1, "login: Could not set audit mask\n"); + /* Initialize with the current audit info. */ + if (getaudit_addr(&auinfo, sizeof(auinfo)) < 0) { + err(1, "getaudit_addr"); + } + auinfo.ai_auid = pwd->pw_uid; + memcpy(&auinfo.ai_termid, &tid, sizeof(auinfo.ai_termid)); + + /* Do the SessionCreate() equivalent. */ + if (!fflag) { + auinfo.ai_asid = AU_ASSIGN_ASID; + auinfo.ai_flags |= AU_SESSION_FLAG_HAS_TTY; + auinfo.ai_flags |= AU_SESSION_FLAG_HAS_AUTHENTICATED; + } - /* Set the audit info for the user. */ - auinfo.ai_auid = uid; - auinfo.ai_asid = pid; - bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid)); - bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask)); - if (setaudit(&auinfo) != 0) - err(1, "login: setaudit failed"); + if (au_cond != AUC_NOAUDIT) { + /* Compute and set the user's preselection mask. */ + if (au_user_mask(pwd->pw_name, &auinfo.ai_mask) < 0) { + errx(1, "login: Could not set audit mask\n"); + } + } + + if (setaudit_addr(&auinfo, sizeof(auinfo)) < 0) + err(1, "login: setaudit_addr failed"); + + char *session = NULL; + asprintf(&session, "%x", auinfo.ai_asid); + if (NULL == session) { + errx(1, "asprintf failed"); + } + setenv("SECURITYSESSIONID", session, 1); + free(session); + + /* If we are not auditing, don't cut an audit record; just return. */ + if (au_cond == AUC_NOAUDIT) + return; if ((aufd = au_open()) == -1) errx(1,"login: Audit Error: au_open() failed"); - if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, + if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, gid, pid, pid, &tid)) == NULL) errx(1, "login: Audit Error: au_to_subject32() failed"); au_write(aufd, tok); @@ -137,14 +160,14 @@ au_login_fail(const char *errmsg, int na) * Non attributable event. Assuming that login is not called * within a user's session => auid,asid == -1. */ - if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1, + if ((tok = au_to_subject32_ex(-1, geteuid(), getegid(), -1, -1, pid, -1, &tid)) == NULL) errx(1, "login: Audit Error: au_to_subject32() failed"); } else { /* We know the subject -- so use its value instead. */ uid = pwd->pw_uid; gid = pwd->pw_gid; - if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, + if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, gid, pid, pid, &tid)) == NULL) errx(1, "login: Audit Error: au_to_subject32() failed"); } @@ -190,7 +213,7 @@ audit_logout(void) errx(1, "login: Audit Error: au_open() failed"); /* The subject that is created (euid, egid of the current process). */ - if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid, + if ((tok = au_to_subject32_ex(uid, geteuid(), getegid(), uid, gid, pid, pid, &tid)) == NULL) errx(1, "login: Audit Error: au_to_subject32() failed"); au_write(aufd, tok); diff --git a/login.tproj/pam.d/login b/login.tproj/pam.d/login new file mode 100644 index 0000000..b035d54 --- /dev/null +++ b/login.tproj/pam.d/login @@ -0,0 +1,12 @@ +# login: auth account password session +auth optional pam_krb5.so use_kcminit +auth optional pam_ntlm.so try_first_pass +auth optional pam_mount.so try_first_pass +auth sufficient pam_serialnumber.so try_first_pass serverinstall +auth required pam_opendirectory.so try_first_pass +account required pam_nologin.so +account required pam_opendirectory.so +password required pam_opendirectory.so +session required pam_launchd.so +session required pam_uwtmp.so +session optional pam_mount.so diff --git a/login.tproj/pam.d/login.term b/login.tproj/pam.d/login.term new file mode 100644 index 0000000..2c57c34 --- /dev/null +++ b/login.tproj/pam.d/login.term @@ -0,0 +1,4 @@ +# login: account session +account required pam_nologin.so +account required pam_opendirectory.so +session required pam_uwtmp.so diff --git a/makekey.tproj/Makefile b/makekey.tproj/Makefile index c35c1f3..fee842d 100644 --- a/makekey.tproj/Makefile +++ b/makekey.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/libexec CFILES = makekey.c MANPAGES = makekey.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/mean.tproj/mean.c b/mean.tproj/mean.c index 9e56018..4ea9255 100644 --- a/mean.tproj/mean.c +++ b/mean.tproj/mean.c @@ -9,8 +9,8 @@ #include #include - -#include +#include +#include #include #include @@ -19,48 +19,46 @@ void usage(void); -#ifndef PRIO_DARWIN_PROCESS -#define PRIO_DARWIN_PROCESS 4 /* Second argument is a PID */ -#endif void usage(void) { - fprintf(stderr, "Usage: mean -t \n"); - fprintf(stderr, "\tthrottle 's usage of cpu, I/O, and networking\n"); - fprintf(stderr, "mean -u \n"); - fprintf(stderr, "\treturn to normal priority\n"); - fprintf(stderr, "mean -[s|r] \n"); - fprintf(stderr, "\tsuspend or resume \n"); + fprintf(stderr, "Usage: mean -[r|s|u] \n"); + fprintf(stderr, "\tLower 's priority.\n"); + fprintf(stderr, "\t-u: return to normal priority\n"); + fprintf(stderr, "\t-r: resume \n"); + fprintf(stderr, "\t-s: suspend \n"); exit(0); } int main(int argc, char **argv) { - int pid, err, ch; + int pid, err, i, ch; + unsigned int count; mach_port_t task; - int priority = 0; + thread_act_array_t threads; + thread_precedence_policy_data_t policy; - boolean_t do_resume = 0, do_suspend = 0; - boolean_t do_throttle = 0, do_undo = 0; + boolean_t do_high = 0, do_resume = 0, do_suspend = 0; + boolean_t do_low = 1; if (argc < 2) usage(); - while ((ch = getopt(argc, argv, "rstu")) != -1) + while ((ch = getopt(argc, argv, "rsu")) != -1) switch (ch) { case 'u': - do_undo = 1; + do_high = 1; + do_low = 0; continue; case 'r': do_resume = 1; + do_low = 0; continue; case 's': do_suspend = 1; - continue; - case 't': - do_throttle = 1; + do_low = 0; continue; default: usage(); @@ -74,40 +72,57 @@ main(int argc, char **argv) pid = atoi(*argv); if (!pid) usage(); + + err = task_for_pid(mach_task_self(), pid, &task); + if (err) { + fprintf(stderr, "Failed to get task port (%d)\n", err); + exit(0); + } - if (do_throttle || do_undo) { - priority = PRIO_DARWIN_BG; - - if (do_undo) - priority = 0; + if (do_low || do_high) { - err = setpriority(PRIO_DARWIN_PROCESS, pid, priority); + err = task_threads(task, &threads, &count); if (err) { - fprintf(stderr, "Failed to set priority (%d)\n", errno); + fprintf(stderr, "Failed to get thread list (%d)\n", err); exit(0); } - } - if (do_suspend || do_resume) { - err = task_for_pid(mach_task_self(), pid, &task); - if (err) { - fprintf(stderr, "Failed to get task port (%d)\n", err); - exit(0); - } + if (do_low) + policy.importance = -100; + else + policy.importance = 0; - if (do_suspend) { - err = task_suspend(task); + for (i = 0; i < count; i++) { + err = thread_policy_set(threads[i], + THREAD_PRECEDENCE_POLICY, + (thread_policy_t) &policy, + THREAD_PRECEDENCE_POLICY_COUNT); if (err) { - fprintf(stderr, "Failed to suspend task (%d)\n", err); + fprintf(stderr, "Failed to set thread priority (%d)\n", err); + exit(0); } - } - if (do_resume) { - err = task_resume(task); - if (err) { - fprintf(stderr, "Failed to resume task (%d)\n", err); - } + printf("Process %d's threads set to %s priority.\n", pid, + (do_low ? "lowest" : "highest")); + } + + if (do_suspend) { + err = task_suspend(task); + if (err) { + fprintf(stderr, "Failed to suspend task (%d)\n", err); + } else { + printf("Process %d suspended.\n", pid); + } + + } + + if (do_resume) { + err = task_resume(task); + if (err) { + fprintf(stderr, "Failed to resume task (%d)\n", err); + } else { + printf("Process %d resumed.\n", pid); } } diff --git a/mkfile.tproj/Makefile b/mkfile.tproj/Makefile index 7ca1598..b2a5c40 100644 --- a/mkfile.tproj/Makefile +++ b/mkfile.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = mkfile.c MANPAGES = mkfile.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/newgrp.tproj/Makefile b/newgrp.tproj/Makefile index 65aa49d..9084908 100644 --- a/newgrp.tproj/Makefile +++ b/newgrp.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = newgrp.c MANPAGES = newgrp.1 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -D__FBSDID=__RCSID Extra_LD_Flags = -dead_strip diff --git a/nologin.tproj/Makefile b/nologin.tproj/Makefile index 7332134..d713444 100644 --- a/nologin.tproj/Makefile +++ b/nologin.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /sbin CFILES = nologin.c MANPAGES = nologin.5 nologin.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -D__FBSDID=__RCSID Extra_LD_Flags = -dead_strip diff --git a/nvram.tproj/Makefile b/nvram.tproj/Makefile index 5689c52..4ce2468 100644 --- a/nvram.tproj/Makefile +++ b/nvram.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = nvram.c MANPAGES = nvram.8 -Extra_CC_Flags = -mdynamic-no-pic -Wall -Werror +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_Frameworks = -framework CoreFoundation -framework IOKit diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c index 26e486f..9cb94ae 100644 --- a/nvram.tproj/nvram.c +++ b/nvram.tproj/nvram.c @@ -46,6 +46,8 @@ static void ClearOFVariables(void); static void ClearOFVariable(const void *key,const void *value,void *context); static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value); +static void NVRamSyncNow(char *name); + // Global Variables static char *gToolName; static io_registry_entry_t gOptionsRef; @@ -325,7 +327,7 @@ static void ParseXMLFile(char *fileName) NULL, NULL, &errorCode) || data == NULL ) { - errx(1, "Error reading XML file (%d)", errorCode); + errx(1, "Error reading XML file (%d)", (int)errorCode); } CFRelease(fileURL); @@ -382,6 +384,7 @@ static void SetOrGetOFVariable(char *str) value = str; result = SetOFVariable(name, value); + NVRamSyncNow(name); /* Try syncing the new data to device, best effort! */ if (result != KERN_SUCCESS) { errx(1, "Error setting variable - '%s': %s", name, mach_error_string(result)); @@ -495,6 +498,10 @@ static void DeleteOFVariable(char *name) SetOFVariable(kIONVRAMDeletePropertyKey, name); } +static void NVRamSyncNow(char *name) +{ + SetOFVariable(kIONVRAMSyncNowPropertyKey, name); +} // PrintOFVariables() // diff --git a/passwd.tproj/Makefile b/passwd.tproj/Makefile index b3136d1..d0303f1 100644 --- a/passwd.tproj/Makefile +++ b/passwd.tproj/Makefile @@ -1,13 +1,12 @@ Project = passwd Install_Dir = /usr/bin -HFILES = stringops.h -CFILES = passwd.c file_passwd.c stringops.c +CFILES = passwd.c file_passwd.c MANPAGES = passwd.1 Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip ifeq ($(Embedded),NO) @@ -17,7 +16,7 @@ endif include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make -Install_Program_Mode = 04555 +Install_Program_Mode = 0555 after_install: $(INSTALL_DIRECTORY) "$(DSTROOT)"/private/etc/pam.d diff --git a/passwd.tproj/file_passwd.c b/passwd.tproj/file_passwd.c index ffc81ca..002f38e 100644 --- a/passwd.tproj/file_passwd.c +++ b/passwd.tproj/file_passwd.c @@ -1,465 +1,236 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ +#include +#include +#include +#include +#include #include +#include +#include #include #include -#include -#include -#include -#include -#include #include +#include #include -#include #include -#include -#include "stringops.h" - -#define TEMP_FILE_TEMPLATE "/var/run/.pwtmpXXXXXX" -#define LOCK_FILE "/var/run/.passwd.lock" #define _PASSWD_FILE "/etc/master.passwd" #define _COMPAT_FILE "/etc/passwd" #define _PASSWD_FIELDS 10 #define BUFSIZE 8192 -extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **); - -//static int do_compat = 1; (unused) +void getpasswd(char *, int, int, int, int, char *, char **, char**, char **); -char * -getline(FILE *fp) +static struct passwd * +parse_user(char *line, size_t len) { - static char s[BUFSIZE]; - int len; - - s[0] = '\0'; - - fgets(s, BUFSIZE, fp); - if (s == NULL || s[0] == '\0') return NULL; - - if (s[0] == '#') return s; - - len = strlen(s) - 1; - s[len] = '\0'; - - return s; -} - -struct passwd * -parse_user(char *line) -{ - static struct passwd pw = {0}; - char **tokens; - int i, len; - - if (pw.pw_name != NULL) free(pw.pw_name); - pw.pw_name = NULL; - if (pw.pw_passwd != NULL) free(pw.pw_passwd); - pw.pw_passwd = NULL; - if (pw.pw_gecos != NULL) free(pw.pw_gecos); - pw.pw_gecos = NULL; - if (pw.pw_dir != NULL) free(pw.pw_dir); - pw.pw_dir = NULL; - if (pw.pw_shell != NULL) free(pw.pw_shell); - pw.pw_shell = NULL; - - if (pw.pw_class != NULL) free(pw.pw_class); - pw.pw_class = NULL; - - if (line == NULL) return (struct passwd *)NULL; - tokens = explode(line, ':'); - len = listLength(tokens); - - if (len != _PASSWD_FIELDS) - { - freeList(tokens); - return (struct passwd *)NULL; + static struct passwd pw; + int i,j; + char *tokens[_PASSWD_FIELDS]; + char *token = NULL; + bool comment = true; + + free(pw.pw_name); + free(pw.pw_passwd); + free(pw.pw_class); + free(pw.pw_gecos); + free(pw.pw_dir); + free(pw.pw_shell); + memset(&pw, 0, sizeof(pw)); + + if (line == NULL) return NULL; + + memset(&tokens, 0, sizeof(char *) * _PASSWD_FIELDS); + + for (i = 0, j = 0; i < len && j < _PASSWD_FIELDS; ++i) { + int c = line[i]; + if (!isspace(c) && c != '#') { + comment = false; + } + if (!comment && token == NULL) { + // start a new token + token = &line[i]; + } else if (token && (c == ':' || c == '\n')) { + // end the current token + // special case for empty token + while (token[0] == ':' && token < &line[i]) { + tokens[j++] = strdup(""); + ++token; + } + tokens[j++] = strndup(token, &line[i] - token); + token = NULL; + } } - i = 0; - pw.pw_name = tokens[i++]; - pw.pw_passwd = tokens[i++]; - pw.pw_uid = atoi(tokens[i]); - free(tokens[i++]); - pw.pw_gid = atoi(tokens[i]); - free(tokens[i++]); - pw.pw_class = tokens[i++]; - pw.pw_change = atoi(tokens[i]); - free(tokens[i++]); - pw.pw_expire = atoi(tokens[i]); - free(tokens[i++]); - pw.pw_gecos = tokens[i++]; - pw.pw_dir = tokens[i++]; - pw.pw_shell = tokens[i++]; + if (comment || j != _PASSWD_FIELDS) return NULL; + + j = 0; + pw.pw_name = tokens[j++]; + pw.pw_passwd = tokens[j++]; + pw.pw_uid = atoi(tokens[j]); + free(tokens[j++]); + pw.pw_gid = atoi(tokens[j]); + free(tokens[j++]); + pw.pw_class = tokens[j++]; + pw.pw_change = atoi(tokens[j]); + free(tokens[j++]); + pw.pw_expire = atoi(tokens[j]); + free(tokens[j++]); + pw.pw_gecos = tokens[j++]; + pw.pw_dir = tokens[j++]; + pw.pw_shell = tokens[j++]; return &pw; } -struct passwd * -find_user(char *uname, FILE *fp) +static struct passwd * +find_user(FILE *fp, char *uname) { + size_t len; char *line; - struct passwd *pw; rewind(fp); - while (NULL != (line = getline(fp))) - { - if (line[0] == '#') continue; - pw = parse_user(line); - if (pw == (struct passwd *)NULL) continue; - if (!strcmp(uname, pw->pw_name)) return pw; + while ((line = fgetln(fp, &len)) != NULL) { + struct passwd *pw = parse_user(line, len); + if (pw && strcmp(uname, pw->pw_name) == 0) { + return pw; + } } - - pw = parse_user(NULL); - return (struct passwd *)NULL; + return NULL; } -void -rewrite_file(char *pwname, FILE *fp, struct passwd *newpw, char *locn) +static void +rewrite_file(char *path, FILE *fp, struct passwd *newpw) { - char *line; - struct passwd *pw; - FILE *tfp, *cfp; int fd; - char fname[256]; + char *line; + size_t len; + FILE *tfp = NULL; + char *tempname = NULL; // temporary master.passwd file + + asprintf(&tempname, "%s.XXXXXX", path); - sprintf(fname, "%s.%.5d", TEMP_FILE_TEMPLATE, getpid()); - fd = mkstemps(fname, 6); - if (fd == -1) - { - fprintf(stderr, "can't create temporary file \"%s\": ", fname); - perror(""); - exit(1); - } - if (fchmod(fd, (S_IRUSR | S_IWUSR)) != 0) - { - close(fd); - unlink(fname); - fprintf(stderr, "can't set permissions for temporary file \"%s\": ", fname); - perror(""); - exit(1); + fd = mkstemp(tempname); + if (fd == -1) { + err(EXIT_FAILURE, "%s", tempname); } tfp = fdopen(fd, "w+"); - if (tfp == NULL) - { - close(fd); - unlink(fname); - fprintf(stderr, "can't write temporary file \"%s\": ", fname); - perror(""); - exit(1); - } - - cfp = NULL; - if (!strcmp(pwname, _PASSWD_FILE)) - { - cfp = fopen(_COMPAT_FILE, "w"); - if (cfp == NULL) - { - fprintf(stderr, "warning: can't write compatability file \"%s\": ", - _COMPAT_FILE); - perror(""); + if (tfp == NULL || fchmod(fd, S_IRUSR | S_IWUSR) != 0) { + int save = errno; + unlink(tempname); + errno = save; + err(EXIT_FAILURE, "%s", tempname); + } + + while ((line = fgetln(fp, &len)) != NULL) { + struct passwd *pw = parse_user(line, len); + + // if this is not the entry we're looking for or if parsing + // failed (likely a comment) then print the entry as is. + if (pw == NULL || strcmp(newpw->pw_name, pw->pw_name) != 0) { + fwrite(line, sizeof(char), len, tfp); + } else { + fprintf(tfp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + newpw->pw_name, + newpw->pw_passwd, + newpw->pw_uid, + newpw->pw_gid, + newpw->pw_class, + newpw->pw_change, + newpw->pw_expire, + newpw->pw_gecos, + newpw->pw_dir, + newpw->pw_shell); } } - if (cfp != NULL) - { - fprintf(cfp, "#\n"); - fprintf(cfp, "# 4.3BSD-compatable User Database\n"); - fprintf(cfp, "#\n"); - fprintf(cfp, "# Note that this file is not consulted for login.\n"); - fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n"); - fprintf(cfp, "#\n"); - fprintf(cfp, "# This file is automatically re-written by various system utilities.\n"); - fprintf(cfp, "# Do not edit this file. Changes will be lost.\n"); - fprintf(cfp, "#\n"); + // Move the temporary file into place. + if (fclose(tfp) != 0 || rename(tempname, path) != 0) { + int save = errno; + unlink(tempname); + errno = save; + err(EXIT_FAILURE, "%s", tempname); } - - rewind(fp); - - while (NULL != (line = getline(fp))) - { - if (line[0] == '#') - { - fprintf(tfp, "%s", line); - continue; - } - - pw = parse_user(line); - if (pw == (struct passwd *)NULL) - { - fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line); - fprintf(tfp, "%s\n", line); - if (cfp != NULL) fprintf(cfp, "%s\n", line); - continue; - } - if (strcmp(newpw->pw_name, pw->pw_name)) - { - fprintf(tfp, "%s\n", line); - if (cfp != NULL) fprintf(cfp, "%s\n", line); - continue; - } - - fprintf(tfp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", - newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid, - newpw->pw_class, newpw->pw_change, newpw->pw_expire, - newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell); - if (cfp != NULL) - { - fprintf(cfp, "%s:",newpw->pw_name); - if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0')) - fprintf(cfp, ":"); - else - fprintf(cfp, "*:"); - fprintf(cfp, "%d:%d:%s:%s:%s\n", - newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos, - newpw->pw_dir, newpw->pw_shell); - } - } - - if (cfp != NULL) fclose(cfp); - fclose(fp); - - rewind(tfp); - - if (locn != NULL) { - if (seteuid(getuid()) != 0) { - fprintf(stderr, "Unable to set privileges."); - perror("seteuid"); - exit(1); - } - } - fp = fopen(pwname, "w"); - if (fp == NULL) - { - fprintf(stderr, "ERROR: can't update \"%s\"\n", pwname); - fprintf(stderr, "new passwd file is \"%s\"\n", fname); - perror("open"); - exit(1); - } - - while (NULL != (line = getline(tfp))) - { - fprintf(fp, "%s", line); - if (line[0] != '#') fprintf(fp, "\n"); - } - fclose(fp); - fclose(tfp); - unlink(fname); + free(tempname); } int -_file_passwd_main(char *uname, char *locn) +file_passwd(char *uname, char *locn) { char *ne, *oc, *nc; + int fd; FILE *fp; + uid_t uid; char *fname; struct passwd *pw; struct passwd newpw; - struct stat sb; - int uid; - uid_t euid; fname = _PASSWD_FILE; if (locn != NULL) fname = locn; - umask((S_IRWXG | S_IRWXO)); - - if ( lstat(fname, &sb) != 0 ) - { - fprintf(stderr, "The file does not exist.\n"); - exit(1); - } - - euid = geteuid(); - if (locn != NULL) { - if (seteuid(getuid()) != 0) { - fprintf(stderr, "Permission denied.\n"); - exit(1); + fd = open(fname, O_RDONLY | O_EXLOCK); + if (fd == -1) { + err(EXIT_FAILURE, "%s", fname); } + + fp = fdopen(fd, "r"); + if (fp == NULL) { + err(EXIT_FAILURE, "%s", fname); } - fp = fopen(fname, "a+"); - if (locn != NULL) { - seteuid(euid); - } - - if (fp == NULL) - { - fprintf(stderr, "can't write to file \"%s\": ", fname); - perror(""); - exit(1); - } - if (fchmod(fileno(fp), (S_IRUSR | S_IWUSR)) != 0) - { - fclose(fp); - fprintf(stderr, "can't set permissions for file \"%s\": ", fname); - perror(""); - exit(1); - } - - pw = find_user(uname, fp); - if (pw == (struct passwd *)NULL) - { - fprintf(stderr, "user %s not found in file %s\n", uname, fname); - exit(1); + + pw = find_user(fp, uname); + if (pw == NULL) { + errx(EXIT_FAILURE, "user %s not found in %s", uname, fname); } uid = getuid(); - if ((uid != 0) && (uid != pw->pw_uid)) - { - fprintf(stderr, "Permission denied\n"); - exit(1); + if (uid != 0 && uid != pw->pw_uid) { + errno = EACCES; + err(EXIT_FAILURE, "%s", uname); } - /* - * Get the new password - */ + // Get the password getpasswd(uname, (uid == 0), 5, 0, 0, pw->pw_passwd, &ne, &oc, &nc); - newpw.pw_name = copyString(pw->pw_name); - newpw.pw_passwd = copyString(ne); + newpw.pw_name = strdup(pw->pw_name); + newpw.pw_passwd = strdup(ne); newpw.pw_uid = pw->pw_uid; newpw.pw_gid = pw->pw_gid; - newpw.pw_class = copyString(pw->pw_class); + newpw.pw_class = strdup(pw->pw_class); newpw.pw_change = pw->pw_change; newpw.pw_expire = pw->pw_expire; - newpw.pw_gecos = copyString(pw->pw_gecos); - newpw.pw_dir = copyString(pw->pw_dir); - newpw.pw_shell = copyString(pw->pw_shell); - - /* - * Re-write the file - */ - rewrite_file(fname, fp, &newpw, locn); + newpw.pw_gecos = strdup(pw->pw_gecos); + newpw.pw_dir = strdup(pw->pw_dir); + newpw.pw_shell = strdup(pw->pw_shell); - /* - * Clean up memory - */ - pw = parse_user(NULL); - free(newpw.pw_name); - free(newpw.pw_passwd); - free(newpw.pw_gecos); - free(newpw.pw_dir); - free(newpw.pw_shell); - free(newpw.pw_class); + // Rewrite the file + rewind(fp); + rewrite_file(fname, fp, &newpw); fclose(fp); return 0; } - - -void sighandler(int inSignal) -{ - unlink(LOCK_FILE); - exit(1); -} - - -int -file_passwd(char *uname, char *locn) -{ - pid_t pid; - int retVal = 0; - int waitResult = 0; - int retries = 0; - struct stat sb; - FILE *lockFile; - struct sigaction action = {{0}}; - struct rlimit rlim; - - /* unlimit the resource limits */ - rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; - (void)setrlimit(RLIMIT_CPU, &rlim); - (void)setrlimit(RLIMIT_FSIZE, &rlim); - (void)setrlimit(RLIMIT_STACK, &rlim); - (void)setrlimit(RLIMIT_DATA, &rlim); - (void)setrlimit(RLIMIT_RSS, &rlim); - (void)setrlimit(RLIMIT_NOFILE, &rlim); - - /* trap signals */ - sigfillset( &action.sa_mask ); - action.sa_flags = SA_RESTART; - action.sa_handler = sighandler; - sigaction(SIGHUP, &action, NULL); - sigaction(SIGINT, &action, NULL); // ctrl-c - sigaction(SIGQUIT, &action, NULL); - sigaction(SIGABRT, &action, NULL); - sigaction(SIGPIPE, &action, NULL); - sigaction(SIGALRM, &action, NULL); - sigaction(SIGTERM, &action, NULL); - sigaction(SIGSTOP, &action, NULL); - sigaction(SIGTSTP, &action, NULL); - - /* Check/create lock file */ - for (retries = 0; retries < 5; retries++) - { - retVal = lstat(LOCK_FILE, &sb); - if (retVal != 0) - break; - /* try in 100 milliseconds */ - usleep(100000); - } - if (retVal == 0) - { - fprintf(stderr, "another passwd process is running.\n"); - exit(EX_TEMPFAIL); - } - - umask((S_IRWXG | S_IRWXO)); - lockFile = fopen(LOCK_FILE, "w"); - if (lockFile == NULL) - { - fprintf(stderr, "can't create lock file.\n"); - exit(EX_CANTCREAT); - } - fprintf(lockFile, "%d\n", getpid()); - fclose(lockFile); - - pid = fork(); - if (pid == -1) - { - fprintf(stderr, "can't fork\n"); - exit(EX_OSERR); - } - - /* Handle the child */ - if (pid == 0) - { - retVal = _file_passwd_main(uname, locn); - exit(retVal); - } - - /* Handle the parent */ - waitResult = waitpid(pid, &retVal, 0); - retVal = (waitResult == 0) ? WEXITSTATUS(retVal) : 1; - - /* delete lock file */ - unlink(LOCK_FILE); - - return retVal; -} - diff --git a/passwd.tproj/od_passwd.c b/passwd.tproj/od_passwd.c index 908d999..16bcf89 100644 --- a/passwd.tproj/od_passwd.c +++ b/passwd.tproj/od_passwd.c @@ -74,57 +74,15 @@ show_error(CFErrorRef error) { } } -static int -is_singleuser(void) { - uint32_t su = 0; - size_t susz = sizeof(su); - if (sysctlbyname("kern.singleuser", &su, &susz, NULL, 0) != 0) { - return 0; - } else { - return (int)su; - } -} - -static int -load_DirectoryServicesLocal() { - const char* launchctl = "/bin/launchctl"; - const char* plist = "/System/Library/LaunchDaemons/com.apple.DirectoryServicesLocal.plist"; - - pid_t pid = fork(); - int status, res; - switch (pid) { - case -1: // ERROR - perror("launchctl"); - return 0; - case 0: // CHILD - execl(launchctl, launchctl, "load", plist, NULL); - /* NOT REACHED */ - perror("launchctl"); - exit(1); - break; - default: // PARENT - do { - res = waitpid(pid, &status, 0); - } while (res == -1 && errno == EINTR); - if (res == -1) { - perror("launchctl"); - return 0; - } - break; - } - return (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS)); -} - int od_passwd(char* uname, char* locn, char* aname) { - int change_pass_on_self; - CFErrorRef error = NULL; + int change_pass_on_self; + CFErrorRef error = NULL; CFStringRef username = NULL; CFStringRef location = NULL; CFStringRef authname = NULL; - ODSessionRef session = NULL; - ODNodeRef node = NULL; + ODNodeRef node = NULL; ODRecordRef rec = NULL; CFStringRef oldpass = NULL; CFStringRef newpass = NULL; @@ -156,44 +114,15 @@ od_passwd(char* uname, char* locn, char* aname) if (!username) return -1; } - /* - * Connect to DS server - */ - session = ODSessionCreate(NULL, NULL, &error); - if ( !session && error && CFErrorGetCode(error) == kODErrorSessionDaemonNotRunning ) { - /* - * In single-user mode, attempt to load the local DS daemon. - */ - if (is_singleuser() && load_DirectoryServicesLocal()) { - CFTypeRef keys[] = { kODSessionLocalPath }; - CFTypeRef vals[] = { CFSTR("/var/db/dslocal") }; - CFDictionaryRef opts = CFDictionaryCreate(NULL, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (opts) { - session = ODSessionCreate(NULL, opts, &error); - CFRelease(opts); - } - - if (!location) { - location = CFRetain(CFSTR("/Local/Default")); - } - } else { - show_error(error); - return -1; - } - } - - /* * Copy the record from the specified node, or perform a search. */ if (location) { - node = ODNodeCreateWithName(NULL, session, location, &error); + node = ODNodeCreateWithName(NULL, kODSessionDefault, location, &error); } else { - node = ODNodeCreateWithNodeType(NULL, session, kODNodeTypeAuthentication, &error); + node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODNodeTypeAuthentication, &error); } - if (session) CFRelease(session); - if (node) { rec = ODNodeCopyRecord(node, kODRecordTypeUsers, username, NULL, &error ); CFRelease(node); @@ -259,22 +188,7 @@ od_passwd(char* uname, char* locn, char* aname) } } - if (needs_auth) { - CFTypeRef values[] = { username, newpass, authname, oldpass }; - CFArrayRef authItems = CFArrayCreate(NULL, values, 4, &kCFTypeArrayCallBacks); - - ODRecordSetNodeCredentialsExtended(rec, - kODRecordTypeUsers, - kODAuthenticationTypeSetPassword, - authItems, - NULL, - NULL, - &error); - - CFRelease(authItems); - } else { - ODRecordChangePassword(rec, oldpass, newpass, &error); - } + ODRecordChangePassword(rec, oldpass, newpass, &error); if (error) { show_error(error); diff --git a/passwd.tproj/passwd.c b/passwd.tproj/passwd.c index 2f8599a..7041406 100644 --- a/passwd.tproj/passwd.c +++ b/passwd.tproj/passwd.c @@ -29,11 +29,7 @@ #define INFO_PAM 4 #endif -#ifndef __SLICK__ #define _PASSWD_FILE "/etc/master.passwd" -#else -#define _PASSWD_FILE "/etc/passwd" -#endif #include #include @@ -41,7 +37,6 @@ #include #include #include -#include "stringops.h" #ifdef __SLICK__ #define _PASSWORD_LEN 8 diff --git a/passwd.tproj/stringops.c b/passwd.tproj/stringops.c deleted file mode 100644 index a3621e3..0000000 --- a/passwd.tproj/stringops.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." - * - * @APPLE_LICENSE_HEADER_END@ - */ -#import -#import -#import -#import -#import "stringops.h" - -char *copyString(char *s) -{ - int len; - char *t; - - if (s == NULL) return NULL; - - len = strlen(s) + 1; - t = malloc(len); - bcopy(s, t, len); - return t; -} - -char *concatString(char *s, char *t) -{ - int len; - - if (t == NULL) return s; - - len = strlen(s) + strlen(t) + 1; - s = realloc(s, len); - strcat(s, t); - return s; -} - -char **insertString(char *s, char **l, unsigned int x) -{ - int i, len; - - if (s == NULL) return l; - if (l == NULL) - { - l = (char **)malloc(2 * sizeof(char *)); - l[0] = copyString(s); - l[1] = NULL; - return l; - } - - for (i = 0; l[i] != NULL; i++); - len = i + 1; /* count the NULL on the end of the list too! */ - - l = (char **)realloc(l, (len + 1) * sizeof(char *)); - - if ((x >= (len - 1)) || (x == IndexNull)) - { - l[len - 1] = copyString(s); - l[len] = NULL; - return l; - } - - for (i = len; i > x; i--) l[i] = l[i - 1]; - l[x] = copyString(s); - return l; -} - -char **appendString(char *s, char **l) -{ - return insertString(s, l, IndexNull); -} - -void freeList(char **l) -{ - int i; - - if (l == NULL) return; - for (i = 0; l[i] != NULL; i++) - { - if (l[i] != NULL) free(l[i]); - l[i] = NULL; - } - if (l != NULL) free(l); -} - -void freeString(char *s) -{ - if (s == NULL) return; - free(s); -} - -unsigned int listLength(char **l) -{ - int i; - - if (l == NULL) return 0; - for (i = 0; l[i] != NULL; i++); - return i; -} - -unsigned int listIndex(char *s,char **l) -{ - int i; - - if (l == NULL) return IndexNull; - for (i = 0; l[i] != NULL; i++) - { - if (strcmp(s, l[i]) == 0) return i; - } - return IndexNull; -} - -char *prefix(char *s, char c) -{ - int i; - char *t; - - if (s == NULL) return NULL; - - for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++); - if (i == 0) return NULL; - if (s[i] == '\0') return copyString(s); - - t = malloc(i + 1); - bcopy(s, t, i); - t[i] = '\0'; - return t; -} - -char *postfix(char *s, char c) -{ - int i, len; - char *t; - - if (s == NULL) return NULL; - - for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++); - if (s[i] == '\0') return NULL; - len = strlen(s) - i; - if (len == 1) return NULL; - - t = malloc(len); - len--; - bcopy((s + i + 1), t, len); - t[len] = '\0'; - return t; -} - -char *presuffix(char *s, char c) -{ - int i, len; - char *t; - - if (s == NULL) return NULL; - - len = strlen(s); - for (i = len - 1; ((i >= 0) && (s[i] != c)); i--); - if (i == 0) return NULL; - if (s[0] == '\0') return NULL; - - t = malloc(i + 1); - bcopy(s, t, i); - t[i] = '\0'; - return t; -} - -char *suffix(char *s, char c) -{ - int i, len; - char *t; - - if (s == NULL) return NULL; - - len = strlen(s); - for (i = len - 1; ((i >= 0) && (s[i] != c)); i--); - if (i == 0) return NULL; - len -= i; - if (len == 1) return NULL; - t = malloc(len); - len--; - bcopy((s + i + 1), t, len); - t[len] = '\0'; - return t; -} - -char *lowerCase(char *s) -{ - int i; - char *t; - - if (s == NULL) return NULL; - t = malloc(strlen(s) + 1); - - for (i = 0; s[i] != '\0'; i++) - { - if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32; - else t[i] = s[i]; - } - t[i] = '\0'; - return t; -} - -char **explode(char *s, char c) -{ - char **l = NULL; - char *p, *t; - int i, n; - - if (s == NULL) return NULL; - - p = s; - while (p[0] != '\0') - { - for (i = 0; ((p[i] != '\0') && p[i] != c); i++); - n = i; - t = malloc(n + 1); - for (i = 0; i < n; i++) t[i] = p[i]; - t[n] = '\0'; - l = appendString(t, l); - free(t); - t = NULL; - if (p[i] == '\0') return l; - if (p[i + 1] == '\0') l = appendString("", l); - p = p + i + 1; - } - return l; -} diff --git a/passwd.tproj/stringops.h b/passwd.tproj/stringops.h deleted file mode 100644 index e0a679e..0000000 --- a/passwd.tproj/stringops.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." - * - * @APPLE_LICENSE_HEADER_END@ - */ -#define streq(A, B) (strcmp(A, B) == 0) -#define IndexNull (unsigned int)-1 -char *copyString(char *); -char *concatString(char *, char *); -char **insertString(char *, char **, unsigned int); -char **appendString(char *, char **); -void freeList(char **); -void freeString(char *); -unsigned int listLength(char **); -unsigned int listIndex(char *,char **); -char *prefix(char *, char); -char *postfix(char *, char); -char *presuffix(char *, char); -char *suffix(char *, char); -char *lowerCase(char *); -char **explode(char *, char); diff --git a/pwd_mkdb.tproj/Makefile b/pwd_mkdb.tproj/Makefile index 03e22f0..22368c3 100644 --- a/pwd_mkdb.tproj/Makefile +++ b/pwd_mkdb.tproj/Makefile @@ -6,7 +6,7 @@ CFILES = pwd_mkdb.c pw_scan.c OTHERSRCS = Makefile.preamble Makefile Makefile.postamble pwd_mkdb.8 MANPAGES = pwd_mkdb.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_CC_Flags += -D_PW_NAME_LEN=MAXLOGNAME -D_PW_YPTOKEN=\"__YP!\" diff --git a/pwd_mkdb.tproj/pwd_mkdb.c b/pwd_mkdb.tproj/pwd_mkdb.c index de64cd6..075200a 100644 --- a/pwd_mkdb.tproj/pwd_mkdb.c +++ b/pwd_mkdb.tproj/pwd_mkdb.c @@ -385,9 +385,7 @@ fmt: errno = EFTYPE; /* XXX */ } void -cp(from, to, mode) - char *from, *to; - mode_t mode; +cp(char *from, char *to, mode_t mode) { static char buf[MAXBSIZE]; int from_fd, rcount, to_fd, wcount; diff --git a/reboot.tproj/Makefile b/reboot.tproj/Makefile index 59a49c4..47332e7 100644 --- a/reboot.tproj/Makefile +++ b/reboot.tproj/Makefile @@ -9,7 +9,7 @@ ifeq ($(Embedded),NO) USERDEFS = kextmanager.defs endif -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sa.tproj/Makefile b/sa.tproj/Makefile index 515b592..dbd7415 100644 --- a/sa.tproj/Makefile +++ b/sa.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = main.c pdb.c usrdb.c db.c MANPAGES = sa.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -D__FBSDID=__RCSID Extra_CC_Flags += -DAHZV1=64 Extra_LD_Flags = -dead_strip diff --git a/sadc.tproj/Makefile b/sadc.tproj/Makefile index 93bd5b1..6f98e25 100644 --- a/sadc.tproj/Makefile +++ b/sadc.tproj/Makefile @@ -8,7 +8,7 @@ MANPAGES = sa1.8 sa2.8 sadc.8 OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sa1.8 sa1.sh\ sa2.8 sa2.sh sadc.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_CC_Flags += -I. diff --git a/sadc.tproj/sadc.c b/sadc.tproj/sadc.c index a88e3ff..70ead05 100644 --- a/sadc.tproj/sadc.c +++ b/sadc.tproj/sadc.c @@ -472,7 +472,7 @@ record_device(io_registry_entry_t drive, struct drivestats* drivestat, int ndriv CFSTR(kIOBSDNameKey)); if (name) { CFStringGetCString(name, BSDName, - MAXDRIVENAME, CFStringGetSystemEncoding()); + MAXDRIVENAME, kCFStringEncodingUTF8); retval++; } diff --git a/sar.tproj/Makefile b/sar.tproj/Makefile index ec59ecc..1e6d991 100644 --- a/sar.tproj/Makefile +++ b/sar.tproj/Makefile @@ -5,7 +5,7 @@ HFILES = sar.h CFILES = sar.c MANPAGES = sar.1 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_CC_Flags += -I. -I../sadc.tproj diff --git a/sc_usage.tproj/Makefile b/sc_usage.tproj/Makefile index 22818ac..fd8b88a 100644 --- a/sc_usage.tproj/Makefile +++ b/sc_usage.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = sc_usage.c MANPAGES = sc_usage.1 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_LD_Flags = -dead_strip Extra_CC_Flags += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ @@ -12,8 +12,3 @@ Extra_CC_Flags += -I$(SDKROOT)/System/Library/Frameworks/System.framework/Privat Extra_LD_Flags += -lcurses -lutil include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make - -after_install: - $(INSTALL_DIRECTORY) $(DSTROOT)/usr/share/misc - $(INSTALL_FILE) trace.codes $(DSTROOT)/usr/share/misc - diff --git a/sc_usage.tproj/trace.codes b/sc_usage.tproj/trace.codes deleted file mode 100644 index c9ff79b..0000000 --- a/sc_usage.tproj/trace.codes +++ /dev/null @@ -1,1507 +0,0 @@ -0x1f000000 DYLD_initialize -0x1f010000 DYLD_CALL_image_init_routine -0x1f010004 DYLD_CALL_dependent_init_routine -0x1f010008 DYLD_CALL_lazy_init_routine -0x1f01000c DYLD_CALL_module_init_for_library -0x1f010010 DYLD_CALL_module_init_for_object -0x1f010014 DYLD_CALL_module_terminator_for_object -0x1f010018 DYLD_CALL_module_init_for_dylib -0x1f01001c DYLD_CALL_mod_term_func -0x1f010020 DYLD_CALL_object_func -0x1f010024 DYLD_CALL_library_func -0x1f010028 DYLD_CALL_add_image_func -0x1f01002c DYLD_CALL_remove_image_func -0x1f010030 DYLD_CALL_link_object_module_func -0x1f010034 DYLD_CALL_link_library_module_func -0x1f010038 DYLD_CALL_link_module_func -0x1f020000 DYLD_lookup_and_bind_with_hint -0x1f020004 DYLD_lookup_and_bind_fully -0x1f020008 DYLD_link_module -0x1f02000c DYLD_ulink_module -0x1f020010 DYLD_bind_objc_module -0x1f020014 DYLD_bind_fully_image_containing_address -0x1f020018 DYLD_make_delayed_module_initializer_calls -0x1f02001c DYLD_NSNameOfSymbol -0x1f020020 DYLD_NSAddressOfSymbol -0x1f020024 DYLD_NSModuleForSymbol -0x1f020028 DYLD_NSLookupAndBindSymbolWithHint -0x1f02002c DYLD_NSLookupSymbolInModule -0x1f020030 DYLD_NSLookupSymbolInImage -0x1f020034 DYLD_NSIsSymbolNameDefined -0x1f020038 DYLD_NSIsSymbolNameDefinedWithHint -0x1f02003c DYLD_NSIsSymbolNameDefinedInImage -0x1f020040 DYLD_NSNameOfModule -0x1f020044 DYLD_NSLibraryNameForModule -0x1f020048 DYLD_NSAddLibrary -0x1f02004c DYLD_NSAddLibraryWithSearching -0x1f020050 DYLD_NSAddImage -0x1f030000 DYLD_lookup_symbol -0x1f030004 DYLD_bind_lazy_symbol_reference -0x1f030008 DYLD_bind_symbol_by_name -0x1f03000c DYLD_link_in_need_modules -0x1f040000 DYLD_map_image -0x1f040004 DYLD_load_executable_image -0x1f040008 DYLD_load_library_image -0x1f04000c DYLD_map_library_image -0x1f040010 DYLD_map_bundle_image -0x1f040014 DYLD_load_dependent_libraries -0x1f040018 DYLD_notify_prebinding_agent -0x21060000 LAUNCH_CPSTraceLineNum -0x21060004 LAUNCH_CPSLaunch -0x21060008 LAUNCH_CPSRegisterwithServer -0x2106000c LAUNCH_CPSCheckInNewProcess -0x21060010 LAUNCH_CPSServerSideLaunch -0x21060014 LAUNCH_CPSExecProcess -0x21070000 LAUNCH_LSOpen -0x21070004 LAUNCH_LSRegisterItem -0x21070008 LAUNCH_LSGetApplicationAndFlagsForInfo -0x1fff0000 LAUNCH_START_FINDER -0x1fff0100 LAUNCH_START_DOCK -0x1fff0310 LAUNCH_APP_EnterEventLoop -0x1fff0314 LAUNCH_APP_WillOpenUntitled -0x1fff031c LAUNCH_APP_DidOpenUntitled -0x1fffffff LAUNCH_END -0xff000104 MSG_mach_notify_port_deleted -0xff000114 MSG_mach_notify_port_destroyed -0xff000118 MSG_mach_notify_no_senders -0xff00011c MSG_mach_notify_send_once -0xff000120 MSG_mach_notify_dead_name -0xff0001ec MSG_audit_triggers -0xff000320 MSG_host_info -0xff000324 MSG_host_kernel_version -0xff000328 MSG_host_page_size -0xff00032c MSG_mach_memory_object_memory_entry -0xff000330 MSG_host_processor_info -0xff000334 MSG_host_get_io_master -0xff000338 MSG_host_get_clock_service -0xff00033c MSG_kmod_get_info -0xff000340 MSG_host_zone_info -0xff000344 MSG_host_virtual_physical_table_info -0xff000348 MSG_host_ipc_hash_info -0xff00034c MSG_enable_bluebox -0xff000350 MSG_disable_bluebox -0xff000354 MSG_processor_set_default -0xff000358 MSG_processor_set_create -0xff00035c MSG_mach_memory_object_memory_entry_64 -0xff000360 MSG_host_statistics -0xff000364 MSG_host_request_notification -0xff000368 MSG_host_lockgroup_info -0xff000640 MSG_host_get_boot_info -0xff000644 MSG_host_reboot -0xff000648 MSG_host_priv_statistics -0xff00064c MSG_host_default_memory_manager -0xff000650 MSG_vm_wire -0xff000654 MSG_thread_wire -0xff000658 MSG_vm_allocate_cpm -0xff00065c MSG_host_processors -0xff000660 MSG_host_get_clock_control -0xff000664 MSG_kmod_create -0xff000668 MSG_kmod_destroy -0xff00066c MSG_kmod_control -0xff000670 MSG_host_get_special_port -0xff000674 MSG_host_set_special_port -0xff000678 MSG_host_set_exception_ports -0xff00067c MSG_host_get_exception_ports -0xff000680 MSG_host_swap_exception_ports -0xff000684 MSG_host_load_symbol_table -0xff000688 MSG_mach_vm_wire -0xff00068c MSG_host_processor_sets -0xff000690 MSG_host_processor_set_priv -0xff000694 MSG_set_dp_control_port -0xff000698 MSG_get_dp_control_port -0xff00069c MSG_host_set_UNDServer -0xff0006a0 MSG_host_get_UNDServer -0xff000960 MSG_host_security_create_task_token -0xff000964 MSG_host_security_set_task_token -0xff000fa0 MSG_clock_get_time -0xff000fa4 MSG_clock_get_attributes -0xff000fa8 MSG_clock_alarm -0xff0012c0 MSG_clock_set_time -0xff0012c4 MSG_clock_set_attributes -0xff001f40 MSG_memory_object_get_attributes -0xff001f44 MSG_memory_object_change_attributes -0xff001f48 MSG_memory_object_synchronize_completed -0xff001f4c MSG_memory_object_lock_request -0xff001f50 MSG_memory_object_destroy -0xff001f54 MSG_memory_object_upl_request -0xff001f58 MSG_memory_object_super_upl_request -0xff001f5c MSG_memory_object_page_op -0xff001f60 MSG_memory_object_recover_named -0xff001f64 MSG_memory_object_release_name -0xff001f68 MSG_memory_object_range_op -0xff002008 MSG_upl_abort -0xff00200c MSG_upl_abort_range -0xff002010 MSG_upl_commit -0xff002014 MSG_upl_commit_range -0xff002260 MSG_memory_object_init -0xff002264 MSG_memory_object_terminate -0xff002268 MSG_memory_object_data_request -0xff00226c MSG_memory_object_data_return -0xff002270 MSG_memory_object_data_initialize -0xff002274 MSG_memory_object_data_unlock -0xff002278 MSG_memory_object_synchronize -0xff00227c MSG_memory_object_unmap -0xff002328 MSG_memory_object_create -0xff00238c MSG_default_pager_object_create -0xff002390 MSG_default_pager_info -0xff002394 MSG_default_pager_objects -0xff002398 MSG_default_pager_object_pages -0xff0023a0 MSG_default_pager_backing_store_create -0xff0023a4 MSG_default_pager_backing_store_delete -0xff0023a8 MSG_default_pager_backing_store_info -0xff0023ac MSG_default_pager_add_file -0xff0023b0 MSG_default_pager_triggers -0xff0023b4 MSG_default_pager_info_64 -0xff0023dc MSG_default_pager_space_alert -0xff002584 MSG_exception_raise -0xff002588 MSG_exception_raise_state -0xff00258c MSG_exception_raise_state_identity -0xff002bc0 MSG_io_object_get_class -0xff002bc4 MSG_io_object_conforms_to -0xff002bc8 MSG_io_iterator_next -0xff002bcc MSG_io_iterator_reset -0xff002bd0 MSG_io_service_get_matching_services -0xff002bd4 MSG_io_registry_entry_get_property -0xff002bd8 MSG_io_registry_create_iterator -0xff002bdc MSG_io_registry_iterator_enter_entry -0xff002be0 MSG_io_registry_iterator_exit_entry -0xff002be4 MSG_io_registry_entry_from_path -0xff002be8 MSG_io_registry_entry_get_name -0xff002bec MSG_io_registry_entry_get_properties -0xff002bf0 MSG_io_registry_entry_get_property_bytes -0xff002bf4 MSG_io_registry_entry_get_child_iterator -0xff002bf8 MSG_io_registry_entry_get_parent_iterator -0xff002bfc MSG_io_service_open -0xff002c00 MSG_io_service_close -0xff002c04 MSG_io_connect_get_service -0xff002c08 MSG_io_connect_set_notification_port -0xff002c0c MSG_io_connect_map_memory -0xff002c10 MSG_io_connect_add_client -0xff002c14 MSG_io_connect_set_properties -0xff002c18 MSG_io_connect_method_scalarI_scalarO -0xff002c1c MSG_io_connect_method_scalarI_structureO -0xff002c20 MSG_io_connect_method_scalarI_structureI -0xff002c24 MSG_io_connect_method_structureI_structureO -0xff002c28 MSG_io_registry_entry_get_path -0xff002c2c MSG_io_registry_get_root_entry -0xff002c30 MSG_io_registry_entry_set_properties -0xff002c34 MSG_io_registry_entry_in_plane -0xff002c38 MSG_io_object_get_retain_count -0xff002c3c MSG_io_service_get_busy_state -0xff002c40 MSG_io_service_wait_quiet -0xff002c44 MSG_io_registry_entry_create_iterator -0xff002c48 MSG_io_iterator_is_valid -0xff002c4c MSG_io_make_matching -0xff002c50 MSG_io_catalog_send_data -0xff002c54 MSG_io_catalog_terminate -0xff002c58 MSG_io_catalog_get_data -0xff002c5c MSG_io_catalog_get_gen_count -0xff002c60 MSG_io_catalog_module_loaded -0xff002c64 MSG_io_catalog_reset -0xff002c68 MSG_io_service_request_probe -0xff002c6c MSG_io_registry_entry_get_name_in_plane -0xff002c70 MSG_io_service_match_property_table -0xff002c74 MSG_io_async_method_scalarI_scalarO -0xff002c78 MSG_io_async_method_scalarI_structureO -0xff002c7c MSG_io_async_method_scalarI_structureI -0xff002c80 MSG_io_async_method_structureI_structureO -0xff002c84 MSG_io_service_add_notification -0xff002c88 MSG_io_service_add_interest_notification -0xff002c8c MSG_io_service_acknowledge_notification -0xff002c90 MSG_io_connect_get_notification_semaphore -0xff002c94 MSG_io_connect_unmap_memory -0xff002c98 MSG_io_registry_entry_get_location_in_plane -0xff002c9c MSG_io_registry_entry_get_property_recursively -0xff002ca0 MSG_io_service_get_state -0xff002ca4 MSG_io_service_get_matching_services_ool -0xff002ca8 MSG_io_service_match_property_table_ool -0xff002cac MSG_io_service_add_notification_ool -0xff002cb0 MSG_io_object_get_superclass -0xff002cb4 MSG_io_object_get_bundle_identifier -0xff002cb8 MSG_io_service_open_extended -0xff002cbc MSG_io_connect_map_memory_into_task -0xff002cc0 MSG_io_connect_unmap_memory_from_task -0xff002cc4 MSG_io_connect_method -0xff002cc8 MSG_io_connect_async_method -0xff002ccc MSG_io_connect_set_notification_port_64 -0xff002cd0 MSG_io_service_add_notification_64 -0xff002cd4 MSG_io_service_add_interest_notification_64 -0xff002cd8 MSG_io_service_add_notification_ool_64 -0xff002ee0 MSG_processor_start -0xff002ee4 MSG_processor_exit -0xff002ee8 MSG_processor_info -0xff002eec MSG_processor_control -0xff002ef0 MSG_processor_assign -0xff002ef4 MSG_processor_get_assignment -0xff003200 MSG_mach_port_names -0xff003204 MSG_mach_port_type -0xff003208 MSG_mach_port_rename -0xff00320c MSG_mach_port_allocate_name -0xff003210 MSG_mach_port_allocate -0xff003214 MSG_mach_port_destroy -0xff003218 MSG_mach_port_deallocate -0xff00321c MSG_mach_port_get_refs -0xff003220 MSG_mach_port_mod_refs -0xff003228 MSG_mach_port_set_mscount -0xff00322c MSG_mach_port_get_set_status -0xff003230 MSG_mach_port_move_member -0xff003234 MSG_mach_port_request_notification -0xff003238 MSG_mach_port_insert_right -0xff00323c MSG_mach_port_extract_right -0xff003240 MSG_mach_port_set_seqno -0xff003244 MSG_mach_port_get_attributes -0xff003248 MSG_mach_port_set_attributes -0xff00324c MSG_mach_port_allocate_qos -0xff003250 MSG_mach_port_allocate_full -0xff003254 MSG_task_set_port_space -0xff003258 MSG_mach_port_get_srights -0xff00325c MSG_mach_port_space_info -0xff003260 MSG_mach_port_dnrequest_info -0xff003264 MSG_mach_port_kernel_object -0xff003268 MSG_mach_port_insert_member -0xff00326c MSG_mach_port_extract_member -0xff003520 MSG_task_create -0xff003524 MSG_task_terminate -0xff003528 MSG_task_threads -0xff00352c MSG_mach_ports_register -0xff003530 MSG_mach_ports_lookup -0xff003534 MSG_task_info -0xff003538 MSG_task_set_info -0xff00353c MSG_task_suspend -0xff003540 MSG_task_resume -0xff003544 MSG_task_get_special_port -0xff003548 MSG_task_set_special_port -0xff00354c MSG_thread_create -0xff003550 MSG_thread_create_running -0xff003554 MSG_task_set_exception_ports -0xff003558 MSG_task_get_exception_ports -0xff00355c MSG_task_swap_exception_ports -0xff003560 MSG_lock_set_create -0xff003564 MSG_lock_set_destroy -0xff003568 MSG_semaphore_create -0xff00356c MSG_semaphore_destroy -0xff003570 MSG_task_policy_set -0xff003574 MSG_task_policy_get -0xff003578 MSG_task_sample -0xff00357c MSG_task_policy -0xff003580 MSG_task_set_emulation -0xff003584 MSG_task_get_emulation_vector -0xff003588 MSG_task_set_emulation_vector -0xff00358c MSG_task_set_ras_pc -0xff003594 MSG_task_assign -0xff003598 MSG_task_assign_default -0xff00359c MSG_task_get_assignment -0xff0035a0 MSG_task_set_policy -0xff003840 MSG_thread_terminate -0xff003844 MSG_act_get_state -0xff003848 MSG_act_set_state -0xff00384c MSG_thread_get_state -0xff003850 MSG_thread_set_state -0xff003854 MSG_thread_suspend -0xff003858 MSG_thread_resume -0xff00385c MSG_thread_abort -0xff003860 MSG_thread_abort_safely -0xff003864 MSG_thread_depress_abort -0xff003868 MSG_thread_get_special_port -0xff00386c MSG_thread_set_special_port -0xff003870 MSG_thread_info -0xff003874 MSG_thread_set_exception_ports -0xff003878 MSG_thread_get_exception_ports -0xff00387c MSG_thread_swap_exception_ports -0xff003880 MSG_thread_policy -0xff003884 MSG_thread_policy_set -0xff003888 MSG_thread_policy_get -0xff00388c MSG_thread_sample -0xff003890 MSG_etap_trace_thread -0xff003894 MSG_thread_assign -0xff003898 MSG_thread_assign_default -0xff00389c MSG_thread_get_assignment -0xff0038a0 MSG_thread_set_policy -0xff003b60 MSG_vm_region -0xff003b64 MSG_vm_allocate -0xff003b68 MSG_vm_deallocate -0xff003b6c MSG_vm_protect -0xff003b70 MSG_vm_inherit -0xff003b74 MSG_vm_read -0xff003b78 MSG_vm_read_list -0xff003b7c MSG_vm_write -0xff003b80 MSG_vm_copy -0xff003b84 MSG_vm_read_overwrite -0xff003b88 MSG_vm_msync -0xff003b8c MSG_vm_behavior_set -0xff003b90 MSG_vm_map -0xff003b94 MSG_vm_machine_attribute -0xff003b98 MSG_vm_remap -0xff003b9c MSG_task_wire -0xff003ba0 MSG_mach_make_memory_entry -0xff003ba4 MSG_vm_map_page_query -0xff003ba8 MSG_mach_vm_region_info -0xff003bac MSG_vm_mapped_pages_info -0xff003bb4 MSG_vm_region_recurse -0xff003bb8 MSG_vm_region_recurse_64 -0xff003bbc MSG_mach_vm_region_info_64 -0xff003bc0 MSG_vm_region_64 -0xff003bc4 MSG_mach_make_memory_entry_64 -0xff003bc8 MSG_vm_map_64 -0xff003bcc MSG_vm_map_get_upl -0xff003bd8 MSG_vm_purgable_control -0xff003e80 MSG_processor_set_statistics -0xff003e84 MSG_processor_set_destroy -0xff003e88 MSG_processor_set_max_priority -0xff003e8c MSG_processor_set_policy_enable -0xff003e90 MSG_processor_set_policy_disable -0xff003e94 MSG_processor_set_tasks -0xff003e98 MSG_processor_set_threads -0xff003e9c MSG_processor_set_policy_control -0xff003ea0 MSG_processor_set_stack_usage -0xff003ea4 MSG_processor_set_info -0xff004b00 MSG_mach_vm_allocate -0xff004b04 MSG_mach_vm_deallocate -0xff004b08 MSG_mach_vm_protect -0xff004b0c MSG_mach_vm_inherit -0xff004b10 MSG_mach_vm_read -0xff004b14 MSG_mach_vm_read_list -0xff004b18 MSG_mach_vm_write -0xff004b1c MSG_mach_vm_copy -0xff004b20 MSG_mach_vm_read_overwrite -0xff004b24 MSG_mach_vm_msync -0xff004b28 MSG_mach_vm_behavior_set -0xff004b2c MSG_mach_vm_map -0xff004b30 MSG_mach_vm_machine_attribute -0xff004b34 MSG_mach_vm_remap -0xff004b38 MSG_mach_vm_page_query -0xff004b3c MSG_mach_vm_region_recurse -0xff004b40 MSG_mach_vm_region -0xff004b44 MSG__mach_make_memory_entry -0xff004b48 MSG__mach_vm_purgable_control -0xff004e20 MSG_ledger_create -0xff004e24 MSG_ledger_terminate -0xff004e28 MSG_ledger_transfer -0xff004e2c MSG_ledger_read -0xff005dc0 MSG_UNDExecute_rpc -0xff005dc4 MSG_UNDDisplayNoticeFromBundle_rpc -0xff005dc8 MSG_UNDDisplayAlertFromBundle_rpc -0xff005dcc MSG_UNDDisplayCustomFromBundle_rpc -0xff005dd0 MSG_UNDDisplayCustomFromDictionary_rpc -0xff005dd4 MSG_UNDCancelNotification_rpc -0xff005dd8 MSG_UNDDisplayNoticeSimple_rpc -0xff005ddc MSG_UNDDisplayAlertSimple_rpc -0xff0060e0 MSG_UNDAlertCompletedWithResult_rpc -0xff0060e4 MSG_UNDNotificationCreated_rpc -0xff25a8a0 MSG_lock_acquire -0xff25a8a4 MSG_lock_release -0xff25a8a8 MSG_lock_try -0xff25a8ac MSG_lock_make_stable -0xff25a8b0 MSG_lock_handoff -0xff25a8b4 MSG_lock_handoff_accept -0xff25abc0 MSG_semaphore_signal -0xff25abc4 MSG_semaphore_signal_all -0xff25abc8 MSG_semaphore_wait -0xff25abcc MSG_semaphore_signal_thread -0xff25abd0 MSG_semaphore_timedwait -0xff25abd4 MSG_semaphore_wait_signal -0xff25abd8 MSG_semaphore_timedwait_signal -0xffbebdcc MSG_clock_alarm_reply -0x1020000 KTrap_DivideError -0x1020004 KTrap_Debug -0x1020008 KTrap_NMI -0x102000c KTrap_Int3 -0x1020010 KTrap_Overflow -0x1020014 KTrap_BoundRange -0x1020018 KTrap_InvalidOpcode -0x102001c KTrap_DeviceNotAvail -0x1020020 KTrap_DoubleFault -0x1020024 KTrap_Coprocessor -0x1020028 KTrap_InvalidTSS -0x102002c KTrap_SegmentNotPresent -0x1020030 KTrap_StackFault -0x1020034 KTrap_GeneralProtection -0x1020038 KTrap_PageFault -0x102003c KTrap_unknown -0x1020040 KTrap_FloatPointError -0x1020044 KTrap_AlignmentCheck -0x1020048 KTrap_MachineCheck -0x102004c KTrap_SIMD_FP -0x10203fc KTrap_Preempt -0x1070000 UTrap_DivideError -0x1070004 UTrap_Debug -0x1070008 UTrap_NMI -0x107000c UTrap_Int3 -0x1070010 UTrap_Overflow -0x1070014 UTrap_BoundRange -0x1070018 UTrap_InvalidOpcode -0x107001c UTrap_DeviceNotAvail -0x1070020 UTrap_DoubleFault -0x1070024 UTrap_Coprocessor -0x1070028 UTrap_InvalidTSS -0x107002c UTrap_SegmentNotPresent -0x1070030 UTrap_StackFault -0x1070034 UTrap_GeneralProtection -0x1070038 UTrap_PageFault -0x107003c UTrap_unknown -0x1070040 UTrap_FloatPointError -0x1070044 UTrap_AlignmentCheck -0x1070048 UTrap_MachineCheck -0x107004c UTrap_SIMD_FP -0x1300004 MACH_Pageout -0x1300008 MACH_vmfault -0x1300100 MACH_purgable_token_add -0x1300104 MACH_purgable_token_delete -0x1300108 MACH_purgable_token_ripened -0x130010c MACH_purgable_token_purged -0x1400000 MACH_SCHED -0x1400004 MACH_STKATTACH -0x1400008 MACH_STKHANDOFF -0x140000c MACH_CALLCONT -0x1400010 MACH_CALLOUT -0x1400014 MACH_ServiceT -0x1400018 MACH_MKRUNNABLE -0x140001c MACH_PROMOTE -0x1400020 MACH_DEMOTE -0x1400024 MACH_IDLE -0x1500000 MACH_MSGID_INVALID -0x1090000 DecrTrap -0x1090004 DecrSet -0x1090008 TimerCallIntr -0x109000c pmsStep -0x1090010 clock_deadline -0x10c0000 MACH_SysCall -0x10c0004 MSC_kern_invalid_#1 -0x10c0008 MSC_kern_invalid_#2 -0x10c000c MSC_kern_invalid_#3 -0x10c0010 MSC_kern_invalid_#4 -0x10c0014 MSC_kern_invalid_#5 -0x10c0018 MSC_kern_invalid_#6 -0x10c001c MSC_kern_invalid_#7 -0x10c0020 MSC_kern_invalid_#8 -0x10c0024 MSC_kern_invalid_#9 -0x10c0028 MSC_kern_invalid_#10 -0x10c002c MSC_kern_invalid_#11 -0x10c0030 MSC_kern_invalid_#12 -0x10c0034 MSC_kern_invalid_#13 -0x10c0038 MSC_kern_invalid_#14 -0x10c003c MSC_kern_invalid_#15 -0x10c0040 MSC_kern_invalid_#16 -0x10c0044 MSC_kern_invalid_#17 -0x10c0048 MSC_kern_invalid_#18 -0x10c004c MSC_kern_invalid_#19 -0x10c0050 MSC_kern_invalid_#20 -0x10c0054 MSC_kern_invalid_#21 -0x10c0058 MSC_kern_invalid_#22 -0x10c005c MSC_kern_invalid_#23 -0x10c0060 MSC_kern_invalid_#24 -0x10c0064 MSC_kern_invalid_#25 -0x10c0068 MSC_mach_reply_port -0x10c006c MSC_thread_self_trap -0x10c0070 MSC_task_self_trap -0x10c0074 MSC_host_self_trap -0x10c0078 MSC_kern_invalid_#30 -0x10c007c MSC_mach_msg_trap -0x10c0080 MSC_mach_msg_overwrite_trap -0x10c0084 MSC_semaphore_signal_trap -0x10c0088 MSC_semaphore_signal_all_trap -0x10c008c MSC_semaphore_signal_thread_trap -0x10c0090 MSC_semaphore_wait_trap -0x10c0094 MSC_semaphore_wait_signal_trap -0x10c0098 MSC_semaphore_timedwait_trap -0x10c009c MSC_semaphore_timedwait_signal_trap -0x10c00a0 MSC_kern_invalid_#40 -0x10c00a4 MSC_init_process -0x10c00a8 MSC_kern_invalid_#42 -0x10c00ac MSC_map_fd -0x10c00b0 MSC_kern_invalid_#44 -0x10c00b4 MSC_task_for_pid -0x10c00b8 MSC_pid_for_task -0x10c00bc MSC_kern_invalid_#47 -0x10c00c0 MSC_macx_swapon -0x10c00c4 MSC_macx_swapoff -0x10c00c8 MSC_kern_invalid_#50 -0x10c00cc MSC_macx_triggers -0x10c00d0 MSC_kern_invalid_#52 -0x10c00d4 MSC_kern_invalid_#53 -0x10c00d8 MSC_kern_invalid_#54 -0x10c00dc MSC_kern_invalid_#55 -0x10c00e0 MSC_kern_invalid_#56 -0x10c00e4 MSC_kern_invalid_#57 -0x10c00e8 MSC_kern_invalid_#58 -0x10c00ec MSC_swtch_pri -0x10c00f0 MSC_swtch -0x10c00f4 MSC_thread_switch -0x10c00f8 MSC_clock_sleep_trap -0x10c00fc MSC_kern_invalid_#63 -0x10c0100 MSC_kern_invalid_#64 -0x10c0104 MSC_kern_invalid_#65 -0x10c0108 MSC_kern_invalid_#66 -0x10c010c MSC_kern_invalid_#67 -0x10c0110 MSC_kern_invalid_#68 -0x10c0114 MSC_kern_invalid_#69 -0x10c0118 MSC_kern_invalid_#70 -0x10c011c MSC_kern_invalid_#71 -0x10c0120 MSC_kern_invalid_#72 -0x10c0124 MSC_kern_invalid_#73 -0x10c0128 MSC_kern_invalid_#74 -0x10c012c MSC_kern_invalid_#75 -0x10c0130 MSC_kern_invalid_#76 -0x10c0134 MSC_kern_invalid_#77 -0x10c0138 MSC_kern_invalid_#78 -0x10c013c MSC_kern_invalid_#79 -0x10c0140 MSC_kern_invalid_#80 -0x10c0144 MSC_kern_invalid_#81 -0x10c0148 MSC_kern_invalid_#82 -0x10c014c MSC_kern_invalid_#83 -0x10c0150 MSC_kern_invalid_#84 -0x10c0154 MSC_kern_invalid_#85 -0x10c0158 MSC_kern_invalid_#86 -0x10c015c MSC_kern_invalid_#87 -0x10c0160 MSC_kern_invalid_#88 -0x10c0164 MSC_mach_timebase_info -0x10c0168 MSC_mach_wait_until -0x10c016c MSC_mk_timer_create -0x10c0170 MSC_mk_timer_destroy -0x10c0174 MSC_mk_timer_arm -0x10c0178 MSC_mk_timer_cancel -0x10c017c MSC_mk_timebase_info -0x10c0180 MSC_kern_invalid_#96 -0x10c0184 MSC_kern_invalid_#97 -0x10c0188 MSC_kern_invalid_#98 -0x10c018c MSC_kern_invalid_#99 -0x10c0190 MSC_audio_fast_trap -0x10c0194 MSC_kern_invalid_#101 -0x10c0198 MSC_kern_invalid_#102 -0x10c019c MSC_kern_invalid_#103 -0x10c01a0 MSC_kern_invalid_#104 -0x10c01a4 MSC_kern_invalid_#105 -0x10c01a8 MSC_kern_invalid_#106 -0x10c01ac MSC_kern_invalid_#107 -0x10c01b0 MSC_kern_invalid_#108 -0x10c01b4 MSC_kern_invalid_#109 -0x10c01b8 MSC_kern_invalid_#110 -0x10c01bc MSC_kern_invalid_#111 -0x10c01c0 MSC_kern_invalid_#112 -0x10c01c4 MSC_kern_invalid_#113 -0x10c01c8 MSC_kern_invalid_#114 -0x10c01cc MSC_kern_invalid_#115 -0x10c01d0 MSC_kern_invalid_#116 -0x10c01d4 MSC_kern_invalid_#117 -0x10c01d8 MSC_kern_invalid_#118 -0x10c01dc MSC_kern_invalid_#119 -0x10c01e0 MSC_kern_invalid_#120 -0x10c01e4 MSC_kern_invalid_#121 -0x10c01e8 MSC_kern_invalid_#122 -0x10c01ec MSC_kern_invalid_#123 -0x10c01f0 MSC_kern_invalid_#124 -0x10c01f4 MSC_kern_invalid_#125 -0x10c01f8 MSC_kern_invalid_#126 -0x10c01fc MSC_kern_invalid_#127 -0x1050000 INTERRUPT -0x3010090 VFS_LOOKUP -0x3020000 P_WrData -0x3020008 P_RdData -0x3020020 P_WrMeta -0x3020028 P_RdMeta -0x3020040 P_PgOut -0x3020048 P_PgIn -0x3020010 P_WrDataAsync -0x3020018 P_RdDataAsync -0x3020030 P_WrMetaAsync -0x3020038 P_RdMetaAsync -0x3020050 P_PgOutAsync -0x3020058 P_PgInAsync -0x3020004 P_WrDataDone -0x302000C P_RdDataDone -0x3020024 P_WrMetaDone -0x302002C P_RdMetaDone -0x3020044 P_PgOutDone -0x302004C P_PgInDone -0x3020014 P_WrDataAsyncDone -0x302001C P_RdDataAsyncDone -0x3020034 P_WrMetaAsyncDone -0x302003C P_RdMetaAsyncDone -0x3020054 P_PgOutAsyncDone -0x302005C P_PgInAsyncDone -0x3050004 journal_flush -0x4010004 proc_exit -0x4010008 force_exit -0x40c0000 BSC_SysCall -0x40c0004 BSC_exit -0x40c0008 BSC_fork -0x40c000c BSC_read -0x40c0010 BSC_write -0x40c0014 BSC_open -0x40c0018 BSC_close -0x40c001c BSC_wait4 -0x40c0020 BSC_obs_creat -0x40c0024 BSC_link -0x40c0028 BSC_unlink -0x40c002c BSC_obs_execv -0x40c0030 BSC_chdir -0x40c0034 BSC_fchdir -0x40c0038 BSC_mknod -0x40c003c BSC_chmod -0x40c0040 BSC_chown -0x40c0044 BSC_obs_break -0x40c0048 BSC_getfsstat -0x40c004c BSC_old_lseek -0x40c0050 BSC_getpid -0x40c0054 BSC_obs_mount -0x40c0058 BSC_obs_unmount -0x40c005c BSC_setuid -0x40c0060 BSC_getuid -0x40c0064 BSC_geteuid -0x40c0068 BSC_ptrace -0x40c006c BSC_recvmsg -0x40c0070 BSC_sendmsg -0x40c0074 BSC_recvfrom -0x40c0078 BSC_accept -0x40c007c BSC_getpeername -0x40c0080 BSC_getsockname -0x40c0084 BSC_access -0x40c0088 BSC_chflags -0x40c008c BSC_fchflags -0x40c0090 BSC_sync -0x40c0094 BSC_kill -0x40c0098 BSC_obs_stat -0x40c009c BSC_getppid -0x40c00a0 BSC_obs_lstat -0x40c00a4 BSC_dup -0x40c00a8 BSC_pipe -0x40c00ac BSC_getegid -0x40c00b0 BSC_profil -0x40c00b4 BSC_obs_ktrace -0x40c00b8 BSC_sigaction -0x40c00bc BSC_getgid -0x40c00c0 BSC_sigprocmask -0x40c00c4 BSC_getlogin -0x40c00c8 BSC_setlogin -0x40c00cc BSC_acct -0x40c00d0 BSC_sigpending -0x40c00d4 BSC_sigaltstack -0x40c00d8 BSC_ioctl -0x40c00dc BSC_reboot -0x40c00e0 BSC_revoke -0x40c00e4 BSC_symlink -0x40c00e8 BSC_readlink -0x40c00ec BSC_execve -0x40c00f0 BSC_umask -0x40c00f4 BSC_chroot -0x40c00f8 BSC_obs_fstat -0x40c00fc BSC_#63 -0x40c0100 BSC_obs_getpagesize -0x40c0104 BSC_msync -0x40e0104 BSC_msync_extended_info -0x40c0108 BSC_vfork -0x40c010c BSC_obs_vread -0x40c0110 BSC_obs_vwrite -0x40c0114 BSC_sbrk -0x40c0118 BSC_sstk -0x40c011c BSC_obs_mmap -0x40c0120 BSC_obs_vadvise -0x40c0124 BSC_munmap -0x40c0128 BSC_mprotect -0x40c012c BSC_madvise -0x40c0130 BSC_obs_vhangup -0x40c0134 BSC_obs_vlimit -0x40c0138 BSC_mincore -0x40c013c BSC_getgroups -0x40c0140 BSC_setgroups -0x40c0144 BSC_getpgrp -0x40c0148 BSC_setpgid -0x40c014c BSC_setitimer -0x40c0150 BSC_obs_wait -0x40c0154 BSC_swapon -0x40c0158 BSC_getitimer -0x40c015c BSC_obs_gethostname -0x40c0160 BSC_obs_sethostname -0x40c0164 BSC_getdtablesize -0x40c0168 BSC_dup2 -0x40c016c BSC_obs_getdopt -0x40c0170 BSC_fcntl -0x40c0174 BSC_select -0x40c0178 BSC_obs_setdopt -0x40c017c BSC_fsync -0x40c0180 BSC_setpriority -0x40c0184 BSC_socket -0x40c0188 BSC_connect -0x40c018c BSC_obs_accept -0x40c0190 BSC_getpriority -0x40c0194 BSC_obs_send -0x40c0198 BSC_obs_recv -0x40c019c BSC_obs_sigreturn -0x40c01a0 BSC_bind -0x40c01a4 BSC_setsockopt -0x40c01a8 BSC_listen -0x40c01ac BSC_obs_vtimes -0x40c01b0 BSC_obs_sigvec -0x40c01b4 BSC_obs_sigblock -0x40c01b8 BSC_obs_sigsetmask -0x40c01bc BSC_sigsuspend -0x40c01c0 BSC_obs_sigstack -0x40c01c4 BSC_obs_recvmsg -0x40c01c8 BSC_obs_sendmsg -0x40c01cc BSC_obs_vtrace -0x40c01d0 BSC_gettimeofday -0x40c01d4 BSC_getrusage -0x40c01d8 BSC_getsockopt -0x40c01dc BSC_obs_resuba -0x40c01e0 BSC_readv -0x40c01e4 BSC_writev -0x40c01e8 BSC_settimeofday -0x40c01ec BSC_fchown -0x40c01f0 BSC_fchmod -0x40c01f4 BSC_obs_recvfrom -0x40c01f8 BSC_setreuid -0x40c01fc BSC_setregid -0x40c0200 BSC_rename -0x40c0204 BSC_obs_truncate -0x40c0208 BSC_obs_ftruncate -0x40c020c BSC_flock -0x40c0210 BSC_mkfifo -0x40c0214 BSC_sendto -0x40c0218 BSC_shutdown -0x40c021c BSC_socketpair -0x40c0220 BSC_mkdir -0x40c0224 BSC_rmdir -0x40c0228 BSC_utimes -0x40c022c BSC_futimes -0x40c0230 BSC_adjtime -0x40c0234 BSC_obs_getpeername -0x40c0238 BSC_gethostuuid -0x40c023c BSC_obs_sethostid -0x40c0240 BSC_obs_getrlimit -0x40c0244 BSC_obs_setrlimit -0x40c0248 BSC_obs_killpg -0x40c024c BSC_setsid -0x40c0250 BSC_obs_setquota -0x40c0254 BSC_obs_qquota -0x40c0258 BSC_obs_getsockname -0x40c025c BSC_getpgid -0x40c0260 BSC_setprivexec -0x40c0264 BSC_pread -0x40e0264 BSC_pread_extended_info -0x40c0268 BSC_pwrite -0x40e0268 BSC_pwrite_extended_info -0x40c026c BSC_nfssvc -0x40c0270 BSC_obs_getdirentries -0x40c0274 BSC_statfs -0x40c0278 BSC_fstatfs -0x40c027c BSC_unmount -0x40c0280 BSC_obs_async_daemon -0x40c0284 BSC_getfh -0x40c0288 BSC_obs_getdomainname -0x40c028c BSC_obs_setdomainname -0x40c0290 BSC_#164 -0x40c0294 BSC_quotactl -0x40c0298 BSC_obs_exportfs -0x40c029c BSC_mount -0x40c02a0 BSC_obs_ustat -0x40c02a4 BSC_csops -0x40c02a8 BSC_obs_table -0x40c02ac BSC_obs_wait3 -0x40c02b0 BSC_obs_rpause -0x40c02b4 BSC_waitid -0x40c02b8 BSC_obs_getdents -0x40c02bc BSC_obs_gc_control -0x40c02c0 BSC_add_profil -0x40c02c4 BSC_#177 -0x40c02c8 BSC_#178 -0x40c02cc BSC_#179 -0x40c02d0 BSC_kdebug_trace -0x40c02d4 BSC_setgid -0x40c02d8 BSC_setegid -0x40c02dc BSC_seteuid -0x40c02e0 BSC_sigreturn -0x40c02e4 BSC_chud -0x40c02e8 BSC_#186 -0x40c02ec BSC_#187 -0x40c02f0 BSC_stat -0x40c02f4 BSC_fstat -0x40c02f8 BSC_lstat -0x40c02fc BSC_pathconf -0x40c0300 BSC_fpathconf -0x40c0304 BSC_#193 -0x40c0308 BSC_getrlimit -0x40c030c BSC_setrlimit -0x40c0310 BSC_getdirentries -0x40c0314 BSC_mmap -0x40e0314 BSC_mmap_extended_info -0x40f0314 BSC_mmap_extended_info2 -0x40c0318 BSC__syscall -0x40c031c BSC_lseek -0x40c0320 BSC_truncate -0x40c0324 BSC_ftruncate -0x40c0328 BSC___sysctl -0x40c032c BSC_mlock -0x40c0330 BSC_munlock -0x40c0334 BSC_undelete -0x40c0338 BSC_ATsocket -0x40c033c BSC_ATgetmsg -0x40c0340 BSC_ATputmsg -0x40c0344 BSC_ATPsndreq -0x40c0348 BSC_ATPsndrsp -0x40c034c BSC_ATPgetreq -0x40c0350 BSC_ATPgetrsp -0x40c0354 BSC_#213 -0x40c0358 BSC_kqueue_from_portset_np -0x40c035c BSC_kqueue_portset_np -0x40c0360 BSC_mkcomplex -0x40c0364 BSC_statv -0x40c0368 BSC_lstatv -0x40c036c BSC_fstatv -0x40c0370 BSC_getattrlist -0x40c0374 BSC_setattrlist -0x40c0378 BSC_getdirentriesattr -0x40c037c BSC_exchangedata -0x40c0380 BSC_224 -0x40c0384 BSC_searchfs -0x40c0388 BSC_delete_Carbon -0x40c038c BSC_copyfile -0x40c0390 BSC_#228 -0x40c0394 BSC_#229 -0x40c0398 BSC_poll -0x40c039c BSC_watchevent -0x40c03a0 BSC_waitevent -0x40c03a4 BSC_modwatch -0x40c03a8 BSC_getxattr -0x40c03ac BSC_fgetxattr -0x40c03b0 BSC_setxattr -0x40c03b4 BSC_fsetxattr -0x40c03b8 BSC_removexattr -0x40c03bc BSC_fremovexattr -0x40c03c0 BSC_listxattr -0x40c03c4 BSC_flistxattr -0x40c03c8 BSC_fsctl -0x40c03cc BSC_initgroups -0x40c03d0 BSC_posix_spawn -0x40c03d4 BSC_#245 -0x40c03d8 BSC_#246 -0x40c03dc BSC_nfsclnt -0x40c03e0 BSC_fhopen -0x40c03e4 BSC_#249 -0x40c03e8 BSC_minherit -0x40c03ec BSC_semsys -0x40c03f0 BSC_msgsys -0x40c03f4 BSC_shmsys -0x40c03f8 BSC_semctl -0x40c03fc BSC_semget -0x40c0400 BSC_semop -0x40c0404 BSC_#257 -0x40c0408 BSC_msgctl -0x40c040c BSC_msgget -0x40c0410 BSC_msgsnd -0x40c0414 BSC_msgrcv -0x40c0418 BSC_shmat -0x40c041c BSC_shmctl -0x40c0420 BSC_shmdt -0x40c0424 BSC_shmget -0x40c0428 BSC_shm_open -0x40c042c BSC_shm_unlink -0x40c0430 BSC_sem_open -0x40c0434 BSC_sem_close -0x40c0438 BSC_sem_unlink -0x40c043c BSC_sem_wait -0x40c0440 BSC_sem_trywait -0x40c0444 BSC_sem_post -0x40c0448 BSC_sem_getvalue -0x40c044c BSC_sem_init -0x40c0450 BSC_sem_destroy -0x40c0454 BSC_open_extended -0x40c0458 BSC_umask_extended -0x40c045c BSC_stat_extended -0x40c0460 BSC_lstat_extended -0x40c0464 BSC_fstat_extended -0x40c0468 BSC_chmod_extended -0x40c046c BSC_fchmod_extended -0x40c0470 BSC_access_extended -0x40c0474 BSC_settid -0x40c0478 BSC_gettid -0x40c047c BSC_setsgroups -0x40c0480 BSC_getsgroups -0x40c0484 BSC_setwgroups -0x40c0488 BSC_getwgroups -0x40c048c BSC_mkfifo_extended -0x40c0490 BSC_mkdir_extended -0x40c0494 BSC_identitysvc -0x40c0498 BSC_shared_region_chk_np -0x40c049c BSC_shared_region_map_np -0x40c04a0 BSC_obs_load_shared_file -0x40c04a4 BSC_obs_reset_shared_file -0x40c04a8 BSC_obs_new_system_shared_regions -0x40c04ac BSC_obs_shared_region_map_file_np -0x40c04b0 BSC_obs_shared_region_make_private_np -0x40c04b4 BSC_pthread_mutex_destroy -0x40c04b8 BSC_pthread_mutex_init -0x40c04bc BSC_pthread_mutex_lock -0x40c04c0 BSC_pthread_mutex_trylock -0x40c04c4 BSC_pthread_mutex_unlock -0x40c04c8 BSC_pthread_cond_init -0x40c04cc BSC_pthread_cond_destroy -0x40c04d0 BSC_pthread_cond_broadcast -0x40c04d4 BSC_pthread_cond_signal -0x40c04d8 BSC_getsid -0x40c04dc BSC_settid_with_pid -0x40c04e0 BSC_pthread_cond_timedwait -0x40c04e4 BSC_aio_fsync -0x40c04e8 BSC_aio_return -0x40c04ec BSC_aio_suspend -0x40c04f0 BSC_aio_cancel -0x40c04f4 BSC_aio_error -0x40c04f8 BSC_aio_read -0x40c04fc BSC_aio_write -0x40c0500 BSC_lio_listio -0x40c0504 BSC__pthread_cond_wait -0x40c0508 BSC_iopolicysys -0x40c050c BSC_#323 -0x40c0510 BSC_mlockall -0x40c0514 BSC_munlockall -0x40c0518 BSC_#326 -0x40c051c BSC_issetugid -0x40c0520 BSC_pthread_kill -0x40c0524 BSC_pthread_sigmask -0x40c0528 BSC_sigwait -0x40c052c BSC_disable_threadsignal -0x40c0530 BSC_pthread_markcancel -0x40c0534 BSC_pthread_canceled -0x40c0538 BSC_semwait_signal -0x40c053c BSC_obs_utrace -0x40c0540 BSC_proc_info -0x40c0544 BSC_sendfile -0x40c0548 BSC_stat64 -0x40c054c BSC_fstat64 -0x40c0550 BSC_lstat64 -0x40c0554 BSC_stat64_extended -0x40c0558 BSC_lstat64_extended -0x40c055c BSC_fstat64_extended -0x40c0560 BSC_getdirentries64 -0x40c0564 BSC_statfs64 -0x40c0568 BSC_fstatfs64 -0x40c056c BSC_getfsstat64 -0x40c0570 BSC_pthread_chdir -0x40c0574 BSC_pthread_fchdir -0x40c0578 BSC_audit -0x40c057c BSC_auditon -0x40c0580 BSC_#352 -0x40c0584 BSC_getauid -0x40c0588 BSC_setauid -0x40c058c BSC_getaudit -0x40c0590 BSC_setaudit -0x40c0594 BSC_getaudit_addr -0x40c0598 BSC_setaudit_addr -0x40c059c BSC_auditctl -0x40c05a0 BSC_bsdthread_create -0x40c05a4 BSC_bsdthread_terminate -0x40c05a8 BSC_kqueue -0x40c05ac BSC_kevent -0x40c05b0 BSC_lchown -0x40c05b4 BSC_stack_snapshot -0x40c05b8 BSC_bsdthread_register -0x40c05bc BSC_workq_open -0x40c05c0 BSC_workq_ops -0x40c05c4 BSC_#369 -0x40c05c8 BSC_#370 -0x40c05cc BSC_#371 -0x40c05d0 BSC_#372 -0x40c05d4 BSC_#373 -0x40c05d8 BSC_#374 -0x40c05dc BSC_#375 -0x40c05e0 BSC_#376 -0x40c05e4 BSC_#377 -0x40c05e8 BSC_#378 -0x40c05ec BSC_#379 -0x40c05f0 BSC_mac_execve -0x40c05f4 BSC_mac_syscall -0x40c05f8 BSC_mac_get_file -0x40c06fc BSC_mac_set_file -0x40c0600 BSC_mac_get_link -0x40c0604 BSC_mac_set_link -0x40c0608 BSC_mac_get_proc -0x40c060c BSC_mac_set_proc -0x40c0610 BSC_mac_get_fd -0x40c0614 BSC_mac_set_fd -0x40c0618 BSC_mac_get_pid -0x40c061c BSC_mac_get_lcid -0x40c0620 BSC_mac_get_lctx -0x40c0624 BSC_mac_set_lctx -0x40c0628 BSC_setlcid -0x40c062c BSC_getlcid -0x40c0630 BSC_read_nocancel -0x40c0634 BSC_write_nocancel -0x40c0638 BSC_open_nocancel -0x40c063c BSC_close_nocancel -0x40c0640 BSC_wait4_nocancel -0x40c0644 BSC_recvmsg_nocancel -0x40c0648 BSC_sendmsg_nocancel -0x40c064c BSC_recvfrom_nocancel -0x40c0650 BSC_accept_nocancel -0x40c0654 BSC_msync_nocancel -0x40c0658 BSC_fcntl_nocancel -0x40c065c BSC_select_nocancel -0x40c0660 BSC_fsync_nocancel -0x40c0664 BSC_connect_nocancel -0x40c0668 BSC_sigsuspend_nocancel -0x40c066c BSC_readv_nocancel -0x40c0670 BSC_writev_nocancel -0x40c0674 BSC_sendto_nocancel -0x40c0678 BSC_pread_nocancel -0x40c067c BSC_pwrite_nocancel -0x40c0680 BSC_waitid_nocancel -0x40c0684 BSC_poll_nocancel -0x40c0688 BSC_msgsnd_nocancel -0x40c068c BSC_msgrcv_nocancel -0x40c0690 BSC_sem_wait_nocancel -0x40c0694 BSC_aio_suspend_nocancel -0x40c0698 BSC_sigwait_nocancel -0x40c069c BSC_semwait_signal_nocancel -0x40c06a0 BSC_mac_mount -0x40c06a4 BSC_mac_get_mount -0x40c06a8 BSC_mac_getfsstat -0x5020004 IES_client -0x5020008 IES_latency -0x502000c IES_sema -0x5020010 IES_intctxt -0x5020018 IES_action -0x502001c IES_filter -0x5030004 TES_client -0x5030008 TES_latency -0x503000c TES_sema -0x5030010 TES_action -0x5040004 CQ_client -0x5040008 CQ_latency -0x504000c CQ_sema -0x5040010 CQ_psema -0x5040014 CQ_plock -0x5040018 CQ_action -0x5100004 PM_SetParent -0x5100008 PM_AddChild -0x510000c PM_RemoveChild -0x5100010 PM_CtrlDriver -0x5100014 PM_CtrlDrvrE1 -0x5100018 PM_CtrlDrvrE2 -0x510001c PM_CtrlDrvrE3 -0x5100020 PM_CtrlDrvrE4 -0x5100024 PM_IntDriver -0x5100028 PM_AckE1 -0x510002c PM_ChildAck -0x5100030 PM_DriverAck -0x5100034 PM_AckE2 -0x5100038 PM_AckE3 -0x510003c PM_AckE4 -0x5100040 PM_DrvrAckSPwr -0x5100044 PM_WillChange -0x5100048 PM_DidChange -0x510004c PM_ReqstDomain -0x5100050 PM_MakeUsable -0x5100054 PM_ChangeTo -0x5100058 PM_ChngeToPriv -0x510005c PM_SetAggrssvs -0x5100060 PM_CritclTemp -0x5100064 PM_OverrideOn -0x5100068 PM_OverrideOff -0x510006c PM_EnqueueErr -0x5100070 PM_CollapseQ -0x5100074 PM_ChangeDone -0x5100078 PM_CtrlDrvTrdy -0x510007c PM_IntDrvrTrdy -0x5100080 PM_StartAckTmr -0x5100084 PM_ParentChnge -0x5100088 PM_AmndPrnChng -0x510008c PM_DeviceChnge -0x5100090 PM_ReqDenied -0x5100094 PM_CtrlDrvrE45 -0x5100098 PM_PrgrmHrdwre -0x510009c PM_InfDrvrPre -0x51000a0 PM_InfDrvrPost -0x51000a4 PM_RemoveDrivr -0x51000a8 PM_IdlTimerPrd -0x51000ac PM_SystemWake -0x51000b0 PM_AckE5 -0x51000b4 PM_ClientAck -0x51000b8 PM_ClientTardy -0x51000bc PM_ClientCancl -0x51000c0 PM_ClientNotfy -0x51000c4 PM_AppNotify -0x5310004 CPUPM_PSTATE -0x5310008 CPUPM_IDLE_CSTATE -0x531000c CPUPM_IDLE_HALT -0x5310010 CPUPM_IDLE_LOOP -0x5310014 CPUPM_HPET_START -0x5310018 CPUPM_HPET_END -0x531001c CPUPM_HPET_INTR -0x5310020 CPUPM_PSTATE_HW -0x5310024 CPUPM_PSTATE_LIMIT -0x5310028 CPUPM_PSTATE_PARK -0x531002c CPUPM_PSTATE_START -0x5310030 CPUPM_PSTATE_PAUSE -0x5310034 CPUPM_PSTATE_RESUME -0x5310038 CPUPM_PSTATE_DOWN -0x531003c CPUPM_PSTATE_UP -0x5310040 CPUPM_PSTATE_NORM -0x5310044 CPUPM_PSTATE_FORCE -0x5310048 CPUPM_PSTATE_TIMEOUT -0x531004c CPUPM_PSTATE_SETTO -0x5310050 CPUPM_SET_DEADLINE -0x5310054 CPUPM_GET_DEADLINE -0x5310058 CPUPM_DEADLINE -0x531005c CPUPM_IDLE_SNOOP -0x5310060 CPUPM_IDLE_LATENCY -0x5310064 CPUPM_IDLE_WAKEUP -0x5310068 CPUPM_IDLE_SW_WAKEUP -0x531006c CPUPM_IDLE_SELECT -0x5310070 CPUPM_IDLE_SELECTED -0x5310074 CPUPM_IDLE_INTSKIP -0x5310078 CPUPM_IDLE_LOCK -0x531007c CPUPM_IDLE_UNLOCK -0x5310080 CPUPM_IDLE_NO_HPET -0x5310084 CPUPM_FI_UP -0x5310088 CPUPM_FI_UP_CPU -0x531008c CPUPM_FI_MP -0x5310090 CPUPM_FI_MP_CPU -0x5310094 CPUPM_FI_PAUSE -0x5310098 CPUPM_FI_RUN -0x531009c CPUPM_PROC_HALT -0x53100a0 CPUPM_TRACE_STOPPED -0x53100a4 CPUPM_HPET_INT_LOCK -0x53100a8 CPUPM_HPET_INT_UNLOCK -0x53100ac CPUPM_HPET_TRY_AGAIN -0x53100b0 CPUPM_HPET_SETDEADLINE -0x53100b4 CPUPM_LOCK_HELDBY -0x53100b8 CPUPM_HPET_DELTA -0x53100bc CPUPM_HPET_TOO_LATE -0x53100c0 CPUPM_HPET_NO_DEADLINE -0x53100c4 CPUPM_IDLE -0x53100c8 CPUPM_CORE_CHK_DEADLINE -0x53100cc CPUPM_SET_HPET_DEADLINE -0x53100d0 CPUPM_HPET_READ -0x53100d4 CPUPM_TIME_ADJUST -0x53100d8 CPUPM_IDLE_MWAIT -0x53100dc CPUPM_FI_SLAVE_IDLE -0x53100e0 CPUPM_FI_SLAVE_BLOCK -0x53100e4 CPUPM_FI_MAST_SIGNAL -0x53100e8 CPUPM_CORE_DEADLINE -0x53100ec CPUPM_IDLE_FAST -0x53100f0 CPUPM_IDLE_PAUSE -0x53100f4 CPUPM_IDLE_SHORT -0x53100f8 CPUPM_IDLE_NORMAL -0x53100fc CPUPM_IDLE_SPURIOUS -0x5310100 CPUPM_PSTATE_INFO -0x5310104 CPUPM_PSTATE_INFO_HW -0x5310108 CPUPM_PSTATE_FSM -0x531010c CPUPM_PSTATE_FSM_STEP -0x5310110 CPUPM_PSTATE_FSM_EVAL -0x5310114 CPUPM_PSTATE_FSM_MAP -0x5310118 CPUPM_CPUSTEP_STEP -0x531011c CPUPM_CPUSTEP_STEP_UP -0x5310120 CPUPM_CPUSTEP_STEP_DOWN -0x5310124 CPUPM_CPUSTEP_AVAIL -0x5310128 CPUPM_CPUSTEP_AVAIL_STEP -0x531012c CPUPM_CPUSTEP_AVAIL_CHNG -0x5310130 CPUPM_CPUSTEP_LOAD -0x5310134 CPUPM_CPUSTEP_START -0x5310138 CPUPM_CPUSTEP_STOP -0x531013c CPUPM_CPUSTEP_COPY -0x5310140 CPUPM_CPUSTEP_CLEAR -0x5310144 CPUPM_CPUSTEP_RUNCOUNT -0x5310148 CPUPM_CPUSTEP_WAKEUP -0x7000004 TRACE_DATA_NEWTHREAD -0x7010004 TRACE_STRING_NEWTHREAD -0x7010008 TRACE_STRING_EXEC -0x8000000 USER_TEST -0x8000004 USER_run -0x8000008 USER_join -0x800000c USER_create -0x8000010 USER_pthread_create -0x8000014 USER_pthread_exit -0x8000018 USER_pthread_join -0x800001c USER_pthread_run -0x8000020 USER_pthread_cleanup_push -0x8040000 USER_STOP -0x21800000 SMB_smbd_idle -0x21800004 SMB_syscall_opendir -0x21800008 SMB_syscall_readdir -0x2180000c SMB_syscall_seekdir -0x21800010 SMB_syscall_telldir -0x21800014 SMB_syscall_rewinddir -0x21800018 SMB_syscall_mkdir -0x2180001c SMB_syscall_rmdir -0x21800020 SMB_syscall_closedir -0x21800024 SMB_syscall_open -0x21800028 SMB_syscall_close -0x2180002c SMB_syscall_read -0x21800030 SMB_syscall_pread -0x21800034 SMB_syscall_write -0x21800038 SMB_syscall_pwrite -0x2180003c SMB_syscall_lseek -0x21800040 SMB_syscall_sendfile -0x21800044 SMB_syscall_rename -0x21800048 SMB_syscall_fsync -0x2180004c SMB_syscall_stat -0x21800050 SMB_syscall_fstat -0x21800054 SMB_syscall_lstat -0x21800058 SMB_syscall_unlink -0x2180005c SMB_syscall_chmod -0x21800060 SMB_syscall_fchmod -0x21800064 SMB_syscall_chown -0x21800068 SMB_syscall_fchown -0x2180006c SMB_syscall_chdir -0x21800070 SMB_syscall_getwd -0x21800074 SMB_syscall_utime -0x21800078 SMB_syscall_ftruncate -0x2180007c SMB_syscall_fcntl_lock -0x21800080 SMB_syscall_kernel_flock -0x21800084 SMB_syscall_fcntl_getlock -0x21800088 SMB_syscall_readlink -0x2180008c SMB_syscall_symlink -0x21800090 SMB_syscall_link -0x21800094 SMB_syscall_mknod -0x21800098 SMB_syscall_realpath -0x2180009c SMB_syscall_get_quota -0x218000a0 SMB_syscall_set_quota -0x218000a4 SMB_smbmkdir -0x218000a8 SMB_smbrmdir -0x218000ac SMB_smbopen -0x218000b0 SMB_smbcreate -0x218000b4 SMB_smbclose -0x218000b8 SMB_smbflush -0x218000bc SMB_smbunlink -0x218000c0 SMB_smbmv -0x218000c4 SMB_smbgetatr -0x218000c8 SMB_smbsetatr -0x218000cc SMB_smbread -0x218000d0 SMB_smbwrite -0x218000d4 SMB_smblock -0x218000d8 SMB_smbunlock -0x218000dc SMB_smbctemp -0x218000e0 SMB_smbmknew -0x218000e4 SMB_smbcheckpath -0x218000e8 SMB_smbexit -0x218000ec SMB_smblseek -0x218000f0 SMB_smblockread -0x218000f4 SMB_smbwriteunlock -0x218000f8 SMB_smbreadbraw -0x218000fc SMB_smbreadbmpx -0x21800100 SMB_smbreadbs -0x21800104 SMB_smbwritebraw -0x21800108 SMB_smbwritebmpx -0x2180010c SMB_smbwritebs -0x21800110 SMB_smbwritec -0x21800114 SMB_smbsetattre -0x21800118 SMB_smbgetattre -0x2180011c SMB_smblockingx -0x21800120 SMB_smbtrans -0x21800124 SMB_smbtranss -0x21800128 SMB_smbioctl -0x2180012c SMB_smbioctls -0x21800130 SMB_smbcopy -0x21800134 SMB_smbmove -0x21800138 SMB_smbecho -0x2180013c SMB_smbwriteclose -0x21800140 SMB_smbopenx -0x21800144 SMB_smbreadx -0x21800148 SMB_smbwritex -0x2180014c SMB_smbtrans2 -0x21800150 SMB_smbtranss2 -0x21800154 SMB_smbfindclose -0x21800158 SMB_smbfindnclose -0x2180015c SMB_smbtcon -0x21800160 SMB_smbtdis -0x21800164 SMB_smbnegprot -0x21800168 SMB_smbsesssetupx -0x2180016c SMB_smbulogoffx -0x21800170 SMB_smbtconx -0x21800174 SMB_smbdskattr -0x21800178 SMB_smbsearch -0x2180017c SMB_smbffirst -0x21800180 SMB_smbfunique -0x21800184 SMB_smbfclose -0x21800188 SMB_smbnttrans -0x2180018c SMB_smbnttranss -0x21800190 SMB_smbntcreatex -0x21800194 SMB_smbntcancel -0x21800198 SMB_smbntrename -0x2180019c SMB_smbsplopen -0x218001a0 SMB_smbsplwr -0x218001a4 SMB_smbsplclose -0x218001a8 SMB_smbsplretq -0x218001ac SMB_smbsends -0x218001b0 SMB_smbsendb -0x218001b4 SMB_smbfwdname -0x218001b8 SMB_smbcancelf -0x218001bc SMB_smbgetmac -0x218001c0 SMB_smbsendstrt -0x218001c4 SMB_smbsendend -0x218001c8 SMB_smbsendtxt -0x218001cc SMB_smbinvalid -0x218001d0 SMB_pathworks_setdir -0x218001d4 SMB_trans2_open -0x218001d8 SMB_trans2_findfirst -0x218001dc SMB_trans2_findnext -0x218001e0 SMB_trans2_qfsinfo -0x218001e4 SMB_trans2_setfsinfo -0x218001e8 SMB_trans2_qpathinfo -0x218001ec SMB_trans2_setpathinfo -0x218001f0 SMB_trans2_qfileinfo -0x218001f4 SMB_trans2_setfileinfo -0x218001f8 SMB_trans2_fsctl -0x218001fc SMB_trans2_ioctl -0x21800200 SMB_trans2_findnotifyfirst -0x21800204 SMB_trans2_findnotifynext -0x21800208 SMB_trans2_mkdir -0x2180020c SMB_trans2_session_setup -0x21800210 SMB_trans2_get_dfs_referral -0x21800214 SMB_trans2_report_dfs_inconsistancy -0x21800218 SMB_nt_transact_create -0x2180021c SMB_nt_transact_ioctl -0x21800220 SMB_nt_transact_set_security_desc -0x21800224 SMB_nt_transact_notify_change -0x21800228 SMB_nt_transact_rename -0x2180022c SMB_nt_transact_query_security_desc -0x21800230 SMB_nt_transact_get_user_quota -0x21800234 SMB_nt_transact_set_user_quota -0x21800238 SMB_get_nt_acl -0x2180023c SMB_fget_nt_acl -0x21800240 SMB_set_nt_acl -0x21800244 SMB_fset_nt_acl -0x21800248 SMB_chmod_acl -0x2180024c SMB_fchmod_acl -0x21800250 SMB_name_release -0x21800254 SMB_name_refresh -0x21800258 SMB_name_registration -0x2180025c SMB_node_status -0x21800260 SMB_name_query -0x21800264 SMB_host_announce -0x21800268 SMB_workgroup_announce -0x2180026c SMB_local_master_announce -0x21800270 SMB_master_browser_announce -0x21800274 SMB_lm_host_announce -0x21800278 SMB_get_backup_list -0x2180027c SMB_reset_browser -0x21800280 SMB_announce_request -0x21800284 SMB_lm_announce_request -0x21800288 SMB_domain_logon -0x2180028c SMB_sync_browse_lists -0x21800290 SMB_run_elections -0x21800294 SMB_election -0xb000000 AFP_asp_tcp_usr_send -0xb000004 AFP_asp_tcp_usr_send_after_Request -0xb000008 AFP_asp_tcp_usr_send_after_FindDSIReq -0xb00000c AFP_asp_tcp_usr_send_after_Reply -0xb000010 AFP_asp_tcp_slowtimo -0xb000014 AFP_asp_tcp_usr_control -0xb000018 AFP_asp_tcp_fasttimo -0xb000020 AFP_Send -0xb000024 AFP_Send_before_sosend -0xb000028 AFP_Send_after_sosend -0xb00002c AFP_Send_before_write -0xb000030 AFP_Send_after_write -0xb000040 AFP_Reply -0xb000044 AFP_Reply_rcvdAlready -0xb000048 AFP_Reply_before_RcvLock -0xb00004c AFP_Reply_fail_RcvLock -0xb000050 AFP_Reply_before_ReadDSIHdr -0xb000054 AFP_Reply_after_ReadDSIHdr -0xb000058 AFP_Reply_fail_ReadDSIHdr -0xb00005c AFP_Reply_after_FindDSIReqInfo -0xb000060 AFP_Reply_SetAFPCmd -0xb000064 AFP_Reply_before_ReadDSIPacket -0xb000068 AFP_Reply_setRcvdReplyLen -0xb000070 AFP_SendReply -0xb000080 AFP_CreateDSIHeader -0xb000084 AFP_CreateDSIHeader_after_GetReqID -0xb000090 AFP_Request -0xb0000a0 AFP_ReceiveLock -0xb0000b0 AFP_ReceiveWakeUp -0xb0000c0 AFP_ReceiveUnLock -0xb0000e0 AFP_SendLock -0xb0000e4 AFP_SendUnLock -0xb0000f0 AFP_SendQueueLock -0xb000100 AFP_SendQueueUnLock -0xb000110 AFP_ReadDSIHeader -0xb000120 AFP_Receive -0xb000124 AFP_Receive_before_sorcv -0xb000128 AFP_Receive_after_sorcv -0xb000130 AFP_ReadDSIPacket -0xb000140 AFP_DoCopyOut -0xb000150 AFP_DoCopyIn -0xb000160 AFP_CheckRcvTickle -0xb000164 AFP_CheckRcvTickleTO -0xb000170 AFP_CheckSendTickle -0xb000180 AFP_CheckIncomingPkts -0xb000190 AFP_ProcessOptions -0xb000200 AFP_FindDSIReqInfo -0xb000204 AFP_FindDSIReqInfo_foundReqInfo -0xb000208 AFP_FindDSIReqInfo_flags -0xb00020c AFP_FindDSIReqLeave -0xb000210 AFP_UsrDisconnect -0xc000000 AFPVFS_UserReply -0xc000004 AFPVFS_UserReplyGetMbuf -0xc000008 AFPVFS_UserReplysosend -0xc000010 AFPVFS_UserCommand -0xc000018 AFPVFS_UserCommandsosend -0xc000020 AFPVFS_ReadFork -0xc000024 AFPVFS_ReadForkFillQPB -0xc000028 AFPVFS_ReadForkNbrRequests -0xc00002c AFPVFS_ReadForkSendQPB -0xc000030 AFPVFS_ReadForkSendErr -0xc000040 AFPVFS_ReadForkGetReply -0xc000044 AFPVFS_ReadForkGetReplyResult -0xc000050 AFPVFS_WriteFork -0xc000054 AFPVFS_WriteForkFillQPB -0xc000058 AFPVFS_WriteForkNbrRequests -0xc00005c AFPVFS_WriteForkSendQPB -0xc000060 AFPVFS_WriteForkSendErr -0xc000064 AFPVFS_WriteForkGetReply -0xc000068 AFPVFS_WriteForkGetReplyResult -0xc000070 AFPVFS_GetAttr -0xc000080 AFPVFS_SetAttr -0xc000090 AFPVFS_GetAttrList -0xc0000a0 AFPVFS_SetAttrList -0xc0000b0 AFPVFS_FSCTL -0xc0000c0 AFPVFS_LookUp -0xc0000d0 AFPVFS_CacheLookUp -0xc0000e0 AFPVFS_Write -0xc0000e4 AFPVFS_WriteNoCluster -0xc0000e8 AFPVFS_WriteDone -0xc0000f0 AFPVFS_DoWrite -0xc000100 AFPVFS_Lock -0xc000110 AFPVFS_Statfs -0xc000120 AFPVFS_Sync -0xc000130 AFPVFS_VGet -0xc000140 AFPVFS_FlushFiles -0xc000150 AFPVFS_Create -0xc000160 AFPVFS_Mknod -0xc000170 AFPVFS_Open -0xc000180 AFPVFS_Close -0xc000190 AFPVFS_Access -0xc000194 AFPVFS_AccessUID -0xc000198 AFPVFS_AccessGID -0xc00019c AFPVFS_AccessWID -0xc0001a0 AFPVFS_Writeperm -0xc0001b0 AFPVFS_Chmod -0xc0001c0 AFPVFS_Chflags -0xc0001d0 AFPVFS_Exchange -0xc0001e0 AFPVFS_Chid -0xc0001f0 AFPVFS_Fsync -0xc000200 AFPVFS_Remove -0xc000210 AFPVFS_Rename -0xc000220 AFPVFS_Copyfile -0xc000230 AFPVFS_Mkdir -0xc000230 AFPVFS_Rmdir -0xc000240 AFPVFS_Symlink -0xc000250 AFPVFS_Readdir -0xc000260 AFPVFS_Readdirattr -0xc000264 AFPVFS_Readdirattr1 -0xc000268 AFPVFS_Readdirattr2 -0xc00026c AFPVFS_Readdirattr3 -0xc000270 AFPVFS_Readlink -0xc000280 AFPVFS_Abortop -0xc000290 AFPVFS_Inactive -0xc0002a0 AFPVFS_Reclaim -0xc0002b0 AFPVFS_Unlock -0xc0002c0 AFPVFS_Islocked -0xc0002d0 AFPVFS_Pathconf -0xc0002e0 AFPVFS_Update -0xc0002e0 AFPVFS_Vinit -0xc0002f0 AFPVFS_Makenode -0xc000300 AFPVFS_Allocate -0xc000310 AFPVFS_Search -0xc000320 AFPVFS_Reconnect -0x14200000 TRACE_LAST_WRAPPER diff --git a/shutdown.tproj/Makefile b/shutdown.tproj/Makefile index b21ef26..c5fc276 100644 --- a/shutdown.tproj/Makefile +++ b/shutdown.tproj/Makefile @@ -6,7 +6,7 @@ CFILES = shutdown.c USERDEFS = kextmanager.defs MANPAGES = shutdown.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip Extra_Frameworks = -framework IOKit diff --git a/sync.tproj/Makefile b/sync.tproj/Makefile index 502fbde..894c3e6 100644 --- a/sync.tproj/Makefile +++ b/sync.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /bin CFILES = sync.c MANPAGES = sync.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_CC_Flags += -D__FBSDID=__RCSID Extra_LD_Flags = -dead_strip diff --git a/sysctl.tproj/Makefile b/sysctl.tproj/Makefile index 9c01459..3dac095 100644 --- a/sysctl.tproj/Makefile +++ b/sysctl.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = sysctl.c MANPAGES = sysctl.8 sysctl.conf.5 -Extra_CC_Flags = -mdynamic-no-pic -Wall -Werror +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/sysctl.tproj/sysctl.c b/sysctl.tproj/sysctl.c index c649826..3b16137 100644 --- a/sysctl.tproj/sysctl.c +++ b/sysctl.tproj/sysctl.c @@ -1,23 +1,22 @@ -/* - * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved. + /* + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -33,10 +32,6 @@ * 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 the University of - * California, Berkeley and its contributors. * 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. @@ -157,7 +152,7 @@ struct list secondlevel[] = { { username, USER_MAXID }, /* CTL_USER_NAMES */ }; -static int Aflag, aflag, bflag, nflag, wflag, Xflag; +static int Aflag, aflag, bflag, hflag, nflag, wflag, Xflag; static int foundSome = 0; static int invalid_name_used = 0; @@ -195,6 +190,7 @@ main(argc, argv) case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'b': bflag = 1; break; + case 'h': hflag = 1; break; case 'n': nflag = 1; break; case 'w': wflag = 1; break; case 'X': Xflag = Aflag = 1; break; @@ -745,8 +741,13 @@ parse(char *string, int flags) return; } + /* + * An non-zero return here is an OID space containing parameters which + * needs to be ignored in the interests of backward compatibility with + * pre-newsysctl sysctls. + */ if (oidfmt(mib, len, fmt, &kind)) - err(1, "couldn't find format of oid '%s'", bufp); + return; if (!wflag) { if ((kind & CTLTYPE) == CTLTYPE_NODE) { @@ -772,7 +773,7 @@ parse(char *string, int flags) if ((uintval == 0) && (errno == EINVAL)) { errx(1, "invalid argument: %s", - newval); + (char *)newval); return; } newval = &uintval; @@ -782,7 +783,7 @@ parse(char *string, int flags) if ((intval == 0) && (errno == EINVAL)) { errx(1, "invalid argument: %s", - newval); + (char *)newval); return; } newval = &intval; @@ -794,11 +795,11 @@ parse(char *string, int flags) case CTLTYPE_QUAD: quadval = strtoq(newval, NULL, 0); if ((quadval == 0) && (errno == EINVAL)) { - errx(1, "invalid argument %s", newval); + errx(1, "invalid argument %s", (char *)newval); return; } newval = &quadval; - newsize = sizeof quadval; + newsize = sizeof(quadval); break; default: errx(1, "oid '%s' is type %d," @@ -842,9 +843,13 @@ static int S_clockinfo(int l2, void *p) { struct clockinfo *ci = (struct clockinfo*)p; - if (l2 != sizeof *ci) - err(1, "S_clockinfo %d != %d", l2, sizeof *ci); - printf("{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }", + + if (l2 != sizeof(*ci)) { + warnx("S_clockinfo %d != %ld", l2, sizeof(*ci)); + return (1); + } + printf(hflag ? "{ hz = %'d, tick = %'d, tickadj = %'d, profhz = %'d, stathz = %'d }" : + "{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }", ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz); return (0); } @@ -854,10 +859,11 @@ S_loadavg(int l2, void *p) { struct loadavg *tv = (struct loadavg*)p; - if (l2 != sizeof *tv) - err(1, "S_loadavg %d != %d", l2, sizeof *tv); - - printf("{ %.2f %.2f %.2f }", + if (l2 != sizeof(*tv)) { + warnx("S_loadavg %d != %ld", l2, sizeof(*tv)); + return (1); + } + printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }", (double)tv->ldavg[0]/(double)tv->fscale, (double)tv->ldavg[1]/(double)tv->fscale, (double)tv->ldavg[2]/(double)tv->fscale); @@ -871,42 +877,50 @@ S_timeval(int l2, void *p) time_t tv_sec; char *p1, *p2; - if (l2 != sizeof *tv) - err(1, "S_timeval %d != %d", l2, sizeof *tv); - printf("{ sec = %ld, usec = %ld } ", - (long) tv->tv_sec, (long) tv->tv_usec); + if (l2 != sizeof(*tv)) { + warnx("S_timeval %d != %ld", l2, sizeof(*tv)); + return (1); + } + printf(hflag ? "{ sec = %'jd, usec = %'ld } " : + "{ sec = %jd, usec = %ld } ", + (intmax_t)tv->tv_sec, (long)tv->tv_usec); tv_sec = tv->tv_sec; p1 = strdup(ctime(&tv_sec)); for (p2=p1; *p2 ; p2++) if (*p2 == '\n') *p2 = '\0'; fputs(p1, stdout); + free(p1); return (0); } static int S_xswusage(int l2, void *p) { - struct xsw_usage *xsu = (struct xsw_usage *)p; + struct xsw_usage *xsu = (struct xsw_usage *)p; - if(l2 != sizeof (*xsu)) - err(1, "S_xswusage %d != %d", l2, sizeof *xsu); - + if (l2 != sizeof(*xsu)) { + warnx("S_xswusage %d != %ld", l2, sizeof(*xsu)); + return (1); + } fprintf(stdout, "total = %.2fM used = %.2fM free = %.2fM %s", - ((double) xsu->xsu_total) / (1024.0 * 1024.0), - ((double) xsu->xsu_used) / (1024.0 * 1024.0), - ((double) xsu->xsu_avail) / (1024.0 * 1024.0), + ((double)xsu->xsu_total) / (1024.0 * 1024.0), + ((double)xsu->xsu_used) / (1024.0 * 1024.0), + ((double)xsu->xsu_avail) / (1024.0 * 1024.0), xsu->xsu_encrypted ? "(encrypted)" : ""); - return 0; + return (0); } static int T_dev_t(int l2, void *p) { dev_t *d = (dev_t *)p; - if (l2 != sizeof *d) - err(1, "T_dev_T %d != %d", l2, sizeof *d); + + if (l2 != sizeof(*d)) { + warnx("T_dev_T %d != %ld", l2, sizeof(*d)); + return (1); + } if ((int)(*d) != -1) { if (minor(*d) > 255 || minor(*d) < 0) printf("{ major = %d, minor = 0x%x }", @@ -957,17 +971,27 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) qoid[1] = 4; memcpy(qoid + 2, oid, len * sizeof(int)); - j = sizeof buf; + j = sizeof(buf); i = sysctl(qoid, len + 2, buf, &j, 0, 0); - if (i) - err(1, "sysctl fmt %d %d %d", i, j, errno); + if (i) { + /* + * An ENOENT error return indicates that the OID in question + * is a node OID followed not by additional OID elements, but + * by integer parameters. We really do not want to support + * this type of thing going forward, but we alow it here for + * historical compatibility. Eventually, this will go away. + */ + if (errno == ENOENT) + return ENOENT; + err(1, "sysctl fmt %d %ld %d", i, j, errno); + } if (kind) *kind = *(u_int *)buf; if (fmt) strcpy(fmt, (char *)(buf + sizeof(u_int))); - return 0; + return (0); } /* @@ -997,7 +1021,7 @@ show_var(int *oid, int nlen, int show_masked) j = sizeof name; i = sysctl(qoid, nlen + 2, name, &j, 0, 0); if (i || !j) - err(1, "sysctl name %d %d %d", i, j, errno); + err(1, "sysctl name %d %ld %d", i, j, errno); /* find an estimate of how much we need for this var */ j = 0; @@ -1021,8 +1045,20 @@ show_var(int *oid, int nlen, int show_masked) qoid[1] = 4; j = sizeof buf; i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); + /* + * An ENOENT error return indicates that the OID in question + * is a node OID followed not by additional OID elements, but + * by integer parameters. We really do not want to support + * this type of thing going forward, but we alow it here for + * historical compatibility. Eventially, this will go away. + */ + if (i && errno == ENOENT) { + retval = 1; + goto RETURN; + } + if (i || !j) - err(1, "sysctl fmt %d %d %d", i, j, errno); + err(1, "sysctl fmt %d %ld %d", i, j, errno); kind = *(u_int *)buf; if (!show_masked && (kind & CTLFLAG_MASKED)) { @@ -1170,7 +1206,7 @@ sysctl_all (int *oid, int len) if (errno == ENOENT) return 0; else - err(1, "sysctl(getnext) %d %d", j, l2); + err(1, "sysctl(getnext) %d %ld", j, l2); } l2 /= sizeof (int); diff --git a/trace.tproj/Makefile b/trace.tproj/Makefile new file mode 100644 index 0000000..dc51126 --- /dev/null +++ b/trace.tproj/Makefile @@ -0,0 +1,14 @@ +Project = trace +Install_Dir = /usr/bin + +CFILES = trace.c +MANPAGES = trace.1 + +Extra_CC_Flags = +Extra_LD_Flags = -dead_strip + +Extra_CC_Flags += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\ + -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd +Extra_LD_Flags += -lutil + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/trace.tproj/trace.1 b/trace.tproj/trace.1 new file mode 100644 index 0000000..9cc4cc8 --- /dev/null +++ b/trace.tproj/trace.1 @@ -0,0 +1,60 @@ +.\" Copyright (c) 2010, Apple Inc. All rights reserved. +.\" +.Dd October 28, 2010 +.Dt TRACE 1 +.Os "Mac OS X" +.Sh NAME +.Nm trace +.Nd configure and record kernel trace events +.Sh SYNOPSIS +.Nm trace +.Fl h +.Pp +.Nm trace +.Fl i +.Op Fl b Ar numbufs +.Pp +.Nm trace +.Fl g +.Pp +.Nm trace +.Fl d +.Op Fl a Ar pid | Fl x Ar pid +.Pp +.Nm trace +.Fl r +.Pp +.Nm trace +.Fl n +.Pp +.Nm trace +.Fl e +.Op Fl c Ar class Oo Fl p Ar class Oc Oo Fl s Ar subclass Oc +.Op Fl a Ar pid | Fl x Ar pid +.Op Fl k Ar code | Fl k Ar code | Fl k Ar code | Fl k Ar code +.Pp +.Nm trace +.Fl E +.Op Fl c Ar class Oo Fl p Ar class Oc Oo Fl s Ar subclass Oc +.Op Fl a Ar pid | Fl x Ar pid +.Op Fl k Ar code | Fl k Ar code | Fl k Ar code | Fl k Ar code +.Ar executable_path +.Op Ar optional args to executable +.Pp +.Nm trace +.Fl t +.Op Fl R Ar rawfile +.Op Fl o Ar OutputFilename +.Op Ar CodeFilename +.Sh DESCRIPTION +The +.Nm trace +command allows developers to initialize and configure +the kernel trace subsystem. Trace events can be recorded +to an in-memory buffer, or logged directly to a file. Raw +data files can later be decoded to a plaintext format. +.Sh SEE ALSO +.Xr fs_usage 1 , +.Xr sc_usage 1 , +.Xr latency 1 , +.Xr top 1 diff --git a/trace.tproj/trace.c b/trace.tproj/trace.c new file mode 100644 index 0000000..e884179 --- /dev/null +++ b/trace.tproj/trace.c @@ -0,0 +1,2240 @@ +/* + cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -arch x86_64 -arch i386 -O -o trace trace.c +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + + +int nbufs = 0; +int enable_flag=0; +int execute_flag=0; +int logRAW_flag=0; +int LogRAW_flag=0; +int readRAW_flag = 0; +int disable_flag=0; +int init_flag=0; +int kval_flag=0; +int remove_flag=0; +int bufset_flag=0; +int bufget_flag=0; +int class_flag=0; +int subclass_flag=0; +int trace_flag=0; +int nowrap_flag=0; +int freerun_flag=0; +int verbose_flag=0; +int pid_flag=0; +int pid_exflag=0; +int ppt_flag=0; +unsigned int class=0; +unsigned int class2=0; +unsigned int subclass=0; +unsigned int value1=0; +unsigned int value2=0; +unsigned int value3=0; +unsigned int value4=0; +pid_t pid=0; +int reenable=0; + +int mib[6]; +size_t needed; + +char *logfile = (char *)0; /* This file is trace format */ +char *RAW_file = (char *)0; +FILE *output_file; +int output_fd; + +extern char **environ; + + +#define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END) +#define DBG_FUNC_MASK 0xfffffffc +#define SHORT_HELP 1 +#define LONG_HELP 0 + +#define CSC_MASK 0xffff0000 + +#define VFS_LOOKUP 0x03010090 +#define BSC_exit 0x040c0004 +#define BSC_thread_terminate 0x040c05a4 +#define TRACE_DATA_NEWTHREAD 0x07000004 +#define TRACE_STRING_NEWTHREAD 0x07010004 +#define TRACE_STRING_EXEC 0x07010008 +#define TRACE_LOST_EVENTS 0x07020008 +#define MACH_SCHEDULED 0x01400000 +#define MACH_MAKERUNNABLE 0x01400018 +#define MACH_STKHANDOFF 0x01400008 + +#define EMPTYSTRING "" +#define UNKNOWN "unknown" + +char tmpcommand[MAXCOMLEN]; + +int total_threads = 0; +int nthreads = 0; +kd_threadmap *mapptr = 0; + +/* + If NUMPARMS changes from the kernel, + then PATHLENGTH will also reflect the change + This is for the vfslookup entries that + return pathnames +*/ +#define NUMPARMS 23 +#define PATHLENGTH (NUMPARMS*sizeof(long)) + + +#define US_TO_SLEEP 50000 +#define BASE_EVENTS 500000 + + +double divisor; + +typedef struct { + uint32_t debugid; + char *debug_string; +} code_type_t; + +code_type_t * codesc = 0; + + +typedef struct event *event_t; + +struct event { + event_t ev_next; + + uintptr_t ev_thread; + uint32_t ev_debugid; + uint64_t ev_timestamp; +}; + +typedef struct lookup *lookup_t; + +struct lookup { + lookup_t lk_next; + + uintptr_t lk_thread; + uintptr_t lk_dvp; + long *lk_pathptr; + long lk_pathname[NUMPARMS + 1]; +}; + +typedef struct threadmap *threadmap_t; + +struct threadmap { + threadmap_t tm_next; + + uintptr_t tm_thread; + uintptr_t tm_pthread; + boolean_t tm_deleteme; + char tm_command[MAXCOMLEN + 1]; +}; + + +#define HASH_SIZE 1024 +#define HASH_MASK 1023 + +event_t event_hash[HASH_SIZE]; +lookup_t lookup_hash[HASH_SIZE]; +threadmap_t threadmap_hash[HASH_SIZE]; + +event_t event_freelist; +lookup_t lookup_freelist; +threadmap_t threadmap_freelist; +threadmap_t threadmap_temp; + + +#define SBUFFER_SIZE (128 * 4096) +char sbuffer[SBUFFER_SIZE]; + +int secs_to_run = 0; + + +kbufinfo_t bufinfo = {0, 0, 0, 0}; + +int codenum = 0; +int codeindx_cache = 0; +char codefile[] = "codes"; +char *cfile = (char *)0; + +// Forward declarations +static void quit(char *); +static int match_debugid(unsigned int, char *, int *); +static void usage(int short_help); +static int argtoi(int flag, char *req, char *str, int base); +static int parse_codefile(char *filename); +static int read_command_map(int, int); +static void find_thread_command(kd_buf *, char **); +static void create_map_entry(uintptr_t, char *); +static void getdivisor(); +static unsigned long argtoul(); + + +#ifndef KERN_KDWRITETR +#define KERN_KDWRITETR 17 +#endif + +#ifndef KERN_KDWRITEMAP +#define KERN_KDWRITEMAP 18 +#endif + +#ifndef F_FLUSH_DATA +#define F_FLUSH_DATA 40 +#endif + +#ifndef RAW_VERSION1 +typedef struct { + int version_no; + int thread_count; + uint64_t TOD_secs; + uint32_t TOD_usecs; +} RAW_header; + +#define RAW_VERSION0 0x55aa0000 +#define RAW_VERSION1 0x55aa0101 +#endif + + +RAW_header raw_header; + + + +void set_enable(int val) +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDENABLE; +#ifdef KDEBUG_ENABLE_PPT + if (ppt_flag && val) { + mib[3] = KDEBUG_ENABLE_PPT; + } else { + mib[3] = val; + } +#else + mib[3] = val; +#endif + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDENABLE\n"); +} + +void set_remove() +{ + extern int errno; + + errno = 0; + + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDREMOVE; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) + { + if (errno == EBUSY) + quit("the trace facility is currently in use...\n fs_usage, sc_usage, trace, and latency use this feature.\n\n"); + else + quit("trace facility failure, KERN_KDREMOVE\n"); + } +} + +void set_numbufs(int nbufs) +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETBUF; + mib[3] = nbufs; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETBUF\n"); + + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETUP; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETUP\n"); +} + +void set_nowrap() +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDEFLAGS; + mib[3] = KDBG_NOWRAP; + mib[4] = 0; + mib[5] = 0; /* no flags */ + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + quit("trace facility failure, KDBG_NOWRAP\n"); + +} + +void set_pidcheck(int pid, int on_off_flag) +{ + kd_regtype kr; + + kr.type = KDBG_TYPENONE; + kr.value1 = pid; + kr.value2 = on_off_flag; + needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDPIDTR; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) + { + if (on_off_flag == 1) + { + printf("trace facility failure, KERN_KDPIDTR,\n\tpid %d does not exist\n", pid); + set_remove(); + exit(2); + } + } +} + +void set_pidexclude(int pid, int on_off_flag) +{ + kd_regtype kr; + + kr.type = KDBG_TYPENONE; + kr.value1 = pid; + kr.value2 = on_off_flag; + needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDPIDEX; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) + { + if (on_off_flag == 1) + { + printf ("pid %d does not exist\n", pid); + set_remove(); + exit(2); + } + } +} + +void set_freerun() +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDEFLAGS; + mib[3] = KDBG_FREERUN; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + quit("trace facility failure, KDBG_FREERUN\n"); +} + +void get_bufinfo(kbufinfo_t *val) +{ + needed = sizeof (*val); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDGETBUF; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, val, &needed, 0, 0) < 0) + quit("trace facility failure, KERN_KDGETBUF\n"); +} + +void set_init() +{ + kd_regtype kr; + + kr.type = KDBG_RANGETYPE; + kr.value1 = 0; + kr.value2 = -1; + needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETREG; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETREG (rangetype)\n"); + + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETUP; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETUP\n"); +} + + +void set_class() +{ + kd_regtype kr; + + kr.type = KDBG_CLASSTYPE; + kr.value1 = class; + kr.value2 = class2; + needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETREG; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETREG (classtype)\n"); +} + +void set_kval_list() +{ + kd_regtype kr; + + kr.type = KDBG_VALCHECK; + kr.value1 = value1; + kr.value2 = value2; + kr.value3 = value3; + kr.value4 = value4; + needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETREG; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETREG (valcheck)\n"); +} + +void set_subclass() +{ + kd_regtype kr; + + kr.type = KDBG_SUBCLSTYPE; + kr.value1 = class; + kr.value2 = subclass; + needed = sizeof(kd_regtype); + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDSETREG; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDSETREG (subclstype)\n"); +} + + +void readtrace(char *buffer) +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDREADTR; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + + if (sysctl(mib, 3, buffer, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDREADTR\n"); +} + + +int writetrace(int fd) +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDWRITETR; + mib[3] = fd; + mib[4] = 0; + mib[5] = 0; + + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + return 1; + + return 0; +} + + +int write_command_map(int fd) +{ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDWRITEMAP; + mib[3] = fd; + mib[4] = 0; + mib[5] = 0; + + if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0) + return 1; + + return 0; +} + + +static +lookup_t handle_lookup_event(uintptr_t thread, int debugid, kd_buf *kdp) +{ + lookup_t lkp; + int hashid; + boolean_t first_record = FALSE; + + hashid = thread & HASH_MASK; + + if (debugid & DBG_FUNC_START) + first_record = TRUE; + + for (lkp = lookup_hash[hashid]; lkp; lkp = lkp->lk_next) { + if (lkp->lk_thread == thread) + break; + } + if (lkp == NULL) { + if (first_record == FALSE) + return (0); + + if ((lkp = lookup_freelist)) + lookup_freelist = lkp->lk_next; + else + lkp = (lookup_t)malloc(sizeof(struct lookup)); + + lkp->lk_thread = thread; + + lkp->lk_next = lookup_hash[hashid]; + lookup_hash[hashid] = lkp; + } + + if (first_record == TRUE) { + lkp->lk_pathptr = lkp->lk_pathname; + lkp->lk_dvp = kdp->arg1; + } else { + if (lkp->lk_pathptr > &lkp->lk_pathname[NUMPARMS-4]) + return (lkp); + + *lkp->lk_pathptr++ = kdp->arg1; + } + *lkp->lk_pathptr++ = kdp->arg2; + *lkp->lk_pathptr++ = kdp->arg3; + *lkp->lk_pathptr++ = kdp->arg4; + *lkp->lk_pathptr = 0; + + return (lkp); +} + + +static +void delete_lookup_event(uintptr_t thread, lookup_t lkp_to_delete) +{ + lookup_t lkp; + lookup_t lkp_prev; + int hashid; + + hashid = thread & HASH_MASK; + + if ((lkp = lookup_hash[hashid])) { + if (lkp == lkp_to_delete) + lookup_hash[hashid] = lkp->lk_next; + else { + lkp_prev = lkp; + + for (lkp = lkp->lk_next; lkp; lkp = lkp->lk_next) { + if (lkp == lkp_to_delete) { + lkp_prev->lk_next = lkp->lk_next; + break; + } + lkp_prev = lkp; + } + } + if (lkp) { + lkp->lk_next = lookup_freelist; + lookup_freelist = lkp; + } + } +} + + +static +void insert_start_event(uintptr_t thread, int debugid, uint64_t now) +{ + event_t evp; + int hashid; + + hashid = thread & HASH_MASK; + + for (evp = event_hash[hashid]; evp; evp = evp->ev_next) { + if (evp->ev_thread == thread && evp->ev_debugid == debugid) + break; + } + if (evp == NULL) { + if ((evp = event_freelist)) + event_freelist = evp->ev_next; + else + evp = (event_t)malloc(sizeof(struct event)); + + evp->ev_thread = thread; + evp->ev_debugid = debugid; + + evp->ev_next = event_hash[hashid]; + event_hash[hashid] = evp; + } + evp->ev_timestamp = now; +} + + +static +uint64_t consume_start_event(uintptr_t thread, int debugid, uint64_t now) +{ + event_t evp; + event_t evp_prev; + int hashid; + uint64_t elapsed = 0; + + hashid = thread & HASH_MASK; + + if ((evp = event_hash[hashid])) { + if (evp->ev_thread == thread && evp->ev_debugid == debugid) + event_hash[hashid] = evp->ev_next; + else { + evp_prev = evp; + + for (evp = evp->ev_next; evp; evp = evp->ev_next) { + + if (evp->ev_thread == thread && evp->ev_debugid == debugid) { + evp_prev->ev_next = evp->ev_next; + break; + } + evp_prev = evp; + } + } + if (evp) { + elapsed = now - evp->ev_timestamp; + + evp->ev_next = event_freelist; + event_freelist = evp; + } + } + return (elapsed); +} + + +log_trace() +{ + char *buffer; + uint32_t buffer_size; + int fd; + int size; + int pad_size; + char pad_buf[4096]; + + + if ((fd = open(logfile, O_TRUNC|O_WRONLY|O_CREAT, 0777)) == -1) { + perror("Can't open logfile"); + exit(1); + } + get_bufinfo(&bufinfo); + + if (bufinfo.nolog != 1) { + reenable = 1; + set_enable(0); /* disable logging*/ + } + get_bufinfo(&bufinfo); + + if (verbose_flag) { + if (bufinfo.flags & KDBG_WRAPPED) + printf("Buffer has wrapped\n"); + else + printf("Buffer has not wrapped\n"); + } + buffer_size = 1000000 * sizeof(kd_buf); + buffer = malloc(buffer_size); + + if (buffer == (char *) 0) + quit("can't allocate memory for tracing info\n"); + + read_command_map(0, 0); + + raw_header.version_no = RAW_VERSION1; + raw_header.thread_count = total_threads; + raw_header.TOD_secs = time((long *)0); + raw_header.TOD_usecs = 0; + + write(fd, &raw_header, sizeof(RAW_header)); + + size = total_threads * sizeof(kd_threadmap); + write(fd, (char *)mapptr, size); + + pad_size = 4096 - ((sizeof(RAW_header) + size) & 4095); + memset(pad_buf, 0, pad_size); + + write(fd, pad_buf, pad_size); + + for (;;) { + needed = buffer_size; + + readtrace(buffer); + + if (needed == 0) + break; + write(fd, buffer, needed * sizeof(kd_buf)); + } + close(fd); +} + + + +Log_trace() +{ + int size; + int n; + kd_buf kd_tmp; + size_t len; + int num_cpus; + int try_writetrace = 1; + int fd; + char *buffer; + kd_buf *kd; + uint64_t sample_window_abs; + uint64_t next_window_begins; + uint64_t current_abs; + uint64_t ending_abstime; + uint64_t last_time_written; + uint32_t us_to_sleep; + uint32_t us_to_adjust; + uint32_t ms_to_run; + + memset(&kd_tmp, 0, sizeof(kd_tmp)); + + if ((fd = open(logfile, O_TRUNC|O_WRONLY|O_CREAT, 0777)) == -1) { + perror("Can't open logfile"); + exit(1); + } + /* + * grab the number of cpus and scale the buffer size + */ + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + mib[2] = 0; + len = sizeof(num_cpus); + + sysctl(mib, 2, &num_cpus, &len, NULL, 0); + + if (!bufset_flag) + nbufs = BASE_EVENTS * num_cpus; + + set_remove(); + set_numbufs(nbufs); + set_init(); + + /* Get kernel buffer information */ + get_bufinfo(&bufinfo); + + buffer = malloc(bufinfo.nkdbufs * sizeof(kd_buf)); + if (buffer == (char *) 0) + quit("can't allocate memory for tracing info\n"); + memset(buffer, 0, bufinfo.nkdbufs * sizeof(kd_buf)); + + set_enable(1); + + if (write_command_map(fd)) { + int pad_size; + char pad_buf[4096]; + + read_command_map(0, 0); + + raw_header.version_no = RAW_VERSION1; + raw_header.thread_count = total_threads; + raw_header.TOD_secs = time((long *)0); + raw_header.TOD_usecs = 0; + + write(fd, &raw_header, sizeof(RAW_header)); + + size = total_threads * sizeof(kd_threadmap); + write(fd, (char *)mapptr, size); + + pad_size = 4096 - ((sizeof(RAW_header) + size) & 4095); + memset(pad_buf, 0, pad_size); + + write(fd, pad_buf, pad_size); + } + sample_window_abs = (uint64_t)((double)US_TO_SLEEP * divisor); + + next_window_begins = mach_absolute_time() + sample_window_abs; + + if (secs_to_run) { + ending_abstime = mach_absolute_time() + (uint64_t)((double)secs_to_run * (double)1000000 * divisor); + ms_to_run = secs_to_run * 1000; + } else + ms_to_run = 0; + last_time_written = mach_absolute_time(); + + while (LogRAW_flag) { + current_abs = mach_absolute_time(); + + if (try_writetrace) { + needed = ms_to_run; + + if (writetrace(fd)) + try_writetrace = 0; + else { + if (needed) { + current_abs = mach_absolute_time(); + + printf("wrote %d events - elapsed time = %.1f secs\n", + (int)needed, ((double)(current_abs - last_time_written) / divisor) / 1000000); + + last_time_written = current_abs; + } + } + } + if (try_writetrace == 0) { + + if (next_window_begins > current_abs) + us_to_adjust = US_TO_SLEEP - (uint32_t)((double)(next_window_begins - current_abs) / divisor); + else + us_to_adjust = US_TO_SLEEP; + + next_window_begins = current_abs + sample_window_abs; + + us_to_sleep = US_TO_SLEEP - us_to_adjust; + + next_window_begins = current_abs + (uint64_t)((double)(us_to_sleep + US_TO_SLEEP) * divisor); + + if (us_to_sleep) + usleep(us_to_sleep); + + get_bufinfo(&bufinfo); + + if (bufinfo.flags & KDBG_WRAPPED) + printf("lost events\n"); + + needed = bufinfo.nkdbufs * sizeof(kd_buf); + + readtrace(buffer); + + if (bufinfo.flags & KDBG_WRAPPED) { + + kd = (kd_buf *) buffer; + + kd_tmp.timestamp = kd[0].timestamp; + kd_tmp.debugid = TRACE_LOST_EVENTS; + + write(fd, &kd_tmp, sizeof(kd_tmp)); + } + write(fd, buffer, needed * sizeof(kd_buf)); + + if (verbose_flag && needed > nbufs) + printf("needed = %ld\n", needed); + } + if (secs_to_run) { + current_abs = mach_absolute_time(); + + if (current_abs > ending_abstime) + break; + ms_to_run = (ending_abstime - current_abs) / (1000 * 1000); + + if (ms_to_run == 0) + break; + } + } + set_enable(0); + set_numbufs(0); + set_remove(); + + close(fd); +} + + +void read_trace() +{ + char *buffer; + uint32_t buffer_size; + kd_buf *kd; + int fd; + int firsttime = 1; + int lines = 0; + int io_lines = 0; + uint64_t bias = 0; + uint32_t count_of_names; + double last_event_time = 0.0; + time_t trace_time; + + if (!readRAW_flag) { + get_bufinfo(&bufinfo); + + if (bufinfo.nolog != 1) { + reenable = 1; + set_enable(0); /* disable logging*/ + } + if (verbose_flag) { + if (bufinfo.flags & KDBG_WRAPPED) + printf("Buffer has wrapped\n"); + else + printf("Buffer has not wrapped\n"); + } + fd = 0; + count_of_names = 0; + + } else { + struct stat statb; + + fd = open(RAW_file, O_RDONLY); + + if (fd < 0) { + perror("Can't open file"); + exit(1); + } + if (read(fd, &raw_header, sizeof(RAW_header)) != sizeof(RAW_header)) { + perror("read failed"); + exit(2); + } + if (raw_header.version_no != RAW_VERSION1) { + raw_header.version_no = RAW_VERSION0; + raw_header.TOD_secs = time((long *)0); + raw_header.TOD_usecs = 0; + + lseek(fd, (off_t)0, SEEK_SET); + + if (read(fd, &raw_header.thread_count, sizeof(int)) != sizeof(int)) { + perror("read failed"); + exit(2); + } + } + count_of_names = raw_header.thread_count; + trace_time = raw_header.TOD_secs; + + printf("%s\n", ctime(&trace_time)); + } + buffer_size = 1000000 * sizeof(kd_buf); + buffer = malloc(buffer_size); + + if (buffer == (char *) 0) + quit("can't allocate memory for tracing info\n"); + + kd = (kd_buf *)buffer; + + read_command_map(fd, count_of_names); + + for (;;) { + uint32_t count; + uint64_t now = 0; + uint64_t prev; + uint64_t prevdelta; + uint32_t cpunum; + uintptr_t thread; + double x = 0.0; + double z = 0.0; + double y = 0.0; + double event_elapsed_time; + kd_buf *kdp; + lookup_t lkp; + boolean_t ending_event; + int i; + int debugid; + int debugid_base; + int dmsgindex; + char dbgmessge[80]; + char outbuf[32]; + char *command; + + if (!readRAW_flag) { + needed = buffer_size; + + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDREADTR; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; + if (sysctl(mib, 3, buffer, &needed, NULL, 0) < 0) + quit("trace facility failure, KERN_KDREADTR\n"); + + if (needed == 0) + break; + count = needed; + + } else { + uint32_t bytes_read; + + bytes_read = read(fd, buffer, buffer_size); + + if (bytes_read == -1) { + perror("read failed"); + exit(2); + } + count = bytes_read / sizeof(kd_buf); + + if (count == 0) + break; + } + for (kdp = &kd[0], i = 0; i < count; i++, kdp++) { + + prev = now; + debugid = kdp->debugid; + debugid_base = debugid & DBG_FUNC_MASK; + now = kdp->timestamp & KDBG_TIMESTAMP_MASK; + + if (firsttime) + bias = now; + now -= bias; + + cpunum = kdbg_get_cpu(kdp); + thread = kdp->arg5; + + if (lines == 64 || firsttime) + { + prevdelta = now - prevdelta; + + if (firsttime) + firsttime = 0; + else { + x = (double)prevdelta; + x /= divisor; + + fprintf(output_file, "\n\nNumber of microsecs since in last page %8.1f\n", x); + } + prevdelta = now; + + /* + * Output description row to output file (make sure to format correctly for 32-bit and 64-bit) + */ + fprintf(output_file, +#ifdef __LP64__ + " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n" +#else + " AbsTime(Us) Delta debugid arg1 arg2 arg3 arg4 thread cpu# command\n\n" +#endif + ); + + lines = 0; + + if (io_lines > 15000) { + fcntl(output_fd, F_FLUSH_DATA, 0); + + io_lines = 0; + } + } + lkp = 0; + + if (debugid_base == VFS_LOOKUP) { + lkp = handle_lookup_event(thread, debugid, kdp); + + if ( !lkp || !(debugid & DBG_FUNC_END)) + continue; + } + x = (double)now; + x /= divisor; + + if (last_event_time) + y = x - last_event_time; + else + y = x; + last_event_time = x; + ending_event = FALSE; + + find_thread_command(kdp, &command); + + /* + * The internal use TRACE points clutter the output. + * Print them only if in verbose mode. + */ + if (!verbose_flag) + { + /* Is this entry of Class DBG_TRACE */ + if ((debugid >> 24) == DBG_TRACE) { + if (((debugid >> 16) & 0xff) != DBG_TRACE_INFO) + continue; + } + } + if ( !lkp) { + int t_debugid; + int t_thread; + + if ((debugid & DBG_FUNC_START) || debugid == MACH_MAKERUNNABLE) { + + if (debugid_base != BSC_thread_terminate && debugid_base != BSC_exit) { + + if (debugid == MACH_MAKERUNNABLE) + t_thread = kdp->arg1; + else + t_thread = thread; + + insert_start_event(t_thread, debugid_base, now); + } + + } else if ((debugid & DBG_FUNC_END) || debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED) { + + if (debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED) { + t_debugid = MACH_MAKERUNNABLE; + t_thread = kdp->arg2; + } else { + t_debugid = debugid_base; + t_thread = thread; + } + event_elapsed_time = (double)consume_start_event(t_thread, t_debugid, now); + event_elapsed_time /= divisor; + ending_event = TRUE; + + if (event_elapsed_time == 0 && (debugid == MACH_STKHANDOFF || debugid == MACH_SCHEDULED)) + ending_event = FALSE; + } + } + if (ending_event) { + char *ch; + + sprintf(&outbuf[0], "(%-10.1f)", event_elapsed_time); + /* + * fix that right paren + */ + ch = &outbuf[11]; + + if (*ch != ')') { + ch = strchr (&outbuf[0], ')'); + } + if (ch) + { + *ch = ' '; + --ch; + + while (ch != &outbuf[0]) + { + if (*ch == ' ') + --ch; + else + { + *(++ch) = ')'; + break; + } + } + } + } + if (match_debugid(debugid_base, dbgmessge, &dmsgindex)) { + if (ending_event) + fprintf(output_file, "%13.1f %10.1f%s %-28x ", x, y, outbuf, debugid_base); + else + fprintf(output_file, "%13.1f %10.1f %-28x ", x, y, debugid_base); + } else { + if (ending_event) + fprintf(output_file, "%13.1f %10.1f%s %-28.28s ", x, y, outbuf, dbgmessge); + else + fprintf(output_file, "%13.1f %10.1f %-28.28s ", x, y, dbgmessge); + } + if (lkp) { + char *strptr; + int len; + + strptr = (char *)lkp->lk_pathname; + + /* + * print the tail end of the pathname + */ + len = strlen(strptr); + if (len > 51) + len -= 51; + else + len = 0; +#ifdef __LP64__ + + fprintf(output_file, "%-16lx %-51s %-16lx %-2d %s\n", lkp->lk_dvp, &strptr[len], thread, cpunum, command); +#else + fprintf(output_file, "%-8x %-51s %-8lx %-2d %s\n", (unsigned int)lkp->lk_dvp, &strptr[len], thread, cpunum, command); +#endif + delete_lookup_event(thread, lkp); + } else { +#ifdef __LP64__ + fprintf(output_file, "%-16lx %-16lx %-16lx %-16lx %-16lx %-2d %s\n", kdp->arg1, kdp->arg2, kdp->arg3, kdp->arg4, thread, cpunum, command); +#else + fprintf(output_file, "%-8lx %-8lx %-8lx %-8lx %-8lx %-2d %s\n", kdp->arg1, kdp->arg2, kdp->arg3, kdp->arg4, thread, cpunum, command); +#endif + } + lines++; + io_lines++; + } + } + if (reenable == 1) + set_enable(1); /* re-enable kernel logging */ +} + + + +void signal_handler(int sig) +{ + ptrace(PT_KILL, pid, (caddr_t)0, 0); + /* + * child is gone; no need to disable the pid + */ + exit(2); +} + + +void signal_handler_RAW(int sig) +{ + LogRAW_flag = 0; +} + + + +int main(argc, argv, env) +int argc; +char **argv; +char **env; +{ + extern char *optarg; + extern int optind; + int status; + int ch; + char *output_filename = NULL; + + if (0 != reexec_to_match_kernel()) { + fprintf(stderr, "Could not re-execute: %d\n", errno); + exit(1); + } + if (setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_PASSIVE) < 0) { + printf("setiopolicy failed\n"); + exit(1); + } + output_file = stdout; + output_fd = 1; + + getdivisor(); + + while ((ch = getopt(argc, argv, "hedEk:irb:gc:p:s:tR:L:l:S:a:x:nfvo:P")) != EOF) + { + switch(ch) + { + case 'h': /* help */ + usage(LONG_HELP); + break; + case 'S': + secs_to_run = argtoi('S', "decimal number", optarg, 10); + break; + case 'a': /* set tracing on a pid */ + pid_flag=1; + pid = argtoi('a', "decimal number", optarg, 10); + break; + case 'x': /* exclude a pid from tracing */ + pid_exflag=1; + pid = argtoi('x', "decimal number", optarg, 10); + break; + case 'v': + verbose_flag=1; + break; + case 'l': + logRAW_flag = 1; + logfile = optarg; + break; + case 'L': + LogRAW_flag = 1; + logfile = optarg; + signal(SIGINT, signal_handler_RAW); + break; + case 'e': + enable_flag = 1; + break; + case 'i': + init_flag = 1; + break; + case 'E': + execute_flag = 1; + break; + case 'd': + disable_flag = 1; + break; + case 'k': + if (kval_flag == 0) + value1 = argtoul('k', "hex number", optarg, 16); + else if (kval_flag == 1) + value2 = argtoul('k', "hex number", optarg, 16); + else if (kval_flag == 2) + value3 = argtoul('k', "hex number", optarg, 16); + else if (kval_flag == 3) + value4 = argtoul('k', "hex number", optarg, 16); + else + { + fprintf(stderr, "A maximum of four values can be specified with -k\n"); + usage(SHORT_HELP); + } + kval_flag++; + break; + case 'r': + remove_flag = 1; + break; + case 'g': + bufget_flag = 1; + break; + case 't': + trace_flag = 1; + break; + case 'R': + readRAW_flag = 1; + RAW_file = optarg; + break; + case 'n': + nowrap_flag = 1; + break; + case 'f': + freerun_flag = 1; + break; + case 'b': + bufset_flag = 1; + nbufs = argtoi('b', "decimal number", optarg, 10); + break; + case 'c': + class_flag = 1; + class = argtoi('c', "decimal number", optarg, 10); + class2 = class+1; + break; + case 's': + subclass_flag = 1; + subclass = argtoi('s', "decimal number", optarg, 10); + break; + case 'p': + if (class_flag != 1) + { fprintf(stderr, "-p must follow -c\n"); + exit(1); + } + class2 = argtoi('p', "decimal number", optarg, 10); + break; + case 'P': + ppt_flag = 1; + break; + case 'o': + output_filename = optarg; + break; + default: + usage(SHORT_HELP); + } + } + argc -= optind; + + if (argc) + { + if (!execute_flag) + { + cfile = argv[optind]; + if (verbose_flag) + printf("Code file is %s \n", cfile); + if (parse_codefile(cfile) == -1) + cfile = (char *)0; + } + } + else + { + if (execute_flag) + { + printf("-E flag needs an executable to launch\n"); + exit(1); + } + } + + if (pid_flag && pid_exflag) + { + fprintf(stderr, "Can't use both -a and -x flag together\n"); + exit(1); + } + + if (subclass_flag && !class_flag) { + fprintf(stderr,"Must define a class ('c') with the subclass ('s') option\n"); + usage(SHORT_HELP); + } + + if (kval_flag && (subclass_flag || class_flag)) + { + fprintf(stderr,"Don't use class or subclass with the 'k' code options.\n"); + usage(SHORT_HELP); + } + + if (output_filename && !trace_flag && !readRAW_flag) + { + fprintf(stderr, "When using 'o' option, must use the 't' or 'R' option too\n"); + usage(SHORT_HELP); + } + + if (disable_flag) + { + if (pid_flag) + { + set_pidcheck(pid, 0); /* disable pid check for given pid */ + exit(1); + } + else if (pid_exflag) + { + set_pidexclude(pid, 0); /* disable pid exclusion for given pid */ + exit(1); + } + set_enable(0); + exit(1); + } + + if (remove_flag) + { + set_remove(); + exit(1); + } + + if (bufset_flag ) + { + if (!init_flag && !LogRAW_flag) + { + fprintf(stderr,"The -b flag must be used with the -i flag\n"); + exit(1); + } + set_numbufs(nbufs); + } + + if (nowrap_flag) + set_nowrap(); + + if (freerun_flag) + set_freerun(); + + if (bufget_flag) + { + get_bufinfo(&bufinfo); + + printf("The kernel buffer settings are:\n"); + + if (bufinfo.flags & KDBG_BUFINIT) + printf("\tKernel buffer is initialized\n"); + else + printf("\tKernel buffer is not initialized\n"); + + printf("\t number of buf entries = %d\n", bufinfo.nkdbufs); + + if (verbose_flag) + { + if (bufinfo.flags & KDBG_MAPINIT) + printf("\tKernel thread map is initialized\n"); + else + printf("\tKernel thread map is not initialized\n"); + printf("\t number of thread entries = %d\n", bufinfo.nkdthreads); + } + + if (bufinfo.nolog) + printf("\tBuffer logging is disabled\n"); + else + printf("\tBuffer logging is enabled\n"); + + if (verbose_flag) + printf("\tkernel flags = 0x%x\n", bufinfo.flags); + + if (bufinfo.flags & KDBG_NOWRAP) + printf("\tKernel buffer wrap is disabled\n"); + else + printf("\tKernel buffer wrap is enabled\n"); + + if (bufinfo.flags & KDBG_RANGECHECK) + printf("\tCollection within a range is enabled\n"); + else + printf("\tCollection within a range is disabled\n"); + + if (bufinfo.flags & KDBG_VALCHECK) + printf("\tCollecting specific code values is enabled\n"); + else + printf("\tCollecting specific code values is disabled\n"); + + if (bufinfo.flags & KDBG_PIDCHECK) + printf("\tCollection based on pid is enabled\n"); + else + printf("\tCollection based on pid is disabled\n"); + + if (bufinfo.flags & KDBG_PIDEXCLUDE) + printf("\tCollection based on pid exclusion is enabled\n"); + else + printf("\tCollection based on pid exclusion is disabled\n"); + + if (bufinfo.bufid == -1) + printf("\tKernel buffer is not controlled by any process.\n"); + else + printf("\tKernel buffer is controlled by proc id [%d]\n", bufinfo.bufid); + } + + if (init_flag) + set_init(); + + if (class_flag) + set_class(); + + if (subclass_flag) + set_subclass(); + + if (kval_flag) + set_kval_list(); + + if (execute_flag) + { + fprintf(stderr, "Starting program: %s\n", argv[optind]); + fflush(stdout); + fflush(stderr); + + switch ((pid = vfork())) + { + case -1: + perror("vfork: "); + exit(1); + case 0: /* child */ + setsid(); + ptrace(PT_TRACE_ME, 0, (caddr_t)0, 0); + execve(argv[optind], &argv[optind], environ); + perror("execve:"); + exit(1); + } + sleep(1); + + signal(SIGINT, signal_handler); + set_pidcheck(pid, 1); + set_enable(1); + ptrace(PT_CONTINUE, pid, (caddr_t)1, 0); + waitpid(pid, &status, 0); + /* child is gone; no need to disable the pid */ + exit(0); + } + else if (enable_flag) + { + if (pid_flag) + set_pidcheck(pid, 1); + else if (pid_exflag) + set_pidexclude(pid, 1); + set_enable(1); + } + + if (output_filename) + { + if (((output_fd = open(output_filename, O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0644)) < 0 ) || + !(output_file = fdopen(output_fd, "w"))) + { + fprintf(stderr, "Cannot open file \"%s\" for writing.\n", output_filename); + usage(SHORT_HELP); + } + setbuffer(output_file, &sbuffer[0], SBUFFER_SIZE); + + if (fcntl(output_fd, F_NOCACHE, 1) < 0) + { + /* Not fatal */ + fprintf(stderr, "Warning: setting F_NOCACHE on %s, failed\n", output_filename); + } + } + if (!LogRAW_flag && !logRAW_flag) + setbuffer(output_file, &sbuffer[0], SBUFFER_SIZE); + + if (trace_flag || readRAW_flag) + read_trace(); + else if (LogRAW_flag) + Log_trace(); + else if (logRAW_flag) + log_trace(); + + exit(0); + +} /* end main */ + + +void +quit(char *s) +{ + if (reenable == 1) + { + reenable = 0; + set_enable(1); /* re-enable kernel logging */ + } + + printf("trace: "); + if (s) + printf("%s ", s); + exit(1); +} + +static void +usage(int short_help) +{ + + if (short_help) + { + (void)fprintf(stderr, " usage: trace -h\n"); + (void)fprintf(stderr, " usage: trace -i [-b numbufs]\n"); + (void)fprintf(stderr, " usage: trace -g\n"); + (void)fprintf(stderr, " usage: trace -d [-a pid | -x pid ]\n"); + (void)fprintf(stderr, " usage: trace -r\n"); + (void)fprintf(stderr, " usage: trace -n\n"); + (void)fprintf(stderr, + " usage: trace -e [ -c class [-p class] [-s subclass] ] [-a pid | -x pid] |\n"); + (void)fprintf(stderr, + " [-k code | -k code | -k code | -k code] [-P] \n\n"); + + (void)fprintf(stderr, + " usage: trace -E [ -c class [-p class] [-s subclass] ] |\n"); + (void)fprintf(stderr, + " [-k code | -k code | -k code | -k code] [-P]\n"); + (void)fprintf(stderr, + " executable_path [optional args to executable] \n\n"); + + (void)fprintf(stderr, + " usage: trace -t [-R rawfile] [-o OutputFilename] [CodeFilename]\n"); + exit(1); + } + + + /* Only get here of printing long usage list */ + (void)fprintf(stderr, "usage: trace -h\n"); + (void)fprintf(stderr, "\tPrint this long command help.\n\n"); + + (void)fprintf(stderr, "usage: trace -i [-b numbufs]\n"); + (void)fprintf(stderr, "\tInitialize the kernel trace buffer.\n\n"); + (void)fprintf(stderr, "\t-b numbufs The number of trace elements the kernel buffer\n"); + (void)fprintf(stderr, "\t can hold is set to numbufs. Use with the -i flag.\n"); + (void)fprintf(stderr, "\t Enter a decimal value.\n\n"); + + (void)fprintf(stderr, "usage: trace -g\n"); + (void)fprintf(stderr, "\tGet the kernel buffer settings.\n\n"); + + (void)fprintf(stderr, "usage: trace -d [-a pid | -x pid]\n"); + (void)fprintf(stderr, "\tDisable/stop collection of kernel trace elements.\n\n"); + (void)fprintf(stderr, "\t -a pid Disable/stop collection for this process only.\n\n"); + (void)fprintf(stderr, "\t -x pid Disable/stop exclusion of this process only.\n\n"); + + (void)fprintf(stderr, "usage: trace -r\n"); + (void)fprintf(stderr, "\tRemove the kernel trace buffer. Set controls to default.\n\n"); + + (void)fprintf(stderr, "usage: trace -n\n"); + (void)fprintf(stderr, "\tDisables kernel buffer wrap around.\n\n"); + + (void)fprintf(stderr, + "usage: trace -e [ -c class [-p class] [-s subclass] ] [-a pid | -x pid] |\n"); + (void)fprintf(stderr, + " [-k code | -k code | -k code | -k code] \n\n"); + (void)fprintf(stderr, "\tEnable/start collection of kernel trace elements.\n"); + (void)fprintf(stderr, "\tEnter values in decimal notation unless otherwise noted..\n\n"); + (void)fprintf(stderr, "\t -c class Restrict trace collection to given class.\n\n"); + (void)fprintf(stderr, "\t -p class Restrict trace collection to given class range.\n"); + (void)fprintf(stderr, "\t Must provide class with -c first.\n\n"); + (void)fprintf(stderr, "\t -s subclass Restrict trace collection to given subclass.\n"); + (void)fprintf(stderr, "\t Must provide class with -c.\n\n"); + (void)fprintf(stderr, "\t -a pid Restrict trace collection to the given process.\n\n"); + (void)fprintf(stderr, "\t -x pid Exclude the given process from trace collection.\n\n"); + (void)fprintf(stderr, "\t -k code Restrict trace collection up to four specific codes.\n"); + (void)fprintf(stderr, "\t Enter codes in hex values.\n\n"); + (void)fprintf(stderr, "\t -P Enable restricted PPT trace points only.\n\n"); + + (void)fprintf(stderr, + "usage: trace -E [ -c class [-p class] [-s subclass] ] |\n"); + (void)fprintf(stderr, + " [-k code | -k code | -k code | -k code] \n"); + (void)fprintf(stderr, + " executable_path [optional args to executable] \n\n"); + (void)fprintf(stderr, "\tLaunch the given executable and enable/start\n"); + (void)fprintf(stderr, "\tcollection of kernel trace elements for that process.\n"); + (void)fprintf(stderr, "\tSee -e(enable) flag for option descriptions.\n\n"); + + (void)fprintf(stderr, + "usage: trace -t [-R rawfile] [-o OutputFilename] [CodeFilename] \n"); + (void)fprintf(stderr, "\t Collect the kernel buffer trace data and print it.\n\n"); + (void)fprintf(stderr, "\t -R rawfile Read raw trace file and print trace output to stdout.\n"); + (void)fprintf(stderr, "\t -o OutputFilename Print trace output to OutputFilename. Default is stdout.\n\n"); + + (void)fprintf(stderr, + "usage: trace -L rawfile\n"); + (void)fprintf(stderr, "\t Continuously collect the kernel buffer trace data in the raw format.\n\n"); + + (void)fprintf(stderr, + "usage: trace -l rawfile\n"); + (void)fprintf(stderr, "\t Collect the existing kernel buffer trace data in the raw format.\n\n"); + + exit(1); +} + + +static int +argtoi(flag, req, str, base) +int flag; +char *req, *str; +int base; +{ + char *cp; + int ret; + + ret = (int)strtol(str, &cp, base); + if (cp == str || *cp) + errx(EINVAL, "-%c flag requires a %s", flag, req); + return (ret); +} + + +static unsigned long +argtoul(flag, req, str, base) +int flag; +char *req, *str; +int base; +{ + char *cp; + unsigned long ret; + + ret = (int)strtoul(str, &cp, base); + if (cp == str || *cp) + errx(EINVAL, "-%c flag requires a %s", flag, req); + return (ret); +} + + +/* + * comparison function for qsort + * sort by debugid + */ +int debugid_compar(p1, p2) + code_type_t *p1; + code_type_t *p2; +{ + if (p1->debugid > p2->debugid) + return(1); + else if (p1->debugid == p2->debugid) + return(0); + else + return(-1); +} + + +/* + * Find the debugid code in the list and return its index + */ +static int binary_search(list, lowbound, highbound, code) + code_type_t *list; + int lowbound, highbound; + unsigned int code; +{ + int low, high, mid; + int tries = 0; + + low = lowbound; + high = highbound; + + while (1) + { + mid = (low + high) / 2; + + tries++; + + if (low > high) + return (-1); /* failed */ + else if ( low + 1 >= high) + { + /* We have a match */ + if (list[high].debugid == code) + return(high); + else if (list[low].debugid == code) + return(low); + else + return(-1); /* search failed */ + } + else if (code < list[mid].debugid) + high = mid; + else + low = mid; + } +} + + +static int +parse_codefile(char *filename) +{ + int fd; + int i, j, count, line; + struct stat stat_buf; + unsigned long file_size; + char *file_addr, *endp; + + if ((fd = open(filename, O_RDONLY, 0)) == -1) + { + printf("Failed to open code description file %s\n",filename); + return(-1); + } + + if (fstat(fd, &stat_buf) == -1) + { + printf("Error: Can't fstat file: %s\n", filename); + return(-1); + } + + /* + * For some reason mapping files with zero size fails + * so it has to be handled specially. + */ + file_size = stat_buf.st_size; + + if (stat_buf.st_size != 0) + { + if ((file_addr = mmap(0, stat_buf.st_size, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_FILE, fd, 0)) == (char*) -1) + { + printf("Error: Can't map file: %s\n", filename); + close(fd); + return(-1); + } + } + else + { + printf("Error: Zero sized file: %s\n", filename); + close(fd); + return(-1); + } + close(fd); + + + /* + * If we get here, we have mapped the file + * and we are ready to parse it. Count + * the newlines to get total number of codes. + */ + + for (count = 0, j=1; j < file_size; j++) + { + if (file_addr[j] == '\n') + count++; + } + + if (count == 0) + { + printf("Error: No codes in %s\n", filename); + return(-1); + } + + /* + * Fudge the count to accomodate the last line in the file - + * in case it doesn't end in a newline. + */ + count++; + + if ((codesc = (code_type_t *)malloc(count * sizeof(code_type_t))) == 0 ) { + printf("Failed to allocate buffer for code descriptions\n"); + return(-1); + } + + bzero((char *)codesc, count * sizeof(code_type_t)); + codenum = 0; + + for (line = 1, i = 0, j = 0; j < file_size && i < count ; i++) + { + /* Skip blank lines */ + while (file_addr[j] == '\n') + { + j++; + line++; + } + + /* Skip leading whitespace */ + while (file_addr[j] == ' ' || file_addr[j] == '\t') + j++; + + /* Get the debugid code */ + codesc[i].debugid = strtoul(file_addr + j, &endp, 16); + j = endp - file_addr; + + if (codesc[i].debugid == 0) + { + /* We didn't find a debugid code - skip this line */ + if (verbose_flag) + printf("Error: while parsing line %d, skip\n", line); + while (file_addr[j] != '\n' && j < file_size) + j++; + i--; + line++; + continue; + } + + /* Skip whitespace */ + while (file_addr[j] == ' ' || file_addr[j] == '\t') + j++; + + /* Get around old file that had count at the beginning */ + if (file_addr[j] == '\n') + { + /* missing debugid string - skip */ + if (verbose_flag) + printf("Error: while parsing line %d, (0x%x) skip\n", line, codesc[i].debugid); + + j++; + i--; + line++; + continue; + } + + /* Next is the debugid string terminated by a newline */ + codesc[i].debug_string = &file_addr[j]; + + /* Null out the newline terminator */ + while ((j < file_size) && (file_addr[j] != '\n')) + j++; + file_addr[j] = '\0'; /* File must be read-write */ + j++; + line++; + codenum++; /*Index into codesc is 0 to codenum-1 */ + } + + if (verbose_flag) + { + printf("Parsed %d codes in %s\n", codenum, filename); + printf("[%6d] 0x%8x %s\n", 0, codesc[0].debugid, codesc[0].debug_string); + printf("[%6d] 0x%8x %s\n\n", codenum-1, codesc[codenum-1].debugid, codesc[codenum-1].debug_string); + } + + /* sort */ + qsort((void *)codesc, codenum, sizeof(code_type_t), debugid_compar); + + if (verbose_flag) + { + printf("Sorted %d codes in %s\n", codenum, filename); + printf("lowbound [%6d]: 0x%8x %s\n", 0, codesc[0].debugid, codesc[0].debug_string); + printf("highbound [%6d]: 0x%8x %s\n\n", codenum-1, codesc[codenum-1].debugid, codesc[codenum-1].debug_string); + } + +#if 0 + /* Dump the codefile */ + for (i = 0; i < codenum; i++) + printf("[%d] 0x%x %s\n",i+1, codesc[i].debugid, codesc[i].debug_string); +#endif + return(0); +} + + + +int match_debugid(unsigned int xx, char * debugstr, int * yy) +{ + int indx; + + if (codenum == 0) + return(-1); + + if (codesc[codeindx_cache].debugid != xx) + indx = binary_search(codesc, 0, (codenum-1), xx); + else + indx = codeindx_cache; + + if (indx == -1) + return(indx); /* match failed */ + else { + bcopy(&codesc[indx].debug_string[0], debugstr,80); + *yy = indx; + codeindx_cache = indx; + return(0); /* match success */ + } +} + + +int +read_command_map(int fd, int count) +{ + int i; + size_t size; + int mib[6]; + + if (readRAW_flag) { + total_threads = count; + size = count * sizeof(kd_threadmap); + } else { + get_bufinfo(&bufinfo); + + total_threads = bufinfo.nkdthreads; + size = bufinfo.nkdthreads * sizeof(kd_threadmap); + } + mapptr = 0; + nthreads = total_threads * 2; + + if (verbose_flag) + printf("Size of map table is %d, thus %d entries\n", (int)size, total_threads); + + if (size) { + if ((mapptr = (kd_threadmap *) malloc(size))) + bzero (mapptr, size); + else + { + if (verbose_flag) + printf("Thread map is not initialized -- this is not fatal\n"); + return(0); + } + } + if (readRAW_flag) { + off_t offset; + + if (read(fd, mapptr, size) != size) { + if (verbose_flag) + printf("Can't read the thread map -- this is not fatal\n"); + free(mapptr); + mapptr = 0; + + if (size < 0) + size = 0; + return(size); + } + if (raw_header.version_no != RAW_VERSION0) { + offset = lseek(fd, (off_t)0, SEEK_CUR); + offset = (offset + (4095)) & ~4095; + + lseek(fd, offset, SEEK_SET); + } + } else { + /* Now read the threadmap */ + mib[0] = CTL_KERN; + mib[1] = KERN_KDEBUG; + mib[2] = KERN_KDTHRMAP; + mib[3] = 0; + mib[4] = 0; + mib[5] = 0; /* no flags */ + if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) + { + /* This is not fatal -- just means I cant map command strings */ + if (verbose_flag) + printf("Can't read the thread map -- this is not fatal\n"); + free(mapptr); + mapptr = 0; + return(0); + } + } + for (i = 0; i < total_threads; i++) + create_map_entry(mapptr[i].thread, &mapptr[i].command[0]); + + if (verbose_flag) { + /* Dump the initial map */ + + printf("Size of maptable returned is %ld, thus %ld entries\n", size, (size/sizeof(kd_threadmap))); + + printf("Thread Command\n"); + for (i = 0; i < total_threads; i++) + { + printf ("0x%lx %s\n", + mapptr[i].thread, + mapptr[i].command); + } + } + return(size); +} + + +void create_map_entry(uintptr_t thread, char *command) +{ + threadmap_t tme; + int hashid; + + if ((tme = threadmap_freelist)) + threadmap_freelist = tme->tm_next; + else + tme = (threadmap_t)malloc(sizeof(struct threadmap)); + + tme->tm_thread = thread; + tme->tm_deleteme = FALSE; + + (void)strncpy (tme->tm_command, command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; + + hashid = thread & HASH_MASK; + + tme->tm_next = threadmap_hash[hashid]; + threadmap_hash[hashid] = tme; +} + + +void delete_thread_entry(uintptr_t thread) +{ + threadmap_t tme = 0; + threadmap_t tme_prev; + int hashid; + + hashid = thread & HASH_MASK; + + if ((tme = threadmap_hash[hashid])) { + if (tme->tm_thread == thread) + threadmap_hash[hashid] = tme->tm_next; + else { + tme_prev = tme; + + for (tme = tme->tm_next; tme; tme = tme->tm_next) { + if (tme->tm_thread == thread) { + tme_prev->tm_next = tme->tm_next; + break; + } + tme_prev = tme; + } + } + if (tme) { + tme->tm_next = threadmap_freelist; + threadmap_freelist = tme; + } + } +} + + +find_and_insert_tmp_map_entry(uintptr_t pthread, char *command) +{ + threadmap_t tme = 0; + threadmap_t tme_prev; + int hashid; + + if ((tme = threadmap_temp)) { + if (tme->tm_pthread == pthread) + threadmap_temp = tme->tm_next; + else { + tme_prev = tme; + + for (tme = tme->tm_next; tme; tme = tme->tm_next) { + if (tme->tm_pthread == pthread) { + tme_prev->tm_next = tme->tm_next; + break; + } + tme_prev = tme; + } + } + if (tme) { + (void)strncpy (tme->tm_command, command, MAXCOMLEN); + tme->tm_command[MAXCOMLEN] = '\0'; + + delete_thread_entry(tme->tm_thread); + + hashid = tme->tm_thread & HASH_MASK; + + tme->tm_next = threadmap_hash[hashid]; + threadmap_hash[hashid] = tme; + } + } +} + + +void create_tmp_map_entry(uintptr_t thread, uintptr_t pthread) +{ + threadmap_t tme; + + if ((tme = threadmap_freelist)) + threadmap_freelist = tme->tm_next; + else + tme = (threadmap_t)malloc(sizeof(struct threadmap)); + + tme->tm_thread = thread; + tme->tm_pthread = pthread; + tme->tm_deleteme = FALSE; + tme->tm_command[0] = '\0'; + + tme->tm_next = threadmap_temp; + threadmap_temp = tme; +} + + +threadmap_t +find_thread_entry(uintptr_t thread) +{ + threadmap_t tme; + int hashid; + + hashid = thread & HASH_MASK; + + for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) { + if (tme->tm_thread == thread) + return (tme); + } + return (0); +} + + +void find_thread_name(uintptr_t thread, char **command, boolean_t deleteme) +{ + threadmap_t tme; + + if ((tme = find_thread_entry(thread))) { + *command = tme->tm_command; + + if (deleteme == TRUE) + tme->tm_deleteme = deleteme; + } else + *command = EMPTYSTRING; +} + + +void find_thread_command(kd_buf *kbufp, char **command) +{ + uintptr_t thread; + threadmap_t tme; + int debugid_base; + + thread = kbufp->arg5; + debugid_base = kbufp->debugid & DBG_FUNC_MASK; + + if (debugid_base == BSC_exit || debugid_base == MACH_STKHANDOFF) { + /* + * Mark entry as invalid and return temp command pointer + */ + if ((tme = find_thread_entry(thread))) { + + strncpy(tmpcommand, tme->tm_command, MAXCOMLEN); + *command = tmpcommand; + + if (debugid_base == BSC_exit || tme->tm_deleteme == TRUE) + delete_thread_entry(thread); + } else + *command = EMPTYSTRING; + } + else if (debugid_base == TRACE_DATA_NEWTHREAD) { + /* + * Save the create thread data + */ + create_tmp_map_entry(kbufp->arg1, kbufp->arg5); + } + else if (debugid_base == TRACE_STRING_NEWTHREAD) { + /* + * process new map entry + */ + find_and_insert_tmp_map_entry(kbufp->arg5, (char *)&kbufp->arg1); + } + else if (debugid_base == TRACE_STRING_EXEC) { + + delete_thread_entry(kbufp->arg5); + + create_map_entry(kbufp->arg5, (char *)&kbufp->arg1); + } + else + find_thread_name(thread, command, (debugid_base == BSC_thread_terminate)); +} + + +static +void getdivisor() +{ + mach_timebase_info_data_t info; + + (void) mach_timebase_info (&info); + + divisor = ( (double)info.denom / (double)info.numer) * 1000; + + if (verbose_flag) + printf("divisor = %g\n", divisor); +} diff --git a/vifs.tproj/Makefile b/vifs.tproj/Makefile index 231d384..c7736c3 100644 --- a/vifs.tproj/Makefile +++ b/vifs.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = vifs.c MANPAGES = vifs.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/vipw.tproj/Makefile b/vipw.tproj/Makefile index 2f5516d..d6ca8dc 100644 --- a/vipw.tproj/Makefile +++ b/vipw.tproj/Makefile @@ -5,7 +5,7 @@ HFILES = pw_util.h CFILES = pw_util.c vipw.c MANPAGES = vipw.8 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/vm_stat.tproj/Makefile b/vm_stat.tproj/Makefile index 14aef47..8b253a1 100644 --- a/vm_stat.tproj/Makefile +++ b/vm_stat.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = vm_stat.c MANPAGES = vm_stat.1 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/zdump.tproj/Makefile b/zdump.tproj/Makefile index 332520f..b4fab3d 100644 --- a/zdump.tproj/Makefile +++ b/zdump.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/sbin CFILES = zdump.c MANPAGES = zdump.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/zic.tproj/Makefile b/zic.tproj/Makefile index 04a05f7..78263b4 100644 --- a/zic.tproj/Makefile +++ b/zic.tproj/Makefile @@ -5,7 +5,7 @@ HFILES = private.h CFILES = ialloc.c scheck.c zic.c MANPAGES = zic.8 -Extra_CC_Flags = -Wall -Werror -mdynamic-no-pic +Extra_CC_Flags = -Wall -Werror Extra_LD_Flags = -dead_strip include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/zprint.tproj/Makefile b/zprint.tproj/Makefile index 508fdcf..8c64074 100644 --- a/zprint.tproj/Makefile +++ b/zprint.tproj/Makefile @@ -4,7 +4,7 @@ Install_Dir = /usr/bin CFILES = zprint.c MANPAGES = zprint.1 -Extra_CC_Flags = -mdynamic-no-pic +Extra_CC_Flags = Extra_LD_Flags = -dead_strip -lutil include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/zprint.tproj/zprint.1 b/zprint.tproj/zprint.1 index 398066f..3acaae7 100644 --- a/zprint.tproj/zprint.1 +++ b/zprint.tproj/zprint.1 @@ -1,9 +1,9 @@ -.TH ZPRINT 1 27/02/87 +.TH ZPRINT 1 02/12/09 .CM 4 .SH NAME zprint \- show information about kernel zones .SH SYNOPSIS -\fBzprint\fP [\fB-w\fP] [\fB-s\fP] [\fB-c\fP] [\fB-h\fP] [name] +\fBzprint\fP [\fB-w\fP] [\fB-s\fP] [\fB-c\fP] [\fB-h\fP] [\fB-t\fP] [\fB-d\fP] [\fB-p \fP][name] .SH DESCRIPTION \fIzprint(1)\fR displays data about Mach zones. By default, \fIzprint\fR will print out information about all Mach zones. If the @@ -30,12 +30,28 @@ It may be useful to override this option when sorting by column. .\" ========== .TP 8 .B \-s -\fIzprint\fR sorts the zones, showing the wasting the most memory first. +\fIzprint\fR sorts the zones, showing the zone wasting the most memory first. .\" ========== .TP 8 .B \-w For each zone, \fIzprint\fR calculates how much space is allocated but not currently in use, the space wasted by the zone. +.TP 8 +.B \-t +For each zone, \fIzprint\fR calculates the total size of allocations from +the zone over the life of the zone. +.TP 8 +.B \-d +Display deltas over time, showing any zones that have achieved a new maximum +current allocation size during the interval. If the total allocation sizes are +being displayed for the zones in question, it will also display the deltas if the +total allocations have doubled. +.B \-p +Display zone usage related to the specified process id. Each zone will display +standard columns and the amount of memory from that zone associated with a given +process. The letter "A" in the flags column indicates that this total is being +accounted to the process. Otherwise, the total is an indication of the influence +the process has on the kernel, but the memory is being accounted to the kernel proper. .PP Any option (including default options) can be overridden by specifying the option in upper-case; for example, -C overrides diff --git a/zprint.tproj/zprint.c b/zprint.tproj/zprint.c index e637a45..c374d0f 100644 --- a/zprint.tproj/zprint.c +++ b/zprint.tproj/zprint.c @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2009 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ /* * @OSF_COPYRIGHT@ */ @@ -50,52 +77,68 @@ #define streql(a, b) (strcmp((a), (b)) == 0) #define strneql(a, b, n) (strncmp((a), (b), (n)) == 0) -static void printzone(); -static void colprintzone(); -static void colprintzoneheader(); -static void printk(); -static int strnlen(); -static boolean_t substr(); +static void usage(void); +static void printzone(mach_zone_name_t *, task_zone_info_t *); +static void colprintzone(mach_zone_name_t *, task_zone_info_t *); +static int find_deltas(mach_zone_name_t *, task_zone_info_t *, task_zone_info_t *, char *, int, int); +static void colprintzoneheader(void); +static void printk(const char *, int); +static boolean_t substr(const char *a, int alen, const char *b, int blen); static char *program; +static pid_t pid = 0; +static task_t task = TASK_NULL; +static boolean_t ShowPid = FALSE; + +static boolean_t ShowDeltas = FALSE; static boolean_t ShowWasted = FALSE; +static boolean_t ShowTotal = FALSE; static boolean_t SortZones = FALSE; static boolean_t ColFormat = TRUE; static boolean_t PrintHeader = TRUE; -static unsigned int totalsize = 0; -static unsigned int totalused = 0; +static unsigned long long totalsize = 0; +static unsigned long long totalused = 0; +static unsigned long long totalsum = 0; +static unsigned long long pidsum = 0; + +static int last_time = 0; + +static char *zname = NULL; +static int znamelen = 0; + +static void +sigintr(__unused int signum) +{ + last_time = 1; +} static void -usage() +usage(void) { - fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [name]\n", program); + fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-p ] [name]\n", program); exit(1); } int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char **argv) { - zone_name_t name_buf[1024]; - zone_name_t *name = name_buf; - unsigned int nameCnt = sizeof name_buf/sizeof name_buf[0]; - zone_info_t info_buf[1024]; - zone_info_t *info = info_buf; - unsigned int infoCnt = sizeof info_buf/sizeof info_buf[0]; + mach_zone_name_t *name = NULL; + unsigned int nameCnt = 0; + task_zone_info_t *info = NULL; + unsigned int infoCnt = 0; - char *zname = NULL; - int znamelen = 0; + task_zone_info_t *max_info = NULL; + char *deltas = NULL; kern_return_t kr; int i, j; + int first_time = 1; + int must_print = 1; + int interval = 1; - if (0 != reexec_to_match_kernel()) { - fprintf(stderr, "Could not re-execute: %d\n", errno); - exit(1); - } + signal(SIGINT, sigintr); program = strrchr(argv[0], '/'); if (program == NULL) @@ -104,7 +147,13 @@ main(argc, argv) program++; for (i = 1; i < argc; i++) { - if (streql(argv[i], "-w")) + if (streql(argv[i], "-d")) + ShowDeltas = TRUE; + else if (streql(argv[i], "-t")) + ShowTotal = TRUE; + else if (streql(argv[i], "-T")) + ShowTotal = FALSE; + else if (streql(argv[i], "-w")) ShowWasted = TRUE; else if (streql(argv[i], "-W")) ShowWasted = FALSE; @@ -118,7 +167,14 @@ main(argc, argv) ColFormat = FALSE; else if (streql(argv[i], "-H")) PrintHeader = FALSE; - else if (streql(argv[i], "--")) { + else if (streql(argv[i], "-p")) { + ShowPid = TRUE; + if (i < argc - 1) { + pid = atoi(argv[i+1]); + i++; + } else + usage(); + } else if (streql(argv[i], "--")) { i++; break; } else if (argv[i][0] == '-') @@ -142,34 +198,87 @@ main(argc, argv) usage(); } - kr = host_zone_info(mach_host_self(), - &name, &nameCnt, &info, &infoCnt); - if (kr != KERN_SUCCESS) { - fprintf(stderr, "%s: host_zone_info: %s\n", - program, mach_error_string(kr)); + if (ShowDeltas) { + SortZones = FALSE; + ColFormat = TRUE; + PrintHeader = TRUE; + } + + if (ShowPid) { + kr = task_for_pid(mach_task_self(), pid, &task); + if (kr != KERN_SUCCESS) { + fprintf(stderr, "%s: task_for_pid(%d) failed: %s (try running as root)\n", + program, pid, mach_error_string(kr)); + exit(1); + } + } + + for (;;) { + if (ShowPid) { + kr = task_zone_info(task, &name, &nameCnt, &info, &infoCnt); + if (kr != KERN_SUCCESS) { + fprintf(stderr, "%s: task_zone_info: %s\n", + program, mach_error_string(kr)); exit(1); + } + } else { + mach_zone_info_t *zinfo = NULL; + + kr = mach_zone_info(mach_host_self(), + &name, &nameCnt, &zinfo, &infoCnt); + if (kr != KERN_SUCCESS) { + fprintf(stderr, "%s: mach_zone_info: %s\n", + program, mach_error_string(kr)); + exit(1); + } + kr = vm_allocate(mach_task_self(), (vm_address_t *)&info, + infoCnt * sizeof *info, VM_FLAGS_ANYWHERE); + if (kr != KERN_SUCCESS) { + fprintf(stderr, "%s vm_allocate: %s\n", + program, mach_error_string(kr)); + exit(1); + } + for (i = 0; i < infoCnt; i++) { + *(mach_zone_info_t *)(info + i) = zinfo[i]; + info[i].tzi_caller_acct = 0; + info[i].tzi_task_alloc = 0; + info[i].tzi_task_free = 0; + } + kr = vm_deallocate(mach_task_self(), (vm_address_t) zinfo, + (vm_size_t) (infoCnt * sizeof *zinfo)); + if (kr != KERN_SUCCESS) { + fprintf(stderr, "%s: vm_deallocate: %s\n", + program, mach_error_string(kr)); + exit(1); + } } - else if (nameCnt != infoCnt) { - fprintf(stderr, "%s: host_zone_info: counts not equal?\n", + + if (nameCnt != infoCnt) { + fprintf(stderr, "%s: mach/task_zone_info: counts not equal?\n", program); exit(1); } + if (first_time) { + deltas = (char *)malloc(infoCnt); + max_info = (task_zone_info_t *)malloc((infoCnt * sizeof *info)); + } + if (SortZones) { for (i = 0; i < nameCnt-1; i++) for (j = i+1; j < nameCnt; j++) { int wastei, wastej; - wastei = (info[i].zi_cur_size - - (info[i].zi_elem_size * - info[i].zi_count)); - wastej = (info[j].zi_cur_size - - (info[j].zi_elem_size * - info[j].zi_count)); + wastei = (info[i].tzi_cur_size - + (info[i].tzi_elem_size * + info[i].tzi_count)); + wastej = (info[j].tzi_cur_size - + (info[j].tzi_elem_size * + info[j].tzi_count)); if (wastej > wastei) { - zone_info_t tinfo; - zone_name_t tname; + task_zone_info_t tinfo; + mach_zone_name_t tname; tinfo = info[i]; info[i] = info[j]; @@ -182,18 +291,26 @@ main(argc, argv) } } - if (ColFormat) { - colprintzoneheader(); + must_print = find_deltas(name, info, max_info, deltas, infoCnt, first_time); + if (must_print) { + if (ColFormat) { + if (!first_time) + printf("\n"); + colprintzoneheader(); + } + for (i = 0; i < nameCnt; i++) { + if (deltas[i]) { + if (ColFormat) + colprintzone(&name[i], &info[i]); + else + printzone(&name[i], &info[i]); + } + } } - for (i = 0; i < nameCnt; i++) - if (substr(zname, znamelen, name[i].zn_name, - strnlen(name[i].zn_name, sizeof name[i].zn_name))) - if (ColFormat) - colprintzone(&name[i], &info[i]); - else - printzone(&name[i], &info[i]); - - if ((name != name_buf) && (nameCnt != 0)) { + + first_time = 0; + + if ((name != NULL) && (nameCnt != 0)) { kr = vm_deallocate(mach_task_self(), (vm_address_t) name, (vm_size_t) (nameCnt * sizeof *name)); if (kr != KERN_SUCCESS) { @@ -203,7 +320,7 @@ main(argc, argv) } } - if ((info != info_buf) && (infoCnt != 0)) { + if ((info != NULL) && (infoCnt != 0)) { kr = vm_deallocate(mach_task_self(), (vm_address_t) info, (vm_size_t) (infoCnt * sizeof *info)); if (kr != KERN_SUCCESS) { @@ -213,34 +330,25 @@ main(argc, argv) } } - if (ShowWasted && PrintHeader) { - printf("TOTAL SIZE = %u\n", totalsize); - printf("TOTAL USED = %u\n", totalused); - printf("TOTAL WASTED = %d\n", totalsize - totalused); + if ((ShowWasted||ShowTotal) && PrintHeader && !ShowDeltas) { + printf("TOTAL SIZE = %llu\n", totalsize); + printf("TOTAL USED = %llu\n", totalused); + if (ShowWasted) + printf("TOTAL WASTED = %llu\n", totalsize - totalused); + if (ShowTotal) + printf("TOTAL ALLOCS = %llu\n", totalsum); } - exit(0); -} - -static int -strnlen(s, n) - char *s; - int n; -{ - int len = 0; - - while ((len < n) && (*s++ != '\0')) - len++; + if (ShowDeltas == FALSE || last_time) + break; - return len; + sleep(interval); + } + exit(0); } static boolean_t -substr(a, alen, b, blen) - char *a; - int alen; - char *b; - int blen; +substr(const char *a, int alen, const char *b, int blen) { int i; @@ -252,58 +360,69 @@ substr(a, alen, b, blen) } static void -printzone(name, info) - zone_name_t *name; - zone_info_t *info; +printzone(mach_zone_name_t *name, task_zone_info_t *info) { - unsigned int used, size; - - printf("%.*s zone:\n", (int)sizeof name->zn_name, name->zn_name); - printf("\tcur_size: %dK bytes (%d elements)\n", - info->zi_cur_size/1024, - info->zi_cur_size/info->zi_elem_size); - printf("\tmax_size: %dK bytes (%d elements)\n", - info->zi_max_size/1024, - info->zi_max_size/info->zi_elem_size); - printf("\telem_size: %d bytes\n", - info->zi_elem_size); - printf("\t# of elems: %d\n", - info->zi_count); - printf("\talloc_size: %dK bytes (%d elements)\n", - info->zi_alloc_size/1024, - info->zi_alloc_size/info->zi_elem_size); - if (info->zi_pageable) - printf("\tPAGEABLE\n"); - if (info->zi_collectable) + unsigned long long used, size; + + printf("%.*s zone:\n", (int)sizeof name->mzn_name, name->mzn_name); + printf("\tcur_size: %lluK bytes (%llu elements)\n", + info->tzi_cur_size/1024, + (info->tzi_elem_size == 0) ? 0 : + info->tzi_cur_size/info->tzi_elem_size); + printf("\tmax_size: %lluK bytes (%llu elements)\n", + info->tzi_max_size/1024, + (info->tzi_elem_size == 0) ? 0 : + info->tzi_max_size/info->tzi_elem_size); + printf("\telem_size: %llu bytes\n", + info->tzi_elem_size); + printf("\t# of elems: %llu\n", + info->tzi_count); + printf("\talloc_size: %lluK bytes (%llu elements)\n", + info->tzi_alloc_size/1024, + (info->tzi_elem_size == 0) ? 0 : + info->tzi_alloc_size/info->tzi_elem_size); + if (info->tzi_exhaustible) + printf("\tEXHAUSTIBLE\n"); + if (info->tzi_collectable) printf("\tCOLLECTABLE\n"); - + if (ShowPid && info->tzi_caller_acct) + printf("\tCALLER ACCOUNTED\n"); + if (ShowPid) { + pidsum += info->tzi_task_alloc - info->tzi_task_free; + printf("\tproc_alloc_size: %8dK bytes (%llu elements)\n", + (int)((info->tzi_task_alloc - info->tzi_task_free)/1024), + (info->tzi_elem_size == 0) ? 0 : + (info->tzi_task_alloc - info->tzi_task_free)/info->tzi_elem_size); + } if (ShowWasted) { - totalused += used = info->zi_elem_size * info->zi_count; - totalsize += size = info->zi_cur_size; - printf("\t\t\t\t\tWASTED: %d\n", size - used); + totalused += used = info->tzi_elem_size * info->tzi_count; + totalsize += size = info->tzi_cur_size; + printf("\t\t\t\t\tWASTED: %llu\n", size - used); + } + if (ShowTotal) { + totalsum += info->tzi_sum_size; + printf("\t\t\t\t\tTOTAL: %llu\n", totalsum); + if (ShowPid) + printf("\t\t\t\t\tPID TOTAL: %llu\n", pidsum); } } static void -printk(fmt, i) - char *fmt; - int i; +printk(const char *fmt, int i) { printf(fmt, i / 1024); putchar('K'); } static void -colprintzone(zone_name, info) - zone_name_t *zone_name; - zone_info_t *info; +colprintzone(mach_zone_name_t *zone_name, task_zone_info_t *info) { - char *name = zone_name->zn_name; + char *name = zone_name->mzn_name; int j, namewidth; - unsigned int used, size; + unsigned long long used, size; namewidth = 25; - if (ShowWasted) { + if (ShowWasted || ShowTotal) { namewidth -= 7; } for (j = 0; j < namewidth - 1 && name[j]; j++) { @@ -324,51 +443,96 @@ colprintzone(zone_name, info) putchar(' '); } } - printf("%5d", info->zi_elem_size); - printk("%6d", info->zi_cur_size); - if (info->zi_max_size >= 99999 * 1024) { - printf(" ----"); + printf("%5llu", info->tzi_elem_size); + printk("%8llu", info->tzi_cur_size); + if (info->tzi_max_size / 1024 > 9999999) { + printf(" ------"); } else { - printk("%6d", info->zi_max_size); + printk("%8llu", info->tzi_max_size); } - printf("%7d", info->zi_cur_size / info->zi_elem_size); - if (info->zi_max_size >= 99999 * 1024) { - printf(" ----"); + printf("%10llu", info->tzi_cur_size / info->tzi_elem_size); + if (info->tzi_max_size / 1024 >= 999999999) { + printf(" ---------"); } else { - printf("%7d", info->zi_max_size / info->zi_elem_size); + printf("%10llu", info->tzi_max_size / info->tzi_elem_size); } - printf("%6d", info->zi_count); - printk("%5d", info->zi_alloc_size); - printf("%6d", info->zi_alloc_size / info->zi_elem_size); - - totalused += used = info->zi_elem_size * info->zi_count; - totalsize += size = info->zi_cur_size; + printf("%10llu", info->tzi_count); + printk("%5llu", info->tzi_alloc_size); + printf("%6llu", info->tzi_alloc_size / info->tzi_elem_size); + + totalused += used = info->tzi_elem_size * info->tzi_count; + totalsize += size = info->tzi_cur_size; + totalsum += info->tzi_sum_size; + + printf(" %c%c%c", + (info->tzi_exhaustible ? 'X' : ' '), + (info->tzi_caller_acct ? 'A' : ' '), + (info->tzi_collectable ? 'C' : ' ')); if (ShowWasted) { - printf("%7d", size - used); + printk("%8llu", size - used); } - - printf("%c%c\n", - (info->zi_pageable ? 'P' : ' '), - (info->zi_collectable ? 'C' : ' ')); + if (ShowPid) { + printf("%8dK", (int)((info->tzi_task_alloc - info->tzi_task_free)/1024)); + } + if (ShowTotal) { + if (info->tzi_sum_size < 1024) + printf("%16lluB", info->tzi_sum_size); + else + printf("%16lluK", info->tzi_sum_size/1024); + } + printf("\n"); } static void -colprintzoneheader() +colprintzoneheader(void) { if (! PrintHeader) { return; } - if (ShowWasted) { - printf(" elem cur max cur max%s", - " cur alloc alloc\n"); - printf("zone name size size size #elts #elts%s", - " inuse size count wasted\n"); - } else { - printf(" elem cur max cur%s", - " max cur alloc alloc\n"); - printf("zone name size size size #elts%s", - " #elts inuse size count\n"); - } - printf("-----------------------------------------------%s", - "--------------------------------\n"); + printf("%s elem cur max cur max" + " cur alloc alloc %s\n", + (ShowWasted||ShowTotal)? "" : " ", (ShowPid) ? "PID" : "" ); + printf("zone name%s size size size #elts #elts" + " inuse size count ", (ShowWasted||ShowTotal)? "" : " " ); + if (ShowWasted) + printf(" wasted"); + if (ShowPid) + printf(" Allocs"); + if (ShowTotal) + printf(" Total Allocs"); + printf("\n%s------------------------------------------" + "--------------------------------------------", + (ShowWasted||ShowTotal)? "" : "-------"); + if (ShowWasted) + printf("---------"); + if (ShowPid) + printf("----------"); + if (ShowTotal) + printf("-----------------"); + printf("\n"); +} + +int +find_deltas(mach_zone_name_t *name, task_zone_info_t *info, task_zone_info_t *max_info, + char *deltas, int cnt, int first_time) +{ + int i; + int found_one = 0; + + for (i = 0; i < cnt; i++) { + deltas[i] = 0; + if (substr(zname, znamelen, name[i].mzn_name, + strnlen(name[i].mzn_name, sizeof name[i].mzn_name))) { + if (first_time || info->tzi_cur_size > max_info->tzi_cur_size || + (ShowTotal && ((info->tzi_sum_size >> 1) > max_info->tzi_sum_size))) { + max_info->tzi_cur_size = info->tzi_cur_size; + max_info->tzi_sum_size = info->tzi_sum_size; + deltas[i] = 1; + found_one = 1; + } + } + info++; + max_info++; + } + return(found_one); } -- 2.45.2