This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: BZ/175: Fix dynamic string offset


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]