From 491993044ba6cfb2b0fc93c8b3032d5c91cccda5 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 25 Jul 2018 15:24:55 +0930 Subject: [PATCH] Enhance powerpc ld -r --relax One of the ill effects of ld -r is to mash together sections. That can result in reduced icache performance at runtime due to unexpected movement of code. Another problem is that sections can become too large to link on targets that have limited relative addressing. ld -r --relax attempts to overcome the large section problem for branches by inserting trampolines, but the powerpc support added lots of unnecessary trampolines. This patch trims them somewhat. bfd/ * elf32-ppc.c (ppc_elf_relax_section): Ignore common or undef locals. Avoid trashing toff with added when used as a symbol index. Ignore R_PPC_PLTREL24 addends in unused example code. Avoid creating unnecessary fixups when relocatable. ld/ * testsuite/ld-powerpc/big.s: New file. * testsuite/ld-powerpc/relaxrl.d: New test. * testsuite/ld-powerpc/powerpc.exp: Run new test. * testsuite/ld-powerpc/relaxr.d: Adjust. --- bfd/ChangeLog | 7 ++++++ bfd/elf32-ppc.c | 33 +++++++++++++++++++++++------ ld/ChangeLog | 7 ++++++ ld/testsuite/ld-powerpc/big.s | 2 ++ ld/testsuite/ld-powerpc/powerpc.exp | 3 +++ ld/testsuite/ld-powerpc/relaxr.d | 26 +++++++---------------- ld/testsuite/ld-powerpc/relaxrl.d | 27 +++++++++++++++++++++++ 7 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/big.s create mode 100644 ld/testsuite/ld-powerpc/relaxrl.d diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8efa3870933..e0e1a46e143 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2018-07-25 Alan Modra + + * elf32-ppc.c (ppc_elf_relax_section): Ignore common or undef locals. + Avoid trashing toff with added when used as a symbol index. + Ignore R_PPC_PLTREL24 addends in unused example code. Avoid + creating unnecessary fixups when relocatable. + 2018-07-25 Alan Modra * elf32-arm.c (elf32_arm_nabi_write_core_note): Disable diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 1ddfc6c1f40..c289eebe316 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -7386,12 +7386,10 @@ ppc_elf_relax_section (bfd *abfd, { if (tsec != NULL) ; - else if (isym->st_shndx == SHN_UNDEF) - tsec = bfd_und_section_ptr; else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; - else if (isym->st_shndx == SHN_COMMON) - tsec = bfd_com_section_ptr; + else + continue; toff = isym->st_value; sym_type = ELF_ST_TYPE (isym->st_info); @@ -7533,6 +7531,17 @@ ppc_elf_relax_section (bfd *abfd, if (tsec == isec) continue; + /* toff is used for the symbol index when the symbol is + undefined and we're doing a relocatable link, so we can't + support addends. It would be possible to do so by + putting the addend in one_branch_fixup but addends on + branches are rare so it hardly seems worth supporting. */ + if (bfd_link_relocatable (link_info) + && tsec == bfd_und_section_ptr + && r_type != R_PPC_PLTREL24 + && irel->r_addend != 0) + continue; + /* 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 @@ -7556,7 +7565,8 @@ ppc_elf_relax_section (bfd *abfd, 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) + if (sym_type == STT_SECTION + && r_type != R_PPC_PLTREL24) toff += irel->r_addend; toff @@ -7564,7 +7574,8 @@ ppc_elf_relax_section (bfd *abfd, elf_section_data (tsec)->sec_info, toff); - if (sym_type != STT_SECTION) + if (sym_type != STT_SECTION + && r_type != R_PPC_PLTREL24) toff += irel->r_addend; } /* PLTREL24 addends are special. */ @@ -7581,6 +7592,16 @@ ppc_elf_relax_section (bfd *abfd, roff = irel->r_offset; + /* Avoid creating a lot of unnecessary fixups when + relocatable if the output section size is such that a + fixup can be created at final link. + The max_branch_offset adjustment allows for some number + of other fixups being needed at final link. */ + if (bfd_link_relocatable (link_info) + && (isec->output_section->rawsize - (isec->output_offset + roff) + < max_branch_offset - (max_branch_offset >> 4))) + continue; + /* If the branch is in range, no need to do anything. */ if (tsec != bfd_und_section_ptr && (!bfd_link_relocatable (link_info) diff --git a/ld/ChangeLog b/ld/ChangeLog index ecbbf485c90..0b3058b20e5 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2018-07-25 Alan Modra + + * testsuite/ld-powerpc/big.s: New file. + * testsuite/ld-powerpc/relaxrl.d: New test. + * testsuite/ld-powerpc/powerpc.exp: Run new test. + * testsuite/ld-powerpc/relaxr.d: Adjust. + 2018-07-24 Nick Clifton * po/fr.po: Updated French translation. diff --git a/ld/testsuite/ld-powerpc/big.s b/ld/testsuite/ld-powerpc/big.s new file mode 100644 index 00000000000..e372c979ee7 --- /dev/null +++ b/ld/testsuite/ld-powerpc/big.s @@ -0,0 +1,2 @@ + .text + .space 32*1024*1024 diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index 0359ba28cb2..cfeb277f043 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -160,6 +160,9 @@ set ppcelftests { {"relocatable relaxing" "-melf32ppc -r --relax" "" "-a32" "relax.s" {{objdump -dr relaxr.d}} "rrelax"} + {"relocatable relaxing large" "-melf32ppc -r --relax" "" "-a32" "relax.s big.s" + {{objdump -dr relaxrl.d}} + "rrelax"} } set ppc64elftests { diff --git a/ld/testsuite/ld-powerpc/relaxr.d b/ld/testsuite/ld-powerpc/relaxr.d index 3ce2751c158..1b3a3c147d0 100644 --- a/ld/testsuite/ld-powerpc/relaxr.d +++ b/ld/testsuite/ld-powerpc/relaxr.d @@ -4,23 +4,13 @@ Disassembly of section .text: 00000000 <_start>: - 0: (48 00 00 15|15 00 00 48) bl 14 <_start\+0x14> - 4: (48 00 00 21|21 00 00 48) bl 24 <_start\+0x24> - 8: (48 00 00 0d|0d 00 00 48) bl 14 <_start\+0x14> - 8: R_PPC_NONE \*ABS\* - c: (48 00 00 19|19 00 00 48) bl 24 <_start\+0x24> - c: R_PPC_NONE \*ABS\* + 0: (48 00 00 01|01 00 00 48) bl 0 <_start> + 0: R_PPC_REL24 near + 4: (48 00 00 01|01 00 00 48) bl 4 <_start\+0x4> + 4: R_PPC_REL24 far + 8: (48 00 00 01|01 00 00 48) bl 8 <_start\+0x8> + 8: R_PPC_REL24 near + c: (48 00 00 01|01 00 00 48) bl c <_start\+0xc> + c: R_PPC_REL24 far 10: (48 00 00 00|00 00 00 48) b 10 <_start\+0x10> 10: R_PPC_REL24 _start - 14: (3d 80 00 00|00 00 80 3d) lis r12,0 - 1(6|4): R_PPC_ADDR16_HA near - 18: (39 8c 00 00|00 00 8c 39) addi r12,r12,0 - 1(a|8): R_PPC_ADDR16_LO near - 1c: (7d 89 03 a6|a6 03 89 7d) mtctr r12 - 20: (4e 80 04 20|20 04 80 4e) bctr - 24: (3d 80 00 00|00 00 80 3d) lis r12,0 - 2(6|4): R_PPC_ADDR16_HA far - 28: (39 8c 00 00|00 00 8c 39) addi r12,r12,0 - 2(a|8): R_PPC_ADDR16_LO far - 2c: (7d 89 03 a6|a6 03 89 7d) mtctr r12 - 30: (4e 80 04 20|20 04 80 4e) bctr diff --git a/ld/testsuite/ld-powerpc/relaxrl.d b/ld/testsuite/ld-powerpc/relaxrl.d new file mode 100644 index 00000000000..8557e3fcfb9 --- /dev/null +++ b/ld/testsuite/ld-powerpc/relaxrl.d @@ -0,0 +1,27 @@ + +.*: file format .* + +Disassembly of section .text: + +0+ <_start>: + +0: (48 00 00 15|15 00 00 48) bl 14 <_start\+0x14> + +4: (48 00 00 21|21 00 00 48) bl 24 <_start\+0x24> + +8: (48 00 00 0d|0d 00 00 48) bl 14 <_start\+0x14> + 8: R_PPC_NONE \*ABS\* + +c: (48 00 00 19|19 00 00 48) bl 24 <_start\+0x24> + c: R_PPC_NONE \*ABS\* + +10: (48 00 00 00|00 00 00 48) b 10 <_start\+0x10> + 10: R_PPC_REL24 _start + +14: (3d 80 00 00|00 00 80 3d) lis r12,0 + 1(6|4): R_PPC_ADDR16_HA near + +18: (39 8c 00 00|00 00 8c 39) addi r12,r12,0 + 1(a|8): R_PPC_ADDR16_LO near + +1c: (7d 89 03 a6|a6 03 89 7d) mtctr r12 + +20: (4e 80 04 20|20 04 80 4e) bctr + +24: (3d 80 00 00|00 00 80 3d) lis r12,0 + 2(6|4): R_PPC_ADDR16_HA far + +28: (39 8c 00 00|00 00 8c 39) addi r12,r12,0 + 2(a|8): R_PPC_ADDR16_LO far + +2c: (7d 89 03 a6|a6 03 89 7d) mtctr r12 + +30: (4e 80 04 20|20 04 80 4e) bctr + \.\.\. -- 2.30.2