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]

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


Hi Jan-Benedict,

Basically, I of course like the idea of parsing the options only
once.  OTOH, this is one more location that's leaking. Maybe the
time is come to *really* implement an initializer and termination
function for the disassembler backends? But I'm not sure if it's
worth it. Disassembling used to be a slow process, and it's a rare
situation. Even on a VAX, I'd accept that it takes some time[tm]
to disassemble something.  ...and with today's PCs, the overhead
of parsing the options each time /one/ opcode is being
disassembled is irrelevant.

So the pros and cons of your implementation are:

	+ faster
	- leaks memory
	- modifies disassembler_info->disassembler_options

If somebody would implement a init/fini function for the backend, that
would turn out to only being faster with no drawbacks...

Being somewhat undecided, I'd say let's push in your version and start
a new thread about init/fini functions for the disassembler backend.
I'll push it through the compiler in the mean time.

Ok - I have pushed my version, with a few fixes to address all of the issues you mentioned, except the memory leak. (See the attached patch). I think that this leak is OK for now, but we should not forget it. One day (soon I hope), I'll write the code to add the necessary hooks, so that the leak can be removed.


Cheers
  Nick


Index: opcodes/vax-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/vax-dis.c,v
retrieving revision 1.9
diff -c -3 -p -r1.9 vax-dis.c
*** opcodes/vax-dis.c	14 Mar 2005 09:35:26 -0000	1.9
--- opcodes/vax-dis.c	29 Mar 2005 16:04:47 -0000
***************
*** 17,22 ****
--- 17,24 ----
     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"
*************** static char *entry_mask_bit[] =
*** 77,91 ****
  /* 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)
--- 79,91 ----
  /* 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;
  };
  
  /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
*************** fetch_data (info, addr)
*** 119,124 ****
--- 119,213 ----
    return 1;
  }
  
+ /* Entry mask handling.  */
+ static unsigned int  entry_addr_occupied_slots = 0;
+ static unsigned int  entry_addr_total_slots = 0;
+ static bfd_vma *     entry_addr = NULL;
+ 
+ /* Parse the VAX specific disassembler options.  These contain function
+    entry addresses, which can be useful to disassemble ROM images, since
+    there's no symbol table.  Returns TRUE upon success, FALSE otherwise.  */
+ 
+ static bfd_boolean
+ parse_disassembler_options (char * options)
+ {
+   const char * entry_switch = "entry:";
+ 
+   while ((options = strstr (options, entry_switch)))
+     {
+       options += strlen (entry_switch);
+ 
+       /* The greater-than part of the test below is paranoia.  */
+       if (entry_addr_occupied_slots >= entry_addr_total_slots)
+ 	{
+ 	  /* A guesstimate of the number of entries we will have to create.  */
+ 	  entry_addr_total_slots +=
+ 	    strlen (options) / (strlen (entry_switch) + 5);
+ 	  
+ 	  entry_addr = realloc (entry_addr, sizeof (bfd_vma)
+ 				* entry_addr_total_slots);
+ 	}
+ 
+       if (entry_addr == NULL)
+ 	return FALSE;
+ 	  
+       entry_addr[entry_addr_occupied_slots] = bfd_scan_vma (options, NULL, 0);
+       entry_addr_occupied_slots ++;
+     }
+ 
+   return TRUE;
+ }
+ 
+ #if 0 /* FIXME:  Ideally the disassembler should have target specific
+ 	 initialisation and termination function pointers.  Then
+ 	 parse_disassembler_options could be the init function and
+ 	 free_entry_array (below) could be the termination routine.
+ 	 Until then there is no way for the disassembler to tell us
+ 	 that it has finished and that we no longer need the entry
+ 	 array, so this routine is suppressed for now.  It does mean
+ 	 that we leak memory, but only to the extent that we do not
+ 	 free it just before the disassembler is about to terminate
+ 	 anyway.  */
+ 
+ /* Free memory allocated to our entry array.  */
+ 
+ static void
+ free_entry_array (void)
+ {
+   if (entry_addr)
+     {
+       free (entry_addr);
+       entry_addr = NULL;
+       entry_addr_occupied_slots = entry_addr_total_slots = 0;
+     }
+ }
+ #endif
+ /* 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 (struct disassemble_info *info, bfd_vma addr)
+ {
+   unsigned int i;
+ 
+   /* 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 = entry_addr_occupied_slots; i--;)
+     if (entry_addr[i] == addr)
+       return TRUE;
+ 
+   return FALSE;
+ }
+ 
  /* Print the vax instruction at address MEMADDR in debugged memory,
     on INFO->STREAM.  Returns length of the instruction, in bytes.  */
  
*************** print_insn_vax (memaddr, info)
*** 127,132 ****
--- 216,222 ----
       bfd_vma memaddr;
       disassemble_info *info;
  {
+   static bfd_boolean parsed_disassembler_options = FALSE;
    const struct vot *votp;
    const char *argp;
    unsigned char *arg;
*************** print_insn_vax (memaddr, info)
*** 137,142 ****
--- 227,241 ----
    priv.max_fetched = priv.the_buffer;
    priv.insn_start = memaddr;
  
+   if (! parsed_disassembler_options
+       && info->disassembler_options != NULL)
+     {
+       parse_disassembler_options (info->disassembler_options);
+ 
+       /* To avoid repeated parsing of these options.  */
+       parsed_disassembler_options = TRUE;
+     }
+ 
    if (setjmp (priv.bailout) != 0)
      {
        /* Error return.  */
*************** print_insn_vax (memaddr, info)
*** 157,166 ****
      }
  
    /* Decode function entry mask.  */
!   if (info->symbols
!       && info->symbols[0]
!       && (info->symbols[0]->flags & BSF_FUNCTION)
!       && memaddr == bfd_asymbol_value (info->symbols[0]))
      {
        int i = 0;
        int register_mask = buffer[1] << 8 | buffer[0];
--- 256,262 ----
      }
  
    /* Decode function entry mask.  */
!   if (is_function_entry (info, memaddr))
      {
        int i = 0;
        int register_mask = buffer[1] << 8 | buffer[0];

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