* elf32-ppc.c (ppc_elf_relax_section): Implement reference code
authorAlan Modra <amodra@gmail.com>
Tue, 22 Jun 2004 05:35:37 +0000 (05:35 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 22 Jun 2004 05:35:37 +0000 (05:35 +0000)
for handling SEC_MERGE symbols in relax_section.
* coff-i386.c: Update copyright date.

bfd/ChangeLog
bfd/coff-i386.c
bfd/elf32-ppc.c

index 2bcd7bd8fcfad7b3907b6128a4271490c63d1ac4..130466142cea66437a35053a764ed312da5093ea 100644 (file)
@@ -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>
index e2bf8602355bc4f7fe8e90128ae00cf9ac7ce2ad..65700b6038b201384be878eb30cf14459e095ba6 100644 (file)
@@ -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.
 
index be052701ddbbd64b9e964486bf17d96616c38632..c4b46f6e242318744dac718f011b14da82f22dbd 100644 (file)
@@ -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;