On 04/27/2017 at 02:15 PM, Pratyush Anand wrote: > If we have to erase a symbol from vmcore whose address is not present in > vmcoreinfo, then we need to pass vmlinux as well to get the symbol > address. > When kaslr is enabled, virtual address of all the kernel symbols are > randomized with an offset. vmlinux always has a static address, but all > the arch specific calculation are based on run time kernel address. So > we need to find a way to translate symbol address from vmlinux to kernel > run time address. > > without this patch: > # makedumpfile --split -d 5 -x vmlinux --config scrub.conf vmcore dumpfile_{1,2,3} > > readpage_kdump_compressed: pfn(f97ea) is excluded from vmcore. > readmem: type_addr: 1, addr:f97eaff8, size:8 > vtop4_x86_64: Can't get pml4 (page_dir:f97eaff8). > readmem: Can't convert a virtual address(ffffffff819f1284) to physical address. > readmem: type_addr: 0, addr:ffffffff819f1284, size:390 > check_release: Can't get the address of system_utsname. > > After this patch check_release() is ok, and also we are able to erase > symbol from vmcore. > > Signed-off-by: Pratyush Anand <panand at redhat.com> > --- > arch/x86_64.c | 23 +++++++++++++++++++++++ > erase_info.c | 1 + > makedumpfile.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ > makedumpfile.h | 15 +++++++++++++++ > 4 files changed, 83 insertions(+) > > diff --git a/arch/x86_64.c b/arch/x86_64.c > index e978a36f8878..ab5aae8f1b26 100644 > --- a/arch/x86_64.c > +++ b/arch/x86_64.c > @@ -33,6 +33,29 @@ get_xen_p2m_mfn(void) > return NOT_FOUND_LONG_VALUE; > } > > +unsigned long > +get_kaslr_offset_x86_64(unsigned long vaddr) > +{ > + unsigned long sym_vmcoreinfo, sym_vmlinux; > + > + if (!info->kaslr_offset) { > + sym_vmlinux = get_symbol_addr("_stext"); > + if (sym_vmlinux == NOT_FOUND_SYMBOL) > + return 0; > + sym_vmcoreinfo = read_vmcoreinfo_symbol(STR_SYMBOL("_stext")); > + info->kaslr_offset = sym_vmcoreinfo - sym_vmlinux; > + } > + if (vaddr >= __START_KERNEL_map && > + vaddr < __START_KERNEL_map + info->kaslr_offset) > + return info->kaslr_offset; > + else > + /* > + * TODO: we need to check if it is vmalloc/vmmemmap/module > + * address, we will have different offset > + */ > + return 0; > +} > + > static int > get_page_offset_x86_64(void) > { > diff --git a/erase_info.c b/erase_info.c > index f2ba9149e93e..60abfa1a1adf 100644 > --- a/erase_info.c > +++ b/erase_info.c > @@ -1088,6 +1088,7 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_vaddr, > ce->line, ce->name); > return FALSE; > } > + ce->sym_addr += get_kaslr_offset(ce->sym_addr); > ce->type_name = get_symbol_type_name(ce->name, > DWARF_INFO_GET_SYMBOL_TYPE, > &ce->size, &ce->type_flag); > diff --git a/makedumpfile.c b/makedumpfile.c > index 301772a8820c..7e78641917d7 100644 > --- a/makedumpfile.c > +++ b/makedumpfile.c > @@ -3782,6 +3782,46 @@ free_for_parallel() > } > > int > +find_kaslr_offsets() > +{ > + off_t offset; > + unsigned long size; > + int ret = FALSE; > + > + get_vmcoreinfo(&offset, &size); > + > + if (!(info->name_vmcoreinfo = strdup(FILENAME_VMCOREINFO))) { > + MSG("Can't duplicate strings(%s).\n", FILENAME_VMCOREINFO); > + return FALSE; > + } > + if (!copy_vmcoreinfo(offset, size)) > + goto out; > + > + if (!open_vmcoreinfo("r")) > + goto out; > + > + unlink(info->name_vmcoreinfo); > + > + /* > + * This arch specific function should update info->kaslr_offset. If > + * kaslr is not enabled then offset will be set to 0. arch specific > + * function might need to read from vmcoreinfo, therefore we have > + * called this function between open_vmcoreinfo() and > + * close_vmcoreinfo() > + */ > + get_kaslr_offset(SYMBOL(_stext)); Looks like acquiring "KERNELOFFSET" in read_vmcoreinfo() should be enough here. We can get kaslr offset directly from the vmcoreinfo because the compressed dumpfile contains vmcoreinfo as well in case of flag_refiltering, also x86_64 kernel has exported "vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());" Regards, Xunlei > + > + close_vmcoreinfo(); > + > + ret = TRUE; > +out: > + free(info->name_vmcoreinfo); > + info->name_vmcoreinfo = NULL; > + > + return ret; > +} > + > +int > initial(void) > { > off_t offset; > @@ -3833,6 +3873,9 @@ initial(void) > set_dwarf_debuginfo("vmlinux", NULL, > info->name_vmlinux, info->fd_vmlinux); > > + if (has_vmcoreinfo() && !find_kaslr_offsets()) > + return FALSE; > + > if (!get_symbol_info()) > return FALSE; > > @@ -11031,6 +11074,7 @@ main(int argc, char *argv[]) > info->fd_memory = -1; > info->fd_dumpfile = -1; > info->fd_bitmap = -1; > + info->kaslr_offset = 0; > initialize_tables(); > > /* > diff --git a/makedumpfile.h b/makedumpfile.h > index e32e567018f6..0d358be8caac 100644 > --- a/makedumpfile.h > +++ b/makedumpfile.h > @@ -253,10 +253,14 @@ static inline int string_exists(char *s) { return (s ? TRUE : FALSE); } > #define SYMBOL_INIT(symbol, str_symbol) \ > do { \ > SYMBOL(symbol) = get_symbol_addr(str_symbol); \ > + if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \ > + SYMBOL(symbol) += info->kaslr_offset; \ > } while (0) > #define SYMBOL_INIT_NEXT(symbol, str_symbol) \ > do { \ > SYMBOL(symbol) = get_next_symbol_addr(str_symbol); \ > + if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \ > + SYMBOL(symbol) += info->kaslr_offset; \ > } while (0) > #define WRITE_SYMBOL(str_symbol, symbol) \ > do { \ > @@ -838,6 +842,7 @@ int get_xen_info_arm64(void); > #define get_phys_base() get_phys_base_arm64() > #define get_machdep_info() get_machdep_info_arm64() > #define get_versiondep_info() get_versiondep_info_arm64() > +#define get_kaslr_offset(X) FALSE > #define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X) > #define get_xen_info_arch(X) get_xen_info_arm64(X) > #define is_phys_addr(X) stub_true_ul(X) > @@ -851,6 +856,7 @@ unsigned long long vaddr_to_paddr_arm(unsigned long vaddr); > #define get_phys_base() get_phys_base_arm() > #define get_machdep_info() get_machdep_info_arm() > #define get_versiondep_info() stub_true() > +#define get_kaslr_offset(X) FALSE > #define vaddr_to_paddr(X) vaddr_to_paddr_arm(X) > #define is_phys_addr(X) stub_true_ul(X) > #endif /* arm */ > @@ -863,11 +869,13 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr); > #define get_phys_base() stub_true() > #define get_machdep_info() get_machdep_info_x86() > #define get_versiondep_info() get_versiondep_info_x86() > +#define get_kaslr_offset(X) FALSE > #define vaddr_to_paddr(X) vaddr_to_paddr_x86(X) > #define is_phys_addr(X) stub_true_ul(X) > #endif /* x86 */ > > #ifdef __x86_64__ > +unsigned long get_kaslr_offset_x86_64(unsigned long vaddr); > int get_phys_base_x86_64(void); > int get_machdep_info_x86_64(void); > int get_versiondep_info_x86_64(void); > @@ -876,6 +884,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr); > #define get_phys_base() get_phys_base_x86_64() > #define get_machdep_info() get_machdep_info_x86_64() > #define get_versiondep_info() get_versiondep_info_x86_64() > +#define get_kaslr_offset(X) get_kaslr_offset_x86_64(X) > #define vaddr_to_paddr(X) vtop4_x86_64(X) > #define is_phys_addr(X) stub_true_ul(X) > #endif /* x86_64 */ > @@ -888,6 +897,7 @@ unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr); > #define get_phys_base() stub_true() > #define get_machdep_info() get_machdep_info_ppc64() > #define get_versiondep_info() get_versiondep_info_ppc64() > +#define get_kaslr_offset(X) FALSE > #define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X) > #define is_phys_addr(X) stub_true_ul(X) > #endif /* powerpc64 */ > @@ -899,6 +909,7 @@ unsigned long long vaddr_to_paddr_ppc(unsigned long vaddr); > #define get_phys_base() stub_true() > #define get_machdep_info() get_machdep_info_ppc() > #define get_versiondep_info() stub_true() > +#define get_kaslr_offset(X) FALSE > #define vaddr_to_paddr(X) vaddr_to_paddr_ppc(X) > #define is_phys_addr(X) stub_true_ul(X) > #endif /* powerpc32 */ > @@ -911,6 +922,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr); > #define get_phys_base() stub_true() > #define get_machdep_info() get_machdep_info_s390x() > #define get_versiondep_info() stub_true() > +#define get_kaslr_offset(X) FALSE > #define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X) > #define is_phys_addr(X) is_iomem_phys_addr_s390x(X) > #endif /* s390x */ > @@ -923,6 +935,7 @@ unsigned long long vaddr_to_paddr_ia64(unsigned long vaddr); > #define get_machdep_info() get_machdep_info_ia64() > #define get_phys_base() get_phys_base_ia64() > #define get_versiondep_info() stub_true() > +#define get_kaslr_offset(X) FALSE > #define vaddr_to_paddr(X) vaddr_to_paddr_ia64(X) > #define VADDR_REGION(X) (((unsigned long)(X)) >> REGION_SHIFT) > #define is_phys_addr(X) stub_true_ul(X) > @@ -1152,6 +1165,7 @@ struct DumpInfo { > int vmemmap_psize; > int vmemmap_cnt; > struct ppc64_vmemmap *vmemmap_list; > + unsigned long kaslr_offset; > > /* > * page table info for ppc64 > @@ -1803,6 +1817,7 @@ struct memory_range { > struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR]; > int crash_reserved_mem_nr; > > +unsigned long read_vmcoreinfo_symbol(char *str_symbol); > int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size); > int get_str_osrelease_from_vmlinux(void); > int read_vmcoreinfo_xen(void);