aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elfxx-mips.c78
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-mips-elf/emit-relocs-1.d37
-rw-r--r--ld/testsuite/ld-mips-elf/emit-relocs-1.ld20
-rw-r--r--ld/testsuite/ld-mips-elf/emit-relocs-1a.s22
-rw-r--r--ld/testsuite/ld-mips-elf/emit-relocs-1b.s17
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp4
8 files changed, 159 insertions, 32 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 70ab598..5ede2ea 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 98974bd..ea8820b 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -6934,6 +6934,48 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
return TRUE;
}
+/* 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);
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 972581c..a9f1357 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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
index 0000000..520d401
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/emit-relocs-1.d
@@ -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
index 0000000..1879ef4
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/emit-relocs-1.ld
@@ -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
index 0000000..9176f97
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/emit-relocs-1a.s
@@ -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
index 0000000..0e88c14
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/emit-relocs-1b.s
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index da278ae..aac3418 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -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: