PR25249, Memory leak in microblaze-dis.c
authorAlan Modra <amodra@gmail.com>
Thu, 5 Dec 2019 04:12:44 +0000 (14:42 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 5 Dec 2019 04:28:15 +0000 (14:58 +1030)
PR 25249
* microblaze-dis.c (NUM_STRBUFS, STRBUF_SIZE): Define.
(struct string_buf): New.
(strbuf): New function.
(get_field): Use strbuf rather than strdup of local temp.
(get_field_imm, get_field_imm5, get_field_imm5_mbar): Likewise.
(get_field_rfsl, get_field_imm15): Likewise.
(get_field_rd, get_field_r1, get_field_r2): Update macros.
(get_field_special): Likewise.  Don't strcpy spr.  Formatting.
(print_insn_microblaze): Formatting.  Init and pass string_buf to
get_field functions.

opcodes/ChangeLog
opcodes/microblaze-dis.c

index 19e719d677d3d8c2bb45fa695ba7038575387086..e8e24b18ffda3c8d1a75032d8060cd94dd12bcc7 100644 (file)
@@ -1,3 +1,17 @@
+2019-12-05  Alan Modra  <amodra@gmail.com>
+
+       PR 25249
+       * microblaze-dis.c (NUM_STRBUFS, STRBUF_SIZE): Define.
+       (struct string_buf): New.
+       (strbuf): New function.
+       (get_field): Use strbuf rather than strdup of local temp.
+       (get_field_imm, get_field_imm5, get_field_imm5_mbar): Likewise.
+       (get_field_rfsl, get_field_imm15): Likewise.
+       (get_field_rd, get_field_r1, get_field_r2): Update macros.
+       (get_field_special): Likewise.  Don't strcpy spr.  Formatting.
+       (print_insn_microblaze): Formatting.  Init and pass string_buf to
+       get_field functions.
+
 2019-12-04  Jan Beulich  <jbeulich@suse.com>
 
        * i386-opc.tbl (lfs, lgs, lss): Drop No_qSuf.
index f691740dfd13bd6def7f21a33439a98957049114..2b3aa8e078601d0853852d01be196bfa2bb71527 100644 (file)
 #include "microblaze-opc.h"
 #include "microblaze-dis.h"
 
-#define get_field_rd(instr)        get_field (instr, RD_MASK, RD_LOW)
-#define get_field_r1(instr)        get_field (instr, RA_MASK, RA_LOW)
-#define get_field_r2(instr)        get_field (instr, RB_MASK, RB_LOW)
+#define get_field_rd(buf, instr)   get_field (buf, instr, RD_MASK, RD_LOW)
+#define get_field_r1(buf, instr)   get_field (buf, instr, RA_MASK, RA_LOW)
+#define get_field_r2(buf, instr)   get_field (buf, instr, RB_MASK, RB_LOW)
 #define get_int_field_imm(instr)   ((instr & IMM_MASK) >> IMM_LOW)
 #define get_int_field_r1(instr)    ((instr & RA_MASK) >> RA_LOW)
 
+#define NUM_STRBUFS 3
+#define STRBUF_SIZE 25
 
+struct string_buf
+{
+  unsigned int which;
+  char str[NUM_STRBUFS][STRBUF_SIZE];
+};
+
+static inline char *
+strbuf (struct string_buf *buf)
+{
+#ifdef ENABLE_CHECKING
+  if (buf->which >= NUM_STRBUFS)
+    abort ();
+#endif
+  return buf->str[buf->which++];
+}
 
 static char *
-get_field (long instr, long mask, unsigned short low)
+get_field (struct string_buf *buf, long instr, long mask, unsigned short low)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%s%d", register_prefix, (int)((instr & mask) >> low));
-  return (strdup (tmpstr));
+  sprintf (p, "%s%d", register_prefix, (int)((instr & mask) >> low));
+  return p;
 }
 
 static char *
-get_field_imm (long instr)
+get_field_imm (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%d", (short)((instr & IMM_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM_MASK) >> IMM_LOW));
+  return p;
 }
 
 static char *
-get_field_imm5 (long instr)
+get_field_imm5 (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
+  return p;
 }
 
 static char *
