* elf-bfd.h (struct bfd_elf_section_reloc_data): New structure.
	(struct bfd_elf_section_data): New members REL and RELA; delete
	members REL_HDR, REL_HDR2, REL_COUNT, REL_COUNT2, REL_IDX,
	REL_IDX2, REL_HASHES.
	(_bfd_elf_init_reloc_shdr): Adjust declaration.
	(_bfd_elf_single_rel_hdr): Declare.
	(RELOC_AGAINST_DISCARDED_SECTION): Use it.
	* elf.c (bfd_section_from_shdr): Adjusted to match changes in
	data structures.
	(_bfd_elf_init_reloc_shdr): New arg RELDATA.  Remove arg REL_HDR.
	All callers changed.  Allocate memory for the Elf_Internal_Shdr
	structure.
	(_bfd_elf_single_rel_hdr): New function.
	(struct fake_section_arg): New structure.
	(elf_fake_section): Expect to see a pointer to it in the third
	argument.  If doing a relocatable link, allocate both REL and RELA
	sections as needed.
	(assign_section_numbers): Adjusted to match changes in
	data structures.
	(_bfd_elf_compute_section_file_positions): Call elf_fake_sections
	with a struct fake_section_args argument.
	* elfcode.h (elf_write_relocs): Adjusted to match changes in
	data structures.
	(elf_slurp_reloc_table): Likewise.
	* elflink.c (_bfd_elf_link_read_relocs): Likewise.
	(_bfd_elf_link_size_reloc_section): Remove arg REL_HDR, replace with
	RELDATA.  Remove argument O.  All callers changed.  Remove code to
	discover the right rel_hdr and count.
	(_bfd_elf_link_output_relocs): Adjusted to match changes in
	data structures.
	(elf_link_adjust_relocs): Remove args REL_HDR, COUNT and REL_HASH;
	replace with RELDATA.  All callers changed.
	(elf_link_input_bfd): Correctly generate rel_hash data when both
	REL and RELA sections are present.
	(elf_reloc_link_order): Adjusted to match changes in
	data structures.
	(bfd_elf_final_link): Simplify code to count relocs.  Free the
	hashes array for both REL and RELA.
	(get_dynamic_reloc_section_name): Use _bfd_elf_single_reloc_hdr
	* elf32-m32r.c (m32r_elf_fake_sections, elf_backend_fake_sections):
	Delete.
	* elf32-tic6x.c (elf32_tic6x_fake_sections, elf_backend_fake_sections):
	Delete.
	(elf32_tic6x_rel_relocation_p): Adjusted to match changes in
	data structures.
 	* elf32-microblaze.c (microblaze_elf_check_relocs): Use
	_bfd_elf_single_rel_hdr.
	* elf32-ppc.c (ppc_elf_relax_section): Likewise.
	* elf32-spu.c (spu_elf_relocate_section): Likewise.
	* elf64-alpha.c (elf64_alpha_relocate_section): Likewise.
	* elf64-hppa.c (get_reloc_section): Likewise.
	* elf64-mips.c (mips_elf64_slurp_reloc_table): Adjusted to match
	changes in data structures.
	(mips_elf64_write_relocs): Use _bfd_elf_single_rel_hdr.
	* elf64-ppc.c (ppc64_elf_edit_opd): Likewise.
	(ppc64_elf_edit_toc): Likewise.
	(get_relocs): Adjusted to match changes in data structures.
	Allocate an Elf_Internal_Shdr structure if necessary.
	(ppc64_elf_finish_dynamic_sections): Use _bfd_elf_single_rel_hdr.
	* elf64-sparc.c (elf64_sparc_slurp_reloc_table): Adjusted to match
	changes in data structures.
	* elfxx-ia64.c (get_reloc_section): Use _bfd_elf_single_rel_hdr.
	* elfxx-mips.c (MIPS_RELOC_RELA_P): Remove macro.
	(mips_elf_rel_relocation_p): Adjusted to match changes in data
	structures.
	(_bfd_mips_elf_relocate_section): Use mips_elf_rel_relocation_p rather
	than MIPS_RELOC_RELOCA_P.
	* elfxx-sparc.c (_bfd_sparc_elf_check_relocs): Use
	_bfd_elf_single_rel_hdr.
	(_bfd_sparc_elf_relocate_section): Likewise.

ld/
	* emultempl/xtensaelf.em (replace_insn_sec_with_prop_sec): Use
	_bfd_elf_single_rel_hdr.
