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.2 2006/01/11 02:00:13 corecode 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] [-x] [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"
172 "\t-x\tdon't append \".debug\" to module name\n",
177 main(int argc
, char *argv
[])
182 FILE *out
; /* output file */
184 int tokens
; /* number of tokens on line */
185 char basetoken
[MAXLINE
];
187 const char *filemode
= "w"; /* mode for outfile */
188 char cwd
[MAXPATHLEN
]; /* current directory */
189 char *token
[MAXTOKEN
];
193 getcwd(cwd
, MAXPATHLEN
); /* find where we are */
195 while ((ch
= getopt(argc
, argv
, "afks")) != -1) {
197 case 'k': /* get input from kldstat(8) */
198 if (!(kldstat
= popen("kldstat", "r"))) {
199 perror("Can't start kldstat");
203 case 'a': /* append to outfile */
206 case 's': /* no subdir */
207 nosubdir
= 1; /* nothing */
209 case 'f': /* find .ko (recursively) */
214 "Invalid option: %s, aborting\n",
225 modules_path
= argv
[0];
238 "Extraneous startup information: \"%s\", aborting\n",
240 usage(getprogname());
243 if (modules_path
== NULL
)
244 modules_path
= "modules";
247 if ((out
= fopen(outfile
, filemode
)) == NULL
) {
249 "Can't open output file %s: %s (%d)\n",
255 while (fgets(buf
, MAXLINE
, kldstat
)) {
256 if ((!(strstr(buf
, "kernel")))
263 tokens
= tokenize(buf
, token
, MAXTOKEN
);
264 base
= strtoll(token
[2], NULL
, 16);
266 strcpy(basetoken
, token
[4]);
267 basetoken
[strlen(basetoken
) - 3] = '/';
268 basetoken
[strlen(basetoken
) - 2] = '\0'; /* cut off the .ko */
271 "/usr/bin/objdump --section-headers %s/%s%s",
273 nosubdir
? "" : basetoken
,
278 modpath
= findmodule(strdup(modules_path
), token
[4]);
283 "/usr/bin/objdump --section-headers %s",
287 if (!(objcopy
= popen(ocbuf
, "r"))) {
289 "Can't start %s: %s (%d)\n",
295 while (fgets(ocbuf
, MAXLINE
, objcopy
)) {
297 char *octoken
[MAXTOKEN
];
299 octokens
= tokenize(ocbuf
, octoken
, MAXTOKEN
);
301 if (!strcmp(octoken
[1], ".text"))
302 textaddr
= strtoll(octoken
[3], NULL
, 16) + base
;
303 else if (!strcmp(octoken
[1], ".data"))
304 dataaddr
= strtoll(octoken
[3], NULL
, 16) + base
;
305 else if (!strcmp(octoken
[1], ".bss"))
306 bssaddr
= strtoll(octoken
[3], NULL
, 16) + base
;
309 if (textaddr
) { /* we must have a text address */
312 "add-symbol-file %s%s%s/%s%s 0x%llx",
313 modules_path
[0] != '/' ? cwd
: "",
314 modules_path
[0] != '/' ? "/" : "",
316 nosubdir
? "" : basetoken
,
322 modpath
= findmodule(strdup(modules_path
), token
[4]);
326 "add-symbol-file %s 0x%llx",
332 fprintf(out
, " -s .data 0x%llx", dataaddr
);
334 fprintf(out
, " -s .bss 0x%llx", bssaddr
);