diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 78 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/emit-relocs-1.d | 37 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/emit-relocs-1.ld | 20 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/emit-relocs-1a.s | 22 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/emit-relocs-1b.s | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/mips-elf.exp | 4 |
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: |