This is the mail archive of the binutils@sources.redhat.com 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]

[PATCH-ping] VAX: Forced decoding of function entry masks (eg. for disassembling ROM images)


Hi!

I'd like to ping for my last patch, introducing the capability to
better disassemble ROM or MOP boot images with eg. objdump. Andreas'
objection about a limited number of entry addresses is fixed.

2005-03-21  Jan-Benedict Glaw  <jbglaw@lug-owl.de>

	opcodes/
	* vax-dis.c: (struct private): Add a bfd_vma pointer to store
	supplied function entry mask addresses.
	(init_private_data): New; fill in supplied entry mask addresses.
	(free_private_data): New; free() entry mask addresses.
	(is_function_entry): Check if a given address is a function's
	start address by looking at supplied entry mask addresses and
	symbol information, if available.
	(print_insn_vax): Use init_private_data(), is_function_entry()
	and free_private_data().

	binutils/doc/
	* binutils.texi: Document new VAX disassembler-specific option
	-M entry:0xfooba8.


diff -Nurp src-fresh/binutils/doc/binutils.texi src-hacked/binutils/doc/binutils.texi
--- src-fresh/binutils/doc/binutils.texi	2005-03-21 13:26:04.000000000 +0100
+++ src-hacked/binutils/doc/binutils.texi	2005-03-21 20:09:33.000000000 +0100
@@ -1793,6 +1793,13 @@ rather than names, for the selected type
 You can list the available values of @var{ABI} and @var{ARCH} using
 the @option{--help} option.
 
+For VAX, you can specify function entry addresses with
+@option{-M entry:0xf00ba}. You can use this multiple times to properly
+disassemble VAX binary files that don't contain symbol tables (like
+ROM dumps). In these cases, the function entry mask would otherwise
+be decoded as VAX instructions, which would probably lead to the
+rest of the function being wrongly disassembled.
+
 @item -p
 @itemx --private-headers
 Print information that is specific to the object file format.  The exact
diff -Nurp src-fresh/opcodes/vax-dis.c src-hacked/opcodes/vax-dis.c
--- src-fresh/opcodes/vax-dis.c	2005-03-14 14:07:03.000000000 +0100
+++ src-hacked/opcodes/vax-dis.c	2005-03-21 16:29:49.000000000 +0100
@@ -17,17 +17,38 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#include <setjmp.h>
+#include <string.h>
 #include "sysdep.h"
 #include "opcode/vax.h"
 #include "dis-asm.h"
 
+/* Maximum length of an instruction.  */
+#define MAXLEN 25
+
+struct private
+{
+  /* Points to first byte not fetched.  */
+  bfd_byte *max_fetched;
+  bfd_byte the_buffer[MAXLEN];
+  bfd_vma insn_start;
+  jmp_buf bailout;
+  /* Entry mask handling  */
+  int num_entry_addr;
+  bfd_vma *entry_addr;
+};
+
 /* Local function prototypes */
 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
 static int print_insn_arg
   PARAMS ((const char *, unsigned char *, bfd_vma, disassemble_info *));
 static int print_insn_mode
   PARAMS ((const char *, int, unsigned char *, bfd_vma, disassemble_info *));
-
+static int init_private_data
+  PARAMS ((struct disassemble_info *, struct private *));
+static void free_private_data PARAMS ((struct private *));
+static bfd_boolean is_function_entry
+  PARAMS ((struct disassemble_info *, bfd_vma addr));
 
 static char *reg_names[] =
 {
@@ -74,20 +95,6 @@ static char *entry_mask_bit[] =
   (p += 4, FETCH_DATA (info, p), \
    (COERCE32 ((((((p[-1] << 8) + p[-2]) << 8) + p[-3]) << 8) + p[-4])))
 
-/* Maximum length of an instruction.  */
-#define MAXLEN 25
-
-#include <setjmp.h>
-
-struct private
-{
-  /* Points to first byte not fetched.  */
-  bfd_byte *max_fetched;
-  bfd_byte the_buffer[MAXLEN];
-  bfd_vma insn_start;
-  jmp_buf bailout;
-};
-
 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
    on error.  */
@@ -95,6 +102,74 @@ struct private
   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
    ? 1 : fetch_data ((info), (addr)))
 
