asf.c revision 116016
1116014Sgrog/* 2116014Sgrog * Copyright (c) 2002, 2003 Greg Lehey 3116014Sgrog * All rights reserved. 4116014Sgrog * 5116014Sgrog * Redistribution and use in source and binary forms, with or without 6116014Sgrog * modification, are permitted provided that the following conditions 7116014Sgrog * are met: 8116014Sgrog * 1. Redistributions of source code must retain the above copyright 9116014Sgrog * notice, this list of conditions and the following disclaimer. 10116014Sgrog * 2. Redistributions in binary form must reproduce the above copyright 11116014Sgrog * notice, this list of conditions and the following disclaimer in the 12116014Sgrog * documentation and/or other materials provided with the distribution. 13116014Sgrog * 14116014Sgrog * This software is provided by the author ``as is'' and any express 15116014Sgrog * or implied warranties, including, but not limited to, the implied 16116014Sgrog * warranties of merchantability and fitness for a particular purpose 17116014Sgrog * are disclaimed. In no event shall the author be liable for any 18116014Sgrog * direct, indirect, incidental, special, exemplary, or consequential 19116014Sgrog * damages (including, but not limited to, procurement of substitute 20116014Sgrog * goods or services; loss of use, data, or profits; or business 21116014Sgrog * interruption) however caused and on any theory of liability, 22116014Sgrog * whether in contract, strict liability, or tort (including 23116014Sgrog * negligence or otherwise) arising in any way out of the use of this 24116014Sgrog * software, even if advised of the possibility of such damage. 25116014Sgrog */ 26116009Sgrog/* $Id: asf.c,v 1.4 2003/05/04 02:55:20 grog Exp grog $ */ 27116009Sgrog/* $FreeBSD: head/usr.sbin/asf/asf.c 116016 2003-06-08 08:33:48Z jmallett $ */ 28116009Sgrog 29116009Sgrog#define MAXLINE 1024 30116009Sgrog#include <ctype.h> 31116009Sgrog#include <errno.h> 32116009Sgrog#include <stdio.h> 33116009Sgrog#include <stdlib.h> 34116009Sgrog#include <string.h> 35116009Sgrog#include <sys/file.h> 36116009Sgrog#include <sys/param.h> 37116009Sgrog#include <sys/stat.h> 38116009Sgrog#include <sys/wait.h> 39116009Sgrog#include <sys/types.h> 40116009Sgrog#include <unistd.h> 41116009Sgrog 42116009Sgrog#define MAXTOKEN 10 43116009Sgrogchar *token[MAXTOKEN]; 44116009Sgrogchar *modules_path; /* path relative to kernel 45116009Sgrog * build directory */ 46116009Sgrogchar *outfile; /* and where to write the output */ 47116009Sgrog 48116009Sgrog/* 49116009Sgrog * Take a blank separated list of tokens and turn it into a list of 50116009Sgrog * individual nul-delimited strings. Build a list of pointers at 51116009Sgrog * token, which must have enough space for the tokens. Return the 52116009Sgrog * number of tokens, or -1 on error (typically a missing string 53116009Sgrog * delimiter). 54116009Sgrog */ 55116009Sgrogint 56116009Sgrogtokenize(char *cptr, char *token[], int maxtoken) 57116009Sgrog{ 58116009Sgrog char delim; /* delimiter to search for */ 59116009Sgrog int tokennr; /* index of this token */ 60116009Sgrog 61116009Sgrog for (tokennr = 0; tokennr < maxtoken;) { 62116009Sgrog while (isspace(*cptr)) 63116009Sgrog cptr++; /* skip initial white space */ 64116009Sgrog if ((*cptr == '\0') || (*cptr == '\n') 65116009Sgrog || (*cptr == '#')) /* end of line */ 66116009Sgrog return tokennr; /* return number of tokens found */ 67116009Sgrog delim = *cptr; 68116009Sgrog token[tokennr] = cptr; /* point to it */ 69116009Sgrog tokennr++; /* one more */ 70116009Sgrog if (tokennr == maxtoken) /* run off the end? */ 71116009Sgrog return tokennr; 72116009Sgrog if ((delim == '\'') || (delim == '"')) { /* delimitered */ 73116009Sgrog for (;;) { 74116009Sgrog cptr++; 75116009Sgrog if ((*cptr == delim) 76116009Sgrog && (cptr[-1] != '\\')) { /* found the partner */ 77116009Sgrog cptr++; /* move on past */ 78116009Sgrog if (!isspace(*cptr)) /* no space after closing quote */ 79116009Sgrog return -1; 80116009Sgrog *cptr++ = '\0'; /* delimit */ 81116009Sgrog } else if ((*cptr == '\0') 82116009Sgrog || (*cptr == '\n')) /* end of line */ 83116009Sgrog return -1; 84116009Sgrog } 85116009Sgrog } else { /* not quoted */ 86116009Sgrog while ((*cptr != '\0') && (!isspace(*cptr)) && (*cptr != '\n')) 87116009Sgrog cptr++; 88116009Sgrog if (*cptr != '\0') /* not end of the line, */ 89116009Sgrog *cptr++ = '\0'; /* delimit and move to the next */ 90116009Sgrog } 91116009Sgrog } 92116009Sgrog return maxtoken; /* can't get here */ 93116009Sgrog} 94116009Sgrog 95116009Sgrogvoid 96116009Sgrogusage(char *myname) 97116009Sgrog{ 98116009Sgrog fprintf(stderr, 99116009Sgrog "Usage:\n" 100116014Sgrog "%s [-a] [-k] [-t] [modules-path [outfile]]\n\n" 101116009Sgrog "\t-a\tappend to outfile)\n" 102116016Sjmallett "\t-k\ttake input from kldstat(8)\n" 103116009Sgrog "\t-x\tdon't append \".debug\" to module name\n", 104116009Sgrog myname); 105116009Sgrog} 106116009Sgrog 107116009Sgrogint 108116009Sgrogmain(int argc, char *argv[]) 109116009Sgrog{ 110116009Sgrog char buf[MAXLINE]; 111116009Sgrog FILE *kldstat; 112116009Sgrog FILE *objcopy; 113116009Sgrog FILE *out; /* output file */ 114116009Sgrog char ocbuf[MAXLINE]; 115116009Sgrog int tokens; /* number of tokens on line */ 116116009Sgrog char basetoken[MAXLINE]; 117116009Sgrog int i; 118116009Sgrog char *filemode = "w"; /* mode for outfile */ 119116009Sgrog char cwd[MAXPATHLEN]; /* current directory */ 120116009Sgrog char *debugname = ".debug"; /* some file names end in this */ 121116009Sgrog 122116009Sgrog getcwd(cwd, MAXPATHLEN); /* find where we are */ 123116009Sgrog kldstat = stdin; 124116009Sgrog for (i = 1; i < argc; i++) { 125116009Sgrog if (argv[i][0] == '-') { 126116009Sgrog if (strcmp(argv[i], "-k") == 0) { /* get input from kldstat(8) */ 127116009Sgrog if (!(kldstat = popen("kldstat", "r"))) { 128116009Sgrog perror("Can't start kldstat"); 129116009Sgrog return 1; 130116009Sgrog } 131116009Sgrog } else if (strcmp(argv[i], "-a") == 0) /* append to outfile */ 132116009Sgrog filemode = "a"; 133116009Sgrog else if (strcmp(argv[i], "-x") == 0) /* no .debug extension */ 134116009Sgrog debugname = ""; /* nothing */ 135116009Sgrog else { 136116009Sgrog fprintf(stderr, 137116009Sgrog "Invalid option: %s, aborting\n", 138116009Sgrog argv[i]); 139116009Sgrog usage(argv[0]); 140116009Sgrog return 1; 141116009Sgrog } 142116009Sgrog } else if (modules_path == NULL) 143116009Sgrog modules_path = argv[i]; 144116009Sgrog else if (outfile == NULL) 145116009Sgrog outfile = argv[i]; 146116009Sgrog else { 147116009Sgrog fprintf(stderr, 148116009Sgrog "Extraneous startup information: \"%s\", aborting\n", 149116009Sgrog argv[i]); 150116009Sgrog usage(argv[0]); 151116009Sgrog return 1; 152116009Sgrog } 153116009Sgrog } 154116009Sgrog if (modules_path == NULL) 155116009Sgrog modules_path = "modules"; 156116009Sgrog if (outfile == NULL) 157116009Sgrog outfile = ".asf"; 158116009Sgrog if ((out = fopen(outfile, filemode)) == NULL) { 159116009Sgrog fprintf(stderr, 160116009Sgrog "Can't open output file %s: %s (%d)\n", 161116009Sgrog outfile, 162116009Sgrog strerror(errno), 163116009Sgrog errno); 164116009Sgrog return 1; 165116009Sgrog } 166116009Sgrog while (fgets(buf, MAXLINE, kldstat)) { 167116009Sgrog if ((!(strstr(buf, "kernel"))) 168116009Sgrog && buf[0] != 'I') { 169116009Sgrog quad_t base; 170116009Sgrog quad_t textaddr; 171116009Sgrog quad_t dataaddr; 172116009Sgrog quad_t bssaddr; 173116009Sgrog 174116009Sgrog tokens = tokenize(buf, token, MAXTOKEN); 175116009Sgrog base = strtoll(token[2], NULL, 16); 176116009Sgrog strcpy(basetoken, token[4]); 177116009Sgrog basetoken[strlen(basetoken) - 3] = '\0'; /* cut off the .ko */ 178116009Sgrog snprintf(ocbuf, 179116009Sgrog MAXLINE, 180116009Sgrog "/usr/bin/objdump --section-headers %s/%s/%s%s", 181116009Sgrog modules_path, 182116009Sgrog basetoken, 183116009Sgrog token[4], 184116009Sgrog debugname); 185116009Sgrog if (!(objcopy = popen(ocbuf, "r"))) { 186116009Sgrog fprintf(stderr, 187116009Sgrog "Can't start %s: %s (%d)\n", 188116009Sgrog ocbuf, 189116009Sgrog strerror(errno), 190116009Sgrog errno); 191116009Sgrog return 1; 192116009Sgrog } 193116009Sgrog while (fgets(ocbuf, MAXLINE, objcopy)) { 194116009Sgrog int octokens; 195116009Sgrog char *octoken[MAXTOKEN]; 196116009Sgrog 197116009Sgrog octokens = tokenize(ocbuf, octoken, MAXTOKEN); 198116009Sgrog if (octokens > 1) { 199116009Sgrog if (!strcmp(octoken[1], ".text")) 200116009Sgrog textaddr = strtoll(octoken[3], NULL, 16) + base; 201116009Sgrog else if (!strcmp(octoken[1], ".data")) 202116009Sgrog dataaddr = strtoll(octoken[3], NULL, 16) + base; 203116009Sgrog else if (!strcmp(octoken[1], ".bss")) 204116009Sgrog bssaddr = strtoll(octoken[3], NULL, 16) + base; 205116009Sgrog } 206116009Sgrog } 207116009Sgrog if (textaddr) { /* we must have a text address */ 208116009Sgrog fprintf(out, 209116009Sgrog "add-symbol-file %s/%s/%s/%s%s 0x%llx", 210116009Sgrog cwd, 211116009Sgrog modules_path, 212116009Sgrog basetoken, 213116009Sgrog token[4], 214116009Sgrog debugname, 215116009Sgrog textaddr); 216116009Sgrog if (dataaddr) 217116009Sgrog fprintf(out, " -s .data 0x%llx", dataaddr); 218116009Sgrog if (bssaddr) 219116009Sgrog fprintf(out, " -s .bss 0x%llx", bssaddr); 220116009Sgrog fprintf(out, "\n"); 221116009Sgrog } 222116009Sgrog } 223116009Sgrog } 224116009Sgrog return 0; 225116009Sgrog} 226