-get_field_imm5_mbar (long instr)
+get_field_imm5_mbar (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf(tmpstr, "%d", (short)((instr & IMM5_MBAR_MASK) >> IMM_MBAR));
-  return(strdup(tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM5_MBAR_MASK) >> IMM_MBAR));
+  return p;
 }
 
 static char *
-get_field_rfsl (long instr)
+get_field_rfsl (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%s%d", fsl_register_prefix,
+  sprintf (p, "%s%d", fsl_register_prefix,
           (short)((instr & RFSL_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  return p;
 }
 
 static char *
-get_field_imm15 (long instr)
+get_field_imm15 (struct string_buf *buf, long instr)
 {
-  char tmpstr[25];
+  char *p = strbuf (buf);
 
-  sprintf (tmpstr, "%d", (short)((instr & IMM15_MASK) >> IMM_LOW));
-  return (strdup (tmpstr));
+  sprintf (p, "%d", (short)((instr & IMM15_MASK) >> IMM_LOW));
+  return p;
 }
 
 static char *
-get_field_special (long instr, struct op_code_struct * op)
+get_field_special (struct string_buf *buf, long instr,
+                  struct op_code_struct *op)
 {
-  char tmpstr[25];
-  char spr[6];
+  char *p = strbuf (buf);
+  char *spr;
 
   switch ((((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask))
     {
     case REG_MSR_MASK :
-      strcpy (spr, "msr");
+      spr = "msr";
       break;
     case REG_PC_MASK :
-      strcpy (spr, "pc");
+      spr = "pc";
       break;
     case REG_EAR_MASK :
-      strcpy (spr, "ear");
+      spr = "ear";
       break;
     case REG_ESR_MASK :
-      strcpy (spr, "esr");
+      spr = "esr";
       break;
     case REG_FSR_MASK :
-      strcpy (spr, "fsr");
+      spr = "fsr";
       break;
     case REG_BTR_MASK :
-      strcpy (spr, "btr");
+      spr = "btr";
       break;
     case REG_EDR_MASK :
-      strcpy (spr, "edr");
+      spr = "edr";
       break;
     case REG_PID_MASK :
-      strcpy (spr, "pid");
+      spr = "pid";
       break;
     case REG_ZPR_MASK :
-      strcpy (spr, "zpr");
+      spr = "zpr";
       break;
     case REG_TLBX_MASK :
-      strcpy (spr, "tlbx");
+      spr = "tlbx";
       break;
     case REG_TLBLO_MASK :
-      strcpy (spr, "tlblo");
+      spr = "tlblo";
       break;
     case REG_TLBHI_MASK :
-      strcpy (spr, "tlbhi");
+      spr = "tlbhi";
       break;
     case REG_TLBSX_MASK :
-      strcpy (spr, "tlbsx");
+      spr = "tlbsx";
       break;
     case REG_SHR_MASK :
-      strcpy (spr, "shr");
+      spr = "shr";
       break;
     case REG_SLR_MASK :
-      strcpy (spr, "slr");
+      spr = "slr";
       break;
     default :
       if (((((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) & 0xE000)
-          == REG_PVR_MASK)
-        {
-         sprintf (tmpstr, "%spvr%d", register_prefix,
+         == REG_PVR_MASK)
+       {
+         sprintf (p, "%spvr%d", register_prefix,
                   (unsigned short)(((instr & IMM_MASK) >> IMM_LOW)
-                                    ^ op->immval_mask) ^ REG_PVR_MASK);
-         return (strdup (tmpstr));
-        }
+                                   ^ op->immval_mask) ^ REG_PVR_MASK);
+         return p;
+       }
       else
-        strcpy (spr, "pc");
+       spr = "pc";
       break;
     }
 
-   sprintf (tmpstr, "%s%s", register_prefix, spr);
-   return (strdup (tmpstr));
+   sprintf (p, "%s%s", register_prefix, spr);
+   return p;
 }
 
 static unsigned long
@@ -210,7 +228,9 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   static bfd_vma      prev_insn_addr = -1; /* Init the prev insn addr.  */
   static int          prev_insn_vma = -1;  /* Init the prev insn vma.  */
   int                 curr_insn_vma = info->buffer_vma;
+  struct string_buf   buf;
 
+  buf.which = 0;
   info->bytes_per_chunk = 4;
 
   inst = read_insn_microblaze (memaddr, info, &op);
@@ -220,8 +240,8 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
   if (prev_insn_vma == curr_insn_vma)
     {
       if (memaddr-(info->bytes_per_chunk) == prev_insn_addr)
-        {
-          prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
+       {
+         prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
          if (prev_inst == 0)
            return -1;
          if (pop->instr == imm)
@@ -249,163 +269,173 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
 
       switch (op->inst_type)
        {
-        case INST_TYPE_RD_R1_R2:
-          print_func (stream, "\t%s, %s, %s", get_field_rd (inst),
-                  get_field_r1(inst), get_field_r2 (inst));
-          break;
-        case INST_TYPE_RD_R1_IMM:
-         print_func (stream, "\t%s, %s, %s", get_field_rd (inst),
-                  get_field_r1(inst), get_field_imm (inst));
+       case INST_TYPE_RD_R1_R2:
+         print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst), get_field_r2 (&buf, inst));
+         break;
+       case INST_TYPE_RD_R1_IMM:
+         print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst), get_field_imm (&buf, inst));
          if (info->print_address_func && get_int_field_r1 (inst) == 0
              && info->symbol_at_address_func)
            {
              if (immfound)
-               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
              else
                {
-                 immval = get_int_field_imm (inst);
-                 if (immval & 0x8000)
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
                    immval |= 0xFFFF0000;
-               }
+               }
              if (immval > 0 && info->symbol_at_address_func (immval, info))
                {
-                 print_func (stream, "\t// ");
-                 info->print_address_func (immval, info);
-               }
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
            }
          break;
        case INST_TYPE_RD_R1_IMM5:
-         print_func (stream, "\t%s, %s, %s", get_field_rd (inst),
-                  get_field_r1(inst), get_field_imm5 (inst));
+         print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst), get_field_imm5 (&buf, inst));
          break;
        case INST_TYPE_RD_RFSL:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_rfsl (inst));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_rfsl (&buf, inst));
          break;
        case INST_TYPE_R1_RFSL:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_rfsl (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_rfsl (&buf, inst));
          break;
        case INST_TYPE_RD_SPECIAL:
