Initialize symbol and type information for acessing VMCORE(s) data. Note that there's vmlinux not including data for user_regs_struct type. In such case, we use the actual offset size calculated using offsetof(). Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com> --- makedumpfile.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ makedumpfile.h | 130 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+), 0 deletions(-) diff --git a/makedumpfile.c b/makedumpfile.c index c5ea9ce..5ceb986 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -19,6 +19,7 @@ #include "elf_info.h" #include "erase_info.h" #include "sadump_info.h" +#include <stddef.h> #include <sys/time.h> struct symbol_table symbol_table; @@ -809,6 +810,19 @@ get_symbol_info(void) SYMBOL_INIT(log_end, "log_end"); SYMBOL_INIT(max_pfn, "max_pfn"); SYMBOL_INIT(modules, "modules"); + SYMBOL_INIT(linux_banner, "linux_banner"); + SYMBOL_INIT(bios_cpu_apicid, "bios_cpu_apicid"); + SYMBOL_INIT(x86_bios_cpu_apicid, "x86_bios_cpu_apicid"); + if (SYMBOL(x86_bios_cpu_apicid) == NOT_FOUND_SYMBOL) + SYMBOL_INIT(x86_bios_cpu_apicid, + "per_cpu__x86_bios_cpu_apicid"); + SYMBOL_INIT(x86_bios_cpu_apicid_early_ptr, + "x86_bios_cpu_apicid_early_ptr"); + SYMBOL_INIT(x86_bios_cpu_apicid_early_map, + "x86_bios_cpu_apicid_early_map"); + SYMBOL_INIT(crash_notes, "crash_notes"); + SYMBOL_INIT(__per_cpu_load, "__per_cpu_load"); + SYMBOL_INIT(__per_cpu_offset, "__per_cpu_offset"); if (SYMBOL(node_data) != NOT_FOUND_SYMBOL) SYMBOL_ARRAY_TYPE_INIT(node_data, "node_data"); @@ -818,6 +832,8 @@ get_symbol_info(void) SYMBOL_ARRAY_LENGTH_INIT(mem_section, "mem_section"); if (SYMBOL(node_memblk) != NOT_FOUND_SYMBOL) SYMBOL_ARRAY_LENGTH_INIT(node_memblk, "node_memblk"); + if (SYMBOL(__per_cpu_offset) != NOT_FOUND_SYMBOL) + SYMBOL_ARRAY_LENGTH_INIT(__per_cpu_offset, "__per_cpu_offset"); return TRUE; } @@ -934,6 +950,158 @@ get_structure_info(void) TYPEDEF_SIZE_INIT(nodemask_t, "nodemask_t"); + SIZE_INIT(percpu_data, "percpu_data"); + + /* + * Get offset of the elf_prstatus members. + */ + SIZE_INIT(elf_prstatus, "elf_prstatus"); + OFFSET_INIT(elf_prstatus.pr_reg, "elf_prstatus", "pr_reg"); + + /* + * Get offset of the user_regs_struct members. + */ + SIZE_INIT(user_regs_struct, "user_regs_struct"); + +#ifdef __x86__ + if (SIZE(user_regs_struct) != NOT_FOUND_STRUCTURE) { + OFFSET_INIT(user_regs_struct.bx, "user_regs_struct", "bx"); + OFFSET_INIT(user_regs_struct.cx, "user_regs_struct", "cx"); + OFFSET_INIT(user_regs_struct.dx, "user_regs_struct", "dx"); + OFFSET_INIT(user_regs_struct.si, "user_regs_struct", "si"); + OFFSET_INIT(user_regs_struct.di, "user_regs_struct", "di"); + OFFSET_INIT(user_regs_struct.bp, "user_regs_struct", "bp"); + OFFSET_INIT(user_regs_struct.ax, "user_regs_struct", "ax"); + OFFSET_INIT(user_regs_struct.ds, "user_regs_struct", "ds"); + OFFSET_INIT(user_regs_struct.es, "user_regs_struct", "es"); + OFFSET_INIT(user_regs_struct.fs, "user_regs_struct", "fs"); + OFFSET_INIT(user_regs_struct.gs, "user_regs_struct", "gs"); + OFFSET_INIT(user_regs_struct.orig_ax, "user_regs_struct", + "orig_ax"); + OFFSET_INIT(user_regs_struct.ip, "user_regs_struct", "ip"); + OFFSET_INIT(user_regs_struct.cs, "user_regs_struct", "cs"); + OFFSET_INIT(user_regs_struct.flags, "user_regs_struct", + "flags"); + OFFSET_INIT(user_regs_struct.sp, "user_regs_struct", "sp"); + OFFSET_INIT(user_regs_struct.ss, "user_regs_struct", "ss"); + + if (OFFSET(user_regs_struct.bx) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.bx, "user_regs_struct", "ebx"); + if (OFFSET(user_regs_struct.cx) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.cx, "user_regs_struct", "ecx"); + if (OFFSET(user_regs_struct.dx) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.dx, "user_regs_struct", "edx"); + if (OFFSET(user_regs_struct.si) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.si, "user_regs_struct", "esi"); + if (OFFSET(user_regs_struct.di) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.di, "user_regs_struct", "edi"); + if (OFFSET(user_regs_struct.bp) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.bp, "user_regs_struct", "ebp"); + if (OFFSET(user_regs_struct.ax) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.ax, "user_regs_struct", "eax"); + if (OFFSET(user_regs_struct.orig_ax) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.orig_ax, "user_regs_struct", "orig_eax"); + if (OFFSET(user_regs_struct.ip) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.ip, "user_regs_struct", "eip"); + if (OFFSET(user_regs_struct.flags) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.flags, "user_regs_struct", "eflags"); + if (OFFSET(user_regs_struct.sp) == NOT_FOUND_STRUCTURE) + OFFSET_INIT(user_regs_struct.sp, "user_regs_struct", "esp"); + } else { + /* + * Note: Sometimes kernel debuginfo doesn't contain + * user_regs_struct structure information. Instead, we + * take offsets from actual datatype. + */ + OFFSET(user_regs_struct.bx) = offsetof(struct user_regs_struct, bx); + OFFSET(user_regs_struct.cx) = offsetof(struct user_regs_struct, cx); + OFFSET(user_regs_struct.dx) = offsetof(struct user_regs_struct, dx); + OFFSET(user_regs_struct.si) = offsetof(struct user_regs_struct, si); + OFFSET(user_regs_struct.di) = offsetof(struct user_regs_struct, di); + OFFSET(user_regs_struct.bp) = offsetof(struct user_regs_struct, bp); + OFFSET(user_regs_struct.ax) = offsetof(struct user_regs_struct, ax); + OFFSET(user_regs_struct.ds) = offsetof(struct user_regs_struct, ds); + OFFSET(user_regs_struct.es) = offsetof(struct user_regs_struct, es); + OFFSET(user_regs_struct.fs) = offsetof(struct user_regs_struct, fs); + OFFSET(user_regs_struct.gs) = offsetof(struct user_regs_struct, gs); + OFFSET(user_regs_struct.orig_ax) = offsetof(struct user_regs_struct, orig_ax); + OFFSET(user_regs_struct.ip) = offsetof(struct user_regs_struct, ip); + OFFSET(user_regs_struct.cs) = offsetof(struct user_regs_struct, cs); + OFFSET(user_regs_struct.flags) = offsetof(struct user_regs_struct, flags); + OFFSET(user_regs_struct.sp) = offsetof(struct user_regs_struct, sp); + OFFSET(user_regs_struct.ss) = offsetof(struct user_regs_struct, ss); + } +#endif /* __x86__ */ + +#ifdef __x86_64__ + if (SIZE(user_regs_struct) != NOT_FOUND_STRUCTURE) { + OFFSET_INIT(user_regs_struct.r15, "user_regs_struct", "r15"); + OFFSET_INIT(user_regs_struct.r14, "user_regs_struct", "r14"); + OFFSET_INIT(user_regs_struct.r13, "user_regs_struct", "r13"); + OFFSET_INIT(user_regs_struct.r12, "user_regs_struct", "r12"); + OFFSET_INIT(user_regs_struct.bp, "user_regs_struct", "bp"); + OFFSET_INIT(user_regs_struct.bx, "user_regs_struct", "bx"); + OFFSET_INIT(user_regs_struct.r11, "user_regs_struct", "r11"); + OFFSET_INIT(user_regs_struct.r10, "user_regs_struct", "r10"); + OFFSET_INIT(user_regs_struct.r9, "user_regs_struct", "r9"); + OFFSET_INIT(user_regs_struct.r8, "user_regs_struct", "r8"); + OFFSET_INIT(user_regs_struct.ax, "user_regs_struct", "ax"); + OFFSET_INIT(user_regs_struct.cx, "user_regs_struct", "cx"); + OFFSET_INIT(user_regs_struct.dx, "user_regs_struct", "dx"); + OFFSET_INIT(user_regs_struct.si, "user_regs_struct", "si"); + OFFSET_INIT(user_regs_struct.di, "user_regs_struct", "di"); + OFFSET_INIT(user_regs_struct.orig_ax, "user_regs_struct", + "orig_ax"); + OFFSET_INIT(user_regs_struct.ip, "user_regs_struct", "ip"); + OFFSET_INIT(user_regs_struct.cs, "user_regs_struct", "cs"); + OFFSET_INIT(user_regs_struct.flags, "user_regs_struct", + "flags"); + OFFSET_INIT(user_regs_struct.sp, "user_regs_struct", "sp"); + OFFSET_INIT(user_regs_struct.ss, "user_regs_struct", "ss"); + OFFSET_INIT(user_regs_struct.fs_base, "user_regs_struct", + "fs_base"); + OFFSET_INIT(user_regs_struct.gs_base, "user_regs_struct", + "gs_base"); + OFFSET_INIT(user_regs_struct.ds, "user_regs_struct", "ds"); + OFFSET_INIT(user_regs_struct.es, "user_regs_struct", "es"); + OFFSET_INIT(user_regs_struct.fs, "user_regs_struct", "fs"); + OFFSET_INIT(user_regs_struct.gs, "user_regs_struct", "gs"); + } else { + /* + * Note: Sometimes kernel debuginfo doesn't contain + * user_regs_struct structure information. Instead, we + * take offsets from actual datatype. + */ + OFFSET(user_regs_struct.r15) = offsetof(struct user_regs_struct, r15); + OFFSET(user_regs_struct.r14) = offsetof(struct user_regs_struct, r14); + OFFSET(user_regs_struct.r13) = offsetof(struct user_regs_struct, r13); + OFFSET(user_regs_struct.r12) = offsetof(struct user_regs_struct, r12); + OFFSET(user_regs_struct.bp) = offsetof(struct user_regs_struct, bp); + OFFSET(user_regs_struct.bx) = offsetof(struct user_regs_struct, bx); + OFFSET(user_regs_struct.r11) = offsetof(struct user_regs_struct, r11); + OFFSET(user_regs_struct.r10) = offsetof(struct user_regs_struct, r10); + OFFSET(user_regs_struct.r9) = offsetof(struct user_regs_struct, r9); + OFFSET(user_regs_struct.r8) = offsetof(struct user_regs_struct, r8); + OFFSET(user_regs_struct.ax) = offsetof(struct user_regs_struct, ax); + OFFSET(user_regs_struct.cx) = offsetof(struct user_regs_struct, cx); + OFFSET(user_regs_struct.dx) = offsetof(struct user_regs_struct, dx); + OFFSET(user_regs_struct.si) = offsetof(struct user_regs_struct, si); + OFFSET(user_regs_struct.di) = offsetof(struct user_regs_struct, di); + OFFSET(user_regs_struct.orig_ax) = offsetof(struct user_regs_struct, orig_ax); + OFFSET(user_regs_struct.ip) = offsetof(struct user_regs_struct, ip); + OFFSET(user_regs_struct.cs) = offsetof(struct user_regs_struct, cs); + OFFSET(user_regs_struct.flags) = offsetof(struct user_regs_struct, flags); + OFFSET(user_regs_struct.sp) = offsetof(struct user_regs_struct, sp); + OFFSET(user_regs_struct.ss) = offsetof(struct user_regs_struct, ss); + OFFSET(user_regs_struct.fs_base) = offsetof(struct user_regs_struct, fs_base); + OFFSET(user_regs_struct.gs_base) = offsetof(struct user_regs_struct, gs_base); + OFFSET(user_regs_struct.ds) = offsetof(struct user_regs_struct, ds); + OFFSET(user_regs_struct.es) = offsetof(struct user_regs_struct, es); + OFFSET(user_regs_struct.fs) = offsetof(struct user_regs_struct, fs); + OFFSET(user_regs_struct.gs) = offsetof(struct user_regs_struct, gs); + } +#endif /* __x86_64__ */ + return TRUE; } diff --git a/makedumpfile.h b/makedumpfile.h index 17ec590..433bc49 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -983,6 +983,18 @@ struct symbol_table { */ unsigned long long modules; + + /* + * for sadump + */ + unsigned long long linux_banner; + unsigned long long bios_cpu_apicid; + unsigned long long x86_bios_cpu_apicid; + unsigned long long x86_bios_cpu_apicid_early_ptr; + unsigned long long x86_bios_cpu_apicid_early_map; + unsigned long long crash_notes; + unsigned long long __per_cpu_offset; + unsigned long long __per_cpu_load; }; struct size_table { @@ -1005,6 +1017,13 @@ struct size_table { * for loading module symbol data */ long module; + + /* + * for sadump + */ + long percpu_data; + long elf_prstatus; + long user_regs_struct; }; struct offset_table { @@ -1073,6 +1092,46 @@ struct offset_table { long symtab; long strtab; } module; + + /* + * for loading elf_prstaus symbol data + */ + struct elf_prstatus_s { + long pr_reg; + } elf_prstatus; + + /* + * for loading user_regs_struct symbol data + */ + struct user_regs_struct_s { + long r15; + long r14; + long r13; + long r12; + long bp; + long bx; + long r11; + long r10; + long r9; + long r8; + long ax; + long cx; + long dx; + long si; + long di; + long orig_ax; + long ip; + long cs; + long flags; + long sp; + long ss; + long fs_base; + long gs_base; + long ds; + long es; + long fs; + long gs; + } user_regs_struct; }; /* @@ -1086,6 +1145,7 @@ struct array_table { long pgdat_list; long mem_section; long node_memblk; + long __per_cpu_offset; /* * Structure @@ -1268,4 +1328,74 @@ is_dumpable(struct dump_bitmap *bitmap, unsigned long long pfn) return is_on(bitmap->buf, pfn%PFN_BUFBITMAP); } +#ifdef __x86__ + +struct user_regs_struct { + unsigned long bx; + unsigned long cx; + unsigned long dx; + unsigned long si; + unsigned long di; + unsigned long bp; + unsigned long ax; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; + unsigned long orig_ax; + unsigned long ip; + unsigned long cs; + unsigned long flags; + unsigned long sp; + unsigned long ss; +}; + +struct elf_prstatus { + char pad1[72]; + struct user_regs_struct pr_reg; + char pad2[4]; +}; + +#endif + +#ifdef __x86_64__ + +struct user_regs_struct { + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long bp; + unsigned long bx; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long ax; + unsigned long cx; + unsigned long dx; + unsigned long si; + unsigned long di; + unsigned long orig_ax; + unsigned long ip; + unsigned long cs; + unsigned long flags; + unsigned long sp; + unsigned long ss; + unsigned long fs_base; + unsigned long gs_base; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; +}; + +struct elf_prstatus { + char pad1[112]; + struct user_regs_struct pr_reg; + char pad2[4]; +}; + +#endif + #endif /* MAKEDUMPFILE_H */