xref: /openbsd-src/gnu/usr.bin/binutils/gdb/core-aout.c (revision 63addd46c1e40ca0f49488ddcdc4ab598023b0c1)
1e93f7393Sniklas /* Extract registers from a "standard" core file, for GDB.
2b725ae77Skettenis    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
3b725ae77Skettenis    1999, 2000, 2001 Free Software Foundation, Inc.
4e93f7393Sniklas 
5e93f7393Sniklas    This file is part of GDB.
6e93f7393Sniklas 
7e93f7393Sniklas    This program is free software; you can redistribute it and/or modify
8e93f7393Sniklas    it under the terms of the GNU General Public License as published by
9e93f7393Sniklas    the Free Software Foundation; either version 2 of the License, or
10e93f7393Sniklas    (at your option) any later version.
11e93f7393Sniklas 
12e93f7393Sniklas    This program is distributed in the hope that it will be useful,
13e93f7393Sniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
14e93f7393Sniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15e93f7393Sniklas    GNU General Public License for more details.
16e93f7393Sniklas 
17e93f7393Sniklas    You should have received a copy of the GNU General Public License
18e93f7393Sniklas    along with this program; if not, write to the Free Software
19b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
21e93f7393Sniklas 
22e93f7393Sniklas /* Typically used on systems that have a.out format executables.
23e93f7393Sniklas    corefile.c is supposed to contain the more machine-independent
24e93f7393Sniklas    aspects of reading registers from core files, while this file is
25e93f7393Sniklas    more machine specific.  */
26e93f7393Sniklas 
27e93f7393Sniklas #include "defs.h"
28b725ae77Skettenis 
29b725ae77Skettenis #ifdef HAVE_PTRACE_H
30b725ae77Skettenis #include <ptrace.h>
31b725ae77Skettenis #else
32b725ae77Skettenis #ifdef HAVE_SYS_PTRACE_H
33b725ae77Skettenis #include <sys/ptrace.h>
34b725ae77Skettenis #endif
35b725ae77Skettenis #endif
36b725ae77Skettenis 
37e93f7393Sniklas #include <sys/types.h>
38e93f7393Sniklas #include <sys/param.h>
39e93f7393Sniklas #include "gdbcore.h"
40*63addd46Skettenis #include "value.h"
41b725ae77Skettenis #include "regcache.h"
42e93f7393Sniklas 
43e93f7393Sniklas /* These are needed on various systems to expand REGISTER_U_ADDR.  */
44b725ae77Skettenis #include "gdb_dirent.h"
45e93f7393Sniklas #include <sys/file.h>
46e93f7393Sniklas #include "gdb_stat.h"
47e93f7393Sniklas #include <sys/user.h>
48e93f7393Sniklas 
49e93f7393Sniklas #ifndef CORE_REGISTER_ADDR
50e93f7393Sniklas #define CORE_REGISTER_ADDR(regno, regptr) register_addr(regno, regptr)
51e93f7393Sniklas #endif /* CORE_REGISTER_ADDR */
52e93f7393Sniklas 
53e93f7393Sniklas #ifdef NEED_SYS_CORE_H
54e93f7393Sniklas #include <sys/core.h>
55e93f7393Sniklas #endif
56e93f7393Sniklas 
57b725ae77Skettenis static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
58b725ae77Skettenis 
59b725ae77Skettenis void _initialize_core_aout (void);
60e93f7393Sniklas 
61e93f7393Sniklas /* Extract the register values out of the core file and store
62e93f7393Sniklas    them where `read_register' will find them.
63e93f7393Sniklas 
64e93f7393Sniklas    CORE_REG_SECT points to the register values themselves, read into memory.
65e93f7393Sniklas    CORE_REG_SIZE is the size of that area.
66e93f7393Sniklas    WHICH says which set of registers we are handling (0 = int, 2 = float
67e93f7393Sniklas    on machines where they are discontiguous).
68e93f7393Sniklas    REG_ADDR is the offset from u.u_ar0 to the register values relative to
69e93f7393Sniklas    core_reg_sect.  This is used with old-fashioned core files to
70e93f7393Sniklas    locate the registers in a large upage-plus-stack ".reg" section.
71e93f7393Sniklas    Original upage address X is at location core_reg_sect+x+reg_addr.
72e93f7393Sniklas  */
73e93f7393Sniklas 
74e93f7393Sniklas static void
fetch_core_registers(char * core_reg_sect,unsigned core_reg_size,int which,CORE_ADDR reg_addr)75b725ae77Skettenis fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
76b725ae77Skettenis 		      CORE_ADDR reg_addr)
77e93f7393Sniklas {
78e93f7393Sniklas   int regno;
79e93f7393Sniklas   CORE_ADDR addr;
80e93f7393Sniklas   int bad_reg = -1;
81e93f7393Sniklas   CORE_ADDR reg_ptr = -reg_addr;	/* Original u.u_ar0 is -reg_addr. */
82b725ae77Skettenis   int numregs = NUM_REGS;
83e93f7393Sniklas 
84e93f7393Sniklas   /* If u.u_ar0 was an absolute address in the core file, relativize it now,
85e93f7393Sniklas      so we can use it as an offset into core_reg_sect.  When we're done,
86e93f7393Sniklas      "register 0" will be at core_reg_sect+reg_ptr, and we can use
87e93f7393Sniklas      CORE_REGISTER_ADDR to offset to the other registers.  If this is a modern
88e93f7393Sniklas      core file without a upage, reg_ptr will be zero and this is all a big
89e93f7393Sniklas      NOP.  */
90e93f7393Sniklas   if (reg_ptr > core_reg_size)
91e93f7393Sniklas     reg_ptr -= KERNEL_U_ADDR;
92e93f7393Sniklas 
93e93f7393Sniklas   for (regno = 0; regno < numregs; regno++)
94e93f7393Sniklas     {
95e93f7393Sniklas       addr = CORE_REGISTER_ADDR (regno, reg_ptr);
96e93f7393Sniklas       if (addr >= core_reg_size
97e93f7393Sniklas 	  && bad_reg < 0)
98e93f7393Sniklas 	bad_reg = regno;
99e93f7393Sniklas       else
100*63addd46Skettenis 	regcache_raw_supply (current_regcache, regno, core_reg_sect + addr);
101e93f7393Sniklas     }
102e93f7393Sniklas 
103e93f7393Sniklas   if (bad_reg >= 0)
104b725ae77Skettenis     error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
105e93f7393Sniklas }
106e93f7393Sniklas 
107e93f7393Sniklas 
108e93f7393Sniklas #ifdef REGISTER_U_ADDR
109e93f7393Sniklas 
110e93f7393Sniklas /* Return the address in the core dump or inferior of register REGNO.
111e93f7393Sniklas    BLOCKEND is the address of the end of the user structure.  */
112e93f7393Sniklas 
113e93f7393Sniklas CORE_ADDR
register_addr(int regno,CORE_ADDR blockend)114b725ae77Skettenis register_addr (int regno, CORE_ADDR blockend)
115e93f7393Sniklas {
116e93f7393Sniklas   CORE_ADDR addr;
117e93f7393Sniklas 
118b725ae77Skettenis   if (regno < 0 || regno >= NUM_REGS)
119e93f7393Sniklas     error ("Invalid register number %d.", regno);
120e93f7393Sniklas 
121e93f7393Sniklas   REGISTER_U_ADDR (addr, blockend, regno);
122e93f7393Sniklas 
123e93f7393Sniklas   return addr;
124e93f7393Sniklas }
125e93f7393Sniklas 
126e93f7393Sniklas #endif /* REGISTER_U_ADDR */
127e93f7393Sniklas 
128b725ae77Skettenis 
129e93f7393Sniklas /* Register that we are able to handle aout (trad-core) file formats.  */
130e93f7393Sniklas 
131e93f7393Sniklas static struct core_fns aout_core_fns =
132e93f7393Sniklas {
133b725ae77Skettenis   bfd_target_unknown_flavour,		/* core_flavour */
134b725ae77Skettenis   default_check_format,			/* check_format */
135b725ae77Skettenis   default_core_sniffer,			/* core_sniffer */
136b725ae77Skettenis   fetch_core_registers,			/* core_read_registers */
137b725ae77Skettenis   NULL					/* next */
138e93f7393Sniklas };
139e93f7393Sniklas 
140e93f7393Sniklas void
_initialize_core_aout(void)141b725ae77Skettenis _initialize_core_aout (void)
142e93f7393Sniklas {
143*63addd46Skettenis   deprecated_add_core_fns (&aout_core_fns);
144e93f7393Sniklas }
145