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