commit 46d2121960d81354facf4e2558c81f82257b740e Author: Dave Anderson Date: Tue May 29 14:04:03 2018 -0400 Fix for the "timer -r" command on Linux 4.10 and later kernels that contain commit 2456e855354415bfaeb7badaa14e11b3e02c8466, titled "ktime: Get rid of the union". Without the patch, the command fails with the error message "timer: invalid structure member offset: ktime_t_sec". (k-hagio@ab.jp.nec.com) diff --git a/kernel.c b/kernel.c index b1886ce..138a47f 100644 --- a/kernel.c +++ b/kernel.c @@ -7740,7 +7740,7 @@ ktime_to_ns(const void *ktime) if (VALID_MEMBER(ktime_t_tv64)) { readmem((ulong)ktime + OFFSET(ktime_t_tv64), KVADDR, &ns, sizeof(ns), "ktime_t tv64", QUIET|RETURN_ON_ERROR); - } else { + } else if (VALID_MEMBER(ktime_t_sec) && VALID_MEMBER(ktime_t_nsec)) { uint32_t sec, nsec; sec = 0; @@ -7753,6 +7753,9 @@ ktime_to_ns(const void *ktime) sizeof(nsec), "ktime_t nsec", QUIET|RETURN_ON_ERROR); ns = sec * 1000000000L + nsec; + } else { + readmem((ulong)ktime, KVADDR, &ns, + sizeof(ns), "ktime_t", QUIET|RETURN_ON_ERROR); } return ns; commit a6cd8408d1d214a67ed0c4b09343fec77a8e2ae7 Author: Dave Anderson Date: Thu May 31 11:43:14 2018 -0400 Fix for the x86 and x86_64 "mach -m" option on Linux 4.12 and later kernels to account for the structure name changes "e820map" to "e820_table", and "e820entry" to "e820_entry", and for the symbol name change from "e820" to "e820_table". Also updated the display output to properly translate E820_PRAM and E820_RESERVED_KERN entries. Without the patch on all kernels, E820_PRAM and E820_RESERVED_KERN entries show "type 12" and "type 128" respectively. Without the patch on Linux 4.12 and later kernels, the command fails with the error message "mach: cannot resolve e820". (anderson@redhat.com) diff --git a/x86.c b/x86.c index 47767b6..88562b6 100644 --- a/x86.c +++ b/x86.c @@ -1,8 +1,8 @@ /* x86.c - core analysis suite * * Portions Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002-2014,2017 David Anderson - * Copyright (C) 2002-2014,2017 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002-2014,2017-2018 David Anderson + * Copyright (C) 2002-2014,2017-2018 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1967,15 +1967,27 @@ x86_init(int when) } MEMBER_OFFSET_INIT(thread_struct_cr3, "thread_struct", "cr3"); STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86"); - STRUCT_SIZE_INIT(e820map, "e820map"); - STRUCT_SIZE_INIT(e820entry, "e820entry"); STRUCT_SIZE_INIT(irq_ctx, "irq_ctx"); + if (STRUCT_EXISTS("e820map")) { + STRUCT_SIZE_INIT(e820map, "e820map"); + MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map"); + } else { + STRUCT_SIZE_INIT(e820map, "e820_table"); + MEMBER_OFFSET_INIT(e820map_nr_map, "e820_table", "nr_entries"); + } + if (STRUCT_EXISTS("e820entry")) { + STRUCT_SIZE_INIT(e820entry, "e820entry"); + MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr"); + MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size"); + MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type"); + } else { + STRUCT_SIZE_INIT(e820entry, "e820_entry"); + MEMBER_OFFSET_INIT(e820entry_addr, "e820_entry", "addr"); + MEMBER_OFFSET_INIT(e820entry_size, "e820_entry", "size"); + MEMBER_OFFSET_INIT(e820entry_type, "e820_entry", "type"); + } if (!VALID_STRUCT(irq_ctx)) STRUCT_SIZE_INIT(irq_ctx, "irq_stack"); - MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map"); - MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr"); - MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size"); - MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type"); if (KVMDUMP_DUMPFILE()) set_kvm_iohole(NULL); if (symbol_exists("irq_desc")) @@ -4415,33 +4427,54 @@ static char *e820type[] = { static void x86_display_memmap(void) { - ulong e820; - int nr_map, i; - char *buf, *e820entry_ptr; - ulonglong addr, size; - ulong type; + ulong e820; + int nr_map, i; + char *buf, *e820entry_ptr; + ulonglong addr, size; + uint type; + + if (kernel_symbol_exists("e820")) { + if (get_symbol_type("e820", NULL, NULL) == TYPE_CODE_PTR) + get_symbol_data("e820", sizeof(void *), &e820); + else + e820 = symbol_value("e820"); + + } else if (kernel_symbol_exists("e820_table")) + get_symbol_data("e820_table", sizeof(void *), &e820); + else + error(FATAL, "neither e820 or e820_table symbols exist\n"); - e820 = symbol_value("e820"); - buf = (char *)GETBUF(SIZE(e820map)); + if (CRASHDEBUG(1)) { + if (STRUCT_EXISTS("e820map")) + dump_struct("e820map", e820, RADIX(16)); + else if (STRUCT_EXISTS("e820_table")) + dump_struct("e820_table", e820, RADIX(16)); + } + buf = (char *)GETBUF(SIZE(e820map)); - readmem(e820, KVADDR, &buf[0], SIZE(e820map), - "e820map", FAULT_ON_ERROR); + readmem(e820, KVADDR, &buf[0], SIZE(e820map), + "e820map", FAULT_ON_ERROR); - nr_map = INT(buf + OFFSET(e820map_nr_map)); + nr_map = INT(buf + OFFSET(e820map_nr_map)); - fprintf(fp, " PHYSICAL ADDRESS RANGE TYPE\n"); + fprintf(fp, " PHYSICAL ADDRESS RANGE TYPE\n"); - for (i = 0; i < nr_map; i++) { - e820entry_ptr = buf + sizeof(int) + (SIZE(e820entry) * i); - addr = ULONGLONG(e820entry_ptr + OFFSET(e820entry_addr)); - size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size)); - type = ULONG(e820entry_ptr + OFFSET(e820entry_type)); + for (i = 0; i < nr_map; i++) { + e820entry_ptr = buf + sizeof(int) + (SIZE(e820entry) * i); + addr = ULONGLONG(e820entry_ptr + OFFSET(e820entry_addr)); + size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size)); + type = UINT(e820entry_ptr + OFFSET(e820entry_type)); fprintf(fp, "%016llx - %016llx ", addr, addr+size); - if (type >= (sizeof(e820type)/sizeof(char *))) - fprintf(fp, "type %ld\n", type); - else + if (type >= (sizeof(e820type)/sizeof(char *))) { + if (type == 12) + fprintf(fp, "E820_PRAM\n"); + else if (type == 128) + fprintf(fp, "E820_RESERVED_KERN\n"); + else + fprintf(fp, "type %d\n", type); + } else fprintf(fp, "%s\n", e820type[type]); - } + } } /* diff --git a/x86_64.c b/x86_64.c index 921552b..1d5e155 100644 --- a/x86_64.c +++ b/x86_64.c @@ -415,12 +415,26 @@ x86_64_init(int when) STRUCT_SIZE_INIT(gate_struct, "gate_desc"); else STRUCT_SIZE_INIT(gate_struct, "gate_struct"); - STRUCT_SIZE_INIT(e820map, "e820map"); - STRUCT_SIZE_INIT(e820entry, "e820entry"); - MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map"); - MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr"); - MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size"); - MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type"); + + if (STRUCT_EXISTS("e820map")) { + STRUCT_SIZE_INIT(e820map, "e820map"); + MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map"); + } else { + STRUCT_SIZE_INIT(e820map, "e820_table"); + MEMBER_OFFSET_INIT(e820map_nr_map, "e820_table", "nr_entries"); + } + if (STRUCT_EXISTS("e820entry")) { + STRUCT_SIZE_INIT(e820entry, "e820entry"); + MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr"); + MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size"); + MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type"); + } else { + STRUCT_SIZE_INIT(e820entry, "e820_entry"); + MEMBER_OFFSET_INIT(e820entry_addr, "e820_entry", "addr"); + MEMBER_OFFSET_INIT(e820entry_size, "e820_entry", "size"); + MEMBER_OFFSET_INIT(e820entry_type, "e820_entry", "type"); + } + if (KVMDUMP_DUMPFILE()) set_kvm_iohole(NULL); MEMBER_OFFSET_INIT(thread_struct_rip, "thread_struct", "rip"); @@ -5643,12 +5657,23 @@ x86_64_display_memmap(void) ulonglong addr, size; uint type; - if (get_symbol_type("e820", NULL, NULL) == TYPE_CODE_PTR) - get_symbol_data("e820", sizeof(void *), &e820); + if (kernel_symbol_exists("e820")) { + if (get_symbol_type("e820", NULL, NULL) == TYPE_CODE_PTR) + get_symbol_data("e820", sizeof(void *), &e820); + else + e820 = symbol_value("e820"); + + } else if (kernel_symbol_exists("e820_table")) + get_symbol_data("e820_table", sizeof(void *), &e820); else - e820 = symbol_value("e820"); - if (CRASHDEBUG(1)) - dump_struct("e820map", e820, RADIX(16)); + error(FATAL, "neither e820 or e820_table symbols exist\n"); + + if (CRASHDEBUG(1)) { + if (STRUCT_EXISTS("e820map")) + dump_struct("e820map", e820, RADIX(16)); + else if (STRUCT_EXISTS("e820_table")) + dump_struct("e820_table", e820, RADIX(16)); + } buf = (char *)GETBUF(SIZE(e820map)); readmem(e820, KVADDR, &buf[0], SIZE(e820map), @@ -5664,9 +5689,14 @@ x86_64_display_memmap(void) size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size)); type = UINT(e820entry_ptr + OFFSET(e820entry_type)); fprintf(fp, "%016llx - %016llx ", addr, addr+size); - if (type >= (sizeof(e820type)/sizeof(char *))) - fprintf(fp, "type %d\n", type); - else + if (type >= (sizeof(e820type)/sizeof(char *))) { + if (type == 12) + fprintf(fp, "E820_PRAM\n"); + else if (type == 128) + fprintf(fp, "E820_RESERVED_KERN\n"); + else + fprintf(fp, "type %d\n", type); + } else fprintf(fp, "%s\n", e820type[type]); } } commit da49e2010b3cb88b4755d69d38fe90af6ba218b2 Author: Dave Anderson Date: Fri Jun 1 10:58:00 2018 -0400 Update for the recognition of the new x86_64 CPU_ENTRY_AREA virtual address range introduced in Linux 4.15. The memory range exists above the vmemmap range and below the mapped kernel static text/data region, and where all of the x86_64 exception stacks have been moved. Without the patch, reads from the new memory region fail because the address range is not recognized as a legitimate virtual address. Most notable is the failure of "bt" on tasks whose backtraces originate from any of the exception stacks, which fail with the two error messages "bt: seek error: kernel virtual address:
type: stack contents" followed by "bt: read of stack at
failed". (anderson@redhat.com) diff --git a/defs.h b/defs.h index 931be07..6e6f6be 100644 --- a/defs.h +++ b/defs.h @@ -3391,6 +3391,9 @@ struct arm64_stackframe { #define VSYSCALL_START 0xffffffffff600000 #define VSYSCALL_END 0xffffffffff601000 +#define CPU_ENTRY_AREA_START 0xfffffe0000000000 +#define CPU_ENTRY_AREA_END 0xfffffe7fffffffff + #define PTOV(X) ((unsigned long)(X)+(machdep->kvbase)) #define VTOP(X) x86_64_VTOP((ulong)(X)) #define IS_VMALLOC_ADDR(X) x86_64_IS_VMALLOC_ADDR((ulong)(X)) @@ -5829,6 +5832,8 @@ struct machine_specific { ulong kpti_entry_stack; ulong kpti_entry_stack_size; ulong ptrs_per_pgd; + ulong cpu_entry_area_start; + ulong cpu_entry_area_end; }; #define KSYMS_START (0x1) diff --git a/x86_64.c b/x86_64.c index 1d5e155..54b6539 100644 --- a/x86_64.c +++ b/x86_64.c @@ -407,6 +407,11 @@ x86_64_init(int when) machdep->machspec->modules_end = MODULES_END_2_6_31; } } + if (STRUCT_EXISTS("cpu_entry_area")) { + machdep->machspec->cpu_entry_area_start = CPU_ENTRY_AREA_START; + machdep->machspec->cpu_entry_area_end = CPU_ENTRY_AREA_END; + } + STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86"); /* * Before 2.6.25 the structure was called gate_struct @@ -879,20 +884,21 @@ x86_64_dump_machdep_table(ulong arg) /* pml4 and upml is legacy for extension modules */ if (ms->pml4) { - fprintf(fp, " pml4: %lx\n", (ulong)ms->pml4); - fprintf(fp, " last_pml4_read: %lx\n", (ulong)ms->last_pml4_read); + fprintf(fp, " pml4: %lx\n", (ulong)ms->pml4); + fprintf(fp, " last_pml4_read: %lx\n", (ulong)ms->last_pml4_read); } else { - fprintf(fp, " pml4: (unused)\n"); - fprintf(fp, " last_pml4_read: (unused)\n"); + fprintf(fp, " pml4: (unused)\n"); + fprintf(fp, " last_pml4_read: (unused)\n"); } if (ms->upml) { - fprintf(fp, " upml: %lx\n", (ulong)ms->upml); - fprintf(fp, " last_upml_read: %lx\n", (ulong)ms->last_upml_read); + fprintf(fp, " upml: %lx\n", (ulong)ms->upml); + fprintf(fp, " last_upml_read: %lx\n", (ulong)ms->last_upml_read); } else { - fprintf(fp, " upml: (unused)\n"); - fprintf(fp, " last_upml_read: (unused)\n"); + fprintf(fp, " GART_end: %lx\n", ms->GART_end); + fprintf(fp, " upml: (unused)\n"); + fprintf(fp, " last_upml_read: (unused)\n"); } if (ms->p4d) { @@ -1016,10 +1022,14 @@ x86_64_dump_machdep_table(ulong arg) fprintf(fp, "\n "); fprintf(fp, "%016lx ", ms->stkinfo.ibase[c]); } - fprintf(fp, "\n kpti_entry_stack_size: %ld", ms->kpti_entry_stack_size); - fprintf(fp, "\n kpti_entry_stack: "); + fprintf(fp, "\n kpti_entry_stack_size: "); + if (ms->kpti_entry_stack_size) + fprintf(fp, "%ld", ms->kpti_entry_stack_size); + else + fprintf(fp, "(unused)"); + fprintf(fp, "\n kpti_entry_stack: "); if (machdep->flags & KPTI) { - fprintf(fp, "%lx\n ", ms->kpti_entry_stack); + fprintf(fp, "(percpu: %lx):\n ", ms->kpti_entry_stack); for (c = 0; c < cpus; c++) { if (c && !(c%4)) fprintf(fp, "\n "); @@ -1028,6 +1038,16 @@ x86_64_dump_machdep_table(ulong arg) fprintf(fp, "\n"); } else fprintf(fp, "(unused)\n"); + fprintf(fp, " cpu_entry_area_start: "); + if (ms->cpu_entry_area_start) + fprintf(fp, "%016lx\n", (ulong)ms->cpu_entry_area_start); + else + fprintf(fp, "(unused)\n"); + fprintf(fp, " cpu_entry_area_end: "); + if (ms->cpu_entry_area_end) + fprintf(fp, "%016lx\n", (ulong)ms->cpu_entry_area_end); + else + fprintf(fp, "(unused)\n"); } /* @@ -1586,7 +1606,10 @@ x86_64_IS_VMALLOC_ADDR(ulong vaddr) ((machdep->flags & VMEMMAP) && (vaddr >= VMEMMAP_VADDR && vaddr <= VMEMMAP_END)) || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END) || - (vaddr >= VSYSCALL_START && vaddr < VSYSCALL_END)); + (vaddr >= VSYSCALL_START && vaddr < VSYSCALL_END) || + (machdep->machspec->cpu_entry_area_start && + vaddr >= machdep->machspec->cpu_entry_area_start && + vaddr <= machdep->machspec->cpu_entry_area_end)); } static int commit 9446958fe211825ed5524317b05d5ea020bb00d6 Author: Dave Anderson Date: Fri Jun 1 14:01:01 2018 -0400 Fix to address a "__builtin___snprintf_chk" compiler warning if bpf.c is compiled with -D_FORTIFY_SOURCE=2. (anderson@redhat.com) diff --git a/bpf.c b/bpf.c index 305d49f..ee1986f 100644 --- a/bpf.c +++ b/bpf.c @@ -362,7 +362,7 @@ do_bpf(ulong flags, ulong prog_id, ulong map_id, int radix) fprintf(fp, " LOAD_TIME: "); if (VALID_MEMBER(bpf_prog_aux_load_time)) { load_time = ULONGLONG(bpf->bpf_prog_aux_buf + OFFSET(bpf_prog_aux_load_time)); - print_boot_time(load_time, buf5, BUFSIZE); + print_boot_time(load_time, buf5, BUFSIZE/2); fprintf(fp, "%s\n", buf5); } else fprintf(fp, "(unknown)\n");