public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Decode function entry mask on VAXen
@ 2005-03-08  2:14 Jan-Benedict Glaw
  2005-03-08 12:14 ` Alan Modra
  0 siblings, 1 reply; 7+ messages in thread
From: Jan-Benedict Glaw @ 2005-03-08  2:14 UTC (permalink / raw)
  To: binutils

Hi!

An entry point of a function on a VAX is a bit different compared to
those of other CPUs: at the address of the entry point the CPU won't
find the first instruction to execute, but a 2 byte long bit mask
indicating the registers to be pushed onto the stack prior function
execution (basically, this is all registers used in that function,
except registers 0+1, which are used for the return value, as well
as stack/frame/argument pointer and PC).

Unfortunately, objdump didn't honor the entry mask, disassembling it
as regular instructions. In some cases, the first (two) bytes won't
make one two-byte (or two one-byte) instructions, thus mixing up the
remaining functional part of the function.

I'd like to see a patch like this installed, please comment on it.
(A changelog entry is however missing...):

diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/binutils/objdump.c src/binutils/objdump.c
--- ../cvs-repos/binutils/binutils-upstream-HEAD/binutils/objdump.c	2005-03-01 16:18:42.000000000 +0100
+++ src/binutils/objdump.c	2005-03-08 02:53:26.000000000 +0100
@@ -1379,7 +1379,11 @@ disassemble_bytes (struct disassemble_in
 	      info->stream = (FILE *) &sfile;
 	      info->bytes_per_line = 0;
 	      info->bytes_per_chunk = 0;
-	      info->flags = 0;
+	      info->last_symbol_address = section->vma + start_offset;
+	      if (disassemble && disassemble_all)
+		info->flags = FORCE_DISASSEMBLE;
+	      else
+		info->flags = 0;
 
 #ifdef DISASSEMBLER_NEEDS_RELOCS
 	      if (*relppp < relppend)
diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/include/dis-asm.h src/include/dis-asm.h
--- ../cvs-repos/binutils/binutils-upstream-HEAD/include/dis-asm.h	2005-03-03 12:58:01.000000000 +0100
+++ src/include/dis-asm.h	2005-03-08 01:26:23.000000000 +0100
@@ -98,7 +98,11 @@ typedef struct disassemble_info {
      The top 16 bits are reserved for public use (and are documented here).
      The bottom 16 bits are for the internal use of the disassembler.  */
   unsigned long flags;
-#define INSN_HAS_RELOC	0x80000000
+#define INSN_HAS_RELOC		0x80000000
+#define FORCE_DISASSEMBLE	0x40000000	/* Force disassembly of the
+						   address, even if it was
+						   probably better handled in
+						   a different way  */
   void *private_data;
 
   /* Function used to get bytes to disassemble.  MEMADDR is the
@@ -187,6 +191,7 @@ typedef struct disassemble_info {
   bfd_vma target;		/* Target address of branch or dref, if known;
 				   zero if unknown.  */
   bfd_vma target2;		/* Second target address for dref2 */
+  bfd_vma last_symbol_address;	/* Address of last symbol or section start  */
 
   /* Command line options specific to the target disassembler.  */
   char * disassembler_options;
diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/opcodes/vax-dis.c src/opcodes/vax-dis.c
--- ../cvs-repos/binutils/binutils-upstream-HEAD/opcodes/vax-dis.c	2002-05-10 01:11:30.000000000 +0200
+++ src/opcodes/vax-dis.c	2005-03-08 03:01:48.000000000 +0100
@@ -1,5 +1,5 @@
 /* Print VAX instructions.
-   Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright 1995, 1998, 2000-2002, 2005 Free Software Foundation, Inc.
    Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
 
 This program is free software; you can redistribute it and/or modify
@@ -34,6 +34,21 @@ static char *reg_names[] =
   "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
 };
 
+/* Definitions for the function entry mask bits.  */
+static char *entry_mask_bit[] =
+{
+  /* Registers 0 and 1 shall not be saved, since they're used to pass back
+     a function's result to it's caller...  */
+  "~r0~", "~r1~",
+  /* Registers 2 .. 11 are normal registers.  */
+  "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+  /* Registers 12 and 13 are argument and frame pointer and must not
+     be saved by using the entry mask.  */
+  "~ap~", "~fp~",
+  /* Bits 14 and 15 control integer and decimal overflow.  */
+  "IntOvfl", "DecOvfl",
+};
+
 /* Sign-extend an (unsigned char). */
 #if __STDC__ == 1
 #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
@@ -140,6 +155,26 @@ print_insn_vax (memaddr, info)
       buffer[1] = 0;
     }
 
+  /* Decode function entry mask.  */
+  if (memaddr - info->last_symbol_address < 2 &&
+		  !(info->flags & FORCE_DISASSEMBLE))
+    {
+      int i = 0;
+      int register_mask = buffer[1] << 8 | buffer[0];
+
+      (*info->fprintf_func) (info->stream, "Entry mask 0x%04x = <",
+			     register_mask);
+
+      for (i = 15; i >= 0; i--)
+	if (register_mask & (1 << i))
+          (*info->fprintf_func) (info->stream, " %s",
+			entry_mask_bit[i]);
+
+      (*info->fprintf_func) (info->stream, " >");
+
+      return 2;
+    }
+
   for (votp = &votstrs[0]; votp->name[0]; votp++)
     {
       register vax_opcodeT opcode = votp->detail.code;


My goal is to do further cleanups of the VAX code (starting with the
simple parts like converting K&R-style function heads, ...).

MfG, JBG
-- 
Look hard: my ~/.signature is well hidden! You won't find it :-)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Decode function entry mask on VAXen
  2005-03-08  2:14 Decode function entry mask on VAXen Jan-Benedict Glaw
@ 2005-03-08 12:14 ` Alan Modra
  2005-03-08 12:25   ` Jan-Benedict Glaw
  2005-03-08 20:30   ` Jan-Benedict Glaw
  0 siblings, 2 replies; 7+ messages in thread
