bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Tue, 14 Mar 2006 07:47:49 +0000 (07:47 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Tue, 14 Mar 2006 07:47:49 +0000 (07:47 +0000)
* elf32-mips.c (mips_elf_adjust_addend): New function, mostly split
out from...
(_bfd_mips_elf_relocate_section): ...here.  Use it to adjust r_addend
for final links too.

ld/testsuite/
* ld-mips/emit-relocs-1a.s, ld-mips/emit-relocs-1b.s,
* ld-mips/emit-relocs-1.ld, ld-mips/emit-relocs-1.d: New test.
* ld-mips/mips-elf.exp: Run it.

bfd/ChangeLog
bfd/elfxx-mips.c
ld/testsuite/ChangeLog
ld/testsuite/ld-mips-elf/emit-relocs-1.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/emit-relocs-1.ld [new file with mode: 0644]
ld/testsuite/ld-mips-elf/emit-relocs-1a.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/emit-relocs-1b.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips-elf.exp

index 70ab598..5ede2ea 100644 (file)
@@ -1,3 +1,10 @@
+2006-03-14  Richard Sandiford  <richard@codesourcery.com>
+
+       * elf32-mips.c (mips_elf_adjust_addend): New function, mostly split
+       out from...
+       (_bfd_mips_elf_relocate_section): ...here.  Use it to adjust r_addend
+       for final links too.
+
 2006-03-13  Richard Sandiford  <richard@codesourcery.com>
 
        * elfxx-mips.c (mips_elf_create_got_section): Initialize hgot.
index 98974bd..ea8820b 100644 (file)
@@ -6934,6 +6934,48 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
   return TRUE;
 }
 \f
+/* REL is a relocation in INPUT_BFD that is being copied to OUTPUT_BFD.
+   Adjust its R_ADDEND field so that it is correct for the output file.
+   LOCAL_SYMS and LOCAL_SECTIONS are arrays of INPUT_BFD's local symbols
+   and sections respectively; both use symbol indexes.  */
+
+static void
+mips_elf_adjust_addend (bfd *output_bfd, struct bfd_link_info *info,
+                       bfd *input_bfd, Elf_Internal_Sym *local_syms,
+                       asection **local_sections, Elf_Internal_Rela *rel)
+{
+  unsigned int r_type, r_symndx;
+  Elf_Internal_Sym *sym;
+  asection *sec;
+
+  if (mips_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE))
+    {
+      r_type = ELF_R_TYPE (output_bfd, rel->r_info);
+      if (r_type == R_MIPS16_GPREL
+         || r_type == R_MIPS_GPREL16
+         || r_type == R_MIPS_GPREL32
+         || r_type == R_MIPS_LITERAL)
+       {
+         rel->r_addend += _bfd_get_gp_value (input_bfd);
+         rel->r_addend -= _bfd_get_gp_value (output_bfd);
+       }
+
+      r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
+      sym = local_syms + r_symndx;
+
+      /* Adjust REL's addend to account for section merging.  */
+      if (!info->relocatable)
+       {
+         sec = local_sections[r_symndx];
+         _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+       }
+
+      /* This would normally be done by the rela_normal code in elflink.c.  */
+      if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+       rel->r_addend += local_sections[r_symndx]->output_offset;
+    }
+}
+
 /* Relocate a MIPS ELF section.  */
 
 bfd_boolean
@@ -7084,47 +7126,19 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            }
          else
            addend = rel->r_addend;
+         mips_elf_adjust_addend (output_bfd, info, input_bfd,
+                                 local_syms, local_sections, rel);
        }
 
       if (info->relocatable)
        {
-         Elf_Internal_Sym *sym;
-         unsigned long r_symndx;
-
          if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd)
              && bfd_big_endian (input_bfd))
            rel->r_offset -= 4;
 
