BTW, I'd prefer to separate out the search_for_switch_to() patch because it
has nothing to do with kaslr.
Which is strange, since "context_switch" has been an inline function
for pretty much ever, and therefore is not even a kernel symbol. But
your kernel apparently does have context_switch as a discrete function.
What kernel version are you testing with? Is it a google-special
that maybe tinkers with the scheduler code?
Yes I was testing with a Google specific kernel, and yes it tinkers
with the scheduler code.
Dave
----- Original Message -----
> [PATCH 1/2] Add support to kaslr for offline vmcore files.
>
> This patch adds a --kaslr command line parameter for loading x86_64
> crash dumps with kaslr enabled. This reuses the code from 32-bit
> x86 relocations with some small changes. The ASLR offset is postive
> instead of negative. Also had to move the code to traverse the
> kernel section before the symbol storing code to figure out which
> symbols were outside any sections and therefore were not relocated.
>
> Also made a very small change in search_for_switch_to it was
> searching through gdb command output for a slightly incorrect syntax.
>
> Tested: Tested by loading kdump files from kernels with aslr enabled
> and not enabled. Ran bt, files, and struct file 0xXXXXXX.
>
> Signed-off-by: Andy Honig <ahonig(a)google.com>
> ---
> defs.h | 2 ++
> main.c | 8 ++++++--
> symbols.c | 66
> +++++++++++++++++++++++++++++++++++++++++++++------------------
> x86_64.c | 20 +++++++++++++------
> 4 files changed, 69 insertions(+), 27 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index 4cae5e5..c9a4b73 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2417,6 +2417,8 @@ struct symbol_table_data {
> ulong __per_cpu_end;
> off_t dwarf_debug_frame_file_offset;
> ulong dwarf_debug_frame_size;
> + ulong first_section_start;
> + ulong last_section_end;
> };
>
> /* flags for st */
> diff --git a/main.c b/main.c
> index e5829bc..39763da 100644
> --- a/main.c
> +++ b/main.c
> @@ -57,6 +57,7 @@ static struct option long_options[] = {
> {"CRASHPAGER", 0, 0, 0},
> {"no_scroll", 0, 0, 0},
> {"reloc", required_argument, 0, 0},
> + {"kaslr", required_argument, 0, 0},
> {"active", 0, 0, 0},
> {"minimal", 0, 0, 0},
> {"mod", required_argument, 0, 0},
> @@ -216,12 +217,15 @@ main(int argc, char **argv)
> else if (STREQ(long_options[option_index].name,
"mod"))
> kt->module_tree = optarg;
>
> - else if (STREQ(long_options[option_index].name,
"reloc")) {
> + else if (STREQ(long_options[option_index].name,
"reloc") ||
> + STREQ(long_options[option_index].name,
"kaslr")) {
> if (!calculate(optarg, &kt->relocate, NULL, 0))
{
> error(INFO, "invalid --reloc argument:
%s\n",
> optarg);
> program_usage(SHORT_FORM);
> - }
> + } else if (STREQ(long_options[option_index].name,
"kaslr")) {
> + kt->relocate *= -1;
> + }
> kt->flags |= RELOC_SET;
> }
>
> diff --git a/symbols.c b/symbols.c
> index d063a0a..28378ab 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -198,22 +198,6 @@ symtab_init(void)
> no_debugging_data(FATAL);
> }
>
> - symcount = bfd_read_minisymbols(st->bfd, FALSE, &minisyms, &size);
> -
> - if (symcount <= 0)
> - no_debugging_data(FATAL);
> -
> - sort_x = bfd_make_empty_symbol(st->bfd);
> - sort_y = bfd_make_empty_symbol(st->bfd);
> - if (sort_x == NULL || sort_y == NULL)
> - error(FATAL, "bfd_make_empty_symbol() failed\n");
> -
> - gnu_qsort(st->bfd, minisyms, symcount, size, sort_x, sort_y);
> -
> - store_symbols(st->bfd, FALSE, minisyms, symcount, size);
> -
> - free(minisyms);
> -
> /*
> * Gather references to the kernel sections.
> */
> @@ -222,6 +206,7 @@ symtab_init(void)
> error(FATAL, "symbol table section array malloc: %s\n",
> strerror(errno));
> BZERO(st->sections, st->bfd->section_count * sizeof(struct sec *));
> + st->first_section_start = st->last_section_end = 0;
>
> bfd_map_over_sections(st->bfd, section_header_info, KERNEL_SECTIONS);
> if ((st->flags & (NO_SEC_LOAD|NO_SEC_CONTENTS)) ==
> @@ -233,6 +218,22 @@ symtab_init(void)
> }
> }
>
> + symcount = bfd_read_minisymbols(st->bfd, FALSE, &minisyms, &size);
> +
> + if (symcount <= 0)
> + no_debugging_data(FATAL);
> +
> + sort_x = bfd_make_empty_symbol(st->bfd);
> + sort_y = bfd_make_empty_symbol(st->bfd);
> + if (sort_x == NULL || sort_y == NULL)
> + error(FATAL, "bfd_make_empty_symbol() failed\n");
> +
> + gnu_qsort(st->bfd, minisyms, symcount, size, sort_x, sort_y);
> +
> + store_symbols(st->bfd, FALSE, minisyms, symcount, size);
> +
> + free(minisyms);
> +
> symname_hash_init();
> symval_hash_init();
> }
> @@ -590,7 +591,7 @@ store_symbols(bfd *abfd, int dynamic, void *minisyms,
> long symcount,
> st->symcnt = 0;
> sp = st->symtable;
>
> - if (machine_type("X86")) {
> + if (machine_type("X86") || machine_type("X86_64")) {
> if (!(kt->flags & RELOC_SET))
> kt->flags |= RELOC_FORCE;
> } else
> @@ -663,7 +664,7 @@ store_sysmap_symbols(void)
> error(FATAL, "symbol table namespace malloc: %s\n",
> strerror(errno));
>
> - if (!machine_type("X86"))
> + if (!machine_type("X86") &&
!machine_type("X86_64"))
> kt->flags &= ~RELOC_SET;
>
> first = 0;
> @@ -735,7 +736,20 @@ relocate(ulong symval, char *symname, int first_symbol)
> break;
> }
>
> - return (symval - kt->relocate);
> + if (machine_type("X86_64")) {
> + /*
> + * There are some symbols which are outside of any section
> + * either because they are offsets or because they are absolute
> + * addresses. These should not be relocated.
> + */
> + if (symval >= st->first_section_start &&
> + symval <= st->last_section_end) {
> + return symval - kt->relocate;
> + } else {
> + return symval;
> + }
> + } else
> + return symval - kt->relocate;
> }
>
> /*
> @@ -9679,6 +9693,7 @@ section_header_info(bfd *bfd, asection *section, void
> *reqptr)
> struct load_module *lm;
> ulong request;
> asection **sec;
> + ulong section_end_address;
>
> request = ((ulong)reqptr);
>
> @@ -9697,6 +9712,11 @@ section_header_info(bfd *bfd, asection *section, void
> *reqptr)
> kt->etext_init = kt->stext_init +
> (ulong)bfd_section_size(bfd, section);
> }
> +
> + if (STREQ(bfd_get_section_name(bfd, section), ".text")) {
> + st->first_section_start = (ulong)
> + bfd_get_section_vma(bfd, section);
> + }
> if (STREQ(bfd_get_section_name(bfd, section), ".text") ||
> STREQ(bfd_get_section_name(bfd, section), ".data")) {
> if (!(bfd_get_section_flags(bfd, section) &
> SEC_LOAD))
> @@ -9713,6 +9733,14 @@ section_header_info(bfd *bfd, asection *section, void
> *reqptr)
> st->dwarf_debug_frame_file_offset =
(off_t)section->filepos;
> st->dwarf_debug_frame_size = (ulong)bfd_section_size(bfd,
section);
> }
> +
> + if (st->first_section_start != 0) {
> + section_end_address =
> + (ulong) bfd_get_section_vma(bfd, section) +
> + (ulong) bfd_section_size(bfd, section);
> + if (section_end_address > st->last_section_end)
> + st->last_section_end = section_end_address;
> + }
> break;
>
> case (ulong)MODULE_SECTIONS:
> diff --git a/x86_64.c b/x86_64.c
> index 8508e4f..b51e285 100644
> --- a/x86_64.c
> +++ b/x86_64.c
> @@ -5414,16 +5414,22 @@ search_for_switch_to(ulong start, ulong end)
> {
> ulong max_instructions, address;
> char buf1[BUFSIZE];
> - char buf2[BUFSIZE];
> + char search_string1[BUFSIZE];
> + char search_string2[BUFSIZE];
> int found;
>
> max_instructions = end - start;
> found = FALSE;
> sprintf(buf1, "x/%ldi 0x%lx", max_instructions, start);
> - if (symbol_exists("__switch_to"))
> - sprintf(buf2, "callq 0x%lx",
symbol_value("__switch_to"));
> - else
> - buf2[0] = NULLCHAR;
> + if (symbol_exists("__switch_to")) {
> + sprintf(search_string1,
> + "callq 0x%lx",
symbol_value("__switch_to"));
> + sprintf(search_string2,
> + "call 0x%lx",
symbol_value("__switch_to"));
> + } else {
> + search_string1[0] = NULLCHAR;
> + search_string2[0] = NULLCHAR;
> + }
>
> open_tmpfile();
>
> @@ -5436,7 +5442,9 @@ search_for_switch_to(ulong start, ulong end)
> break;
> if (strstr(buf1, "<__switch_to>"))
> found = TRUE;
> - if (strlen(buf2) && strstr(buf1, buf2))
> + if (strlen(search_string1) && strstr(buf1, search_string1))
> + found = TRUE;
> + if (strlen(search_string2) && strstr(buf1, search_string2))
> found = TRUE;
> }
> close_tmpfile();
> --
> 1.9.0.rc1.175.g0b1dcb5
>
> --
> Crash-utility mailing list
> Crash-utility(a)redhat.com
>
https://www.redhat.com/mailman/listinfo/crash-utility
>
--
Crash-utility mailing list
Crash-utility(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility