* config/alpha/tm-fbsd.h (FRAME_CHAIN_VALID): Remove.
[deliverable/binutils-gdb.git] / gdb / mips-linux-tdep.c
CommitLineData
75c9abc6 1/* Target-dependent code for GNU/Linux on MIPS processors.
2aa830e4
DJ
2 Copyright 2001 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include "defs.h"
22#include "gdbcore.h"
23#include "target.h"
24#include "solib-svr4.h"
25
26/* Copied from <asm/elf.h>. */
27#define ELF_NGREG 45
28#define ELF_NFPREG 33
29
30typedef unsigned char elf_greg_t[4];
31typedef elf_greg_t elf_gregset_t[ELF_NGREG];
32
33typedef unsigned char elf_fpreg_t[8];
34typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
35
36/* 0 - 31 are integer registers, 32 - 63 are fp registers. */
37#define FPR_BASE 32
38#define PC 64
39#define CAUSE 65
40#define BADVADDR 66
41#define MMHI 67
42#define MMLO 68
43#define FPC_CSR 69
44#define FPC_EIR 70
45
46#define EF_REG0 6
47#define EF_REG31 37
48#define EF_LO 38
49#define EF_HI 39
50#define EF_CP0_EPC 40
51#define EF_CP0_BADVADDR 41
52#define EF_CP0_STATUS 42
53#define EF_CP0_CAUSE 43
54
55#define EF_SIZE 180
56
57/* Figure out where the longjmp will land.
58 We expect the first arg to be a pointer to the jmp_buf structure from
59 which we extract the pc (JB_PC) that we will land at. The pc is copied
60 into PC. This routine returns 1 on success. */
61
62int
63mips_linux_get_longjmp_target (CORE_ADDR *pc)
64{
65 CORE_ADDR jb_addr;
66 char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
67
68 jb_addr = read_register (A0_REGNUM);
69
70 if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
71 TARGET_PTR_BIT / TARGET_CHAR_BIT))
72 return 0;
73
74 *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
75
76 return 1;
77}
78
79/* Unpack an elf_gregset_t into GDB's register cache. */
80
81void
82supply_gregset (elf_gregset_t *gregsetp)
83{
84 int regi;
85 elf_greg_t *regp = *gregsetp;
86 static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
87
88 for (regi = EF_REG0; regi <= EF_REG31; regi++)
89 supply_register ((regi - EF_REG0), (char *)(regp + regi));
90
91 supply_register (LO_REGNUM, (char *)(regp + EF_LO));
92 supply_register (HI_REGNUM, (char *)(regp + EF_HI));
93
94 supply_register (PC_REGNUM, (char *)(regp + EF_CP0_EPC));
95 supply_register (BADVADDR_REGNUM, (char *)(regp + EF_CP0_BADVADDR));
96 supply_register (PS_REGNUM, (char *)(regp + EF_CP0_STATUS));
97 supply_register (CAUSE_REGNUM, (char *)(regp + EF_CP0_CAUSE));
98
99 /* Fill inaccessible registers with zero. */
100 supply_register (FP_REGNUM, zerobuf);
101 supply_register (UNUSED_REGNUM, zerobuf);
102 for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
103 supply_register (regi, zerobuf);
104}
105
106/* Pack our registers (or one register) into an elf_gregset_t. */
107
108void
109fill_gregset (elf_gregset_t *gregsetp, int regno)
110{
111 int regaddr, regi;
112 elf_greg_t *regp = *gregsetp;
113 void *src, *dst;
114
115 if (regno == -1)
116 {
117 memset (regp, 0, sizeof (elf_gregset_t));
118 for (regi = 0; regi < 32; regi++)
119 fill_gregset (gregsetp, regi);
120 fill_gregset (gregsetp, LO_REGNUM);
121 fill_gregset (gregsetp, HI_REGNUM);
122 fill_gregset (gregsetp, PC_REGNUM);
123 fill_gregset (gregsetp, BADVADDR_REGNUM);
124 fill_gregset (gregsetp, PS_REGNUM);
125 fill_gregset (gregsetp, CAUSE_REGNUM);
126
127 return;
128 }
129
130 if (regno < 32)
131 {
132 src = &registers[REGISTER_BYTE (regno)];
133 dst = regp + regno + EF_REG0;
134 memcpy (dst, src, sizeof (elf_greg_t));
135 return;
136 }
137
138 regaddr = -1;
139 switch (regno)
140 {
141 case LO_REGNUM:
142 regaddr = EF_LO;
143 break;
144 case HI_REGNUM:
145 regaddr = EF_HI;
146 break;
147 case PC_REGNUM:
148 regaddr = EF_CP0_EPC;
149 break;
150 case BADVADDR_REGNUM:
151 regaddr = EF_CP0_BADVADDR;
152 break;
153 case PS_REGNUM:
154 regaddr = EF_CP0_STATUS;
155 break;
156 case CAUSE_REGNUM:
157 regaddr = EF_CP0_CAUSE;
158 break;
159 }
160
161 if (regaddr != -1)
162 {
163 src = &registers[REGISTER_BYTE (regno)];
164 dst = regp + regaddr;
165 memcpy (dst, src, sizeof (elf_greg_t));
166 }
167}
168
169/* Likewise, unpack an elf_fpregset_t. */
170
171void
172supply_fpregset (elf_fpregset_t *fpregsetp)
173{
174 register int regi;
175 static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
176
177 for (regi = 0; regi < 32; regi++)
178 supply_register (FP0_REGNUM + regi,
179 (char *)(*fpregsetp + regi));
180
181 supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
182
183 /* FIXME: how can we supply FCRIR_REGNUM? The ABI doesn't tell us. */
184 supply_register (FCRIR_REGNUM, zerobuf);
185}
186
187/* Likewise, pack one or all floating point registers into an
188 elf_fpregset_t. */
189
190void
191fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
192{
193 char *from, *to;
194
195 if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
196 {
197 from = (char *) &registers[REGISTER_BYTE (regno)];
198 to = (char *) (*fpregsetp + regno - FP0_REGNUM);
199 memcpy (to, from, REGISTER_RAW_SIZE (regno - FP0_REGNUM));
200 }
201 else if (regno == FCRCS_REGNUM)
202 {
203 from = (char *) &registers[REGISTER_BYTE (regno)];
204 to = (char *) (*fpregsetp + 32);
205 memcpy (to, from, REGISTER_RAW_SIZE (regno));
206 }
207 else if (regno == -1)
208 {
209 int regi;
210
211 for (regi = 0; regi < 32; regi++)
212 fill_fpregset (fpregsetp, FP0_REGNUM + regi);
213 fill_fpregset(fpregsetp, FCRCS_REGNUM);
214 }
215}
216
217/* Map gdb internal register number to ptrace ``address''.
218 These ``addresses'' are normally defined in <asm/ptrace.h>. */
219
220CORE_ADDR
221register_addr (int regno, CORE_ADDR blockend)
222{
223 int regaddr;
224
225 if (regno < 0 || regno >= NUM_REGS)
226 error ("Bogon register number %d.", regno);
227
228 if (regno < 32)
229 regaddr = regno;
230 else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
231 regaddr = FPR_BASE + (regno - FP0_REGNUM);
232 else if (regno == PC_REGNUM)
233 regaddr = PC;
234 else if (regno == CAUSE_REGNUM)
235 regaddr = CAUSE;
236 else if (regno == BADVADDR_REGNUM)
237 regaddr = BADVADDR;
238 else if (regno == LO_REGNUM)
239 regaddr = MMLO;
240 else if (regno == HI_REGNUM)
241 regaddr = MMHI;
242 else if (regno == FCRCS_REGNUM)
243 regaddr = FPC_CSR;
244 else if (regno == FCRIR_REGNUM)
245 regaddr = FPC_EIR;
246 else
247 error ("Unknowable register number %d.", regno);
248
249 return regaddr;
250}
251
252/* Use a local version of this function to get the correct types for
253 regsets, until multi-arch core support is ready. */
254
255static void
256fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
257 int which, CORE_ADDR reg_addr)
258{
259 elf_gregset_t gregset;
260 elf_fpregset_t fpregset;
261
262 if (which == 0)
263 {
264 if (core_reg_size != sizeof (gregset))
265 {
266 warning ("wrong size gregset struct in core file");
267 }
268 else
269 {
270 memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
271 supply_gregset (&gregset);
272 }
273 }
274 else if (which == 2)
275 {
276 if (core_reg_size != sizeof (fpregset))
277 {
278 warning ("wrong size fpregset struct in core file");
279 }
280 else
281 {
282 memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
283 supply_fpregset (&fpregset);
284 }
285 }
286}
287
288/* Register that we are able to handle ELF file formats using standard
289 procfs "regset" structures. */
290
291static struct core_fns regset_core_fns =
292{
293 bfd_target_elf_flavour, /* core_flavour */
294 default_check_format, /* check_format */
295 default_core_sniffer, /* core_sniffer */
296 fetch_core_registers, /* core_read_registers */
297 NULL /* next */
298};
299
300/* Fetch (and possibly build) an appropriate link_map_offsets
75c9abc6 301 structure for native GNU/Linux MIPS targets using the struct offsets
2aa830e4
DJ
302 defined in link.h (but without actual reference to that file).
303
75c9abc6
DJ
304 This makes it possible to access GNU/Linux MIPS shared libraries from a
305 GDB that was built on a different host platform (for cross debugging). */
2aa830e4
DJ
306
307struct link_map_offsets *
308mips_linux_svr4_fetch_link_map_offsets (void)
309{
310 static struct link_map_offsets lmo;
311 static struct link_map_offsets *lmp = NULL;
312
313 if (lmp == NULL)
314 {
315 lmp = &lmo;
316
317 lmo.r_debug_size = 8; /* The actual size is 20 bytes, but
318 this is all we need. */
319 lmo.r_map_offset = 4;
320 lmo.r_map_size = 4;
321
322 lmo.link_map_size = 20;
323
324 lmo.l_addr_offset = 0;
325 lmo.l_addr_size = 4;
326
327 lmo.l_name_offset = 4;
328 lmo.l_name_size = 4;
329
330 lmo.l_next_offset = 12;
331 lmo.l_next_size = 4;
332
333 lmo.l_prev_offset = 16;
334 lmo.l_prev_size = 4;
335 }
336
337 return lmp;
338}
339
340void
d1bacddc 341_initialize_mips_linux_tdep (void)
2aa830e4
DJ
342{
343 add_core_fns (&regset_core_fns);
344}
This page took 0.100945 seconds and 4 git commands to generate.