(3) ELF section symbols are handled rather sloppily now. This should
be cleaned up, and ELF section symbols reconciled with BFD section
symbols.
+
+ (4) We need a published spec for 64-bit ELF. We've got some stuff here
+ that we're using for SPARC V9 64-bit chips, but don't assume that
+ it's cast in stone.
*/
#include <string.h> /* For strrchr and friends */
#define elf_swap_reloca_in NAME(bfd_elf,swap_reloca_in)
#define elf_swap_reloc_out NAME(bfd_elf,swap_reloc_out)
#define elf_swap_reloca_out NAME(bfd_elf,swap_reloca_out)
+#define elf_swap_symbol_in NAME(bfd_elf,swap_symbol_in)
+#define elf_swap_symbol_out NAME(bfd_elf,swap_symbol_out)
#define elf_swap_dyn_in NAME(bfd_elf,swap_dyn_in)
#define elf_swap_dyn_out NAME(bfd_elf,swap_dyn_out)
#define elf_get_reloc_upper_bound NAME(bfd_elf,get_reloc_upper_bound)
static long elf_slurp_symbol_table PARAMS ((bfd *, asymbol **, boolean));
+static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
+
static int elf_symbol_from_bfd_symbol PARAMS ((bfd *,
struct symbol_cache_entry **));
static boolean elf_compute_section_file_positions
PARAMS ((bfd *, struct bfd_link_info *));
static boolean prep_headers PARAMS ((bfd *));
+static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
static boolean assign_section_numbers PARAMS ((bfd *));
static file_ptr align_file_position PARAMS ((file_ptr));
static file_ptr assign_file_position_for_section
/* Translate an ELF symbol in external format into an ELF symbol in internal
format. */
-static void
+void
elf_swap_symbol_in (abfd, src, dst)
bfd *abfd;
Elf_External_Sym *src;
/* Translate an ELF symbol in internal format into an ELF symbol in external
format. */
-static void
+void
elf_swap_symbol_out (abfd, src, dst)
bfd *abfd;
Elf_Internal_Sym *src;
return ss->length - ln;
}
\f
-
/* ELF .o/exec file reading */
/* Create a new bfd section from an ELF section header. */
{
Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
- asection *newsect;
char *name;
name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
switch (hdr->sh_type)
{
-
case SHT_NULL:
- /* inactive section. Throw it away. */
- return true;
-
- case SHT_PROGBITS:
- case SHT_DYNAMIC:
- /* Bits that get saved. This one is real. */
- if (hdr->rawdata == NULL)
- {
- newsect = bfd_make_section_anyway (abfd, name);
- if (newsect == NULL)
- return false;
-
- newsect->filepos = hdr->sh_offset;
- newsect->flags |= SEC_HAS_CONTENTS;
- newsect->vma = hdr->sh_addr;
- newsect->_raw_size = hdr->sh_size;
- newsect->alignment_power = bfd_log2 (hdr->sh_addralign);
-
- if (hdr->sh_flags & SHF_ALLOC)
- {
- newsect->flags |= SEC_ALLOC;
- newsect->flags |= SEC_LOAD;
- }
-
- if (!(hdr->sh_flags & SHF_WRITE))
- newsect->flags |= SEC_READONLY;
-
- if (hdr->sh_flags & SHF_EXECINSTR)
- newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */
- else if (newsect->flags & SEC_ALLOC)
- newsect->flags |= SEC_DATA;
-
- /* The debugging sections appear to recognized only by name,
- not any sort of flag. */
- 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 = (PTR) newsect;
- }
+ /* Inactive section. Throw it away. */
return true;
- case SHT_NOBITS:
- /* Bits that get saved. This one is real. */
- if (hdr->rawdata == NULL)
- {
- newsect = bfd_make_section_anyway (abfd, name);
- if (newsect == NULL)
- return false;
-
- newsect->vma = hdr->sh_addr;
- newsect->_raw_size = hdr->sh_size;
- newsect->filepos = hdr->sh_offset; /* fake */
- newsect->alignment_power = bfd_log2 (hdr->sh_addralign);
- if (hdr->sh_flags & SHF_ALLOC)
- newsect->flags |= SEC_ALLOC;
-
- 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 */
-
- hdr->rawdata = (PTR) newsect;
- }
- return true;
+ case SHT_PROGBITS: /* Normal section with contents. */
+ case SHT_DYNAMIC: /* Dynamic linking information. */
+ case SHT_NOBITS: /* .bss section. */
+ case SHT_HASH: /* .hash section. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
case SHT_SYMTAB: /* A symbol table */
if (elf_onesymtab (abfd) == shindex)
elf_tdata (abfd)->dynsymtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->dynsymtab_hdr;
abfd->flags |= HAS_SYMS;
- return true;
+
+ /* Besides being a symbol table, we also treat this as a regular
+ section, so that objcopy can handle it. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
case SHT_STRTAB: /* A string table */
- if (hdr->rawdata)
+ if (hdr->rawdata != NULL)
return true;
if (ehdr->e_shstrndx == shindex)
{
if (elf_onesymtab (abfd) == i)
{
elf_tdata (abfd)->strtab_hdr = *hdr;
- elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr;
+ elf_elfsections (abfd)[shindex] =
+ &elf_tdata (abfd)->strtab_hdr;
return true;
}
if (elf_dynsymtab (abfd) == i)
{
elf_tdata (abfd)->dynstrtab_hdr = *hdr;
- elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->dynstrtab_hdr;
- return true;
+ elf_elfsections (abfd)[shindex] =
+ &elf_tdata (abfd)->dynstrtab_hdr;
+ /* We also treat this as a regular section, so
+ that objcopy can handle it. */
+ break;
}
#if 0 /* Not handling other string tables specially right now. */
hdr2 = elf_elfsections (abfd)[i]; /* in case it moved */
}
}
- newsect = bfd_make_section_anyway (abfd, name);
- if (newsect == NULL)
- return false;
-
- newsect->flags = SEC_HAS_CONTENTS;
- hdr->rawdata = (PTR) newsect;
- newsect->_raw_size = hdr->sh_size;
- newsect->alignment_power = bfd_log2 (hdr->sh_addralign);
- newsect->vma = hdr->sh_addr;
- newsect->filepos = hdr->sh_offset;
-
- if (hdr->sh_flags & SHF_ALLOC)
- newsect->flags |= SEC_ALLOC | SEC_LOAD;
- if (!(hdr->sh_flags & SHF_WRITE))
- newsect->flags |= SEC_READONLY;
- if (hdr->sh_flags & SHF_EXECINSTR)
- newsect->flags |= SEC_CODE;
- 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;
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
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 */
-
+ /* *These* do a lot of work -- but build no sections! */
{
asection *target_sect;
Elf_Internal_Shdr *hdr2;
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+ /* Get the symbol table. */
+ if (! bfd_section_from_shdr (abfd, hdr->sh_link))
+ return false;
+
+ /* If this reloc section does not use the main symbol table we
+ don't treat it as a reloc section. BFD can't adequately
+ represent such a section, so at least for now, we don't
+ try. We just present it as a normal section. */
+ if (hdr->sh_link != elf_onesymtab (abfd))
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+
/* Don't allow REL relocations on a machine that uses RELA and
vice versa. */
/* @@ Actually, the generic ABI does suggest that both might be
each of those architectures. It's conceivable that, e.g., a
bunch of absolute 32-bit relocs might be more compact in REL
form even on a RELA machine... */
- BFD_ASSERT (!(use_rela_p && (hdr->sh_type == SHT_REL)));
- BFD_ASSERT (!(!use_rela_p && (hdr->sh_type == SHT_RELA)));
- BFD_ASSERT (hdr->sh_entsize ==
- (use_rela_p
- ? sizeof (Elf_External_Rela)
- : sizeof (Elf_External_Rel)));
-
- if (! bfd_section_from_shdr (abfd, hdr->sh_info) /* target */
- || ! bfd_section_from_shdr (abfd, hdr->sh_link)) /* symbol table */
+ BFD_ASSERT (use_rela_p
+ ? (hdr->sh_type == SHT_RELA
+ && hdr->sh_entsize == sizeof (Elf_External_Rela))
+ : (hdr->sh_type == SHT_REL
+ && hdr->sh_entsize == sizeof (Elf_External_Rel)));
+
+ if (! bfd_section_from_shdr (abfd, hdr->sh_info))
return false;
target_sect = section_from_elf_index (abfd, hdr->sh_info);
if (target_sect == NULL
elf_elfsections (abfd)[shindex] = hdr2;
target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize;
target_sect->flags |= SEC_RELOC;
- target_sect->relocation = 0;
+ target_sect->relocation = NULL;
target_sect->rel_filepos = hdr->sh_offset;
abfd->flags |= HAS_RELOC;
return true;
}
break;
- case SHT_HASH:
-#if 0
- fprintf (stderr, "Dynamic Linking sections not yet supported.\n");
- BFD_FAIL ();
-#endif
- break;
-
case SHT_NOTE:
#if 0
fprintf (stderr, "Note Sections not yet supported.\n");
any side effects in ABFD, or any data it points to (like tdata), if the
file does not match the target vector. */
-bfd_target *
+const bfd_target *
elf_object_p (abfd)
bfd *abfd;
{
BFD format expects. */
if (ebd->elf_machine_code != i_ehdrp->e_machine)
{
- bfd_target **target_ptr;
+ const bfd_target * const *target_ptr;
if (ebd->elf_machine_code != EM_NONE)
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;
+ if (i_ehdrp->e_phnum > 0)
+ abfd->flags |= D_PAGED;
+
if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0))
goto got_no_match;
/* 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. */
goto got_no_match;
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)
{
goto got_no_match;
}
+ /* 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;
+ }
+
return (abfd->xvec);
got_wrong_format_error:
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. */
-
-static void
-elf_make_sections (abfd, asect, obj)
- bfd *abfd;
- asection *asect;
- PTR obj;
-{
- /* most of what is in bfd_shdr_from_section goes in here... */
- /* and all of these sections generate at *least* one ELF section. */
- Elf_Internal_Shdr *this_hdr;
- this_hdr = &elf_section_data (asect)->this_hdr;
-
- this_hdr->sh_addr = asect->vma;
- this_hdr->sh_size = asect->_raw_size;
- /* contents already set by elf_set_section_contents */
-
- if (asect->flags & SEC_RELOC)
- {
- /* emit a reloc section, and thus strtab and symtab... */
- Elf_Internal_Shdr *rela_hdr;
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
-
- rela_hdr = &elf_section_data (asect)->rel_hdr;
-
- /* orelocation has the data, reloc_count has the count... */
- if (use_rela_p)
- {
- rela_hdr->sh_type = SHT_RELA;
- rela_hdr->sh_entsize = sizeof (Elf_External_Rela);
- }
- else
- /* REL relocations */
- {
- rela_hdr->sh_type = SHT_REL;
- rela_hdr->sh_entsize = sizeof (Elf_External_Rel);
- }
- rela_hdr->sh_flags = 0;
- rela_hdr->sh_addr = 0;
- rela_hdr->sh_offset = 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)
- {
- this_hdr->sh_flags |= SHF_ALLOC;
- if (asect->flags & SEC_LOAD)
- {
- /* @@ 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;
-
- if (asect->flags & SEC_CODE)
- this_hdr->sh_flags |= SHF_EXECINSTR;
-}
-
void
write_relocs (abfd, sec, xxx)
bfd *abfd;
}
}
-static void
-fix_up_strtabs (abfd, asect, obj)
- bfd *abfd;
- asection *asect;
- PTR obj;
-{
- Elf_Internal_Shdr *this_hdr = &elf_section_data (asect)->this_hdr;
- int this_idx = elf_section_data (asect)->this_idx;
-
- /* @@ Check flags! */
- if (!strncmp (asect->name, ".stab", 5)
- && !strcmp ("str", asect->name + strlen (asect->name) - 3))
- {
- size_t len = strlen (asect->name) + 1;
- char *s = (char *) malloc (len);
- if (s == NULL)
- /* FIXME: Should deal more gracefully with errors. */
- abort ();
- strcpy (s, asect->name);
- s[len - 4] = 0;
- asect = bfd_get_section_by_name (abfd, s);
- free (s);
- if (!asect)
- abort ();
- elf_section_data (asect)->this_hdr.sh_link = this_idx;
- /* @@ Assuming 32 bits! */
- elf_section_data (asect)->this_hdr.sh_entsize = 0xc;
-
- this_hdr->sh_type = SHT_STRTAB;
- }
-}
+/* Set up an ELF internal section header for a section. */
+/*ARGSUSED*/
static void
-elf_fake_sections (abfd, asect, obj)
+elf_fake_sections (abfd, asect, ignore)
bfd *abfd;
asection *asect;
- PTR obj;
+ PTR ignore;
{
- /* most of what is in bfd_shdr_from_section goes in here... */
- /* and all of these sections generate at *least* one ELF section. */
-
Elf_Internal_Shdr *this_hdr;
+
this_hdr = &elf_section_data (asect)->this_hdr;
- this_hdr->sh_name =
- bfd_add_to_strtab (abfd, elf_shstrtab (abfd), asect->name);
+
+ this_hdr->sh_name = bfd_add_to_strtab (abfd, elf_shstrtab (abfd),
+ asect->name);
if (this_hdr->sh_name == (unsigned long) -1)
abort (); /* FIXME */
- /* We need to log the type *now* so that elf_section_from_bfd_section
- can find us... have to set rawdata too. */
- this_hdr->rawdata = (void *) asect;
+
+ this_hdr->sh_flags = 0;
+ if ((asect->flags & SEC_ALLOC) != 0)
+ this_hdr->sh_addr = asect->vma;
+ else
+ this_hdr->sh_addr = 0;
+ this_hdr->sh_offset = 0;
+ this_hdr->sh_size = asect->_raw_size;
+ this_hdr->sh_link = 0;
+ this_hdr->sh_info = 0;
this_hdr->sh_addralign = 1 << asect->alignment_power;
+ this_hdr->sh_entsize = 0;
+
+ this_hdr->rawdata = (PTR) asect;
+ this_hdr->contents = NULL;
+ this_hdr->size = 0;
/* FIXME: This should not be based on section names. */
if (strcmp (asect->name, ".dynstr") == 0)
this_hdr->sh_type = SHT_STRTAB;
else if (strcmp (asect->name, ".hash") == 0)
- this_hdr->sh_type = SHT_HASH;
+ {
+ this_hdr->sh_type = SHT_HASH;
+ this_hdr->sh_entsize = ARCH_SIZE / 8;
+ }
else if (strcmp (asect->name, ".dynsym") == 0)
- this_hdr->sh_type = SHT_DYNSYM;
+ {
+ this_hdr->sh_type = SHT_DYNSYM;
+ this_hdr->sh_entsize = sizeof (Elf_External_Sym);
+ }
else if (strcmp (asect->name, ".dynamic") == 0)
- this_hdr->sh_type = SHT_DYNAMIC;
+ {
+ this_hdr->sh_type = SHT_DYNAMIC;
+ this_hdr->sh_entsize = sizeof (Elf_External_Dyn);
+ }
else if (strncmp (asect->name, ".rel.", 5) == 0)
- this_hdr->sh_type = SHT_REL;
+ {
+ this_hdr->sh_type = SHT_REL;
+ this_hdr->sh_entsize = sizeof (Elf_External_Rel);
+ }
else if (strncmp (asect->name, ".rela.", 6) == 0)
- this_hdr->sh_type = SHT_RELA;
- else if ((asect->flags & SEC_ALLOC) && (asect->flags & SEC_LOAD))
+ {
+ this_hdr->sh_type = SHT_RELA;
+ this_hdr->sh_entsize = sizeof (Elf_External_Rela);
+ }
+ else if (strcmp (asect->name, ".note") == 0)
+ this_hdr->sh_type = SHT_NOTE;
+ else if (strncmp (asect->name, ".stab", 5) == 0
+ && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
+ this_hdr->sh_type = SHT_STRTAB;
+ else if ((asect->flags & SEC_ALLOC) != 0
+ && (asect->flags & SEC_LOAD) != 0)
this_hdr->sh_type = SHT_PROGBITS;
- else if ((asect->flags & SEC_ALLOC) && ((asect->flags & SEC_LOAD) == 0))
+ else if ((asect->flags & SEC_ALLOC) != 0
+ && ((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
- this_hdr->sh_type = SHT_PROGBITS;
+ {
+ /* Who knows? */
+ this_hdr->sh_type = SHT_PROGBITS;
+ }
- this_hdr->sh_flags = 0;
- this_hdr->sh_addr = 0;
- this_hdr->sh_size = 0;
- this_hdr->sh_entsize = 0;
- this_hdr->sh_info = 0;
- this_hdr->sh_link = 0;
- this_hdr->sh_offset = 0;
- this_hdr->size = 0;
+ if ((asect->flags & SEC_ALLOC) != 0)
+ this_hdr->sh_flags |= SHF_ALLOC;
+ if ((asect->flags & SEC_READONLY) == 0)
+ this_hdr->sh_flags |= SHF_WRITE;
+ if ((asect->flags & SEC_CODE) != 0)
+ this_hdr->sh_flags |= SHF_EXECINSTR;
- /* Now, check for processor-specific section types. */
+ /* Check for processor-specific section types. */
{
struct elf_backend_data *bed = get_elf_backend_data (abfd);
(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
}
- {
- /* Emit a strtab and symtab, and possibly a reloc section. */
- Elf_Internal_Shdr *rela_hdr;
+ /* If the section has relocs, set up a section header for the
+ SHT_REL[A] section. */
+ if ((asect->flags & SEC_RELOC) != 0)
+ {
+ Elf_Internal_Shdr *rela_hdr;
+ int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
- /* Note that only one symtab is used, so just remember it
- for now. */
+ rela_hdr = &elf_section_data (asect)->rel_hdr;
+ rela_hdr->sh_name =
+ bfd_add_2_to_strtab (abfd, elf_shstrtab (abfd),
+ use_rela_p ? ".rela" : ".rel",
+ asect->name);
+ rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
+ rela_hdr->sh_entsize = (use_rela_p
+ ? sizeof (Elf_External_Rela)
+ : sizeof (Elf_External_Rel));
+ rela_hdr->sh_addralign = FILE_ALIGN;
+ rela_hdr->sh_flags = 0;
+ rela_hdr->sh_addr = 0;
+ rela_hdr->sh_size = 0;
+ rela_hdr->sh_offset = 0;
+ rela_hdr->size = 0;
+ }
+}
- if (asect->flags & SEC_RELOC)
- {
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+/* Assign all ELF section numbers. The dummy first section is handled here
+ too. The link/info pointers for the standard section types are filled
+ in here too, while we're at it. */
- rela_hdr = &elf_section_data (asect)->rel_hdr;
- rela_hdr->sh_name =
- bfd_add_2_to_strtab (abfd, elf_shstrtab (abfd),
- use_rela_p ? ".rela" : ".rel",
- asect->name);
- rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
- rela_hdr->sh_entsize = (use_rela_p
- ? sizeof (Elf_External_Rela)
- : sizeof (Elf_External_Rel));
-
- rela_hdr->sh_flags = 0;
- rela_hdr->sh_addr = 0;
- rela_hdr->sh_size = 0;
- rela_hdr->sh_offset = 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;
- }
- }
- if (asect->flags & SEC_ALLOC)
+static boolean
+assign_section_numbers (abfd)
+ bfd *abfd;
+{
+ struct elf_obj_tdata *t = elf_tdata (abfd);
+ asection *sec;
+ unsigned int section_number;
+ Elf_Internal_Shdr **i_shdrp;
+
+ section_number = 1;
+
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ struct bfd_elf_section_data *d = elf_section_data (sec);
+
+ d->this_idx = section_number++;
+ if ((sec->flags & SEC_RELOC) == 0)
+ d->rel_idx = 0;
+ else
+ d->rel_idx = section_number++;
+ }
+
+ t->shstrtab_section = section_number++;
+ elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
+ t->shstrtab_hdr.sh_size = elf_shstrtab (abfd)->length;
+ t->shstrtab_hdr.contents = (PTR) elf_shstrtab (abfd)->tab;
+
+ if (abfd->symcount > 0)
+ {
+ t->symtab_section = section_number++;
+ t->strtab_section = section_number++;
+ }
+
+ elf_elfheader (abfd)->e_shnum = section_number;
+
+ /* Set up the list of section header pointers, in agreement with the
+ indices. */
+ i_shdrp = ((Elf_Internal_Shdr **)
+ bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *)));
+ if (i_shdrp == NULL)
{
- this_hdr->sh_flags |= SHF_ALLOC;
- if (asect->flags & SEC_LOAD)
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+
+ i_shdrp[0] = ((Elf_Internal_Shdr *)
+ bfd_alloc (abfd, sizeof (Elf_Internal_Shdr)));
+ if (i_shdrp[0] == NULL)
+ {
+ bfd_release (abfd, i_shdrp);
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
+
+ elf_elfsections (abfd) = i_shdrp;
+
+ i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
+ if (abfd->symcount > 0)
+ {
+ i_shdrp[t->symtab_section] = &t->symtab_hdr;
+ i_shdrp[t->strtab_section] = &t->strtab_hdr;
+ t->symtab_hdr.sh_link = t->strtab_section;
+ }
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ struct bfd_elf_section_data *d = elf_section_data (sec);
+ asection *s;
+ const char *name;
+
+ i_shdrp[d->this_idx] = &d->this_hdr;
+ if (d->rel_idx != 0)
+ i_shdrp[d->rel_idx] = &d->rel_hdr;
+
+ /* Fill in the sh_link and sh_info fields while we're at it. */
+
+ /* sh_link of a reloc section is the section index of the symbol
+ table. sh_info is the section index of the section to which
+ the relocation entries apply. */
+ if (d->rel_idx != 0)
+ {
+ d->rel_hdr.sh_link = t->symtab_section;
+ d->rel_hdr.sh_info = d->this_idx;
+ }
+
+ switch (d->this_hdr.sh_type)
{
- /* @@ Do something with sh_type? */
+ case SHT_REL:
+ case SHT_RELA:
+ /* A reloc section which we are treating as a normal BFD
+ section. sh_link is the section index of the symbol
+ table. sh_info is the section index of the section to
+ which the relocation entries apply. We assume that an
+ allocated reloc section uses the dynamic symbol table.
+ FIXME: How can we be sure? */
+ s = bfd_get_section_by_name (abfd, ".dynsym");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+
+ /* We look up the section the relocs apply to by name. */
+ name = sec->name;
+ if (d->this_hdr.sh_type == SHT_REL)
+ name += 4;
+ else
+ name += 5;
+ s = bfd_get_section_by_name (abfd, name);
+ if (s != NULL)
+ d->this_hdr.sh_info = elf_section_data (s)->this_idx;
+ break;
+
+ case SHT_STRTAB:
+ /* We assume that a section named .stab*str is a stabs
+ string section. We look for a section with the same name
+ but without the trailing ``str'', and set its sh_link
+ field to point to this section. */
+ if (strncmp (sec->name, ".stab", sizeof ".stab" - 1) == 0
+ && strcmp (sec->name + strlen (sec->name) - 3, "str") == 0)
+ {
+ size_t len;
+ char *alc;
+
+ len = strlen (sec->name);
+ alc = (char *) malloc (len - 2);
+ if (alc == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ strncpy (alc, sec->name, len - 3);
+ alc[len - 3] = '\0';
+ s = bfd_get_section_by_name (abfd, alc);
+ free (alc);
+ if (s != NULL)
+ {
+ elf_section_data (s)->this_hdr.sh_link = d->this_idx;
+
+ /* This is a .stab section. */
+ elf_section_data (s)->this_hdr.sh_entsize =
+ 4 + 2 * (ARCH_SIZE / 8);
+ }
+ }
+ break;
+
+ case SHT_DYNAMIC:
+ case SHT_DYNSYM:
+ /* sh_link is the section header index of the string table
+ used for the dynamic entries or symbol table. */
+ s = bfd_get_section_by_name (abfd, ".dynstr");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ break;
+
+ case SHT_HASH:
+ /* sh_link is the section header index of the symbol table
+ this hash table is for. */
+ s = bfd_get_section_by_name (abfd, ".dynsym");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ break;
}
}
- if (!(asect->flags & SEC_READONLY))
- this_hdr->sh_flags |= SHF_WRITE;
- if (asect->flags & SEC_CODE)
- this_hdr->sh_flags |= SHF_EXECINSTR;
+
+ return true;
}
/* Map symbol from it's internal number to the external number, moving
return 1;
}
- if (sym->section == &bfd_und_section)
+ if (bfd_is_und_section (sym->section))
return 1;
if (bfd_is_com_section (sym->section))
return 1;
/* Do any elf backend specific processing first. */
if (bed->elf_backend_begin_write_processing)
- (*bed->elf_backend_begin_write_processing) (abfd);
+ (*bed->elf_backend_begin_write_processing) (abfd, link_info);
if (! prep_headers (abfd))
return false;
if (!assign_section_numbers (abfd))
return false;
- bfd_map_over_sections (abfd, elf_make_sections, 0);
-
- bfd_map_over_sections (abfd, fix_up_strtabs, 0); /* .stab/.stabstr &c */
-
/* The backend linker builds symbol table information itself. */
if (link_info == NULL)
{
/* sh_offset is set in assign_file_positions_for_symtabs_and_strtabs. */
shstrtab_hdr->sh_addralign = 1;
shstrtab_hdr->contents = (PTR) elf_shstrtab (abfd)->tab;
-
- if (!assign_file_positions_except_relocs (abfd,
- link_info == NULL ? true : false))
- return false;
-
- abfd->output_has_begun = true;
-
- return true;
-}
-
-
-/* Assign all ELF section numbers. The dummy first section is handled here
- too. The link/info pointers for the standard section types are filled
- in here too, while we're at it. (Link pointers for .stab sections are
- not filled in here.) */
-static boolean
-assign_section_numbers (abfd)
- bfd *abfd;
-{
- struct elf_obj_tdata *t = elf_tdata (abfd);
- asection *sec;
- int section_number = 1;
- int i;
- Elf_Internal_Shdr **i_shdrp;
-
- t->shstrtab_hdr.sh_size = elf_shstrtab (abfd)->length;
- t->shstrtab_hdr.contents = (void *) elf_shstrtab (abfd)->tab;
-
- t->shstrtab_section = section_number++;
- elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
- if (abfd->symcount)
- {
- t->symtab_section = section_number++;
- t->strtab_section = section_number++;
- t->symtab_hdr.sh_link = t->strtab_section;
- }
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- struct bfd_elf_section_data *d = elf_section_data (sec);
- d->this_idx = section_number++;
- if (sec->flags & SEC_RELOC)
- {
- d->rel_idx = section_number++;
- d->rel_hdr.sh_link = t->symtab_section;
- d->rel_hdr.sh_info = d->this_idx;
- }
- else
- d->rel_idx = 0;
- /* No handling for per-section string tables currently. */
- }
- elf_elfheader (abfd)->e_shnum = section_number;
-
- /* Set up the list of section header pointers, in agreement with the
- indices. */
- i_shdrp = ((Elf_Internal_Shdr **)
- bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *)));
- if (i_shdrp == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- i_shdrp[0] = ((Elf_Internal_Shdr *)
- bfd_alloc (abfd, sizeof (Elf_Internal_Shdr)));
- if (i_shdrp[0] == NULL)
- {
- bfd_release (abfd, i_shdrp);
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- elf_elfsections (abfd) = i_shdrp;
- for (i = 1; i < section_number; i++)
- i_shdrp[i] = NULL;
- memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
-
- i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
- if (abfd->symcount)
- {
- i_shdrp[t->symtab_section] = &t->symtab_hdr;
- i_shdrp[t->strtab_section] = &t->strtab_hdr;
- }
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- struct bfd_elf_section_data *d = elf_section_data (sec);
- i_shdrp[d->this_idx] = &d->this_hdr;
- if (d->rel_idx)
- i_shdrp[d->rel_idx] = &d->rel_hdr;
- }
- /* Make sure we got everything.... */
- for (i = 0; i < section_number; i++)
- if (i_shdrp[i] == NULL)
- abort ();
+
+ if (!assign_file_positions_except_relocs (abfd,
+ link_info == NULL ? true : false))
+ return false;
+
+ abfd->output_has_begun = true;
+
return true;
}
+
/* Align to the maximum file alignment that could be required for any
ELF data structure. */
Elf_Internal_Shdr *first;
bfd_size_type phdr_size;
{
- Elf_Internal_Phdr phdrs[5];
+ Elf_Internal_Phdr phdrs[10];
unsigned int phdr_count;
Elf_Internal_Phdr *phdr;
int phdr_size_adjust;
Elf_Internal_Ehdr *i_ehdrp;
BFD_ASSERT ((abfd->flags & EXEC_P) != 0);
+ BFD_ASSERT (phdr_size / sizeof (Elf_Internal_Phdr)
+ <= sizeof phdrs / sizeof (phdrs[0]));
phdr_count = 0;
phdr = phdrs;
++phdr_count;
}
- /* Make sure we didn't run off our array. */
- if (phdr_count > sizeof (phdrs) / sizeof (phdr[0]))
- abort ();
-
/* Make sure the return value from get_program_header_size matches
what we computed here. */
- if (phdr_count != phdr_size / sizeof (Elf_Internal_Phdr))
+ if (phdr_count != phdr_size / sizeof (Elf_External_Phdr))
abort ();
/* Set up program header information. */
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;
+ if ((abfd->flags & DYNAMIC) != 0)
+ i_ehdrp->e_type = ET_DYN;
+ else if ((abfd->flags & EXEC_P) != 0)
+ i_ehdrp->e_type = ET_EXEC;
+ else
+ i_ehdrp->e_type = 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;
- /* start-sanitize-v9 */
#if ARCH_SIZE == 64
i_ehdrp->e_machine = EM_SPARC64;
+#else
+ i_ehdrp->e_machine = EM_SPARC;
#endif
- /* end-sanitize-v9 */
break;
case bfd_arch_i386:
i_ehdrp->e_machine = EM_386;
symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
+ symtab_hdr->sh_addralign = FILE_ALIGN;
- /* 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;
{
Elf_Internal_Sym sym;
bfd_vma value = syms[idx]->value;
+ elf_symbol_type *type_ptr;
if (syms[idx]->flags & BSF_SECTION_SYM)
/* Section symbols have no names. */
return false;
}
+ type_ptr = elf_symbol_from (abfd, syms[idx]);
+
if (bfd_is_com_section (syms[idx]->section))
{
/* ELF common symbols put the alignment into the `value' field,
and the size into the `size' field. This is backwards from
how BFD handles it, so reverse it here. */
sym.st_size = value;
- /* Should retrieve this from somewhere... */
- sym.st_value = 16;
+ sym.st_value = type_ptr ? type_ptr->internal_elf_sym.st_value : 16;
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;
- 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_OBJECT);
- else if (syms[idx]->section == &bfd_und_section)
+ else if (bfd_is_und_section (syms[idx]->section))
sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE);
else if (syms[idx]->flags & BSF_SECTION_SYM)
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
Elf_Internal_Shdr **i_shdrp;
unsigned 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_set_error (bfd_error_wrong_format);
- return false;
- }
-
if (! abfd->output_has_begun
&& ! elf_compute_section_file_positions (abfd,
(struct bfd_link_info *) NULL))
}
if (bed->elf_backend_final_write_processing)
- (*bed->elf_backend_final_write_processing) (abfd);
+ (*bed->elf_backend_final_write_processing) (abfd, NULL);
return write_shdrs_and_ehdr (abfd);
}
bfd *abfd;
unsigned int index;
{
- /* @@ Is bfd_com_section really correct in all the places it could
+ /* @@ Is bfd_com_section_ptr really correct in all the places it could
be returned from this routine? */
if (index == SHN_ABS)
- return &bfd_com_section; /* not abs? */
+ return bfd_com_section_ptr; /* not abs? */
if (index == SHN_COMMON)
- return &bfd_com_section;
+ return bfd_com_section_ptr;
if (index > elf_elfheader (abfd)->e_shnum)
return NULL;
return (struct sec *) hdr->rawdata;
default:
- return (struct sec *) &bfd_abs_section;
+ return bfd_abs_section_ptr;
}
}
}
Elf_Internal_Shdr *hdr;
int maxindex = elf_elfheader (abfd)->e_shnum;
- if (asect == &bfd_abs_section)
- return SHN_ABS;
- if (asect == &bfd_com_section)
- return SHN_COMMON;
- if (asect == &bfd_und_section)
- return SHN_UNDEF;
+ if (asect->owner == NULL)
+ {
+ if (bfd_is_abs_section (asect))
+ return SHN_ABS;
+ if (bfd_is_com_section (asect))
+ return SHN_COMMON;
+ if (bfd_is_und_section (asect))
+ return SHN_UNDEF;
+ return -1;
+ }
+
+ BFD_ASSERT (asect->owner == abfd);
for (index = 0; index < maxindex; index++)
{
case SHT_NOTE:
case SHT_HASH:
case SHT_DYNAMIC:
+ case SHT_DYNSYM:
if (hdr->rawdata)
{
if (((struct sec *) (hdr->rawdata)) == asect)
}
break;
+ case SHT_REL:
+ case SHT_RELA:
+ /* We sometimes map a reloc section to a BFD section. */
+ if (hdr->sh_link != elf_onesymtab (abfd)
+ && (asection *) 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;
- }
+ /* We map most string tables to BFD sections. */
+ if (index != elf_elfheader (abfd)->e_shstrndx
+ && index != elf_onesymtab (abfd)
+ && (asection *) hdr->rawdata == asect)
+ return index;
+
/* FALL THROUGH */
default:
{
/* This symbol is in a section for which we did not
create a BFD section. Just use bfd_abs_section,
although it is wrong. FIXME. */
- sym->symbol.section = &bfd_abs_section;
+ sym->symbol.section = bfd_abs_section_ptr;
}
}
else if (i_sym.st_shndx == SHN_ABS)
{
- sym->symbol.section = &bfd_abs_section;
+ sym->symbol.section = bfd_abs_section_ptr;
}
else if (i_sym.st_shndx == SHN_COMMON)
{
- sym->symbol.section = &bfd_com_section;
+ sym->symbol.section = bfd_com_section_ptr;
/* Elf puts the alignment into the `value' field, and
the size into the `size' field. BFD wants to see the
size in the value field, and doesn't care (at the
}
else if (i_sym.st_shndx == SHN_UNDEF)
{
- sym->symbol.section = &bfd_und_section;
+ sym->symbol.section = bfd_und_section_ptr;
}
else
- sym->symbol.section = &bfd_abs_section;
+ sym->symbol.section = bfd_abs_section_ptr;
sym->symbol.value -= sym->symbol.section->vma;
long symtab_size;
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ if (elf_dynsymtab (abfd) == 0)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+
symcount = hdr->sh_size / sizeof (Elf_External_Sym);
symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
return symtab_size;
}
-/*
- This function return the number of bytes required to store the
- relocation information associated with section <<sect>>
- attached to bfd <<abfd>>
-
-*/
long
elf_get_reloc_upper_bound (abfd, asect)
bfd *abfd;
sec_ptr asect;
{
- if (asect->flags & SEC_RELOC)
- {
- /* either rel or rela */
- return elf_section_data (asect)->rel_hdr.sh_size;
- }
- else
- return 0;
+ return (asect->reloc_count + 1) * sizeof (arelent *);
}
+/* Read in and swap the external relocs. */
+
static boolean
-elf_slurp_reloca_table (abfd, asect, symbols)
+elf_slurp_reloc_table (abfd, asect, symbols)
bfd *abfd;
- sec_ptr asect;
+ asection *asect;
asymbol **symbols;
{
- Elf_External_Rela *native_relocs;
- arelent *reloc_cache;
- arelent *cache_ptr;
-
- unsigned int idx;
+ struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
+ struct bfd_elf_section_data * const d = elf_section_data (asect);
+ PTR allocated = NULL;
+ bfd_byte *native_relocs;
+ arelent *relents;
+ arelent *relent;
+ unsigned int i;
+ int entsize;
- if (asect->relocation)
- return true;
- if (asect->reloc_count == 0)
- return true;
- if (asect->flags & SEC_CONSTRUCTOR)
+ if (asect->relocation != NULL)
return true;
- if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
- return false;
- native_relocs = (Elf_External_Rela *)
- bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rela));
- if (!native_relocs)
+ BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset
+ && (asect->reloc_count
+ == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
+
+ native_relocs = (bfd_byte *) elf_section_data (asect)->relocs;
+ if (native_relocs == NULL)
{
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- if (bfd_read ((PTR) native_relocs,
- sizeof (Elf_External_Rela), asect->reloc_count, abfd)
- != sizeof (Elf_External_Rela) * asect->reloc_count)
- return false;
+ allocated = (PTR) malloc (d->rel_hdr.sh_size);
+ if (allocated == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
+ if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
+ || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
+ != d->rel_hdr.sh_size))
+ goto error_return;
- reloc_cache = (arelent *)
- bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
+ native_relocs = (bfd_byte *) allocated;
+ }
- if (!reloc_cache)
+ relents = ((arelent *)
+ bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
+ if (relents == NULL)
{
bfd_set_error (bfd_error_no_memory);
- return false;
+ goto error_return;
}
- for (idx = 0; idx < asect->reloc_count; idx++)
- {
- Elf_Internal_Rela dst;
- Elf_External_Rela *src;
+ entsize = d->rel_hdr.sh_entsize;
+ BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
+ || entsize == sizeof (Elf_External_Rela));
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
- elf_swap_reloca_in (abfd, src, &dst);
+ for (i = 0, relent = relents;
+ i < asect->reloc_count;
+ i++, relent++, native_relocs += entsize)
+ {
+ Elf_Internal_Rela rela;
+ Elf_Internal_Rel rel;
-#ifdef RELOC_PROCESSING
- RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
-#else
- if (asect->flags & SEC_RELOC)
- {
- /* relocatable, so the offset is off of the section */
- cache_ptr->address = dst.r_offset + asect->vma;
- }
+ if (entsize == sizeof (Elf_External_Rela))
+ elf_swap_reloca_in (abfd, (Elf_External_Rela *) native_relocs, &rela);
else
{
- /* non-relocatable, so the offset a virtual address */
- cache_ptr->address = dst.r_offset;
+ elf_swap_reloc_in (abfd, (Elf_External_Rel *) native_relocs, &rel);
+ rela.r_offset = rel.r_offset;
+ rela.r_info = rel.r_info;
+ rela.r_addend = 0;
}
- /* 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;
+ /* The address of an ELF reloc is section relative for an object
+ file, and absolute for an executable file or shared library.
+ The address of a BFD reloc is always section relative. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ relent->address = rela.r_offset;
+ else
+ relent->address = rela.r_offset - asect->vma;
+
+ if (ELF_R_SYM (rela.r_info) == 0)
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
else
{
- asymbol *s;
+ asymbol **ps, *s;
- cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
+ ps = symbols + ELF_R_SYM (rela.r_info) - 1;
+ s = *ps;
- /* 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 ();
- }
+ /* Canonicalize ELF section symbols. FIXME: Why? */
+ if ((s->flags & BSF_SECTION_SYM) == 0)
+ relent->sym_ptr_ptr = ps;
+ else
+ relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
}
- cache_ptr->addend = dst.r_addend;
- /* Fill in the cache_ptr->howto field from dst.r_type */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- (*ebd->elf_info_to_howto) (abfd, cache_ptr, &dst);
- }
-#endif
+ relent->addend = rela.r_addend;
+
+ if (entsize == sizeof (Elf_External_Rela))
+ (*ebd->elf_info_to_howto) (abfd, relent, &rela);
+ else
+ (*ebd->elf_info_to_howto_rel) (abfd, relent, &rel);
}
- asect->relocation = reloc_cache;
+ asect->relocation = relents;
+
+ if (allocated != NULL)
+ free (allocated);
+
return true;
+
+ error_return:
+ if (allocated != NULL)
+ free (allocated);
+ return false;
}
#ifdef DEBUG
}
#endif
-static boolean
-elf_slurp_reloc_table (abfd, asect, symbols)
- bfd *abfd;
- sec_ptr asect;
- asymbol **symbols;
-{
- Elf_External_Rel *native_relocs;
- arelent *reloc_cache;
- arelent *cache_ptr;
- Elf_Internal_Shdr *data_hdr;
- bfd_vma data_off;
- unsigned long data_max;
- char buf[4]; /* FIXME -- might be elf64 */
-
- unsigned int idx;
-
- if (asect->relocation)
- return true;
- if (asect->reloc_count == 0)
- return true;
- if (asect->flags & SEC_CONSTRUCTOR)
- return true;
-
- if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
- return false;
- native_relocs = (Elf_External_Rel *)
- bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rel));
- if (!native_relocs)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- if (bfd_read ((PTR) native_relocs,
- sizeof (Elf_External_Rel), asect->reloc_count, abfd)
- != sizeof (Elf_External_Rel) * asect->reloc_count)
- return false;
-
- reloc_cache = (arelent *)
- bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
-
- if (!reloc_cache)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* Get the offset of the start of the segment we are relocating to read in
- the implicit addend. */
- data_hdr = &elf_section_data (asect)->this_hdr;
- data_off = data_hdr->sh_offset;
- data_max = data_hdr->sh_size - sizeof (buf) + 1;
-
-#if DEBUG & 2
- elf_debug_section ("data section", -1, data_hdr);
-#endif
-
- for (idx = 0; idx < asect->reloc_count; idx++)
- {
-#ifdef RELOC_PROCESSING
- Elf_Internal_Rel dst;
- Elf_External_Rel *src;
-
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
- elf_swap_reloc_in (abfd, src, &dst);
-
- RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
-#else
- Elf_Internal_Rel dst;
- Elf_External_Rel *src;
-
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
-
- elf_swap_reloc_in (abfd, src, &dst);
-
- if (asect->flags & SEC_RELOC)
- {
- /* relocatable, so the offset is off of the section */
- cache_ptr->address = dst.r_offset + asect->vma;
- }
- else
- {
- /* 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. 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 ();
- }
- }
- BFD_ASSERT (dst.r_offset <= data_max);
- cache_ptr->addend = 0;
-
- /* Fill in the cache_ptr->howto field from dst.r_type */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- (*ebd->elf_info_to_howto_rel) (abfd, cache_ptr, &dst);
- }
-#endif
- }
-
- asect->relocation = reloc_cache;
- return true;
-}
+/* Canonicalize the relocs. */
long
elf_canonicalize_reloc (abfd, section, relptr, symbols)
arelent **relptr;
asymbol **symbols;
{
- arelent *tblptr = section->relocation;
- unsigned int count = 0;
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+ arelent *tblptr;
+ unsigned int i;
- /* snarfed from coffcode.h */
- if (use_rela_p)
- {
- if (! elf_slurp_reloca_table (abfd, section, symbols))
- return -1;
- }
- else
- {
- if (! elf_slurp_reloc_table (abfd, section, symbols))
- return -1;
- }
+ if (! elf_slurp_reloc_table (abfd, section, symbols))
+ return -1;
tblptr = section->relocation;
-
- for (; count++ < section->reloc_count;)
+ for (i = 0; i < section->reloc_count; i++)
*relptr++ = tblptr++;
- *relptr = 0;
+ *relptr = NULL;
+
return section->reloc_count;
}
return false;
newsect->_raw_size = sizeof (status->pr_reg);
newsect->filepos = filepos + (long) &status->pr_reg;
- newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
+ newsect->flags = SEC_HAS_CONTENTS;
newsect->alignment_power = 2;
if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL)
{
return false;
newsect->_raw_size = descsz;
newsect->filepos = filepos;
- newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
+ newsect->flags = SEC_HAS_CONTENTS;
newsect->alignment_power = 2;
return true;
}
*/
-bfd_target *
+const bfd_target *
elf_core_file_p (abfd)
bfd *abfd;
{
BFD format expects. */
if (ebd->elf_machine_code != i_ehdrp->e_machine)
{
- bfd_target **target_ptr;
+ const bfd_target * const *target_ptr;
if (ebd->elf_machine_code != EM_NONE)
goto wrong;
Elf_Internal_Shdr *hdr;
size_t symcount;
size_t extsymcount;
+ size_t extsymoff;
Elf_External_Sym *buf = NULL;
struct elf_link_hash_entry **sym_hash;
boolean dynamic;
/* The sh_info field of the symtab header tells us where the
external symbols start. We don't care about the local symbols at
this point. */
- extsymcount = symcount - hdr->sh_info;
+ if (elf_bad_symtab (abfd))
+ {
+ extsymcount = symcount;
+ extsymoff = 0;
+ }
+ else
+ {
+ extsymcount = symcount - hdr->sh_info;
+ extsymoff = hdr->sh_info;
+ }
buf = (Elf_External_Sym *) malloc (extsymcount * sizeof (Elf_External_Sym));
if (buf == NULL && extsymcount != 0)
elf_sym_hashes (abfd) = sym_hash;
if (elf_elfheader (abfd)->e_type != ET_DYN)
- dynamic = false;
+ {
+ dynamic = false;
+
+ /* If we are creating a shared library, create all the dynamic
+ sections immediately. We need to attach them to something,
+ so we attach them to this BFD, provided it is the right
+ format. FIXME: If there are no input BFD's of the same
+ format as the output, we can't make a shared library. */
+ if (info->shared
+ && elf_hash_table (info)->dynobj == NULL
+ && abfd->xvec == info->hash->creator)
+ {
+ if (! elf_link_create_dynamic_sections (abfd, info))
+ goto error_return;
+ elf_hash_table (info)->dynobj = abfd;
+ }
+ }
else
{
asection *s;
/* Find the name to use in a DT_NEEDED entry that refers to this
object. If the object has a DT_SONAME entry, we use it.
- Otherwise, we use the file name. */
+ Otherwise, if the generic linker stuck something in
+ elf_dt_needed_name, we use that. Otherwise, we just use the
+ file name. */
name = bfd_get_filename (abfd);
+ if (elf_dt_needed_name (abfd) != NULL)
+ name = elf_dt_needed_name (abfd);
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL)
{
}
if (bfd_seek (abfd,
- hdr->sh_offset + hdr->sh_info * sizeof (Elf_External_Sym),
+ hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
SEEK_SET) != 0
|| (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
!= extsymcount * sizeof (Elf_External_Sym)))
{
/* This should be impossible, since ELF requires that all
global symbols follow all local symbols, and that sh_info
- point to the first global symbol. */
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
+ point to the first global symbol. Unfortunatealy, Irix 5
+ screws this up. */
+ continue;
}
else if (bind == STB_GLOBAL)
flags = BSF_GLOBAL;
}
if (sym.st_shndx == SHN_UNDEF)
- sec = &bfd_und_section;
+ sec = bfd_und_section_ptr;
else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)
{
sec = section_from_elf_index (abfd, sym.st_shndx);
value -= sec->vma;
}
else if (sym.st_shndx == SHN_ABS)
- sec = &bfd_abs_section;
+ sec = bfd_abs_section_ptr;
else if (sym.st_shndx == SHN_COMMON)
{
- sec = &bfd_com_section;
+ sec = bfd_com_section_ptr;
/* What ELF calls the size we call the value. What ELF
calls the value we call the alignment. */
value = sym.st_size;
goto error_return;
}
- if (sec == &bfd_und_section
+ if (bfd_is_und_section (sec)
|| bfd_is_com_section (sec))
definition = false;
else
by some other object. If it has, we want to use the
existing definition, and we do not want to report a
multiple symbol definition error; we do this by
- clobbering sec to be bfd_und_section. */
+ clobbering sec to be bfd_und_section_ptr. */
if (dynamic && definition)
{
if (h->root.type == bfd_link_hash_defined)
- sec = &bfd_und_section;
+ sec = bfd_und_section_ptr;
}
/* Similarly, if we are not looking at a dynamic object, and
with the new definition. */
h->root.type = bfd_link_hash_undefined;
h->root.u.undef.abfd = h->root.u.def.section->owner;
+ h->elf_link_hash_flags &=~ ELF_LINK_HASH_DEFINED_WEAK;
}
+
+ /* If this is a weak definition which we are going to use,
+ and the symbol is currently undefined, record that the
+ definition is weak. */
+ if (definition
+ && (flags & BSF_WEAK) != 0
+ && ! bfd_is_und_section (sec)
+ && (h->root.type == bfd_link_hash_new
+ || h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_weak))
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEFINED_WEAK;
}
if (! (_bfd_generic_link_add_one_symbol
sections. */
flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
- s = bfd_make_section (abfd, ".interp");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
- return false;
+ /* A dynamically linked executable has a .interp section, but a
+ shared library does not. */
+ if (! info->shared)
+ {
+ s = bfd_make_section (abfd, ".interp");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
+ return false;
+ }
s = bfd_make_section (abfd, ".dynamic");
if (s == NULL
addresses of the various sections. */
boolean
-NAME(bfd_elf,size_dynamic_sections) (output_bfd, info)
+NAME(bfd_elf,size_dynamic_sections) (output_bfd, rpath, info, sinterpptr)
bfd *output_bfd;
+ const char *rpath;
struct bfd_link_info *info;
+ asection **sinterpptr;
{
bfd *dynobj;
size_t dynsymcount;
size_t bucketcount;
struct elf_backend_data *bed;
+ *sinterpptr = NULL;
+
dynobj = elf_hash_table (info)->dynobj;
dynsymcount = elf_hash_table (info)->dynsymcount;
if (dynobj == NULL)
return true;
+ *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (*sinterpptr != NULL || info->shared);
+
/* Set the size of the .dynsym and .hash sections. We counted the
number of dynamic symbols in elf_link_add_object_symbols. We
will build the contents of .dynsym and .hash when we build the
elf_hash_table (info)->bucketcount = bucketcount;
+ if (rpath != NULL)
+ {
+ unsigned long indx;
+
+ indx = bfd_add_to_strtab (dynobj, elf_hash_table (info)->dynstr, rpath);
+ if (indx == (unsigned long) -1
+ || ! elf_add_dynamic_entry (info, DT_RPATH, indx))
+ return false;
+ }
+
s = bfd_get_section_by_name (dynobj, ".dynstr");
BFD_ASSERT (s != NULL);
s->_raw_size = elf_hash_table (info)->dynstr->length;
};
static boolean elf_link_output_sym
- PARAMS ((struct elf_final_link_info *, const char *, Elf_Internal_Sym *));
+ PARAMS ((struct elf_final_link_info *, const char *,
+ Elf_Internal_Sym *, asection *));
static boolean elf_link_flush_output_syms
PARAMS ((struct elf_final_link_info *));
static boolean elf_link_output_extsym
unsigned int i;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Shdr *symstrtab_hdr;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (info->shared)
+ {
+ fprintf (stderr,
+ "Generating ELF shared libraries is not yet supported\n");
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
dynobj = elf_hash_table (info)->dynobj;
/* We are interested in just local symbols, not all
symbols. */
- if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
- && (elf_tdata (sec->owner)->symtab_hdr.sh_info
- > max_sym_count))
- max_sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
-
- if ((sec->flags & SEC_RELOC) != 0)
+ if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour)
{
- size_t ext_size;
+ size_t sym_count;
+
+ if (elf_bad_symtab (sec->owner))
+ sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
+ / sizeof (Elf_External_Sym));
+ else
+ sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
+
+ if (sym_count > max_sym_count)
+ max_sym_count = sym_count;
+
+ if ((sec->flags & SEC_RELOC) != 0)
+ {
+ size_t ext_size;
- ext_size = elf_section_data (sec)->rel_hdr.sh_size;
- if (ext_size > max_external_reloc_size)
- max_external_reloc_size = ext_size;
- if (sec->reloc_count > max_internal_reloc_count)
- max_internal_reloc_count = sec->reloc_count;
+ ext_size = elf_section_data (sec)->rel_hdr.sh_size;
+ if (ext_size > max_external_reloc_size)
+ max_external_reloc_size = ext_size;
+ if (sec->reloc_count > max_internal_reloc_count)
+ max_internal_reloc_count = sec->reloc_count;
+ }
}
}
}
elfsym.st_info = 0;
elfsym.st_other = 0;
elfsym.st_shndx = SHN_UNDEF;
- if (! elf_link_output_sym (&finfo, (const char *) NULL, &elfsym))
+ if (! elf_link_output_sym (&finfo, (const char *) NULL,
+ &elfsym, bfd_und_section_ptr))
goto error_return;
#if 0
elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
elfsym.st_other = 0;
elfsym.st_shndx = SHN_ABS;
- if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd), &elfsym))
+ if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
+ &elfsym, bfd_abs_section_ptr))
goto error_return;
#endif
for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
{
o = section_from_elf_index (abfd, i);
- if (o != &bfd_abs_section)
+ if (! bfd_is_abs_section (o))
o->target_index = abfd->symcount;
elfsym.st_shndx = i;
- if (! elf_link_output_sym (&finfo, (const char *) NULL, &elfsym))
+ if (! elf_link_output_sym (&finfo, (const char *) NULL,
+ &elfsym, o))
goto error_return;
}
if (dynobj != NULL)
{
Elf_External_Dyn *dyncon, *dynconend;
- struct elf_backend_data *bed;
/* Fix up .dynamic entries. */
o = bfd_get_section_by_name (dynobj, ".dynamic");
}
}
- bed = get_elf_backend_data (abfd);
if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
goto error_return;
for (o = dynobj->sections; o != NULL; o = o->next)
{
- Elf_Internal_Shdr *hdr;
- asection *s;
- const char *name;
-
if ((o->flags & SEC_HAS_CONTENTS) == 0)
continue;
- BFD_ASSERT ((o->flags & SEC_IN_MEMORY) != 0);
+ if ((o->flags & SEC_IN_MEMORY) == 0)
+ {
+ BFD_ASSERT (info->shared);
+ continue;
+ }
if (! bfd_set_section_contents (abfd, o->output_section,
o->contents, o->output_offset,
o->_raw_size))
goto error_return;
-
- hdr = &elf_section_data (o->output_section)->this_hdr;
- switch (hdr->sh_type)
- {
- case SHT_DYNAMIC:
- s = bfd_get_section_by_name (abfd, ".dynstr");
- hdr->sh_link = elf_section_data (s)->this_idx;
- hdr->sh_entsize = sizeof (Elf_External_Dyn);
- break;
-
- case SHT_HASH:
- s = finfo.dynsym_sec->output_section;
- hdr->sh_link = elf_section_data (s)->this_idx;
- hdr->sh_entsize = ARCH_SIZE / 8;
- break;
-
- case SHT_DYNSYM:
- s = bfd_get_section_by_name (abfd, ".dynstr");
- hdr->sh_link = elf_section_data (s)->this_idx;
- hdr->sh_entsize = sizeof (Elf_External_Sym);
- break;
-
- case SHT_REL:
- case SHT_RELA:
- name = bfd_get_section_name (abfd, o->output_section);
- s = finfo.dynsym_sec->output_section;
- hdr->sh_link = elf_section_data (s)->this_idx;
- if (hdr->sh_type == SHT_REL)
- {
- name += 4;
- hdr->sh_entsize = sizeof (Elf_External_Rel);
- }
- else
- {
- name += 5;
- hdr->sh_entsize = sizeof (Elf_External_Rela);
- }
- s = bfd_get_section_by_name (abfd, name);
- if (s != NULL)
- hdr->sh_info = elf_section_data (s)->this_idx;
- break;
- }
}
}
+ /* Now backend stuff. */
+ if (bed->elf_backend_final_write_processing)
+ (*bed->elf_backend_final_write_processing) (abfd, NULL);
+
if (finfo.contents != NULL)
free (finfo.contents);
if (finfo.external_relocs != NULL)
/* Add a symbol to the output symbol table. */
static boolean
-elf_link_output_sym (finfo, name, elfsym)
+elf_link_output_sym (finfo, name, elfsym, input_sec)
struct elf_final_link_info *finfo;
const char *name;
Elf_Internal_Sym *elfsym;
+ asection *input_sec;
{
+ boolean (*output_symbol_hook) PARAMS ((bfd *,
+ struct bfd_link_info *info,
+ const char *,
+ Elf_Internal_Sym *,
+ asection *));
+
+ output_symbol_hook = get_elf_backend_data (finfo->output_bfd)->
+ elf_backend_link_output_symbol_hook;
+ if (output_symbol_hook != NULL)
+ {
+ if (! ((*output_symbol_hook)
+ (finfo->output_bfd, finfo->info, name, elfsym, input_sec)))
+ return false;
+ }
+
if (name == (const char *) NULL || *name == '\0')
elfsym->st_name = 0;
else
struct elf_final_link_info *finfo = (struct elf_final_link_info *) data;
boolean strip;
Elf_Internal_Sym sym;
+ asection *input_sec;
/* We don't want to output symbols that have never been mentioned by
a regular file, or that we have been told to strip. However, if
output it. */
if (h->indx == -2)
strip = false;
- else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ else if (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
strip = true;
else if (finfo->info->strip == strip_all
sym.st_value = 0;
sym.st_size = h->size;
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
sym.st_other = 0;
+ if (h->root.type == bfd_link_hash_weak
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0)
+ sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+ else
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
switch (h->root.type)
{
return false;
case bfd_link_hash_undefined:
+ input_sec = bfd_und_section_ptr;
sym.st_shndx = SHN_UNDEF;
break;
case bfd_link_hash_weak:
+ input_sec = bfd_und_section_ptr;
sym.st_shndx = SHN_UNDEF;
- sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
break;
case bfd_link_hash_defined:
{
- asection *sec;
- sec = h->root.u.def.section;
- if (sec->output_section != NULL)
+ input_sec = h->root.u.def.section;
+ if (input_sec->output_section != NULL)
{
sym.st_shndx = elf_section_from_bfd_section (finfo->output_bfd,
- sec->output_section);
+ input_sec->output_section);
if (sym.st_shndx == (unsigned short) -1)
{
/* FIXME: No way to handle errors. */
/* ELF symbols in relocateable files are section relative,
but in nonrelocateable files they are virtual
addresses. */
- sym.st_value = h->root.u.def.value + sec->output_offset;
+ sym.st_value = h->root.u.def.value + input_sec->output_offset;
if (! finfo->info->relocateable)
- sym.st_value += sec->output_section->vma;
+ sym.st_value += input_sec->output_section->vma;
}
else
{
- BFD_ASSERT (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour
- && elf_elfheader (sec->owner)->e_type == ET_DYN);
+ BFD_ASSERT (bfd_get_flavour (input_sec->owner)
+ == bfd_target_elf_flavour
+ && elf_elfheader (input_sec->owner)->e_type == ET_DYN);
sym.st_shndx = SHN_UNDEF;
+ input_sec = bfd_und_section_ptr;
}
}
break;
case bfd_link_hash_common:
+ input_sec = bfd_com_section_ptr;
sym.st_shndx = SHN_COMMON;
if (h->align == 0)
sym.st_value = 1;
h->indx = finfo->output_bfd->symcount;
- if (! elf_link_output_sym (finfo, h->root.root.string, &sym))
+ if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec))
{
/* FIXME: No way to return error. */
abort ();
bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *,
Elf_Internal_Sym *,
- asection **));
+ asection **, char *));
bfd *output_bfd;
Elf_Internal_Shdr *symtab_hdr;
+ size_t locsymcount;
+ size_t extsymoff;
Elf_External_Sym *esym;
Elf_External_Sym *esymend;
Elf_Internal_Sym *isym;
if (elf_elfheader (input_bfd)->e_type == ET_DYN)
return true;
- /* Read the local symbols. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
- if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (finfo->external_syms, sizeof (Elf_External_Sym),
- symtab_hdr->sh_info, input_bfd)
- != symtab_hdr->sh_info * sizeof (Elf_External_Sym)))
+ if (elf_bad_symtab (input_bfd))
+ {
+ locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
+ extsymoff = 0;
+ }
+ else
+ {
+ locsymcount = symtab_hdr->sh_info;
+ extsymoff = symtab_hdr->sh_info;
+ }
+
+ /* Read the local symbols. */
+ if (locsymcount > 0
+ && (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+ || (bfd_read (finfo->external_syms, sizeof (Elf_External_Sym),
+ locsymcount, input_bfd)
+ != locsymcount * sizeof (Elf_External_Sym))))
return false;
/* Swap in the local symbols and write out the ones which we know
are going into the output file. */
esym = finfo->external_syms;
- esymend = esym + symtab_hdr->sh_info;
+ esymend = esym + locsymcount;
isym = finfo->internal_syms;
pindex = finfo->indices;
ppsection = finfo->sections;
elf_swap_symbol_in (input_bfd, esym, isym);
*pindex = -1;
+ if (elf_bad_symtab (input_bfd))
+ {
+ if (ELF_ST_BIND (isym->st_info) != STB_LOCAL)
+ {
+ *ppsection = NULL;
+ continue;
+ }
+ }
+
if (isym->st_shndx == SHN_UNDEF)
- isec = &bfd_und_section;
+ isec = bfd_und_section_ptr;
else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
{
isec = section_from_elf_index (input_bfd, isym->st_shndx);
return false;
}
else if (isym->st_shndx == SHN_ABS)
- isec = &bfd_abs_section;
+ isec = bfd_abs_section_ptr;
else if (isym->st_shndx == SHN_COMMON)
- isec = &bfd_com_section;
+ isec = bfd_com_section_ptr;
else
{
/* Who knows? */
if (! finfo->info->relocateable)
isym->st_value += isec->output_section->vma;
- if (! elf_link_output_sym (finfo, name, isym))
+ if (! elf_link_output_sym (finfo, name, isym, isec))
return false;
/* Restore the old value for reloc handling. */
if ((o->flags & SEC_HAS_CONTENTS) == 0)
continue;
+ if ((o->flags & SEC_IN_MEMORY) != 0
+ && input_bfd == elf_hash_table (finfo->info)->dynobj)
+ {
+ /* Section was created by elf_link_create_dynamic_sections.
+ FIXME: This test is fragile. */
+ continue;
+ }
+
/* Read the contents of the section. */
if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
(file_ptr) 0, o->_raw_size))
if ((o->flags & SEC_RELOC) != 0)
{
- /* Read in the relocs. */
- input_rel_hdr = &elf_section_data (o)->rel_hdr;
- if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
- || bfd_read (finfo->external_relocs, 1, input_rel_hdr->sh_size,
- input_bfd) != input_rel_hdr->sh_size)
- return false;
+ PTR external_relocs;
+
+ /* Get the external relocs. They may have been cached. */
+ external_relocs = elf_section_data (o)->relocs;
+ if (external_relocs == NULL)
+ {
+ input_rel_hdr = &elf_section_data (o)->rel_hdr;
+ if ((bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET)
+ != 0)
+ || (bfd_read (finfo->external_relocs, 1,
+ input_rel_hdr->sh_size, input_bfd)
+ != input_rel_hdr->sh_size))
+ return false;
+ external_relocs = finfo->external_relocs;
+ }
/* Swap in the relocs. For convenience, we always produce
an Elf_Internal_Rela array; if the relocs are Rel, we set
Elf_External_Rel *erelend;
Elf_Internal_Rela *irela;
- erel = (Elf_External_Rel *) finfo->external_relocs;
+ erel = (Elf_External_Rel *) external_relocs;
erelend = erel + o->reloc_count;
irela = finfo->internal_relocs;
for (; erel < erelend; erel++, irela++)
BFD_ASSERT (input_rel_hdr->sh_entsize
== sizeof (Elf_External_Rela));
- erela = (Elf_External_Rela *) finfo->external_relocs;
+ erela = (Elf_External_Rela *) external_relocs;
erelaend = erela + o->reloc_count;
irela = finfo->internal_relocs;
for (; erela < erelaend; erela++, irela++)
finfo->contents,
finfo->internal_relocs,
finfo->internal_syms,
- finfo->sections))
+ finfo->sections,
+ finfo->symstrtab->tab))
return false;
if (finfo->info->relocateable)
if (r_symndx == 0)
continue;
- if (r_symndx >= symtab_hdr->sh_info)
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && finfo->sections[r_symndx] == NULL))
{
long indx;
reloc to point to the global hash table entry
for this symbol. The symbol index is then
set at the end of elf_bfd_final_link. */
- indx = r_symndx - symtab_hdr->sh_info;
+ indx = r_symndx - extsymoff;
*rel_hash = elf_sym_hashes (input_bfd)[indx];
/* Setting the index to -2 tells
/* I suppose the backend ought to fill in the
section of any STT_SECTION symbol against a
processor specific section. */
- if (sec == NULL
- || sec == &bfd_und_section
- || sec == &bfd_com_section)
+ if (sec != NULL && bfd_is_abs_section (sec))
+ r_symndx = 0;
+ else if (sec == NULL || sec->owner == NULL)
{
bfd_set_error (bfd_error_bad_value);
return false;
}
- else if (sec == &bfd_abs_section)
- r_symndx = 0;
else
{
r_symndx = sec->output_section->target_index;
finfo->indices[r_symndx] = output_bfd->symcount;
- if (! elf_link_output_sym (finfo, name, isym))
+ if (! elf_link_output_sym (finfo, name, isym, sec))
return false;
}