Add VAX specific disassembler option -Mentry: to specify a function entry

address, and add code to test this new option.
This commit is contained in:
Nick Clifton 2005-03-29 16:13:48 +00:00
parent deb04cdb5e
commit ec72cfe589
8 changed files with 240 additions and 10 deletions

View file

@ -1,3 +1,9 @@
2005-03-21 Jan-Benedict Glaw <jbglaw@lug-owl.de>
* doc/binutils.texi: Document new VAX disassembler-specific option
-M entry:0xfooba8.
* NEWS: Mention the new option.
2005-03-29 Anil Paranjpe <anilp1@kpitcummins.com> 2005-03-29 Anil Paranjpe <anilp1@kpitcummins.com>
* MAINTAINERS: Add myself as H8300 maintainer. * MAINTAINERS: Add myself as H8300 maintainer.

View file

@ -1,5 +1,8 @@
-*- text -*- -*- text -*-
* Add "-M entry:<addr>" switch to objdump to specify a function entry address
when disassembling VAX binaries.
* Add "--globalize-symbol <name>" and "--globalize-symbols <filename>" switches * Add "--globalize-symbol <name>" and "--globalize-symbols <filename>" switches
to objcopy to convert local symbols into global symbols. to objcopy to convert local symbols into global symbols.

View file

@ -1793,6 +1793,13 @@ rather than names, for the selected types of registers.
You can list the available values of @var{ABI} and @var{ARCH} using You can list the available values of @var{ABI} and @var{ARCH} using
the @option{--help} option. 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 the the rest
of the function being wrongly disassembled.
@item -p @item -p
@itemx --private-headers @itemx --private-headers
Print information that is specific to the object file format. The exact Print information that is specific to the object file format. The exact

View file

@ -1,3 +1,10 @@
2005-03-29 Jan-Benedict Glaw <jbglaw@lug-owl.de>
* binutils-all/vax: New directory.
* binutils-all/vax/objdump.exp: New script. Test the -Mentry:
switch added to the VAX disassembler.
* binutils-all/vax/entrymask.s: New assembler source file.
2005-03-08 Ben Elliston <bje@au.ibm.com> 2005-03-08 Ben Elliston <bje@au.ibm.com>
* config/default.exp: Remove send_user call for stray output. * config/default.exp: Remove send_user call for stray output.

View file

@ -0,0 +1,11 @@
.text
.global label1
label1:
.word 0x0110
.global label2
.type label2,@function
label2:
.word 0x0224

View file

@ -0,0 +1,82 @@
#
# Copyright 1993, 1994, 1995, 1997, 1999, 2000, 2002, 2005
# Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# This file was written by Jan-Benedict Glaw <jbglaw@lug-owl.de>. It's goal
# is to check the VAX-specific support of the -M entry:0xf00 switch, which
# allows to force function entry masks at given addresses.
#
if ![istarget vax*-*-*] then {
return
}
if {[which $OBJDUMP] == 0} then {
perror "$OBJDUMP does not exist"
return
}
send_user "Version [binutil_version $OBJDUMP]"
if {![binutils_assemble $srcdir/$subdir/entrymask.s tmpdir/entrymask.o]} then {
return
}
if [is_remote host] {
set objfile [remote_download host tmpdir/entrymask.o]
} else {
set objfile tmpdir/entrymask.o
}
#
# First run. We expect the function to be a function and the sole label
# not to produce an entry mask.
#
set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -d $objfile"]
set want1 "\[ \]+0:\[ \]+10 01\[ \]+bsbb 3"
set want2 "\[ \]+2:\[ \]+24 02\[ \]+\\.word 0x0224.\*r9 r5 r2"
if [regexp $want1 $got] then {
pass "entrymask test 1"
} else {
fail "entrymask test 1"
}
if [regexp $want2 $got] then {
pass "entrymask test 2"
} else {
fail "entrymask test 2"
}
#
# Second run. Now, we force the label as a function, so we expect that
# it also produces an entry mask, as any call'able function should.
#
set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -d -M entry:0x0 $objfile"]
set want3 "\[ \]+0:\[ \]+10 01\[ \]+\\.word 0x0110.\*r8 r4"
set want4 "\[ \]+2:\[ \]+24 02\[ \]+\\.word 0x0224.\*r9 r5 r2"
if [regexp $want3 $got] then {
pass "entrymask test 3"
} else {
fail "entrymask test 3"
}
if [regexp $want4 $got] then {
pass "entrymask test 4"
} else {
fail "entrymask test 4"
}

