2002-07-04 Daniel Jacobowitz <drow@mvista.com>
[deliverable/binutils-gdb.git] / gdb / osabi.c
CommitLineData
70f80edf
JT
1/* OS ABI variant handling for GDB.
2 Copyright 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include "defs.h"
22#include "osabi.h"
23
24#include "elf-bfd.h"
25
26
27/* This table matches the indices assigned to enum gdb_osabi. Keep
28 them in sync. */
29static const char * const gdb_osabi_names[] =
30{
31 "<unknown>",
32
33 "SVR4",
34 "GNU/Hurd",
35 "Solaris",
36 "OSF/1",
37 "GNU/Linux",
38 "FreeBSD a.out",
39 "FreeBSD ELF",
40 "NetBSD a.out",
41 "NetBSD ELF",
42 "Windows CE",
1029b7fa
MK
43 "DJGPP",
44 "NetWare",
daa66587 45 "LynxOS",
70f80edf
JT
46
47 "ARM EABI v1",
48 "ARM EABI v2",
49 "ARM APCS",
50
51 "<invalid>"
52};
53
54const char *
55gdbarch_osabi_name (enum gdb_osabi osabi)
56{
57 if (osabi >= GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
58 return gdb_osabi_names[osabi];
59
60 return gdb_osabi_names[GDB_OSABI_INVALID];
61}
62
63/* Handler for a given architecture/OS ABI pair. There should be only
64 one handler for a given OS ABI each architecture family. */
65struct gdb_osabi_handler
66{
67 struct gdb_osabi_handler *next;
68 enum bfd_architecture arch;
69 enum gdb_osabi osabi;
70 void (*init_osabi)(struct gdbarch_info, struct gdbarch *);
71};
72
73static struct gdb_osabi_handler *gdb_osabi_handler_list;
74
75void
76gdbarch_register_osabi (enum bfd_architecture arch, enum gdb_osabi osabi,
77 void (*init_osabi)(struct gdbarch_info,
78 struct gdbarch *))
79{
80 struct gdb_osabi_handler **handler_p;
81
82 /* Registering an OS ABI handler for "unknown" is not allowed. */
83 if (osabi == GDB_OSABI_UNKNOWN)
84 {
85 internal_error
86 (__FILE__, __LINE__,
87 "gdbarch_register_osabi: An attempt to register a handler for "
88 "OS ABI \"%s\" for architecture %s was made. The handler will "
89 "not be registered",
90 gdbarch_osabi_name (osabi),
91 bfd_printable_arch_mach (arch, 0));
92 return;
93 }
94
95 for (handler_p = &gdb_osabi_handler_list; *handler_p != NULL;
96 handler_p = &(*handler_p)->next)
97 {
98 if ((*handler_p)->arch == arch
99 && (*handler_p)->osabi == osabi)
100 {
101 internal_error
102 (__FILE__, __LINE__,
103 "gdbarch_register_osabi: A handler for OS ABI \"%s\" "
104 "has already been registered for architecture %s",
105 gdbarch_osabi_name (osabi),
106 bfd_printable_arch_mach (arch, 0));
107 /* If user wants to continue, override previous definition. */
108 (*handler_p)->init_osabi = init_osabi;
109 return;
110 }
111 }
112
113 (*handler_p)
114 = (struct gdb_osabi_handler *) xmalloc (sizeof (struct gdb_osabi_handler));
115 (*handler_p)->next = NULL;
116 (*handler_p)->arch = arch;
117 (*handler_p)->osabi = osabi;
118 (*handler_p)->init_osabi = init_osabi;
119}
120\f
121
122/* Sniffer to find the OS ABI for a given file's architecture and flavour.
123 It is legal to have multiple sniffers for each arch/flavour pair, to
124 disambiguate one OS's a.out from another, for example. The first sniffer
125 to return something other than GDB_OSABI_UNKNOWN wins, so a sniffer should
126 be careful to claim a file only if it knows for sure what it is. */
127struct gdb_osabi_sniffer
128{
129 struct gdb_osabi_sniffer *next;
130 enum bfd_architecture arch; /* bfd_arch_unknown == wildcard */
131 enum bfd_flavour flavour;
132 enum gdb_osabi (*sniffer)(bfd *);
133};
134
135static struct gdb_osabi_sniffer *gdb_osabi_sniffer_list;
136
137void
138gdbarch_register_osabi_sniffer (enum bfd_architecture arch,
139 enum bfd_flavour flavour,
140 enum gdb_osabi (*sniffer_fn)(bfd *))
141{
142 struct gdb_osabi_sniffer *sniffer;
143
144 sniffer =
145 (struct gdb_osabi_sniffer *) xmalloc (sizeof (struct gdb_osabi_sniffer));
146 sniffer->arch = arch;
147 sniffer->flavour = flavour;
148 sniffer->sniffer = sniffer_fn;
149
150 sniffer->next = gdb_osabi_sniffer_list;
151 gdb_osabi_sniffer_list = sniffer;
152}
153\f
154
155enum gdb_osabi
156gdbarch_lookup_osabi (bfd *abfd)
157{
158 struct gdb_osabi_sniffer *sniffer;
159 enum gdb_osabi osabi, match;
160 int match_specific;
161
162 match = GDB_OSABI_UNKNOWN;
163 match_specific = 0;
164
165 for (sniffer = gdb_osabi_sniffer_list; sniffer != NULL;
166 sniffer = sniffer->next)
167 {
168 if ((sniffer->arch == bfd_arch_unknown /* wildcard */
169 || sniffer->arch == bfd_get_arch (abfd))
170 && sniffer->flavour == bfd_get_flavour (abfd))
171 {
172 osabi = (*sniffer->sniffer) (abfd);
173 if (osabi < GDB_OSABI_UNKNOWN || osabi >= GDB_OSABI_INVALID)
174 {
175 internal_error
176 (__FILE__, __LINE__,
177 "gdbarch_lookup_osabi: invalid OS ABI (%d) from sniffer "
178 "for architecture %s flavour %d",
179 (int) osabi,
180 bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
181 (int) bfd_get_flavour (abfd));
182 }
183 else if (osabi != GDB_OSABI_UNKNOWN)
184 {
185 /* A specific sniffer always overrides a generic sniffer.
186 Croak on multiple match if the two matches are of the
187 same class. If the user wishes to continue, we'll use
188 the first match. */
189 if (match != GDB_OSABI_UNKNOWN)
190 {
191 if ((match_specific && sniffer->arch != bfd_arch_unknown)
192 || (!match_specific && sniffer->arch == bfd_arch_unknown))
193 {
194 internal_error
195 (__FILE__, __LINE__,
196 "gdbarch_lookup_osabi: multiple %sspecific OS ABI "
197 "match for architecture %s flavour %d: first "
198 "match \"%s\", second match \"%s\"",
199 match_specific ? "" : "non-",
200 bfd_printable_arch_mach (bfd_get_arch (abfd), 0),
201 (int) bfd_get_flavour (abfd),
202 gdbarch_osabi_name (match),
203 gdbarch_osabi_name (osabi));
204 }
205 else if (sniffer->arch != bfd_arch_unknown)
206 {
207 match = osabi;
208 match_specific = 1;
209 }
210 }
211 else
212 {
213 match = osabi;
214 if (sniffer->arch != bfd_arch_unknown)
215 match_specific = 1;
216 }
217 }
218 }
219 }
220
221 return match;
222}
223
224void
225gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch,
226 enum gdb_osabi osabi)
227{
228 struct gdb_osabi_handler *handler;
229 bfd *abfd = info.abfd;
230 const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
231
232 if (osabi == GDB_OSABI_UNKNOWN)
233 {
234 /* Don't complain about not knowing the OS ABI if we don't
235 have an inferior. */
236 if (info.abfd)
237 fprintf_filtered
238 (gdb_stderr, "GDB doesn't recognize the OS ABI of the inferior. "
239 "Attempting to continue with the default %s settings",
240 bfd_printable_arch_mach (arch_info->arch, arch_info->mach));
241 return;
242 }
243
244 for (handler = gdb_osabi_handler_list; handler != NULL;
245 handler = handler->next)
246 {
247 if (handler->arch == bfd_get_arch (abfd)
248 && handler->osabi == osabi)
249 {
250 (*handler->init_osabi) (info, gdbarch);
251 return;
252 }
253 }
254
255 /* We assume that if GDB_MULTI_ARCH is less than GDB_MULTI_ARCH_TM
256 that an ABI variant can be supported by overriding definitions in
257 the tm-file. */
258 if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL)
259 fprintf_filtered
260 (gdb_stderr,
261 "A handler for the OS ABI \"%s\" is not built into this "
262 "configuration of GDB. "
263 "Attempting to continue with the default %s settings",
264 gdbarch_osabi_name (osabi),
265 bfd_printable_arch_mach (arch_info->arch, arch_info->mach));
266}
267\f
268
269/* Generic sniffer for ELF flavoured files. */
270
271void
272generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
273{
274 enum gdb_osabi *os_ident_ptr = obj;
275 const char *name;
276 unsigned int sectsize;
277
278 name = bfd_get_section_name (abfd, sect);
279 sectsize = bfd_section_size (abfd, sect);
280
281 /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD. */
282 if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
283 {
284 unsigned int name_length, data_length, note_type;
285 char *note;
286
287 /* If the section is larger than this, it's probably not what we are
288 looking for. */
289 if (sectsize > 128)
290 sectsize = 128;
291
292 note = alloca (sectsize);
293
294 bfd_get_section_contents (abfd, sect, note,
295 (file_ptr) 0, (bfd_size_type) sectsize);
296
297 name_length = bfd_h_get_32 (abfd, note);
298 data_length = bfd_h_get_32 (abfd, note + 4);
299 note_type = bfd_h_get_32 (abfd, note + 8);
300
301 if (name_length == 4 && data_length == 16 && note_type == NT_GNU_ABI_TAG
302 && strcmp (note + 12, "GNU") == 0)
303 {
304 int os_number = bfd_h_get_32 (abfd, note + 16);
305
306 switch (os_number)
307 {
308 case GNU_ABI_TAG_LINUX:
309 *os_ident_ptr = GDB_OSABI_LINUX;
310 break;
311
312 case GNU_ABI_TAG_HURD:
313 *os_ident_ptr = GDB_OSABI_HURD;
314 break;
315
316 case GNU_ABI_TAG_SOLARIS:
317 *os_ident_ptr = GDB_OSABI_SOLARIS;
318 break;
319
320 default:
321 internal_error
322 (__FILE__, __LINE__,
323 "generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d",
324 os_number);
325 }
326 return;
327 }
328 else if (name_length == 8 && data_length == 4
329 && note_type == NT_FREEBSD_ABI_TAG
330 && strcmp (note + 12, "FreeBSD") == 0)
331 {
332 /* XXX Should we check the version here? Probably not
333 necessary yet. */
334 *os_ident_ptr = GDB_OSABI_FREEBSD_ELF;
335 }
336 return;
337 }
338
339 /* .note.netbsd.ident notes, used by NetBSD. */
340 if (strcmp (name, ".note.netbsd.ident") == 0 && sectsize > 0)
341 {
342 unsigned int name_length, data_length, note_type;
343 char *note;
344
345 /* If the section is larger than this, it's probably not what we are
346 looking for. */
347 if (sectsize > 128)
348 sectsize = 128;
349
350 note = alloca (sectsize);
351
352 bfd_get_section_contents (abfd, sect, note,
353 (file_ptr) 0, (bfd_size_type) sectsize);
354
355 name_length = bfd_h_get_32 (abfd, note);
356 data_length = bfd_h_get_32 (abfd, note + 4);
357 note_type = bfd_h_get_32 (abfd, note + 8);
358
359 if (name_length == 7 && data_length == 4 && note_type == NT_NETBSD_IDENT
360 && strcmp (note + 12, "NetBSD") == 0)
361 {
362 /* XXX Should we check the version here? Probably not
363 necessary yet. */
364 *os_ident_ptr = GDB_OSABI_NETBSD_ELF;
365 }
366 return;
367 }
368}
369
370static enum gdb_osabi
371generic_elf_osabi_sniffer (bfd *abfd)
372{
373 unsigned int elfosabi;
374 enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
375
376 elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
377
378 switch (elfosabi)
379 {
380 case ELFOSABI_NONE:
381 /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the
382 file are conforming to the base specification for that machine
383 (there are no OS-specific extensions). In order to determine the
384 real OS in use we must look for OS notes that have been added. */
385 bfd_map_over_sections (abfd,
386 generic_elf_osabi_sniff_abi_tag_sections,
387 &osabi);
388 break;
389
390 case ELFOSABI_FREEBSD:
391 osabi = GDB_OSABI_FREEBSD_ELF;
392 break;
393
394 case ELFOSABI_NETBSD:
395 osabi = GDB_OSABI_NETBSD_ELF;
396 break;
397
398 case ELFOSABI_LINUX:
399 osabi = GDB_OSABI_LINUX;
400 break;
401
402 case ELFOSABI_HURD:
403 osabi = GDB_OSABI_HURD;
404 break;
405
406 case ELFOSABI_SOLARIS:
407 osabi = GDB_OSABI_SOLARIS;
408 break;
409 }
410
411 return osabi;
412}
413\f
414
415void
416_initialize_gdb_osabi (void)
417{
418 if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "<invalid>") != 0)
419 internal_error
420 (__FILE__, __LINE__,
421 "_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent");
422
423 /* Register a generic sniffer for ELF flavoured files. */
424 gdbarch_register_osabi_sniffer (bfd_arch_unknown,
425 bfd_target_elf_flavour,
426 generic_elf_osabi_sniffer);
427}
This page took 0.051445 seconds and 4 git commands to generate.