4.4BSD/usr/src/contrib/gdb-4.7.lbl/gdb/kcore.c

Compare this file to the similar file:
Show the results in this format:

/* Work with kernel crash dumps and live systems through kvm.
   This module was developed at Lawrence Berkeley Laboratory
   by Steven McCanne (mccanne@ee.lbl.gov).  It is derived from
   the gdb module core.c.

   Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
   
   This file is part of GDB.
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#ifdef KERNELDEBUG

#include <sys/param.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include "defs.h"
#include "frame.h"  /* required by inferior.h */
#include "inferior.h"
#include "symtab.h"
#include "command.h"
#include "bfd.h"
#include "target.h"
#include "gdbcore.h"

#include "kernel.h"

#include <kvm.h>
#include <sys/stat.h>

/* KVM library handle */

#ifndef KERNEL_XFER_MEMORY
#define KERNEL_XFER_MEMORY kernel_xfer_memory
#endif

static kvm_t *kd;

/* Forward decl */
extern struct target_ops kernel_core_ops;

/* Discard all vestiges of any previous core file
   and mark data and stack spaces as empty.  */

/* ARGSUSED */
void
kernel_core_close (quitting)
	int quitting;
{
	if (kd != 0) {
		kvm_close(kd);
		kd = 0;
	}
	kernel_debugging = 0;
}

/* This routine opens and sets up the core file bfd */

void
kernel_core_open(filename, from_tty)
	char *filename;
	int from_tty;
{
	char *cp;
	struct cleanup *old_chain;
	int ontop;
	char *execfile;
	struct stat stb;
	char *get_exec_file_name();
	
	if (kd != 0) 
		error("kvm already target -- must detach first");

	target_preopen(from_tty);
	if (filename == 0)
		error ("No core file specified.");
	filename = tilde_expand (filename);
	if (filename[0] != '/') {
		cp = concat (current_directory, "/", filename, NULL);
		free(filename);
		filename = cp;
	}
	old_chain = make_cleanup (free, filename);
	execfile = get_exec_file_name();
	if (execfile == 0) 
		error("No executable image specified");

	/*
	 * If we want the active memory file, just use a null arg for kvm.
	 * The SunOS kvm can't read from the default swap device, unless
	 * /dev/mem is indicated with a null pointer.  This has got to be 
	 * a bug.
	 */
	if (stat(filename, &stb) == 0 && S_ISCHR(stb.st_mode))
		filename = 0;

	kd = kvm_open(execfile, filename, (char *)0,
		      write_files ? O_RDWR : O_RDONLY, "gdb");
	if (kd == 0)
		error("Cannot open kernel core image");

	kernel_debugging = 1;
	unpush_target (&kernel_core_ops);
	old_chain = make_cleanup(kernel_core_close, (int)kd);
#ifdef notdef
	validate_files ();
#endif
	ontop = !push_target (&kernel_core_ops);
	discard_cleanups (old_chain);
	
	if (ontop) {
		/* Fetch all registers from core file */
		target_fetch_registers (-1);
		
		/* Now, set up the frame cache, and print the top of stack */
		set_current_frame (create_new_frame (read_register (FP_REGNUM),
						     read_pc ()));
		select_frame (get_current_frame (), 0);
		print_stack_frame (selected_frame, selected_frame_level, 1);
	} else {
		printf (
			"Warning: you won't be able to access this core file until you terminate\n\
your %s; do ``info files''\n", current_target->to_longname);
	}
	/* Machine dependent call to print out panic string etc. */
	kerninfo();
}

void
kernel_core_detach (args, from_tty)
	char *args;
	int from_tty;
{
	if (args)
		error ("Too many arguments");
	unpush_target (&kernel_core_ops);
	if (from_tty)
		printf ("No kernel core file now.\n");
}

static void
kernel_core_files_info (t)
	struct target_ops *t;
{
#ifdef notdef
	struct section_table *p;
	
	printf_filtered ("\t`%s', ", bfd_get_filename(core_bfd));
	wrap_here ("        ");
	printf_filtered ("file type %s.\n", bfd_get_target(core_bfd));
	
	for (p = t->sections; p < t->sections_end; p++) {
		printf_filtered ("\t%s", local_hex_string_custom (p->addr, "08"));
		printf_filtered (" - %s is %s",
				 local_hex_string_custom (p->endaddr, "08"),
				 bfd_section_name (p->bfd, p->sec_ptr));
		if (p->bfd != core_bfd) {
			printf_filtered (" in %s", bfd_get_filename (p->bfd));
		}
		printf_filtered ("\n");
	}
#endif
}

/*
 * Called by the machine dependent module to set a user context.
 * We call kvm_getu() for this desired side effect.
 * BSD kvm doesn't need to do this.
 */
kernel_getu(p)
	u_long *p;
{
#if BSD < 199103 && !defined(ultrix)
        if (kd != 0)
		return (kvm_getu(kd, p) != 0);
#endif
	return (0);
}

int
kernel_xfer_memory(addr, cp, len, write, target)
     CORE_ADDR addr;
     char *cp;
     int len;
     int write;
     struct target_ops *target;
{
	if (write)
		return kvm_write(kd, addr, cp, len);
	else
		return kvm_read(kd, addr, cp, len);
}


/* 
 * In target dependent module.
 */
extern void kernel_core_registers();

struct target_ops kernel_core_ops = {
	"kvm",			/* shortname */
	"Kernel core file",	/* longname */
	"Use a kernel core file as a target.\
  Specify the filename of the core file.", /* doc */
	kernel_core_open,	/* open */
	kernel_core_close,	/* close */
	0,			/* attach */
	kernel_core_detach,	/* detach */
	0,			/* resume */
	0,			/* wait */
	kernel_core_registers,	/* fetch_registers */
	0,			/* store_registers */
	0,			/* prepare_to_store */
	KERNEL_XFER_MEMORY,	/* xfer_memory */
	kernel_core_files_info,	/* files_info */
	0,			/* insert_breakpoint */
	0,			/* remove_breakpoint */
	0,			/* terminal_init */
	0,			/* terminal_inferior */
	0,			/* terminal_ours_for_output */
	0,			/* terminal_ours */
	0,			/* terminal_info */
	0,			/* kill */
	0,			/* load */
	0,			/* lookup_symbol */
	0,			/* create_inferior */
	0,			/* mourn_inferior */
	0,			/* can_run */
	0,			/* notice_signals */
	core_stratum,		/* stratum */
	0,			/* next */
	0,			/* has_all_memory */
	1,			/* has_memory */
	1,			/* has_stack */
	1,			/* has_registers */
	0,			/* has_execution */
	0,			/* sections */
	0,			/* sections_end */
	OPS_MAGIC,		/* magic */
};
#endif

void
_initialize_kernel_core()
{
#ifdef KERNELDEBUG
#ifdef notdef
	
	add_com ("kcore", class_files, core_file_command,
		 "Use FILE as core dump for examining memory and registers.\n\
No arg means have no core file.  This command has been superseded by the\n\
`target core' and `detach' commands.");
#endif
	add_target (&kernel_core_ops);
#endif
}