This commit was manufactured by cvs2svn to create tag 'drow-cplus-
[external/binutils.git] / gdb / core-sol2.c
1 /* Machine independent support for Solaris 2 core files for GDB.
2    Copyright 1994, 1995, 1996, 1998, 1999, 2000, 2001
3    Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22
23 /* Solaris comes with two flavours of core files, cores generated by
24    an ELF executable and cores generated by programs that were
25    run under BCP (the part of Solaris which allows it to run SunOS4
26    a.out files).
27    This file combines the core register fetching from core-regset.c
28    and sparc-nat.c to be able to read both flavours.  */
29
30 #include "defs.h"
31
32 #if defined (__sparcv9)
33 /* Fails to get included by the Solaris system header files.  */
34 # include <v9/sys/privregs.h>
35 #endif
36
37 #include <time.h>
38 #include <sys/types.h>
39 #include <sys/regset.h>
40 #include <sys/procfs.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include "gdb_string.h"
44 #include "regcache.h"
45
46 #include "inferior.h"
47 #include "target.h"
48 #include "command.h"
49 #include "gdbcore.h"
50
51 /* Prototypes for supply_gregset etc. */
52 #include "gregset.h"
53
54 static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
55
56 /* Fetch registers from core file data pointed to by CORE_REG_SECT.  When
57    WHICH is 0, the the general register set is fetched; when WHICH is
58    2, the floating point registers are fetched.  CORE_REG_SIZE is used
59    to validate the size of the data pointed to by CORE_REG_SECT.  REG_ADDR
60    is unused. */
61
62 static void
63 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
64                       CORE_ADDR reg_addr)
65 {
66   int i;
67
68   if (which == 0)
69     {
70       prgregset_t prgregset;
71
72       if (core_reg_size == sizeof (prgregset_t))
73         {
74           memcpy ((char *) &prgregset, core_reg_sect, sizeof (prgregset));
75           supply_gregset (&prgregset);
76         }
77 #if defined (HAVE_PRGREGSET32_T)
78       /* 32-bit corefile, 64-bit debugger.  */
79       else if (core_reg_size == sizeof (prgregset32_t))
80         {
81           prgreg32_t *core_gregs;
82
83           /* Can't use memcpy here, because the core file contains
84              32-bit regs; supply_register expects 64-bit regs.  */
85           core_gregs = (prgreg32_t *) core_reg_sect;
86           for (i = 0; i < NPRGREG; i++)
87             prgregset[i] = core_gregs[i];
88
89           supply_gregset (&prgregset);
90         }
91 #endif /* HAVE_PRGREGSET32_T */
92       else if (core_reg_size == sizeof (struct regs))
93         {
94           struct regs *gregs = (struct regs *) core_reg_sect;
95
96           /* G0 *always* holds 0.  */
97           *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (0)] = 0;
98
99           /* The globals and output registers.  */
100           memcpy (&deprecated_registers[DEPRECATED_REGISTER_BYTE (G1_REGNUM)],
101                   &gregs->r_g1, 15 * DEPRECATED_REGISTER_RAW_SIZE (G1_REGNUM));
102           *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (PS_REGNUM)]
103             = gregs->r_ps;
104           *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (PC_REGNUM)]
105             = gregs->r_pc;
106           *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (DEPRECATED_NPC_REGNUM)]
107             = gregs->r_npc;
108           *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (Y_REGNUM)]
109             = gregs->r_y;
110
111           /* My best guess at where to get the locals and input
112              registers is exactly where they usually are, right above
113              the stack pointer.  If the core dump was caused by a bus error
114              from blowing away the stack pointer (as is possible) then this
115              won't work, but it's worth the try. */
116           {
117             int sp;
118
119             sp = *(int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (SP_REGNUM)];
120             if (0 != target_read_memory (sp,
121                                          &deprecated_registers[DEPRECATED_REGISTER_BYTE (L0_REGNUM)],
122                                          16 * DEPRECATED_REGISTER_RAW_SIZE (L0_REGNUM)))
123               {
124                 warning ("couldn't read input and local registers from core file\n");
125               }
126           }
127         }
128       else
129         {
130           warning ("wrong size gregset struct in core file");
131         }
132     }
133   else if (which == 2)
134     {
135       prfpregset_t prfpregset;
136
137       if (core_reg_size == sizeof (prfpregset_t))
138         {
139           memcpy ((char *) &prfpregset, core_reg_sect, sizeof (prfpregset));
140           supply_fpregset (&prfpregset);
141         }
142 #if defined (HAVE_PRFPREGSET32_T)
143       /* 32-bit corefile, 64-bit debugger.  */
144       else if (core_reg_size == sizeof (prfpregset32_t))
145         {
146           prfpregset32_t *core_fpregset;
147
148           /* Can't use memcpy here, because the core file contains
149              32-bit regs; supply_fpregset expects 64-bit regs.  */
150
151           core_fpregset = (prfpregset32_t *) core_reg_sect;
152           for (i = 0; i < 16; i++)
153             prfpregset.pr_fr.pr_dregs[i] = core_fpregset->pr_fr.pr_dregs[i];
154           while (i < 32)
155             prfpregset.pr_fr.pr_dregs[i++] = 0;
156
157           prfpregset.pr_fsr         = core_fpregset->pr_fsr;
158           prfpregset.pr_qcnt        = core_fpregset->pr_qcnt;
159           prfpregset.pr_q_entrysize = core_fpregset->pr_q_entrysize;
160           prfpregset.pr_en          = core_fpregset->pr_en;
161           /* We will not use the pr_q array.  */
162
163           supply_fpregset (&prfpregset);
164         }
165 #endif /* HAVE_PRFPREGSET32_T */
166       else if (core_reg_size >= sizeof (struct fpu))
167         {
168           struct fpu *fpuregs = (struct fpu *) core_reg_sect;
169
170           memcpy (&deprecated_registers[DEPRECATED_REGISTER_BYTE (FP0_REGNUM)],
171                   &fpuregs->fpu_fr, sizeof (fpuregs->fpu_fr));
172           memcpy (&deprecated_registers[DEPRECATED_REGISTER_BYTE (FPS_REGNUM)],
173                   &fpuregs->fpu_fsr, sizeof (FPU_FSR_TYPE));
174         }
175       else
176         {
177           warning ("wrong size fpregset struct in core file");
178         }
179     }
180 }
181 \f
182
183 /* Register that we are able to handle solaris core file formats. */
184
185 static struct core_fns solaris_core_fns =
186 {
187   bfd_target_elf_flavour,               /* core_flavour */
188   default_check_format,                 /* check_format */
189   default_core_sniffer,                 /* core_sniffer */
190   fetch_core_registers,                 /* core_read_registers */
191   NULL                                  /* next */
192 };
193
194 void
195 _initialize_core_solaris (void)
196 {
197   add_core_fns (&solaris_core_fns);
198 }