diff options
author | grog <grog@FreeBSD.org> | 2003-06-08 06:18:13 +0000 |
---|---|---|
committer | grog <grog@FreeBSD.org> | 2003-06-08 06:18:13 +0000 |
commit | f43a5d35329d6ca5a8be2b769410927ebfab1d48 (patch) | |
tree | bd300ed2ffd73e907734d499baa54d3cc350e589 /usr.sbin/asf | |
parent | bdb8232f29e0189c9f6236c04240436aafae4eb5 (diff) | |
download | FreeBSD-src-f43a5d35329d6ca5a8be2b769410927ebfab1d48.zip FreeBSD-src-f43a5d35329d6ca5a8be2b769410927ebfab1d48.tar.gz |
Introducing asf, a helper program for kernel debugging.
Diffstat (limited to 'usr.sbin/asf')
-rw-r--r-- | usr.sbin/asf/Makefile | 7 | ||||
-rw-r--r-- | usr.sbin/asf/asf.c | 200 |
2 files changed, 207 insertions, 0 deletions
diff --git a/usr.sbin/asf/Makefile b/usr.sbin/asf/Makefile new file mode 100644 index 0000000..19df365 --- /dev/null +++ b/usr.sbin/asf/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= asf +SRCS= asf.c +MAN= asf.8 +WARNS= 0 +.include <bsd.prog.mk> diff --git a/usr.sbin/asf/asf.c b/usr.sbin/asf/asf.c new file mode 100644 index 0000000..f6d4d70 --- /dev/null +++ b/usr.sbin/asf/asf.c @@ -0,0 +1,200 @@ +/* $Id: asf.c,v 1.4 2003/05/04 02:55:20 grog Exp grog $ */ +/* $FreeBSD$ */ + +#define MAXLINE 1024 +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/file.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <unistd.h> + +#define MAXTOKEN 10 +char *token[MAXTOKEN]; +char *modules_path; /* path relative to kernel + * build directory */ +char *outfile; /* and where to write the output */ + +/* + * Take a blank separated list of tokens and turn it into a list of + * individual nul-delimited strings. Build a list of pointers at + * token, which must have enough space for the tokens. Return the + * number of tokens, or -1 on error (typically a missing string + * delimiter). + */ +int +tokenize(char *cptr, char *token[], int maxtoken) +{ + char delim; /* delimiter to search for */ + int tokennr; /* index of this token */ + + for (tokennr = 0; tokennr < maxtoken;) { + while (isspace(*cptr)) + cptr++; /* skip initial white space */ + if ((*cptr == '\0') || (*cptr == '\n') + || (*cptr == '#')) /* end of line */ + return tokennr; /* return number of tokens found */ + delim = *cptr; + token[tokennr] = cptr; /* point to it */ + tokennr++; /* one more */ + if (tokennr == maxtoken) /* run off the end? */ + return tokennr; + if ((delim == '\'') || (delim == '"')) { /* delimitered */ + for (;;) { + cptr++; + if ((*cptr == delim) + && (cptr[-1] != '\\')) { /* found the partner */ + cptr++; /* move on past */ + if (!isspace(*cptr)) /* no space after closing quote */ + return -1; + *cptr++ = '\0'; /* delimit */ + } else if ((*cptr == '\0') + || (*cptr == '\n')) /* end of line */ + return -1; + } + } else { /* not quoted */ + while ((*cptr != '\0') && (!isspace(*cptr)) && (*cptr != '\n')) + cptr++; + if (*cptr != '\0') /* not end of the line, */ + *cptr++ = '\0'; /* delimit and move to the next */ + } + } + return maxtoken; /* can't get here */ +} + +void +usage(char *myname) +{ + fprintf(stderr, + "Usage:\n" + "%s [-a] [-k] [modules-path [outfile]]\n\n" + "\t-a\tappend to outfile)\n" + "\t-k\ttake input from kldstat(8)\n", + "\t-x\tdon't append \".debug\" to module name\n", + myname); +} + +int +main(int argc, char *argv[]) +{ + char buf[MAXLINE]; + FILE *kldstat; + FILE *objcopy; + FILE *out; /* output file */ + char ocbuf[MAXLINE]; + int tokens; /* number of tokens on line */ + char basetoken[MAXLINE]; + int i; + char *filemode = "w"; /* mode for outfile */ + char cwd[MAXPATHLEN]; /* current directory */ + char *debugname = ".debug"; /* some file names end in this */ + + getcwd(cwd, MAXPATHLEN); /* find where we are */ + kldstat = stdin; + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-k") == 0) { /* get input from kldstat(8) */ + if (!(kldstat = popen("kldstat", "r"))) { + perror("Can't start kldstat"); + return 1; + } + } else if (strcmp(argv[i], "-a") == 0) /* append to outfile */ + filemode = "a"; + else if (strcmp(argv[i], "-x") == 0) /* no .debug extension */ + debugname = ""; /* nothing */ + else { + fprintf(stderr, + "Invalid option: %s, aborting\n", + argv[i]); + usage(argv[0]); + return 1; + } + } else if (modules_path == NULL) + modules_path = argv[i]; + else if (outfile == NULL) + outfile = argv[i]; + else { + fprintf(stderr, + "Extraneous startup information: \"%s\", aborting\n", + argv[i]); + usage(argv[0]); + return 1; + } + } + if (modules_path == NULL) + modules_path = "modules"; + if (outfile == NULL) + outfile = ".asf"; + if ((out = fopen(outfile, filemode)) == NULL) { + fprintf(stderr, + "Can't open output file %s: %s (%d)\n", + outfile, + strerror(errno), + errno); + return 1; + } + while (fgets(buf, MAXLINE, kldstat)) { + if ((!(strstr(buf, "kernel"))) + && buf[0] != 'I') { + quad_t base; + quad_t textaddr; + quad_t dataaddr; + quad_t bssaddr; + + tokens = tokenize(buf, token, MAXTOKEN); + base = strtoll(token[2], NULL, 16); + strcpy(basetoken, token[4]); + basetoken[strlen(basetoken) - 3] = '\0'; /* cut off the .ko */ + snprintf(ocbuf, + MAXLINE, + "/usr/bin/objdump --section-headers %s/%s/%s%s", + modules_path, + basetoken, + token[4], + debugname); + if (!(objcopy = popen(ocbuf, "r"))) { + fprintf(stderr, + "Can't start %s: %s (%d)\n", + ocbuf, + strerror(errno), + errno); + return 1; + } + while (fgets(ocbuf, MAXLINE, objcopy)) { + int octokens; + char *octoken[MAXTOKEN]; + + octokens = tokenize(ocbuf, octoken, MAXTOKEN); + if (octokens > 1) { + if (!strcmp(octoken[1], ".text")) + textaddr = strtoll(octoken[3], NULL, 16) + base; + else if (!strcmp(octoken[1], ".data")) + dataaddr = strtoll(octoken[3], NULL, 16) + base; + else if (!strcmp(octoken[1], ".bss")) + bssaddr = strtoll(octoken[3], NULL, 16) + base; + } + } + if (textaddr) { /* we must have a text address */ + fprintf(out, + "add-symbol-file %s/%s/%s/%s%s 0x%llx", + cwd, + modules_path, + basetoken, + token[4], + debugname, + textaddr); + if (dataaddr) + fprintf(out, " -s .data 0x%llx", dataaddr); + if (bssaddr) + fprintf(out, " -s .bss 0x%llx", bssaddr); + fprintf(out, "\n"); + } + } + } + return 0; +} |