+
+/* Init our private data. This decodes supplied entry addresses, which can
+   be useful to disassemble ROM images, since there's no symbol table.  */
+static int
+init_private_data (info, priv)
+    struct disassemble_info *info;
+    struct private *priv;
+{
+  char *tmp;
+
+  priv->num_entry_addr = 0;
+  priv->entry_addr = NULL;
+
+  if (info->disassembler_options)
+    {
+      tmp = info->disassembler_options;
+      while ((tmp = strstr (tmp, "entry:")))
+	{
+	  tmp += strlen ("entry:");
+	  priv->entry_addr = realloc (priv->entry_addr, sizeof (bfd_vma)
+				      * (priv->num_entry_addr + 1));
+	  if (!priv->entry_addr)
+	    return -1;
+	  priv->entry_addr[priv->num_entry_addr++] = bfd_scan_vma (tmp, NULL,
+			  					   0);
+	}
+    }
+
+  return 0;
+}
+
+/* Free memory allocated by init_private_data()  */
+static void
+free_private_data (priv)
+    struct private *priv;
+{
+  if (priv->entry_addr)
+    free (priv->entry_addr);
+}
+
+/* Check if the given address is a known function entry. Either there must
+   be a symbol of function type at this address, or the address must be
+   a forced entry point. The later helps in disassembling ROM images, because
+   there's no symbol table at all. Forced entry points can be given by
+   supplying several -M options to objdump: -M entry:0xffbb7730 .  */
+static bfd_boolean
+is_function_entry (info, addr)
+      struct disassemble_info *info;
+      bfd_vma addr;
+{
+  int i;
+  struct private *priv = info->private_data;
+
+  /* Check if there's a BSF_FUNCTION symbol at our address.  */
+  if (info->symbols
+      && info->symbols[0]
+      && (info->symbols[0]->flags & BSF_FUNCTION)
+      && addr == bfd_asymbol_value (info->symbols[0]))
+    return TRUE;
+
+  /* Check for forced function entry address.  */
+  for (i = 0; i < priv->num_entry_addr; i++)
+    if (priv->entry_addr[i] == addr)
+      return TRUE;
+
+  return FALSE;
+}
+
 static int
 fetch_data (info, addr)
      struct disassemble_info *info;
@@ -133,6 +208,9 @@ print_insn_vax (memaddr, info)
   struct private priv;
   bfd_byte *buffer = priv.the_buffer;
 
+  if (init_private_data (info, &priv) < 0)
+    return -1;
+
   info->private_data = (PTR) &priv;
   priv.max_fetched = priv.the_buffer;
   priv.insn_start = memaddr;
@@ -140,6 +218,7 @@ print_insn_vax (memaddr, info)
   if (setjmp (priv.bailout) != 0)
     {
       /* Error return.  */
+      free_private_data (&priv);
       return -1;
     }
 
@@ -157,10 +236,7 @@ print_insn_vax (memaddr, info)
     }
 
   /* Decode function entry mask.  */
-  if (info->symbols
-      && info->symbols[0]
-      && (info->symbols[0]->flags & BSF_FUNCTION)
-      && memaddr == bfd_asymbol_value (info->symbols[0]))
+  if (is_function_entry (info, memaddr))
     {
       int i = 0;
       int register_mask = buffer[1] << 8 | buffer[0];
@@ -174,6 +250,7 @@ print_insn_vax (memaddr, info)
 
       (*info->fprintf_func) (info->stream, " >");
 
+      free_private_data (&priv);
       return 2;
     }
 
@@ -194,6 +271,7 @@ print_insn_vax (memaddr, info)
       /* Handle undefined instructions. */
       (*info->fprintf_func) (info->stream, ".word 0x%x",
 			     (buffer[0] << 8) + buffer[1]);
+      free_private_data (&priv);
       return 2;
     }
 
@@ -216,6 +294,7 @@ print_insn_vax (memaddr, info)
 	(*info->fprintf_func) (info->stream, ",");
     }
 
+  free_private_data (&priv);
   return arg - buffer;
 }
 
MfG, JBG

-- 
AWEK microdata GmbH -- Am Wellbach 4 -- 33609 Bielefeld


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