-         print_func (stream, "\t%s, %s", get_field_rd (inst),
-                  get_field_special (inst, op));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_special (&buf, inst, op));
          break;
        case INST_TYPE_SPECIAL_R1:
-         print_func (stream, "\t%s, %s", get_field_special (inst, op),
-                  get_field_r1(inst));
+         print_func (stream, "\t%s, %s", get_field_special (&buf, inst, op),
+                     get_field_r1 (&buf, inst));
          break;
        case INST_TYPE_RD_R1:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_r1 (inst));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_r1 (&buf, inst));
          break;
        case INST_TYPE_R1_R2:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_r2 (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_R1_IMM:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_imm (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_imm (&buf, inst));
          /* The non-pc relative instructions are returns, which shouldn't
             have a label printed.  */
          if (info->print_address_func && op->inst_offset_type == INST_PC_OFFSET
              && info->symbol_at_address_func)
            {
              if (immfound)
-               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
              else
                {
-                 immval = get_int_field_imm (inst);
-                 if (immval & 0x8000)
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
                    immval |= 0xFFFF0000;
-               }
+               }
              immval += memaddr;
              if (immval > 0 && info->symbol_at_address_func (immval, info))
                {
-                 print_func (stream, "\t// ");
-                 info->print_address_func (immval, info);
-               }
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
              else
                {
-                 print_func (stream, "\t\t// ");
-                 print_func (stream, "%x", immval);
-               }
+                 print_func (stream, "\t\t// ");
+                 print_func (stream, "%x", immval);
+               }
            }
          break;
