/* ELF executable support for BFD.
- Copyright 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999, 2000 Free
+ Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
in "UNIX System V Release 4, Programmers Guide: ANSI C and
#define elf_add_dynamic_entry NAME(bfd_elf,add_dynamic_entry)
#define elf_write_shdrs_and_ehdr NAME(bfd_elf,write_shdrs_and_ehdr)
#define elf_write_out_phdrs NAME(bfd_elf,write_out_phdrs)
+#define elf_write_relocs NAME(bfd_elf,write_relocs)
+#define elf_slurp_reloc_table NAME(bfd_elf,slurp_reloc_table)
#define elf_link_create_dynamic_sections \
NAME(bfd_elf,link_create_dynamic_sections)
#define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
#define elf_gc_common_final_link NAME(_bfd_elf,gc_common_final_link)
#define elf_gc_record_vtinherit NAME(_bfd_elf,gc_record_vtinherit)
#define elf_gc_record_vtentry NAME(_bfd_elf,gc_record_vtentry)
+#define elf_link_record_local_dynamic_symbol \
+ NAME(_bfd_elf,link_record_local_dynamic_symbol)
#if ARCH_SIZE == 64
#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y)
#define section_from_elf_index bfd_section_from_elf_index
-static boolean elf_slurp_reloc_table
- PARAMS ((bfd *, asection *, asymbol **, boolean));
-
-static void write_relocs PARAMS ((bfd *, asection *, PTR));
+static boolean elf_slurp_reloc_table_from_section
+ PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, bfd_size_type,
+ arelent *, asymbol **, boolean));
static boolean elf_file_p PARAMS ((Elf_External_Ehdr *));
const Elf_External_Sym *src;
Elf_Internal_Sym *dst;
{
+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+
dst->st_name = bfd_h_get_32 (abfd, (bfd_byte *) src->st_name);
- dst->st_value = get_word (abfd, (bfd_byte *) src->st_value);
+ if (signed_vma)
+ dst->st_value = get_signed_word (abfd, (bfd_byte *) src->st_value);
+ else
+ dst->st_value = get_word (abfd, (bfd_byte *) src->st_value);
dst->st_size = get_word (abfd, (bfd_byte *) src->st_size);
dst->st_info = bfd_h_get_8 (abfd, (bfd_byte *) src->st_info);
dst->st_other = bfd_h_get_8 (abfd, (bfd_byte *) src->st_other);
const Elf_External_Ehdr *src;
Elf_Internal_Ehdr *dst;
{
+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
dst->e_type = bfd_h_get_16 (abfd, (bfd_byte *) src->e_type);
dst->e_machine = bfd_h_get_16 (abfd, (bfd_byte *) src->e_machine);
dst->e_version = bfd_h_get_32 (abfd, (bfd_byte *) src->e_version);
- dst->e_entry = get_word (abfd, (bfd_byte *) src->e_entry);
+ if (signed_vma)
+ dst->e_entry = get_signed_word (abfd, (bfd_byte *) src->e_entry);
+ else
+ dst->e_entry = get_word (abfd, (bfd_byte *) src->e_entry);
dst->e_phoff = get_word (abfd, (bfd_byte *) src->e_phoff);
dst->e_shoff = get_word (abfd, (bfd_byte *) src->e_shoff);
dst->e_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->e_flags);
const Elf_Internal_Ehdr *src;
Elf_External_Ehdr *dst;
{
+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
/* note that all elements of dst are *arrays of unsigned char* already... */
bfd_h_put_16 (abfd, src->e_type, dst->e_type);
bfd_h_put_16 (abfd, src->e_machine, dst->e_machine);
bfd_h_put_32 (abfd, src->e_version, dst->e_version);
- put_word (abfd, src->e_entry, dst->e_entry);
+ if (signed_vma)
+ put_signed_word (abfd, src->e_entry, dst->e_entry);
+ else
+ put_word (abfd, src->e_entry, dst->e_entry);
put_word (abfd, src->e_phoff, dst->e_phoff);
put_word (abfd, src->e_shoff, dst->e_shoff);
bfd_h_put_32 (abfd, src->e_flags, dst->e_flags);
const Elf_External_Shdr *src;
Elf_Internal_Shdr *dst;
{
+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+
dst->sh_name = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_name);
dst->sh_type = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_type);
dst->sh_flags = get_word (abfd, (bfd_byte *) src->sh_flags);
- dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr);
+ if (signed_vma)
+ dst->sh_addr = get_signed_word (abfd, (bfd_byte *) src->sh_addr);
+ else
+ dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr);
dst->sh_offset = get_word (abfd, (bfd_byte *) src->sh_offset);
dst->sh_size = get_word (abfd, (bfd_byte *) src->sh_size);
dst->sh_link = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_link);
const Elf_External_Phdr *src;
Elf_Internal_Phdr *dst;
{
+ int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
+
dst->p_type = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type);
dst->p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->p_flags);
dst->p_offset = get_word (abfd, (bfd_byte *) src->p_offset);
- dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr);
- dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr);
+ if (signed_vma)
+ {
+ dst->p_vaddr = get_signed_word (abfd, (bfd_byte *) src->p_vaddr);
+ dst->p_paddr = get_signed_word (abfd, (bfd_byte *) src->p_paddr);
+ }
+ else
+ {
+ dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr);
+ dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr);
+ }
dst->p_filesz = get_word (abfd, (bfd_byte *) src->p_filesz);
dst->p_memsz = get_word (abfd, (bfd_byte *) src->p_memsz);
dst->p_align = get_word (abfd, (bfd_byte *) src->p_align);
}
INLINE void
-elf_swap_dyn_out (abfd, src, dst)
+elf_swap_dyn_out (abfd, src, p)
bfd *abfd;
const Elf_Internal_Dyn *src;
- Elf_External_Dyn *dst;
+ PTR p;
{
+ Elf_External_Dyn *dst = (Elf_External_Dyn *) p;
+
put_word (abfd, src->d_tag, dst->d_tag);
put_word (abfd, src->d_un.d_val, dst->d_un.d_val);
}
char *shstrtab; /* Internal copy of section header stringtab */
struct elf_backend_data *ebd;
struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
+ struct sec *preserved_sections = abfd->sections;
+ unsigned int preserved_section_count = abfd->section_count;
struct elf_obj_tdata *new_tdata = NULL;
asection *s;
+ /* Clear section information, since there might be a recognized bfd that
+ we now check if we can replace, and we don't want to append to it. */
+ abfd->sections = NULL;
+ abfd->section_count = 0;
+
/* Read in the ELF header in external format. */
if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr))
}
/* Remember the entry point specified in the ELF file header. */
- bfd_get_start_address (abfd) = i_ehdrp->e_entry;
+ bfd_set_start_address (abfd, i_ehdrp->e_entry);
/* Allocate space for a copy of the section header table in
internal form, seek to the section header table in the file,
if (new_tdata != NULL)
bfd_release (abfd, new_tdata);
elf_tdata (abfd) = preserved_tdata;
+ abfd->sections = preserved_sections;
+ abfd->section_count = preserved_section_count;
return (NULL);
}
\f
/* Write out the relocs. */
-static void
-write_relocs (abfd, sec, data)
+void
+elf_write_relocs (abfd, sec, data)
bfd *abfd;
asection *sec;
PTR data;
Elf_External_Rela *outbound_relocas;
Elf_External_Rel *outbound_relocs;
unsigned int idx;
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+ int use_rela_p;
asymbol *last_sym = 0;
int last_sym_idx = 0;
return;
}
+ /* Figure out whether the relocations are RELA or REL relocations. */
+ if (rela_hdr->sh_type == SHT_RELA)
+ use_rela_p = true;
+ else if (rela_hdr->sh_type == SHT_REL)
+ use_rela_p = false;
+ else
+ /* Every relocation section should be either an SHT_RELA or an
+ SHT_REL section. */
+ abort ();
+
/* orelocation has the data, reloc_count has the count... */
if (use_rela_p)
{
if (sym == last_sym)
n = last_sym_idx;
+ else if (bfd_is_abs_section (sym->section) && sym->value == 0)
+ n = STN_UNDEF;
else
{
last_sym = sym;
last_sym_idx = n;
}
- if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+ if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
+ && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
&& ! _bfd_elf_validate_reloc (abfd, ptr))
{
*failedp = true;
return -1;
}
-/* Read in and swap the external relocs. */
+/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of
+ them. */
static boolean
-elf_slurp_reloc_table (abfd, asect, symbols, dynamic)
+elf_slurp_reloc_table_from_section (abfd, asect, rel_hdr, reloc_count,
+ relents, symbols, dynamic)
bfd *abfd;
asection *asect;
+ Elf_Internal_Shdr *rel_hdr;
+ bfd_size_type reloc_count;
+ arelent *relents;
asymbol **symbols;
boolean dynamic;
{
struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
- struct bfd_elf_section_data * const d = elf_section_data (asect);
- Elf_Internal_Shdr *rel_hdr;
- bfd_size_type reloc_count;
PTR allocated = NULL;
bfd_byte *native_relocs;
- arelent *relents;
arelent *relent;
unsigned int i;
int entsize;
- if (asect->relocation != NULL)
- return true;
-
- if (! dynamic)
- {
- if ((asect->flags & SEC_RELOC) == 0
- || asect->reloc_count == 0)
- return true;
-
- rel_hdr = &d->rel_hdr;
- reloc_count = asect->reloc_count;
-
- BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
- && reloc_count == rel_hdr->sh_size / rel_hdr->sh_entsize);
- }
- else
- {
- if (asect->_raw_size == 0)
- return true;
-
- rel_hdr = &d->this_hdr;
- reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize;
- }
-
allocated = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size);
if (allocated == NULL)
goto error_return;
native_relocs = (bfd_byte *) allocated;
- relents = (arelent *) bfd_alloc (abfd, reloc_count * sizeof (arelent));
- if (relents == NULL)
- goto error_return;
-
entsize = rel_hdr->sh_entsize;
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
|| entsize == sizeof (Elf_External_Rela));
(*ebd->elf_info_to_howto_rel) (abfd, relent, &rel);
}
- asect->relocation = relents;
-
if (allocated != NULL)
free (allocated);
return false;
}
+/* Read in and swap the external relocs. */
+
+boolean
+elf_slurp_reloc_table (abfd, asect, symbols, dynamic)
+ bfd *abfd;
+ asection *asect;
+ asymbol **symbols;
+ boolean dynamic;
+{
+ struct bfd_elf_section_data * const d = elf_section_data (asect);
+ Elf_Internal_Shdr *rel_hdr;
+ Elf_Internal_Shdr *rel_hdr2;
+ bfd_size_type reloc_count;
+ bfd_size_type reloc_count2;
+ arelent *relents;
+
+ if (asect->relocation != NULL)
+ return true;
+
+ if (! dynamic)
+ {
+ if ((asect->flags & SEC_RELOC) == 0
+ || asect->reloc_count == 0)
+ return true;
+
+ rel_hdr = &d->rel_hdr;
+ reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize;
+ rel_hdr2 = d->rel_hdr2;
+ reloc_count2 = (rel_hdr2
+ ? (rel_hdr2->sh_size / rel_hdr2->sh_entsize)
+ : 0);
+
+ BFD_ASSERT (asect->reloc_count == reloc_count + reloc_count2);
+ BFD_ASSERT (asect->rel_filepos == rel_hdr->sh_offset
+ || (rel_hdr2 && asect->rel_filepos == rel_hdr2->sh_offset));
+
+ }
+ else
+ {
+ /* Note that ASECT->RELOC_COUNT tends not to be accurate in this
+ case because relocations against this section may use the
+ dynamic symbol table, and in that case bfd_section_from_shdr
+ in elf.c does not update the RELOC_COUNT. */
+ if (asect->_raw_size == 0)
+ return true;
+
+ rel_hdr = &d->this_hdr;
+ reloc_count = rel_hdr->sh_size / rel_hdr->sh_entsize;
+ rel_hdr2 = NULL;
+ reloc_count2 = 0;
+ }
+
+ relents = ((arelent *)
+ bfd_alloc (abfd,
+ (reloc_count + reloc_count2) * sizeof (arelent)));
+ if (relents == NULL)
+ return false;
+
+ if (!elf_slurp_reloc_table_from_section (abfd, asect,
+ rel_hdr, reloc_count,
+ relents,
+ symbols, dynamic))
+ return false;
+
+ if (rel_hdr2
+ && !elf_slurp_reloc_table_from_section (abfd, asect,
+ rel_hdr2, reloc_count2,
+ relents + reloc_count,
+ symbols, dynamic))
+ return false;
+
+
+ asect->relocation = relents;
+ return true;
+}
+
#ifdef DEBUG
static void
elf_debug_section (num, hdr)
sizeof (Elf_External_Sym),
sizeof (Elf_External_Dyn),
sizeof (Elf_External_Note),
-
+ 4,
+ 1,
ARCH_SIZE, FILE_ALIGN,
ELFCLASS, EV_CURRENT,
elf_write_out_phdrs,
elf_write_shdrs_and_ehdr,
- write_relocs,
+ elf_write_relocs,
elf_swap_symbol_out,
elf_slurp_reloc_table,
elf_slurp_symbol_table,
- elf_swap_dyn_in
+ elf_swap_dyn_in,
+ elf_swap_dyn_out,
+ NULL,
+ NULL,
+ NULL,
+ NULL
};