From e5c85fb1978c71df0a0c94e8f5d96aac05068970 Mon Sep 17 00:00:00 2001 From: Kuan-Lin Chen Date: Wed, 27 Nov 2019 10:25:36 +0800 Subject: [PATCH] RISC-V: Fix .p2align is not at smallest instruction alignment. As far as I know, RISC-V compilers (LLVM & GCC) doesn't mix code and data in the same section. But we cannot avoid users mixing them in manual assembly code. Example: .text .globl main .option norvc .option relax main: nop .byte 0x99 .byte 0x99 .byte 0x99 .p2align 1 nop After assembling: 00000000
: 0: 00000013 nop 4: 9999 andi a1,a1,-26 6: 1399 addi t2,t2,-26 8: 0000 unimp The second nop doesn't align to 2-byte alignment. BTW, the test case ld/testsuite/ld-riscv-elf/align-1.d is for commit(ed0816bd936492aa7dc00e4fbbf8ff8de1253854). bfd/ChangeLog: * elfnn-riscv.c (_bfd_riscv_relax_align): Fill nops for alignment. * elfxx-riscv.c (howto_table): Modify size of R_RISCV_ALIGN. gas/ChangeLog: * config/tc-riscv.c (md_apply_fix): Adjust BFD_RELOC_RISCV_ALIGN addend. * (riscv_frag_align_code): New the alignment fragments. * (riscv_handle_align): Fill rs_align_code fragments. * testsuite/gas/riscv/align-2.d: New test. * testsuite/gas/riscv/align-2.s: New test. * testsuite/gas/riscv/align-3.d: New test. * testsuite/gas/riscv/align-3.s: New test. * testsuite/gas/riscv/align-4.d: New test. * testsuite/gas/riscv/align-4.s: New test. * testsuite/gas/riscv/align-5.d: New test. * testsuite/gas/riscv/align-5.s: New test. ld/ChangeLog: * testsuite/ld-riscv-elf/align-1.d: New test. * testsuite/ld-riscv-elf/align-1.s New test. * testsuite/ld-riscv-elf/align-2.d New test. * testsuite/ld-riscv-elf/align-2.s New test. * testsuite/ld-riscv-elf/align-3.d New test. * testsuite/ld-riscv-elf/align-3.s New test. * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add align-1, align-2 and align-3. --- bfd/ChangeLog | 5 + bfd/elfnn-riscv.c | 8 +- bfd/elfxx-riscv.c | 2 +- gas/ChangeLog | 15 +++ gas/config/tc-riscv.c | 103 +++++++++++---------- gas/testsuite/gas/riscv/align-2.d | 13 +++ gas/testsuite/gas/riscv/align-2.s | 11 +++ gas/testsuite/gas/riscv/align-3.d | 13 +++ gas/testsuite/gas/riscv/align-3.s | 8 ++ gas/testsuite/gas/riscv/align-4.d | 14 +++ gas/testsuite/gas/riscv/align-4.s | 8 ++ gas/testsuite/gas/riscv/align-5.d | 13 +++ gas/testsuite/gas/riscv/align-5.s | 8 ++ ld/ChangeLog | 11 +++ ld/testsuite/ld-riscv-elf/align-1.d | 17 ++++ ld/testsuite/ld-riscv-elf/align-1.s | 10 ++ ld/testsuite/ld-riscv-elf/align-2.d | 17 ++++ ld/testsuite/ld-riscv-elf/align-2.s | 10 ++ ld/testsuite/ld-riscv-elf/align-3.d | 17 ++++ ld/testsuite/ld-riscv-elf/align-3.s | 10 ++ ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 3 + 21 files changed, 262 insertions(+), 54 deletions(-) create mode 100644 gas/testsuite/gas/riscv/align-2.d create mode 100644 gas/testsuite/gas/riscv/align-2.s create mode 100644 gas/testsuite/gas/riscv/align-3.d create mode 100644 gas/testsuite/gas/riscv/align-3.s create mode 100644 gas/testsuite/gas/riscv/align-4.d create mode 100644 gas/testsuite/gas/riscv/align-4.s create mode 100644 gas/testsuite/gas/riscv/align-5.d create mode 100644 gas/testsuite/gas/riscv/align-5.s create mode 100644 ld/testsuite/ld-riscv-elf/align-1.d create mode 100644 ld/testsuite/ld-riscv-elf/align-1.s create mode 100644 ld/testsuite/ld-riscv-elf/align-2.d create mode 100644 ld/testsuite/ld-riscv-elf/align-2.s create mode 100644 ld/testsuite/ld-riscv-elf/align-3.d create mode 100644 ld/testsuite/ld-riscv-elf/align-3.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4a0852e577..6161da2171 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2019-11-28 Kuan-Lin Chen + + * elfnn-riscv.c (_bfd_riscv_relax_align): Fill nops for alignment. + * elfxx-riscv.c (howto_table): Modify size of R_RISCV_ALIGN. + 2019-11-27 Alan Modra PR 23652 diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 997f786602..aa6e88f411 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -3764,10 +3764,6 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec, /* Delete the reloc. */ rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE); - /* If the number of NOPs is already correct, there's nothing to do. */ - if (nop_bytes == rel->r_addend) - return TRUE; - /* Write as many RISC-V NOPs as we need. */ for (pos = 0; pos < (nop_bytes & -4); pos += 4) bfd_put_32 (abfd, RISCV_NOP, contents + rel->r_offset + pos); @@ -3776,6 +3772,10 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec, if (nop_bytes % 4 != 0) bfd_put_16 (abfd, RVC_NOP, contents + rel->r_offset + pos); + /* If the number of NOPs is already correct, there's nothing to do. */ + if (nop_bytes == rel->r_addend) + return TRUE; + /* Delete the excess bytes. */ return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes, rel->r_addend - nop_bytes, link_info); diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 245717f70f..15a4f32f8c 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -634,7 +634,7 @@ static reloc_howto_type howto_table[] = addend rounded up to the next power of two. */ HOWTO (R_RISCV_ALIGN, /* type */ 0, /* rightshift */ - 2, /* size */ + 3, /* size */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ diff --git a/gas/ChangeLog b/gas/ChangeLog index 09991524da..ec5191bf16 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,18 @@ +2019-11-27 Kuan-Lin Chen + + * config/tc-riscv.c (md_apply_fix): Adjust BFD_RELOC_RISCV_ALIGN + addend. + * (riscv_frag_align_code): New the alignment fragments. + * (riscv_handle_align): Fill rs_align_code fragments. + * testsuite/gas/riscv/align-2.d: New test. + * testsuite/gas/riscv/align-2.s: New test. + * testsuite/gas/riscv/align-3.d: New test. + * testsuite/gas/riscv/align-3.s: New test. + * testsuite/gas/riscv/align-4.d: New test. + * testsuite/gas/riscv/align-4.s: New test. + * testsuite/gas/riscv/align-5.d: New test. + * testsuite/gas/riscv/align-5.s: New test. + 2019-11-25 Andrew Pinski * config/tc-aarch64.c (md_begin): Use correct diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index e50505138e..a1f4881dbd 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -2581,6 +2581,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_RISCV_ALIGN: + if (fixP->fx_frag->fr_var >= 2) + fixP->fx_addnumber += 2; break; default: @@ -2764,39 +2766,43 @@ riscv_make_nops (char *buf, bfd_vma bytes) md_number_to_chars (buf + i, RISCV_NOP, 4); } -/* Called from md_do_align. Used to create an alignment frag in a - code section by emitting a worst-case NOP sequence that the linker - will later relax to the correct number of NOPs. We can't compute - the correct alignment now because of other linker relaxations. */ +/* Called from md_do_align. Insert a ALIGN relocation for linker to + relax and compute the correct alignment. + TODO: handle the reset arguments of .p2align that linker can relax these + types. */ bfd_boolean riscv_frag_align_code (int n) { + expressionS exp; bfd_vma bytes = (bfd_vma) 1 << n; + bfd_vma alignment_power = riscv_opts.rvc ? 1 : 2; bfd_vma insn_alignment = riscv_opts.rvc ? 2 : 4; bfd_vma worst_case_bytes = bytes - insn_alignment; - char *nops; - expressionS ex; - - /* If we are moving to a smaller alignment than the instruction size, then no - alignment is required. */ - if (bytes <= insn_alignment) - return TRUE; + fragS* fragP = frag_now; + /* Set the address at the optimizable begining. */ + unsigned fragP_fix = (frag_now_fix() + 1) >> 1 << 1; /* When not relaxing, riscv_handle_align handles code alignment. */ if (!riscv_opts.relax) return FALSE; - nops = frag_more (worst_case_bytes); - - ex.X_op = O_constant; - ex.X_add_number = worst_case_bytes; - - riscv_make_nops (nops, worst_case_bytes); - - fix_new_exp (frag_now, nops - frag_now->fr_literal, 0, - &ex, FALSE, BFD_RELOC_RISCV_ALIGN); + /* If we are moving to a smaller alignment than the instruction size, + riscv_handle_align handles code alignment. */ + if (bytes <= insn_alignment) + return FALSE; + /* Make sure the current alignment is align to insntruction alignment. */ + frag_align_code (alignment_power, 0); + + /* Insert a ALIGN relocation for linker to remove the redandunt nops. + Locate the relocation in the rs_align_code frag instead of frag_now, + because we want linker to know the whole size of the alignment. */ + exp.X_op = O_constant; + /* Just set the worst value temporarily. */ + exp.X_add_number = worst_case_bytes; + fix_new_exp (fragP, fragP_fix, 0, &exp, 0, BFD_RELOC_RISCV_ALIGN); + frag_more (worst_case_bytes); return TRUE; } @@ -2805,38 +2811,37 @@ riscv_frag_align_code (int n) void riscv_handle_align (fragS *fragP) { - switch (fragP->fr_type) - { - case rs_align_code: - /* When relaxing, riscv_frag_align_code handles code alignment. */ - if (!riscv_opts.relax) - { - bfd_signed_vma bytes = (fragP->fr_next->fr_address - - fragP->fr_address - fragP->fr_fix); - /* We have 4 byte uncompressed nops. */ - bfd_signed_vma size = 4; - bfd_signed_vma excess = bytes % size; - char *p = fragP->fr_literal + fragP->fr_fix; - - if (bytes <= 0) - break; + bfd_signed_vma bytes ; - /* Insert zeros or compressed nops to get 4 byte alignment. */ - if (excess) - { - riscv_make_nops (p, excess); - fragP->fr_fix += excess; - p += excess; - } + if (fragP->fr_type != rs_align_code) + return; - /* Insert variable number of 4 byte uncompressed nops. */ - riscv_make_nops (p, size); - fragP->fr_var = size; - } - break; + bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix; + /* We have 4 byte uncompressed nops. */ + bfd_signed_vma size = 4; + bfd_signed_vma excess = bytes % size; + char *p = fragP->fr_literal + fragP->fr_fix; - default: - break; + if (bytes <= 0) + return; + + /* Insert zeros or compressed nops to get 4 byte alignment. */ + if (excess) + { + riscv_make_nops (p, excess); + fragP->fr_fix += excess; + p += excess; + if (excess >= 2) + fragP->fr_var = 2; + } + + if (bytes > size) + { + /* After this function, the frag will be set to fr_fill. We only + insert one 4 byte nop here. The reset space will be filled in + write_contents. */ + riscv_make_nops (p, size); + fragP->fr_var = size; } } diff --git a/gas/testsuite/gas/riscv/align-2.d b/gas/testsuite/gas/riscv/align-2.d new file mode 100644 index 0000000000..157af5bbaf --- /dev/null +++ b/gas/testsuite/gas/riscv/align-2.d @@ -0,0 +1,13 @@ +#as: -march=rv32ic +#objdump: -dr + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000
: +[^:]+:[ ]+00000013[ ]+nop +[^:]+:[ ]+9999.* +[^:]+:[ ]+0099.* +[^:]+8:[ ]+00000013[ ]+nop diff --git a/gas/testsuite/gas/riscv/align-2.s b/gas/testsuite/gas/riscv/align-2.s new file mode 100644 index 0000000000..87c36efd41 --- /dev/null +++ b/gas/testsuite/gas/riscv/align-2.s @@ -0,0 +1,11 @@ +.text +.globl main +.option norvc +.option relax +main: + nop + .byte 0x99 + .byte 0x99 + .byte 0x99 +.p2align 1 + nop diff --git a/gas/testsuite/gas/riscv/align-3.d b/gas/testsuite/gas/riscv/align-3.d new file mode 100644 index 0000000000..097cc9626d --- /dev/null +++ b/gas/testsuite/gas/riscv/align-3.d @@ -0,0 +1,13 @@ +#as: -march=rv32i +#objdump: -dr + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000
: +[^:]+:[ ]+00000013[ ]+nop +[^:]+:[ ]+9999.* +.* +[^:]+8:[ ]+00000013[ ]+nop diff --git a/gas/testsuite/gas/riscv/align-3.s b/gas/testsuite/gas/riscv/align-3.s new file mode 100644 index 0000000000..7cebd33255 --- /dev/null +++ b/gas/testsuite/gas/riscv/align-3.s @@ -0,0 +1,8 @@ +.text +.globl main +.option relax +main: + nop + .short 0x9999 +.p2align 2 + nop diff --git a/gas/testsuite/gas/riscv/align-4.d b/gas/testsuite/gas/riscv/align-4.d new file mode 100644 index 0000000000..81914cb430 --- /dev/null +++ b/gas/testsuite/gas/riscv/align-4.d @@ -0,0 +1,14 @@ +#as: -march=rv32ic +#objdump: -dr + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000
: +[^:]+:[ ]+0001[ ]+nop +[^:]+:[ ]+9999.* +.* +[^:]+4: R_RISCV_ALIGN[ ]+\*ABS\*\+0x2 +[^:]+6:[ ]+0001[ ]+nop diff --git a/gas/testsuite/gas/riscv/align-4.s b/gas/testsuite/gas/riscv/align-4.s new file mode 100644 index 0000000000..7cebd33255 --- /dev/null +++ b/gas/testsuite/gas/riscv/align-4.s @@ -0,0 +1,8 @@ +.text +.globl main +.option relax +main: + nop + .short 0x9999 +.p2align 2 + nop diff --git a/gas/testsuite/gas/riscv/align-5.d b/gas/testsuite/gas/riscv/align-5.d new file mode 100644 index 0000000000..530f9d9a64 --- /dev/null +++ b/gas/testsuite/gas/riscv/align-5.d @@ -0,0 +1,13 @@ +#as: -march=rv32i +#objdump: -dr + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000
: +[^:]+:[ ]+00000013[ ]+nop +[^:]+:[ ]+9999.* +[^:]+:[ ]+1111.* +[^:]+8:[ ]+00000013[ ]+nop diff --git a/gas/testsuite/gas/riscv/align-5.s b/gas/testsuite/gas/riscv/align-5.s new file mode 100644 index 0000000000..b907643e08 --- /dev/null +++ b/gas/testsuite/gas/riscv/align-5.s @@ -0,0 +1,8 @@ +.text +.globl main +.option relax +main: + nop + .short 0x9999 +.p2align 2, 0x11 + nop diff --git a/ld/ChangeLog b/ld/ChangeLog index 969ab78035..54abd7955c 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,14 @@ +2019-11-27 Kuan-Lin Chen + + * testsuite/ld-riscv-elf/align-1.d: New test. + * testsuite/ld-riscv-elf/align-1.s New test. + * testsuite/ld-riscv-elf/align-2.d New test. + * testsuite/ld-riscv-elf/align-2.s New test. + * testsuite/ld-riscv-elf/align-3.d New test. + * testsuite/ld-riscv-elf/align-3.s New test. + * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add align-1, align-2 and + align-3. + 2019-11-26 Martin Liska * scripttempl/arclinux.sc: Add .text.sorted.* which is sorted diff --git a/ld/testsuite/ld-riscv-elf/align-1.d b/ld/testsuite/ld-riscv-elf/align-1.d new file mode 100644 index 0000000000..7653d76a81 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/align-1.d @@ -0,0 +1,17 @@ +#source: align-1.s +#as: -march=rv32ic +#ld: -melf32lriscv +#objdump: -d + +.*:[ ]+file format .* + +Disassembly of section .text: + +.* <_start>: +.*:[ ]+8086[ ]+mv[ ]+ra,ra +.*:[ ]+810a[ ]+mv[ ]+sp,sp + +.* : +.*:[ ]+00000013[ ]+nop +.*:[ ]+00018193[ ]+mv[ ]+gp,gp +#pass diff --git a/ld/testsuite/ld-riscv-elf/align-1.s b/ld/testsuite/ld-riscv-elf/align-1.s new file mode 100644 index 0000000000..61abfd24fd --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/align-1.s @@ -0,0 +1,10 @@ +.global _start +.option rvc +_start: + mv x1, x1 + mv x2, x2 +.align 2 +rvc_boundry: +.option norvc +.align 3 + mv x3, x3 diff --git a/ld/testsuite/ld-riscv-elf/align-2.d b/ld/testsuite/ld-riscv-elf/align-2.d new file mode 100644 index 0000000000..b5e0dfffa6 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/align-2.d @@ -0,0 +1,17 @@ +#source: align-2.s +#as: -march=rv32i +#ld: -melf32lriscv +#objdump: -d + +.*:[ ]+file format .* + +Disassembly of section .text: + +.* <_start>: +.*:[ ]+00010093[ ]+mv[ ]+ra,sp +.*:[ ]+9999[ ]+.* +.*:[ ]+[0-9]{4}.* +.*:[ ]+00010093[ ]+mv[ ]+ra,sp +.*:[ ]+00000013[ ]+nop +.*:[ ]+00010093[ ]+mv[ ]+ra,sp +#pass diff --git a/ld/testsuite/ld-riscv-elf/align-2.s b/ld/testsuite/ld-riscv-elf/align-2.s new file mode 100644 index 0000000000..f551c1347b --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/align-2.s @@ -0,0 +1,10 @@ +.text +.globl _start +.option norvc +_start: + mv x1, x2 + .short 0x9999 +.p2align 2 + mv x1, x2 +.p2align 3 + mv x1, x2 diff --git a/ld/testsuite/ld-riscv-elf/align-3.d b/ld/testsuite/ld-riscv-elf/align-3.d new file mode 100644 index 0000000000..b2f872210c --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/align-3.d @@ -0,0 +1,17 @@ +#source: align-3.s +#as: -march=rv32i +#ld: -melf32lriscv +#objdump: -d + +.*:[ ]+file format .* + +Disassembly of section .text: + +.* <_start>: +.*[08]:[ ]+9999[ ]+.* +.* +.* +.*[08]:[ ]+00010093[ ]+mv[ ]+ra,sp +.*:[ ]+00010093[ ]+mv[ ]+ra,sp +.*:[ ]+00010093[ ]+mv[ ]+ra,sp +#pass diff --git a/ld/testsuite/ld-riscv-elf/align-3.s b/ld/testsuite/ld-riscv-elf/align-3.s new file mode 100644 index 0000000000..63c8cc99f4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/align-3.s @@ -0,0 +1,10 @@ +.text +.globl _start +.option norvc +_start: +.p2align 3 + .short 0x9999 +.p2align 3 + mv x1, x2 + mv x1, x2 + mv x1, x2 diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index 7aabbdd641..bbdd089bec 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -38,6 +38,9 @@ if [istarget "riscv*-*-*"] { run_dump_test "attr-merge-priv-spec" run_dump_test "attr-merge-arch-failed-01" run_dump_test "attr-merge-stack-align-failed" + run_dump_test "align-1" + run_dump_test "align-2" + run_dump_test "align-3" run_ld_link_tests { { "Weak reference 32" "-T weakref.ld -melf32lriscv" "" "-march=rv32i -mabi=ilp32" {weakref32.s} -- 2.17.0