View file

@ -1,3 +1,21 @@
2005-03-21 Jan-Benedict Glaw <jbglaw@lug-owl.de>
Nick Clifton <nickc@redhat.com>
* vax-dis.c: (entry_addr): New varible: An array of user supplied
function entry mask addresses.
(entry_addr_occupied_slots): New variable: The number of occupied
elements in entry_addr.
(entry_addr_total_slots): New variable: The total number of
elements in entry_addr.
(parse_disassembler_options): New function. Fills in the entry_addr
array.
(free_entry_array): New function. Release the memory used by the
entry addr array. Suppressed because there is no way to call it.
(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 parse_disassembler_options and is_function_entry.
2005-03-23 H.J. Lu <hongjiu.lu@intel.com> 2005-03-23 H.J. Lu <hongjiu.lu@intel.com>
* cris-dis.c (print_with_operands): Use ~31L for long instead * cris-dis.c (print_with_operands): Use ~31L for long instead

View file

@ -17,6 +17,8 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <setjmp.h>
#include <string.h>
#include "sysdep.h" #include "sysdep.h"
#include "opcode/vax.h" #include "opcode/vax.h"
#include "dis-asm.h" #include "dis-asm.h"
@ -77,15 +79,13 @@ static char *entry_mask_bit[] =
/* Maximum length of an instruction. */ /* Maximum length of an instruction. */
#define MAXLEN 25 #define MAXLEN 25
#include <setjmp.h>
struct private struct private
{ {
/* Points to first byte not fetched. */ /* Points to first byte not fetched. */
bfd_byte *max_fetched; bfd_byte * max_fetched;
bfd_byte the_buffer[MAXLEN]; bfd_byte the_buffer[MAXLEN];
bfd_vma insn_start; bfd_vma insn_start;
jmp_buf bailout; jmp_buf bailout;
}; };
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
@ -119,6 +119,95 @@ fetch_data (info, addr)
return 1; 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, /* Print the vax instruction at address MEMADDR in debugged memory,
on INFO->STREAM. Returns length of the instruction, in bytes. */ on INFO->STREAM. Returns length of the instruction, in bytes. */
@ -127,6 +216,7 @@ print_insn_vax (memaddr, info)
bfd_vma memaddr; bfd_vma memaddr;
disassemble_info *info; disassemble_info *info;
{ {
static bfd_boolean parsed_disassembler_options = FALSE;
const struct vot *votp; const struct vot *votp;
const char *argp; const char *argp;
unsigned char *arg; unsigned char *arg;
@ -137,6 +227,15 @@ print_insn_vax (memaddr, info)
priv.max_fetched = priv.the_buffer; priv.max_fetched = priv.the_buffer;
priv.insn_start = memaddr; 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) if (setjmp (priv.bailout) != 0)
{ {
/* Error return. */ /* Error return. */
@ -157,10 +256,7 @@ print_insn_vax (memaddr, info)
} }
/* Decode function entry mask. */ /* Decode function entry mask. */
if (info->symbols if (is_function_entry (info, memaddr))
&& info->symbols[0]
&& (info->symbols[0]->flags & BSF_FUNCTION)
&& memaddr == bfd_asymbol_value (info->symbols[0]))
{ {
int i = 0; int i = 0;
int register_mask = buffer[1] << 8 | buffer[0]; int register_mask = buffer[1] << 8 | buffer[0];