summaryrefslogtreecommitdiffstats
path: root/scripts/ksymoops/ksymoops.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/ksymoops/ksymoops.c')
-rw-r--r--scripts/ksymoops/ksymoops.c678
1 files changed, 0 insertions, 678 deletions
diff --git a/scripts/ksymoops/ksymoops.c b/scripts/ksymoops/ksymoops.c
deleted file mode 100644
index 0cd65795b..000000000
--- a/scripts/ksymoops/ksymoops.c
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- ksymoops.c.
-
- Read a kernel Oops file and make the best stab at converting the code to
- instructions and mapping stack values to kernel symbols.
-
- Copyright Keith Owens <kaos@ocs.com.au>.
- Released under the GNU Public Licence, Version 2.
-*/
-
-#define VERSION "0.6e"
-
-/*
-
- Tue Jan 5 19:26:02 EST 1999
- Version 0.6e
- Added to kernel.
-
- Mon Jan 4 09:48:13 EST 1999
- Version 0.6d
- Add ARM support.
-
- Thu Nov 26 16:37:46 EST 1998
- Version 0.6c
- Typo in oops_code.
- Add -c option.
- Add -1 option.
- Report if options were specified or defaulted.
-
- Fri Nov 6 10:38:42 EST 1998
- Version 0.6b
- Remove false warnings when comparing ksyms and lsmod.
-
- Tue Nov 3 23:33:04 EST 1998
- Version 0.6a
- Performance inprovements.
-
- Tue Nov 3 02:31:01 EST 1998
- Version 0.6
- Read lsmod (/proc/modules).
- Ignore addresses 0-4095 when mapping address to symbol.
- Discard default objects if -o specified.
- Oops file must be regular.
- Add "invalid operand" to Oops_print.
- Move "Using_Version" copy to map.c.
- Add Makefile defaults for vmlinux, ksyms, objects, System.map, lsmod.
- Minor adjustment to re for ppc.
- Minor adjustment to re for objdump lines with <_EIP+xxx>.
- Convert from a.out to bfd, using same format as ksymoops.
- Added MIPS.
- PPC handling based on patches by "Ryan Nielsen" <ran@krazynet.com>
-
- Wed Oct 28 23:14:55 EST 1998
- Version 0.5
- No longer read vmlinux by default, it only duplicates System.map.
-
- Wed Oct 28 13:47:38 EST 1998
- Version 0.4
- Split into separate sources.
-
- Mon Oct 26 00:01:47 EST 1998
- Version 0.3c
- Add alpha (arm) processing.
-
- Mon Oct 26 00:01:47 EST 1998
- Version 0.3b
- Add sparc processing.
- Handle kernel symbol versions.
-
- Fri Oct 23 13:11:20 EST 1998
- Version 0.3
- Add -follow to find command for people who use symlinks to modules.
- Add Version_ checking.
-
- Thu Oct 22 22:28:30 EST 1998
- Version 0.2.
- Generalise text prefix handling.
- Handle messages on Code: line.
- Format addresses with leading zeroes.
- Minor bug fixes.
-
- Wed Oct 21 23:28:48 EST 1998
- Version 0.1. Rewrite from scratch in C.
-
- CREDITS.
- Oops disassembly based on ksymoops.cc,
- Copyright (C) 1995 Greg McGary <gkm@magilla.cichlid.com>
- m68k code based on ksymoops.cc changes by
- Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- */
-
-#include "ksymoops.h"
-#include <ctype.h>
-#include <errno.h>
-#include <malloc.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/utsname.h>
-
-char *prefix;
-char *path_nm = "/usr/bin/nm"; /* env KSYMOOPS_NM */
-char *path_find = "/usr/bin/find"; /* env KSYMOOPS_FIND */
-char *path_objdump = "/usr/bin/objdump"; /* env KSYMOOPS_OBJDUMP */
-int debug = 0;
-int errors = 0;
-int warnings = 0;
-
-SYMBOL_SET ss_vmlinux;
-SYMBOL_SET ss_ksyms_base;
-SYMBOL_SET *ss_ksyms_module;
-int ss_ksyms_modules;
-SYMBOL_SET ss_lsmod;
-SYMBOL_SET *ss_object;
-int ss_objects;
-SYMBOL_SET ss_system_map;
-
-SYMBOL_SET ss_merged; /* merged map with info from all sources */
-SYMBOL_SET ss_Version; /* Version_ numbers where available */
-
-/* Regular expression stuff */
-
-regex_t re_nm;
-regmatch_t *re_nm_pmatch;
-regex_t re_bracketed_address;
-regmatch_t *re_bracketed_address_pmatch;
-regex_t re_unbracketed_address;
-regmatch_t *re_unbracketed_address_pmatch;
-
-static void usage(void)
-{
- fprintf(stderr, "Version " VERSION "\n");
- fprintf(stderr, "usage: %s\n", prefix);
- fprintf(stderr,
- "\t\t[-v vmlinux]\tWhere to read vmlinux\n"
- "\t\t[-V]\t\tNo vmlinux is available\n"
- "\t\t[-o object_dir]\tDirectory containing modules\n"
- "\t\t[-O]\t\tNo modules is available\n"
- "\t\t[-k ksyms]\tWhere to read ksyms\n"
- "\t\t[-K]\t\tNo ksyms is available\n"
- "\t\t[-l lsmod]\tWhere to read lsmod\n"
- "\t\t[-L]\t\tNo lsmod is available\n"
- "\t\t[-m system.map]\tWhere to read System.map\n"
- "\t\t[-M]\t\tNo System.map is available\n"
- "\t\t[-s save.map]\tSave consolidated map\n"
- "\t\t[-d]\t\tIncrease debug level by 1\n"
- "\t\t[-h]\t\tPrint help text\n"
- "\t\t[-c code_bytes]\tHow many bytes in each unit of code\n"
- "\t\t[-1]\t\tOne shot toggle (exit after first Oops)\n"
- "\t\t<Oops.file\tOops report to decode\n"
- "\n"
- "\t\tAll flags can occur more than once. With the exception "
- "of -o\n"
- "\t\tand -d which are cumulative, the last occurrence of each "
- "flag is\n"
- "\t\tused. Note that \"-v my.vmlinux -V\" will be taken as "
- "\"No vmlinux\n"
- "\t\tavailable\" but \"-V -v my.vmlinux\" will read "
- "my.vmlinux. You\n"
- "\t\twill be warned about such combinations.\n"
- "\n"
- "\t\tEach occurrence of -d increases the debug level.\n"
- "\n"
- "\t\tEach -o flag can refer to a directory or to a single "
- "object\n"
- "\t\tfile. If a directory is specified then all *.o files in "
- "that\n"
- "\t\tdirectory and its subdirectories are assumed to be "
- "modules.\n"
- "\n"
- "\t\tIf any of the vmlinux, object_dir, ksyms or system.map "
- "options\n"
- "\t\tcontain the string *r (*m, *n, *s) then it is replaced "
- "at run\n"
- "\t\ttime by the current value of `uname -r` (-m, -n, -s).\n"
- "\n"
- "\t\tThe defaults can be changed in the Makefile, current "
- "defaults\n"
- "\t\tare\n\n"
- "\t\t\t"
-#ifdef DEF_VMLINUX
- "-v " DEF_LINUX
-#else
- "-V"
-#endif
- "\n"
- "\t\t\t"
-#ifdef DEF_OBJECTS
- "-o " DEF_OBJECTS
-#else
- "-O"
-#endif
- "\n"
- "\t\t\t"
-#ifdef DEF_KSYMS
- "-k " DEF_KSYMS
-#else
- "-K"
-#endif
- "\n"
- "\t\t\t"
-#ifdef DEF_LSMOD
- "-l " DEF_LSMOD
-#else
- "-L"
-#endif
- "\n"
- "\t\t\t"
-#ifdef DEF_MAP
- "-m " DEF_MAP
-#else
- "-M"
-#endif
- "\n"
- "\t\t\t-c %d\n" /* DEF_CODE_BYTES */
- "\t\t\tOops report is read from stdin\n"
- "\n",
- DEF_CODE_BYTES
- );
-}
-
-/* Check if possibly conflicting options were specified */
-static void multi_opt(int specl, int specu, char type, const char *using)
-{
- if (specl && specu) {
- fprintf(stderr,
- "Warning - you specified both -%c and -%c. Using '",
- type, toupper(type));
- ++warnings;
- if (using) {
- fprintf(stderr, "-%c %s", type, using);
- if (type == 'o')
- fprintf(stderr, " ...");
- fprintf(stderr, "'\n");
- }
- else
- fprintf(stderr, "-%c'\n", toupper(type));
- }
- else if (specl > 1 && type != 'o') {
- fprintf(stderr,
- "Warning - you specified -%c more than once. "
- "Using '-%c %s'\n",
- type, type, using);
- ++warnings;
- }
- else if (specu > 1) {
- fprintf(stderr,
- "Warning - you specified -%c more than once. "
- "Second and subsequent '-%c' ignored\n",
- toupper(type), toupper(type));
- ++warnings;
- }
-}
-
-/* If a name contains *r (*m, *n, *s), replace with the current value of
- * `uname -r` (-m, -n, -s). Actually uses uname system call rather than the
- * uname command but the result is the same.
- */
-static void convert_uname(char **name)
-{
- char *p, *newname, *oldname, *replacement;
- unsigned len;
- int free_oldname = 0;
- static char procname[] = "convert_uname";
-
- if (!*name)
- return;
-
- while ((p = strchr(*name, '*'))) {
- struct utsname buf;
- int i = uname(&buf);
- if (debug)
- fprintf(stderr, "DEBUG: %s %s in\n", procname, *name);
- if (i) {
- fprintf(stderr,
- "%s: uname failed, %s will not be processed\n",
- prefix, *name);
- perror(prefix);
- ++errors;
- return;
- }
- switch (*(p+1)) {
- case 'r':
- replacement = buf.release;
- break;
- case 'm':
- replacement = buf.machine;
- break;
- case 'n':
- replacement = buf.nodename;
- break;
- case 's':
- replacement = buf.sysname;
- break;
- default:
- fprintf(stderr,
- "%s: invalid replacement character '*%c' "
- "in %s\n",
- prefix, *(p+1), *name);
- ++errors;
- return;
- }
- len = strlen(*name)-2+strlen(replacement)+1;
- if (!(newname = malloc(len)))
- malloc_error(procname);
- strncpy(newname, *name, (p-*name));
- strcpy(newname+(p-*name), replacement);
- strcpy(newname+(p-*name)+strlen(replacement), p+2);
- p = newname+(p-*name)+strlen(replacement); /* no rescan */
- oldname = *name;
- *name = newname;
- if (free_oldname)
- free(oldname);
- free_oldname = 1;
- if (debug)
- fprintf(stderr, "DEBUG: %s %s out\n", procname, *name);
- }
- return;
-}
-
-/* Report if the option was specified or defaulted */
-static void spec_or_default(int spec, int *some_spec) {
- if (spec) {
- printf(" (specified)\n");
- if (some_spec)
- *some_spec = 1;
- }
- else
- printf(" (default)\n");
-}
-
-/* Parse the options. Verbose but what's new with getopt? */
-static void parse(int argc,
- char **argv,
- char **vmlinux,
- char ***object,
- int *objects,
- char **ksyms,
- char **lsmod,
- char **system_map,
- char **save_system_map,
- char ***filename,
- int *filecount,
- int *spec_h,
- int *code_bytes,
- int *one_shot
- )
-{
- int spec_v = 0, spec_V = 0;
- int spec_o = 0, spec_O = 0;
- int spec_k = 0, spec_K = 0;
- int spec_l = 0, spec_L = 0;
- int spec_m = 0, spec_M = 0;
- int spec_s = 0;
- int spec_c = 0;
-
- int c, i, some_spec = 0;
- char *p;
-
- while ((c = getopt(argc, argv, "v:Vo:Ok:Kl:Lm:Ms:dhc:1")) != EOF) {
- if (debug && c != 'd')
- fprintf(stderr, "DEBUG: getopt '%c' '%s'\n", c, optarg);
- switch(c) {
- case 'v':
- *vmlinux = optarg;
- ++spec_v;
- break;
- case 'V':
- *vmlinux = NULL;
- ++spec_V;
- break;
- case 'o':
- if (!spec_o) {
- /* First -o, discard default value(s) */
- for (i = 0; i < *objects; ++i)
- free((*object)[i]);
- free(*object);
- *object = NULL;
- *objects = 0;
- }
- *object = realloc(*object,
- ((*objects)+1)*sizeof(**object));
- if (!*object)
- malloc_error("object");
- if (!(p = strdup(optarg)))
- malloc_error("strdup -o");
- else {
- (*object)[(*objects)++] = p;
- ++spec_o;
- }
- break;
- case 'O':
- ++spec_O;
- for (i = 0; i < *objects; ++i)
- free((*object)[i]);
- free(*object);
- *object = NULL;
- *objects = 0;
- break;
- case 'k':
- *ksyms = optarg;
- ++spec_k;
- break;
- case 'K':
- *ksyms = NULL;
- ++spec_K;
- break;
- case 'l':
- *lsmod = optarg;
- ++spec_l;
- break;
- case 'L':
- *lsmod = NULL;
- ++spec_L;
- break;
- case 'm':
- *system_map = optarg;
- ++spec_m;
- break;
- case 'M':
- *system_map = NULL;
- ++spec_M;
- break;
- case 's':
- *save_system_map = optarg;
- ++spec_s;
- break;
- case 'd':
- ++debug;
- break;
- case 'h':
- usage();
- ++*spec_h;
- break;
- case 'c':
- ++spec_c;
- errno = 0;
- *code_bytes = strtoul(optarg, &p, 10);
- /* Oops_code_values assumes that code_bytes is a
- * multiple of 2.
- */
- if (!*optarg || *p || errno ||
- (*code_bytes != 1 &&
- *code_bytes != 2 &&
- *code_bytes != 4 &&
- *code_bytes != 8)) {
- fprintf(stderr,
- "%s Invalid value for -c '%s'\n",
- prefix, optarg);
- ++errors;
- if (errno)
- perror(" ");
- *code_bytes = DEF_CODE_BYTES;
- }
- break;
- case '1':
- *one_shot = !*one_shot;
- break;
- case '?':
- usage();
- exit(2);
- }
- }
-
- *filecount = argc - optind;
- *filename = argv + optind;
-
- /* Expand any requests for the current uname values */
- convert_uname(vmlinux);
- if (*objects) {
- for (i = 0; i < *objects; ++i)
- convert_uname(*object+i);
- }
- convert_uname(ksyms);
- convert_uname(lsmod);
- convert_uname(system_map);
-
- /* Check for multiple options specified */
- multi_opt(spec_v, spec_V, 'v', *vmlinux);
- multi_opt(spec_o, spec_O, 'o', *object ? **object : NULL);
- multi_opt(spec_k, spec_K, 'k', *ksyms);
- multi_opt(spec_l, spec_L, 'l', *lsmod);
- multi_opt(spec_m, spec_M, 'm', *system_map);
-
- printf("Options used:");
- if (*vmlinux)
- printf(" -v %s", *vmlinux);
- else
- printf(" -V");
- spec_or_default(spec_v || spec_V, &some_spec);
-
- printf(" ");
- if (*objects) {
- for (i = 0; i < *objects; ++i)
- printf(" -o %s", (*object)[i]);
- }
- else
- printf(" -O");
- spec_or_default(spec_o || spec_O, &some_spec);
-
- printf(" ");
- if (*ksyms)
- printf(" -k %s", *ksyms);
- else
- printf(" -K");
- spec_or_default(spec_k || spec_K, &some_spec);
-
- printf(" ");
- if (*lsmod)
- printf(" -l %s", *lsmod);
- else
- printf(" -L");
- spec_or_default(spec_l || spec_L, &some_spec);
-
- printf(" ");
- if (*system_map)
- printf(" -m %s", *system_map);
- else
- printf(" -M");
- spec_or_default(spec_m || spec_M, &some_spec);
-
- printf(" ");
- printf(" -c %d", *code_bytes);
- spec_or_default(spec_c, NULL);
-
- if (*one_shot) {
- printf(" ");
- printf(" -1");
- }
-
- printf("\n");
-
- if (!some_spec) {
- printf(
-"You did not tell me where to find symbol information. I will assume\n"
-"that the log matches the kernel and modules that are running right now\n"
-"and I'll use the default options above for symbol resolution.\n"
-"If the current kernel and/or modules do not match the log, you can get\n"
-"more accurate output by telling me the kernel version and where to find\n"
-"map, modules, ksyms etc. ksymoops -h explains the options.\n"
- "\n");
- ++warnings;
- }
-}
-
-/* Read environment variables */
-static void read_env(const char *external, char **internal)
-{
- char *p;
- if ((p = getenv(external))) {
- *internal = p;
- if (debug)
- fprintf(stderr,
- "DEBUG: env override %s=%s\n",
- external, *internal);
- }
- else {
- if (debug)
- fprintf(stderr,
- "DEBUG: env default %s=%s\n",
- external, *internal);
- }
-}
-
-
-int main(int argc, char **argv)
-{
- char *vmlinux = NULL;
- char **object = NULL;
- int objects = 0;
- char *ksyms = NULL;
- char *lsmod = NULL;
- char *system_map = NULL;
- char *save_system_map = NULL;
- char **filename;
- int filecount = 0;
- int spec_h = 0; /* -h was specified */
- int code_bytes = DEF_CODE_BYTES;
- int one_shot = 0;
- int i, ret;
-
- prefix = *argv;
- setvbuf(stdout, NULL, _IONBF, 0);
-
-#ifdef DEF_VMLINUX
- vmlinux = DEF_LINUX;
-#endif
-#ifdef DEF_OBJECTS
- {
- char *p;
- object = realloc(object, (objects+1)*sizeof(*object));
- if (!object)
- malloc_error("DEF_OBJECTS");
- if (!(p = strdup(DEF_OBJECTS)))
- malloc_error("DEF_OBJECTS");
- else
- object[objects++] = p;
- }
-#endif
-#ifdef DEF_KSYMS
- ksyms = DEF_KSYMS;
-#endif
-#ifdef DEF_LSMOD
- lsmod = DEF_LSMOD;
-#endif
-#ifdef DEF_MAP
- system_map = DEF_MAP;
-#endif
-
- parse(argc,
- argv,
- &vmlinux,
- &object,
- &objects,
- &ksyms,
- &lsmod,
- &system_map,
- &save_system_map,
- &filename,
- &filecount,
- &spec_h,
- &code_bytes,
- &one_shot
- );
-
- if (spec_h && filecount == 0)
- return(0); /* just the help text */
-
- if (errors)
- return(1);
-
- if (debug)
- fprintf(stderr, "DEBUG: level %d\n", debug);
-
- read_env("KSYMOOPS_NM", &path_nm);
- read_env("KSYMOOPS_FIND", &path_find);
- read_env("KSYMOOPS_OBJDUMP", &path_objdump);
-
- re_compile_common();
- ss_init_common();
-
- read_vmlinux(vmlinux);
- read_ksyms(ksyms);
- /* No point in reading modules unless ksyms shows modules loaded */
- if (ss_ksyms_modules) {
- expand_objects(object, objects);
- for (i = 0; i < ss_objects; ++i)
- read_object(ss_object[i].source, i);
- }
- else if (objects)
- printf("No modules in ksyms, skipping objects\n");
- /* No point in reading lsmod without ksyms */
- if (ss_ksyms_modules || ss_ksyms_base.used)
- read_lsmod(lsmod);
- else if (lsmod)
- printf("No ksyms, skipping lsmod\n");
- read_system_map(system_map);
- merge_maps(save_system_map);
-
- /* After all that work, it is finally time to read the Oops report */
- ret = Oops_read(filecount, filename, code_bytes, one_shot);
-
- if (warnings || errors) {
- printf("\n");
- if (warnings)
- printf("%d warning%s ",
- warnings, warnings == 1 ? "" : "s");
- if (warnings && errors)
- printf("and ");
- if (errors)
- printf("%d error%s ", errors, errors == 1 ? "" : "s");
- printf("issued. Results may not be reliable.\n");
- if (!ret)
- return(1);
- }
-
- return(ret);
-}