From 058430b4a1ed7441dfc2e167bfdb9dc89ea9a209 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 17 Nov 2020 12:41:36 +1030 Subject: [PATCH] Re: Stop Gas from generating line info or address ranges * doc/as.texi (.nop): Document optional size arg. * dwarf2dbg.c (dwarf2_gen_line_info_1): Only check SEC_ALLOC when ELF. Warn whenever dwarf line number information is ignored. * frags.c (frag_offset_ignore_align_p): New function. * frags.h (frag_offset_ignore_align_p): Declare. * read.c (s_nop): Extend to support optional size arg. * testsuite/gas/elf/dwarf2-20.d: Expect warnings, and exact range. * testsuite/gas/elf/dwarf2-20.s: Emit 16 bytes worth of nops. * testsuite/gas/m68hc11/indexed12.d: Expect warnings. --- gas/ChangeLog | 12 +++++++ gas/doc/as.texi | 14 +++++--- gas/dwarf2dbg.c | 16 ++++++---- gas/frags.c | 42 ++++++++++++++++++++++++ gas/frags.h | 2 ++ gas/read.c | 46 +++++++++++++++++++-------- gas/testsuite/gas/elf/dwarf2-20.d | 8 ++++- gas/testsuite/gas/elf/dwarf2-20.s | 10 +++--- gas/testsuite/gas/m68hc11/indexed12.d | 4 +++ 9 files changed, 122 insertions(+), 32 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index fcfce70fc7..9266585550 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +2020-11-18 Alan Modra + + * doc/as.texi (.nop): Document optional size arg. + * dwarf2dbg.c (dwarf2_gen_line_info_1): Only check SEC_ALLOC + when ELF. Warn whenever dwarf line number information is ignored. + * frags.c (frag_offset_ignore_align_p): New function. + * frags.h (frag_offset_ignore_align_p): Declare. + * read.c (s_nop): Extend to support optional size arg. + * testsuite/gas/elf/dwarf2-20.d: Expect warnings, and exact range. + * testsuite/gas/elf/dwarf2-20.s: Emit 16 bytes worth of nops. + * testsuite/gas/m68hc11/indexed12.d: Expect warnings. + 2020-11-18 Jozef Lawrynowicz H.J. Lu diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 84a7e6191a..983cec3cbf 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -6169,14 +6169,18 @@ counter, and @code{.nolist} decrements it. Assembly listings are generated whenever the counter is greater than zero. @node Nop -@section @code{.nop} +@section @code{.nop [@var{size}]} @cindex @code{nop} directive @cindex filling memory with no-op instructions -This directive emits a single no-op instruction. It is provided on all -architectures, allowing the creation of architecture neutral tests involving -actual code. The size of the generated instruction is target specific. The -instruction does affect the generation of DWARF debug line information. +This directive emits no-op instructions. It is provided on all architectures, +allowing the creation of architecture neutral tests involving actual code. The +size of the generated instruction is target specific, but if the optional +@var{size} argument is given and resolves to an absolute positive value at that +point in assembly (no forward expressions allowed) then the fewest no-op +instructions are emitted that equal or exceed a total @var{size} in bytes. +@code{.nop} does affect the generation of DWARF debug line information. +Some targets do not support using @code{.nop} with @var{size}. @node Nops @section @code{.nops @var{size}[, @var{control}]} diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 25ebc94a8d..e927c5059b 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -504,16 +504,18 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc) { struct line_subseg *lss; struct line_entry *e; - flagword need_flags = SEC_ALLOC | SEC_LOAD | SEC_CODE; + flagword need_flags = SEC_LOAD | SEC_CODE; - /* PR 26850: Do not record LOCs in non-executable, non-allocated, - or non-loaded sections. */ + /* PR 26850: Do not record LOCs in non-executable or non-loaded + sections. SEC_ALLOC isn't tested for non-ELF because obj-coff.c + obj_coff_section is careless in setting SEC_ALLOC. */ + if (IS_ELF) + need_flags |= SEC_ALLOC; if ((now_seg->flags & need_flags) != need_flags) { - if (! SEG_NORMAL (now_seg)) - /* FIXME: Add code to suppress multiple warnings ? */ - as_warn ("dwarf line number information for %s ignored", - segment_name (now_seg)); + /* FIXME: Add code to suppress multiple warnings ? */ + as_warn ("dwarf line number information for %s ignored", + segment_name (now_seg)); return; } diff --git a/gas/frags.c b/gas/frags.c index c926ec3ba1..9ed4d7bc0d 100644 --- a/gas/frags.c +++ b/gas/frags.c @@ -468,6 +468,48 @@ frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset) return FALSE; } +/* Return TRUE if FRAG2 follows FRAG1 with a fixed relationship + between the two assuming alignment frags do nothing. Set OFFSET to + the difference in address not already accounted for in the frag + FR_ADDRESS. */ + +bfd_boolean +frag_offset_ignore_align_p (const fragS *frag1, const fragS *frag2, + offsetT *offset) +{ + const fragS *frag; + offsetT off; + + /* Start with offset initialised to difference between the two frags. + Prior to assigning frag addresses this will be zero. */ + off = frag1->fr_address - frag2->fr_address; + if (frag1 == frag2) + { + *offset = off; + return TRUE; + } + + frag = frag1; + while (frag->fr_type == rs_fill + || frag->fr_type == rs_align + || frag->fr_type == rs_align_code + || frag->fr_type == rs_align_test) + { + if (frag->fr_type == rs_fill) + off += frag->fr_fix + frag->fr_offset * frag->fr_var; + frag = frag->fr_next; + if (frag == NULL) + break; + if (frag == frag2) + { + *offset = off; + return TRUE; + } + } + + return FALSE; +} + /* Return TRUE if we can determine whether FRAG2 OFF2 appears after (strict >, not >=) FRAG1 OFF1, assuming it is not before. Set *OFFSET so that resolve_expression will resolve an O_gt operation diff --git a/gas/frags.h b/gas/frags.h index 39005ae71b..6e519ab783 100644 --- a/gas/frags.h +++ b/gas/frags.h @@ -154,6 +154,8 @@ char *frag_var (relax_stateT type, char *opcode); bfd_boolean frag_offset_fixed_p (const fragS *, const fragS *, offsetT *); +bfd_boolean frag_offset_ignore_align_p (const fragS *, const fragS *, + offsetT *); bfd_boolean frag_gtoffset_p (valueT, const fragS *, valueT, const fragS *, offsetT *); diff --git a/gas/read.c b/gas/read.c index 9ba61cd96f..a4c6e4ed83 100644 --- a/gas/read.c +++ b/gas/read.c @@ -3506,6 +3506,11 @@ s_space (int mult) void s_nop (int ignore ATTRIBUTE_UNUSED) { + expressionS exp; + fragS *start; + addressT start_off; + offsetT frag_off; + #ifdef md_flush_pending_output md_flush_pending_output (); #endif @@ -3515,29 +3520,42 @@ s_nop (int ignore ATTRIBUTE_UNUSED) #endif SKIP_WHITESPACE (); + expression (&exp); demand_empty_rest_of_line (); + start = frag_now; + start_off = frag_now_fix (); + do + { #ifdef md_emit_single_noop - md_emit_single_noop; + md_emit_single_noop; #else - char * nop; + char *nop; #ifndef md_single_noop_insn #define md_single_noop_insn "nop" #endif - /* md_assemble might modify its argument, so - we must pass it a string that is writeable. */ - if (asprintf (&nop, "%s", md_single_noop_insn) < 0) - as_fatal ("%s", xstrerror (errno)); - - /* Some targets assume that they can update input_line_pointer inside - md_assemble, and, worse, that they can leave it assigned to the string - pointer that was provided as an argument. So preserve ilp here. */ - char * saved_ilp = input_line_pointer; - md_assemble (nop); - input_line_pointer = saved_ilp; - free (nop); + /* md_assemble might modify its argument, so + we must pass it a string that is writable. */ + if (asprintf (&nop, "%s", md_single_noop_insn) < 0) + as_fatal ("%s", xstrerror (errno)); + + /* Some targets assume that they can update input_line_pointer + inside md_assemble, and, worse, that they can leave it + assigned to the string pointer that was provided as an + argument. So preserve ilp here. */ + char *saved_ilp = input_line_pointer; + md_assemble (nop); + input_line_pointer = saved_ilp; + free (nop); +#endif +#ifdef md_flush_pending_output + md_flush_pending_output (); #endif + } while (exp.X_op == O_constant + && exp.X_add_number > 0 + && frag_offset_ignore_align_p (start, frag_now, &frag_off) + && frag_off + frag_now_fix () < start_off + exp.X_add_number); } void diff --git a/gas/testsuite/gas/elf/dwarf2-20.d b/gas/testsuite/gas/elf/dwarf2-20.d index 363510a9b0..7f3d21cec9 100644 --- a/gas/testsuite/gas/elf/dwarf2-20.d +++ b/gas/testsuite/gas/elf/dwarf2-20.d @@ -3,6 +3,12 @@ #name: DWARF2_20: debug ranges ignore non-code sections # The mn10200 target has a pointer size of 3, but it does not use segment selectors. This confuses DWARF and readelf will complain. #xfail: mn102*-* +# score-elf, tic6x-elf and xtensa-elf need special handling to support .nop 16 +#xfail: score-* tic6x-* xtensa-* +#warning: .* \.alloc0 ignored +#warning: .* \.alloc1 ignored +#warning: .* \.nonalloc ignored +#warning: .* \.nonallocexec ignored Contents of the .debug_aranges section: @@ -13,6 +19,6 @@ Contents of the .debug_aranges section: [ ]+Segment Size:[ ]+0 [ ]+Address[ ]+Length -[ ]+0+000 0+00. +[ ]+0+000 0+010 [ ]+0+000 0+000 #pass diff --git a/gas/testsuite/gas/elf/dwarf2-20.s b/gas/testsuite/gas/elf/dwarf2-20.s index 0ad0cc3ff0..00b631448b 100644 --- a/gas/testsuite/gas/elf/dwarf2-20.s +++ b/gas/testsuite/gas/elf/dwarf2-20.s @@ -1,10 +1,10 @@ .section .alloc0,"a" - .nop + .nop 16 .section .alloc1,"a" - .nop + .nop 16 .section .nonalloc,"" - .nop + .nop 16 .section .allocexec,"ax" - .nop + .nop 16 .section .nonallocexec,"x" - .nop + .nop 16 diff --git a/gas/testsuite/gas/m68hc11/indexed12.d b/gas/testsuite/gas/m68hc11/indexed12.d index 1862b6ac07..08279d7394 100644 --- a/gas/testsuite/gas/m68hc11/indexed12.d +++ b/gas/testsuite/gas/m68hc11/indexed12.d @@ -2,6 +2,10 @@ #as: -m68hc12 -gdwarf2 #name: 68HC12 indexed addressing mode with 5, 9 and 16-bit offsets (indexed12) #source: indexed12.s +#warning: .* line number information for \.data ignored +#warning: .* line number information for \.data ignored +#warning: .* line number information for \.data ignored +#warning: .* line number information for \.data ignored .*: +file format elf32\-m68hc12 -- 2.34.1