once in 64-bit mode. More of it should be made size-independent
and moved into elf.c.
-*/
+ (3) ELF section symbols are handled rather sloppily now. This should
+ be cleaned up, and ELF section symbols reconciled with BFD section
+ symbols.
+ */
#include <assert.h>
#include <string.h> /* For strrchr and friends */
#include "libbfd.h"
#include "libelf.h"
+#ifndef alloca
+PTR alloca ();
+#endif
+
/* Renaming structures, typedefs, macros and functions to be size-specific. */
#define Elf_External_Ehdr NAME(Elf,External_Ehdr)
#define Elf_External_Sym NAME(Elf,External_Sym)
#define Elf_External_Rel NAME(Elf,External_Rel)
#define Elf_External_Rela NAME(Elf,External_Rela)
-#define elf_symbol_type NAME(elf,symbol_type)
-
#define elf_core_file_failing_command NAME(bfd_elf,core_file_failing_command)
#define elf_core_file_failing_signal NAME(bfd_elf,core_file_failing_signal)
#define elf_core_file_matches_executable_p NAME(bfd_elf,core_file_matches_executable_p)
#define elf_set_section_contents NAME(bfd_elf,set_section_contents)
#define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto)
#define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel)
-#define elf_hash NAME(bfd_elf,hash)
#define elf_new_section_hook NAME(bfd_elf,new_section_hook)
#define write_relocs NAME(bfd_elf,_write_relocs)
+#define elf_find_section NAME(bfd_elf,find_section)
#if ARCH_SIZE == 64
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y)
#define ELF_R_SYM(X) ELF64_R_SYM(X)
#define ELFCLASS ELFCLASS64
+#define FILE_ALIGN 8
#endif
#if ARCH_SIZE == 32
#define ELF_R_INFO(X,Y) ELF32_R_INFO(X,Y)
#define ELF_R_SYM(X) ELF32_R_SYM(X)
#define ELFCLASS ELFCLASS32
-#endif
-
-#ifndef INLINE
-#if __GNUC__ >= 2
-#define INLINE __inline__
-#else
-#define INLINE
-#endif
+#define FILE_ALIGN 4
#endif
static int shstrtab_length_fixed;
if (hdr->sh_flags & SHF_EXECINSTR)
newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */
- else
+ else if (newsect->flags & SEC_ALLOC)
newsect->flags |= SEC_DATA;
+ /* The debugging sections appear to recognized only by
+ name. */
+ if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0
+ || strncmp (name, ".line", sizeof ".line" - 1) == 0
+ || strncmp (name, ".stab", sizeof ".stab" - 1) == 0)
+ newsect->flags |= SEC_DEBUGGING;
+
hdr->rawdata = (void *) newsect;
}
else
if (!(hdr->sh_flags & SHF_WRITE))
newsect->flags |= SEC_READONLY;
+ /* FIXME: This section is empty. Does it really make
+ sense to set SEC_CODE for it? */
if (hdr->sh_flags & SHF_EXECINSTR)
newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */
- else
- newsect->flags |= SEC_DATA;
hdr->rawdata = (void *) newsect;
}
newsect->_raw_size = hdr->sh_size;
newsect->alignment_power = 0;
newsect->vma = 0;
+ newsect->filepos = hdr->sh_offset;
if (hdr->sh_flags & SHF_ALLOC)
newsect->flags |= SEC_ALLOC|SEC_LOAD;
newsect->flags |= SEC_READONLY;
if (hdr->sh_flags & SHF_EXECINSTR)
newsect->flags |= SEC_CODE;
- else
+ else if (newsect->flags & SEC_ALLOC)
newsect->flags |= SEC_DATA;
+
+ /* Check for debugging string tables. */
+ if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0
+ || strncmp (name, ".stab", sizeof ".stab" - 1) == 0)
+ newsect->flags |= SEC_DEBUGGING;
}
return true;
bfd_section_from_shdr (abfd, hdr->sh_info); /* target */
bfd_section_from_shdr (abfd, hdr->sh_link); /* symbol table */
target_sect = section_from_elf_index (abfd, hdr->sh_info);
- if (target_sect == NULL)
+ if (target_sect == NULL
+ || elf_section_data (target_sect) == NULL)
return false;
hdr2 = &elf_section_data (target_sect)->rel_hdr;
return true;
default:
+ /* Check for any processor-specific section types. */
+ {
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (bed->elf_backend_section_from_shdr)
+ (*bed->elf_backend_section_from_shdr) (abfd, hdr, name);
+ }
break;
}
AND asection *sec)
{
struct bfd_elf_section_data *sdata;
- sec->used_by_bfd = sdata = bfd_alloc (abfd, sizeof (*sdata));
+
+ sdata = (struct bfd_elf_section_data *) bfd_alloc (abfd, sizeof (*sdata));
+ sec->used_by_bfd = (PTR) sdata;
memset (sdata, 0, sizeof (*sdata));
return true;
}
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
}
+/* Check to see if the file associated with ABFD matches the target vector
+ that ABFD points to.
+
+ Note that we may be called several times with the same ABFD, but different
+ target vectors, most of which will not match. We have to avoid leaving
+ any side effects in ABFD, or any data it points to (like tdata), if the
+ file does not match the target vector.
+
+ FIXME: There is memory leak if we are called more than once with the same
+ ABFD, and that bfd already has tdata allocated, since we allocate more tdata
+ and the old tdata is orphaned. Since it's in the bfd obstack, there isn't
+ much we can do about this except possibly rewrite the code. There are
+ also other bfd_allocs that may be the source of memory leaks as well. */
+
bfd_target *
DEFUN (elf_object_p, (abfd), bfd * abfd)
{
Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */
int shindex;
char *shstrtab; /* Internal copy of section header stringtab */
- struct elf_backend_data *ebd; /* Use to get ELF_ARCH stored in xvec */
+ struct elf_backend_data *ebd;
+ struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
/* 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;
- }
+ goto got_system_call_error;
/* 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')
section header table (FIXME: See comments re sections at top of this
file). */
- if (elf_file_p (&x_ehdr) == false)
- {
- wrong:
- bfd_error = wrong_format;
- return NULL;
- }
-
- if (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT)
- goto wrong;
-
- if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
- goto wrong;
+ if ((elf_file_p (&x_ehdr) == false) ||
+ (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) ||
+ (x_ehdr.e_ident[EI_CLASS] != ELFCLASS))
+ goto got_wrong_format_error;
- /* Switch xvec to match the specified byte order. */
+ /* Check that file's byte order matches xvec's */
switch (x_ehdr.e_ident[EI_DATA])
{
case ELFDATA2MSB: /* Big-endian */
if (!abfd->xvec->header_byteorder_big_p)
- goto wrong;
+ goto got_wrong_format_error;
break;
case ELFDATA2LSB: /* Little-endian */
if (abfd->xvec->header_byteorder_big_p)
- goto wrong;
+ goto got_wrong_format_error;
break;
case ELFDATANONE: /* No data encoding specified */
default: /* Unknown data encoding specified */
- goto wrong;
+ goto got_wrong_format_error;
}
/* Allocate an instance of the elf_obj_tdata structure and hook it up to
- the tdata pointer in the bfd. */
-
- if (NULL == (elf_tdata (abfd) = (struct elf_obj_tdata *)
- bfd_zalloc (abfd, sizeof (struct elf_obj_tdata))))
- {
- bfd_error = no_memory;
- return NULL;
- }
+ the tdata pointer in the bfd. FIXME: memory leak, see above. */
- /* FIXME: Any `wrong' exits below here will leak memory (tdata). */
+ elf_tdata (abfd) =
+ (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+ if (elf_tdata (abfd) == NULL)
+ goto got_no_memory_error;
/* Now that we know the byte order, swap in the rest of the header */
i_ehdrp = elf_elfheader (abfd);
/* If there is no section header table, we're hosed. */
if (i_ehdrp->e_shoff == 0)
- goto wrong;
+ goto got_wrong_format_error;
- if (i_ehdrp->e_type == ET_EXEC || i_ehdrp->e_type == ET_DYN)
- abfd->flags |= EXEC_P;
-
- /* Retrieve the architecture information from the xvec and verify
- that it matches the machine info stored in the ELF header.
- This allows us to resolve ambiguous formats that might not
- otherwise be distinguishable. */
+ /* As a simple sanity 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_ehdrp->e_shentsize != sizeof (x_shdr))
+ goto got_wrong_format_error;
ebd = get_elf_backend_data (abfd);
- /* Perhaps the elf architecture value should be another field in the
- elf backend data? If you change this to work that way, make sure
- that you still get bfd_arch_unknown for unknown architecture types,
- and that it still gets accepted by the `generic' elf target. */
- {
- int i;
- enum bfd_architecture arch = bfd_arch_unknown;
+ /* Check that the ELF e_machine field matches what this particular
+ BFD format expects. */
+ if (ebd->elf_machine_code != i_ehdrp->e_machine)
+ {
+ bfd_target **target_ptr;
- for (i = 0; i < bfd_elf_arch_map_size; i++)
- {
- if (bfd_elf_arch_map[i].elf_arch == i_ehdrp->e_machine)
- {
- arch = bfd_elf_arch_map[i].bfd_arch;
- break;
- }
- }
- /* start-sanitize-v9 */
- if (i_ehdrp->e_machine == EM_SPARC64)
- arch = bfd_arch_sparc;
- /* end-sanitize-v9 */
- if (ebd->arch != arch)
- goto wrong;
- bfd_default_set_arch_mach (abfd, arch, 0);
- }
+ if (ebd->elf_machine_code != EM_NONE)
+ goto got_wrong_format_error;
+
+ /* This is the generic ELF target. Let it match any ELF target
+ for which we do not have a specific backend. */
+ for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
+ {
+ struct elf_backend_data *back;
+
+ if ((*target_ptr)->flavour != bfd_target_elf_flavour)
+ continue;
+ back = (struct elf_backend_data *) (*target_ptr)->backend_data;
+ if (back->elf_machine_code == i_ehdrp->e_machine)
+ {
+ /* target_ptr is an ELF backend which matches this
+ object file, so reject the generic ELF target. */
+ goto got_wrong_format_error;
+ }
+ }
+ }
+
+
+ /* Set the flags and architecture before calling the backend so that
+ it can override them. */
+ if (i_ehdrp->e_type == ET_EXEC)
+ abfd->flags |= EXEC_P;
+ else if (i_ehdrp->e_type == ET_DYN)
+ abfd->flags |= DYNAMIC;
+
+ bfd_default_set_arch_mach (abfd, ebd->arch, 0);
+
+ /* Remember the entry point specified in the ELF file header. */
+ bfd_get_start_address (abfd) = i_ehdrp->e_entry;
+ /* Let the backend double check the format and override global
+ information. */
+ if (ebd->elf_backend_object_p)
+ {
+ if ((*ebd->elf_backend_object_p) (abfd) == false)
+ goto got_wrong_format_error;
+ }
+
/* Allocate space for a copy of the section header table in
internal form, seek to the section 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 section
- header table entry actually matches the size recorded in the file. */
-
- if (i_ehdrp->e_shentsize != sizeof (x_shdr))
- goto wrong;
+ read it in, and convert it to internal form. */
i_shdrp = (Elf_Internal_Shdr *)
bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum);
- elf_elfsections (abfd) = bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum);
+ elf_elfsections (abfd) =
+ (Elf_Internal_Shdr **) bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum);
if (!i_shdrp || !elf_elfsections(abfd))
- {
- bfd_error = no_memory;
- return NULL;
- }
+ goto got_no_memory_error;
if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) == -1)
- {
- bfd_error = system_call_error;
- return NULL;
- }
+ goto got_system_call_error;
for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++)
{
- if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd)
- != sizeof (x_shdr))
- {
- bfd_error = system_call_error;
- return NULL;
- }
+ if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) != sizeof (x_shdr))
+ goto got_system_call_error;
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
elf_elfsections(abfd)[shindex] = i_shdrp + shindex;
+
+ /* If this is a .dynamic section, mark the object file as being
+ dynamically linked. */
+ if (i_shdrp[shindex].sh_type == SHT_DYNAMIC)
+ abfd->flags |= DYNAMIC;
}
if (i_ehdrp->e_shstrndx)
{
shstrtab = elf_get_str_section (abfd, i_ehdrp->e_shstrndx);
if (!shstrtab)
- return NULL;
+ goto got_wrong_format_error;
/* Once all of the section headers have been read and converted, we
can start processing them. Note that the first section header is
bfd_section_from_shdr (abfd, shindex);
}
- /* Remember the entry point specified in the ELF file header. */
+ return (abfd->xvec);
- bfd_get_start_address (abfd) = i_ehdrp->e_entry;
+ /* If we are going to use goto's to avoid duplicating error setting
+ and return(NULL) code, then this at least makes it more maintainable. */
- return abfd->xvec;
+ got_system_call_error:
+ bfd_error = system_call_error;
+ goto got_no_match;
+ got_wrong_format_error:
+ bfd_error = wrong_format;
+ goto got_no_match;
+ got_no_memory_error:
+ bfd_error = no_memory;
+ goto got_no_match;
+ got_no_match:
+ elf_tdata (abfd) = preserved_tdata;
+ return (NULL);
}
\f
/* ELF .o/exec file writing */
-/* Create a new ELF section from a bfd section. */
-
-#if 0 /* not used */
-static boolean
-DEFUN (bfd_shdr_from_section, (abfd, hdr, shstrtab, indx),
- bfd * abfd AND
- Elf_Internal_Shdr * hdr AND
- struct strtab *shstrtab AND
- int indx)
-{
- asection *sect;
- int ndx;
-
- sect = abfd->sections;
- for (ndx = indx; --ndx;)
- {
- sect = sect->next;
- }
- hdr[indx].sh_name = bfd_add_to_strtab (abfd, shstrtab,
- bfd_section_name (abfd, sect));
- hdr[indx].sh_addr = sect->vma;
- hdr[indx].sh_size = sect->_raw_size;
- hdr[indx].sh_addralign = 1 << sect->alignment_power;
- hdr[indx].sh_flags = 0;
- /* these need to be preserved on */
- hdr[indx].sh_link = 0;
- hdr[indx].sh_info = 0;
- hdr[indx].sh_entsize = 0;
-
- hdr[indx].sh_type = 0;
- if (sect->flags & SEC_RELOC)
- {
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
- hdr[indx].sh_type = use_rela_p ? SHT_RELA : SHT_REL;
- }
-
- if (sect->flags & SEC_HAS_CONTENTS)
- {
- hdr[indx].sh_offset = sect->filepos;
- hdr[indx].sh_size = sect->_raw_size;
- }
- if (sect->flags & SEC_ALLOC)
- {
- hdr[indx].sh_flags |= SHF_ALLOC;
- if (sect->flags & SEC_LOAD)
- {
- /* do something with sh_type ? */
- }
- }
- if (!(sect->flags & SEC_READONLY))
- hdr[indx].sh_flags |= SHF_WRITE;
-
- if (sect->flags & SEC_CODE)
- hdr[indx].sh_flags |= SHF_EXECINSTR;
-
- return true;
-}
-#endif
-
-/*
- Takes a bfd and a symbol, returns a pointer to the elf specific area
- of the symbol if there is one.
- */
+/* Takes a bfd and a symbol, returns a pointer to the elf specific area
+ of the symbol if there is one. */
static INLINE elf_symbol_type *
DEFUN (elf_symbol_from, (ignore_abfd, symbol),
bfd * ignore_abfd AND
return (elf_symbol_type *) symbol;
}
-/*
- Create ELF output from BFD sections.
-
- Essentially, just create the section header and forget about the program
- header for now.
+/* Create ELF output from BFD sections.
-*/
+ Essentially, just create the section header and forget about the program
+ header for now. */
static void
DEFUN (elf_make_sections, (abfd, asect, obj),
{
/* most of what is in bfd_shdr_from_section goes in here... */
/* and all of these sections generate at *least* one ELF section. */
- int idx;
-
Elf_Internal_Shdr *this_hdr;
this_hdr = &elf_section_data (asect)->this_hdr;
this_hdr->sh_size = asect->_raw_size;
/* contents already set by elf_set_section_contents */
- if ((asect->flags & SEC_RELOC)
-#if 0
- /* The flags are sometimes inconsistent. */
- && asect->reloc_count > 0
-#endif
- )
+ if (asect->flags & SEC_RELOC)
{
/* emit a reloc section, and thus strtab and symtab... */
Elf_Internal_Shdr *rela_hdr;
- Elf_External_Rela *outbound_relocas;
- Elf_External_Rel *outbound_relocs;
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
rela_hdr = &elf_section_data (asect)->rel_hdr;
rela_hdr->sh_flags = 0;
rela_hdr->sh_addr = 0;
rela_hdr->sh_offset = 0;
- rela_hdr->sh_addralign = 0;
+
+ /* FIXME: Systems I've checked use an alignment of 4, but it is
+ possible that some systems use a different alignment. */
+ rela_hdr->sh_addralign = 4;
+
rela_hdr->size = 0;
}
if (asect->flags & SEC_ALLOC)
/* @@ Do something with sh_type? */
}
}
+ else
+ {
+ /* If this section is not part of the program image during
+ execution, leave the address fields at 0. */
+ this_hdr->sh_addr = 0;
+ asect->vma = 0;
+ }
if (!(asect->flags & SEC_READONLY))
this_hdr->sh_flags |= SHF_WRITE;
Elf_External_Rel *outbound_relocs;
int idx;
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+ asymbol *last_sym = 0;
+ int last_sym_idx = 9999999; /* should always be written before use */
-malloc(0);
if ((sec->flags & SEC_RELOC) == 0)
return;
/* Flags are sometimes inconsistent. */
rela_hdr->contents = (void *) bfd_alloc (abfd, rela_hdr->sh_size);
/* orelocation has the data, reloc_count has the count... */
- if (use_rela_p)
+ if (use_rela_p)
+ {
+ outbound_relocas = (Elf_External_Rela *) rela_hdr->contents;
+
+ for (idx = 0; idx < sec->reloc_count; idx++)
{
- outbound_relocas = (Elf_External_Rela *) rela_hdr->contents;
+ Elf_Internal_Rela dst_rela;
+ Elf_External_Rela *src_rela;
+ arelent *ptr;
+ asymbol *sym;
+ int n;
+
+ ptr = sec->orelocation[idx];
+ src_rela = outbound_relocas + idx;
+ if (!(abfd->flags & EXEC_P))
+ dst_rela.r_offset = ptr->address - sec->vma;
+ else
+ dst_rela.r_offset = ptr->address;
- for (idx = 0; idx < sec->reloc_count; idx++)
+ sym = *ptr->sym_ptr_ptr;
+ if (sym == last_sym)
+ n = last_sym_idx;
+ else
{
- Elf_Internal_Rela dst_rela;
- Elf_External_Rela *src_rela;
- arelent *ptr;
- asymbol *sym;
-
- ptr = sec->orelocation[idx];
- src_rela = outbound_relocas + idx;
- if (!(abfd->flags & EXEC_P))
- dst_rela.r_offset = ptr->address - sec->vma;
- else
- dst_rela.r_offset = ptr->address;
-
- sym = *ptr->sym_ptr_ptr;
-#if 0
- /* I think this bit is wrong. But doing it right here means
- fixing bfd_perform_relocation, and verifying that it doesn't
- break other targets. Sigh.
-
- Problem I'm trying to solve here: `ld -r' tends to get
- offset of target symbol in output-file section put into
- addend, but retains the original symbol, so the net
- result is doubling of that offset. */
- if (!bfd_is_com_section (sym->section)
- && sym->section != &bfd_und_section)
- {
- /* Could adjust either the offset or the symbol here.
- I'm pretty indifferent. */
- sym = sym->section->symbol;
- }
-#endif
- dst_rela.r_info
- = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, &sym),
- ptr->howto->type);
-
- dst_rela.r_addend = ptr->addend;
- elf_swap_reloca_out (abfd, &dst_rela, src_rela);
-malloc(0);
+ last_sym = sym;
+ last_sym_idx = n = elf_symbol_from_bfd_symbol (abfd, &sym);
}
+ dst_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
+
+ dst_rela.r_addend = ptr->addend;
+ elf_swap_reloca_out (abfd, &dst_rela, src_rela);
}
- else
- /* REL relocations */
+ }
+ else
+ /* REL relocations */
+ {
+ outbound_relocs = (Elf_External_Rel *) rela_hdr->contents;
+
+ for (idx = 0; idx < sec->reloc_count; idx++)
{
- outbound_relocs = (Elf_External_Rel *) rela_hdr->contents;
+ Elf_Internal_Rel dst_rel;
+ Elf_External_Rel *src_rel;
+ arelent *ptr;
+ int n;
+ asymbol *sym;
+
+ ptr = sec->orelocation[idx];
+ sym = *ptr->sym_ptr_ptr;
+ src_rel = outbound_relocs + idx;
+ if (!(abfd->flags & EXEC_P))
+ dst_rel.r_offset = ptr->address - sec->vma;
+ else
+ dst_rel.r_offset = ptr->address;
- for (idx = 0; idx < sec->reloc_count; idx++)
+ if (sym == last_sym)
+ n = last_sym_idx;
+ else
{
- Elf_Internal_Rel dst_rel;
- Elf_External_Rel *src_rel;
- arelent *ptr;
-
- ptr = sec->orelocation[idx];
- src_rel = outbound_relocs + idx;
- if (!(abfd->flags & EXEC_P))
- dst_rel.r_offset = ptr->address - sec->vma;
- else
- dst_rel.r_offset = ptr->address;
-
- dst_rel.r_info
- = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, ptr->sym_ptr_ptr),
- ptr->howto->type);
-
- elf_swap_reloc_out (abfd, &dst_rel, src_rel);
-
- /* Update the addend -- FIXME add 64 bit support. */
- bfd_put_32 (abfd, ptr->addend,
- (unsigned char *) (elf_section_data (sec)->this_hdr.contents)
- + dst_rel.r_offset);
+ last_sym = sym;
+ last_sym_idx = n = elf_symbol_from_bfd_symbol (abfd, &sym);
}
+ dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type);
+
+ elf_swap_reloc_out (abfd, &dst_rel, src_rel);
}
+ }
}
static void
&& !strcmp ("str", asect->name + strlen (asect->name) - 3))
{
size_t len = strlen (asect->name) + 1;
- char *s = alloca (len);
+ char *s = (char *) alloca (len);
strcpy (s, asect->name);
s[len - 4] = 0;
asect = bfd_get_section_by_name (abfd, s);
if (!asect)
abort ();
elf_section_data(asect)->this_hdr.sh_link = this_idx;
-
/* @@ Assuming 32 bits! */
- this_hdr->sh_entsize = 0xc;
+ elf_section_data(asect)->this_hdr.sh_entsize = 0xc;
+
+ this_hdr->sh_type = SHT_STRTAB;
}
}
this_hdr->sh_addralign = 1 << asect->alignment_power;
if ((asect->flags & SEC_ALLOC) && (asect->flags & SEC_LOAD))
this_hdr->sh_type = SHT_PROGBITS;
- /* @@ Select conditions correctly! */
- else if (!strcmp (asect->name, ".bss"))
- this_hdr->sh_type = SHT_NOBITS;
+ else if ((asect->flags & SEC_ALLOC) && ((asect->flags & SEC_LOAD) == 0))
+ {
+ BFD_ASSERT (strcmp (asect->name, ".bss") == 0
+ || strcmp (asect->name, ".sbss") == 0);
+ this_hdr->sh_type = SHT_NOBITS;
+ }
+ /* FIXME I am not sure how to detect a .note section from the flags
+ word of an `asection'. */
+ else if (!strcmp (asect->name, ".note"))
+ this_hdr->sh_type = SHT_NOTE;
else
- /* what *do* we put here? */
this_hdr->sh_type = SHT_PROGBITS;
this_hdr->sh_flags = 0;
this_hdr->sh_offset = 0;
this_hdr->size = 0;
+ /* Now, check for processor-specific section types. */
+ {
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (bed->elf_backend_fake_sections)
+ (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
+ }
+
{
/* Emit a strtab and symtab, and possibly a reloc section. */
Elf_Internal_Shdr *rela_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
/* Note that only one symtab is used, so just remember it
for now. */
- if ((asect->flags & SEC_RELOC)
- /* inconsistent flags... */
- && asect->reloc_count > 0)
+ if (asect->flags & SEC_RELOC)
{
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
rela_hdr->sh_addr = 0;
rela_hdr->sh_size = 0;
rela_hdr->sh_offset = 0;
- rela_hdr->sh_addralign = 0;
+
+ /* FIXME: Systems I've checked use an alignment of 4, but some
+ systems may use a different alignment. */
+ rela_hdr->sh_addralign = 4;
+
rela_hdr->size = 0;
}
}
this_hdr->sh_flags |= SHF_EXECINSTR;
}
-
-/*
-xxxINTERNAL_FUNCTION
- bfd_elf_locate_sh
-
-xxxSYNOPSIS
- struct elf_internal_shdr *bfd_elf_locate_sh (bfd *abfd,
- struct strtab *strtab,
- struct elf_internal_shdr *shdrp,
- CONST char *name);
-
-xxxDESCRIPTION
- Helper function to locate an ELF section header given the
- name of a BFD section.
-*/
-
-static struct elfNAME (internal_shdr) *
-DEFUN (elf_locate_sh, (abfd, strtab, shdrp, name),
- bfd * abfd AND
- struct strtab *strtab AND
- struct elfNAME (internal_shdr) *shdrp AND
- CONST char *name)
-{
- Elf_Internal_Shdr *gotit = NULL;
- int max, i;
-
- if (shdrp != NULL && strtab != NULL)
- {
- max = elf_elfheader (abfd)->e_shnum;
- for (i = 1; i < max; i++)
- {
- if (!strcmp (strtab->tab + shdrp[i].sh_name, name))
- {
- gotit = &shdrp[i];
- }
- }
- }
- return gotit;
-}
-
/* Map symbol from it's internal number to the external number, moving
all local symbols to be at the head of the list. */
static INLINE int
-sym_is_global (sym)
+sym_is_global (abfd, sym)
+ bfd *abfd;
asymbol *sym;
{
- if (sym->flags & BSF_GLOBAL)
+ /* If the backend has a special mapping, use it. */
+ if (get_elf_backend_data (abfd)->elf_backend_sym_is_global)
+ return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global)
+ (abfd, sym));
+
+ if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
{
if (sym->flags & BSF_LOCAL)
abort ();
return 1;
}
+ if (sym->section == 0)
+ {
+ /* Is this valid? */
+ abort ();
+
+ return 1;
+ }
if (sym->section == &bfd_und_section)
return 1;
if (bfd_is_com_section (sym->section))
{
int symcount = bfd_get_symcount (abfd);
asymbol **syms = bfd_get_outsymbols (abfd);
+ asymbol **sect_syms;
int num_locals = 0;
int num_globals = 0;
int num_locals2 = 0;
int num_globals2 = 0;
+ int max_index = 0;
int num_sections = 0;
- int *symtab_map;
+ Elf_Sym_Extra *sym_extra;
int idx;
asection *asect;
fflush (stderr);
#endif
- /* Add local symbols for each allocated section
- FIXME -- we should only put out symbols for sections that
- are actually relocated against. */
+ /* Add local symbols for each section for which there are relocs.
+ FIXME: How can we tell which sections have relocs at this point?
+ Will reloc_count always be accurate? Actually, I think most ELF
+ targets create section symbols for all sections anyhow. */
for (asect = abfd->sections; asect; asect = asect->next)
{
- if (/*asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE)*/1)
- num_sections++;
+ if (max_index < asect->index)
+ max_index = asect->index;
+ }
+
+ max_index++;
+ elf_num_section_syms (abfd) = max_index;
+ sect_syms = (asymbol **) bfd_zalloc (abfd, max_index * sizeof (asymbol *));
+ elf_section_syms (abfd) = sect_syms;
+
+ BFD_ASSERT (sect_syms != 0);
+
+ for (asect = abfd->sections; asect; asect = asect->next)
+ {
+ asymbol *sym = bfd_make_empty_symbol (abfd);
+ sym->the_bfd = abfd;
+ sym->name = asect->name;
+ sym->value = asect->vma;
+ sym->flags = BSF_SECTION_SYM;
+ sym->section = asect;
+ sect_syms[asect->index] = sym;
+ num_sections++;
+#ifdef DEBUG
+ fprintf (stderr,
+ "creating section symbol, name = %s, value = 0x%.8lx, index = %d, section = 0x%.8lx\n",
+ asect->name, (long) asect->vma, asect->index, (long) asect);
+#endif
}
if (num_sections)
for (asect = abfd->sections; asect; asect = asect->next)
{
- if (/* asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE) */ 1)
- {
- asymbol *sym = syms[symcount++] = bfd_make_empty_symbol (abfd);
- sym->the_bfd = abfd;
- sym->name = asect->name;
- sym->value = asect->vma;
- sym->flags = BSF_SECTION_SYM;
- sym->section = asect;
- }
+ if (sect_syms[asect->index])
+ syms[symcount++] = sect_syms[asect->index];
}
syms[symcount] = (asymbol *) 0;
bfd_set_symtab (abfd, syms, symcount);
}
- elf_symtab_map (abfd) = symtab_map
- = (int *) bfd_alloc (abfd, symcount * sizeof (int *));
+ elf_sym_extra (abfd) = sym_extra
+ = (Elf_Sym_Extra *) bfd_alloc (abfd, symcount * sizeof (Elf_Sym_Extra));
/* Identify and classify all of the symbols. */
for (idx = 0; idx < symcount; idx++)
{
- if (!sym_is_global (syms[idx]))
+ if (!sym_is_global (abfd, syms[idx]))
num_locals++;
else
num_globals++;
dummy symbol. */
for (idx = 0; idx < symcount; idx++)
{
- if (!sym_is_global (syms[idx]))
- symtab_map[idx] = 1 + num_locals2++;
+ syms[idx]->udata = (PTR) &sym_extra[idx];
+ if (!sym_is_global (abfd, syms[idx]))
+ sym_extra[idx].elf_sym_num = 1 + num_locals2++;
else
- symtab_map[idx] = 1 + num_locals + num_globals2++;
+ sym_extra[idx].elf_sym_num = 1 + num_locals + num_globals2++;
}
elf_num_locals (abfd) = num_locals;
static boolean
DEFUN (elf_compute_section_file_positions, (abfd), bfd * abfd)
{
- Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */
- struct strtab *shstrtab;
- int count, maxsections;
-
bfd_map_over_sections (abfd, elf_fake_sections, 0);
assign_section_numbers (abfd);
Elf32_Half phdr_cnt)
{
/* first program header entry goes after the file header */
- int outbase = i_ehdrp->e_ehsize;
+ int outbase = i_ehdrp->e_phoff;
int i;
Elf_External_Phdr x_phdr;
return true;
}
-static Elf_Internal_Phdr *
-DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt),
- bfd * abfd AND
- Elf_Internal_Ehdr * i_ehdrp AND
- Elf_Internal_Shdr * i_shdrp AND
- Elf32_Half * phdr_cnt)
-{
- Elf_Internal_Phdr *phdr_buf;
- int idx;
- /* NOTES:
- 1. The program header table is *not* loaded as part
- of the memory image of the program. If this
- changes later, the PT_PHDR entry must come first.
- 2. there is currently no support for program header
- entries of type PT_PHDR, PT_DYNAMIC, PT_INTERP,
- or PT_SHLIB. */
-
- /* A. Figure out how many program header table entries are needed
- 1. PT_LOAD for the text segment
- 2. PT_LOAD for the data segment
- Then, reserve space for one more pointer. This will be NULL
- to indicate the end of the program header table. */
-
-#ifdef PHDRS_INCLUDED
- *phdr_cnt = 4;
-#else
- /* XXX right now, execve() expects exactly 3 PT entries on HPPA-OSF. */
- *phdr_cnt = 3;
-#endif
-
- phdr_buf = (Elf_Internal_Phdr *) bfd_xmalloc (((*phdr_cnt) + 1)
- *
- sizeof (Elf_Internal_Phdr));
-
- idx = 0;
-#ifdef PHDRS_INCLUDED
- /* B. Fill in the PT_PHDR entry. */
-
- idx++;
-#endif
-
- /* C. Fill in the PT_LOAD entry for the text segment. */
-
- phdr_buf[idx].p_type = PT_LOAD;
-
- /* get virtual/physical address from .text section */
- phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".text")->vma;
- phdr_buf[idx].p_paddr = 0; /* XXX */
-
- /* Ultimately, we would like the size of the .text load
- segment to be the sum of the following sections:
- the program header table itself
- .interp
- .hash
- .dynsym
- .dynstr
- .rela.bss
- .rela.plt
- .init
- .text
- .fini
- .rodata
- But, right now, it will be the sum of the following sections:
- .text
- .rodata */
-
- {
- static char *CONST ld_sect_names[] =
- {".text", ".rodata", NULL};
- int i;
- int ld_size = 0;
-
- for (i = 0; ld_sect_names[i]; i++)
- {
- asection *asect = bfd_get_section_by_name (abfd,
- ld_sect_names[i]);
-
- if (asect)
- ld_size += bfd_section_size (abfd, asect);
- }
- phdr_buf[idx].p_filesz = ld_size;
- /* XXX: need to fix this */
- phdr_buf[idx].p_memsz = ld_size;
- }
- phdr_buf[idx].p_flags = PF_R + PF_X;
- phdr_buf[idx].p_align =
- bfd_get_section_by_name (abfd, ".text")->alignment_power;
-
- idx++;
-
- /* D. Fill in the PT_LOAD entry for the data segment. */
-
- phdr_buf[idx].p_type = PT_LOAD;
-
- /* get virtual/physical address from .data section */
- phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".data")->vma;
- phdr_buf[idx].p_paddr = 0; /* XXX */
-
- /* Ultimately, we would like the size of the data load segment
- to be the sum of the following sections:
- the PT_DYNAMIC program header table entry
- .plt
- .data
- .data1
- .got
- .dynamic
- But, right now, it will be the sum of the following sections:
- .data */
-
- {
- static char *CONST ld_sect_names[] =
- {".data", NULL};
- int i;
- int ld_size = 0;
-
- for (i = 0; ld_sect_names[i]; i++)
- {
- asection *asect = bfd_get_section_by_name (abfd,
- ld_sect_names[i]);
-
- if (asect)
- ld_size += bfd_section_size (abfd, asect);
- }
- phdr_buf[idx].p_filesz = ld_size;
- /* XXX: need to fix this */
- phdr_buf[idx].p_memsz = ld_size;
- }
- phdr_buf[idx].p_flags = PF_R + PF_W + PF_X;
- phdr_buf[idx].p_align
- = bfd_get_section_by_name (abfd, ".data")->alignment_power;
-
- idx++;
-
- /* E. Fill in the PT_LOAD entry for the bss segment. */
-
- phdr_buf[idx].p_type = PT_LOAD;
-
- /* get virtual/physical address from .data section */
- phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".bss")->vma;
- phdr_buf[idx].p_paddr = 0; /* XXX */
-
- {
- static char *CONST ld_sect_names[] =
- {".bss", NULL};
- int i;
- int ld_size = 0;
-
- for (i = 0; ld_sect_names[i]; i++)
- {
- asection *asect = bfd_get_section_by_name (abfd,
- ld_sect_names[i]);
-
- if (asect)
- ld_size += bfd_section_size (abfd, asect);
- }
- phdr_buf[idx].p_filesz = 0;
- /* XXX: need to fix this */
- phdr_buf[idx].p_memsz = ld_size;
- }
- phdr_buf[idx].p_flags = PF_R + PF_W + PF_X;
- phdr_buf[idx].p_align
- = bfd_get_section_by_name (abfd, ".bss")->alignment_power;
-
- idx++;
-
- /* F. Set up the "end of program header table" sentinel. */
-
- memset ((char *) (phdr_buf + idx), 0, sizeof (Elf_Internal_Phdr));
- idx++;
-
- BFD_ASSERT (idx - 1 == *phdr_cnt);
-
- return phdr_buf;
-}
-
static const Elf_Internal_Shdr null_shdr;
/* Assign all ELF section numbers. The dummy first section is handled here
{
struct bfd_elf_section_data *d = elf_section_data (sec);
d->this_idx = section_number++;
- if (sec->reloc_count != 0)
+ if (sec->flags & SEC_RELOC)
{
d->rel_idx = section_number++;
d->rel_hdr.sh_link = t->symtab_section;
/* Set up the list of section header pointers, in agreement with the
indices. */
- i_shdrp = bfd_alloc (abfd,
- section_number * sizeof (Elf_Internal_Shdr *));
+ i_shdrp = (Elf_Internal_Shdr **)
+ bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *));
elf_elfsections(abfd) = i_shdrp;
for (i = 0; i < section_number; i++)
i_shdrp[i] = 0;
Elf_Internal_Shdr *i_shdrp;
file_ptr offset;
{
- i_shdrp->sh_offset = offset;
- offset += i_shdrp->sh_size;
+ int align;
+
+ if (i_shdrp->sh_addralign != 0)
+ align = i_shdrp->sh_addralign;
+ else
+ align = 1;
+ i_shdrp->sh_offset = offset = BFD_ALIGN (offset, align);
+ if (i_shdrp->rawdata != NULL)
+ ((asection *) i_shdrp->rawdata)->filepos = offset;
+ if (i_shdrp->sh_type != SHT_NOBITS)
+ offset += i_shdrp->sh_size;
return offset;
}
+static INLINE file_ptr
+align_file_position (off)
+ file_ptr off;
+{
+ return (off + FILE_ALIGN - 1) & ~(FILE_ALIGN - 1);
+}
+
+static INLINE file_ptr
+assign_file_positions_for_symtab_and_strtabs (abfd, off)
+ bfd *abfd;
+ file_ptr off;
+{
+ struct elf_obj_tdata *t = elf_tdata (abfd);
+
+ off = align_file_position (off);
+ off = assign_file_position_for_section (&t->symtab_hdr, off);
+ off = assign_file_position_for_section (&t->shstrtab_hdr, off);
+ off = assign_file_position_for_section (&t->strtab_hdr, off);
+ return off;
+}
+
+struct seg_info {
+ bfd_vma low, mem_size;
+ file_ptr file_size;
+ int start_pos;
+ int sh_flags;
+ struct seg_info *next;
+};
+
+static void
+map_program_segments (abfd)
+ bfd *abfd;
+{
+ Elf_Internal_Shdr **i_shdrpp = elf_elfsections (abfd);
+ Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+ Elf_Internal_Shdr *i_shdrp;
+ Elf_Internal_Phdr *phdr;
+ char *done;
+ int i, n_left = 0;
+ file_ptr lowest_offset = 0;
+ struct seg_info *seg = 0;
+
+ done = (char *) alloca (i_ehdrp->e_shnum);
+ memset (done, 0, i_ehdrp->e_shnum);
+ for (i = 1; i < i_ehdrp->e_shnum; i++)
+ {
+ i_shdrp = i_shdrpp[i];
+ /* If it's going to be mapped in, it's been assigned a position. */
+ if (i_shdrp->sh_offset + 1 == 0)
+ {
+ /* Well, not really, but we won't process it here. */
+ done[i] = 1;
+ continue;
+ }
+ if (i_shdrp->sh_offset < lowest_offset
+ || lowest_offset == 0)
+ lowest_offset = i_shdrp->sh_offset;
+ /* Only interested in PROGBITS or NOBITS for generating segments. */
+ switch (i_shdrp->sh_type)
+ {
+ case SHT_PROGBITS:
+ case SHT_NOBITS:
+ break;
+ default:
+ done[i] = 1;
+ }
+ if (!done[i])
+ n_left++;
+ }
+ while (n_left)
+ {
+ bfd_vma lowest_vma = -1, high;
+ int low_sec = 0;
+ int mem_size;
+ int file_size = 0;
+
+ for (i = 1; i < i_ehdrp->e_shnum; i++)
+ {
+ i_shdrp = i_shdrpp[i];
+ if (!done[i] && i_shdrp->sh_addr < lowest_vma)
+ {
+ lowest_vma = i_shdrp->sh_addr;
+ low_sec = i;
+ }
+ }
+ if (low_sec == 0)
+ abort ();
+ /* So now we know the lowest vma of any unassigned sections; start
+ a segment there. */
+ {
+ struct seg_info *s;
+ s = (struct seg_info *) bfd_alloc (abfd, sizeof (struct seg_info));
+ s->next = seg;
+ seg = s;
+ }
+ seg->low = lowest_vma;
+ i_shdrp = i_shdrpp[low_sec];
+ seg->start_pos = i_shdrp->sh_offset;
+ seg->sh_flags = i_shdrp->sh_flags;
+ done[low_sec] = 1, n_left--;
+ mem_size = i_shdrp->sh_size;
+ high = lowest_vma + i_shdrp->sh_size;
+
+ if (i_shdrp->sh_type == SHT_PROGBITS)
+ file_size = i_shdrp->sh_size;
+
+ for (i = 1; i < i_ehdrp->e_shnum; i++)
+ {
+ file_ptr f1;
+
+ if (done[i])
+ continue;
+ i_shdrp = i_shdrpp[i];
+ /* position of next byte on disk */
+ f1 = seg->start_pos + file_size;
+ if (i_shdrp->sh_type == SHT_PROGBITS)
+ {
+ if (i_shdrp->sh_offset - f1 != i_shdrp->sh_addr - high)
+ continue;
+ if (file_size != mem_size)
+ break;
+ }
+ else /* sh_type == NOBITS */
+ {
+ /* If the section in question has no contents in the disk
+ file, we really don't care where it supposedly starts.
+ But we don't want to bother merging it into this segment
+ if it doesn't start on this memory page. */
+ bfd_vma page1, page2;
+ bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
+
+ /* page number in address space of current end of seg */
+ page1 = (high - 1 + maxpagesize - 1) / maxpagesize;
+ /* page number in address space of start of this section */
+ page2 = (i_shdrp->sh_addr + maxpagesize - 1) / maxpagesize;
+
+ if (page1 != page2)
+ continue;
+ }
+ done[i] = 1, n_left--;
+ if (i_shdrp->sh_type == SHT_PROGBITS)
+ file_size = i_shdrp->sh_offset + i_shdrp->sh_size - seg->start_pos;
+ mem_size = i_shdrp->sh_addr + i_shdrp->sh_size - seg->low;
+ high = i_shdrp->sh_addr + i_shdrp->sh_size;
+ i = 0;
+ }
+ seg->file_size = file_size;
+ seg->mem_size = mem_size;
+ }
+ /* Now do something with the list of segments we've built up. */
+ {
+ bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
+ struct seg_info *s;
+ int n_segs = 0;
+ int sz;
+
+ for (s = seg; s; s = s->next)
+ {
+ n_segs++;
+ }
+ i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
+ sz = sizeof (Elf_External_Phdr) * n_segs;
+ if (align_file_position (i_ehdrp->e_ehsize) + sz <= lowest_offset)
+ i_ehdrp->e_phoff = align_file_position (i_ehdrp->e_ehsize);
+ else
+ {
+ i_ehdrp->e_phoff = align_file_position (elf_tdata (abfd)->next_file_pos);
+ elf_tdata (abfd)->next_file_pos = i_ehdrp->e_phoff + sz;
+ }
+ phdr = (Elf_Internal_Phdr*) bfd_alloc (abfd,
+ n_segs * sizeof (Elf_Internal_Phdr));
+ elf_tdata (abfd)->phdr = phdr;
+ while (seg)
+ {
+ phdr->p_type = PT_LOAD; /* only type we really support so far */
+ phdr->p_offset = seg->start_pos;
+ phdr->p_vaddr = seg->low;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = seg->file_size;
+ phdr->p_memsz = seg->mem_size;
+ phdr->p_flags = PF_R;
+ phdr->p_align = maxpagesize; /* ? */
+ if (seg->sh_flags & SHF_WRITE)
+ /* SysVr4 ELF docs say "data segments normally have read, write,
+ and execute permissions." */
+ phdr->p_flags |= (PF_W | PF_X);
+ if (seg->sh_flags & SHF_EXECINSTR)
+ phdr->p_flags |= PF_X;
+ phdr++;
+ seg = seg->next;
+ }
+ i_ehdrp->e_phnum = n_segs;
+ }
+ elf_write_phdrs (abfd, i_ehdrp, elf_tdata (abfd)->phdr, i_ehdrp->e_phnum);
+}
+
static void
assign_file_positions_except_relocs (abfd)
bfd *abfd;
a given section, we don't figure them in here. We'll put them at the
end of the file, at positions computed during bfd_close.
- The order, for now: <ehdr> <shdr> <sec1> <sec2> <sec3> ... <rel1> ... */
+ The order, for now: <ehdr> <shdr> <sec1> <sec2> <sec3> ... <rel1> ...
+ or: <ehdr> <phdr> <sec1> <sec2> ... <shdr> <rel1> ... */
+ struct elf_obj_tdata *t = elf_tdata (abfd);
file_ptr off;
int i;
Elf_Internal_Shdr **i_shdrpp = elf_elfsections (abfd);
Elf_Internal_Shdr *i_shdrp;
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+ int exec_p = (abfd->flags & EXEC_P) != 0;
+ bfd_vma maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
+ /* Everything starts after the ELF file header. */
off = i_ehdrp->e_ehsize;
- i_ehdrp->e_shoff = off;
- off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
- off = assign_file_position_for_section (&elf_tdata(abfd)->shstrtab_hdr, off);
- off = assign_file_position_for_section (&elf_tdata(abfd)->symtab_hdr, off);
- off = assign_file_position_for_section (&elf_tdata(abfd)->strtab_hdr, off);
- for (i = 0; i < i_ehdrp->e_shnum; i++)
+
+ if (!exec_p)
{
+ /* Section headers. */
+ off = align_file_position (off);
+ i_ehdrp->e_shoff = off;
+ off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
+ off = assign_file_positions_for_symtab_and_strtabs (abfd, off);
+ }
+ for (i = 1; i < i_ehdrp->e_shnum; i++)
+ {
+ /* The symtab and strtab sections are placed by
+ assign_file_positions_for_symtab_and_strtabs. */
+ if (i == t->symtab_section
+ || i == t->strtab_section
+ || i == t->shstrtab_section)
+ continue;
+
i_shdrp = i_shdrpp[i];
if (i_shdrp->sh_type == SHT_REL || i_shdrp->sh_type == SHT_RELA)
{
i_shdrp->sh_offset = -1;
continue;
}
+ if (exec_p)
+ {
+ if (maxpagesize == 0)
+ maxpagesize = 1; /* make the arithmetic work */
+ /* This isn't necessarily going to give the best packing, if the
+ segments require padding between them, but since that isn't
+ usually the case, this'll do. */
+ if ((i_shdrp->sh_flags & SHF_ALLOC) == 0)
+ {
+ i_shdrp->sh_offset = -1;
+ continue;
+ }
+ /* Blindly assume that the segments are ordered optimally. With
+ the default LD script, they will be. */
+ if (i_shdrp->sh_type != SHT_NOBITS)
+ {
+ /* need big unsigned type */
+ bfd_vma addtl_off;
+ addtl_off = i_shdrp->sh_addr - off;
+ addtl_off = addtl_off % maxpagesize;
+ if (addtl_off)
+ {
+ off += addtl_off;
+ }
+ }
+ }
off = assign_file_position_for_section (i_shdrp, off);
+
+ if (exec_p
+ && i_shdrp->sh_type == SHT_NOBITS
+ && (i == i_ehdrp->e_shnum
+ || i_shdrpp[i + 1]->sh_type != SHT_NOBITS))
+ {
+ /* Skip to the next page to ensure that when the file is
+ loaded the bss section is loaded with zeroes. I don't
+ know if this is required on all platforms, but it
+ shouldn't really hurt. */
+ off = BFD_ALIGN (off, maxpagesize);
+ }
+
+ if (exec_p
+ && get_elf_backend_data(abfd)->maxpagesize > 1
+ && i_shdrp->sh_type == SHT_PROGBITS
+ && (i_shdrp->sh_flags & SHF_ALLOC)
+ && (i_shdrp->sh_offset - i_shdrp->sh_addr) % get_elf_backend_data (abfd)->maxpagesize != 0)
+ abort ();
+ }
+ if (exec_p)
+ {
+ elf_tdata (abfd)->next_file_pos = off;
+ map_program_segments (abfd);
+ off = elf_tdata (abfd)->next_file_pos;
+
+ /* Section headers. */
+ off = align_file_position (off);
+ i_ehdrp->e_shoff = off;
+ off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
+
+ off = assign_file_positions_for_symtab_and_strtabs (abfd, off);
+
+ for (i = 1; i < i_ehdrp->e_shnum; i++)
+ {
+ i_shdrp = i_shdrpp[i];
+ if (i_shdrp->sh_offset + 1 == 0
+ && i_shdrp->sh_type != SHT_REL
+ && i_shdrp->sh_type != SHT_RELA)
+ off = assign_file_position_for_section (i_shdrp, off);
+ }
}
elf_tdata (abfd)->next_file_pos = off;
}
prep_headers (abfd)
bfd *abfd;
{
- Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
- Elf_External_Shdr *x_shdrp; /* Section header table, external form */
Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
-
int count;
- int scnt;
struct strtab *shstrtab;
i_ehdrp = elf_elfheader (abfd);
/* if we're building an executable, we'll need a program header table */
if (abfd->flags & EXEC_P)
{
- abort ();
-
+ /* it all happens later */
#if 0
i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
".strtab");
elf_tdata (abfd)->shstrtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
".shstrtab");
-
+ return true;
}
static void
swap_out_syms (abfd)
bfd *abfd;
{
- struct strtab *shstrtab = elf_shstrtab (abfd);
-
elf_map_symbols (abfd);
/* Dump out the symtabs. */
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
+ /* FIXME: Systems I've checked use 4 byte alignment for .symtab,
+ but it is possible that there are systems which use a different
+ alignment. */
+ symtab_hdr->sh_addralign = 4;
+
/* see assert in elf_fake_sections that supports this: */
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
symstrtab_hdr->sh_type = SHT_STRTAB;
sym.st_size = value;
/* Should retrieve this from somewhere... */
sym.st_value = 16;
- sym.st_shndx = SHN_COMMON;
+ sym.st_shndx = elf_section_from_bfd_section (abfd,
+ syms[idx]->section);
}
else
{
asection *sec = syms[idx]->section;
+ elf_symbol_type *type_ptr;
int shndx;
if (sec->output_section)
}
value += sec->vma;
sym.st_value = value;
- sym.st_size = (elf_symbol_from (abfd, syms[idx]))->internal_elf_sym.st_size;
+ type_ptr = elf_symbol_from (abfd, syms[idx]);
+ sym.st_size = type_ptr ? type_ptr->internal_elf_sym.st_size : 0;
sym.st_shndx = shndx = elf_section_from_bfd_section (abfd, sec);
if (shndx == -1)
{
}
if (bfd_is_com_section (syms[idx]->section))
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE);
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT);
else if (syms[idx]->section == &bfd_und_section)
sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE);
- else if (syms[idx]->flags & BSF_WEAK)
- sym.st_info = ELF_ST_INFO (STB_WEAK, 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);
- else if (syms[idx]->flags & (BSF_GLOBAL | BSF_EXPORT))
- {
- if (syms[idx]->flags & BSF_FUNCTION)
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC);
- else
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT);
- }
- else if (syms[idx]->flags & BSF_LOCAL)
+ else
{
- if (syms[idx]->flags & BSF_FUNCTION)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
- else
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT);
+ int bind = STB_LOCAL;
+ int type = STT_OBJECT;
+ unsigned int flags = syms[idx]->flags;
+
+ if (flags & BSF_LOCAL)
+ bind = STB_LOCAL;
+ else if (flags & BSF_WEAK)
+ bind = STB_WEAK;
+ else if (flags & BSF_GLOBAL)
+ bind = STB_GLOBAL;
+
+ if (flags & BSF_FUNCTION)
+ type = STT_FUNC;
+
+ sym.st_info = ELF_ST_INFO (bind, type);
}
- else
- /* Default to local if flag isn't set at all. */
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT);
sym.st_other = 0;
elf_swap_symbol_out (abfd, &sym,
- outbound_syms + elf_symtab_map (abfd)[idx]);
+ (outbound_syms
+ + elf_sym_extra (abfd)[idx].elf_sym_num));
}
symtab_hdr->contents = (PTR) outbound_syms;
symstrtab_hdr->sh_entsize = 0;
symstrtab_hdr->sh_link = 0;
symstrtab_hdr->sh_info = 0;
- symstrtab_hdr->sh_addralign = 0;
+ symstrtab_hdr->sh_addralign = 1;
symstrtab_hdr->size = 0;
}
this_hdr->sh_flags = 0;
this_hdr->sh_addr = 0;
this_hdr->sh_entsize = 0;
- this_hdr->sh_addralign = 0;
+ this_hdr->sh_addralign = 1;
this_hdr->size = 0;
}
}
{
Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
Elf_External_Shdr *x_shdrp; /* Section header table, external form */
Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
-
int count;
- int scnt;
struct strtab *shstrtab;
i_ehdrp = elf_elfheader (abfd);
bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd);
- /* If we're building an executable, fixup the program header table
- offsets.
-
- @@ For now, assume that the entries are in a fixed order: text,
- data, bss. FIXME */
-
- if (abfd->flags & EXEC_P)
- {
- static char *CONST section_name[] =
- {".text", ".data", ".bss"};
-
- for (count = 0; count < 3; count++)
- {
- asection *asect = bfd_get_section_by_name (abfd,
- section_name[count]);
- int sh_idx = elf_section_from_bfd_section (abfd, asect);
-
- i_phdrp[count].p_offset = i_shdrp[sh_idx]->sh_offset;
- }
-
- /* write out the program header table entries */
- elf_write_phdrs (abfd, i_ehdrp, i_phdrp, i_ehdrp->e_phnum);
- }
-
/* at this point we've concocted all the ELF sections... */
x_shdrp = (Elf_External_Shdr *)
bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum));
int i;
Elf_Internal_Shdr **shdrpp = elf_elfsections (abfd);
Elf_Internal_Shdr *shdrp;
- for (i = 0; i < elf_elfheader(abfd)->e_shnum; i++)
+ for (i = 1; i < elf_elfheader(abfd)->e_shnum; i++)
{
shdrp = shdrpp[i];
if (shdrp->sh_type != SHT_REL && shdrp->sh_type != SHT_RELA)
continue;
+ off = align_file_position (off);
off = assign_file_position_for_section (shdrp, off);
}
elf_tdata(abfd)->next_file_pos = off;
boolean
DEFUN (NAME(bfd_elf,write_object_contents), (abfd), bfd * abfd)
{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Ehdr *i_ehdrp;
Elf_Internal_Shdr **i_shdrp;
int count;
+ /* We don't know how to write dynamic objects. Specifically, we
+ don't know how to construct the program header. */
+ if ((abfd->flags & DYNAMIC) != 0)
+ {
+ fprintf (stderr, "Writing ELF dynamic objects is not supported\n");
+ bfd_error = wrong_format;
+ return false;
+ }
+
if (abfd->output_has_begun == false)
{
- malloc (0);
prep_headers (abfd);
-malloc(0);
elf_compute_section_file_positions (abfd);
-malloc(0);
abfd->output_has_begun = true;
}
i_ehdrp = elf_elfheader (abfd);
bfd_map_over_sections (abfd, write_relocs, (PTR) 0);
-malloc(0);
assign_file_positions_for_relocs (abfd);
/* After writing the headers, we need to write the sections too... */
- for (count = 0; count < i_ehdrp->e_shnum; count++)
- if (i_shdrp[count]->contents)
- {
- bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET);
- bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size, 1, abfd);
- }
+ for (count = 1; count < i_ehdrp->e_shnum; count++)
+ {
+ if (bed->elf_backend_section_processing)
+ (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
+ if (i_shdrp[count]->contents)
+ {
+ bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET);
+ bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size, 1,
+ abfd);
+ }
+ }
+
+ if (bed->elf_backend_final_write_processing)
+ (*bed->elf_backend_final_write_processing) (abfd);
+
return write_shdrs_and_ehdr (abfd);
}
/* ELF sections that map to BFD sections */
case SHT_PROGBITS:
case SHT_NOBITS:
+ case SHT_NOTE:
if (hdr->rawdata)
{
if (((struct sec *) (hdr->rawdata)) == asect)
return index;
}
break;
+
+ case SHT_STRTAB:
+ /* fix_up_strtabs will generate STRTAB sections with names
+ of .stab*str. */
+ if (!strncmp (asect->name, ".stab", 5)
+ && !strcmp ("str", asect->name + strlen (asect->name) - 3))
+ {
+ if (hdr->rawdata)
+ {
+ if (((struct sec *) (hdr->rawdata)) == asect)
+ return index;
+ }
+ break;
+ }
+ /* FALL THROUGH */
default:
+ {
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (bed->elf_backend_section_from_bfd_section)
+ {
+ int retval;
+
+ retval = index;
+ if ((*bed->elf_backend_section_from_bfd_section)
+ (abfd, hdr, asect, &retval))
+ return retval;
+ }
+ }
break;
}
}
struct symbol_cache_entry **asym_ptr_ptr)
{
struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr;
- CONST char *name = asym_ptr->name;
int idx;
- int symcount = bfd_get_symcount (abfd);
- asymbol **syms = bfd_get_outsymbols (abfd);
+ flagword flags = asym_ptr->flags;
- /* FIXME -- there has to be a better way than linear search. */
- for (idx = 0; idx < symcount; idx++)
+ /* When gas creates relocations against local labels, it creates its
+ own symbol for the section, but does put the symbol into the
+ symbol chain, so udata is 0. When the linker is generating
+ relocatable output, this section symbol may be for one of the
+ input sections rather than the output section. */
+ if (asym_ptr->udata == (PTR) 0
+ && (flags & BSF_SECTION_SYM)
+ && asym_ptr->section)
{
- if (syms[idx] == asym_ptr
- || (name == syms[idx]->name && name)
- || ((asym_ptr->flags & BSF_SECTION_SYM)
- && (syms[idx]->flags & BSF_SECTION_SYM)
- && asym_ptr->section == syms[idx]->section))
- break;
+ int indx;
+
+ if (asym_ptr->section->output_section != NULL)
+ indx = asym_ptr->section->output_section->index;
+ else
+ indx = asym_ptr->section->index;
+ if (elf_section_syms (abfd)[indx])
+ asym_ptr->udata = elf_section_syms (abfd)[indx]->udata;
}
- if (idx >= symcount)
+ if (asym_ptr->udata)
+ idx = ((Elf_Sym_Extra *)asym_ptr->udata)->elf_sym_num;
+ else
{
- /* badness... */
- fprintf (stderr, "bfd app err: can't find sym `%s' in symtab\n",
- name);
abort ();
}
- idx = elf_symtab_map (abfd)[idx];
#if DEBUG & 4
{
- flagword flags = asym_ptr->flags;
fprintf (stderr,
- "elfsym<-bfdsym %.8lx `%s' sec=%s symnum=%d {",
- (long) asym_ptr, asym_ptr->name, asym_ptr->section->name, idx);
-
- if (flags == BSF_NO_FLAGS)
- fprintf (stderr, " none");
-
- if (flags & BSF_LOCAL)
- fprintf (stderr, " local");
-
- if (flags & BSF_GLOBAL)
- fprintf (stderr, " global");
-
- if (flags & BSF_EXPORT)
- fprintf (stderr, " export");
-
- if (flags & BSF_DEBUGGING)
- fprintf (stderr, " debugging");
-
- if (flags & BSF_KEEP)
- fprintf (stderr, " keep");
-
- if (flags & BSF_KEEP_G)
- fprintf (stderr, " keep_g");
-
- if (flags & BSF_WEAK)
- fprintf (stderr, " weak");
-
- if (flags & BSF_SECTION_SYM)
- fprintf (stderr, " section_sym");
-
- if (flags & BSF_OLD_COMMON)
- fprintf (stderr, " old_common");
-
- if (flags & BSF_NOT_AT_END)
- fprintf (stderr, " not_at_end");
-
- if (flags & BSF_CONSTRUCTOR)
- fprintf (stderr, " constructor");
-
- if (flags & BSF_WARNING)
- fprintf (stderr, " warning");
-
- if (flags & BSF_INDIRECT)
- fprintf (stderr, " indirect");
-
- if (flags & BSF_FILE)
- fprintf (stderr, " file");
-
- if (flags & BSF_FUNCTION)
- fprintf (stderr, " function");
-
- fputs (" }\n", stderr);
+ "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx %s\n",
+ (long) asym_ptr, asym_ptr->name, idx, flags, elf_symbol_flags (flags));
fflush (stderr);
}
#endif
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;
- }
/* Read each raw ELF symbol, converting from external ELF form to
internal ELF form, and then using the information to create a
{
elf_swap_symbol_in (abfd, x_symp + i, &i_sym);
memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym));
+#ifdef ELF_KEEP_EXTSYM
memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym));
+#endif
sym->symbol.the_bfd = abfd;
sym->symbol.name = elf_string_from_elf_section (abfd, hdr->sh_link,
sym->symbol.flags |= BSF_LOCAL;
break;
case STB_GLOBAL:
- sym->symbol.flags |= (BSF_GLOBAL | BSF_EXPORT);
+ sym->symbol.flags |= BSF_GLOBAL;
break;
case STB_WEAK:
sym->symbol.flags |= BSF_WEAK;
sym->symbol.flags |= BSF_FUNCTION;
break;
}
- /* Is this a definition of $global$? If so, keep it because it will be
- needd if any relocations are performed. */
- if (!strcmp (sym->symbol.name, "$global$")
- && sym->symbol.section != &bfd_und_section)
- {
- /* @@ Why is this referring to backend data and not a field of
- abfd? FIXME */
- struct elf_backend_data *be_data = (struct elf_backend_data *) abfd->xvec->backend_data;
- be_data->global_sym = (PTR) sym;
- }
+ /* Do some backend-specific processing on this symbol. */
+ {
+ struct elf_backend_data *ebd = get_elf_backend_data (abfd);
+ if (ebd->elf_backend_symbol_processing)
+ (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
+ }
+
sym++;
}
- /* We rely on the zalloc to clear out the final symbol entry. */
+ /* Do some backend-specific processing on this symbol table. */
+ {
+ struct elf_backend_data *ebd = get_elf_backend_data (abfd);
+ if (ebd->elf_backend_symbol_table_processing)
+ (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
+ }
- /* obj_raw_syms macro uses a cast... */
- elf_tdata (abfd)->raw_syms = (PTR) x_symp;
+ /* We rely on the zalloc to clear out the final symbol entry. */
bfd_get_symcount (abfd) = symcount = sym - symbase;
*symptrs = 0; /* Final null pointer */
}
+ free ((PTR) x_symp);
return true;
}
for (idx = 0; idx < asect->reloc_count; idx++)
{
-#ifdef RELOC_PROCESSING
Elf_Internal_Rela dst;
Elf_External_Rela *src;
src = native_relocs + idx;
elf_swap_reloca_in (abfd, src, &dst);
+#ifdef RELOC_PROCESSING
RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
#else
- Elf_Internal_Rela dst;
- Elf_External_Rela *src;
-
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
-
- elf_swap_reloca_in (abfd, src, &dst);
-
if (asect->flags & SEC_RELOC)
{
/* relocatable, so the offset is off of the section */
/* non-relocatable, so the offset a virtual address */
cache_ptr->address = dst.r_offset;
}
- /* ELF_R_SYM(dst.r_info) is the symbol table offset; subtract 1
- because the first entry is NULL. */
- cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
- {
- /* Is it an ELF section symbol? If so, translate it into a
- BFD section symbol. */
- asymbol *s = *(cache_ptr->sym_ptr_ptr);
- if (s->flags & BSF_SECTION_SYM)
- cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
- }
+
+ /* ELF_R_SYM(dst.r_info) is the symbol table offset. An offset
+ of zero points to the dummy symbol, which was not read into
+ the symbol table SYMBOLS. */
+ if (ELF_R_SYM (dst.r_info) == 0)
+ cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ else
+ {
+ asymbol *s;
+
+ cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
+
+ /* Translate any ELF section symbol into a BFD section
+ symbol. */
+ s = *(cache_ptr->sym_ptr_ptr);
+ if (s->flags & BSF_SECTION_SYM)
+ {
+ cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
+ s = *cache_ptr->sym_ptr_ptr;
+ if (s->name == 0 || s->name[0] == 0)
+ abort ();
+ }
+ }
cache_ptr->addend = dst.r_addend;
/* Fill in the cache_ptr->howto field from dst.r_type */
/* non-relocatable, so the offset a virtual address */
cache_ptr->address = dst.r_offset;
}
- /* ELF_R_SYM(dst.r_info) is the symbol table offset...
- -1 is to skip the dummy symbol table entry */
- cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
- BFD_ASSERT (dst.r_offset <= data_max);
- if (bfd_seek (abfd, data_off + dst.r_offset, SEEK_SET) != 0
- || bfd_read ((PTR) buf, sizeof (buf), 1, abfd) != sizeof (buf))
+
+ /* ELF_R_SYM(dst.r_info) is the symbol table offset. An offset
+ of zero points to the dummy symbol, which was not read into
+ the symbol table SYMBOLS. */
+ if (ELF_R_SYM (dst.r_info) == 0)
+ cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ else
{
- bfd_error = system_call_error;
- return false;
- }
+ asymbol *s;
- cache_ptr->addend = (*abfd->xvec->bfd_getx_signed_32) ((bfd_byte *) buf);
+ cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
+
+ /* Translate any ELF section symbol into a BFD section
+ symbol. */
+ s = *(cache_ptr->sym_ptr_ptr);
+ if (s->flags & BSF_SECTION_SYM)
+ {
+ cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
+ s = *cache_ptr->sym_ptr_ptr;
+ if (s->name == 0 || s->name[0] == 0)
+ abort ();
+ }
+ }
+ BFD_ASSERT (dst.r_offset <= data_max);
+ cache_ptr->addend = 0;
/* Fill in the cache_ptr->howto field from dst.r_type */
{