-         /* Since we're just relocating, all we need to do is copy
-            the relocations back out to the object file, unless
-            they're against a section symbol, in which case we need
-            to adjust by the section offset, or unless they're GP
-            relative in which case we need to adjust by the amount
-            that we're adjusting GP in this relocatable object.  */
-
-         if (! mips_elf_local_relocation_p (input_bfd, rel, local_sections,
-                                            FALSE))
-           /* There's nothing to do for non-local relocations.  */
-           continue;
-
-         if (r_type == R_MIPS16_GPREL
-             || r_type == R_MIPS_GPREL16
-             || r_type == R_MIPS_GPREL32
-             || r_type == R_MIPS_LITERAL)
-           addend -= (_bfd_get_gp_value (output_bfd)
-                      - _bfd_get_gp_value (input_bfd));
-
-         r_symndx = ELF_R_SYM (output_bfd, rel->r_info);
-         sym = local_syms + r_symndx;
-         if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-           /* Adjust the addend appropriately.  */
-           addend += local_sections[r_symndx]->output_offset;
-
-         if (rela_relocation_p)
-           /* If this is a RELA relocation, just update the addend.  */
-           rel->r_addend = addend;
-         else
+         if (!rela_relocation_p && rel->r_addend)
            {
+             addend += rel->r_addend;
              if (r_type == R_MIPS_HI16
                  || r_type == R_MIPS_GOT16)
                addend = mips_elf_high (addend);
index 972581c..a9f1357 100644 (file)
@@ -1,3 +1,9 @@
+2006-03-14  Richard Sandiford  <richard@codesourcery.com>
+
+       * ld-mips/emit-relocs-1a.s, ld-mips/emit-relocs-1b.s,
+       * ld-mips/emit-relocs-1.ld, ld-mips/emit-relocs-1.d: New test.
+       * ld-mips/mips-elf.exp: Run it.
+
 2006-03-07  Richard Sandiford  <richard@codesourcery.com>
 
        * ld-arm/vxworks1.dd, ld-arm/vxworks1.ld, ld-arm/vxworks1-lib.dd,
diff --git a/ld/testsuite/ld-mips-elf/emit-relocs-1.d b/ld/testsuite/ld-mips-elf/emit-relocs-1.d
new file mode 100644 (file)
index 0000000..520d401
--- /dev/null
@@ -0,0 +1,37 @@
+#name: Emit relocs 1
+#source: emit-relocs-1a.s -mabi=n32 -EB
+#source: emit-relocs-1b.s -mabi=n32 -EB
+#ld: -q -T emit-relocs-1.ld -melf32btsmipn32
+#objdump: -sr
+
+.*:     file format .*
+
+RELOCATION RECORDS FOR \[\.data\]:
+OFFSET   TYPE              VALUE *
+00000000 R_MIPS_32         \.data
+00000004 R_MIPS_32         \.data\+0x00001000
+00000008 R_MIPS_32         \.merge1\+0x00000002
+0000000c R_MIPS_32         \.merge2
+00000010 R_MIPS_32         \.merge3
+00000014 R_MIPS_32         \.merge3\+0x00000004
+00000020 R_MIPS_32         \.data\+0x00000020
+00000024 R_MIPS_32         \.data\+0x00001020
+00000028 R_MIPS_32         \.merge1
+0000002c R_MIPS_32         \.merge2\+0x00000002
+00000030 R_MIPS_32         \.merge3\+0x00000008
+00000034 R_MIPS_32         \.merge3\+0x00000004
+
+
+Contents of section \.text:
+ 80000 03e00008 00000000 00000000 00000000  .*
+Contents of section \.merge1:
+ 80400 666c7574 74657200                    flutter.*
+Contents of section \.merge2:
+ 80800 74617374 696e6700                    tasting.*
+Contents of section \.merge3:
+ 80c00 00000100 00000200 00000300           .*
+Contents of section \.data:
+ 81000 00081000 00082000 00080402 00080800  .*
+ 81010 00080c00 00080c04 00000000 00000000  .*
+ 81020 00081020 00082020 00080400 00080802  .*
+ 81030 00080c08 00080c04 .*
diff --git a/ld/testsuite/ld-mips-elf/emit-relocs-1.ld b/ld/testsuite/ld-mips-elf/emit-relocs-1.ld
new file mode 100644 (file)
index 0000000..1879ef4
--- /dev/null
@@ -0,0 +1,20 @@
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x80000;
+  .text : { *(.text) }
+
+  . = ALIGN (0x400);
+  .merge1 : { *(.merge1) }
+
+  . = ALIGN (0x400);
+  .merge2 : { *(.merge2) }
+
+  . = ALIGN (0x400);
+  .merge3 : { *(.merge3) }
+
+  . = ALIGN (0x400);
+  .data : { *(.data) }
+
+  /DISCARD/ : { *(*) }
+}
diff --git a/ld/testsuite/ld-mips-elf/emit-relocs-1a.s b/ld/testsuite/ld-mips-elf/emit-relocs-1a.s
new file mode 100644 (file)
index 0000000..9176f97
--- /dev/null
@@ -0,0 +1,22 @@
+       .text
+       .globl  _start
+_start:
+       jr      $31
+
+       .section .merge1,"aMS",@progbits,1
+A:     .string "utter"
+
+       .section .merge2,"aMS",@progbits,1
+B:     .string "tasting"
+
+       .section .merge3,"aM",@progbits,4
+C:     .4byte  0x100
+D:     .4byte  0x200
+
+       .data
+E:     .4byte  E
+       .4byte  E + 0x1000
+       .4byte  A
+       .4byte  B
+       .4byte  C
+       .4byte  D
diff --git a/ld/testsuite/ld-mips-elf/emit-relocs-1b.s b/ld/testsuite/ld-mips-elf/emit-relocs-1b.s
new file mode 100644 (file)
index 0000000..0e88c14
--- /dev/null
@@ -0,0 +1,17 @@
+       .section .merge1,"aMS",@progbits,1
+A:     .string "flutter"
+
+       .section .merge2,"aMS",@progbits,1
+B:     .string "sting"
+
+       .section .merge3,"aM",@progbits,4
+C:     .4byte  0x300
+D:     .4byte  0x200
+
+       .data
+E:     .4byte  E
+       .4byte  E + 0x1000
+       .4byte  A
+       .4byte  B
+       .4byte  C
+       .4byte  D
index da278ae..aac3418 100644 (file)
@@ -105,6 +105,10 @@ if { $linux_gnu } {
     run_dump_test "textrel-1"
 }
 
+if $has_newabi {
+    run_dump_test "emit-relocs-1"
+}
+
 # For tests which may involve multiple files, use run_ld_link_tests.
 
 # List contains test-items with 3 items followed by 2 lists: