Add partial support for ELF format corefiles. Still needs code to extract

register values from corefiles and make them available to bfd clients.
This commit is contained in:
Fred Fish 1991-10-24 10:26:26 +00:00
parent dcd15e5e7a
commit e0796d2213
2 changed files with 267 additions and 48 deletions

View File

@ -1,5 +1,8 @@
Thu Oct 24 02:03:24 1991 Fred Fish (fnf at cygnus.com)
* elf.c: Add partial support for ELF format corefiles. Still needs
support for extracting registers from corefiles.
* config/t-m68k-elf: Set DEFAULT_VECTOR to elf_big_vec.
* config/{h-amix,h-dgux,h-irix3,h-ultra3}: For systems where

312
bfd/elf.c
View File

@ -68,9 +68,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
*/
#include <ansidecl.h>
#include <sysdep.h>
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "obstack.h"
#include "elf-common.h"
@ -128,6 +127,26 @@ DEFUN(bfd_swap_shdr_in,(abfd, src, dst),
}
/* Translate an ELF program header table entry in external format into an
ELF program header table entry in internal format. */
static void
DEFUN(bfd_swap_phdr_in,(abfd, src, dst),
bfd *abfd AND
Elf_External_Phdr *src AND
Elf_Internal_Phdr *dst)
{
dst -> p_type = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_type);
dst -> p_offset = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_offset);
dst -> p_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_vaddr);
dst -> p_paddr = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_paddr);
dst -> p_filesz = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_filesz);
dst -> p_memsz = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_memsz);
dst -> p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_flags);
dst -> p_align = bfd_h_get_32 (abfd, (bfd_byte *) src -> p_align);
}
/* Create a new bfd section from an ELF section header. */
static boolean
@ -172,6 +191,91 @@ DEFUN(bfd_section_from_shdr, (abfd, hdr, shstrtab),
return (true);
}
/* Create a new bfd section from an ELF program header.
Since program segments have no names, we generate a synthetic name
of the form segment<NUM>, where NUM is generally the index in the
program header table. For segments that are split (see below) we
generate the names segment<NUM>a and segment<NUM>b.
Note that some program segments may have a file size that is different than
(less than) the memory size. All this means is that at execution the
system must allocate the amount of memory specified by the memory size,
but only initialize it with the first "file size" bytes read from the
file. This would occur for example, with program segments consisting
of combined data+bss.
To handle the above situation, this routine generates TWO bfd sections
for the single program segment. The first has the length specified by
the file size of the segment, and the second has the length specified
by the difference between the two sizes. In effect, the segment is split
into it's initialized and uninitialized parts.
*/
static boolean
DEFUN(bfd_section_from_phdr, (abfd, hdr, index),
bfd *abfd AND
Elf_Internal_Phdr *hdr AND
int index)
{
asection *newsect;
char *name;
char namebuf[64];
int split;
split = ((hdr -> p_memsz > 0) &&
(hdr -> p_filesz > 0) &&
(hdr -> p_memsz > hdr -> p_filesz));
sprintf (namebuf, split ? "segment%da" : "segment%d", index);
name = bfd_alloc (abfd, strlen (namebuf) + 1);
(void) strcpy (name, namebuf);
newsect = bfd_make_section (abfd, name);
newsect -> vma = hdr -> p_vaddr;
newsect -> size = hdr -> p_filesz;
newsect -> filepos = hdr -> p_offset;
newsect -> flags |= SEC_HAS_CONTENTS;
if (hdr -> p_type == PT_LOAD)
{
newsect -> flags |= SEC_ALLOC;
newsect -> flags |= SEC_LOAD;
if (hdr -> p_flags & PF_X)
{
/* FIXME: all we known is that it has execute PERMISSION,
may be data. */
newsect -> flags |= SEC_CODE;
}
}
if (!(hdr -> p_flags & PF_W))
{
newsect -> flags |= SEC_READONLY;
}
if (split)
{
sprintf (namebuf, "segment%db", index);
name = bfd_alloc (abfd, strlen (namebuf) + 1);
(void) strcpy (name, namebuf);
newsect = bfd_make_section (abfd, name);
newsect -> vma = hdr -> p_vaddr + hdr -> p_filesz;
newsect -> size = hdr -> p_memsz - hdr -> p_filesz;
if (hdr -> p_type == PT_LOAD)
{
newsect -> flags |= SEC_ALLOC;
if (hdr -> p_flags & PF_X)
{
newsect -> flags |= SEC_CODE;
}
}
if (!(hdr -> p_flags & PF_W))
{
newsect -> flags |= SEC_READONLY;
}
}
return (true);
}
/* Begin processing a given object.
First we validate the file by reading in the ELF header and checking
@ -241,7 +345,9 @@ wrong:
/* Now that we know the byte order, swap in the rest of the header */
bfd_swap_ehdr_in (abfd, &x_ehdr, &i_ehdr);
if (x_ehdr.e_shoff == 0)
/* If there is no section header table, we're hosed. */
if (i_ehdr.e_shoff == 0)
goto wrong;
if (i_ehdr.e_type == ET_EXEC || i_ehdr.e_type == ET_DYN)
@ -316,6 +422,125 @@ wrong:
return (abfd->xvec);
}
/* Core files are simply standard ELF formatted files that partition
the file using the execution view of the file (program header table)
rather than the linking view. In fact, there is no section header
table in a core file.
*/
static bfd_target *
DEFUN (elf_core_file_p, (abfd), bfd *abfd)
{
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */
Elf_External_Phdr *x_phdr; /* Program header table, external form */
Elf_Internal_Phdr *i_phdr; /* Program header table, internal form */
int phindex;
/* Read in the ELF header in external format. */
if (bfd_read ((PTR) &x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr))
{
bfd_error = system_call_error;
return (NULL);
}
/* Now check to see if we have a valid ELF file, and one that BFD can
make use of. The magic number must match, the address size ('class')
and byte-swapping must match our XVEC entry, and it must have a
program header table (FIXME: See comments re segments at top of this
file). */
if (x_ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
x_ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
x_ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
x_ehdr.e_ident[EI_MAG3] != ELFMAG3)
{
wrong:
bfd_error = wrong_format;
return (NULL);
}
/* FIXME, Check EI_VERSION here ! */
switch (x_ehdr.e_ident[EI_CLASS]) {
case ELFCLASSNONE: /* address size not specified */
goto wrong; /* No support if can't tell address size */
case ELFCLASS32: /* 32-bit addresses */
break;
case ELFCLASS64: /* 64-bit addresses */
goto wrong; /* FIXME: 64 bits not yet supported */
default:
goto wrong; /* No support if unknown address class */
}
/* Switch xvec to match the specified byte order. */
switch (x_ehdr.e_ident[EI_DATA]) {
case ELFDATA2MSB: /* Big-endian */
abfd->xvec = &elf_big_vec;
break;
case ELFDATA2LSB: /* Little-endian */
abfd->xvec = &elf_little_vec;
case ELFDATANONE: /* No data encoding specified */
default: /* Unknown data encoding specified */
goto wrong;
}
/* Now that we know the byte order, swap in the rest of the header */
bfd_swap_ehdr_in (abfd, &x_ehdr, &i_ehdr);
/* If there is no program header, or the type is not a core file, then
we are hosed. */
if (i_ehdr.e_phoff == 0 || i_ehdr.e_type != ET_CORE)
goto wrong;
/* Allocate space for copies of the program header table in external
and internal form, seek to the program header table in the file,
read it in, and convert it to internal form. As a simple sanity
check, verify that the what BFD thinks is the size of each program
header table entry actually matches the size recorded in the file. */
if (i_ehdr.e_phentsize != sizeof (*x_phdr))
goto wrong;
if ((x_phdr = (Elf_External_Phdr *)
bfd_alloc (abfd, sizeof (*x_phdr) * i_ehdr.e_phnum)) == NULL)
{
bfd_error = no_memory;
return (NULL);
}
if ((i_phdr = (Elf_Internal_Phdr *)
bfd_alloc (abfd, sizeof (*i_phdr) * i_ehdr.e_phnum)) == NULL)
{
bfd_error = no_memory;
return (NULL);
}
if (bfd_seek (abfd, i_ehdr.e_phoff, SEEK_SET) == -1)
{
bfd_error = system_call_error;
return (NULL);
}
for (phindex = 0; phindex < i_ehdr.e_phnum; phindex++)
{
if (bfd_read ((PTR) (x_phdr + phindex), sizeof (*x_phdr), 1, abfd)
!= sizeof (*x_phdr))
{
bfd_error = system_call_error;
return (NULL);
}
bfd_swap_phdr_in (abfd, x_phdr + phindex, i_phdr + phindex);
}
/* Once all of the program headers have been read and converted, we
can start processing them. */
for (phindex = 0; phindex < i_ehdr.e_phnum; phindex++)
{
bfd_section_from_phdr (abfd, i_phdr + phindex, phindex);
}
return (abfd->xvec);
}
static boolean
DEFUN (elf_mkobject, (abfd), bfd *abfd)
{
@ -334,39 +559,6 @@ DEFUN (elf_write_object_contents, (abfd), bfd *abfd)
return (false);
}
static boolean
DEFUN (elf_set_section_contents, (abfd, section, location, offset, count),
bfd *abfd AND
sec_ptr section AND
PTR location AND
file_ptr offset AND
bfd_size_type count)
{
fprintf (stderr, "elf_set_section_contents unimplemented\n");
fflush (stderr);
abort ();
return (false);
}
#define elf_new_section_hook _bfd_dummy_new_section_hook
#define elf_core_file_failing_command _bfd_dummy_core_file_failing_command
#define elf_core_file_failing_signal _bfd_dummy_core_file_failing_signal
#define elf_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
#define elf_slurp_armap bfd_false
#define elf_slurp_extended_name_table _bfd_slurp_extended_name_table
#define elf_truncate_arname bfd_dont_truncate_arname
#define elf_openr_next_archived_file bfd_generic_openr_next_archived_file
#define elf_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define elf_get_section_contents bfd_generic_get_section_contents
#define elf_close_and_cleanup bfd_generic_close_and_cleanup
#define elf_bfd_debug_info_start bfd_void
#define elf_bfd_debug_info_end bfd_void
#define elf_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
#define elf_write_armap bfd_false
static unsigned int
elf_get_symtab_upper_bound(abfd)
bfd *abfd;
@ -427,7 +619,7 @@ DEFUN (elf_print_symbol,(ignore_abfd, filep, symbol, how),
bfd *ignore_abfd AND
PTR filep AND
asymbol *symbol AND
bfd_print_symbol_enum_type how)
bfd_print_symbol_type how)
{
fprintf (stderr, "elf_print_symbol unimplemented\n");
fflush (stderr);
@ -489,7 +681,7 @@ DEFUN (elf_sizeof_headers, (abfd, reloc),
abort ();
return (0);
}
/* This structure contains everything that BFD knows about a target.
It includes things like its byte order, name, what routines to call
to do various operations, etc. Every BFD points to a target structure
@ -498,13 +690,37 @@ DEFUN (elf_sizeof_headers, (abfd, reloc),
There are two such structures here: one for big-endian machines and
one for little-endian machines. */
#define elf_core_file_failing_command _bfd_dummy_core_file_failing_command
#define elf_core_file_failing_signal _bfd_dummy_core_file_failing_signal
#define elf_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
/* Archives are generic or unimplemented. */
#define elf_slurp_armap bfd_false
#define elf_slurp_extended_name_table _bfd_slurp_extended_name_table
#define elf_truncate_arname bfd_dont_truncate_arname
#define elf_openr_next_archived_file bfd_generic_openr_next_archived_file
#define elf_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define elf_write_armap (PROTO (boolean, (*), \
(bfd *arch, unsigned int elength, struct orl *map, int orl_count, \
int stridx))) bfd_false
/* Ordinary section reading and writing */
#define elf_new_section_hook _bfd_dummy_new_section_hook
#define elf_get_section_contents bfd_generic_get_section_contents
#define elf_set_section_contents bfd_generic_set_section_contents
#define elf_close_and_cleanup bfd_generic_close_and_cleanup
#define elf_bfd_debug_info_start bfd_void
#define elf_bfd_debug_info_end bfd_void
#define elf_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
bfd_target elf_big_vec =
{
/* name: identify kind of target */
"elf-big",
/* flavour: general indication about file */
bfd_target_elf_flavour_enum,
bfd_target_elf_flavour,
/* byteorder_big_p: data is big endian */
true,
@ -542,10 +758,10 @@ bfd_target elf_big_vec =
_do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16,
/* bfd_check_format: check the format of a file being read */
{ _bfd_dummy_target,
elf_object_p,
bfd_generic_archive_p,
_bfd_dummy_target
{ _bfd_dummy_target, /* unknown format */
elf_object_p, /* assembler/linker output (object file) */
bfd_generic_archive_p, /* an archive */
elf_core_file_p /* a core file */
},
/* bfd_set_format: set the format of a file being written */
@ -576,7 +792,7 @@ bfd_target elf_little_vec =
"elf-little",
/* flavour: general indication about file */
bfd_target_elf_flavour_enum,
bfd_target_elf_flavour,
/* byteorder_big_p: data is big endian */
false, /* Nope -- this one's little endian */
@ -614,10 +830,10 @@ bfd_target elf_little_vec =
_do_getl64, _do_putl64, _do_getl32, _do_putl32, _do_getl16, _do_putl16,
/* bfd_check_format: check the format of a file being read */
{ _bfd_dummy_target,
elf_object_p,
bfd_generic_archive_p,
_bfd_dummy_target
{ _bfd_dummy_target, /* unknown format */
elf_object_p, /* assembler/linker output (object file) */
bfd_generic_archive_p, /* an archive */
elf_core_file_p /* a core file */
},
/* bfd_set_format: set the format of a file being written */