Blame lkcd_v1.c

Packit bf408e
/* lkcd_v1.c - core analysis suite
Packit bf408e
 *
Packit bf408e
 * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Packit bf408e
 * Copyright (C) 2002, 2003, 2004, 2005 David Anderson
Packit bf408e
 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. All rights reserved.
Packit bf408e
 *
Packit bf408e
 * This program is free software; you can redistribute it and/or modify
Packit bf408e
 * it under the terms of the GNU General Public License as published by
Packit bf408e
 * the Free Software Foundation; either version 2 of the License, or
Packit bf408e
 * (at your option) any later version.
Packit bf408e
 *
Packit bf408e
 * This program is distributed in the hope that it will be useful,
Packit bf408e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bf408e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bf408e
 * GNU General Public License for more details.
Packit bf408e
 */
Packit bf408e
Packit bf408e
#define LKCD_COMMON
Packit bf408e
#include "defs.h"
Packit bf408e
#define CONFIG_VMDUMP
Packit bf408e
#include "lkcd_vmdump_v1.h"
Packit bf408e
Packit bf408e
static dump_header_t dump_header_v1 = { 0 };
Packit bf408e
static dump_page_t dump_page = { 0 };
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Verify and initialize the LKCD environment, storing the common data
Packit bf408e
 *  in the global lkcd_environment structure.
Packit bf408e
 */
