This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR25249, Memory leak in microblaze-dis.c


	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.

diff --git a/opcodes/microblaze-dis.c b/opcodes/microblaze-dis.c
index f691740dfd..2b3aa8e078 100644
--- a/opcodes/microblaze-dis.c
+++ b/opcodes/microblaze-dis.c
@@ -29,138 +29,156 @@
 #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;
 	}
     }

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]