From: Alan Modra @ 2005-03-08 12:14 UTC (permalink / raw)
  To: Jan-Benedict Glaw; +Cc: binutils

objdump already breaks up calls to disassemble_bytes into the pieces of
a section between two defined symbols (possibly validated by a target
symbol_is_valid function).  So if the only symbols in vax code are those
at the beginning of a function, your idea of using last_symbol_address
will work.  However, I think it would be better to pass
"asymbol *last_symbol" instead, which gives your backend disassembler_fn
a chance to deal with non-function symbols that might appear in code.

Note that gdb also uses the disassembler, so it would be a good idea to
see how your ideas fit in with gdb too.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Decode function entry mask on VAXen
  2005-03-08 12:14 ` Alan Modra
@ 2005-03-08 12:25   ` Jan-Benedict Glaw
  2005-03-08 20:30   ` Jan-Benedict Glaw
  1 sibling, 0 replies; 7+ messages in thread
From: Jan-Benedict Glaw @ 2005-03-08 12:25 UTC (permalink / raw)
  To: binutils

On Tue, Mar 08, 2005 at 10:44:00PM +1030, Alan Modra wrote:

Hi Alan!

> objdump already breaks up calls to disassemble_bytes into the pieces of
> a section between two defined symbols (possibly validated by a target
> symbol_is_valid function).  So if the only symbols in vax code are those
> at the beginning of a function, your idea of using last_symbol_address
> will work.  However, I think it would be better to pass
> "asymbol *last_symbol" instead, which gives your backend disassembler_fn
> a chance to deal with non-function symbols that might appear in code.

I'll try to implement that. For sure, non-function symbols will show up
from time to time... However, in a typical ELF object file, there are
somewhat rare, while wrongly disassembled functions were the standard :)

> Note that gdb also uses the disassembler, so it would be a good idea to
> see how your ideas fit in with gdb too.

I think vax-linux isn't yet a supported gdb target, but I'll try to get
NetBSD running on one of my /90 and have a test with it, too. The BSD
guys should have basically the same problems here...

Thanks again, JBG

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Decode function entry mask on VAXen
  2005-03-08 12:14 ` Alan Modra
  2005-03-08 12:25   ` Jan-Benedict Glaw
@ 2005-03-08 20:30   ` Jan-Benedict Glaw
  2005-03-09  0:45     ` Alan Modra
  1 sibling, 1 reply; 7+ messages in thread
From: Jan-Benedict Glaw @ 2005-03-08 20:30 UTC (permalink / raw)
  To: binutils

On Tue, Mar 08, 2005 at 10:44:00PM +1030, Alan Modra wrote:
> objdump already breaks up calls to disassemble_bytes into the pieces of
> a section between two defined symbols (possibly validated by a target
> symbol_is_valid function).  So if the only symbols in vax code are those
> at the beginning of a function, your idea of using last_symbol_address
> will work.  However, I think it would be better to pass
> "asymbol *last_symbol" instead, which gives your backend disassembler_fn
> a chance to deal with non-function symbols that might appear in code.

Here's a new version, which indeed works even better than the previous
version (correctly, there's no entry mask decoded for hand-crafted
assembler parts that we jump to). Could you please also comment on this?

diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/binutils/objdump.c src/binutils/objdump.c
--- ../cvs-repos/binutils/binutils-upstream-HEAD/binutils/objdump.c	2005-03-01 16:18:42.000000000 +0100
+++ src/binutils/objdump.c	2005-03-08 19:40:46.000000000 +0100
@@ -1379,7 +1379,12 @@ disassemble_bytes (struct disassemble_in
 	      info->stream = (FILE *) &sfile;
 	      info->bytes_per_line = 0;
 	      info->bytes_per_chunk = 0;
-	      info->flags = 0;
+	      info->last_symbol = find_symbol_for_address (section->vma +
+			      start_offset, info, NULL);
+	      if (disassemble && disassemble_all)
+		info->flags = FORCE_DISASSEMBLE;
+	      else
+		info->flags = 0;
 
 #ifdef DISASSEMBLER_NEEDS_RELOCS
 	      if (*relppp < relppend)
diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/include/dis-asm.h src/include/dis-asm.h
--- ../cvs-repos/binutils/binutils-upstream-HEAD/include/dis-asm.h	2005-03-03 12:58:01.000000000 +0100
+++ src/include/dis-asm.h	2005-03-08 19:39:36.000000000 +0100
@@ -98,7 +98,11 @@ typedef struct disassemble_info {
      The top 16 bits are reserved for public use (and are documented here).
      The bottom 16 bits are for the internal use of the disassembler.  */
   unsigned long flags;
-#define INSN_HAS_RELOC	0x80000000
+#define INSN_HAS_RELOC		0x80000000
+#define FORCE_DISASSEMBLE	0x40000000	/* Force disassembly of the
+						   address, even if it was
+						   probably better handled in
+						   a different way  */
   void *private_data;
 
   /* Function used to get bytes to disassemble.  MEMADDR is the
@@ -187,6 +191,7 @@ typedef struct disassemble_info {
   bfd_vma target;		/* Target address of branch or dref, if known;
 				   zero if unknown.  */
   bfd_vma target2;		/* Second target address for dref2 */
+  asymbol *last_symbol;		/* Address of last symbol or section start  */
 
   /* Command line options specific to the target disassembler.  */
   char * disassembler_options;
diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/opcodes/vax-dis.c src/opcodes/vax-dis.c
--- ../cvs-repos/binutils/binutils-upstream-HEAD/opcodes/vax-dis.c	2002-05-10 01:11:30.000000000 +0200
+++ src/opcodes/vax-dis.c	2005-03-08 19:51:47.000000000 +0100
@@ -1,5 +1,5 @@
 /* Print VAX instructions.
-   Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright 1995, 1998, 2000-2002, 2005 Free Software Foundation, Inc.
    Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
 
 This program is free software; you can redistribute it and/or modify
@@ -34,6 +34,21 @@ static char *reg_names[] =
   "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
 };
 
+/* Definitions for the function entry mask bits.  */
+static char *entry_mask_bit[] =
+{
+  /* Registers 0 and 1 shall not be saved, since they're used to pass back
+     a function's result to it's caller...  */
+  "~r0~", "~r1~",
+  /* Registers 2 .. 11 are normal registers.  */
+  "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+  /* Registers 12 and 13 are argument and frame pointer and must not
+     be saved by using the entry mask.  */
+  "~ap~", "~fp~",
+  /* Bits 14 and 15 control integer and decimal overflow.  */
+  "IntOvfl", "DecOvfl",
+};
+
 /* Sign-extend an (unsigned char). */
 #if __STDC__ == 1
 #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
@@ -140,6 +155,28 @@ print_insn_vax (memaddr, info)
       buffer[1] = 0;
     }
 
+  /* Decode function entry mask.  */
+  if (info->last_symbol
+		  && (info->last_symbol->flags & BSF_FUNCTION)
+		  && !(info->flags & FORCE_DISASSEMBLE)
+		  && memaddr == bfd_asymbol_value (info->last_symbol))
+    {
+      int i = 0;
+      int register_mask = buffer[1] << 8 | buffer[0];
+
+      (*info->fprintf_func) (info->stream, "Entry mask 0x%04x = <",
+			     register_mask);
+
+      for (i = 15; i >= 0; i--)
+	if (register_mask & (1 << i))
+          (*info->fprintf_func) (info->stream, " %s",
+			entry_mask_bit[i]);
+
+      (*info->fprintf_func) (info->stream, " >");
+
+      return 2;
+    }
+
   for (votp = &votstrs[0]; votp->name[0]; votp++)
     {
       register vax_opcodeT opcode = votp->detail.code;

> Note that gdb also uses the disassembler, so it would be a good idea to
> see how your ideas fit in with gdb too.

Still don't have a NetBSD installation, but I'll post this patch to the
NetBSD-VAX in a minute, too.

Thanks, JBG

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Decode function entry mask on VAXen
  2005-03-08 20:30   ` Jan-Benedict Glaw
