core-aout.c   [plain text]

/* Extract registers from a "standard" core file, for GDB.
   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
   1999, 2000, 2001 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
   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., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

/* Typically used on systems that have a.out format executables.
   corefile.c is supposed to contain the more machine-independent
   aspects of reading registers from core files, while this file is
   more machine specific.  */

#include "defs.h"

#include <ptrace.h>
#include <sys/ptrace.h>

#include <sys/types.h>
#include <sys/param.h>
#include "gdbcore.h"
#include "value.h"
#include "regcache.h"

/* These are needed on various systems to expand REGISTER_U_ADDR.  */
#include "gdb_dirent.h"
#include <sys/file.h>
#include "gdb_stat.h"
#include <sys/user.h>

#define CORE_REGISTER_ADDR(regno, regptr) register_addr(regno, regptr)

#include <sys/core.h>

static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);

void _initialize_core_aout (void);

/* Extract the register values out of the core file and store
   them where `read_register' will find them.

   CORE_REG_SECT points to the register values themselves, read into memory.
   CORE_REG_SIZE is the size of that area.
   WHICH says which set of registers we are handling (0 = int, 2 = float
   on machines where they are discontiguous).
   REG_ADDR is the offset from u.u_ar0 to the register values relative to
   core_reg_sect.  This is used with old-fashioned core files to
   locate the registers in a large upage-plus-stack ".reg" section.
   Original upage address X is at location core_reg_sect+x+reg_addr.

static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
		      CORE_ADDR reg_addr)
  int regno;
  CORE_ADDR addr;
  int bad_reg = -1;
  CORE_ADDR reg_ptr = -reg_addr;	/* Original u.u_ar0 is -reg_addr. */
  int numregs = NUM_REGS;

  /* If u.u_ar0 was an absolute address in the core file, relativize it now,
     so we can use it as an offset into core_reg_sect.  When we're done,
     "register 0" will be at core_reg_sect+reg_ptr, and we can use
     CORE_REGISTER_ADDR to offset to the other registers.  If this is a modern
     core file without a upage, reg_ptr will be zero and this is all a big
     NOP.  */
  if (reg_ptr > core_reg_size)
    reg_ptr -= KERNEL_U_ADDR;

  for (regno = 0; regno < numregs; regno++)
      addr = CORE_REGISTER_ADDR (regno, reg_ptr);
      if (addr >= core_reg_size
	  && bad_reg < 0)
	bad_reg = regno;
	regcache_raw_supply (current_regcache, regno, core_reg_sect + addr);

  if (bad_reg >= 0)
    error (_("Register %s not found in core file."), REGISTER_NAME (bad_reg));


/* Return the address in the core dump or inferior of register REGNO.
   BLOCKEND is the address of the end of the user structure.  */

register_addr (int regno, CORE_ADDR blockend)
  CORE_ADDR addr;

  if (regno < 0 || regno >= NUM_REGS)
    error (_("Invalid register number %d."), regno);

  REGISTER_U_ADDR (addr, blockend, regno);

  return addr;

#endif /* REGISTER_U_ADDR */

/* Register that we are able to handle aout (trad-core) file formats.  */

static struct core_fns aout_core_fns =
  bfd_target_unknown_flavour,		/* core_flavour */
  default_check_format,			/* check_format */
  default_core_sniffer,			/* core_sniffer */
  fetch_core_registers,			/* core_read_registers */
  NULL					/* next */

_initialize_core_aout (void)
  deprecated_add_core_fns (&aout_core_fns);