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