asf.c revision 116009
1116009Sgrog/* $Id: asf.c,v 1.4 2003/05/04 02:55:20 grog Exp grog $ */ 2116009Sgrog/* $FreeBSD: head/usr.sbin/asf/asf.c 116009 2003-06-08 06:18:13Z grog $ */ 3116009Sgrog 4116009Sgrog#define MAXLINE 1024 5116009Sgrog#include <ctype.h> 6116009Sgrog#include <errno.h> 7116009Sgrog#include <stdio.h> 8116009Sgrog#include <stdlib.h> 9116009Sgrog#include <string.h> 10116009Sgrog#include <sys/file.h> 11116009Sgrog#include <sys/param.h> 12116009Sgrog#include <sys/stat.h> 13116009Sgrog#include <sys/wait.h> 14116009Sgrog#include <sys/types.h> 15116009Sgrog#include <unistd.h> 16116009Sgrog 17116009Sgrog#define MAXTOKEN 10 18116009Sgrogchar *token[MAXTOKEN]; 19116009Sgrogchar *modules_path; /* path relative to kernel 20116009Sgrog * build directory */ 21116009Sgrogchar *outfile; /* and where to write the output */ 22116009Sgrog 23116009Sgrog/* 24116009Sgrog * Take a blank separated list of tokens and turn it into a list of 25116009Sgrog * individual nul-delimited strings. Build a list of pointers at 26116009Sgrog * token, which must have enough space for the tokens. Return the 27116009Sgrog * number of tokens, or -1 on error (typically a missing string 28116009Sgrog * delimiter). 29116009Sgrog */ 30116009Sgrogint 31116009Sgrogtokenize(char *cptr, char *token[], int maxtoken) 32116009Sgrog{ 33116009Sgrog char delim; /* delimiter to search for */ 34116009Sgrog int tokennr; /* index of this token */ 35116009Sgrog 36116009Sgrog for (tokennr = 0; tokennr < maxtoken;) { 37116009Sgrog while (isspace(*cptr)) 38116009Sgrog cptr++; /* skip initial white space */ 39116009Sgrog if ((*cptr == '\0') || (*cptr == '\n') 40116009Sgrog || (*cptr == '#')) /* end of line */ 41116009Sgrog return tokennr; /* return number of tokens found */ 42116009Sgrog delim = *cptr; 43116009Sgrog token[tokennr] = cptr; /* point to it */ 44116009Sgrog tokennr++; /* one more */ 45116009Sgrog if (tokennr == maxtoken) /* run off the end? */ 46116009Sgrog return tokennr; 47116009Sgrog if ((delim == '\'') || (delim == '"')) { /* delimitered */ 48116009Sgrog for (;;) { 49116009Sgrog cptr++; 50116009Sgrog if ((*cptr == delim) 51116009Sgrog && (cptr[-1] != '\\')) { /* found the partner */ 52116009Sgrog cptr++; /* move on past */ 53116009Sgrog if (!isspace(*cptr)) /* no space after closing quote */ 54116009Sgrog return -1; 55116009Sgrog *cptr++ = '\0'; /* delimit */ 56116009Sgrog } else if ((*cptr == '\0') 57116009Sgrog || (*cptr == '\n')) /* end of line */ 58116009Sgrog return -1; 59116009Sgrog } 60116009Sgrog } else { /* not quoted */ 61116009Sgrog while ((*cptr != '\0') && (!isspace(*cptr)) && (*cptr != '\n')) 62116009Sgrog cptr++; 63116009Sgrog if (*cptr != '\0') /* not end of the line, */ 64116009Sgrog *cptr++ = '\0'; /* delimit and move to the next */ 65116009Sgrog } 66116009Sgrog } 67116009Sgrog return maxtoken; /* can't get here */ 68116009Sgrog} 69116009Sgrog 70116009Sgrogvoid 71116009Sgrogusage(char *myname) 72116009Sgrog{ 73116009Sgrog fprintf(stderr, 74116009Sgrog "Usage:\n" 75116009Sgrog "%s [-a] [-k] [modules-path [outfile]]\n\n" 76116009Sgrog "\t-a\tappend to outfile)\n" 77116009Sgrog "\t-k\ttake input from kldstat(8)\n", 78116009Sgrog "\t-x\tdon't append \".debug\" to module name\n", 79116009Sgrog myname); 80116009Sgrog} 81116009Sgrog 82116009Sgrogint 83116009Sgrogmain(int argc, char *argv[]) 84116009Sgrog{ 85116009Sgrog char buf[MAXLINE]; 86116009Sgrog FILE *kldstat; 87116009Sgrog FILE *objcopy; 88116009Sgrog FILE *out; /* output file */ 89116009Sgrog char ocbuf[MAXLINE]; 90116009Sgrog int tokens; /* number of tokens on line */ 91116009Sgrog char basetoken[MAXLINE]; 92116009Sgrog int i; 93116009Sgrog char *filemode = "w"; /* mode for outfile */ 94116009Sgrog char cwd[MAXPATHLEN]; /* current directory */ 95116009Sgrog char *debugname = ".debug"; /* some file names end in this */ 96116009Sgrog 97116009Sgrog getcwd(cwd, MAXPATHLEN); /* find where we are */ 98116009Sgrog kldstat = stdin; 99116009Sgrog for (i = 1; i < argc; i++) { 100116009Sgrog if (argv[i][0] == '-') { 101116009Sgrog if (strcmp(argv[i], "-k") == 0) { /* get input from kldstat(8) */ 102116009Sgrog if (!(kldstat = popen("kldstat", "r"))) { 103116009Sgrog perror("Can't start kldstat"); 104116009Sgrog return 1; 105116009Sgrog } 106116009Sgrog } else if (strcmp(argv[i], "-a") == 0) /* append to outfile */ 107116009Sgrog filemode = "a"; 108116009Sgrog else if (strcmp(argv[i], "-x") == 0) /* no .debug extension */ 109116009Sgrog debugname = ""; /* nothing */ 110116009Sgrog else { 111116009Sgrog fprintf(stderr, 112116009Sgrog "Invalid option: %s, aborting\n", 113116009Sgrog argv[i]); 114116009Sgrog usage(argv[0]); 115116009Sgrog return 1; 116116009Sgrog } 117116009Sgrog } else if (modules_path == NULL) 118116009Sgrog modules_path = argv[i]; 119116009Sgrog else if (outfile == NULL) 120116009Sgrog outfile = argv[i]; 121116009Sgrog else { 122116009Sgrog fprintf(stderr, 123116009Sgrog "Extraneous startup information: \"%s\", aborting\n", 124116009Sgrog argv[i]); 125116009Sgrog usage(argv[0]); 126116009Sgrog return 1; 127116009Sgrog } 128116009Sgrog } 129116009Sgrog if (modules_path == NULL) 130116009Sgrog modules_path = "modules"; 131116009Sgrog if (outfile == NULL) 132116009Sgrog outfile = ".asf"; 133116009Sgrog if ((out = fopen(outfile, filemode)) == NULL) { 134116009Sgrog fprintf(stderr, 135116009Sgrog "Can't open output file %s: %s (%d)\n", 136116009Sgrog outfile, 137116009Sgrog strerror(errno), 138116009Sgrog errno); 139116009Sgrog return 1; 140116009Sgrog } 141116009Sgrog while (fgets(buf, MAXLINE, kldstat)) { 142116009Sgrog if ((!(strstr(buf, "kernel"))) 143116009Sgrog && buf[0] != 'I') { 144116009Sgrog quad_t base; 145116009Sgrog quad_t textaddr; 146116009Sgrog quad_t dataaddr; 147116009Sgrog quad_t bssaddr; 148116009Sgrog 149116009Sgrog tokens = tokenize(buf, token, MAXTOKEN); 150116009Sgrog base = strtoll(token[2], NULL, 16); 151116009Sgrog strcpy(basetoken, token[4]); 152116009Sgrog basetoken[strlen(basetoken) - 3] = '\0'; /* cut off the .ko */ 153116009Sgrog snprintf(ocbuf, 154116009Sgrog MAXLINE, 155116009Sgrog "/usr/bin/objdump --section-headers %s/%s/%s%s", 156116009Sgrog modules_path, 157116009Sgrog basetoken, 158116009Sgrog token[4], 159116009Sgrog debugname); 160116009Sgrog if (!(objcopy = popen(ocbuf, "r"))) { 161116009Sgrog fprintf(stderr, 162116009Sgrog "Can't start %s: %s (%d)\n", 163116009Sgrog ocbuf, 164116009Sgrog strerror(errno), 165116009Sgrog errno); 166116009Sgrog return 1; 167116009Sgrog } 168116009Sgrog while (fgets(ocbuf, MAXLINE, objcopy)) { 169116009Sgrog int octokens; 170116009Sgrog char *octoken[MAXTOKEN]; 171116009Sgrog 172116009Sgrog octokens = tokenize(ocbuf, octoken, MAXTOKEN); 173116009Sgrog if (octokens > 1) { 174116009Sgrog if (!strcmp(octoken[1], ".text")) 175116009Sgrog textaddr = strtoll(octoken[3], NULL, 16) + base; 176116009Sgrog else if (!strcmp(octoken[1], ".data")) 177116009Sgrog dataaddr = strtoll(octoken[3], NULL, 16) + base; 178116009Sgrog else if (!strcmp(octoken[1], ".bss")) 179116009Sgrog bssaddr = strtoll(octoken[3], NULL, 16) + base; 180116009Sgrog } 181116009Sgrog } 182116009Sgrog if (textaddr) { /* we must have a text address */ 183116009Sgrog fprintf(out, 184116009Sgrog "add-symbol-file %s/%s/%s/%s%s 0x%llx", 185116009Sgrog cwd, 186116009Sgrog modules_path, 187116009Sgrog basetoken, 188116009Sgrog token[4], 189116009Sgrog debugname, 190116009Sgrog textaddr); 191116009Sgrog if (dataaddr) 192116009Sgrog fprintf(out, " -s .data 0x%llx", dataaddr); 193116009Sgrog if (bssaddr) 194116009Sgrog fprintf(out, " -s .bss 0x%llx", bssaddr); 195116009Sgrog fprintf(out, "\n"); 196116009Sgrog } 197116009Sgrog } 198116009Sgrog } 199116009Sgrog return 0; 200116009Sgrog} 201