aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-07-17 01:15:42 +0000
committerIan Lance Taylor <ian@airs.com>1994-07-17 01:15:42 +0000
commitea61717495bad0a5fe182954bbb1c8a80890a98a (patch)
tree69232719f0957741d2893d9ae0aa49c2e614386b /bfd
parent62a5dabced9c5369448d52c847cb96a388d76e1e (diff)
downloadgdb-ea61717495bad0a5fe182954bbb1c8a80890a98a.zip
gdb-ea61717495bad0a5fe182954bbb1c8a80890a98a.tar.gz
gdb-ea61717495bad0a5fe182954bbb1c8a80890a98a.tar.bz2
* libelf.h (struct bfd_elf_section_data): Add relocs field.
(shdr_name): Remove; unused. * elfcode.h (elf_slurp_reloc_table): Rewrote to handle both REL and RELA relocs. Free up the unswapped relocs. Permit the relocs to be cached in the section_data. Correct the reloc address. (elf_slurp_reloca_table): Remove. (elf_canonicalize_reloc): Rewrote. (elf_link_input_bfd): Permit the relocs to be cached in the section data.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elfcode.h330
-rw-r--r--bfd/libelf.h19
3 files changed, 141 insertions, 220 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 8146194..310c12d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+Sat Jul 16 21:10:39 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * libelf.h (struct bfd_elf_section_data): Add relocs field.
+ (shdr_name): Remove; unused.
+ * elfcode.h (elf_slurp_reloc_table): Rewrote to handle both REL
+ and RELA relocs. Free up the unswapped relocs. Permit the relocs
+ to be cached in the section_data. Correct the reloc address.
+ (elf_slurp_reloca_table): Remove.
+ (elf_canonicalize_reloc): Rewrote.
+ (elf_link_input_bfd): Permit the relocs to be cached in the
+ section data.
+
Sat Jul 16 13:55:38 1994 Stan Shebs (shebs@andros.cygnus.com)
* config.bfd (m88*-harris-cxux*): Recognize.
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index 756d08d..223b751 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -145,6 +145,8 @@ static int elf_section_from_bfd_section PARAMS ((bfd *, struct sec *));
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 **));
@@ -2899,105 +2901,120 @@ elf_get_reloc_upper_bound (abfd, asect)
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_ptr->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
@@ -3045,129 +3062,7 @@ elf_debug_file (ehdrp)
}
#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_ptr->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)
@@ -3176,28 +3071,18 @@ 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;
}
@@ -6041,12 +5926,21 @@ elf_link_input_bfd (finfo, input_bfd)
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
@@ -6057,7 +5951,7 @@ elf_link_input_bfd (finfo, input_bfd)
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++)
@@ -6079,7 +5973,7 @@ elf_link_input_bfd (finfo, input_bfd)
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++)
diff --git a/bfd/libelf.h b/bfd/libelf.h
index 748e482..84f79bb 100644
--- a/bfd/libelf.h
+++ b/bfd/libelf.h
@@ -375,14 +375,29 @@ struct elf_sym_extra
typedef struct elf_sym_extra Elf_Sym_Extra;
+/* Information stored for each BFD section in an ELF file. This
+ structure is allocated by elf_new_section_hook. */
+
struct bfd_elf_section_data {
+ /* The ELF header for this section. */
Elf_Internal_Shdr this_hdr;
+ /* The ELF header for the reloc section associated with this
+ section, if any. */
Elf_Internal_Shdr rel_hdr;
- int this_idx, rel_idx;
+ /* The ELF section number of this section. Only used for an output
+ file. */
+ int this_idx;
+ /* The ELF section number of the reloc section associated with this
+ section, if any. Only used for an output file. */
+ int rel_idx;
+ /* Used by the backend linker to store the symbol hash table entries
+ associated with relocs against global symbols. */
struct elf_link_hash_entry **rel_hashes;
+ /* A pointer to the unswapped external relocs; this may be NULL. */
+ PTR relocs;
};
+
#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
-#define shdr_name(abfd,shdr) (elf_shstrtab (abfd)->tab + (shdr)->sh_name)
#define get_elf_backend_data(abfd) \
((struct elf_backend_data *) (abfd)->xvec->backend_data)