@ 2005-03-09  0:45     ` Alan Modra
  2005-03-09  9:46       ` Jan-Benedict Glaw
  0 siblings, 1 reply; 7+ messages in thread
From: Alan Modra @ 2005-03-09  0:45 UTC (permalink / raw)
  To: Jan-Benedict Glaw; +Cc: binutils

On Tue, Mar 08, 2005 at 09:30:18PM +0100, Jan-Benedict Glaw wrote:
> On Tue, Mar 08, 2005 at 10:44:00PM +1030, Alan Modra wrote:
> > objdump already breaks up calls to disassemble_bytes into the pieces of
> > a section between two defined symbols (possibly validated by a target
> > symbol_is_valid function).  So if the only symbols in vax code are those
> > at the beginning of a function, your idea of using last_symbol_address
> > will work.  However, I think it would be better to pass
> > "asymbol *last_symbol" instead, which gives your backend disassembler_fn
> > a chance to deal with non-function symbols that might appear in code.
> 
> Here's a new version, which indeed works even better than the previous
> version (correctly, there's no entry mask decoded for hand-crafted
> assembler parts that we jump to). Could you please also comment on this?

Supply a changelog entry, and it's good to commit with a few minor
changes.

> +#define FORCE_DISASSEMBLE	0x40000000	/* Force disassembly of the
> +						   address, even if it was
> +						   probably better handled in
> +						   a different way  */

