/* ELF executable support for BFD.
- Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
in "UNIX System V Release 4, Programmers Guide: ANSI C and
- Programming Support Tools". Sufficient support for gdb.
+ Programming Support Tools". Sufficient support for gdb.
Rewritten by Mark Eichin @ Cygnus Support, from information
published in "System V Application Binary Interface", chapters 4
#define bfd_prpsinfo(abfd, descdata, descsz, filepos) /* Define away */
#endif
+/* Forward declarations of static functions */
+
+static char *
+elf_read PARAMS ((bfd *, long, int));
+
+static struct sec *
+section_from_elf_index PARAMS ((bfd *, int));
+
+static int
+elf_section_from_bfd_section PARAMS ((bfd *, struct sec *));
+
+static boolean
+elf_slurp_symbol_table PARAMS ((bfd *, asymbol **));
+
+static void
+elf_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+
+static char *
+elf_get_str_section PARAMS ((bfd *, unsigned int));
+
/* Forward data declarations */
extern bfd_target elf_little_vec, elf_big_vec;
} elf_symbol_type;
/* Some private data is stashed away for future use using the tdata pointer
- in the bfd structure. This information is different for ELF core files
- and other ELF files. */
+ in the bfd structure. */
-typedef struct elf_core_tdata_struct
+struct elf_obj_tdata
{
- void *prstatus; /* The raw /proc prstatus structure */
- void *prpsinfo; /* The raw /proc prpsinfo structure */
-} elf_core_tdata;
-
-#define core_prpsinfo(bfd) (((bfd)->tdata.elf_core_data) -> prpsinfo)
-#define core_prstatus(bfd) (((bfd)->tdata.elf_core_data) -> prstatus)
-
-
-typedef struct elf_obj_tdata_struct
-{
- Elf_Internal_Ehdr *elf_header;
+ Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */
Elf_Internal_Shdr *elf_sect_ptr;
struct strtab *strtab_ptr;
int symtab_section;
-} elf_obj_tdata;
+ void *prstatus; /* The raw /proc prstatus structure */
+ void *prpsinfo; /* The raw /proc prpsinfo structure */
+};
#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header)
#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr)
#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr)
#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section)
+#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo)
+#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus)
/* Translate an ELF symbol in external format into an ELF symbol in internal
format. */
bfd_h_put_32 (abfd, src->r_addend, dst->r_addend);
}
-static char *EXFUN(elf_read, (bfd *, long, int));
-static struct sec * EXFUN(section_from_elf_index, (bfd *, int));
-static int EXFUN(elf_section_from_bfd_section, (bfd *, struct sec *));
-static boolean EXFUN(elf_slurp_symbol_table, (bfd *, Elf_Internal_Shdr*));
-static void EXFUN(elf_info_to_howto, (bfd *, arelent *, Elf_Internal_Rela *));
-
+/*
+INTERNAL_FUNCTION
+ bfd_elf_find_section
+
+SYNOPSIS
+ Elf_Internal_Shdr *bfd_elf_find_section (bfd *abfd, char *name);
+
+DESCRIPTION
+ Helper functions for GDB to locate the string tables.
+ Since BFD hides string tables from callers, GDB needs to use an
+ internal hook to find them. Sun's .stabstr, in particular,
+ isn't even pointed to by the .stab section, so ordinary
+ mechanisms wouldn't work to find it, even if we had some.
+*/
+
+Elf_Internal_Shdr *
+DEFUN(bfd_elf_find_section, (abfd, name),
+ bfd *abfd AND
+ char *name)
+{
+ Elf_Internal_Shdr *i_shdrp;
+ Elf_Internal_Shdr *gotit = NULL;
+ char *shstrtab;
+ unsigned int max;
+ unsigned int i;
+
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp != NULL)
+ {
+ shstrtab = elf_get_str_section (abfd, elf_elfheader (abfd)->e_shstrndx);
+ if (shstrtab != NULL)
+ {
+ max = elf_elfheader (abfd)->e_shnum;
+ for (i = 1; i < max; i++)
+ {
+ if (!strcmp (&shstrtab[i_shdrp[i].sh_name], name))
+ {
+ gotit = &i_shdrp[i];
+ }
+ }
+ }
+ }
+ return (gotit);
+}
+
+/* End of GDB support. */
static char *
DEFUN(elf_get_str_section, (abfd, shindex),
bfd *abfd AND
unsigned int shindex)
{
- Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd);
- unsigned int shstrtabsize = i_shdrp[shindex].sh_size;
- unsigned int offset = i_shdrp[shindex].sh_offset;
- char *shstrtab;
- if ((shstrtab = elf_read (abfd, offset, shstrtabsize)) == NULL)
+ Elf_Internal_Shdr *i_shdrp;
+ char *shstrtab = NULL;
+ unsigned int offset;
+ unsigned int shstrtabsize;
+
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp != NULL)
{
- return (NULL);
+ shstrtab = i_shdrp[shindex].rawdata;
+ if (shstrtab == NULL)
+ {
+ /* No cached one, attempt to read, and cache what we read. */
+ offset = i_shdrp[shindex].sh_offset;
+ shstrtabsize = i_shdrp[shindex].sh_size;
+ shstrtab = elf_read (abfd, offset, shstrtabsize);
+ i_shdrp[shindex].rawdata = (void*) shstrtab;
+ }
}
- i_shdrp[shindex].rawdata = (void*)shstrtab;
-
+ return (shstrtab);
}
+
static char *
DEFUN(elf_string_from_elf_section, (abfd, shindex, strindex),
bfd *abfd AND
{
Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd);
Elf_Internal_Shdr *hdr = i_shdrp + shindex;
+
if (! hdr->rawdata)
{
if (elf_get_str_section (abfd, shindex) == NULL)
elf_string_from_elf_strtab (abfd, hdr->sh_name) : "unnamed";
switch(hdr->sh_type) {
+
case SHT_NULL:
/* inactive section. Throw it away. */
return true;
+
case SHT_PROGBITS:
case SHT_NOBITS:
/* Bits that get saved. This one is real. */
}
return true;
break;
- case SHT_SYMTAB:
- /* we may be getting called by reference. Bring'em in... */
- if (! hdr->rawdata) {
- /* fetch our corresponding string table. */
- bfd_section_from_shdr (abfd, hdr->sh_link);
-
- /* start turning our elf symbols into bfd symbols. */
- BFD_ASSERT (hdr->sh_entsize == sizeof (Elf_External_Sym));
- elf_slurp_symbol_table (abfd, hdr);
- abfd->flags |= HAS_SYMS;
-
- }
+
+ case SHT_SYMTAB: /* A symbol table */
+ BFD_ASSERT (hdr->sh_entsize == sizeof (Elf_External_Sym));
+ elf_onesymtab (abfd) = shindex;
+ abfd->flags |= HAS_SYMS;
return true;
- case SHT_STRTAB:
- /* we may be getting called by reference. Bring'em in... */
- if (! hdr->rawdata)
- {
- /* we don't need to do anything, just make the data available. */
- if (elf_get_str_section (abfd, shindex) == NULL)
- return false;
- }
+
+ case SHT_STRTAB: /* A string table */
return true;
+
case SHT_REL:
case SHT_RELA:
/* *these* do a lot of work -- but build no sections! */
/* the spec says there can be multiple strtabs, but only one symtab */
/* but there can be lots of REL* sections. */
+ /* FIXME: The above statement is wrong! There are typically at least
+ two symbol tables in a dynamically linked executable, ".dynsym"
+ which is the dynamic linkage symbol table and ".symtab", which is
+ the "traditional" symbol table. -fnf */
+
{
asection *target_sect;
- unsigned int idx;
bfd_section_from_shdr (abfd, hdr->sh_link); /* symbol table */
bfd_section_from_shdr (abfd, hdr->sh_info); /* target */
target_sect = section_from_elf_index (abfd, hdr->sh_info);
-
+ if (target_sect == NULL)
+ return false;
+
+#if 0
+ /* FIXME: We are only prepared to read one symbol table, so
+ do NOT read the dynamic symbol table since it is only a
+ subset of the full symbol table. Also see comment above. -fnf */
if (!elf_slurp_symbol_table(abfd, i_shdrp + hdr->sh_link))
return false;
+#endif
target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize;
target_sect->flags |= SEC_RELOC;
target_sect->relocation = 0;
target_sect->rel_filepos = hdr->sh_offset;
- fprintf(stderr, "ELF>> section %s reading %d relocs\n",
- target_sect->name, target_sect->reloc_count);
return true;
-
}
break;
+
case SHT_HASH:
case SHT_DYNAMIC:
case SHT_DYNSYM: /* could treat this like symtab... */
+#if 0
fprintf(stderr, "Dynamic Linking sections not yet supported.\n");
abort ();
+#endif
break;
+
case SHT_NOTE:
+#if 0
fprintf(stderr, "Note Sections not yet supported.\n");
abort ();
+#endif
break;
+
case SHT_SHLIB:
+#if 0
fprintf(stderr, "SHLIB Sections not supported (and non conforming.)\n");
+#endif
return true;
+
default:
break;
}
return (true);
}
-
+
struct strtab {
DEFUN(bfd_add_to_strtab, (abfd, ss, str),
bfd *abfd AND
struct strtab *ss AND
- char *str)
+ CONST char *str)
{
/* should search first, but for now: */
/* include the trailing NUL */
bfd *abfd AND
struct strtab *ss AND
char *str AND
- char *str2)
+ CONST char *str2)
{
/* should search first, but for now: */
/* include the trailing NUL */
(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);
+ strcpy (name, namebuf);
newsect = bfd_make_section (abfd, name);
newsect -> vma = hdr -> p_vaddr;
newsect -> _raw_size = hdr -> p_filesz;
{
sprintf (namebuf, "segment%db", index);
name = bfd_alloc (abfd, strlen (namebuf) + 1);
- (void) strcpy (name, namebuf);
+ strcpy (name, namebuf);
newsect = bfd_make_section (abfd, name);
newsect -> vma = hdr -> p_vaddr + hdr -> p_filesz;
newsect -> _raw_size = hdr -> p_memsz - hdr -> p_filesz;
{
if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) != NULL)
{
- bcopy (descdata, core_prpsinfo (abfd), descsz);
+ memcpy (core_prpsinfo (abfd), descdata, descsz);
}
}
}
if (hdr -> p_filesz > 0
&& (buf = (char *) bfd_xmalloc (hdr -> p_filesz)) != NULL
- && bfd_seek (abfd, hdr -> p_offset, SEEK_SET) != -1L
+ && bfd_seek (abfd, hdr -> p_offset, SEEK_SET) != -1
&& bfd_read ((PTR) buf, hdr -> p_filesz, 1, abfd) == hdr -> p_filesz)
{
x_note_p = (Elf_External_Note *) buf;
DEFUN (elf_object_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_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
Elf_External_Shdr x_shdr; /* Section header table entry, external form */
Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */
int shindex;
char *shstrtab; /* Internal copy of section header stringtab */
- Elf_Off offset; /* Temp place to stash file offsets */
/* Read in the ELF header in external format. */
/* Allocate an instance of the elf_obj_tdata structure and hook it up to
the tdata pointer in the bfd. */
- if ((abfd -> tdata.elf_obj_data =
- (elf_obj_tdata*) bfd_zalloc (abfd, sizeof (elf_obj_tdata)))
- == NULL)
+ if (NULL == (elf_tdata (abfd) = (struct elf_obj_tdata *)
+ bfd_zalloc (abfd, sizeof (struct elf_obj_tdata))))
{
bfd_error = no_memory;
return (NULL);
}
+ /* FIXME: Any `wrong' exits below here will leak memory (tdata). */
+
/* Now that we know the byte order, swap in the rest of the header */
- elf_swap_ehdr_in (abfd, &x_ehdr, &i_ehdr);
- /* FIXME: should be alloc'ed */
- elf_elfheader (abfd) = &i_ehdr;
+ i_ehdrp = elf_elfheader (abfd);
+ elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
/* If there is no section header table, we're hosed. */
- if (i_ehdr.e_shoff == 0)
+ if (i_ehdrp->e_shoff == 0)
goto wrong;
- if (i_ehdr.e_type == ET_EXEC || i_ehdr.e_type == ET_DYN)
+ if (i_ehdrp->e_type == ET_EXEC || i_ehdrp->e_type == ET_DYN)
abfd -> flags |= EXEC_P;
- switch (i_ehdr.e_machine)
+ switch (i_ehdrp->e_machine)
{
case EM_NONE:
case EM_M32: /* or should this be bfd_arch_obscure? */
check, verify that the what BFD thinks is the size of each section
header table entry actually matches the size recorded in the file. */
- if (i_ehdr.e_shentsize != sizeof (x_shdr))
+ if (i_ehdrp->e_shentsize != sizeof (x_shdr))
goto wrong;
i_shdrp = (Elf_Internal_Shdr *)
- bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdr.e_shnum);
+ bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum);
if (! i_shdrp)
{
bfd_error = no_memory;
return (NULL);
}
- if (bfd_seek (abfd, i_ehdr.e_shoff, SEEK_SET) == -1)
+ if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) == -1)
{
bfd_error = system_call_error;
return (NULL);
}
- for (shindex = 0; shindex < i_ehdr.e_shnum; shindex++)
+ for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++)
{
if (bfd_read ((PTR) &x_shdr, sizeof x_shdr, 1, abfd)
!= sizeof (x_shdr))
bfd_section_from_shdr with it (since this particular strtab is
used to find all of the ELF section names.) */
- shstrtab = elf_get_str_section (abfd, i_ehdr.e_shstrndx);
+ shstrtab = elf_get_str_section (abfd, i_ehdrp->e_shstrndx);
if (! shstrtab)
return (NULL);
offset and section size for both the symbol table section and the
associated string table section. */
- for (shindex = 1; shindex < i_ehdr.e_shnum; shindex++)
+ for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
{
bfd_section_from_shdr (abfd, shindex);
}
/* Remember the entry point specified in the ELF file header. */
- bfd_get_start_address (abfd) = i_ehdr.e_entry;
+ bfd_get_start_address (abfd) = i_ehdrp->e_entry;
return (abfd->xvec);
}
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_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
Elf_External_Phdr x_phdr; /* Program header table entry, external form */
Elf_Internal_Phdr *i_phdrp; /* Program header table, internal form */
unsigned int phindex;
goto wrong;
}
- /* Now that we know the byte order, swap in the rest of the header */
- elf_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 an instance of the elf_core_tdata structure and hook it up to
+ /* Allocate an instance of the elf_obj_tdata structure and hook it up to
the tdata pointer in the bfd. */
- abfd->tdata.elf_core_data =
- (elf_core_tdata *) bfd_zalloc (abfd, sizeof (elf_core_tdata));
- if (abfd->tdata.elf_core_data == NULL)
+ elf_tdata (abfd) =
+ (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+ if (elf_tdata (abfd) == NULL)
{
bfd_error = no_memory;
return (NULL);
}
+ /* FIXME, `wrong' returns from this point onward, leak memory. */
+
+ /* Now that we know the byte order, swap in the rest of the header */
+ i_ehdrp = elf_elfheader (abfd);
+ elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
+
+ /* If there is no program header, or the type is not a core file, then
+ we are hosed. */
+ if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
+ goto wrong;
+
/* Allocate space for a copy of the program header table in
- internal form, seek to the program header table in the file,
+ 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))
+ if (i_ehdrp->e_phentsize != sizeof (x_phdr))
goto wrong;
i_phdrp = (Elf_Internal_Phdr *)
- bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdr.e_phnum);
+ bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum);
if (! i_phdrp)
{
bfd_error = no_memory;
return (NULL);
}
- if (bfd_seek (abfd, i_ehdr.e_phoff, SEEK_SET) == -1)
+ if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
{
bfd_error = system_call_error;
return (NULL);
}
- for (phindex = 0; phindex < i_ehdr.e_phnum; phindex++)
+ for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
{
if (bfd_read ((PTR) &x_phdr, sizeof (x_phdr), 1, abfd)
!= sizeof (x_phdr))
/* 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++)
+ for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
{
bfd_section_from_phdr (abfd, i_phdrp + phindex, phindex);
if ((i_phdrp + phindex) -> p_type == PT_NOTE)
/* Remember the entry point specified in the ELF file header. */
- bfd_get_start_address (abfd) = i_ehdr.e_entry;
+ bfd_get_start_address (abfd) = i_ehdrp->e_entry;
return (abfd->xvec);
}
{
/* this just does initialization */
/* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
- elf_tdata(abfd) = (elf_obj_tdata *)
- bfd_zalloc (abfd, sizeof(elf_obj_tdata));
+ elf_tdata(abfd) = (struct elf_obj_tdata *)
+ bfd_zalloc (abfd, sizeof(struct elf_obj_tdata));
if (elf_tdata(abfd) == 0) {
bfd_error = no_memory;
return false;
rela_hdr->sh_entsize = sizeof (Elf_External_Rela);
/* orelocation has the data, reloc_count has the count... */
rela_hdr->sh_size = rela_hdr->sh_entsize * asect->reloc_count;
- fprintf(stderr,"ELF>> sending out %d relocs to %s\n",
- asect->reloc_count, asect->name);
outbound_relocs = (Elf_External_Rela *)
bfd_alloc(abfd, asect->reloc_count * sizeof(Elf_External_Rela));
for (idx = 0; idx < asect->reloc_count; idx++)
elf_sect_thunk est;
if (! elf_shstrtab (abfd)) {
- i_ehdrp = (Elf_Internal_Ehdr *)
- bfd_alloc (abfd, sizeof (*i_ehdrp));
- shstrtab = bfd_new_strtab(abfd);
-
- i_ehdrp->e_ident[EI_MAG0] = ELFMAG0;
- i_ehdrp->e_ident[EI_MAG1] = ELFMAG1;
- i_ehdrp->e_ident[EI_MAG2] = ELFMAG2;
- i_ehdrp->e_ident[EI_MAG3] = ELFMAG3;
-
- i_ehdrp->e_ident[EI_CLASS] = ELFCLASS32; /* FIXME: find out from bfd */
- i_ehdrp->e_ident[EI_DATA] =
- abfd->xvec->byteorder_big_p ? ELFDATA2MSB : ELFDATA2LSB;
- i_ehdrp->e_ident[EI_VERSION] = EV_CURRENT;
-
- for(count = EI_PAD; count < EI_NIDENT; count ++)
- i_ehdrp->e_ident[count] = 0;
+ i_ehdrp = elf_elfheader (abfd); /* build new header in tdata memory */
+ shstrtab = bfd_new_strtab(abfd);
- i_ehdrp->e_type = (abfd->flags & EXEC_P)? ET_EXEC : ET_REL;
- switch(bfd_get_arch(abfd))
- {
- case bfd_arch_unknown:
- i_ehdrp->e_machine = EM_NONE;
- break;
- case bfd_arch_sparc:
- i_ehdrp->e_machine = EM_SPARC;
- break;
- case bfd_arch_i386:
- i_ehdrp->e_machine = EM_386;
- break;
- case bfd_arch_m68k:
- i_ehdrp->e_machine = EM_68K;
- break;
- case bfd_arch_m88k:
- i_ehdrp->e_machine = EM_88K;
- break;
- case bfd_arch_i860:
- i_ehdrp->e_machine = EM_860;
- break;
- case bfd_arch_mips: /* MIPS Rxxxx */
- i_ehdrp->e_machine = EM_MIPS; /* only MIPS R3000 */
- break;
- /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
- default:
- i_ehdrp->e_machine = EM_NONE;
- }
- i_ehdrp->e_version = EV_CURRENT;
- i_ehdrp->e_ehsize = sizeof(Elf_External_Ehdr);
-
- /* no program header, for now. */
- i_ehdrp->e_phoff = 0;
- i_ehdrp->e_phentsize = 0;
- i_ehdrp->e_phnum = 0;
+ i_ehdrp->e_ident[EI_MAG0] = ELFMAG0;
+ i_ehdrp->e_ident[EI_MAG1] = ELFMAG1;
+ i_ehdrp->e_ident[EI_MAG2] = ELFMAG2;
+ i_ehdrp->e_ident[EI_MAG3] = ELFMAG3;
+
+ i_ehdrp->e_ident[EI_CLASS] = ELFCLASS32; /* FIXME: find out from bfd */
+ i_ehdrp->e_ident[EI_DATA] =
+ abfd->xvec->byteorder_big_p ? ELFDATA2MSB : ELFDATA2LSB;
+ i_ehdrp->e_ident[EI_VERSION] = EV_CURRENT;
+
+ for(count = EI_PAD; count < EI_NIDENT; count ++)
+ i_ehdrp->e_ident[count] = 0;
+
+ i_ehdrp->e_type = (abfd->flags & EXEC_P)? ET_EXEC : ET_REL;
+ switch(bfd_get_arch(abfd))
+ {
+ case bfd_arch_unknown:
+ i_ehdrp->e_machine = EM_NONE;
+ break;
+ case bfd_arch_sparc:
+ i_ehdrp->e_machine = EM_SPARC;
+ break;
+ case bfd_arch_i386:
+ i_ehdrp->e_machine = EM_386;
+ break;
+ case bfd_arch_m68k:
+ i_ehdrp->e_machine = EM_68K;
+ break;
+ case bfd_arch_m88k:
+ i_ehdrp->e_machine = EM_88K;
+ break;
+ case bfd_arch_i860:
+ i_ehdrp->e_machine = EM_860;
+ break;
+ case bfd_arch_mips: /* MIPS Rxxxx */
+ i_ehdrp->e_machine = EM_MIPS; /* only MIPS R3000 */
+ break;
+ /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
+ default:
+ i_ehdrp->e_machine = EM_NONE;
+ }
+ i_ehdrp->e_version = EV_CURRENT;
+ i_ehdrp->e_ehsize = sizeof(Elf_External_Ehdr);
+
+ /* no program header, for now. */
+ i_ehdrp->e_phoff = 0;
+ i_ehdrp->e_phentsize = 0;
+ i_ehdrp->e_phnum = 0;
- /* each bfd section is section header entry */
- i_ehdrp->e_entry = bfd_get_start_address (abfd);
- i_ehdrp->e_shentsize = sizeof (Elf_External_Shdr);
+ /* each bfd section is section header entry */
+ i_ehdrp->e_entry = bfd_get_start_address (abfd);
+ i_ehdrp->e_shentsize = sizeof (Elf_External_Shdr);
- /* can't do this: we'll need many more... */
- /* i_ehdr.e_shnum = bfd_count_sections(abfd)+1; /* include 0th, shstrtab */
- /* figure at most each section can have a rel, strtab, symtab */
- maxsections = 4*bfd_count_sections(abfd)+2;
+ /* figure at most each section can have a rel, strtab, symtab */
+ maxsections = 4*bfd_count_sections(abfd)+2;
- i_ehdrp->e_shoff = i_ehdrp->e_ehsize;
+ i_ehdrp->e_shoff = i_ehdrp->e_ehsize;
- /* and we'll just have to fix up the offsets later. */
- /* outbase += i_ehdr.e_shentsize * i_ehdr.e_shnum; */
-
- i_shdrp = (Elf_Internal_Shdr *)
- bfd_alloc (abfd, sizeof (*i_shdrp) * maxsections);
- if (! i_shdrp)
- {
- bfd_error = no_memory;
- return (NULL);
- }
- for (count=0; count < maxsections; count++)
- {
- i_shdrp[count].rawdata = 0;
- i_shdrp[count].contents = 0;
- }
-
-
- i_shdrp[0].sh_name = 0;
- i_shdrp[0].sh_type = SHT_NULL;
- i_shdrp[0].sh_flags = 0;
- i_shdrp[0].sh_addr = 0;
- i_shdrp[0].sh_offset = 0;
- i_shdrp[0].sh_size = 0;
- i_shdrp[0].sh_link = SHN_UNDEF;
- i_shdrp[0].sh_info = 0;
- i_shdrp[0].sh_addralign = 0;
- i_shdrp[0].sh_entsize = 0;
-
- i_ehdrp->e_shnum = 1;
-
- elf_elfheader (abfd) = i_ehdrp;
- elf_elfsections (abfd) = i_shdrp;
- elf_shstrtab (abfd) = shstrtab;
+ /* and we'll just have to fix up the offsets later. */
+ /* outbase += i_ehdr.e_shentsize * i_ehdr.e_shnum; */
+
+ i_shdrp = (Elf_Internal_Shdr *)
+ bfd_alloc (abfd, sizeof (*i_shdrp) * maxsections);
+ if (! i_shdrp)
+ {
+ bfd_error = no_memory;
+ return (false);
+ }
+ for (count=0; count < maxsections; count++)
+ {
+ i_shdrp[count].rawdata = 0;
+ i_shdrp[count].contents = 0;
+ }
+
+
+ i_shdrp[0].sh_name = 0;
+ i_shdrp[0].sh_type = SHT_NULL;
+ i_shdrp[0].sh_flags = 0;
+ i_shdrp[0].sh_addr = 0;
+ i_shdrp[0].sh_offset = 0;
+ i_shdrp[0].sh_size = 0;
+ i_shdrp[0].sh_link = SHN_UNDEF;
+ i_shdrp[0].sh_info = 0;
+ i_shdrp[0].sh_addralign = 0;
+ i_shdrp[0].sh_entsize = 0;
+
+ i_ehdrp->e_shnum = 1;
+
+ elf_elfsections (abfd) = i_shdrp;
+ elf_shstrtab (abfd) = shstrtab;
}
est.i_ehdr = elf_elfheader(abfd);
est.i_shdrp = elf_elfsections(abfd);
bfd_map_over_sections(abfd, elf_fake_sections, &est);
elf_onesymtab (abfd) = est.symtab_section;
+ return (true);
}
static boolean
symtab_hdr->sh_link = symstrtab_section;
symstrtab_hdr->sh_type = SHT_STRTAB;
- fprintf(stderr,"ELF>> sending out %d syms\n",symcount);
outbound_syms = (Elf_External_Sym*)
bfd_alloc(abfd, (1+symcount) * sizeof(Elf_External_Sym));
/* now generate the data (for "contents") */
sym.st_info = ELF_ST_INFO(STB_LOCAL, STT_OBJECT);
else if (syms[idx]->flags & BSF_GLOBAL)
sym.st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
+ else if (syms[idx]->flags & BSF_SECTION_SYM)
+ sym.st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION);
+ else if (syms[idx]->flags & BSF_FILE)
+ sym.st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
sym.st_other = 0;
if (syms[idx]->section)
/* swap the header before spitting it out... */
elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr);
- bfd_seek (abfd, 0L, SEEK_SET);
+ bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
bfd_write ((PTR) &x_ehdr, sizeof(x_ehdr), 1, abfd);
outbase += i_ehdrp->e_shentsize * i_ehdrp->e_shnum;
if (! x_shdrp)
{
bfd_error = no_memory;
- return (NULL);
+ return (false);
}
- fprintf(stderr, "ELF>> total sections: %d\n", i_ehdrp->e_shnum);
for (count = 0; count < i_ehdrp->e_shnum; count ++)
{
elf_swap_shdr_out (abfd, i_shdrp+count, x_shdrp+count);
{
if(i_shdrp[count].contents)
{
- fprintf(stderr, "found some userdata: count %d, pos 0x%x\n",
- count, i_shdrp[count].sh_offset);
bfd_seek (abfd, i_shdrp[count].sh_offset, SEEK_SET);
bfd_write (i_shdrp[count].contents, i_shdrp[count].sh_size, 1, abfd);
}
}
/* sample use of bfd:
- * bfd_seek (abfd, 0L, false);
+ * bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
* bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd);
* if (bfd_seek(abfd, scn_base, SEEK_SET) != 0)
* return false;
return (struct sec *)hdr->rawdata;
break;
default:
- return 0;
+ return (struct sec *)&bfd_abs_section;
}
}
}
static boolean
-DEFUN (elf_slurp_symbol_table, (abfd, hdr),
+DEFUN (elf_slurp_symbol_table, (abfd, symptrs),
bfd *abfd AND
- Elf_Internal_Shdr *hdr)
+ asymbol **symptrs) /* Buffer for generated bfd symbols */
{
+ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd);
+ Elf_Internal_Shdr *hdr = i_shdrp + elf_onesymtab (abfd);
int symcount; /* Number of external ELF symbols */
- char *strtab; /* Buffer for raw ELF string table section */
+ int i;
asymbol *sym; /* Pointer to current bfd symbol */
asymbol *symbase; /* Buffer for generated bfd symbols */
- asymbol **vec; /* Pointer to current bfd symbol pointer */
Elf_Internal_Sym i_sym;
- Elf_External_Sym x_sym;
Elf_External_Sym *x_symp;
- unsigned int *table_ptr; /* bfd symbol translation table */
/* this is only valid because there is only one symtab... */
+ /* FIXME: This is incorrect, there may also be a dynamic symbol
+ table which is a subset of the full symbol table. We either need
+ to be prepared to read both (and merge them) or ensure that we
+ only read the full symbol table. Currently we only get called to
+ read the full symbol table. -fnf */
if (bfd_get_outsymbols (abfd) != NULL)
{
return (true);
Note that we allocate the initial bfd canonical symbol buffer
based on a one-to-one mapping of the ELF symbols to canonical
- symbols. However, it is likely that not all the ELF symbols will
- be used, so there will be some space leftover at the end. Once
- we know how many symbols we actual generate, we realloc the buffer
- to the correct size and then build the pointer vector. */
+ symbols. We actually use all the ELF symbols, so there will be no
+ space left over at the end. When we have all the symbols, we
+ build the caller's pointer vector. */
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
{
}
symcount = hdr->sh_size / sizeof (Elf_External_Sym);
- sym = symbase = (asymbol *) bfd_zalloc (abfd, symcount * sizeof (asymbol));
- x_symp = (Elf_External_Sym *)
- bfd_zalloc (abfd, symcount * sizeof (Elf_External_Sym));
+ symbase = (asymbol *) bfd_zalloc (abfd, symcount * sizeof (asymbol));
+ sym = symbase;
+
+ /* Temporarily allocate room for the raw ELF symbols. */
+ x_symp = (Elf_External_Sym *) malloc (symcount * sizeof (Elf_External_Sym));
if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
!= symcount * sizeof (Elf_External_Sym))
{
+ free ((PTR)x_symp);
bfd_error = system_call_error;
return (false);
}
- while (symcount-- > 0)
+ /* Skip first symbol, which is a null dummy. */
+ for (i = 1; i < symcount; i++)
{
- elf_swap_symbol_in (abfd, x_symp + symcount, &i_sym);
+ elf_swap_symbol_in (abfd, x_symp + i, &i_sym);
+ sym -> the_bfd = abfd;
if (i_sym.st_name > 0)
+ sym -> name = elf_string_from_elf_section(abfd, hdr->sh_link,
+ i_sym.st_name);
+ else
+ sym -> name = "unnamed"; /* perhaps should include the number? */
+ sym -> value = i_sym.st_value;
+/* FIXME -- this is almost certainly bogus. It's from Pace Willisson's
+hasty Solaris support, to pass the sizes of object files or functions
+down into GDB via the back door, to circumvent some other kludge in
+how Sun hacked stabs. -- gnu@cygnus.com */
+ sym -> udata = (PTR)i_sym.st_size;
+/* FIXME -- end of bogosity. */
+ if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERV)
{
- sym -> the_bfd = abfd;
- sym -> name = elf_string_from_elf_section(abfd, hdr->sh_link,
- i_sym.st_name);
- sym -> value = i_sym.st_value;
- if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERV)
- {
- sym -> section = section_from_elf_index (abfd, i_sym.st_shndx);
- }
- else if (i_sym.st_shndx == SHN_ABS)
- {
- sym -> section = &bfd_abs_section;
- }
- else if (i_sym.st_shndx == SHN_COMMON)
- {
- sym -> section = &bfd_com_section;
- }
- else if (i_sym.st_shndx == SHN_UNDEF)
- {
- sym -> section = &bfd_und_section;
- }
-
- switch (ELF_ST_BIND (i_sym.st_info))
- {
- case STB_LOCAL:
- sym -> flags |= BSF_LOCAL;
- break;
- case STB_GLOBAL:
- sym -> flags |= (BSF_GLOBAL | BSF_EXPORT);
- break;
- case STB_WEAK:
- sym -> flags |= BSF_WEAK;
- break;
- }
- sym++;
+ sym -> section = section_from_elf_index (abfd, i_sym.st_shndx);
}
- else
+ else if (i_sym.st_shndx == SHN_ABS)
{
- /* let's try *not* punting unnamed symbols... */
- sym -> the_bfd = abfd;
- sym -> name = "unnamed"; /* perhaps should include the number? */
- sym -> value = i_sym.st_value;
- if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERV)
- {
- sym -> section = section_from_elf_index (abfd, i_sym.st_shndx);
- }
- else if (i_sym.st_shndx == SHN_ABS)
- {
- sym -> section = &bfd_abs_section;
- }
- else if (i_sym.st_shndx == SHN_COMMON)
- {
- sym -> section = &bfd_com_section;
- }
- else if (i_sym.st_shndx == SHN_UNDEF)
- {
- sym -> section = &bfd_und_section;
- }
-
- switch (ELF_ST_BIND (i_sym.st_info))
- {
- case STB_LOCAL:
- sym -> flags |= BSF_LOCAL;
- break;
- case STB_GLOBAL:
- sym -> flags |= (BSF_GLOBAL | BSF_EXPORT);
- break;
- case STB_WEAK:
- sym -> flags |= BSF_WEAK;
- break;
- }
- sym++;
+ sym -> section = &bfd_abs_section;
+ }
+ else if (i_sym.st_shndx == SHN_COMMON)
+ {
+ sym -> section = &bfd_com_section;
+ }
+ else if (i_sym.st_shndx == SHN_UNDEF)
+ {
+ sym -> section = &bfd_und_section;
+ }
+ else
+ sym -> section = &bfd_abs_section;
+
+ switch (ELF_ST_BIND (i_sym.st_info))
+ {
+ case STB_LOCAL:
+ sym -> flags |= BSF_LOCAL;
+ break;
+ case STB_GLOBAL:
+ sym -> flags |= (BSF_GLOBAL | BSF_EXPORT);
+ break;
+ case STB_WEAK:
+ sym -> flags |= BSF_WEAK;
+ break;
+ }
+ switch (ELF_ST_TYPE (i_sym.st_info))
+ {
+ case STT_SECTION:
+ sym->flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
+ break;
+ case STT_FILE:
+ sym->flags |= BSF_FILE | BSF_DEBUGGING;
+ break;
}
+ sym++;
}
- bfd_get_symcount(abfd) = symcount = sym - symbase;
- sym = symbase = (asymbol *)
- bfd_realloc (abfd, symbase, symcount * sizeof (asymbol));
- bfd_get_outsymbols(abfd) = vec = (asymbol **)
- bfd_alloc (abfd, symcount * sizeof (asymbol *));
+ /* We rely on the zalloc to clear out the final symbol entry. */
+
+ /* We're now done with the raw symbols. */
+ free ((PTR)x_symp);
- while (symcount-- > 0)
+ bfd_get_symcount(abfd) = symcount = sym - symbase;
+
+ /* Fill in the user's symbol pointer vector if needed. */
+ if (symptrs)
{
- *vec++ = sym++;
+ sym = symbase;
+ while (symcount-- > 0)
+ {
+ *symptrs++ = sym++;
+ }
+ *symptrs = 0; /* Final null pointer */
}
return (true);
/* Return the number of bytes required to hold the symtab vector.
Note that we base it on the count plus 1, since we will null terminate
- the vector allocated based on this size. */
+ the vector allocated based on this size. However, the ELF symbol table
+ always has a dummy entry as symbol #0, so it ends up even. */
static unsigned int
DEFUN (elf_get_symtab_upper_bound, (abfd), bfd *abfd)
{
+ unsigned int symcount;
unsigned int symtab_size = 0;
+ Elf_Internal_Shdr *i_shdrp;
+ Elf_Internal_Shdr *hdr;
- /* if (elf_slurp_symbol_table (abfd, ???)) */
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp != NULL)
{
- symtab_size = (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol));
+ hdr = i_shdrp + elf_onesymtab (abfd);
+ symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+ symtab_size = (symcount - 1 + 1) * (sizeof (asymbol));
}
return (symtab_size);
}
return true;
if (asect->flags & SEC_CONSTRUCTOR)
return true;
- /* if (!elf_slurp_symbol_table(abfd))
- return false; -- should be done by now */
bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
native_relocs = (Elf_External_Rela *)
bfd_alloc(abfd, asect->reloc_count * sizeof(Elf_External_Rela));
- fprintf(stderr, "ELF>> really reading %d relocs for section %s\n",
- asect->reloc_count, asect->name);
bfd_read ((PTR) native_relocs,
sizeof(Elf_External_Rela), asect->reloc_count, abfd);
RELOC_PROCESSING(cache_ptr, &dst, symbols, abfd, asect);
#else
Elf_Internal_Rela dst;
- asymbol *ptr;
Elf_External_Rela *src;
cache_ptr = reloc_cache + idx;
/* ELF_R_SYM(dst.r_info) is the symbol table offset... */
cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM(dst.r_info);
cache_ptr->addend = dst.r_addend;
- /* ptr = *(cache_ptr->sym_ptr_ptr); */
/* Fill in the cache_ptr->howto field from dst.r_type */
elf_info_to_howto(abfd, cache_ptr, &dst);
bfd *abfd AND
asymbol **alocation)
{
- unsigned int symcount;
- asymbol **vec;
-/* if (!elf_slurp_symbol_table (abfd))
+ if (!elf_slurp_symbol_table (abfd, alocation))
return (0);
- else */
- {
- symcount = bfd_get_symcount (abfd);
- vec = bfd_get_outsymbols (abfd);
- while (symcount-- > 0)
- {
- *alocation++ = *vec++;
- }
- *alocation++ = NULL;
- return (bfd_get_symcount (abfd));
- }
+ else
+ return (bfd_get_symcount (abfd));
}
static asymbol *
case bfd_print_symbol_nm:
case bfd_print_symbol_all:
{
- char *section_name;
+ CONST char *section_name;
section_name = symbol->section? symbol->section->name : "(*none*)";
bfd_print_symbol_vandf((PTR) file, symbol);
- fprintf(file, " %-5s %s %s %s",
+ fprintf(file, " %s\t%s",
section_name,
- " ", " ",
symbol->name);
}
break;
one for little-endian machines. */
/* Archives are generic or unimplemented. */
-#define elf_slurp_armap bfd_false
+#define elf_slurp_armap bfd_slurp_coff_armap
#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, unsigned int orl_count, \
- int stridx))) bfd_false
+#define elf_write_armap coff_write_armap
/* Ordinary section reading and writing */
#define elf_new_section_hook _bfd_dummy_new_section_hook
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY |
SEC_CODE | SEC_DATA),
+ /* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ 0,
+
/* ar_pad_char: pad character for filenames within an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and/or os and should be independently tunable */
bfd_false
},
- /* Initialize a jump table with the standard macro. All names start
- with "elf" */
+ /* Initialize a jump table with the standard macro. All names start with
+ "elf" */
JUMP_TABLE(elf),
- /* SWAP_TABLE */
- NULL, NULL, NULL
+ /* reloc_type_lookup: How applications can find out about amiga relocation
+ types (see documentation on reloc types). */
+ NULL,
+
+ /* _bfd_make_debug_symbol: Back-door to allow format aware applications to
+ create debug symbols while using BFD for everything else. */
+ NULL,
+
+ /* backend_data: */
+ NULL
};
bfd_target elf_little_vec =
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY |
SEC_DATA),
+ /* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ 0,
+
/* ar_pad_char: pad character for filenames within an archive header
FIXME: this really has nothing to do with ELF, this is a characteristic
of the archiver and/or os and should be independently tunable */
bfd_false
},
- /* Initialize a jump table with the standard macro. All names start
- with "elf" */
+ /* Initialize a jump table with the standard macro. All names start with
+ "elf" */
JUMP_TABLE(elf),
- /* SWAP_TABLE */
- NULL, NULL, NULL
+ /* reloc_type_lookup: How applications can find out about amiga relocation
+ types (see documentation on reloc types). */
+ NULL,
+
+ /* _bfd_make_debug_symbol: Back-door to allow format aware applications to
+ create debug symbols while using BFD for everything else. */
+ NULL,
+
+ /* backend_data: */
+ NULL
};