Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/gnu/dist/toolchain Pull up changes from binutils master sources



details:   https://anonhg.NetBSD.org/src/rev/8928d2847a3b
branches:  trunk
changeset: 542824:8928d2847a3b
user:      tsutsui <tsutsui%NetBSD.org@localhost>
date:      Sat Feb 08 17:09:35 2003 +0000

description:
Pull up changes from binutils master sources
<http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/?cvsroot=src>
to fix relocation problem on linking startup routines for sh3:

src/bfd/elf32-sh.c revision 1.36:
> * elf32-sh.c (sh_elf_howto_table, R_SH_REL32): Make
> partial_inplace, matching assembler output.  Set src_mask to
> all ones.
> (sh_elf_relocate_section): Delete misplaced comment.
> For relocatable linking against section symbol, call
> _bfd_relocate_contents for partial_inplace relocs and adjust
> rel->r_addend for others.
> <case R_SH_DIR32, R_SH_REL32>: Fetch partial_inplace addend with
> bfd_get_32, not at rel->r_addend.

src/gas/config/tc-sh.c revision 1.43:
> * config/tc-sh.c (md_pcrel_from_section): Transformed from
> md_pcrel_from.  Handle pc-relativeness against link-time
> symbol.  Handle relativeness to elsewhere than the fixup.

src/gas/config/tc-sh.h revision 1.14:
> * config/tc-sh.h (MD_PCREL_FROM_SECTION): Define.
> (md_pcrel_from_section): Prototype.

Thanks to Kaz Kojima and Jason R Thorpe for their comments.

diffstat:

 gnu/dist/toolchain/bfd/elf32-sh.c     |  51 ++++++++++++++++++++++++++++------
 gnu/dist/toolchain/gas/config/tc-sh.c |  16 ++++++++++-
 gnu/dist/toolchain/gas/config/tc-sh.h |   3 ++
 3 files changed, 60 insertions(+), 10 deletions(-)

diffs (150 lines):

diff -r 09088cfa9d54 -r 8928d2847a3b gnu/dist/toolchain/bfd/elf32-sh.c
--- a/gnu/dist/toolchain/bfd/elf32-sh.c Sat Feb 08 12:06:13 2003 +0000
+++ b/gnu/dist/toolchain/bfd/elf32-sh.c Sat Feb 08 17:09:35 2003 +0000
@@ -121,8 +121,8 @@
         complain_overflow_signed, /* complain_on_overflow */
         sh_elf_ignore_reloc,   /* special_function */
         "R_SH_REL32",          /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         true),                 /* pcrel_offset */
 
@@ -2918,7 +2918,11 @@
 
       howto = sh_elf_howto_table + r_type;
 
-      /* This is a final link.  */
+      /* For relocs that aren't partial_inplace, we get the addend from
+         the relocation.  */
+      if (! howto->partial_inplace)
+       addend = rel->r_addend;
+
       h = NULL;
       sym = NULL;
       sec = NULL;
@@ -2938,7 +2942,32 @@
                 section symbol winds up in the output section.  */
              sym = local_syms + r_symndx;
              if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               goto final_link_relocate;
+               {
+                 if (! howto->partial_inplace)
+                   {
+                     /* For relocations with the addend in the
+                        relocation, we need just to update the addend.
+                        All real relocs are of type partial_inplace; this
+                        code is mostly for completeness.  */
+                     rel->r_addend += sec->output_offset + sym->st_value;
+
+                     continue;
+                   }
+
+                 /* Relocs of type partial_inplace need to pick up the
+                    contents in the contents and add the offset resulting
+                    from the changed location of the section symbol.
+                    Using _bfd_final_link_relocate (e.g. goto
+                    final_link_relocate) here would be wrong, because
+                    relocations marked pc_relative would get the current
+                    location subtracted, and we must only do that at the
+                    final link.  */
+                 r = _bfd_relocate_contents (howto, input_bfd,
+                                             sec->output_offset
+                                             + sym->st_value,
+                                             contents + rel->r_offset);
+                 goto relocation_done;
+               }
 
              continue;
            }
@@ -3111,7 +3140,8 @@
                  BFD_ASSERT (h != NULL && h->dynindx != -1);
                  relocate = false;
                  outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
-                 outrel.r_addend = rel->r_addend;
+                 outrel.r_addend
+                   = bfd_get_32 (input_bfd, contents + rel->r_offset);
                }
              else
                {
@@ -3124,14 +3154,18 @@
                    {
                      relocate = true;
                      outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
-                     outrel.r_addend = relocation + rel->r_addend;
+                     outrel.r_addend
+                       = relocation + bfd_get_32 (input_bfd,
+                                                  contents + rel->r_offset);
                    }
                  else
                    {
                      BFD_ASSERT (h->dynindx != -1);
                      relocate = false;
                      outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
-                     outrel.r_addend = relocation + rel->r_addend;
+                     outrel.r_addend
+                       = relocation + bfd_get_32 (input_bfd,
+                                                  contents + rel->r_offset);
                    }
                }
 
@@ -3148,8 +3182,6 @@
              if (! relocate)
                continue;
            }
-         else if (r_type == R_SH_DIR32)
-           addend = rel->r_addend;
          goto final_link_relocate;
 
        case R_SH_GOT32:
@@ -3329,6 +3361,7 @@
          }
        }
 
+    relocation_done:
       if (r != bfd_reloc_ok)
        {
          switch (r)
diff -r 09088cfa9d54 -r 8928d2847a3b gnu/dist/toolchain/gas/config/tc-sh.c
--- a/gnu/dist/toolchain/gas/config/tc-sh.c     Sat Feb 08 12:06:13 2003 +0000
+++ b/gnu/dist/toolchain/gas/config/tc-sh.c     Sat Feb 08 17:09:35 2003 +0000
@@ -3136,9 +3136,23 @@
 }
 
 long
-md_pcrel_from (fixP)
+md_pcrel_from_section (fixP, sec)
      fixS *fixP;
+     segT sec;
 {
+  if (fixP->fx_addsy != (symbolS *) NULL
+      && (! S_IS_DEFINED (fixP->fx_addsy)
+         || S_IS_EXTERN (fixP->fx_addsy)
+         || S_IS_WEAK (fixP->fx_addsy)
+         || S_GET_SEGMENT (fixP->fx_addsy) != sec))
+    {
+      /* The symbol is undefined (or is defined but not in this section,
+        or we're not sure about it being the final definition).  Let the
+        linker figure it out.  We need to adjust the subtraction of a
+        symbol to the position of the relocated data, though.  */
+      return fixP->fx_subsy ? fixP->fx_where + fixP->fx_frag->fr_address : 0;
+    }
+
   return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address + 2;
 }
 
diff -r 09088cfa9d54 -r 8928d2847a3b gnu/dist/toolchain/gas/config/tc-sh.h
--- a/gnu/dist/toolchain/gas/config/tc-sh.h     Sat Feb 08 12:06:13 2003 +0000
+++ b/gnu/dist/toolchain/gas/config/tc-sh.h     Sat Feb 08 17:09:35 2003 +0000
@@ -70,6 +70,9 @@
 #define TC_FIX_ADJUSTABLE(fixP) obj_fix_adjustable (fixP)
 #endif
 
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section (FIXP, SEC)
+extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
+
 #define IGNORE_NONSTANDARD_ESCAPES
 
 #define LISTING_HEADER (!target_big_endian ? "Hitachi Super-H GAS Little Endian" : "Hitachi Super-H GAS Big Endian")



Home | Main Index | Thread Index | Old Index