diff options
Diffstat (limited to 'gdb/osabi.c')
-rw-r--r-- | gdb/osabi.c | 153 |
1 files changed, 86 insertions, 67 deletions
diff --git a/gdb/osabi.c b/gdb/osabi.c index 4c94c5e..3acfc70 100644 --- a/gdb/osabi.c +++ b/gdb/osabi.c @@ -60,6 +60,7 @@ static const char * const gdb_osabi_names[] = "FreeBSD ELF", "NetBSD a.out", "NetBSD ELF", + "OpenBSD ELF", "Windows CE", "DJGPP", "NetWare", @@ -354,119 +355,137 @@ gdbarch_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch) info.bfd_arch_info->printable_name); } +/* Limit on the amount of data to be read. */ +#define MAX_NOTESZ 128 + +/* Return non-zero if NOTE matches NAME, DESCSZ and TYPE. */ + +static int +check_note (bfd *abfd, asection *sect, const char *note, + const char *name, unsigned long descsz, unsigned long type) +{ + unsigned long notesz; + + /* Calculate the size of this note. */ + notesz = strlen (name) + 1; + notesz = ((notesz + 3) & ~3); + notesz += descsz; + notesz = ((notesz + 3) & ~3); + + /* If this assertion triggers, increase MAX_NOTESZ. */ + gdb_assert (notesz <= MAX_NOTESZ); + + /* Check whether SECT is big enough to comtain the complete note. */ + if (notesz > bfd_section_size (abfd, sect)) + return 0; + + /* Check the note name. */ + if (bfd_h_get_32 (abfd, note) != (strlen (name) + 1) + || strcmp (note + 12, name) != 0) + return 0; + + /* Check the descriptor size. */ + if (bfd_h_get_32 (abfd, note + 4) != descsz) + return 0; + + /* Check the note type. */ + if (bfd_h_get_32 (abfd, note + 8) != type) + return 0; + + return 1; +} /* Generic sniffer for ELF flavoured files. */ void generic_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, void *obj) { - enum gdb_osabi *os_ident_ptr = obj; + enum gdb_osabi *osabi = obj; const char *name; unsigned int sectsize; + char *note; name = bfd_get_section_name (abfd, sect); sectsize = bfd_section_size (abfd, sect); - /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD. */ - if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0) - { - unsigned int name_length, data_length, note_type; - char *note; - - /* If the section is larger than this, it's probably not what we are - looking for. */ - if (sectsize > 128) - sectsize = 128; + /* Limit the amount of data to read. */ + if (sectsize > MAX_NOTESZ) + sectsize = MAX_NOTESZ; - note = alloca (sectsize); + note = alloca (sectsize); + bfd_get_section_contents (abfd, sect, note, 0, sectsize); - bfd_get_section_contents (abfd, sect, note, - (file_ptr) 0, (bfd_size_type) sectsize); - - name_length = bfd_h_get_32 (abfd, note); - data_length = bfd_h_get_32 (abfd, note + 4); - note_type = bfd_h_get_32 (abfd, note + 8); - - if (name_length == 4 && data_length == 16 && note_type == NT_GNU_ABI_TAG - && strcmp (note + 12, "GNU") == 0) + /* .note.ABI-tag notes, used by GNU/Linux and FreeBSD. */ + if (strcmp (name, ".note.ABI-tag") == 0) + { + /* GNU. */ + if (check_note (abfd, sect, note, "GNU", 16, NT_GNU_ABI_TAG)) { - int os_number = bfd_h_get_32 (abfd, note + 16); + unsigned int abi_tag = bfd_h_get_32 (abfd, note + 16); - switch (os_number) + switch (abi_tag) { case GNU_ABI_TAG_LINUX: - *os_ident_ptr = GDB_OSABI_LINUX; + *osabi = GDB_OSABI_LINUX; break; case GNU_ABI_TAG_HURD: - *os_ident_ptr = GDB_OSABI_HURD; + *osabi = GDB_OSABI_HURD; break; case GNU_ABI_TAG_SOLARIS: - *os_ident_ptr = GDB_OSABI_SOLARIS; + *osabi = GDB_OSABI_SOLARIS; break; case GNU_ABI_TAG_FREEBSD: - *os_ident_ptr = GDB_OSABI_FREEBSD_ELF; + *osabi = GDB_OSABI_FREEBSD_ELF; break; - + case GNU_ABI_TAG_NETBSD: - *os_ident_ptr = GDB_OSABI_NETBSD_ELF; + *osabi = GDB_OSABI_NETBSD_ELF; break; - + default: - internal_error - (__FILE__, __LINE__, - "generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d", - os_number); + internal_error (__FILE__, __LINE__, "\ +generic_elf_osabi_sniff_abi_tag_sections: unknown OS number %d", + abi_tag); } return; } - else if (name_length == 8 && data_length == 4 - && note_type == NT_FREEBSD_ABI_TAG - && strcmp (note + 12, "FreeBSD") == 0) + + /* FreeBSD. */ + if (check_note (abfd, sect, note, "FreeBSD", 4, NT_FREEBSD_ABI_TAG)) { - /* XXX Should we check the version here? Probably not - necessary yet. */ - *os_ident_ptr = GDB_OSABI_FREEBSD_ELF; + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_FREEBSD_ELF; + return; } + return; } - + /* .note.netbsd.ident notes, used by NetBSD. */ - if (strcmp (name, ".note.netbsd.ident") == 0 && sectsize > 0) + if (strcmp (name, ".note.netbsd.ident") == 0 + && check_note (abfd, sect, note, "NetBSD", 4, NT_NETBSD_IDENT)) { - unsigned int name_length, data_length, note_type; - char *note; - - /* If the section is larger than this, it's probably not what we are - looking for. */ - if (sectsize > 128) - sectsize = 128; - - note = alloca (sectsize); - - bfd_get_section_contents (abfd, sect, note, - (file_ptr) 0, (bfd_size_type) sectsize); - - name_length = bfd_h_get_32 (abfd, note); - data_length = bfd_h_get_32 (abfd, note + 4); - note_type = bfd_h_get_32 (abfd, note + 8); + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_NETBSD_ELF; + return; + } - if (name_length == 7 && data_length == 4 && note_type == NT_NETBSD_IDENT - && strcmp (note + 12, "NetBSD") == 0) - { - /* XXX Should we check the version here? Probably not - necessary yet. */ - *os_ident_ptr = GDB_OSABI_NETBSD_ELF; - } + /* .note.openbsd.ident notes, used by OpenBSD. */ + if (strcmp (name, ".note.openbsd.ident") == 0 + && check_note (abfd, sect, note, "OpenBSD", 4, NT_OPENBSD_IDENT)) + { + /* There is no need to check the version yet. */ + *osabi = GDB_OSABI_OPENBSD_ELF; return; } /* .note.netbsdcore.procinfo notes, used by NetBSD. */ - if (strcmp (name, ".note.netbsdcore.procinfo") == 0 && sectsize > 0) + if (strcmp (name, ".note.netbsdcore.procinfo") == 0) { - *os_ident_ptr = GDB_OSABI_NETBSD_ELF; + *osabi = GDB_OSABI_NETBSD_ELF; return; } } |