sadump doesn't save phys_base, so we must estimate it in any way. Here we borrow the method in crash utility that we search a certain range of addresses for linux_banner symbol value. Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com> --- makedumpfile.c | 12 ++++++++++++ sadump_info.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ sadump_info.h | 13 +++++++++++++ 3 files changed, 72 insertions(+), 0 deletions(-) diff --git a/makedumpfile.c b/makedumpfile.c index e4b3b38..4e3beef 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -2504,6 +2504,15 @@ initial(void) (void) sadump_set_timestamp(&info->timestamp); + /* + * NOTE: phys_base is never saved by sadump and so + * must be computed in some way. We here choose the + * way of looking at linux_banner. See + * sadump_virt_phys_base(). The processing is + * postponed until debug information becomes + * available. + */ + } else if (!get_phys_base()) return FALSE; @@ -2579,6 +2588,9 @@ out: return FALSE; if (debug_info) { + if (info->flag_sadump) + (void) sadump_virt_phys_base(); + if (!get_machdep_info()) return FALSE; diff --git a/sadump_info.c b/sadump_info.c index c4806c4..fa05443 100644 --- a/sadump_info.c +++ b/sadump_info.c @@ -22,6 +22,12 @@ #include "print_info.h" #include "sadump_mod.h" +#ifdef __x86_64__ + +#define MEGABYTES(x) ((x) * (1048576)) + +#endif + struct sadump_diskset_info { char *name_memory; int fd_memory; @@ -666,6 +672,47 @@ sadump_get_max_mapnr(void) return si->sh_memory->max_mapnr; } +#ifdef __x86_64__ + +int +sadump_virt_phys_base(void) +{ + char buf[BUFSIZE]; + unsigned long phys, linux_banner_phys; + + if (SYMBOL(linux_banner) == NOT_FOUND_SYMBOL) { + DEBUG_MSG("sadump: symbol linux_banner is not found\n"); + goto failed; + } + + linux_banner_phys = SYMBOL(linux_banner) - __START_KERNEL_map; + + if (readmem(PADDR, linux_banner_phys + info->phys_base, buf, + strlen("Linux version")) && STRNEQ(buf, "Linux version")) + return TRUE; + + for (phys = (-MEGABYTES(16)); phys != MEGABYTES(16+1); + phys += MEGABYTES(1)) { + if (readmem(PADDR, linux_banner_phys + phys, buf, + strlen("Linux version")) && + STRNEQ(buf, "Linux version")) { + DEBUG_MSG("sadump: phys_base: %lx %s\n", phys, + info->phys_base != phys ? "override" : ""); + info->phys_base = phys; + return TRUE; + } + } + +failed: + info->phys_base = 0; + + DEBUG_MSG("sadump: failed to calculate phys_base; default to 0\n"); + + return FALSE; +} + +#endif /* __x86_64__ */ + int readpmem_sadump(unsigned long long paddr, void *bufptr, size_t size) { diff --git a/sadump_info.h b/sadump_info.h index b6b9cdd..401b769 100644 --- a/sadump_info.h +++ b/sadump_info.h @@ -22,6 +22,19 @@ #include "makedumpfile.h" +#ifdef __x86_64__ + +int sadump_virt_phys_base(void); + +#else + +static inline int sadump_virt_phys_base(void) +{ + return TRUE; +} + +#endif + #if defined(__x86__) || defined(__x86_64__) int check_and_get_sadump_header_info(char *filename); -- 1.7.4.4