This commit is contained in:
Bernd Schmidt
2010-10-04 14:13:10 +00:00
parent 83e3a93c83
commit d4730f921a
20 changed files with 456 additions and 414 deletions

176
bfd/elf.c
View File

@ -1710,8 +1710,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
/* *These* do a lot of work -- but build no sections! */
{
asection *target_sect;
Elf_Internal_Shdr *hdr2;
Elf_Internal_Shdr *hdr2, **p_hdr;
unsigned int num_sec = elf_numsections (abfd);
struct bfd_elf_section_data *esdt;
bfd_size_type amt;
if (hdr->sh_entsize
!= (bfd_size_type) (hdr->sh_type == SHT_REL
@ -1790,20 +1792,19 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
if (target_sect == NULL)
return FALSE;
if ((target_sect->flags & SEC_RELOC) == 0
|| target_sect->reloc_count == 0)
hdr2 = &elf_section_data (target_sect)->rel_hdr;
esdt = elf_section_data (target_sect);
if (hdr->sh_type == SHT_RELA)
p_hdr = &esdt->rela.hdr;
else
{
bfd_size_type amt;
BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
amt = sizeof (*hdr2);
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
if (hdr2 == NULL)
return FALSE;
elf_section_data (target_sect)->rel_hdr2 = hdr2;
}
p_hdr = &esdt->rel.hdr;
BFD_ASSERT (*p_hdr == NULL);
amt = sizeof (*hdr2);
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
if (hdr2 == NULL)
return FALSE;
*hdr2 = *hdr;
*p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
target_sect->flags |= SEC_RELOC;
@ -1812,7 +1813,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
/* In the section to which the relocations apply, mark whether
its relocations are of the REL or RELA variety. */
if (hdr->sh_size != 0)
target_sect->use_rela_p = hdr->sh_type == SHT_RELA;
{
if (hdr->sh_type == SHT_RELA)
target_sect->use_rela_p = 1;
}
abfd->flags |= HAS_RELOC;
return TRUE;
}
@ -2410,20 +2414,43 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
}
}
/* Initialize REL_HDR, the section-header for new section, containing
relocations against ASECT. If USE_RELA_P is TRUE, we use RELA
relocations; otherwise, we use REL relocations. */
/* Return the REL_HDR for SEC, assuming there is only a single one, either
REL or RELA. */
Elf_Internal_Shdr *
_bfd_elf_single_rel_hdr (asection *sec)
{
if (elf_section_data (sec)->rel.hdr)
{
BFD_ASSERT (elf_section_data (sec)->rela.hdr == NULL);
return elf_section_data (sec)->rel.hdr;
}
else
return elf_section_data (sec)->rela.hdr;
}
/* Allocate and initialize a section-header for a new reloc section,
containing relocations against ASECT. It is stored in RELDATA. If
USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL
relocations. */
bfd_boolean
_bfd_elf_init_reloc_shdr (bfd *abfd,
Elf_Internal_Shdr *rel_hdr,
struct bfd_elf_section_reloc_data *reldata,
asection *asect,
bfd_boolean use_rela_p)
{
Elf_Internal_Shdr *rel_hdr;
char *name;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
bfd_size_type amt;
amt = sizeof (Elf_Internal_Shdr);
BFD_ASSERT (reldata->hdr == NULL);
rel_hdr = bfd_zalloc (abfd, amt);
reldata->hdr = rel_hdr;
amt = sizeof ".rela" + strlen (asect->name);
name = (char *) bfd_alloc (abfd, amt);
if (name == NULL)
return FALSE;
@ -2457,30 +2484,37 @@ bfd_elf_get_default_section_type (flagword flags)
return SHT_PROGBITS;
}
struct fake_section_arg
{
struct bfd_link_info *link_info;
bfd_boolean failed;
};
/* Set up an ELF internal section header for a section. */
static void
elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
{
struct fake_section_arg *arg = (struct fake_section_arg *)fsarg;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
struct bfd_elf_section_data *esd = elf_section_data (asect);
Elf_Internal_Shdr *this_hdr;
unsigned int sh_type;
if (*failedptr)
if (arg->failed)
{
/* We already failed; just get out of the bfd_map_over_sections
loop. */
return;
}
this_hdr = &elf_section_data (asect)->this_hdr;
this_hdr = &esd->this_hdr;
this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
asect->name, FALSE);
if (this_hdr->sh_name == (unsigned int) -1)
{
*failedptr = TRUE;
arg->failed = TRUE;
return;
}
@ -2632,11 +2666,45 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE)
this_hdr->sh_flags |= SHF_EXCLUDE;
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
this section, it is up to the processor-specific back-end to
create the other. */
if ((asect->flags & SEC_RELOC) != 0)
{
/* When doing a relocatable link, create both REL and RELA sections if
needed. */
if (arg->link_info
/* Do the normal setup if we wouldn't create any sections here. */
&& esd->rel.count + esd->rela.count > 0
&& (arg->link_info->relocatable || arg->link_info->emitrelocations))
{
if (esd->rel.count && esd->rel.hdr == NULL
&& !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, asect, FALSE))
{
arg->failed = TRUE;
return;
}
if (esd->rela.count && esd->rela.hdr == NULL
&& !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, asect, TRUE))
{
arg->failed = TRUE;
return;
}
}
else if (!_bfd_elf_init_reloc_shdr (abfd,
(asect->use_rela_p
? &esd->rela : &esd->rel),
asect,
asect->use_rela_p))
arg->failed = TRUE;
}
/* Check for processor-specific section types. */
sh_type = this_hdr->sh_type;
if (bed->elf_backend_fake_sections
&& !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
*failedptr = TRUE;
arg->failed = TRUE;
if (sh_type == SHT_NOBITS && asect->size != 0)
{
@ -2644,17 +2712,6 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
called for objcopy --only-keep-debug. */
this_hdr->sh_type = sh_type;
}
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
this section, it is up to the processor-specific back-end to
create the other. */
if ((asect->flags & SEC_RELOC) != 0
&& !_bfd_elf_init_reloc_shdr (abfd,
&elf_section_data (asect)->rel_hdr,
asect,
asect->use_rela_p))
*failedptr = TRUE;
}
/* Fill in the contents of a SHT_GROUP section. Called from
@ -2820,21 +2877,21 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
if (d->this_hdr.sh_type != SHT_GROUP)
d->this_idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
if ((sec->flags & SEC_RELOC) == 0)
d->rel_idx = 0;
else
if (d->rel.hdr)
{
d->rel_idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
d->rel.idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name);
}
else
d->rel.idx = 0;
if (d->rel_hdr2)
if (d->rela.hdr)
{
d->rel_idx2 = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
d->rela.idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name);
}
else
d->rel_idx2 = 0;
d->rela.idx = 0;
}
t->shstrtab_section = section_number++;
@ -2906,25 +2963,25 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
d = elf_section_data (sec);
i_shdrp[d->this_idx] = &d->this_hdr;
if (d->rel_idx != 0)
i_shdrp[d->rel_idx] = &d->rel_hdr;
if (d->rel_idx2 != 0)
i_shdrp[d->rel_idx2] = d->rel_hdr2;
if (d->rel.idx != 0)
i_shdrp[d->rel.idx] = d->rel.hdr;
if (d->rela.idx != 0)
i_shdrp[d->rela.idx] = d->rela.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)
if (d->rel.idx != 0)
{
d->rel_hdr.sh_link = t->symtab_section;
d->rel_hdr.sh_info = d->this_idx;
d->rel.hdr->sh_link = t->symtab_section;
d->rel.hdr->sh_info = d->this_idx;
}
if (d->rel_idx2 != 0)
if (d->rela.idx != 0)
{
d->rel_hdr2->sh_link = t->symtab_section;
d->rel_hdr2->sh_info = d->this_idx;
d->rela.hdr->sh_link = t->symtab_section;
d->rela.hdr->sh_info = d->this_idx;
}
/* We need to set up sh_link for SHF_LINK_ORDER. */
@ -3278,6 +3335,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
struct bfd_link_info *link_info)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct fake_section_arg fsargs;
bfd_boolean failed;
struct bfd_strtab_hash *strtab = NULL;
Elf_Internal_Shdr *shstrtab_hdr;
@ -3297,9 +3355,10 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
if (bed->elf_backend_post_process_headers)
(*bed->elf_backend_post_process_headers) (abfd, link_info);
failed = FALSE;
bfd_map_over_sections (abfd, elf_fake_sections, &failed);
if (failed)
fsargs.failed = FALSE;
fsargs.link_info = link_info;
bfd_map_over_sections (abfd, elf_fake_sections, &fsargs);
if (fsargs.failed)
return FALSE;
if (!assign_section_numbers (abfd, link_info))
@ -3319,6 +3378,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
return FALSE;
}
failed = FALSE;
if (link_info == NULL)
{
bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);