Subject: [PATCH 07/18] Initialize debug information for ELF note extraction This is a backport of commit 78906468c6c2e19c59cb910da483c909be8729b8 Author: HATAYAMA Daisuke Date: Fri Dec 16 10:47:40 2011 +0900 [PATCH v2 07/14] Initialize debug information for ELF note extraction 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 --- diff -Nrup kexec-tools-2.0.0.old/makedumpfile-1.3.5/makedumpfile.c kexec-tools-2.0.0/makedumpfile-1.3.5/makedumpfile.c --- kexec-tools-2.0.0.old/makedumpfile-1.3.5/makedumpfile.c 2012-04-04 05:28:42.600591461 -0400 +++ kexec-tools-2.0.0/makedumpfile-1.3.5/makedumpfile.c 2012-04-04 05:33:24.909591864 -0400 @@ -15,6 +15,7 @@ */ #include "makedumpfile.h" #include "sadump_info.h" +#include struct symbol_table symbol_table; struct size_table size_table; @@ -2548,6 +2549,19 @@ get_symbol_info(void) SYMBOL_INIT(max_pfn, "max_pfn"); SYMBOL_INIT(modules, "modules"); SYMBOL_INIT(high_memory, "high_memory"); + 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"); @@ -2557,6 +2571,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; } @@ -2673,6 +2689,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 -Nrup kexec-tools-2.0.0.old/makedumpfile-1.3.5/makedumpfile.h kexec-tools-2.0.0/makedumpfile-1.3.5/makedumpfile.h --- kexec-tools-2.0.0.old/makedumpfile-1.3.5/makedumpfile.h 2012-04-04 05:28:42.600591461 -0400 +++ kexec-tools-2.0.0/makedumpfile-1.3.5/makedumpfile.h 2012-04-04 05:31:54.880631251 -0400 @@ -1087,6 +1087,18 @@ struct symbol_table { * vmalloc_start address on s390x arch */ unsigned long long high_memory; + + /* + * 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 { @@ -1109,6 +1121,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 { @@ -1177,6 +1196,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; }; /* @@ -1190,6 +1249,7 @@ struct array_table { long pgdat_list; long mem_section; long node_memblk; + long __per_cpu_offset; /* * Structure @@ -1511,4 +1571,74 @@ is_dumpable(struct dump_bitmap *bitmap, 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 */