xref: /openbsd-src/gnu/usr.bin/binutils/gdb/mips-linux-tdep.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
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 (&regset_core_fns);
1192b725ae77Skettenis }
1193