2 * Copyright (c) 2002, 2003 Greg Lehey
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * This software is provided by the author ``as is'' and any express
15 * or implied warranties, including, but not limited to, the implied
16 * warranties of merchantability and fitness for a particular purpose
17 * are disclaimed. In no event shall the author be liable for any
18 * direct, indirect, incidental, special, exemplary, or consequential
19 * damages (including, but not limited to, procurement of substitute
20 * goods or services; loss of use, data, or profits; or business
21 * interruption) however caused and on any theory of liability,
22 * whether in contract, strict liability, or tort (including
23 * negligence or otherwise) arising in any way out of the use of this
24 * software, even if advised of the possibility of such damage.
26 /* $Id: asf.c,v 1.6 2003/11/04 06:38:37 green Exp $ */
27 /* $FreeBSD: src/usr.sbin/asf/asf.c,v 1.6 2003/11/04 06:38:37 green Exp $ */
28 /* $DragonFly: src/usr.sbin/asf/asf.c,v 1.4 2007/11/12 21:19:11 swildner Exp $ */
37 #include <sys/param.h>
40 #include <sys/types.h>
45 const char *modules_path; /* path relative to kernel
47 const char *outfile; /* and where to write the output */
50 * Take a blank separated list of tokens and turn it into a list of
51 * individual nul-delimited strings. Build a list of pointers at
52 * token, which must have enough space for the tokens. Return the
53 * number of tokens, or -1 on error (typically a missing string
57 tokenize(char *cptr, char *token[], int maxtoken)
59 char delim; /* delimiter to search for */
60 int tokennr; /* index of this token */
62 for (tokennr = 0; tokennr < maxtoken;) {
63 while (isspace(*cptr))
64 cptr++; /* skip initial white space */
65 if ((*cptr == '\0') || (*cptr == '\n')
66 || (*cptr == '#')) /* end of line */
67 return tokennr; /* return number of tokens found */
69 token[tokennr] = cptr; /* point to it */
70 tokennr++; /* one more */
71 if (tokennr == maxtoken) /* run off the end? */
73 if ((delim == '\'') || (delim == '"')) { /* delimitered */
77 && (cptr[-1] != '\\')) { /* found the partner */
78 cptr++; /* move on past */
79 if (!isspace(*cptr)) /* no space after closing quote */
81 *cptr++ = '\0'; /* delimit */
82 } else if ((*cptr == '\0')
83 || (*cptr == '\n')) /* end of line */
86 } else { /* not quoted */
87 while ((*cptr != '\0') && (!isspace(*cptr)) && (*cptr != '\n'))
89 if (*cptr != '\0') /* not end of the line, */
90 *cptr++ = '\0'; /* delimit and move to the next */
93 return maxtoken; /* can't get here */
97 findmodule(char *modules_path, const char *module_name)
99 char *const path_argv[2] = { modules_path, NULL };
100 char *module_path = NULL;
101 int module_name_len = strlen(module_name);
105 if (modules_path == NULL) {
107 "Can't allocate memory to traverse a path: %s (%d)\n",
112 fts = fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
115 "Can't begin traversing path %s: %s (%d)\n",
121 while ((ftsent = fts_read(fts)) != NULL) {
122 if (ftsent->fts_info == FTS_DNR ||
123 ftsent->fts_info == FTS_ERR ||
124 ftsent->fts_info == FTS_NS) {
126 "Error while traversing path %s: %s (%d)\n",
132 if (ftsent->fts_info != FTS_F ||
133 ftsent->fts_namelen != module_name_len ||
134 memcmp(module_name, ftsent->fts_name, module_name_len) != 0)
136 if (asprintf(&module_path,
139 ftsent->fts_path) == -1) {
141 "Can't allocate memory traversing path %s: %s (%d)\n",
149 if (ftsent == NULL && errno != 0) {
151 "Couldn't complete traversing path %s: %s (%d)\n",
159 return (module_path);
163 usage(const char *myname)
167 "%s [-a] [-f] [-k] [-s] [modules-path [outfile]]\n\n"
168 "\t-a\tappend to outfile)\n"
169 "\t-f\tfind the module in any subdirectory of module-path\n"
170 "\t-k\ttake input from kldstat(8)\n"
171 "\t-s\tdon't prepend subdir for module path\n",
176 main(int argc, char *argv[])
181 FILE *out; /* output file */
183 int tokens; /* number of tokens on line */
184 char basetoken[MAXLINE];
186 const char *filemode = "w"; /* mode for outfile */
187 char cwd[MAXPATHLEN]; /* current directory */
188 char *token[MAXTOKEN];
192 getcwd(cwd, MAXPATHLEN); /* find where we are */
194 while ((ch = getopt(argc, argv, "afks")) != -1) {
196 case 'k': /* get input from kldstat(8) */
197 if (!(kldstat = popen("kldstat", "r"))) {
198 perror("Can't start kldstat");
202 case 'a': /* append to outfile */
205 case 's': /* no subdir */
206 nosubdir = 1; /* nothing */
208 case 'f': /* find .ko (recursively) */
213 "Invalid option: %s, aborting\n",
224 modules_path = argv[0];
237 "Extraneous startup information: \"%s\", aborting\n",
239 usage(getprogname());
242 if (modules_path == NULL)
243 modules_path = "modules";
246 if ((out = fopen(outfile, filemode)) == NULL) {
248 "Can't open output file %s: %s (%d)\n",
254 while (fgets(buf, MAXLINE, kldstat)) {
255 if ((!(strstr(buf, "kernel")))
262 tokens = tokenize(buf, token, MAXTOKEN);
263 base = strtoll(token[2], NULL, 16);
265 strcpy(basetoken, token[4]);
266 basetoken[strlen(basetoken) - 3] = '/';
267 basetoken[strlen(basetoken) - 2] = '\0'; /* cut off the .ko */
270 "/usr/bin/objdump --section-headers %s/%s%s",
272 nosubdir ? "" : basetoken,
277 modpath = findmodule(strdup(modules_path), token[4]);
282 "/usr/bin/objdump --section-headers %s",
286 if (!(objcopy = popen(ocbuf, "r"))) {
288 "Can't start %s: %s (%d)\n",
294 while (fgets(ocbuf, MAXLINE, objcopy)) {
296 char *octoken[MAXTOKEN];
298 octokens = tokenize(ocbuf, octoken, MAXTOKEN);
300 if (!strcmp(octoken[1], ".text"))
301 textaddr = strtoll(octoken[3], NULL, 16) + base;
302 else if (!strcmp(octoken[1], ".data"))
303 dataaddr = strtoll(octoken[3], NULL, 16) + base;
304 else if (!strcmp(octoken[1], ".bss"))
305 bssaddr = strtoll(octoken[3], NULL, 16) + base;
308 if (textaddr) { /* we must have a text address */
311 "add-symbol-file %s%s%s/%s%s 0x%llx",
312 modules_path[0] != '/' ? cwd : "",
313 modules_path[0] != '/' ? "/" : "",
315 nosubdir ? "" : basetoken,
321 modpath = findmodule(strdup(modules_path), token[4]);
325 "add-symbol-file %s 0x%llx",
331 fprintf(out, " -s .data 0x%llx", dataaddr);
333 fprintf(out, " -s .bss 0x%llx", bssaddr);