* osabi.c (generic_elf_osabi_sniffer): Add check for FreeBSD 3.x's
[deliverable/binutils-gdb.git] / gdb / osabi.c
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. */
29 static 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",
43 "DJGPP",
44 "NetWare",
45 "LynxOS",
46
47 "ARM EABI v1",
48 "ARM EABI v2",
49 "ARM APCS",
50
51 "<invalid>"
52 };
53
54 const char *
55 gdbarch_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. */
65 struct 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
73 static struct gdb_osabi_handler *gdb_osabi_handler_list;
74
75 void
76 gdbarch_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. */
127 struct 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
135 static struct gdb_osabi_sniffer *gdb_osabi_sniffer_list;
136
137 void
138 gdbarch_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
155 enum gdb_osabi
156 gdbarch_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
224 void
225 gdbarch_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
271 void
272 generic_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
370 static enum gdb_osabi
371 generic_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 if (osabi == GDB_OSABI_UNKNOWN)
412 {
413 /* The FreeBSD folks have been naughty; they stored the string
414 "FreeBSD" in the padding of the e_ident field of the ELF
415 header to "brand" their ELF binaries in FreeBSD 3.x. */
416 if (strcmp (&elf_elfheader (abfd)->e_ident[8], "FreeBSD") == 0)
417 osabi = GDB_OSABI_FREEBSD_ELF;
418 }
419
420 return osabi;
421 }
422 \f
423
424 void
425 _initialize_gdb_osabi (void)
426 {
427 if (strcmp (gdb_osabi_names[GDB_OSABI_INVALID], "<invalid>") != 0)
428 internal_error
429 (__FILE__, __LINE__,
430 "_initialize_gdb_osabi: gdb_osabi_names[] is inconsistent");
431
432 /* Register a generic sniffer for ELF flavoured files. */
433 gdbarch_register_osabi_sniffer (bfd_arch_unknown,
434 bfd_target_elf_flavour,
435 generic_elf_osabi_sniffer);
436 }
This page took 0.038609 seconds and 5 git commands to generate.