]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
rs_fill_nop and md_generate_nops
authorAlan Modra <amodra@gmail.com>
Mon, 19 May 2025 06:37:20 +0000 (16:07 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 22 May 2025 22:56:08 +0000 (08:26 +0930)
Make rs_fill_nop behave like rs_fill in using a repeat count
(fr_offset) to emit fr_var length repeated nop patterns.  Besides
being more elegant, this reduces memory required for large .nops
directives.

* as.h (rs_fill_nop): Update comment.
* config/tc-i386.c (i386_generate_nops): Handle rs_fill_nop as
for rs_align_code.
* config/tc-i386.h (MAX_MEM_FOR_RS_SPACE_NOP): Define.
* listing.c (calc_hex): Handle rs_fill_nop as for rs_fill.
* read.c (MAX_MEM_FOR_RS_SPACE_NOP): Define.
(s_nops): Use MAX_MEM_FOR_RS_SPACE_NOP setting up frag.
* write.c (write_contents): Call md_generate_nops for rs_fill_nop
before the fr_fix part is written, so that rs_fill_nop can be
handled as for rs_fill.

gas/as.h
gas/config/tc-i386.c
gas/config/tc-i386.h
gas/listing.c
gas/read.c
gas/write.c

index 826d88db013ee045c8661aadc2c228991c2cfac2..4b5f78b53d09c663b18975d9ff403705551a80ff 100644 (file)
--- a/gas/as.h
+++ b/gas/as.h
@@ -247,9 +247,7 @@ enum _relax_state
      1 constant byte: no-op fill control byte.  */
   rs_space_nop,
 
-  /* Similar to rs_fill.  It is used to implement .nops directive.
-     When listings are enabled, fr_opcode gets the buffer assigned, once
-     that's available.  */
+  /* Similar to rs_fill.  It is used to implement .nops directive.  */
   rs_fill_nop,
 
   /* A DWARF leb128 value; only ELF uses this.  The subtype is 0 for
index 1669d432a0fb431700d96bc0e2927da2ac80b884..73d552edb1391fcb8de6c3f5c43942f7fdfdf99e 100644 (file)
@@ -1769,7 +1769,7 @@ i386_generate_nops (fragS *fragP, char *where, offsetT count, int limit)
       count -= non_repeat;
     }
 
-  if (fragP->fr_type == rs_align_code)
+  if (fragP->fr_type != rs_machine_dependent)
     {
       /* Set up the frag so that everything we have emitted so far is
         included in fr_fix.  The repeating larger nop only needs to
index 2119d71c99b8910ee00e73bff0f778aa49a4a481..9137d8430965429c3a58e62707de243568fa631c 100644 (file)
@@ -390,6 +390,7 @@ if (fragP->fr_type == rs_align_code)                                        \
    Yes, the branch might be one byte longer in CODE_16BIT but then the
    largest nop is smaller.  */
 #define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 5 + 2 * 15 - 1)
+#define MAX_MEM_FOR_RS_SPACE_NOP MAX_MEM_FOR_RS_ALIGN_CODE
 
 /* We want .cfi_* pseudo-ops for generating unwind info.  */
 #define TARGET_USE_CFIPOP 1
index c47a43d3f4994fc774ab6fce7b63f254763e699f..0d1f4e8066a3448e1809bc5574e7c7ea6acf1418 100644 (file)
@@ -826,7 +826,7 @@ calc_hex (list_info_type *list)
          data_buffer_size += 2;
          octet_in_frag++;
        }
-      if (frag_ptr->fr_type == rs_fill)
+      if (frag_ptr->fr_type == rs_fill || frag_ptr->fr_type == rs_fill_nop)
        {
          unsigned int var_rep_max = octet_in_frag;
          unsigned int var_rep_idx = octet_in_frag;
@@ -851,27 +851,6 @@ calc_hex (list_info_type *list)
                var_rep_idx = var_rep_max;
            }
        }
