From 9254c7f206d54fe6b0bf69086d0cbec83b4ace32 Mon Sep 17 00:00:00 2001 From: Dave Anderson Date: Tue, 1 Sep 2015 16:23:24 -0400 Subject: [PATCH] Added a new "--src " command line option for use by the "dis -s" option if the kernel source code is not located in the standard location that is compiled into the kernel's debuginfo data. The directory argument should point to the top-level directory of the kernel source tree. (anderson@redhat.com) --- defs.h | 1 + help.c | 4 ++++ kernel.c | 39 +++++++++++++++++++++++++++++++++++++++ main.c | 4 ++++ 4 files changed, 48 insertions(+) diff --git a/defs.h b/defs.h index 0169889c..b0cdd42e 100644 --- a/defs.h +++ b/defs.h @@ -732,6 +732,7 @@ struct kernel_table { /* kernel data */ ulong _stext_SYMBOL; } vmcoreinfo; ulonglong flags2; + char *source_tree; }; /* diff --git a/help.c b/help.c index c3a0667b..883ddd01 100644 --- a/help.c +++ b/help.c @@ -309,6 +309,10 @@ char *program_usage_info[] = { " command, search for their object files in directory instead of in ", " the standard location.", "", + " --src directory", + " Search for the kernel source code in directory instead of in the", + " standard location that is compiled into the debuginfo data.", + "", " --reloc size", " When analyzing live x86 kernels configured with a CONFIG_PHYSICAL_START ", " value that is larger than its CONFIG_PHYSICAL_ALIGN value, then it will", diff --git a/kernel.c b/kernel.c index 8afc97bb..d069c9dd 100644 --- a/kernel.c +++ b/kernel.c @@ -78,6 +78,7 @@ static void dump_variable_length_record(void); static int is_livepatch(void); static void show_kernel_taints(char *, int); static void list_source_code(struct gnu_request *, int); +static void source_tree_init(void); /* @@ -728,6 +729,9 @@ kernel_init() if (INVALID_MEMBER(ktime_t_nsec)) MEMBER_OFFSET_INIT(ktime_t_nsec, "ktime_t", "nsec"); + if (kt->source_tree) + source_tree_init(); + kt->flags &= ~PRE_KERNEL_INIT; } @@ -1318,6 +1322,39 @@ verify_namelist() program_usage(SHORT_FORM); } +/* + * Set up the gdb source code path. + */ +static void +source_tree_init(void) +{ + FILE *pipe; + char command[BUFSIZE]; + char buf[BUFSIZE]; + + if (!is_directory(kt->source_tree)) { + error(INFO, "invalid --src argument: %s\n\n", + kt->source_tree); + kt->source_tree = NULL; + return; + } + + sprintf(command, "/usr/bin/ls -d %s/arch/*/include/asm 2>/dev/null", + kt->source_tree); + if ((pipe = popen(command, "r"))) { + if (fgets(buf, BUFSIZE-1, pipe)) { + sprintf(command, "directory %s", buf); + gdb_pass_through(command, NULL, GNU_RETURN_ON_ERROR); + } + pclose(pipe); + } else + error(INFO, "%s: %s\n", command, strerror(errno)); + + sprintf(command, "directory %s", kt->source_tree); + gdb_pass_through(command, NULL, GNU_RETURN_ON_ERROR); + +} + static void list_source_code(struct gnu_request *req, int count_entered) @@ -5557,6 +5594,8 @@ dump_kernel_table(int verbose) fprintf(fp, "mods_installed: %d\n", kt->mods_installed); fprintf(fp, " module_tree: %s\n", kt->module_tree ? kt->module_tree : "(not used)"); + fprintf(fp, " source_tree: %s\n", kt->source_tree ? + kt->source_tree : "(not used)"); if (!(pc->flags & KERNEL_DEBUG_QUERY) && ACTIVE()) get_xtime(&kt->date); fprintf(fp, " date: %s\n", diff --git a/main.c b/main.c index ccb5e337..fccbfe55 100644 --- a/main.c +++ b/main.c @@ -72,6 +72,7 @@ static struct option long_options[] = { {"no_strip", 0, 0, 0}, {"hash", required_argument, 0, 0}, {"offline", required_argument, 0, 0}, + {"src", required_argument, 0, 0}, {0, 0, 0, 0} }; @@ -293,6 +294,9 @@ main(int argc, char **argv) } } + else if (STREQ(long_options[option_index].name, "src")) + kt->source_tree = optarg; + else { error(INFO, "internal error: option %s unhandled\n", long_options[option_index].name);