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