I would just comment this as "/* --disassemble-all given.  */"

> +  /* Decode function entry mask.  */
> +  if (info->last_symbol
> +		  && (info->last_symbol->flags & BSF_FUNCTION)
> +		  && !(info->flags & FORCE_DISASSEMBLE)
> +		  && memaddr == bfd_asymbol_value (info->last_symbol))

Formatting.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Decode function entry mask on VAXen
  2005-03-09  0:45     ` Alan Modra
@ 2005-03-09  9:46       ` Jan-Benedict Glaw
  2005-03-09 13:20         ` Alan Modra
  0 siblings, 1 reply; 7+ messages in thread
From: Jan-Benedict Glaw @ 2005-03-09  9:46 UTC (permalink / raw)
  To: binutils; +Cc: Alan Modra

On Wed, Mar 09, 2005 at 11:15:06AM +1030, Alan Modra wrote:
> On Tue, Mar 08, 2005 at 09:30:18PM +0100, Jan-Benedict Glaw wrote:

> Supply a changelog entry, and it's good to commit with a few minor
> changes.

I've done another change to it. The whole last_symbol stuff isn't
needed at all, because objdump nicely fills disassemble_info->symbols,
which can be used instead. I've also dropped the FORCE_DISASSEMBLE
flag, which isn't needed either, because I now let it check for
BSF_FUNCTION symbols. Here's the changelog:

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

	* opcodes/vax-dis.c: Update copyright
	(entry_mask_bit): New array containing descriptions for entry
	mask bits.
	(print_insn_vax): Decode function entry mask.

This is my current patch:

diff -Nurp ../cvs-repos/binutils/binutils-upstream-HEAD/opcodes/vax-dis.c src/opcodes/vax-dis.c
--- ../cvs-repos/binutils/binutils-upstream-HEAD/opcodes/vax-dis.c	2002-05-10 01:11:30.000000000 +0200
+++ src/opcodes/vax-dis.c	2005-03-09 09:35:42.000000000 +0100
@@ -1,5 +1,5 @@
 /* Print VAX instructions.
-   Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright 1995, 1998, 2000-2002, 2005 Free Software Foundation, Inc.
    Contributed by Pauline Middelink <middelin@polyware.iaf.nl>
 
 This program is free software; you can redistribute it and/or modify
@@ -34,6 +34,21 @@ static char *reg_names[] =
   "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc"
 };
 
+/* Definitions for the function entry mask bits.  */
+static char *entry_mask_bit[] =
+{
+  /* Registers 0 and 1 shall not be saved, since they're used to pass back
+     a function's result to it's caller...  */
+  "~r0~", "~r1~",
+  /* Registers 2 .. 11 are normal registers.  */
+  "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+  /* Registers 12 and 13 are argument and frame pointer and must not
+     be saved by using the entry mask.  */
+  "~ap~", "~fp~",
+  /* Bits 14 and 15 control integer and decimal overflow.  */
+  "IntOvfl", "DecOvfl",
+};
+
 /* Sign-extend an (unsigned char). */
 #if __STDC__ == 1
 #define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
@@ -140,6 +155,28 @@ print_insn_vax (memaddr, info)
       buffer[1] = 0;
     }
 
+  /* Decode function entry mask.  */
+  if (info->num_symbols
+      && 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];
+
+      (*info->fprintf_func) (info->stream, "Entry mask 0x%04x = <",
+			     register_mask);
+
+      for (i = 15; i >= 0; i--)
+	if (register_mask & (1 << i))
+          (*info->fprintf_func) (info->stream, " %s", entry_mask_bit[i]);
+
+      (*info->fprintf_func) (info->stream, " >");
+
+      return 2;
+    }
+
   for (votp = &votstrs[0]; votp->name[0]; votp++)
     {
       register vax_opcodeT opcode = votp->detail.code;


Thanks, JBG

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Decode function entry mask on VAXen
  2005-03-09  9:46       ` Jan-Benedict Glaw
