* osabi.c (MAX_NOTESZ): New define.

(check_note): New function.
(generic_elf_osabi_sniff_abi_tag_sections): Reorganize code using
check_note.
This commit is contained in:
Mark Kettenis 2004-01-21 23:07:26 +00:00
parent afd82b6fec
commit a49d618c8c
2 changed files with 85 additions and 69 deletions

View File

@ -1,3 +1,10 @@
2004-01-22 Mark Kettenis <kettenis@gnu.org>
* osabi.c (MAX_NOTESZ): New define.
(check_note): New function.
(generic_elf_osabi_sniff_abi_tag_sections): Reorganize code using
check_note.
2004-01-21 Roland McGrath <roland@redhat.com>
* MAINTAINERS (write after approval): Add myself.

View File

@ -355,119 +355,128 @@ 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);
/* Limit the amount of data to read. */
if (sectsize > MAX_NOTESZ)
sectsize = MAX_NOTESZ;
note = alloca (sectsize);
bfd_get_section_contents (abfd, sect, note, 0, sectsize);
/* .note.ABI-tag notes, used by GNU/Linux and FreeBSD. */
if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
if (strcmp (name, ".note.ABI-tag") == 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;
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);
if (name_length == 4 && data_length == 16 && note_type == NT_GNU_ABI_TAG
&& strcmp (note + 12, "GNU") == 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)
{
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);
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.netbsd.ident notes, used by NetBSD. */
if (strcmp (name, ".note.netbsd.ident") == 0
&& check_note (abfd, sect, note, "NetBSD", 4, NT_NETBSD_IDENT))
{
/* There is no need to check the version yet. */
*osabi = GDB_OSABI_NETBSD_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;
}
}