This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: PATCH: BZ/175: Fix dynamic string offset
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: "H. J. Lu" <hjl at gcc dot gnu dot org>
- Cc: Jim Wilson <wilson at specifixinc dot com>, jakub at redhat dot com,binutils at sources dot redhat dot com
- Date: Sun, 6 Jun 2004 10:15:29 +0930
- Subject: Re: PATCH: BZ/175: Fix dynamic string offset
- References: <20040529222358.GA9983@lucon.org> <1086038644.1064.4.camel@leaf.tuliptree.org> <20040602192144.GA12672@lucon.org> <20040604200456.GA26805@lucon.org>
On Fri, Jun 04, 2004 at 01:04:56PM -0700, H. J. Lu wrote:
> Here is a patch. It uses _bfd_elf_rela_local_sym to compute the offset
> of local symbol.
No, this isn't correct. I think the following is right, but I haven't
tested it yet since I'm still away from home. Hopefully the comments
I've added will make things clear.
--- cygnus.orig/bfd/elf32-ppc.c 2004-05-22 10:47:29.000000000 +0930
+++ cygnus/bfd/elf32-ppc.c 2004-06-06 10:10:41.000000000 +0930
@@ -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;
+ /* 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 (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
- toff = _bfd_merged_section_offset (abfd, &tsec,
- elf_section_data (tsec)->sec_info,
- toff);
+ {
+ /* 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;
--
Alan Modra
IBM OzLabs - Linux Technology Centre