Packit bf408e
int
Packit bf408e
lkcd_dump_init_v1(FILE *fp, int fd)
Packit bf408e
{
Packit bf408e
	int i; 
Packit bf408e
	int eof;
Packit bf408e
	uint32_t pgcnt;
Packit bf408e
	dump_header_t *dh;
Packit bf408e
	dump_page_t *dp;
Packit bf408e
Packit bf408e
	lkcd->fd = fd;
Packit bf408e
	lkcd->fp = fp;
Packit bf408e
Packit bf408e
	lseek(lkcd->fd, 0, SEEK_SET);
Packit bf408e
Packit bf408e
	dh = &dump_header_v1;
Packit bf408e
	dp = &dump_page;
Packit bf408e
Packit bf408e
	if (read(lkcd->fd, dh, sizeof(dump_header_t)) !=
Packit bf408e
	    sizeof(dump_header_t))
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
        lkcd->dump_header = dh;
Packit bf408e
        lkcd->dump_page = dp;
Packit bf408e
	if (lkcd->debug) 
Packit bf408e
		dump_lkcd_environment(LKCD_DUMP_HEADER_ONLY);
Packit bf408e
Packit bf408e
        /*
Packit bf408e
         *  Allocate and clear the benchmark offsets, one per megabyte.
Packit bf408e
         */
Packit bf408e
        lkcd->page_size = dh->dh_page_size;
Packit bf408e
	lkcd->page_shift = ffs(lkcd->page_size) - 1;
Packit bf408e
	lkcd->bits = sizeof(long) * 8;
Packit bf408e
	lkcd->total_pages = dh->dh_num_pages;
Packit bf408e
        lkcd->benchmark_pages = (dh->dh_num_pages/LKCD_PAGES_PER_MEGABYTE())+1;
Packit bf408e
	lkcd->page_header_size = sizeof(dump_page_t);
Packit bf408e
Packit bf408e
	lkcd->zone_shift = ffs(ZONE_SIZE) - 1;
Packit bf408e
	lkcd->zone_mask = ~(ZONE_SIZE - 1);
Packit bf408e
	lkcd->num_zones = 0;
Packit bf408e
	lkcd->max_zones = 0;
Packit bf408e
Packit bf408e
	lkcd->get_dp_flags = get_dp_flags_v1;
Packit bf408e
	lkcd->get_dp_address = get_dp_address_v1;
Packit bf408e
	lkcd->get_dp_size = get_dp_size_v1;
Packit bf408e
	lkcd->compression = LKCD_DUMP_COMPRESS_RLE;
Packit bf408e
Packit bf408e
        lseek(lkcd->fd, LKCD_OFFSET_TO_FIRST_PAGE, SEEK_SET);
Packit bf408e
Packit bf408e
	for (pgcnt = 0, eof = FALSE; !eof; pgcnt++) {
Packit bf408e
Packit bf408e
		switch (lkcd_load_dump_page_header(dp, pgcnt))
Packit bf408e
		{
Packit bf408e
		case LKCD_DUMPFILE_OK:
Packit bf408e
		case LKCD_DUMPFILE_END:
Packit bf408e
			break;
Packit bf408e
Packit bf408e
		case LKCD_DUMPFILE_EOF:
Packit bf408e
			eof = TRUE;
Packit bf408e
			continue;
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if (!(dp->dp_flags & (DUMP_COMPRESSED|DUMP_RAW|DUMP_END))) {
Packit bf408e
			lkcd_print("unknown page flag in dump: %lx\n",
Packit bf408e
				dp->dp_flags);
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if (dp->dp_size > 4096) {
Packit bf408e
			lkcd_print("dp_size > 4096: %d\n", dp->dp_size);
Packit bf408e
			dump_lkcd_environment(LKCD_DUMP_PAGE_ONLY);
Packit bf408e
		}
Packit bf408e
Packit bf408e
		if (dp->dp_flags & DUMP_END) {
Packit bf408e
			lkcd_print("found DUMP_END\n");
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e
Packit bf408e
        	lseek(lkcd->fd, dp->dp_size, SEEK_CUR);
Packit bf408e
Packit bf408e
		if (!LKCD_DEBUG(1))
Packit bf408e
			break;
Packit bf408e
	}
Packit bf408e
Packit bf408e
        /*
Packit bf408e
         *  Allocate space for LKCD_CACHED_PAGES data pages plus one to
Packit bf408e
         *  contain a copy of the compressed data of the current page.
Packit bf408e
         */
Packit bf408e
	if ((lkcd->page_cache_buf = (char *)malloc
Packit bf408e
	    (dh->dh_page_size * (LKCD_CACHED_PAGES))) == NULL)
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
        /*
Packit bf408e
         *  Clear the page data areas.
Packit bf408e
         */
Packit bf408e
        lkcd_free_memory();
Packit bf408e
	for (i = 0; i < LKCD_CACHED_PAGES; i++) {
Packit bf408e
		lkcd->page_cache_hdr[i].pg_bufptr = 
Packit bf408e
			&lkcd->page_cache_buf[i * dh->dh_page_size];
Packit bf408e
	}
Packit bf408e
Packit bf408e
	if ((lkcd->compressed_page = (char *)malloc(dh->dh_page_size)) == NULL)
Packit bf408e
                return FALSE;
Packit bf408e
Packit bf408e
	if ((lkcd->page_hash = (struct page_hash_entry *)calloc
Packit bf408e
	    	(LKCD_PAGE_HASH, sizeof(struct page_hash_entry))) == NULL)
Packit bf408e
		return FALSE;
Packit bf408e
Packit bf408e
	lkcd->total_pages = eof || (pgcnt > dh->dh_num_pages) ? 
Packit bf408e
		pgcnt : dh->dh_num_pages;
Packit bf408e
	lkcd->panic_task = (ulong)dh->dh_current_task;
Packit bf408e
	lkcd->panic_string = (char *)&dh->dh_panic_string[0];
Packit bf408e
	if (!fp) 
Packit bf408e
		lkcd->flags |= LKCD_REMOTE;
Packit bf408e
	lkcd->flags |= LKCD_VALID;
Packit bf408e
Packit bf408e
	return TRUE;
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Return the current page's dp_size.   
Packit bf408e
 */
Packit bf408e
uint32_t 
Packit bf408e
get_dp_size_v1(void)
Packit bf408e
{
Packit bf408e
        dump_page_t *dp;
Packit bf408e
Packit bf408e
        dp = (dump_page_t *)lkcd->dump_page;
Packit bf408e
Packit bf408e
	return(dp->dp_size);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Return the current page's dp_flags. 
Packit bf408e
 */
Packit bf408e
uint32_t
Packit bf408e
get_dp_flags_v1(void)
Packit bf408e
{
Packit bf408e
        dump_page_t *dp;
Packit bf408e
Packit bf408e
        dp = (dump_page_t *)lkcd->dump_page;
Packit bf408e
Packit bf408e
        return(dp->dp_flags);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  Return the current page's dp_address.
Packit bf408e
 */
Packit bf408e
uint64_t
Packit bf408e
get_dp_address_v1(void)
Packit bf408e
{
Packit bf408e
        dump_page_t *dp;
Packit bf408e
Packit bf408e
        dp = (dump_page_t *)lkcd->dump_page;
Packit bf408e
Packit bf408e
        return(dp->dp_address);
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  console-only output for info regarding current page.
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
dump_dump_page_v1(char *s, void *dpp)
Packit bf408e
{
Packit bf408e
        dump_page_t *dp;
Packit bf408e
        uint32_t flags;
Packit bf408e
        int others;
Packit bf408e
Packit bf408e
        console(s);
Packit bf408e
Packit bf408e
        dp = (dump_page_t *)dpp;
Packit bf408e
        others = 0;
Packit bf408e
Packit bf408e
        console("dp_address: %llx  ", dp->dp_address);
Packit bf408e
        console("dp_size: %ld  ", dp->dp_size);
Packit bf408e
        console("dp_flags: %lx  (", flags = dp->dp_flags);
Packit bf408e
Packit bf408e
        if (flags & DUMP_COMPRESSED)
Packit bf408e
                console("DUMP_COMPRESSED", others++);
Packit bf408e
        if (flags & DUMP_RAW)
Packit bf408e
                console("%sDUMP_RAW", others++ ? "|" : "");
Packit bf408e
        if (flags & DUMP_END)
Packit bf408e
                console("DUMP_END", others++ ? "|" : "");
Packit bf408e
        console(")\n");
Packit bf408e
}
Packit bf408e
Packit bf408e
/*
Packit bf408e
 *  help -S output, or as specified by arg.
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
dump_lkcd_environment_v1(ulong arg)
Packit bf408e
{
Packit bf408e
	int others;
Packit bf408e
        dump_header_t *dh;
Packit bf408e
        dump_page_t *dp;
Packit bf408e
Packit bf408e
        dh = (dump_header_t *)lkcd->dump_header;
Packit bf408e
        dp = (dump_page_t *)lkcd->dump_page;
Packit bf408e
Packit bf408e
	if (arg == LKCD_DUMP_HEADER_ONLY)
Packit bf408e
		goto dump_header_only;
Packit bf408e
	if (arg == LKCD_DUMP_PAGE_ONLY)
Packit bf408e
		goto dump_page_only;
Packit bf408e
Packit bf408e
dump_header_only:
Packit bf408e
Packit bf408e
	lkcd_print("     dump_header:\n");
Packit bf408e
        lkcd_print(" dh_magic_number: %llx  ",
Packit bf408e
                        dh->dh_magic_number);
Packit bf408e
	if (dh->dh_magic_number == DUMP_MAGIC_NUMBER)
Packit bf408e
		lkcd_print("(DUMP_MAGIC_NUMBER)\n");
Packit bf408e
	else
Packit bf408e
		lkcd_print("(?)\n");
Packit bf408e
        lkcd_print("      dh_version: %d\n", dh->dh_version);
Packit bf408e
        lkcd_print("  dh_header_size: %d\n", dh->dh_header_size);
Packit bf408e
        lkcd_print("   dh_dump_level: %d\n", dh->dh_dump_level);
Packit bf408e
        lkcd_print("    dh_page_size: %d\n", dh->dh_page_size);
Packit bf408e
        lkcd_print("  dh_memory_size: %lld\n", dh->dh_memory_size);
Packit bf408e
        lkcd_print(" dh_memory_start: %llx\n", dh->dh_memory_start);
Packit bf408e
        lkcd_print("   dh_memory_end: %llx\n", dh->dh_memory_end);
Packit bf408e
       	lkcd_print("          dh_esp: %lx\n", dh->dh_esp);
Packit bf408e
        lkcd_print("          dh_eip: %lx\n", dh->dh_eip);
Packit bf408e
	lkcd_print("    dh_num_pages: %d\n", dh->dh_num_pages);
Packit bf408e
        lkcd_print(" dh_panic_string: %s%s", dh->dh_panic_string,
Packit bf408e
		dh && dh->dh_panic_string &&
Packit bf408e
		strstr(dh->dh_panic_string, "\n") ? "" : "\n");
Packit bf408e
        lkcd_print("         dh_time: %s\n",
Packit bf408e
                        strip_linefeeds(ctime(&(dh->dh_time.tv_sec))));
Packit bf408e
Packit bf408e
	lkcd_print("      dh_utsname:\n");
Packit bf408e
	lkcd_print("         sysname: %s\n", dh->dh_utsname.sysname);
Packit bf408e
	lkcd_print("        nodename: %s\n", dh->dh_utsname.nodename);
Packit bf408e
	lkcd_print("         release: %s\n", dh->dh_utsname.release);
Packit bf408e
	lkcd_print("         version: %s\n", dh->dh_utsname.version);
Packit bf408e
	lkcd_print("         machine: %s\n", dh->dh_utsname.machine);
Packit bf408e
	lkcd_print("      domainname: %s\n", dh->dh_utsname.domainname);
Packit bf408e
Packit bf408e
        lkcd_print(" dh_current_task: %lx\n", dh->dh_current_task);
Packit bf408e
Packit bf408e
	lkcd_print("         dh_regs:\n");
Packit bf408e
#ifdef PPC
Packit bf408e
	lkcd_print("             (PowerPC register display TBD)\n");
Packit bf408e
#endif
Packit bf408e
#ifdef X86
Packit bf408e
	lkcd_print("             ebx: %lx\n", dh->dh_regs.ebx);
Packit bf408e
	lkcd_print("             ecx: %lx\n", dh->dh_regs.ecx);
Packit bf408e
	lkcd_print("             edx: %lx\n", dh->dh_regs.edx);
Packit bf408e
	lkcd_print("             esi: %lx\n", dh->dh_regs.esi);
Packit bf408e
	lkcd_print("             edi: %lx\n", dh->dh_regs.edi);
Packit bf408e
	lkcd_print("             eax: %lx\n", dh->dh_regs.eax);
Packit bf408e
	lkcd_print("             xds: %x\n", dh->dh_regs.xds);
Packit bf408e
	lkcd_print("             xes: %x\n", dh->dh_regs.xes);
Packit bf408e
	lkcd_print("        orig_eax: %lx\n", dh->dh_regs.orig_eax);
Packit bf408e
	lkcd_print("             eip: %lx\n", dh->dh_regs.eip);
Packit bf408e
	lkcd_print("             xcs: %x\n", dh->dh_regs.xcs);
Packit bf408e
	lkcd_print("          eflags: %lx\n", dh->dh_regs.eflags);
Packit bf408e
	lkcd_print("             esp: %lx\n", dh->dh_regs.esp);
Packit bf408e
	lkcd_print("             xss: %x\n", dh->dh_regs.xss);
Packit bf408e
#endif
Packit bf408e
Packit bf408e
        if (arg == LKCD_DUMP_HEADER_ONLY)
Packit bf408e
                return;
Packit bf408e
Packit bf408e
dump_page_only:
Packit bf408e
Packit bf408e
	lkcd_print("       dump_page:\n");
Packit bf408e
        lkcd_print("      dp_address: %llx\n", dp->dp_address);
Packit bf408e
        lkcd_print("         dp_size: %ld\n", dp->dp_size);
Packit bf408e
        lkcd_print("        dp_flags: %lx  (", dp->dp_flags);
Packit bf408e
	others = 0;
Packit bf408e
        if (dp->dp_flags & DUMP_COMPRESSED)
Packit bf408e
                lkcd_print("DUMP_COMPRESSED", others++);
Packit bf408e
        if (dp->dp_flags & DUMP_RAW)
Packit bf408e
                lkcd_print("%sDUMP_RAW", others++ ? "|" : "");
Packit bf408e
        if (dp->dp_flags & DUMP_END)
Packit bf408e
                lkcd_print("DUMP_END", others++ ? "|" : "");
Packit bf408e
        lkcd_print(")\n");
Packit bf408e
}