-      else if (frag_ptr->fr_type == rs_fill_nop && frag_ptr->fr_opcode)
-       {
-         /* Print as many bytes from fr_opcode as is sensible.  */
-         octet_in_frag = 0;
-         while (octet_in_frag < (unsigned int) frag_ptr->fr_offset
-                && data_buffer_size < MAX_BYTES - 3)
-           {
-             if (address == ~(unsigned int) 0)
-               address = frag_ptr->fr_address / OCTETS_PER_BYTE;
-
-             sprintf (data_buffer + data_buffer_size,
-                      "%02X",
-                      frag_ptr->fr_opcode[octet_in_frag] & 0xff);
-             data_buffer_size += 2;
-
-             octet_in_frag++;
-           }
-
-         free (frag_ptr->fr_opcode);
-         frag_ptr->fr_opcode = NULL;
-       }
 
       frag_ptr = frag_ptr->fr_next;
     }
index de26d4b646088ffe22356760f4d3fc5b9e44c996..832a19632f2940a2fccbbba91cc37fc607db5b5f 100644 (file)
@@ -3617,6 +3617,13 @@ s_nop (int ignore ATTRIBUTE_UNUSED)
             && frag_off + frag_now_fix () < start_off + exp.X_add_number);
 }
 
+/* Use this to specify the amount of memory allocated for representing
+   the nops.  Needs to be large enough to hold any fixed size prologue
+   plus the replicating portion.  */
+#ifndef MAX_MEM_FOR_RS_SPACE_NOP
+# define MAX_MEM_FOR_RS_SPACE_NOP 1
+#endif
+
 void
 s_nops (int ignore ATTRIBUTE_UNUSED)
 {
@@ -3665,8 +3672,7 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
   /* Store the no-op instruction control byte in the first byte of frag.  */
   char *p;
   symbolS *sym = make_expr_symbol (&exp);
-  p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0,
-               sym, (offsetT) 0, (char *) 0);
+  p = frag_var (rs_space_nop, MAX_MEM_FOR_RS_SPACE_NOP, 1, 0, sym, 0, NULL);
   *p = val.X_add_number;
 }
 
index c725841d50560ac75ec72e49adf8f17f42cbc837..8ccd996089cadf8fec7f8cb71ea85c68655e3acc 100644 (file)
@@ -1653,6 +1653,19 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
       offsetT count;
 
       gas_assert (f->fr_type == rs_fill || f->fr_type == rs_fill_nop);
+
+      count = f->fr_offset;
+      fill_literal = f->fr_literal + f->fr_fix;
+      if (f->fr_type == rs_fill_nop && count > 0)
+       {
+         md_generate_nops (f, fill_literal, count, *fill_literal);
+         /* md_generate_nops updates fr_fix and fr_var.  */
+         f->fr_offset = (f->fr_next->fr_address - f->fr_address
+                         - f->fr_fix) / f->fr_var;
+         count = f->fr_offset;
+         fill_literal = f->fr_literal + f->fr_fix;
+       }
+
       if (f->fr_fix)
        {
          x = bfd_set_section_contents (stdoutput, sec,
@@ -1671,39 +1684,6 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
        }
 
       fill_size = f->fr_var;
-      count = f->fr_offset;
-      fill_literal = f->fr_literal + f->fr_fix;
-
-      if (f->fr_type == rs_fill_nop)
-       {
-         gas_assert (count >= 0 && fill_size == 1);
-         if (count > 0)
-           {
-             char *buf = xmalloc (count);
-             md_generate_nops (f, buf, count, *fill_literal);
-             x = bfd_set_section_contents
-               (stdoutput, sec, buf, (file_ptr) offset,
-                (bfd_size_type) count);
-             if (!x)
-               as_fatal (ngettext ("can't fill %ld byte "
-                                   "in section %s of %s: '%s'",
-                                   "can't fill %ld bytes "
-                                   "in section %s of %s: '%s'",
-                                   (long) count),
-                         (long) count,
-                         bfd_section_name (sec),
-                         bfd_get_filename (stdoutput),
-                         bfd_errmsg (bfd_get_error ()));
-             offset += count;
-#ifndef NO_LISTING
-             if (listing & LISTING_LISTING)
-               f->fr_opcode = buf;
-             else
-#endif
-               free (buf);
-           }
-         continue;
-       }
 
       gas_assert (count >= 0);
       if (fill_size && count)