-        case INST_TYPE_RD_IMM:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_imm (inst));
+       case INST_TYPE_RD_IMM:
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_imm (&buf, inst));
          if (info->print_address_func && info->symbol_at_address_func)
            {
-           if (immfound)
-             immval |= (get_int_field_imm (inst) & 0x0000ffff);
-           else
-             {
-               immval = get_int_field_imm (inst);
-               if (immval & 0x8000)
-                 immval |= 0xFFFF0000;
-             }
-           if (op->inst_offset_type == INST_PC_OFFSET)
-             immval += (int) memaddr;
-           if (info->symbol_at_address_func (immval, info))
-             {
-               print_func (stream, "\t// ");
-               info->print_address_func (immval, info);
-             }
+             if (immfound)
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+             else
+               {
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
+                   immval |= 0xFFFF0000;
+               }
+             if (op->inst_offset_type == INST_PC_OFFSET)
+               immval += (int) memaddr;
+             if (info->symbol_at_address_func (immval, info))
+               {
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
            }
          break;
-        case INST_TYPE_IMM:
-         print_func (stream, "\t%s", get_field_imm (inst));
+       case INST_TYPE_IMM:
+         print_func (stream, "\t%s", get_field_imm (&buf, inst));
          if (info->print_address_func && info->symbol_at_address_func
              && op->instr != imm)
            {
              if (immfound)
-               immval |= (get_int_field_imm (inst) & 0x0000ffff);
+               immval |= (get_int_field_imm (inst) & 0x0000ffff);
              else
                {
-                 immval = get_int_field_imm (inst);
-                 if (immval & 0x8000)
+                 immval = get_int_field_imm (inst);
+                 if (immval & 0x8000)
                    immval |= 0xFFFF0000;
-               }
+               }
              if (op->inst_offset_type == INST_PC_OFFSET)
-               immval += (int) memaddr;
+               immval += (int) memaddr;
              if (immval > 0 && info->symbol_at_address_func (immval, info))
                {
-                 print_func (stream, "\t// ");
-                 info->print_address_func (immval, info);
-               }
+                 print_func (stream, "\t// ");
+                 info->print_address_func (immval, info);
+               }
              else if (op->inst_offset_type == INST_PC_OFFSET)
                {
-                 print_func (stream, "\t\t// ");
-                 print_func (stream, "%x", immval);
-               }
+                 print_func (stream, "\t\t// ");
+                 print_func (stream, "%x", immval);
+               }
            }
          break;
-        case INST_TYPE_RD_R2:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_r2 (inst));
+       case INST_TYPE_RD_R2:
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_R2:
-         print_func (stream, "\t%s", get_field_r2 (inst));
+         print_func (stream, "\t%s", get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_R1:
-         print_func (stream, "\t%s", get_field_r1 (inst));
+         print_func (stream, "\t%s", get_field_r1 (&buf, inst));
          break;
        case INST_TYPE_R1_R2_SPECIAL:
-         print_func (stream, "\t%s, %s", get_field_r1 (inst), get_field_r2 (inst));
+         print_func (stream, "\t%s, %s", get_field_r1 (&buf, inst),
+                     get_field_r2 (&buf, inst));
          break;
        case INST_TYPE_RD_IMM15:
-         print_func (stream, "\t%s, %s", get_field_rd (inst), get_field_imm15 (inst));
+         print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
+                     get_field_imm15 (&buf, inst));
          break;
-        /* For mbar insn.  */
-        case INST_TYPE_IMM5:
-          print_func (stream, "\t%s", get_field_imm5_mbar (inst));
-          break;
-        /* For mbar 16 or sleep insn.  */
-        case INST_TYPE_NONE:
-          break;
-       /* For tuqula instruction */
+         /* For mbar insn.  */
+       case INST_TYPE_IMM5:
+         print_func (stream, "\t%s", get_field_imm5_mbar (&buf, inst));
+         break;
+         /* For mbar 16 or sleep insn.  */
+       case INST_TYPE_NONE:
+         break;
+         /* For tuqula instruction */
        case INST_TYPE_RD:
-         print_func (stream, "\t%s", get_field_rd (inst));
+         print_func (stream, "\t%s", get_field_rd (&buf, inst));
          break;
        case INST_TYPE_RFSL:
-         print_func (stream, "\t%s", get_field_rfsl (inst));
+         print_func (stream, "\t%s", get_field_rfsl (&buf, inst));
          break;
        default:
          /* If the disassembler lags the instruction set.  */
-         print_func (stream, "\tundecoded operands, inst is 0x%04x", (unsigned int) inst);
+         print_func (stream, "\tundecoded operands, inst is 0x%04x",
+                     (unsigned int) inst);
          break;
        }
     }