aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/coff-i386.c2
-rw-r--r--bfd/elf32-ppc.c44
3 files changed, 45 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 2bcd7bd..1304661 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2004-06-22 Alan Modra <amodra@bigpond.net.au>
+
+ * elf32-ppc.c (ppc_elf_relax_section): Implement reference code
+ for handling SEC_MERGE symbols in relax_section.
+
2004-06-21 Alexandre Oliva <aoliva@redhat.com>
2003-05-15 Richard Sandiford <rsandifo@redhat.com>
diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index e2bf860..65700b6 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -1,6 +1,6 @@
/* BFD back-end for Intel 386 COFF files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003
+ 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Written by Cygnus Support.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index be05270..c4b46f6 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -1723,6 +1723,7 @@ ppc_elf_relax_section (bfd *abfd,
bfd_vma max_branch_offset, val;
bfd_byte *hit_addr;
unsigned long t0;
+ unsigned char sym_type;
switch (r_type)
{
@@ -1770,6 +1771,7 @@ ppc_elf_relax_section (bfd *abfd,
tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
toff = isym->st_value;
+ sym_type = ELF_ST_TYPE (isym->st_info);
}
else
{
@@ -1799,6 +1801,8 @@ ppc_elf_relax_section (bfd *abfd,
}
else
continue;
+
+ sym_type = h->type;
}
/* If the branch and target are in the same section, you have
@@ -1807,11 +1811,41 @@ ppc_elf_relax_section (bfd *abfd,
if (tsec == isec)
continue;
- toff += irel->r_addend;
- if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
- toff = _bfd_merged_section_offset (abfd, &tsec,
- elf_section_data (tsec)->sec_info,
- toff);
+ /* There probably isn't any reason to handle symbols in
+ SEC_MERGE sections; SEC_MERGE doesn't seem a likely
+ attribute for a code section, and we are only looking at
+ branches. However, implement it correctly here as a
+ reference for other target relax_section functions. */
+ if (0 && tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
+ {
+ /* At this stage in linking, no SEC_MERGE symbol has been
+ adjusted, so all references to such symbols need to be
+ passed through _bfd_merged_section_offset. (Later, in
+ relocate_section, all SEC_MERGE symbols *except* for
+ section symbols have been adjusted.)
+
+ gas may reduce relocations against symbols in SEC_MERGE
+ sections to a relocation against the section symbol when
+ the original addend was zero. When the reloc is against
+ a section symbol we should include the addend in the
+ offset passed to _bfd_merged_section_offset, since the
+ location of interest is the original symbol. On the
+ other hand, an access to "sym+addend" where "sym" is not
+ a section symbol should not include the addend; Such an
+ access is presumed to be an offset from "sym"; The
+ location of interest is just "sym". */
+ if (sym_type == STT_SECTION)
+ toff += irel->r_addend;
+
+ toff = _bfd_merged_section_offset (abfd, &tsec,
+ elf_section_data (tsec)->sec_info,
+ toff);
+
+ if (sym_type != STT_SECTION)
+ toff += irel->r_addend;
+ }
+ else
+ toff += irel->r_addend;
symaddr = tsec->output_section->vma + tsec->output_offset + toff;