* NEWS: Note new sh*-*-netbsdelf* configuration.
[external/binutils.git] / gdb / sh-nbsd-tdep.c
1 /* Target-dependent code for SuperH running NetBSD, for GDB.
2    Copyright 2002 Free Software Foundation, Inc.
3    Contributed by Wasabi Systems, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "regcache.h"
25 #include "value.h"
26 #include "solib-svr4.h"
27
28 #include "sh-nbsd-tdep.h"
29
30 /* Convert an r0-r15 register number into an offset into a ptrace
31    register structure.  */
32 static const int regmap[] =
33 {
34   (20 * 4),     /* r0 */
35   (19 * 4),     /* r1 */
36   (18 * 4),     /* r2 */ 
37   (17 * 4),     /* r3 */ 
38   (16 * 4),     /* r4 */
39   (15 * 4),     /* r5 */
40   (14 * 4),     /* r6 */
41   (13 * 4),     /* r7 */
42   (12 * 4),     /* r8 */ 
43   (11 * 4),     /* r9 */
44   (10 * 4),     /* r10 */
45   ( 9 * 4),     /* r11 */
46   ( 8 * 4),     /* r12 */
47   ( 7 * 4),     /* r13 */
48   ( 6 * 4),     /* r14 */
49   ( 5 * 4),     /* r15 */
50 };
51
52 #define SIZEOF_STRUCT_REG (21 * 4)
53
54 void
55 sh_nbsd_supply_registers (char *regs)
56 {
57   int regno;
58
59   for (regno = R0_REGNUM; regno <= (R0_REGNUM + 15); regno++)
60     supply_register (regno, regs + regmap[regno - R0_REGNUM]);
61
62   supply_register (PC_REGNUM, regs + (0 * 4));
63   supply_register (SR_REGNUM, regs + (1 * 4));
64   supply_register (PR_REGNUM, regs + (2 * 4));
65   supply_register (MACH_REGNUM, regs + (3 * 4));
66   supply_register (MACL_REGNUM, regs + (4 * 4));
67 }
68
69 void
70 sh_nbsd_supply_register (char *regs, int regno)
71 {
72   if (regno == -1)
73     sh_nbsd_supply_registers (regs);
74
75   if (regno == PC_REGNUM)
76     supply_register (PC_REGNUM, regs + (0 * 4));
77   else if (regno == SR_REGNUM)
78     supply_register (SR_REGNUM, regs + (1 * 4));
79   else if (regno == PR_REGNUM)
80     supply_register (PR_REGNUM, regs + (2 * 4));
81   else if (regno == MACH_REGNUM)
82     supply_register (MACH_REGNUM, regs + (3 * 4));
83   else if (regno == MACL_REGNUM)
84     supply_register (MACL_REGNUM, regs + (4 * 4));
85   else if (regno >= R0_REGNUM && regno <= (R0_REGNUM + 15))
86     supply_register (regno, regs + regmap[regno - R0_REGNUM]);
87 }
88
89 void
90 sh_nbsd_fill_registers (char *regs)
91 {
92   int regno;
93
94   for (regno = R0_REGNUM; regno <= (R0_REGNUM + 15); regno++)
95     regcache_collect (regno, regs + regmap[regno - R0_REGNUM]);
96
97   regcache_collect (PC_REGNUM, regs + (0 * 4));
98   regcache_collect (SR_REGNUM, regs + (1 * 4));
99   regcache_collect (PR_REGNUM, regs + (2 * 4));
100   regcache_collect (MACH_REGNUM, regs + (3 * 4));
101   regcache_collect (MACL_REGNUM, regs + (4 * 4));
102 }
103
104 void
105 sh_nbsd_fill_register (char *regs, int regno)
106 {
107   if (regno == -1)
108     sh_nbsd_fill_registers (regs);
109
110   if (regno == PC_REGNUM)
111     regcache_collect (PC_REGNUM, regs + (0 * 4));
112   else if (regno == SR_REGNUM)
113     regcache_collect (SR_REGNUM, regs + (1 * 4));
114   else if (regno == PR_REGNUM)
115     regcache_collect (PR_REGNUM, regs + (2 * 4));
116   else if (regno == MACH_REGNUM)
117     regcache_collect (MACH_REGNUM, regs + (3 * 4));
118   else if (regno == MACL_REGNUM)
119     regcache_collect (MACL_REGNUM, regs + (4 * 4));
120   else if (regno >= R0_REGNUM && regno <= (R0_REGNUM + 15))
121     regcache_collect (regno, regs + regmap[regno - R0_REGNUM]);
122 }
123
124 /* Fetch (and possibly build) an appropriate link_map_offsets
125    structure for NetBSD/sh targets using the struct offsets
126    defined in <link.h> (but without actual reference to that file).
127
128    This makes it possible to access NetBSD/sh shared libraries
129    from a GDB that was not built on a NetBSD/sh host (for cross
130    debugging).  */
131
132 static struct link_map_offsets *
133 sh_nbsd_solib_svr4_fetch_link_map_offsets (void)
134 {
135   static struct link_map_offsets lmo;
136   static struct link_map_offsets *lmp = NULL;
137
138   if (lmp == NULL)
139     {
140       lmp = &lmo;
141
142       lmo.r_debug_size = 16;
143
144       lmo.r_map_offset = 4;
145       lmo.r_map_size   = 4;
146
147       lmo.link_map_size = 20;
148
149       lmo.l_addr_offset = 0;
150       lmo.l_addr_size   = 4;
151
152       lmo.l_name_offset = 4;
153       lmo.l_name_size   = 4;
154
155       lmo.l_next_offset = 12;
156       lmo.l_next_size   = 4;
157
158       lmo.l_prev_offset = 16;
159       lmo.l_prev_size   = 4;
160     }
161
162   return lmp;
163 }
164
165 static void
166 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
167                       int which, CORE_ADDR ignore)
168 {
169   /* We get everything from the .reg section.  */
170   if (which != 0)
171     return;
172
173   if (core_reg_size < SIZEOF_STRUCT_REG)
174     {
175       warning ("Wrong size register set in core file.");
176       return;
177     }
178
179   /* Integer registers.  */
180   sh_nbsd_supply_registers (core_reg_sect);
181 }
182
183 static void
184 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
185                          int which, CORE_ADDR ignore)
186 {
187   switch (which)
188     {
189     case 0:  /* Integer registers.  */
190       if (core_reg_size != SIZEOF_STRUCT_REG)
191         warning ("Wrong size register set in core file.");
192       else
193         sh_nbsd_supply_registers (core_reg_sect);
194       break;
195
196     default:
197       /* Don't know what kind of register request this is; just ignore it.  */
198       break;
199     }
200 }
201
202 static struct core_fns sh_nbsd_core_fns =
203 {
204   bfd_target_unknown_flavour,           /* core_flavour */
205   default_check_format,                 /* check_format */
206   default_core_sniffer,                 /* core_sniffer */
207   fetch_core_registers,                 /* core_read_registers */
208   NULL                                  /* next */
209 };
210
211 static struct core_fns sh_nbsd_elfcore_fns =
212 {
213   bfd_target_elf_flavour,               /* core_flavour */
214   default_check_format,                 /* check_format */
215   default_core_sniffer,                 /* core_sniffer */
216   fetch_elfcore_registers,              /* core_read_registers */
217   NULL                                  /* next */
218 };
219
220 static void
221 sh_nbsd_init_abi (struct gdbarch_info info,
222                   struct gdbarch *gdbarch)
223 {
224   set_solib_svr4_fetch_link_map_offsets (gdbarch,
225                                    sh_nbsd_solib_svr4_fetch_link_map_offsets);
226 }
227
228 void
229 _initialize_sh_nbsd_tdep (void)
230 {
231   add_core_fns (&sh_nbsd_core_fns);
232   add_core_fns (&sh_nbsd_elfcore_fns);
233
234   sh_gdbarch_register_os_abi (SH_OSABI_NETBSD_ELF, sh_nbsd_init_abi);
235 }