@ 2005-03-09 13:20         ` Alan Modra
  0 siblings, 0 replies; 7+ messages in thread
From: Alan Modra @ 2005-03-09 13:20 UTC (permalink / raw)
  To: Jan-Benedict Glaw; +Cc: binutils

On Wed, Mar 09, 2005 at 10:46:27AM +0100, Jan-Benedict Glaw wrote:
> I've done another change to it. The whole last_symbol stuff isn't
> needed at all, because objdump nicely fills disassemble_info->symbols,
> which can be used instead. I've also dropped the FORCE_DISASSEMBLE
> flag, which isn't needed either, because I now let it check for
> BSF_FUNCTION symbols. Here's the changelog:

Even better.  I've applied this mainline and branch, with a couple of
minor changes.

> -   Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
> +   Copyright 1995, 1998, 2000-2002, 2005 Free Software Foundation, Inc.

We don't use year ranges.

> +  if (info->num_symbols
> +      && info->symbols

I reckon the num_symbols test is redundant, so I removed it.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-03-09 13:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-08  2:14 Decode function entry mask on VAXen Jan-Benedict Glaw
2005-03-08 12:14 ` Alan Modra
2005-03-08 12:25   ` Jan-Benedict Glaw
2005-03-08 20:30   ` Jan-Benedict Glaw
2005-03-09  0:45     ` Alan Modra
2005-03-09  9:46       ` Jan-Benedict Glaw
2005-03-09 13:20         ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).