1b725ae77Skettenis /* Target-dependent code for GNU/Linux on MIPS processors.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 2001, 2002, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis
5b725ae77Skettenis This file is part of GDB.
6b725ae77Skettenis
7b725ae77Skettenis This program is free software; you can redistribute it and/or modify
8b725ae77Skettenis it under the terms of the GNU General Public License as published by
9b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
10b725ae77Skettenis (at your option) any later version.
11b725ae77Skettenis
12b725ae77Skettenis This program is distributed in the hope that it will be useful,
13b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
14b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15b725ae77Skettenis GNU General Public License for more details.
16b725ae77Skettenis
17b725ae77Skettenis You should have received a copy of the GNU General Public License
18b725ae77Skettenis 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. */
21b725ae77Skettenis
22b725ae77Skettenis #include "defs.h"
23b725ae77Skettenis #include "gdbcore.h"
24b725ae77Skettenis #include "target.h"
25b725ae77Skettenis #include "solib-svr4.h"
26b725ae77Skettenis #include "osabi.h"
27b725ae77Skettenis #include "mips-tdep.h"
28b725ae77Skettenis #include "gdb_string.h"
29b725ae77Skettenis #include "gdb_assert.h"
30b725ae77Skettenis #include "frame.h"
31*11efff7fSkettenis #include "trad-frame.h"
32*11efff7fSkettenis #include "tramp-frame.h"
33b725ae77Skettenis
34b725ae77Skettenis /* Copied from <asm/elf.h>. */
35b725ae77Skettenis #define ELF_NGREG 45
36b725ae77Skettenis #define ELF_NFPREG 33
37b725ae77Skettenis
38b725ae77Skettenis typedef unsigned char elf_greg_t[4];
39b725ae77Skettenis typedef elf_greg_t elf_gregset_t[ELF_NGREG];
40b725ae77Skettenis
41b725ae77Skettenis typedef unsigned char elf_fpreg_t[8];
42b725ae77Skettenis typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
43b725ae77Skettenis
44b725ae77Skettenis /* 0 - 31 are integer registers, 32 - 63 are fp registers. */
45b725ae77Skettenis #define FPR_BASE 32
46b725ae77Skettenis #define PC 64
47b725ae77Skettenis #define CAUSE 65
48b725ae77Skettenis #define BADVADDR 66
49b725ae77Skettenis #define MMHI 67
50b725ae77Skettenis #define MMLO 68
51b725ae77Skettenis #define FPC_CSR 69
52b725ae77Skettenis #define FPC_EIR 70
53b725ae77Skettenis
54b725ae77Skettenis #define EF_REG0 6
55b725ae77Skettenis #define EF_REG31 37
56b725ae77Skettenis #define EF_LO 38
57b725ae77Skettenis #define EF_HI 39
58b725ae77Skettenis #define EF_CP0_EPC 40
59b725ae77Skettenis #define EF_CP0_BADVADDR 41
60b725ae77Skettenis #define EF_CP0_STATUS 42
61b725ae77Skettenis #define EF_CP0_CAUSE 43
62b725ae77Skettenis
63b725ae77Skettenis #define EF_SIZE 180
64b725ae77Skettenis
65b725ae77Skettenis /* Figure out where the longjmp will land.
66b725ae77Skettenis We expect the first arg to be a pointer to the jmp_buf structure from
67b725ae77Skettenis which we extract the pc (MIPS_LINUX_JB_PC) that we will land at. The pc
68b725ae77Skettenis is copied into PC. This routine returns 1 on success. */
69b725ae77Skettenis
70b725ae77Skettenis #define MIPS_LINUX_JB_ELEMENT_SIZE 4
71b725ae77Skettenis #define MIPS_LINUX_JB_PC 0
72b725ae77Skettenis
73b725ae77Skettenis static int
mips_linux_get_longjmp_target(CORE_ADDR * pc)74b725ae77Skettenis mips_linux_get_longjmp_target (CORE_ADDR *pc)
75b725ae77Skettenis {
76b725ae77Skettenis CORE_ADDR jb_addr;
77b725ae77Skettenis char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
78b725ae77Skettenis
79b725ae77Skettenis jb_addr = read_register (A0_REGNUM);
80b725ae77Skettenis
81b725ae77Skettenis if (target_read_memory (jb_addr
82b725ae77Skettenis + MIPS_LINUX_JB_PC * MIPS_LINUX_JB_ELEMENT_SIZE,
83b725ae77Skettenis buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
84b725ae77Skettenis return 0;
85b725ae77Skettenis
86b725ae77Skettenis *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
87b725ae77Skettenis
88b725ae77Skettenis return 1;
89b725ae77Skettenis }
90b725ae77Skettenis
91b725ae77Skettenis /* Transform the bits comprising a 32-bit register to the right size
92*11efff7fSkettenis for regcache_raw_supply(). This is needed when mips_isa_regsize()
93*11efff7fSkettenis is 8. */
94b725ae77Skettenis
95b725ae77Skettenis static void
supply_32bit_reg(int regnum,const void * addr)96b725ae77Skettenis supply_32bit_reg (int regnum, const void *addr)
97b725ae77Skettenis {
98b725ae77Skettenis char buf[MAX_REGISTER_SIZE];
99*11efff7fSkettenis store_signed_integer (buf, register_size (current_gdbarch, regnum),
100b725ae77Skettenis extract_signed_integer (addr, 4));
101*11efff7fSkettenis regcache_raw_supply (current_regcache, regnum, buf);
102b725ae77Skettenis }
103b725ae77Skettenis
104b725ae77Skettenis /* Unpack an elf_gregset_t into GDB's register cache. */
105b725ae77Skettenis
106b725ae77Skettenis void
supply_gregset(elf_gregset_t * gregsetp)107b725ae77Skettenis supply_gregset (elf_gregset_t *gregsetp)
108b725ae77Skettenis {
109b725ae77Skettenis int regi;
110b725ae77Skettenis elf_greg_t *regp = *gregsetp;
111b725ae77Skettenis char zerobuf[MAX_REGISTER_SIZE];
112b725ae77Skettenis
113b725ae77Skettenis memset (zerobuf, 0, MAX_REGISTER_SIZE);
114b725ae77Skettenis
115b725ae77Skettenis for (regi = EF_REG0; regi <= EF_REG31; regi++)
116b725ae77Skettenis supply_32bit_reg ((regi - EF_REG0), (char *)(regp + regi));
117b725ae77Skettenis
118b725ae77Skettenis supply_32bit_reg (mips_regnum (current_gdbarch)->lo,
119b725ae77Skettenis (char *)(regp + EF_LO));
120b725ae77Skettenis supply_32bit_reg (mips_regnum (current_gdbarch)->hi,
121b725ae77Skettenis (char *)(regp + EF_HI));
122b725ae77Skettenis
123b725ae77Skettenis supply_32bit_reg (mips_regnum (current_gdbarch)->pc,
124b725ae77Skettenis (char *)(regp + EF_CP0_EPC));
125b725ae77Skettenis supply_32bit_reg (mips_regnum (current_gdbarch)->badvaddr,
126b725ae77Skettenis (char *)(regp + EF_CP0_BADVADDR));
127b725ae77Skettenis supply_32bit_reg (PS_REGNUM, (char *)(regp + EF_CP0_STATUS));
128b725ae77Skettenis supply_32bit_reg (mips_regnum (current_gdbarch)->cause,
129b725ae77Skettenis (char *)(regp + EF_CP0_CAUSE));
130b725ae77Skettenis
131b725ae77Skettenis /* Fill inaccessible registers with zero. */
132*11efff7fSkettenis regcache_raw_supply (current_regcache, UNUSED_REGNUM, zerobuf);
133b725ae77Skettenis for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
134*11efff7fSkettenis regcache_raw_supply (current_regcache, regi, zerobuf);
135b725ae77Skettenis }
136b725ae77Skettenis
137b725ae77Skettenis /* Pack our registers (or one register) into an elf_gregset_t. */
138b725ae77Skettenis
139b725ae77Skettenis void
fill_gregset(elf_gregset_t * gregsetp,int regno)140b725ae77Skettenis fill_gregset (elf_gregset_t *gregsetp, int regno)
141b725ae77Skettenis {
142b725ae77Skettenis int regaddr, regi;
143b725ae77Skettenis elf_greg_t *regp = *gregsetp;
144b725ae77Skettenis void *dst;
145b725ae77Skettenis
146b725ae77Skettenis if (regno == -1)
147b725ae77Skettenis {
148b725ae77Skettenis memset (regp, 0, sizeof (elf_gregset_t));
149b725ae77Skettenis for (regi = 0; regi < 32; regi++)
150b725ae77Skettenis fill_gregset (gregsetp, regi);
151b725ae77Skettenis fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo);
152b725ae77Skettenis fill_gregset (gregsetp, mips_regnum (current_gdbarch)->hi);
153b725ae77Skettenis fill_gregset (gregsetp, mips_regnum (current_gdbarch)->pc);
154b725ae77Skettenis fill_gregset (gregsetp, mips_regnum (current_gdbarch)->badvaddr);
155b725ae77Skettenis fill_gregset (gregsetp, PS_REGNUM);
156b725ae77Skettenis fill_gregset (gregsetp, mips_regnum (current_gdbarch)->cause);
157b725ae77Skettenis
158b725ae77Skettenis return;
159b725ae77Skettenis }
160b725ae77Skettenis
161b725ae77Skettenis if (regno < 32)
162b725ae77Skettenis {
163b725ae77Skettenis dst = regp + regno + EF_REG0;
164*11efff7fSkettenis regcache_raw_collect (current_regcache, regno, dst);
165b725ae77Skettenis return;
166b725ae77Skettenis }
167b725ae77Skettenis
168b725ae77Skettenis if (regno == mips_regnum (current_gdbarch)->lo)
169b725ae77Skettenis regaddr = EF_LO;
170b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->hi)
171b725ae77Skettenis regaddr = EF_HI;
172b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->pc)
173b725ae77Skettenis regaddr = EF_CP0_EPC;
174b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->badvaddr)
175b725ae77Skettenis regaddr = EF_CP0_BADVADDR;
176b725ae77Skettenis else if (regno == PS_REGNUM)
177b725ae77Skettenis regaddr = EF_CP0_STATUS;
178b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->cause)
179b725ae77Skettenis regaddr = EF_CP0_CAUSE;
180b725ae77Skettenis else
181b725ae77Skettenis regaddr = -1;
182b725ae77Skettenis
183b725ae77Skettenis if (regaddr != -1)
184b725ae77Skettenis {
185b725ae77Skettenis dst = regp + regaddr;
186*11efff7fSkettenis regcache_raw_collect (current_regcache, regno, dst);
187b725ae77Skettenis }
188b725ae77Skettenis }
189b725ae77Skettenis
190b725ae77Skettenis /* Likewise, unpack an elf_fpregset_t. */
191b725ae77Skettenis
192b725ae77Skettenis void
supply_fpregset(elf_fpregset_t * fpregsetp)193b725ae77Skettenis supply_fpregset (elf_fpregset_t *fpregsetp)
194b725ae77Skettenis {
195b725ae77Skettenis int regi;
196b725ae77Skettenis char zerobuf[MAX_REGISTER_SIZE];
197b725ae77Skettenis
198b725ae77Skettenis memset (zerobuf, 0, MAX_REGISTER_SIZE);
199b725ae77Skettenis
200b725ae77Skettenis for (regi = 0; regi < 32; regi++)
201*11efff7fSkettenis regcache_raw_supply (current_regcache, FP0_REGNUM + regi,
202b725ae77Skettenis (char *)(*fpregsetp + regi));
203b725ae77Skettenis
204*11efff7fSkettenis regcache_raw_supply (current_regcache,
205*11efff7fSkettenis mips_regnum (current_gdbarch)->fp_control_status,
206b725ae77Skettenis (char *)(*fpregsetp + 32));
207b725ae77Skettenis
208b725ae77Skettenis /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */
209*11efff7fSkettenis regcache_raw_supply (current_regcache,
210*11efff7fSkettenis mips_regnum (current_gdbarch)->fp_implementation_revision,
211b725ae77Skettenis zerobuf);
212b725ae77Skettenis }
213b725ae77Skettenis
214b725ae77Skettenis /* Likewise, pack one or all floating point registers into an
215b725ae77Skettenis elf_fpregset_t. */
216b725ae77Skettenis
217b725ae77Skettenis void
fill_fpregset(elf_fpregset_t * fpregsetp,int regno)218b725ae77Skettenis fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
219b725ae77Skettenis {
220b725ae77Skettenis char *from, *to;
221b725ae77Skettenis
222b725ae77Skettenis if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
223b725ae77Skettenis {
224b725ae77Skettenis from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
225b725ae77Skettenis to = (char *) (*fpregsetp + regno - FP0_REGNUM);
226*11efff7fSkettenis memcpy (to, from, register_size (current_gdbarch, regno - FP0_REGNUM));
227b725ae77Skettenis }
228b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
229b725ae77Skettenis {
230b725ae77Skettenis from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
231b725ae77Skettenis to = (char *) (*fpregsetp + 32);
232*11efff7fSkettenis memcpy (to, from, register_size (current_gdbarch, regno));
233b725ae77Skettenis }
234b725ae77Skettenis else if (regno == -1)
235b725ae77Skettenis {
236b725ae77Skettenis int regi;
237b725ae77Skettenis
238b725ae77Skettenis for (regi = 0; regi < 32; regi++)
239b725ae77Skettenis fill_fpregset (fpregsetp, FP0_REGNUM + regi);
240b725ae77Skettenis fill_fpregset(fpregsetp, mips_regnum (current_gdbarch)->fp_control_status);
241b725ae77Skettenis }
242b725ae77Skettenis }
243b725ae77Skettenis
244b725ae77Skettenis /* Map gdb internal register number to ptrace ``address''.
245b725ae77Skettenis These ``addresses'' are normally defined in <asm/ptrace.h>. */
246b725ae77Skettenis
247b725ae77Skettenis static CORE_ADDR
mips_linux_register_addr(int regno,CORE_ADDR blockend)248b725ae77Skettenis mips_linux_register_addr (int regno, CORE_ADDR blockend)
249b725ae77Skettenis {
250b725ae77Skettenis int regaddr;
251b725ae77Skettenis
252b725ae77Skettenis if (regno < 0 || regno >= NUM_REGS)
253b725ae77Skettenis error ("Bogon register number %d.", regno);
254b725ae77Skettenis
255b725ae77Skettenis if (regno < 32)
256b725ae77Skettenis regaddr = regno;
257b725ae77Skettenis else if ((regno >= mips_regnum (current_gdbarch)->fp0)
258b725ae77Skettenis && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
259b725ae77Skettenis regaddr = FPR_BASE + (regno - mips_regnum (current_gdbarch)->fp0);
260b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->pc)
261b725ae77Skettenis regaddr = PC;
262b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->cause)
263b725ae77Skettenis regaddr = CAUSE;
264b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->badvaddr)
265b725ae77Skettenis regaddr = BADVADDR;
266b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->lo)
267b725ae77Skettenis regaddr = MMLO;
268b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->hi)
269b725ae77Skettenis regaddr = MMHI;
270b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
271b725ae77Skettenis regaddr = FPC_CSR;
272b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
273b725ae77Skettenis regaddr = FPC_EIR;
274b725ae77Skettenis else
275b725ae77Skettenis error ("Unknowable register number %d.", regno);
276b725ae77Skettenis
277b725ae77Skettenis return regaddr;
278b725ae77Skettenis }
279b725ae77Skettenis
280b725ae77Skettenis
281b725ae77Skettenis /* Fetch (and possibly build) an appropriate link_map_offsets
282b725ae77Skettenis structure for native GNU/Linux MIPS targets using the struct offsets
283b725ae77Skettenis defined in link.h (but without actual reference to that file).
284b725ae77Skettenis
285b725ae77Skettenis This makes it possible to access GNU/Linux MIPS shared libraries from a
286b725ae77Skettenis GDB that was built on a different host platform (for cross debugging). */
287b725ae77Skettenis
288b725ae77Skettenis static struct link_map_offsets *
mips_linux_svr4_fetch_link_map_offsets(void)289b725ae77Skettenis mips_linux_svr4_fetch_link_map_offsets (void)
290b725ae77Skettenis {
291b725ae77Skettenis static struct link_map_offsets lmo;
292b725ae77Skettenis static struct link_map_offsets *lmp = NULL;
293b725ae77Skettenis
294b725ae77Skettenis if (lmp == NULL)
295b725ae77Skettenis {
296b725ae77Skettenis lmp = &lmo;
297b725ae77Skettenis
298b725ae77Skettenis lmo.r_debug_size = 8; /* The actual size is 20 bytes, but
299b725ae77Skettenis this is all we need. */
300b725ae77Skettenis lmo.r_map_offset = 4;
301b725ae77Skettenis lmo.r_map_size = 4;
302b725ae77Skettenis
303b725ae77Skettenis lmo.link_map_size = 20;
304b725ae77Skettenis
305b725ae77Skettenis lmo.l_addr_offset = 0;
306b725ae77Skettenis lmo.l_addr_size = 4;
307b725ae77Skettenis
308b725ae77Skettenis lmo.l_name_offset = 4;
309b725ae77Skettenis lmo.l_name_size = 4;
310b725ae77Skettenis
311b725ae77Skettenis lmo.l_next_offset = 12;
312b725ae77Skettenis lmo.l_next_size = 4;
313b725ae77Skettenis
314b725ae77Skettenis lmo.l_prev_offset = 16;
315b725ae77Skettenis lmo.l_prev_size = 4;
316b725ae77Skettenis }
317b725ae77Skettenis
318b725ae77Skettenis return lmp;
319b725ae77Skettenis }
320b725ae77Skettenis
321b725ae77Skettenis /* Support for 64-bit ABIs. */
322b725ae77Skettenis
323b725ae77Skettenis /* Copied from <asm/elf.h>. */
324b725ae77Skettenis #define MIPS64_ELF_NGREG 45
325b725ae77Skettenis #define MIPS64_ELF_NFPREG 33
326b725ae77Skettenis
327b725ae77Skettenis typedef unsigned char mips64_elf_greg_t[8];
328b725ae77Skettenis typedef mips64_elf_greg_t mips64_elf_gregset_t[MIPS64_ELF_NGREG];
329b725ae77Skettenis
330b725ae77Skettenis typedef unsigned char mips64_elf_fpreg_t[8];
331b725ae77Skettenis typedef mips64_elf_fpreg_t mips64_elf_fpregset_t[MIPS64_ELF_NFPREG];
332b725ae77Skettenis
333b725ae77Skettenis /* 0 - 31 are integer registers, 32 - 63 are fp registers. */
334b725ae77Skettenis #define MIPS64_FPR_BASE 32
335b725ae77Skettenis #define MIPS64_PC 64
336b725ae77Skettenis #define MIPS64_CAUSE 65
337b725ae77Skettenis #define MIPS64_BADVADDR 66
338b725ae77Skettenis #define MIPS64_MMHI 67
339b725ae77Skettenis #define MIPS64_MMLO 68
340b725ae77Skettenis #define MIPS64_FPC_CSR 69
341b725ae77Skettenis #define MIPS64_FPC_EIR 70
342b725ae77Skettenis
343b725ae77Skettenis #define MIPS64_EF_REG0 0
344b725ae77Skettenis #define MIPS64_EF_REG31 31
345b725ae77Skettenis #define MIPS64_EF_LO 32
346b725ae77Skettenis #define MIPS64_EF_HI 33
347b725ae77Skettenis #define MIPS64_EF_CP0_EPC 34
348b725ae77Skettenis #define MIPS64_EF_CP0_BADVADDR 35
349b725ae77Skettenis #define MIPS64_EF_CP0_STATUS 36
350b725ae77Skettenis #define MIPS64_EF_CP0_CAUSE 37
351b725ae77Skettenis
352b725ae77Skettenis #define MIPS64_EF_SIZE 304
353b725ae77Skettenis
354b725ae77Skettenis /* Figure out where the longjmp will land.
355b725ae77Skettenis We expect the first arg to be a pointer to the jmp_buf structure from
356b725ae77Skettenis which we extract the pc (MIPS_LINUX_JB_PC) that we will land at. The pc
357b725ae77Skettenis is copied into PC. This routine returns 1 on success. */
358b725ae77Skettenis
359b725ae77Skettenis /* Details about jmp_buf. */
360b725ae77Skettenis
361b725ae77Skettenis #define MIPS64_LINUX_JB_PC 0
362b725ae77Skettenis
363b725ae77Skettenis static int
mips64_linux_get_longjmp_target(CORE_ADDR * pc)364b725ae77Skettenis mips64_linux_get_longjmp_target (CORE_ADDR *pc)
365b725ae77Skettenis {
366b725ae77Skettenis CORE_ADDR jb_addr;
367b725ae77Skettenis void *buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
368b725ae77Skettenis int element_size = TARGET_PTR_BIT == 32 ? 4 : 8;
369b725ae77Skettenis
370b725ae77Skettenis jb_addr = read_register (A0_REGNUM);
371b725ae77Skettenis
372b725ae77Skettenis if (target_read_memory (jb_addr + MIPS64_LINUX_JB_PC * element_size,
373b725ae77Skettenis buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
374b725ae77Skettenis return 0;
375b725ae77Skettenis
376b725ae77Skettenis *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
377b725ae77Skettenis
378b725ae77Skettenis return 1;
379b725ae77Skettenis }
380b725ae77Skettenis
381b725ae77Skettenis /* Unpack an elf_gregset_t into GDB's register cache. */
382b725ae77Skettenis
383b725ae77Skettenis static void
mips64_supply_gregset(mips64_elf_gregset_t * gregsetp)384b725ae77Skettenis mips64_supply_gregset (mips64_elf_gregset_t *gregsetp)
385b725ae77Skettenis {
386b725ae77Skettenis int regi;
387b725ae77Skettenis mips64_elf_greg_t *regp = *gregsetp;
388b725ae77Skettenis char zerobuf[MAX_REGISTER_SIZE];
389b725ae77Skettenis
390b725ae77Skettenis memset (zerobuf, 0, MAX_REGISTER_SIZE);
391b725ae77Skettenis
392b725ae77Skettenis for (regi = MIPS64_EF_REG0; regi <= MIPS64_EF_REG31; regi++)
393*11efff7fSkettenis regcache_raw_supply (current_regcache, (regi - MIPS64_EF_REG0),
394*11efff7fSkettenis (char *)(regp + regi));
395b725ae77Skettenis
396*11efff7fSkettenis regcache_raw_supply (current_regcache, mips_regnum (current_gdbarch)->lo,
397b725ae77Skettenis (char *)(regp + MIPS64_EF_LO));
398*11efff7fSkettenis regcache_raw_supply (current_regcache, mips_regnum (current_gdbarch)->hi,
399b725ae77Skettenis (char *)(regp + MIPS64_EF_HI));
400b725ae77Skettenis
401*11efff7fSkettenis regcache_raw_supply (current_regcache, mips_regnum (current_gdbarch)->pc,
402b725ae77Skettenis (char *)(regp + MIPS64_EF_CP0_EPC));
403*11efff7fSkettenis regcache_raw_supply (current_regcache, mips_regnum (current_gdbarch)->badvaddr,
404b725ae77Skettenis (char *)(regp + MIPS64_EF_CP0_BADVADDR));
405*11efff7fSkettenis regcache_raw_supply (current_regcache, PS_REGNUM,
406*11efff7fSkettenis (char *)(regp + MIPS64_EF_CP0_STATUS));
407*11efff7fSkettenis regcache_raw_supply (current_regcache, mips_regnum (current_gdbarch)->cause,
408b725ae77Skettenis (char *)(regp + MIPS64_EF_CP0_CAUSE));
409b725ae77Skettenis
410b725ae77Skettenis /* Fill inaccessible registers with zero. */
411*11efff7fSkettenis regcache_raw_supply (current_regcache, UNUSED_REGNUM, zerobuf);
412b725ae77Skettenis for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
413*11efff7fSkettenis regcache_raw_supply (current_regcache, regi, zerobuf);
414b725ae77Skettenis }
415b725ae77Skettenis
416b725ae77Skettenis /* Pack our registers (or one register) into an elf_gregset_t. */
417b725ae77Skettenis
418b725ae77Skettenis static void
mips64_fill_gregset(mips64_elf_gregset_t * gregsetp,int regno)419b725ae77Skettenis mips64_fill_gregset (mips64_elf_gregset_t *gregsetp, int regno)
420b725ae77Skettenis {
421b725ae77Skettenis int regaddr, regi;
422b725ae77Skettenis mips64_elf_greg_t *regp = *gregsetp;
423b725ae77Skettenis void *src, *dst;
424b725ae77Skettenis
425b725ae77Skettenis if (regno == -1)
426b725ae77Skettenis {
427b725ae77Skettenis memset (regp, 0, sizeof (mips64_elf_gregset_t));
428b725ae77Skettenis for (regi = 0; regi < 32; regi++)
429b725ae77Skettenis mips64_fill_gregset (gregsetp, regi);
430b725ae77Skettenis mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->lo);
431b725ae77Skettenis mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->hi);
432b725ae77Skettenis mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->pc);
433b725ae77Skettenis mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->badvaddr);
434b725ae77Skettenis mips64_fill_gregset (gregsetp, PS_REGNUM);
435b725ae77Skettenis mips64_fill_gregset (gregsetp, mips_regnum (current_gdbarch)->cause);
436b725ae77Skettenis
437b725ae77Skettenis return;
438b725ae77Skettenis }
439b725ae77Skettenis
440b725ae77Skettenis if (regno < 32)
441b725ae77Skettenis {
442b725ae77Skettenis dst = regp + regno + MIPS64_EF_REG0;
443*11efff7fSkettenis regcache_raw_collect (current_regcache, regno, dst);
444b725ae77Skettenis return;
445b725ae77Skettenis }
446b725ae77Skettenis
447b725ae77Skettenis if (regno == mips_regnum (current_gdbarch)->lo)
448b725ae77Skettenis regaddr = MIPS64_EF_LO;
449b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->hi)
450b725ae77Skettenis regaddr = MIPS64_EF_HI;
451b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->pc)
452b725ae77Skettenis regaddr = MIPS64_EF_CP0_EPC;
453b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->badvaddr)
454b725ae77Skettenis regaddr = MIPS64_EF_CP0_BADVADDR;
455b725ae77Skettenis else if (regno == PS_REGNUM)
456b725ae77Skettenis regaddr = MIPS64_EF_CP0_STATUS;
457b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->cause)
458b725ae77Skettenis regaddr = MIPS64_EF_CP0_CAUSE;
459b725ae77Skettenis else
460b725ae77Skettenis regaddr = -1;
461b725ae77Skettenis
462b725ae77Skettenis if (regaddr != -1)
463b725ae77Skettenis {
464b725ae77Skettenis dst = regp + regaddr;
465*11efff7fSkettenis regcache_raw_collect (current_regcache, regno, dst);
466b725ae77Skettenis }
467b725ae77Skettenis }
468b725ae77Skettenis
469b725ae77Skettenis /* Likewise, unpack an elf_fpregset_t. */
470b725ae77Skettenis
471b725ae77Skettenis static void
mips64_supply_fpregset(mips64_elf_fpregset_t * fpregsetp)472b725ae77Skettenis mips64_supply_fpregset (mips64_elf_fpregset_t *fpregsetp)
473b725ae77Skettenis {
474b725ae77Skettenis int regi;
475b725ae77Skettenis char zerobuf[MAX_REGISTER_SIZE];
476b725ae77Skettenis
477b725ae77Skettenis memset (zerobuf, 0, MAX_REGISTER_SIZE);
478b725ae77Skettenis
479b725ae77Skettenis for (regi = 0; regi < 32; regi++)
480*11efff7fSkettenis regcache_raw_supply (current_regcache, FP0_REGNUM + regi,
481b725ae77Skettenis (char *)(*fpregsetp + regi));
482b725ae77Skettenis
483*11efff7fSkettenis regcache_raw_supply (current_regcache,
484*11efff7fSkettenis mips_regnum (current_gdbarch)->fp_control_status,
485b725ae77Skettenis (char *)(*fpregsetp + 32));
486b725ae77Skettenis
487b725ae77Skettenis /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */
488*11efff7fSkettenis regcache_raw_supply (current_regcache,
489*11efff7fSkettenis mips_regnum (current_gdbarch)->fp_implementation_revision,
490b725ae77Skettenis zerobuf);
491b725ae77Skettenis }
492b725ae77Skettenis
493b725ae77Skettenis /* Likewise, pack one or all floating point registers into an
494b725ae77Skettenis elf_fpregset_t. */
495b725ae77Skettenis
496b725ae77Skettenis static void
mips64_fill_fpregset(mips64_elf_fpregset_t * fpregsetp,int regno)497b725ae77Skettenis mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
498b725ae77Skettenis {
499b725ae77Skettenis char *from, *to;
500b725ae77Skettenis
501b725ae77Skettenis if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
502b725ae77Skettenis {
503b725ae77Skettenis from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
504b725ae77Skettenis to = (char *) (*fpregsetp + regno - FP0_REGNUM);
505*11efff7fSkettenis memcpy (to, from, register_size (current_gdbarch, regno - FP0_REGNUM));
506b725ae77Skettenis }
507b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
508b725ae77Skettenis {
509b725ae77Skettenis from = (char *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno)];
510b725ae77Skettenis to = (char *) (*fpregsetp + 32);
511*11efff7fSkettenis memcpy (to, from, register_size (current_gdbarch, regno));
512b725ae77Skettenis }
513b725ae77Skettenis else if (regno == -1)
514b725ae77Skettenis {
515b725ae77Skettenis int regi;
516b725ae77Skettenis
517b725ae77Skettenis for (regi = 0; regi < 32; regi++)
518b725ae77Skettenis mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
519b725ae77Skettenis mips64_fill_fpregset(fpregsetp,
520b725ae77Skettenis mips_regnum (current_gdbarch)->fp_control_status);
521b725ae77Skettenis }
522b725ae77Skettenis }
523b725ae77Skettenis
524b725ae77Skettenis
525b725ae77Skettenis /* Map gdb internal register number to ptrace ``address''.
526b725ae77Skettenis These ``addresses'' are normally defined in <asm/ptrace.h>. */
527b725ae77Skettenis
528b725ae77Skettenis static CORE_ADDR
mips64_linux_register_addr(int regno,CORE_ADDR blockend)529b725ae77Skettenis mips64_linux_register_addr (int regno, CORE_ADDR blockend)
530b725ae77Skettenis {
531b725ae77Skettenis int regaddr;
532b725ae77Skettenis
533b725ae77Skettenis if (regno < 0 || regno >= NUM_REGS)
534b725ae77Skettenis error ("Bogon register number %d.", regno);
535b725ae77Skettenis
536b725ae77Skettenis if (regno < 32)
537b725ae77Skettenis regaddr = regno;
538b725ae77Skettenis else if ((regno >= mips_regnum (current_gdbarch)->fp0)
539b725ae77Skettenis && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
540b725ae77Skettenis regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
541b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->pc)
542b725ae77Skettenis regaddr = MIPS64_PC;
543b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->cause)
544b725ae77Skettenis regaddr = MIPS64_CAUSE;
545b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->badvaddr)
546b725ae77Skettenis regaddr = MIPS64_BADVADDR;
547b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->lo)
548b725ae77Skettenis regaddr = MIPS64_MMLO;
549b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->hi)
550b725ae77Skettenis regaddr = MIPS64_MMHI;
551b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
552b725ae77Skettenis regaddr = MIPS64_FPC_CSR;
553b725ae77Skettenis else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
554b725ae77Skettenis regaddr = MIPS64_FPC_EIR;
555b725ae77Skettenis else
556b725ae77Skettenis error ("Unknowable register number %d.", regno);
557b725ae77Skettenis
558b725ae77Skettenis return regaddr;
559b725ae77Skettenis }
560b725ae77Skettenis
561b725ae77Skettenis /* Use a local version of this function to get the correct types for
562b725ae77Skettenis regsets, until multi-arch core support is ready. */
563b725ae77Skettenis
564b725ae77Skettenis static void
fetch_core_registers(char * core_reg_sect,unsigned core_reg_size,int which,CORE_ADDR reg_addr)565b725ae77Skettenis fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
566b725ae77Skettenis int which, CORE_ADDR reg_addr)
567b725ae77Skettenis {
568b725ae77Skettenis elf_gregset_t gregset;
569b725ae77Skettenis elf_fpregset_t fpregset;
570b725ae77Skettenis mips64_elf_gregset_t gregset64;
571b725ae77Skettenis mips64_elf_fpregset_t fpregset64;
572b725ae77Skettenis
573b725ae77Skettenis if (which == 0)
574b725ae77Skettenis {
575b725ae77Skettenis if (core_reg_size == sizeof (gregset))
576b725ae77Skettenis {
577b725ae77Skettenis memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
578b725ae77Skettenis supply_gregset (&gregset);
579b725ae77Skettenis }
580b725ae77Skettenis else if (core_reg_size == sizeof (gregset64))
581b725ae77Skettenis {
582b725ae77Skettenis memcpy ((char *) &gregset64, core_reg_sect, sizeof (gregset64));
583b725ae77Skettenis mips64_supply_gregset (&gregset64);
584b725ae77Skettenis }
585b725ae77Skettenis else
586b725ae77Skettenis {
587b725ae77Skettenis warning ("wrong size gregset struct in core file");
588b725ae77Skettenis }
589b725ae77Skettenis }
590b725ae77Skettenis else if (which == 2)
591b725ae77Skettenis {
592b725ae77Skettenis if (core_reg_size == sizeof (fpregset))
593b725ae77Skettenis {
594b725ae77Skettenis memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
595b725ae77Skettenis supply_fpregset (&fpregset);
596b725ae77Skettenis }
597b725ae77Skettenis else if (core_reg_size == sizeof (fpregset64))
598b725ae77Skettenis {
599b725ae77Skettenis memcpy ((char *) &fpregset64, core_reg_sect, sizeof (fpregset64));
600b725ae77Skettenis mips64_supply_fpregset (&fpregset64);
601b725ae77Skettenis }
602b725ae77Skettenis else
603b725ae77Skettenis {
604b725ae77Skettenis warning ("wrong size fpregset struct in core file");
605b725ae77Skettenis }
606b725ae77Skettenis }
607b725ae77Skettenis }
608b725ae77Skettenis
609b725ae77Skettenis /* Register that we are able to handle ELF file formats using standard
610b725ae77Skettenis procfs "regset" structures. */
611b725ae77Skettenis
612b725ae77Skettenis static struct core_fns regset_core_fns =
613b725ae77Skettenis {
614b725ae77Skettenis bfd_target_elf_flavour, /* core_flavour */
615b725ae77Skettenis default_check_format, /* check_format */
616b725ae77Skettenis default_core_sniffer, /* core_sniffer */
617b725ae77Skettenis fetch_core_registers, /* core_read_registers */
618b725ae77Skettenis NULL /* next */
619b725ae77Skettenis };
620b725ae77Skettenis
621b725ae77Skettenis /* Fetch (and possibly build) an appropriate link_map_offsets
622b725ae77Skettenis structure for native GNU/Linux MIPS targets using the struct offsets
623b725ae77Skettenis defined in link.h (but without actual reference to that file).
624b725ae77Skettenis
625b725ae77Skettenis This makes it possible to access GNU/Linux MIPS shared libraries from a
626b725ae77Skettenis GDB that was built on a different host platform (for cross debugging). */
627b725ae77Skettenis
628b725ae77Skettenis static struct link_map_offsets *
mips64_linux_svr4_fetch_link_map_offsets(void)629b725ae77Skettenis mips64_linux_svr4_fetch_link_map_offsets (void)
630b725ae77Skettenis {
631b725ae77Skettenis static struct link_map_offsets lmo;
632b725ae77Skettenis static struct link_map_offsets *lmp = NULL;
633b725ae77Skettenis
634b725ae77Skettenis if (lmp == NULL)
635b725ae77Skettenis {
636b725ae77Skettenis lmp = &lmo;
637b725ae77Skettenis
638b725ae77Skettenis lmo.r_debug_size = 16; /* The actual size is 40 bytes, but
639b725ae77Skettenis this is all we need. */
640b725ae77Skettenis lmo.r_map_offset = 8;
641b725ae77Skettenis lmo.r_map_size = 8;
642b725ae77Skettenis
643b725ae77Skettenis lmo.link_map_size = 40;
644b725ae77Skettenis
645b725ae77Skettenis lmo.l_addr_offset = 0;
646b725ae77Skettenis lmo.l_addr_size = 8;
647b725ae77Skettenis
648b725ae77Skettenis lmo.l_name_offset = 8;
649b725ae77Skettenis lmo.l_name_size = 8;
650b725ae77Skettenis
651b725ae77Skettenis lmo.l_next_offset = 24;
652b725ae77Skettenis lmo.l_next_size = 8;
653b725ae77Skettenis
654b725ae77Skettenis lmo.l_prev_offset = 32;
655b725ae77Skettenis lmo.l_prev_size = 8;
656b725ae77Skettenis }
657b725ae77Skettenis
658b725ae77Skettenis return lmp;
659b725ae77Skettenis }
660b725ae77Skettenis
661b725ae77Skettenis /* Handle for obtaining pointer to the current register_addr() function
662b725ae77Skettenis for a given architecture. */
663b725ae77Skettenis static struct gdbarch_data *register_addr_data;
664b725ae77Skettenis
665b725ae77Skettenis CORE_ADDR
register_addr(int regno,CORE_ADDR blockend)666b725ae77Skettenis register_addr (int regno, CORE_ADDR blockend)
667b725ae77Skettenis {
668b725ae77Skettenis CORE_ADDR (*register_addr_ptr) (int, CORE_ADDR) =
669b725ae77Skettenis gdbarch_data (current_gdbarch, register_addr_data);
670b725ae77Skettenis
671b725ae77Skettenis gdb_assert (register_addr_ptr != 0);
672b725ae77Skettenis
673b725ae77Skettenis return register_addr_ptr (regno, blockend);
674b725ae77Skettenis }
675b725ae77Skettenis
676b725ae77Skettenis static void
set_mips_linux_register_addr(struct gdbarch * gdbarch,CORE_ADDR (* register_addr_ptr)(int,CORE_ADDR))677b725ae77Skettenis set_mips_linux_register_addr (struct gdbarch *gdbarch,
678b725ae77Skettenis CORE_ADDR (*register_addr_ptr) (int, CORE_ADDR))
679b725ae77Skettenis {
680*11efff7fSkettenis deprecated_set_gdbarch_data (gdbarch, register_addr_data, register_addr_ptr);
681b725ae77Skettenis }
682b725ae77Skettenis
683b725ae77Skettenis static void *
init_register_addr_data(struct gdbarch * gdbarch)684b725ae77Skettenis init_register_addr_data (struct gdbarch *gdbarch)
685b725ae77Skettenis {
686b725ae77Skettenis return 0;
687b725ae77Skettenis }
688b725ae77Skettenis
689b725ae77Skettenis /* Check the code at PC for a dynamic linker lazy resolution stub. Because
690b725ae77Skettenis they aren't in the .plt section, we pattern-match on the code generated
691b725ae77Skettenis by GNU ld. They look like this:
692b725ae77Skettenis
693b725ae77Skettenis lw t9,0x8010(gp)
694b725ae77Skettenis addu t7,ra
695b725ae77Skettenis jalr t9,ra
696b725ae77Skettenis addiu t8,zero,INDEX
697b725ae77Skettenis
698b725ae77Skettenis (with the appropriate doubleword instructions for N64). Also return the
699b725ae77Skettenis dynamic symbol index used in the last instruction. */
700b725ae77Skettenis
701b725ae77Skettenis static int
mips_linux_in_dynsym_stub(CORE_ADDR pc,char * name)702b725ae77Skettenis mips_linux_in_dynsym_stub (CORE_ADDR pc, char *name)
703b725ae77Skettenis {
704b725ae77Skettenis unsigned char buf[28], *p;
705b725ae77Skettenis ULONGEST insn, insn1;
706b725ae77Skettenis int n64 = (mips_abi (current_gdbarch) == MIPS_ABI_N64);
707b725ae77Skettenis
708b725ae77Skettenis read_memory (pc - 12, buf, 28);
709b725ae77Skettenis
710b725ae77Skettenis if (n64)
711b725ae77Skettenis {
712b725ae77Skettenis /* ld t9,0x8010(gp) */
713b725ae77Skettenis insn1 = 0xdf998010;
714b725ae77Skettenis }
715b725ae77Skettenis else
716b725ae77Skettenis {
717b725ae77Skettenis /* lw t9,0x8010(gp) */
718b725ae77Skettenis insn1 = 0x8f998010;
719b725ae77Skettenis }
720b725ae77Skettenis
721b725ae77Skettenis p = buf + 12;
722b725ae77Skettenis while (p >= buf)
723b725ae77Skettenis {
724b725ae77Skettenis insn = extract_unsigned_integer (p, 4);
725b725ae77Skettenis if (insn == insn1)
726b725ae77Skettenis break;
727b725ae77Skettenis p -= 4;
728b725ae77Skettenis }
729b725ae77Skettenis if (p < buf)
730b725ae77Skettenis return 0;
731b725ae77Skettenis
732b725ae77Skettenis insn = extract_unsigned_integer (p + 4, 4);
733b725ae77Skettenis if (n64)
734b725ae77Skettenis {
735b725ae77Skettenis /* daddu t7,ra */
736b725ae77Skettenis if (insn != 0x03e0782d)
737b725ae77Skettenis return 0;
738b725ae77Skettenis }
739b725ae77Skettenis else
740b725ae77Skettenis {
741b725ae77Skettenis /* addu t7,ra */
742b725ae77Skettenis if (insn != 0x03e07821)
743b725ae77Skettenis return 0;
744b725ae77Skettenis }
745b725ae77Skettenis
746b725ae77Skettenis insn = extract_unsigned_integer (p + 8, 4);
747b725ae77Skettenis /* jalr t9,ra */
748b725ae77Skettenis if (insn != 0x0320f809)
749b725ae77Skettenis return 0;
750b725ae77Skettenis
751b725ae77Skettenis insn = extract_unsigned_integer (p + 12, 4);
752b725ae77Skettenis if (n64)
753b725ae77Skettenis {
754b725ae77Skettenis /* daddiu t8,zero,0 */
755b725ae77Skettenis if ((insn & 0xffff0000) != 0x64180000)
756b725ae77Skettenis return 0;
757b725ae77Skettenis }
758b725ae77Skettenis else
759b725ae77Skettenis {
760b725ae77Skettenis /* addiu t8,zero,0 */
761b725ae77Skettenis if ((insn & 0xffff0000) != 0x24180000)
762b725ae77Skettenis return 0;
763b725ae77Skettenis }
764b725ae77Skettenis
765b725ae77Skettenis return (insn & 0xffff);
766b725ae77Skettenis }
767b725ae77Skettenis
768b725ae77Skettenis /* Return non-zero iff PC belongs to the dynamic linker resolution code
769b725ae77Skettenis or to a stub. */
770b725ae77Skettenis
771b725ae77Skettenis int
mips_linux_in_dynsym_resolve_code(CORE_ADDR pc)772b725ae77Skettenis mips_linux_in_dynsym_resolve_code (CORE_ADDR pc)
773b725ae77Skettenis {
774b725ae77Skettenis /* Check whether PC is in the dynamic linker. This also checks whether
775b725ae77Skettenis it is in the .plt section, which MIPS does not use. */
776b725ae77Skettenis if (in_solib_dynsym_resolve_code (pc))
777b725ae77Skettenis return 1;
778b725ae77Skettenis
779b725ae77Skettenis /* Pattern match for the stub. It would be nice if there were a more
780b725ae77Skettenis efficient way to avoid this check. */
781b725ae77Skettenis if (mips_linux_in_dynsym_stub (pc, NULL))
782b725ae77Skettenis return 1;
783b725ae77Skettenis
784b725ae77Skettenis return 0;
785b725ae77Skettenis }
786b725ae77Skettenis
787b725ae77Skettenis /* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c,
788b725ae77Skettenis and glibc_skip_solib_resolver in glibc-tdep.c. The normal glibc
789b725ae77Skettenis implementation of this triggers at "fixup" from the same objfile as
790b725ae77Skettenis "_dl_runtime_resolve"; MIPS GNU/Linux can trigger at
791b725ae77Skettenis "__dl_runtime_resolve" directly. An unresolved PLT entry will
792b725ae77Skettenis point to _dl_runtime_resolve, which will first call
793b725ae77Skettenis __dl_runtime_resolve, and then pass control to the resolved
794b725ae77Skettenis function. */
795b725ae77Skettenis
796b725ae77Skettenis static CORE_ADDR
mips_linux_skip_resolver(struct gdbarch * gdbarch,CORE_ADDR pc)797b725ae77Skettenis mips_linux_skip_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
798b725ae77Skettenis {
799b725ae77Skettenis struct minimal_symbol *resolver;
800b725ae77Skettenis
801b725ae77Skettenis resolver = lookup_minimal_symbol ("__dl_runtime_resolve", NULL, NULL);
802b725ae77Skettenis
803b725ae77Skettenis if (resolver && SYMBOL_VALUE_ADDRESS (resolver) == pc)
804b725ae77Skettenis return frame_pc_unwind (get_current_frame ());
805b725ae77Skettenis
806b725ae77Skettenis return 0;
807b725ae77Skettenis }
808b725ae77Skettenis
809*11efff7fSkettenis /* Signal trampoline support. There are four supported layouts for a
810*11efff7fSkettenis signal frame: o32 sigframe, o32 rt_sigframe, n32 rt_sigframe, and
811*11efff7fSkettenis n64 rt_sigframe. We handle them all independently; not the most
812*11efff7fSkettenis efficient way, but simplest. First, declare all the unwinders. */
813*11efff7fSkettenis
814*11efff7fSkettenis static void mips_linux_o32_sigframe_init (const struct tramp_frame *self,
815*11efff7fSkettenis struct frame_info *next_frame,
816*11efff7fSkettenis struct trad_frame_cache *this_cache,
817*11efff7fSkettenis CORE_ADDR func);
818*11efff7fSkettenis
819*11efff7fSkettenis static void mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
820*11efff7fSkettenis struct frame_info *next_frame,
821*11efff7fSkettenis struct trad_frame_cache *this_cache,
822*11efff7fSkettenis CORE_ADDR func);
823*11efff7fSkettenis
824*11efff7fSkettenis #define MIPS_NR_LINUX 4000
825*11efff7fSkettenis #define MIPS_NR_N64_LINUX 5000
826*11efff7fSkettenis #define MIPS_NR_N32_LINUX 6000
827*11efff7fSkettenis
828*11efff7fSkettenis #define MIPS_NR_sigreturn MIPS_NR_LINUX + 119
829*11efff7fSkettenis #define MIPS_NR_rt_sigreturn MIPS_NR_LINUX + 193
830*11efff7fSkettenis #define MIPS_NR_N64_rt_sigreturn MIPS_NR_N64_LINUX + 211
831*11efff7fSkettenis #define MIPS_NR_N32_rt_sigreturn MIPS_NR_N32_LINUX + 211
832*11efff7fSkettenis
833*11efff7fSkettenis #define MIPS_INST_LI_V0_SIGRETURN 0x24020000 + MIPS_NR_sigreturn
834*11efff7fSkettenis #define MIPS_INST_LI_V0_RT_SIGRETURN 0x24020000 + MIPS_NR_rt_sigreturn
835*11efff7fSkettenis #define MIPS_INST_LI_V0_N64_RT_SIGRETURN 0x24020000 + MIPS_NR_N64_rt_sigreturn
836*11efff7fSkettenis #define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn
837*11efff7fSkettenis #define MIPS_INST_SYSCALL 0x0000000c
838*11efff7fSkettenis
839*11efff7fSkettenis static const struct tramp_frame mips_linux_o32_sigframe = {
840*11efff7fSkettenis SIGTRAMP_FRAME,
841*11efff7fSkettenis 4,
842*11efff7fSkettenis {
843*11efff7fSkettenis { MIPS_INST_LI_V0_SIGRETURN, -1 },
844*11efff7fSkettenis { MIPS_INST_SYSCALL, -1 },
845*11efff7fSkettenis { TRAMP_SENTINEL_INSN, -1 }
846*11efff7fSkettenis },
847*11efff7fSkettenis mips_linux_o32_sigframe_init
848*11efff7fSkettenis };
849*11efff7fSkettenis
850*11efff7fSkettenis static const struct tramp_frame mips_linux_o32_rt_sigframe = {
851*11efff7fSkettenis SIGTRAMP_FRAME,
852*11efff7fSkettenis 4,
853*11efff7fSkettenis {
854*11efff7fSkettenis { MIPS_INST_LI_V0_RT_SIGRETURN, -1 },
855*11efff7fSkettenis { MIPS_INST_SYSCALL, -1 },
856*11efff7fSkettenis { TRAMP_SENTINEL_INSN, -1 } },
857*11efff7fSkettenis mips_linux_o32_sigframe_init
858*11efff7fSkettenis };
859*11efff7fSkettenis
860*11efff7fSkettenis static const struct tramp_frame mips_linux_n32_rt_sigframe = {
861*11efff7fSkettenis SIGTRAMP_FRAME,
862*11efff7fSkettenis 4,
863*11efff7fSkettenis {
864*11efff7fSkettenis { MIPS_INST_LI_V0_N32_RT_SIGRETURN, -1 },
865*11efff7fSkettenis { MIPS_INST_SYSCALL, -1 },
866*11efff7fSkettenis { TRAMP_SENTINEL_INSN, -1 }
867*11efff7fSkettenis },
868*11efff7fSkettenis mips_linux_n32n64_sigframe_init
869*11efff7fSkettenis };
870*11efff7fSkettenis
871*11efff7fSkettenis static const struct tramp_frame mips_linux_n64_rt_sigframe = {
872*11efff7fSkettenis SIGTRAMP_FRAME,
873*11efff7fSkettenis 4,
874*11efff7fSkettenis { MIPS_INST_LI_V0_N64_RT_SIGRETURN, MIPS_INST_SYSCALL, TRAMP_SENTINEL_INSN },
875*11efff7fSkettenis mips_linux_n32n64_sigframe_init
876*11efff7fSkettenis };
877*11efff7fSkettenis
878*11efff7fSkettenis /* *INDENT-OFF* */
879*11efff7fSkettenis /* The unwinder for o32 signal frames. The legacy structures look
880*11efff7fSkettenis like this:
881*11efff7fSkettenis
882*11efff7fSkettenis struct sigframe {
883*11efff7fSkettenis u32 sf_ass[4]; [argument save space for o32]
884*11efff7fSkettenis u32 sf_code[2]; [signal trampoline]
885*11efff7fSkettenis struct sigcontext sf_sc;
886*11efff7fSkettenis sigset_t sf_mask;
887*11efff7fSkettenis };
888*11efff7fSkettenis
889*11efff7fSkettenis struct sigcontext {
890*11efff7fSkettenis unsigned int sc_regmask; [Unused]
891*11efff7fSkettenis unsigned int sc_status;
892*11efff7fSkettenis unsigned long long sc_pc;
893*11efff7fSkettenis unsigned long long sc_regs[32];
894*11efff7fSkettenis unsigned long long sc_fpregs[32];
895*11efff7fSkettenis unsigned int sc_ownedfp;
896*11efff7fSkettenis unsigned int sc_fpc_csr;
897*11efff7fSkettenis unsigned int sc_fpc_eir; [Unused]
898*11efff7fSkettenis unsigned int sc_used_math;
899*11efff7fSkettenis unsigned int sc_ssflags; [Unused]
900*11efff7fSkettenis [Alignment hole of four bytes]
901*11efff7fSkettenis unsigned long long sc_mdhi;
902*11efff7fSkettenis unsigned long long sc_mdlo;
903*11efff7fSkettenis
904*11efff7fSkettenis unsigned int sc_cause; [Unused]
905*11efff7fSkettenis unsigned int sc_badvaddr; [Unused]
906*11efff7fSkettenis
907*11efff7fSkettenis unsigned long sc_sigset[4]; [kernel's sigset_t]
908*11efff7fSkettenis };
909*11efff7fSkettenis
910*11efff7fSkettenis The RT signal frames look like this:
911*11efff7fSkettenis
912*11efff7fSkettenis struct rt_sigframe {
913*11efff7fSkettenis u32 rs_ass[4]; [argument save space for o32]
914*11efff7fSkettenis u32 rs_code[2] [signal trampoline]
915*11efff7fSkettenis struct siginfo rs_info;
916*11efff7fSkettenis struct ucontext rs_uc;
917*11efff7fSkettenis };
918*11efff7fSkettenis
919*11efff7fSkettenis struct ucontext {
920*11efff7fSkettenis unsigned long uc_flags;
921*11efff7fSkettenis struct ucontext *uc_link;
922*11efff7fSkettenis stack_t uc_stack;
923*11efff7fSkettenis [Alignment hole of four bytes]
924*11efff7fSkettenis struct sigcontext uc_mcontext;
925*11efff7fSkettenis sigset_t uc_sigmask;
926*11efff7fSkettenis }; */
927*11efff7fSkettenis /* *INDENT-ON* */
928*11efff7fSkettenis
929*11efff7fSkettenis #define SIGFRAME_CODE_OFFSET (4 * 4)
930*11efff7fSkettenis #define SIGFRAME_SIGCONTEXT_OFFSET (6 * 4)
931*11efff7fSkettenis
932*11efff7fSkettenis #define RTSIGFRAME_SIGINFO_SIZE 128
933*11efff7fSkettenis #define STACK_T_SIZE (3 * 4)
934*11efff7fSkettenis #define UCONTEXT_SIGCONTEXT_OFFSET (2 * 4 + STACK_T_SIZE + 4)
935*11efff7fSkettenis #define RTSIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \
936*11efff7fSkettenis + RTSIGFRAME_SIGINFO_SIZE \
937*11efff7fSkettenis + UCONTEXT_SIGCONTEXT_OFFSET)
938*11efff7fSkettenis
939*11efff7fSkettenis #define SIGCONTEXT_PC (1 * 8)
940*11efff7fSkettenis #define SIGCONTEXT_REGS (2 * 8)
941*11efff7fSkettenis #define SIGCONTEXT_FPREGS (34 * 8)
942*11efff7fSkettenis #define SIGCONTEXT_FPCSR (66 * 8 + 4)
943*11efff7fSkettenis #define SIGCONTEXT_HI (69 * 8)
944*11efff7fSkettenis #define SIGCONTEXT_LO (70 * 8)
945*11efff7fSkettenis #define SIGCONTEXT_CAUSE (71 * 8 + 0)
946*11efff7fSkettenis #define SIGCONTEXT_BADVADDR (71 * 8 + 4)
947*11efff7fSkettenis
948*11efff7fSkettenis #define SIGCONTEXT_REG_SIZE 8
949*11efff7fSkettenis
950*11efff7fSkettenis static void
mips_linux_o32_sigframe_init(const struct tramp_frame * self,struct frame_info * next_frame,struct trad_frame_cache * this_cache,CORE_ADDR func)951*11efff7fSkettenis mips_linux_o32_sigframe_init (const struct tramp_frame *self,
952*11efff7fSkettenis struct frame_info *next_frame,
953*11efff7fSkettenis struct trad_frame_cache *this_cache,
954*11efff7fSkettenis CORE_ADDR func)
955*11efff7fSkettenis {
956*11efff7fSkettenis int ireg, reg_position;
957*11efff7fSkettenis CORE_ADDR sigcontext_base = func - SIGFRAME_CODE_OFFSET;
958*11efff7fSkettenis const struct mips_regnum *regs = mips_regnum (current_gdbarch);
959*11efff7fSkettenis
960*11efff7fSkettenis if (self == &mips_linux_o32_sigframe)
961*11efff7fSkettenis sigcontext_base += SIGFRAME_SIGCONTEXT_OFFSET;
962*11efff7fSkettenis else
963*11efff7fSkettenis sigcontext_base += RTSIGFRAME_SIGCONTEXT_OFFSET;
964*11efff7fSkettenis
965*11efff7fSkettenis /* I'm not proud of this hack. Eventually we will have the infrastructure
966*11efff7fSkettenis to indicate the size of saved registers on a per-frame basis, but
967*11efff7fSkettenis right now we don't; the kernel saves eight bytes but we only want
968*11efff7fSkettenis four. */
969*11efff7fSkettenis if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
970*11efff7fSkettenis sigcontext_base += 4;
971*11efff7fSkettenis
972*11efff7fSkettenis #if 0
973*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, ORIG_ZERO_REGNUM + NUM_REGS,
974*11efff7fSkettenis sigcontext_base + SIGCONTEXT_REGS);
975*11efff7fSkettenis #endif
976*11efff7fSkettenis
977*11efff7fSkettenis for (ireg = 1; ireg < 32; ireg++)
978*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, ireg + ZERO_REGNUM + NUM_REGS,
979*11efff7fSkettenis sigcontext_base + SIGCONTEXT_REGS
980*11efff7fSkettenis + ireg * SIGCONTEXT_REG_SIZE);
981*11efff7fSkettenis
982*11efff7fSkettenis for (ireg = 0; ireg < 32; ireg++)
983*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, ireg + regs->fp0 + NUM_REGS,
984*11efff7fSkettenis sigcontext_base + SIGCONTEXT_FPREGS
985*11efff7fSkettenis + ireg * SIGCONTEXT_REG_SIZE);
986*11efff7fSkettenis
987*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->pc + NUM_REGS,
988*11efff7fSkettenis sigcontext_base + SIGCONTEXT_PC);
989*11efff7fSkettenis
990*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->fp_control_status + NUM_REGS,
991*11efff7fSkettenis sigcontext_base + SIGCONTEXT_FPCSR);
992*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->hi + NUM_REGS,
993*11efff7fSkettenis sigcontext_base + SIGCONTEXT_HI);
994*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->lo + NUM_REGS,
995*11efff7fSkettenis sigcontext_base + SIGCONTEXT_LO);
996*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->cause + NUM_REGS,
997*11efff7fSkettenis sigcontext_base + SIGCONTEXT_CAUSE);
998*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->badvaddr + NUM_REGS,
999*11efff7fSkettenis sigcontext_base + SIGCONTEXT_BADVADDR);
1000*11efff7fSkettenis
1001*11efff7fSkettenis /* Choice of the bottom of the sigframe is somewhat arbitrary. */
1002*11efff7fSkettenis trad_frame_set_id (this_cache,
1003*11efff7fSkettenis frame_id_build (func - SIGFRAME_CODE_OFFSET, func));
1004*11efff7fSkettenis }
1005*11efff7fSkettenis
1006*11efff7fSkettenis /* *INDENT-OFF* */
1007*11efff7fSkettenis /* For N32/N64 things look different. There is no non-rt signal frame.
1008*11efff7fSkettenis
1009*11efff7fSkettenis struct rt_sigframe_n32 {
1010*11efff7fSkettenis u32 rs_ass[4]; [ argument save space for o32 ]
1011*11efff7fSkettenis u32 rs_code[2]; [ signal trampoline ]
1012*11efff7fSkettenis struct siginfo rs_info;
1013*11efff7fSkettenis struct ucontextn32 rs_uc;
1014*11efff7fSkettenis };
1015*11efff7fSkettenis
1016*11efff7fSkettenis struct ucontextn32 {
1017*11efff7fSkettenis u32 uc_flags;
1018*11efff7fSkettenis s32 uc_link;
1019*11efff7fSkettenis stack32_t uc_stack;
1020*11efff7fSkettenis struct sigcontext uc_mcontext;
1021*11efff7fSkettenis sigset_t uc_sigmask; [ mask last for extensibility ]
1022*11efff7fSkettenis };
1023*11efff7fSkettenis
1024*11efff7fSkettenis struct rt_sigframe_n32 {
1025*11efff7fSkettenis u32 rs_ass[4]; [ argument save space for o32 ]
1026*11efff7fSkettenis u32 rs_code[2]; [ signal trampoline ]
1027*11efff7fSkettenis struct siginfo rs_info;
1028*11efff7fSkettenis struct ucontext rs_uc;
1029*11efff7fSkettenis };
1030*11efff7fSkettenis
1031*11efff7fSkettenis struct ucontext {
1032*11efff7fSkettenis unsigned long uc_flags;
1033*11efff7fSkettenis struct ucontext *uc_link;
1034*11efff7fSkettenis stack_t uc_stack;
1035*11efff7fSkettenis struct sigcontext uc_mcontext;
1036*11efff7fSkettenis sigset_t uc_sigmask; [ mask last for extensibility ]
1037*11efff7fSkettenis };
1038*11efff7fSkettenis
1039*11efff7fSkettenis And the sigcontext is different (this is for both n32 and n64):
1040*11efff7fSkettenis
1041*11efff7fSkettenis struct sigcontext {
1042*11efff7fSkettenis unsigned long long sc_regs[32];
1043*11efff7fSkettenis unsigned long long sc_fpregs[32];
1044*11efff7fSkettenis unsigned long long sc_mdhi;
1045*11efff7fSkettenis unsigned long long sc_mdlo;
1046*11efff7fSkettenis unsigned long long sc_pc;
1047*11efff7fSkettenis unsigned int sc_status;
1048*11efff7fSkettenis unsigned int sc_fpc_csr;
1049*11efff7fSkettenis unsigned int sc_fpc_eir;
1050*11efff7fSkettenis unsigned int sc_used_math;
1051*11efff7fSkettenis unsigned int sc_cause;
1052*11efff7fSkettenis unsigned int sc_badvaddr;
1053*11efff7fSkettenis }; */
1054*11efff7fSkettenis /* *INDENT-ON* */
1055*11efff7fSkettenis
1056*11efff7fSkettenis #define N32_STACK_T_SIZE STACK_T_SIZE
1057*11efff7fSkettenis #define N64_STACK_T_SIZE (2 * 8 + 4)
1058*11efff7fSkettenis #define N32_UCONTEXT_SIGCONTEXT_OFFSET (2 * 4 + N32_STACK_T_SIZE + 4)
1059*11efff7fSkettenis #define N64_UCONTEXT_SIGCONTEXT_OFFSET (2 * 8 + N64_STACK_T_SIZE + 4)
1060*11efff7fSkettenis #define N32_SIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \
1061*11efff7fSkettenis + RTSIGFRAME_SIGINFO_SIZE \
1062*11efff7fSkettenis + N32_UCONTEXT_SIGCONTEXT_OFFSET)
1063*11efff7fSkettenis #define N64_SIGFRAME_SIGCONTEXT_OFFSET (SIGFRAME_SIGCONTEXT_OFFSET \
1064*11efff7fSkettenis + RTSIGFRAME_SIGINFO_SIZE \
1065*11efff7fSkettenis + N64_UCONTEXT_SIGCONTEXT_OFFSET)
1066*11efff7fSkettenis
1067*11efff7fSkettenis #define N64_SIGCONTEXT_REGS (0 * 8)
1068*11efff7fSkettenis #define N64_SIGCONTEXT_FPREGS (32 * 8)
1069*11efff7fSkettenis #define N64_SIGCONTEXT_HI (64 * 8)
1070*11efff7fSkettenis #define N64_SIGCONTEXT_LO (65 * 8)
1071*11efff7fSkettenis #define N64_SIGCONTEXT_PC (66 * 8)
1072*11efff7fSkettenis #define N64_SIGCONTEXT_FPCSR (67 * 8 + 1 * 4)
1073*11efff7fSkettenis #define N64_SIGCONTEXT_FIR (67 * 8 + 2 * 4)
1074*11efff7fSkettenis #define N64_SIGCONTEXT_CAUSE (67 * 8 + 4 * 4)
1075*11efff7fSkettenis #define N64_SIGCONTEXT_BADVADDR (67 * 8 + 5 * 4)
1076*11efff7fSkettenis
1077*11efff7fSkettenis #define N64_SIGCONTEXT_REG_SIZE 8
1078*11efff7fSkettenis
1079*11efff7fSkettenis static void
mips_linux_n32n64_sigframe_init(const struct tramp_frame * self,struct frame_info * next_frame,struct trad_frame_cache * this_cache,CORE_ADDR func)1080*11efff7fSkettenis mips_linux_n32n64_sigframe_init (const struct tramp_frame *self,
1081*11efff7fSkettenis struct frame_info *next_frame,
1082*11efff7fSkettenis struct trad_frame_cache *this_cache,
1083*11efff7fSkettenis CORE_ADDR func)
1084*11efff7fSkettenis {
1085*11efff7fSkettenis int ireg, reg_position;
1086*11efff7fSkettenis CORE_ADDR sigcontext_base = func - SIGFRAME_CODE_OFFSET;
1087*11efff7fSkettenis const struct mips_regnum *regs = mips_regnum (current_gdbarch);
1088*11efff7fSkettenis
1089*11efff7fSkettenis if (self == &mips_linux_n32_rt_sigframe)
1090*11efff7fSkettenis sigcontext_base += N32_SIGFRAME_SIGCONTEXT_OFFSET;
1091*11efff7fSkettenis else
1092*11efff7fSkettenis sigcontext_base += N64_SIGFRAME_SIGCONTEXT_OFFSET;
1093*11efff7fSkettenis
1094*11efff7fSkettenis #if 0
1095*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, ORIG_ZERO_REGNUM + NUM_REGS,
1096*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_REGS);
1097*11efff7fSkettenis #endif
1098*11efff7fSkettenis
1099*11efff7fSkettenis for (ireg = 1; ireg < 32; ireg++)
1100*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, ireg + ZERO_REGNUM + NUM_REGS,
1101*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_REGS
1102*11efff7fSkettenis + ireg * N64_SIGCONTEXT_REG_SIZE);
1103*11efff7fSkettenis
1104*11efff7fSkettenis for (ireg = 0; ireg < 32; ireg++)
1105*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, ireg + regs->fp0 + NUM_REGS,
1106*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_FPREGS
1107*11efff7fSkettenis + ireg * N64_SIGCONTEXT_REG_SIZE);
1108*11efff7fSkettenis
1109*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->pc + NUM_REGS,
1110*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_PC);
1111*11efff7fSkettenis
1112*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->fp_control_status + NUM_REGS,
1113*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_FPCSR);
1114*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->hi + NUM_REGS,
1115*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_HI);
1116*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->lo + NUM_REGS,
1117*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_LO);
1118*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->cause + NUM_REGS,
1119*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_CAUSE);
1120*11efff7fSkettenis trad_frame_set_reg_addr (this_cache, regs->badvaddr + NUM_REGS,
1121*11efff7fSkettenis sigcontext_base + N64_SIGCONTEXT_BADVADDR);
1122*11efff7fSkettenis
1123*11efff7fSkettenis /* Choice of the bottom of the sigframe is somewhat arbitrary. */
1124*11efff7fSkettenis trad_frame_set_id (this_cache,
1125*11efff7fSkettenis frame_id_build (func - SIGFRAME_CODE_OFFSET, func));
1126*11efff7fSkettenis }
1127*11efff7fSkettenis
1128*11efff7fSkettenis /* Initialize one of the GNU/Linux OS ABIs. */
1129*11efff7fSkettenis
1130b725ae77Skettenis static void
mips_linux_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1131b725ae77Skettenis mips_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1132b725ae77Skettenis {
1133b725ae77Skettenis struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1134b725ae77Skettenis enum mips_abi abi = mips_abi (gdbarch);
1135b725ae77Skettenis
1136b725ae77Skettenis switch (abi)
1137b725ae77Skettenis {
1138b725ae77Skettenis case MIPS_ABI_O32:
1139b725ae77Skettenis set_gdbarch_get_longjmp_target (gdbarch,
1140b725ae77Skettenis mips_linux_get_longjmp_target);
1141b725ae77Skettenis set_solib_svr4_fetch_link_map_offsets
1142b725ae77Skettenis (gdbarch, mips_linux_svr4_fetch_link_map_offsets);
1143b725ae77Skettenis set_mips_linux_register_addr (gdbarch, mips_linux_register_addr);
1144*11efff7fSkettenis tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe);
1145*11efff7fSkettenis tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe);
1146b725ae77Skettenis break;
1147b725ae77Skettenis case MIPS_ABI_N32:
1148b725ae77Skettenis set_gdbarch_get_longjmp_target (gdbarch,
1149b725ae77Skettenis mips_linux_get_longjmp_target);
1150b725ae77Skettenis set_solib_svr4_fetch_link_map_offsets
1151b725ae77Skettenis (gdbarch, mips_linux_svr4_fetch_link_map_offsets);
1152b725ae77Skettenis set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
1153*11efff7fSkettenis tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
1154b725ae77Skettenis break;
1155b725ae77Skettenis case MIPS_ABI_N64:
1156b725ae77Skettenis set_gdbarch_get_longjmp_target (gdbarch,
1157b725ae77Skettenis mips64_linux_get_longjmp_target);
1158b725ae77Skettenis set_solib_svr4_fetch_link_map_offsets
1159b725ae77Skettenis (gdbarch, mips64_linux_svr4_fetch_link_map_offsets);
1160b725ae77Skettenis set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
1161*11efff7fSkettenis tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
1162b725ae77Skettenis break;
1163b725ae77Skettenis default:
1164b725ae77Skettenis internal_error (__FILE__, __LINE__, "can't handle ABI");
1165b725ae77Skettenis break;
1166b725ae77Skettenis }
1167b725ae77Skettenis
1168b725ae77Skettenis set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver);
1169b725ae77Skettenis
1170b725ae77Skettenis /* This overrides the MIPS16 stub support from mips-tdep. But no
1171b725ae77Skettenis one uses MIPS16 on GNU/Linux yet, so this isn't much of a loss. */
1172b725ae77Skettenis set_gdbarch_in_solib_call_trampoline (gdbarch, mips_linux_in_dynsym_stub);
1173b725ae77Skettenis }
1174b725ae77Skettenis
1175b725ae77Skettenis void
_initialize_mips_linux_tdep(void)1176b725ae77Skettenis _initialize_mips_linux_tdep (void)
1177b725ae77Skettenis {
1178b725ae77Skettenis const struct bfd_arch_info *arch_info;
1179b725ae77Skettenis
1180b725ae77Skettenis register_addr_data =
1181*11efff7fSkettenis gdbarch_data_register_post_init (init_register_addr_data);
1182b725ae77Skettenis
1183b725ae77Skettenis for (arch_info = bfd_lookup_arch (bfd_arch_mips, 0);
1184b725ae77Skettenis arch_info != NULL;
1185b725ae77Skettenis arch_info = arch_info->next)
1186b725ae77Skettenis {
1187b725ae77Skettenis gdbarch_register_osabi (bfd_arch_mips, arch_info->mach, GDB_OSABI_LINUX,
1188b725ae77Skettenis mips_linux_init_abi);
1189b725ae77Skettenis }
1190b725ae77Skettenis
1191*11efff7fSkettenis deprecated_add_core_fns (®set_core_fns);
1192b725ae77Skettenis }
1193