This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB 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]

RFC/RFA: Move new disassembler to libgdb proper


This is the first step in the disassembler unification.
As Elena mentioned, we want to use a single disassembler code.

Next step is to make the CLI use this one and get rid of the old one in printcmd.c.


2002-09-22 Fernando Nasser <fnasser@redhat.com>

* disasm.c: New file.
* disasm.h: New file.
* mi/mi-cmd-disas.c (gdb_dis_asm_read_memory): Moved to disasm.c.
(compare_lines): Ditto.
(dump_insns): Ditto.
(do_mixed_source_and_assembly): Ditto.
(do_assembly_only): Ditto.
(do_disassembly): Renamed to gdb_disassembly and moved to disasm.c.
* Makefile.in: Add new files. Reorder SFILES list. Update dependencies. Include libgdb.a later in the insight executable.



--
Fernando Nasser
Red Hat Canada Ltd. E-Mail: fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario M4P 2C9
Index: mi/mi-cmd-disas.c
===================================================================
RCS file: /cvs/src/src/gdb/mi/mi-cmd-disas.c,v
retrieving revision 1.19
diff -c -p -r1.19 mi-cmd-disas.c
*** mi/mi-cmd-disas.c	26 Sep 2002 18:35:21 -0000	1.19
--- mi/mi-cmd-disas.c	26 Sep 2002 22:37:24 -0000
***************
*** 24,376 ****
  #include "value.h"
  #include "mi-cmds.h"
  #include "mi-getopt.h"
- #include "ui-out.h"
  #include "gdb_string.h"
! 
! /* Disassemble functions. FIXME: these do not really belong here. We
!    should get rid of all the duplicate code in gdb that does the same
!    thing: disassemble_command() and the gdbtk variation. */
! 
! /* This Structure is used in mi_cmd_disassemble.
!    We need a different sort of line table from the normal one cuz we can't
!    depend upon implicit line-end pc's for lines to do the
!    reordering in this function.  */
! 
! struct dis_line_entry
! {
!   int line;
!   CORE_ADDR start_pc;
!   CORE_ADDR end_pc;
! };
! 
! /* This variable determines where memory used for disassembly is read from. */
! int gdb_disassemble_from_exec = -1;
! 
! /* This is the memory_read_func for gdb_disassemble when we are
!    disassembling from the exec file. */
! static int
! gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr,
! 			 unsigned int len, disassemble_info * info)
! {
!   extern struct target_ops exec_ops;
!   int res;
! 
!   errno = 0;
!   res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops);
! 
!   if (res == len)
!     return 0;
!   else if (errno == 0)
!     return EIO;
!   else
!     return errno;
! }
! 
! static int
! compare_lines (const PTR mle1p, const PTR mle2p)
! {
!   struct dis_line_entry *mle1, *mle2;
!   int val;
! 
!   mle1 = (struct dis_line_entry *) mle1p;
!   mle2 = (struct dis_line_entry *) mle2p;
! 
!   val = mle1->line - mle2->line;
! 
!   if (val != 0)
!     return val;
! 
!   return mle1->start_pc - mle2->start_pc;
! }
! 
! static int
! dump_insns (disassemble_info * di, CORE_ADDR low, CORE_ADDR high,
! 	    int how_many, struct ui_stream *stb)
! {
!   int num_displayed = 0;
!   CORE_ADDR pc;
! 
!   /* parts of the symbolic representation of the address */
!   int unmapped;
!   char *filename = NULL;
!   char *name = NULL;
!   int offset;
!   int line;
! 
!   for (pc = low; pc < high;)
!     {
!       QUIT;
!       if (how_many >= 0)
! 	{
! 	  if (num_displayed >= how_many)
! 	    break;
! 	  else
! 	    num_displayed++;
! 	}
!       ui_out_tuple_begin (uiout, NULL);
!       ui_out_field_core_addr (uiout, "address", pc);
! 
!       if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
! 				   &line, &unmapped))
! 	{
! 	  /* We don't care now about line, filename and
! 	     unmapped. But we might in the future. */
! 	  ui_out_text (uiout, " <");
! 	  ui_out_field_string (uiout, "func-name", name);
! 	  ui_out_text (uiout, "+");
! 	  ui_out_field_int (uiout, "offset", offset);
! 	  ui_out_text (uiout, ">:\t");
! 	}
!       if (filename != NULL)
! 	xfree (filename);
!       if (name != NULL)
! 	xfree (name);
! 
!       ui_file_rewind (stb->stream);
!       pc += TARGET_PRINT_INSN (pc, di);
!       ui_out_field_stream (uiout, "inst", stb);
!       ui_file_rewind (stb->stream);
!       ui_out_tuple_end (uiout);
!       ui_out_text (uiout, "\n");
!     }
!   return num_displayed;
! }
! 
! /* The idea here is to present a source-O-centric view of a
!    function to the user.  This means that things are presented
!    in source order, with (possibly) out of order assembly
!    immediately following.  */
! static void
! do_mixed_source_and_assembly (struct disassemble_info *di, int nlines,
! 			      struct linetable_entry *le,
! 			      CORE_ADDR low, CORE_ADDR high,
! 			      struct symtab *symtab,
! 			      int how_many, struct ui_stream *stb)
! {
!   int newlines = 0;
!   struct dis_line_entry *mle;
!   struct symtab_and_line sal;
!   int i;
!   int out_of_order = 0;
!   int next_line = 0;
!   CORE_ADDR pc;
!   int num_displayed = 0;
! 
!   mle = (struct dis_line_entry *) alloca (nlines
! 					  * sizeof (struct dis_line_entry));
! 
!   /* Copy linetable entries for this function into our data
!      structure, creating end_pc's and setting out_of_order as
!      appropriate.  */
! 
!   /* First, skip all the preceding functions.  */
! 
!   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
! 
!   /* Now, copy all entries before the end of this function.  */
! 
!   for (; i < nlines - 1 && le[i].pc < high; i++)
!     {
!       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
! 	continue;		/* Ignore duplicates */
! 
!       /* Skip any end-of-function markers.  */
!       if (le[i].line == 0)
! 	continue;
! 
!       mle[newlines].line = le[i].line;
!       if (le[i].line > le[i + 1].line)
! 	out_of_order = 1;
!       mle[newlines].start_pc = le[i].pc;
!       mle[newlines].end_pc = le[i + 1].pc;
!       newlines++;
!     }
! 
!   /* If we're on the last line, and it's part of the function,
!      then we need to get the end pc in a special way.  */
! 
!   if (i == nlines - 1 && le[i].pc < high)
!     {
!       mle[newlines].line = le[i].line;
!       mle[newlines].start_pc = le[i].pc;
!       sal = find_pc_line (le[i].pc, 0);
!       mle[newlines].end_pc = sal.end;
!       newlines++;
!     }
! 
!   /* Now, sort mle by line #s (and, then by addresses within
!      lines). */
! 
!   if (out_of_order)
!     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
! 
!   /* Now, for each line entry, emit the specified lines (unless
!      they have been emitted before), followed by the assembly code
!      for that line.  */
! 
!   ui_out_list_begin (uiout, "asm_insns");
! 
!   for (i = 0; i < newlines; i++)
!     {
!       int close_list = 1;
!       /* Print out everything from next_line to the current line.  */
!       if (mle[i].line >= next_line)
! 	{
! 	  if (next_line != 0)
! 	    {
! 	      /* Just one line to print. */
! 	      if (next_line == mle[i].line)
! 		{
! 		  ui_out_tuple_begin (uiout, "src_and_asm_line");
! 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
! 		}
! 	      else
! 		{
! 		  /* Several source lines w/o asm instructions associated. */
! 		  for (; next_line < mle[i].line; next_line++)
! 		    {
! 		      ui_out_tuple_begin (uiout, "src_and_asm_line");
! 		      print_source_lines (symtab, next_line, next_line + 1,
! 					  0);
! 		      ui_out_list_begin (uiout, "line_asm_insn");
! 		      ui_out_list_end (uiout);
! 		      ui_out_tuple_end (uiout);
! 		    }
! 		  /* Print the last line and leave list open for
! 		     asm instructions to be added. */
! 		  ui_out_tuple_begin (uiout, "src_and_asm_line");
! 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
! 		}
! 	    }
! 	  else
! 	    {
! 	      ui_out_tuple_begin (uiout, "src_and_asm_line");
! 	      print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
! 	    }
! 
! 	  next_line = mle[i].line + 1;
! 	  ui_out_list_begin (uiout, "line_asm_insn");
! 	  /* Don't close the list if the lines are not in order. */
! 	  if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line)
! 	    close_list = 0;
! 	}
! 
!       num_displayed += dump_insns (di, mle[i].start_pc, mle[i].end_pc,
! 				   how_many, stb);
!       if (close_list)
! 	{
! 	  ui_out_list_end (uiout);
! 	  ui_out_tuple_end (uiout);
! 	  ui_out_text (uiout, "\n");
! 	  close_list = 0;
! 	}
!       if (how_many >= 0)
! 	if (num_displayed >= how_many)
! 	  break;
!     }
!   ui_out_list_end (uiout);
! }
! 
! 
! static void
! do_assembly_only (disassemble_info * di, CORE_ADDR low,
! 		  CORE_ADDR high, int how_many, struct ui_stream *stb)
! {
!   int num_displayed = 0;
! 
!   ui_out_list_begin (uiout, "asm_insns");
! 
!   num_displayed = dump_insns (di, low, high, how_many, stb);
! 
!   ui_out_list_end (uiout);
! }
! 
! enum mi_cmd_result
! do_disassembly (char *file_string,
! 		int line_num,
! 		int mixed_source_and_assembly,
! 		int how_many, CORE_ADDR low, CORE_ADDR high)
! {
!   static disassemble_info di;
!   static int di_initialized;
!   /* To collect the instruction outputted from opcodes. */
!   static struct ui_stream *stb = NULL;
!   struct symtab *symtab = NULL;
!   struct linetable_entry *le = NULL;
!   int nlines = -1;
! 
!   if (!di_initialized)
!     {
!       /* We don't add a cleanup for this, because the allocation of
!          the stream is done once only for each gdb run, and we need to
!          keep it around until the end. Hopefully there won't be any
!          errors in the init code below, that make this function bail
!          out. */
!       stb = ui_out_stream_new (uiout);
!       INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
! 				     (fprintf_ftype) fprintf_unfiltered);
!       di.flavour = bfd_target_unknown_flavour;
!       di.memory_error_func = dis_asm_memory_error;
!       di.print_address_func = dis_asm_print_address;
!       di_initialized = 1;
!     }
! 
!   di.mach = TARGET_PRINT_INSN_INFO->mach;
!   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
!     di.endian = BFD_ENDIAN_BIG;
!   else
!     di.endian = BFD_ENDIAN_LITTLE;
! 
!   /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
!      determine whether or not to do disassembly from target memory or from the
!      exec file:
! 
!      If we're debugging a local process, read target memory, instead of the
!      exec file.  This makes disassembly of functions in shared libs work
!      correctly.  Also, read target memory if we are debugging native threads.
! 
!      Else, we're debugging a remote process, and should disassemble from the
!      exec file for speed.  However, this is no good if the target modifies its
!      code (for relocation, or whatever).  */
! 
!   if (gdb_disassemble_from_exec == -1)
!     {
!       if (strcmp (target_shortname, "child") == 0
! 	  || strcmp (target_shortname, "procfs") == 0
! 	  || strcmp (target_shortname, "vxprocess") == 0
! 	  || strstr (target_shortname, "-threads") != NULL)
! 	gdb_disassemble_from_exec = 0;	/* It's a child process, read inferior mem */
!       else
! 	gdb_disassemble_from_exec = 1;	/* It's remote, read the exec file */
!     }
! 
!   if (gdb_disassemble_from_exec)
!     di.read_memory_func = gdb_dis_asm_read_memory;
!   else
!     di.read_memory_func = dis_asm_read_memory;
! 
!   /* Assume symtab is valid for whole PC range */
!   symtab = find_pc_symtab (low);
! 
!   if (symtab != NULL && symtab->linetable != NULL)
!     {
!       /* Convert the linetable to a bunch of my_line_entry's.  */
!       le = symtab->linetable->item;
!       nlines = symtab->linetable->nitems;
!     }
! 
!   if (!mixed_source_and_assembly || nlines <= 0
!       || symtab == NULL || symtab->linetable == NULL)
!     do_assembly_only (&di, low, high, how_many, stb);
! 
!   else if (mixed_source_and_assembly)
!     do_mixed_source_and_assembly (&di, nlines, le, low,
! 				  high, symtab, how_many, stb);
! 
!   gdb_flush (gdb_stdout);
! 
!   return MI_CMD_DONE;
! }
  
  /* The arguments to be passed on the command line and parsed here are:
  
--- 24,31 ----
  #include "value.h"
  #include "mi-cmds.h"
  #include "mi-getopt.h"
  #include "gdb_string.h"
! #include "disasm.h"
  
  /* The arguments to be passed on the command line and parsed here are:
  
*************** mi_cmd_disassemble (char *command, char 
*** 498,505 ****
  	error ("mi_cmd_disassemble: No function contains specified address");
      }
  
!   retval = do_disassembly (file_string,
! 			   line_num,
! 			   mixed_source_and_assembly, how_many, low, high);
!   return retval;
  }
--- 153,161 ----
  	error ("mi_cmd_disassemble: No function contains specified address");
      }
  
!   gdb_disassembly (file_string,
! 		   line_num,
! 		   mixed_source_and_assembly, how_many, low, high);
! 
!   return MI_CMD_DONE;
  }
Index: disasm.c
===================================================================
RCS file: disasm.c
diff -N disasm.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- disasm.c	26 Sep 2002 22:52:16 -0000
***************
*** 0 ****
--- 1,371 ----
+ /* Disassemble support for GDB.
+    Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+    Contributed by Cygnus Solutions (a Red Hat company).
+ 
+    This file is part of GDB.
+ 
+    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.  */
+ 
+ #include "defs.h"
+ #include "target.h"
+ #include "value.h"
+ #include "ui-out.h"
+ #include "gdb_string.h"
+ 
+ #include "disasm.h"
+ 
+ /* Disassemble functions.
+    FIXME: We should get rid of all the duplicate code in gdb that does
+    the same thing: disassemble_command() and the gdbtk variation. */
+ 
+ /* This Structure is used to store line number information.
+    We need a different sort of line table from the normal one cuz we can't
+    depend upon implicit line-end pc's for lines to do the
+    reordering in this function.  */
+ 
+ struct dis_line_entry
+ {
+   int line;
+   CORE_ADDR start_pc;
+   CORE_ADDR end_pc;
+ };
+ 
+ /* This variable determines where memory used for disassembly is read from. */
+ int gdb_disassemble_from_exec = -1;
+ 
+ /* This is the memory_read_func for gdb_disassemble when we are
+    disassembling from the exec file. */
+ static int
+ gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr,
+ 			 unsigned int len, disassemble_info * info)
+ {
+   extern struct target_ops exec_ops;
+   int res;
+ 
+   errno = 0;
+   res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops);
+ 
+   if (res == len)
+     return 0;
+   else if (errno == 0)
+     return EIO;
+   else
+     return errno;
+ }
+ 
+ static int
+ compare_lines (const PTR mle1p, const PTR mle2p)
+ {
+   struct dis_line_entry *mle1, *mle2;
+   int val;
+ 
+   mle1 = (struct dis_line_entry *) mle1p;
+   mle2 = (struct dis_line_entry *) mle2p;
+ 
+   val = mle1->line - mle2->line;
+ 
+   if (val != 0)
+     return val;
+ 
+   return mle1->start_pc - mle2->start_pc;
+ }
+ 
+ static int
+ dump_insns (disassemble_info * di, CORE_ADDR low, CORE_ADDR high,
+ 	    int how_many, struct ui_stream *stb)
+ {
+   int num_displayed = 0;
+   CORE_ADDR pc;
+ 
+   /* parts of the symbolic representation of the address */
+   int unmapped;
+   char *filename = NULL;
+   char *name = NULL;
+   int offset;
+   int line;
+ 
+   for (pc = low; pc < high;)
+     {
+       QUIT;
+       if (how_many >= 0)
+ 	{
+ 	  if (num_displayed >= how_many)
+ 	    break;
+ 	  else
+ 	    num_displayed++;
+ 	}
+       ui_out_tuple_begin (uiout, NULL);
+       ui_out_field_core_addr (uiout, "address", pc);
+ 
+       if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
+ 				   &line, &unmapped))
+ 	{
+ 	  /* We don't care now about line, filename and
+ 	     unmapped. But we might in the future. */
+ 	  ui_out_text (uiout, " <");
+ 	  ui_out_field_string (uiout, "func-name", name);
+ 	  ui_out_text (uiout, "+");
+ 	  ui_out_field_int (uiout, "offset", offset);
+ 	  ui_out_text (uiout, ">:\t");
+ 	}
+       if (filename != NULL)
+ 	xfree (filename);
+       if (name != NULL)
+ 	xfree (name);
+ 
+       ui_file_rewind (stb->stream);
+       pc += TARGET_PRINT_INSN (pc, di);
+       ui_out_field_stream (uiout, "inst", stb);
+       ui_file_rewind (stb->stream);
+       ui_out_tuple_end (uiout);
+       ui_out_text (uiout, "\n");
+     }
+   return num_displayed;
+ }
+ 
+ /* The idea here is to present a source-O-centric view of a
+    function to the user.  This means that things are presented
+    in source order, with (possibly) out of order assembly
+    immediately following.  */
+ static void
+ do_mixed_source_and_assembly (struct disassemble_info *di, int nlines,
+ 			      struct linetable_entry *le,
+ 			      CORE_ADDR low, CORE_ADDR high,
+ 			      struct symtab *symtab,
+ 			      int how_many, struct ui_stream *stb)
+ {
+   int newlines = 0;
+   struct dis_line_entry *mle;
+   struct symtab_and_line sal;
+   int i;
+   int out_of_order = 0;
+   int next_line = 0;
+   CORE_ADDR pc;
+   int num_displayed = 0;
+ 
+   mle = (struct dis_line_entry *) alloca (nlines
+ 					  * sizeof (struct dis_line_entry));
+ 
+   /* Copy linetable entries for this function into our data
+      structure, creating end_pc's and setting out_of_order as
+      appropriate.  */
+ 
+   /* First, skip all the preceding functions.  */
+ 
+   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
+ 
+   /* Now, copy all entries before the end of this function.  */
+ 
+   for (; i < nlines - 1 && le[i].pc < high; i++)
+     {
+       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
+ 	continue;		/* Ignore duplicates */
+ 
+       /* Skip any end-of-function markers.  */
+       if (le[i].line == 0)
+ 	continue;
+ 
+       mle[newlines].line = le[i].line;
+       if (le[i].line > le[i + 1].line)
+ 	out_of_order = 1;
+       mle[newlines].start_pc = le[i].pc;
+       mle[newlines].end_pc = le[i + 1].pc;
+       newlines++;
+     }
+ 
+   /* If we're on the last line, and it's part of the function,
+      then we need to get the end pc in a special way.  */
+ 
+   if (i == nlines - 1 && le[i].pc < high)
+     {
+       mle[newlines].line = le[i].line;
+       mle[newlines].start_pc = le[i].pc;
+       sal = find_pc_line (le[i].pc, 0);
+       mle[newlines].end_pc = sal.end;
+       newlines++;
+     }
+ 
+   /* Now, sort mle by line #s (and, then by addresses within
+      lines). */
+ 
+   if (out_of_order)
+     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
+ 
+   /* Now, for each line entry, emit the specified lines (unless
+      they have been emitted before), followed by the assembly code
+      for that line.  */
+ 
+   ui_out_list_begin (uiout, "asm_insns");
+ 
+   for (i = 0; i < newlines; i++)
+     {
+       int close_list = 1;
+       /* Print out everything from next_line to the current line.  */
+       if (mle[i].line >= next_line)
+ 	{
+ 	  if (next_line != 0)
+ 	    {
+ 	      /* Just one line to print. */
+ 	      if (next_line == mle[i].line)
+ 		{
+ 		  ui_out_tuple_begin (uiout, "src_and_asm_line");
+ 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
+ 		}
+ 	      else
+ 		{
+ 		  /* Several source lines w/o asm instructions associated. */
+ 		  for (; next_line < mle[i].line; next_line++)
+ 		    {
+ 		      ui_out_tuple_begin (uiout, "src_and_asm_line");
+ 		      print_source_lines (symtab, next_line, next_line + 1,
+ 					  0);
+ 		      ui_out_list_begin (uiout, "line_asm_insn");
+ 		      ui_out_list_end (uiout);
+ 		      ui_out_tuple_end (uiout);
+ 		    }
+ 		  /* Print the last line and leave list open for
+ 		     asm instructions to be added. */
+ 		  ui_out_tuple_begin (uiout, "src_and_asm_line");
+ 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
+ 		}
+ 	    }
+ 	  else
+ 	    {
+ 	      ui_out_tuple_begin (uiout, "src_and_asm_line");
+ 	      print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
+ 	    }
+ 
+ 	  next_line = mle[i].line + 1;
+ 	  ui_out_list_begin (uiout, "line_asm_insn");
+ 	  /* Don't close the list if the lines are not in order. */
+ 	  if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line)
+ 	    close_list = 0;
+ 	}
+ 
+       num_displayed += dump_insns (di, mle[i].start_pc, mle[i].end_pc,
+ 				   how_many, stb);
+       if (close_list)
+ 	{
+ 	  ui_out_list_end (uiout);
+ 	  ui_out_tuple_end (uiout);
+ 	  ui_out_text (uiout, "\n");
+ 	  close_list = 0;
+ 	}
+       if (how_many >= 0)
+ 	if (num_displayed >= how_many)
+ 	  break;
+     }
+   ui_out_list_end (uiout);
+ }
+ 
+ 
+ static void
+ do_assembly_only (disassemble_info * di, CORE_ADDR low,
+ 		  CORE_ADDR high, int how_many, struct ui_stream *stb)
+ {
+   int num_displayed = 0;
+ 
+   ui_out_list_begin (uiout, "asm_insns");
+ 
+   num_displayed = dump_insns (di, low, high, how_many, stb);
+ 
+   ui_out_list_end (uiout);
+ }
+ 
+ void
+ gdb_disassembly (char *file_string,
+ 		int line_num,
+ 		int mixed_source_and_assembly,
+ 		int how_many, CORE_ADDR low, CORE_ADDR high)
+ {
+   static disassemble_info di;
+   static int di_initialized;
+   /* To collect the instruction outputted from opcodes. */
+   static struct ui_stream *stb = NULL;
+   struct symtab *symtab = NULL;
+   struct linetable_entry *le = NULL;
+   int nlines = -1;
+ 
+   if (!di_initialized)
+     {
+       /* We don't add a cleanup for this, because the allocation of
+          the stream is done once only for each gdb run, and we need to
+          keep it around until the end. Hopefully there won't be any
+          errors in the init code below, that make this function bail
+          out. */
+       stb = ui_out_stream_new (uiout);
+       INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
+ 				     (fprintf_ftype) fprintf_unfiltered);
+       di.flavour = bfd_target_unknown_flavour;
+       di.memory_error_func = dis_asm_memory_error;
+       di.print_address_func = dis_asm_print_address;
+       di_initialized = 1;
+     }
+ 
+   di.mach = TARGET_PRINT_INSN_INFO->mach;
+   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+     di.endian = BFD_ENDIAN_BIG;
+   else
+     di.endian = BFD_ENDIAN_LITTLE;
+ 
+   /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
+      determine whether or not to do disassembly from target memory or from the
+      exec file:
+ 
+      If we're debugging a local process, read target memory, instead of the
+      exec file.  This makes disassembly of functions in shared libs work
+      correctly.  Also, read target memory if we are debugging native threads.
+ 
+      Else, we're debugging a remote process, and should disassemble from the
+      exec file for speed.  However, this is no good if the target modifies its
+      code (for relocation, or whatever).  */
+ 
+   if (gdb_disassemble_from_exec == -1)
+     {
+       if (strcmp (target_shortname, "child") == 0
+ 	  || strcmp (target_shortname, "procfs") == 0
+ 	  || strcmp (target_shortname, "vxprocess") == 0
+ 	  || strstr (target_shortname, "-threads") != NULL)
+ 	gdb_disassemble_from_exec = 0;	/* It's a child process, read inferior mem */
+       else
+ 	gdb_disassemble_from_exec = 1;	/* It's remote, read the exec file */
+     }
+ 
+   if (gdb_disassemble_from_exec)
+     di.read_memory_func = gdb_dis_asm_read_memory;
+   else
+     di.read_memory_func = dis_asm_read_memory;
+ 
+   /* Assume symtab is valid for whole PC range */
+   symtab = find_pc_symtab (low);
+ 
+   if (symtab != NULL && symtab->linetable != NULL)
+     {
+       /* Convert the linetable to a bunch of my_line_entry's.  */
+       le = symtab->linetable->item;
+       nlines = symtab->linetable->nitems;
+     }
+ 
+   if (!mixed_source_and_assembly || nlines <= 0
+       || symtab == NULL || symtab->linetable == NULL)
+     do_assembly_only (&di, low, high, how_many, stb);
+ 
+   else if (mixed_source_and_assembly)
+     do_mixed_source_and_assembly (&di, nlines, le, low,
+ 				  high, symtab, how_many, stb);
+ 
+   gdb_flush (gdb_stdout);
+ }
Index: disasm.h
===================================================================
RCS file: disasm.h
diff -N disasm.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- disasm.h	26 Sep 2002 22:52:16 -0000
***************
*** 0 ****
--- 1,25 ----
+ /* Disassemble support for GDB.
+    Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+    Contributed by Cygnus Solutions (a Red Hat company).
+ 
+    This file is part of GDB.
+ 
+    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.  */
+ 
+ extern void gdb_disassembly (char *file_string,
+ 			     int line_num,
+ 			     int mixed_source_and_assembly,
+ 			     int how_many, CORE_ADDR low, CORE_ADDR high);
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.264
diff -c -p -r1.264 Makefile.in
*** Makefile.in	26 Sep 2002 17:46:04 -0000	1.264
--- Makefile.in	26 Sep 2002 22:37:23 -0000
*************** TARGET_FLAGS_TO_PASS = \
*** 530,558 ****
  # SFILES is used in building the distribution archive.
  
  SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
! 	ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \
! 	charset.c \
! 	buildsym.c c-exp.y c-lang.c c-typeprint.c c-valprint.c \
! 	coffread.c \
! 	complaints.c completer.c corefile.c cp-valprint.c dbxread.c \
! 	demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
! 	event-loop.c event-top.c \
! 	expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
! 	findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \
! 	inf-loop.c infcmd.c inflow.c infrun.c language.c \
! 	kod.c kod-cisco.c \
! 	ui-out.c cli-out.c \
! 	varobj.c wrapper.c \
  	jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
! 	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \
! 	memattr.c mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \
! 	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c \
! 	macrotab.c macroexp.c macrocmd.c macroscope.c \
! 	printcmd.c remote.c scm-exp.c scm-lang.c \
! 	scm-valprint.c source.c stabsread.c stack.c symfile.c \
! 	symmisc.c symtab.c linespec.c target.c thread.c top.c tracepoint.c \
! 	typeprint.c utils.c valarith.c valops.c valprint.c values.c \
! 	serial.c ser-unix.c mdebugread.c \
  	tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \
  	tui/tuiData.c tui/tuiData.h tui/tuiDataWin.c tui/tuiDataWin.h \
  	tui/tuiDisassem.c tui/tuiDisassem.h tui/tuiGeneralWin.c \
--- 530,559 ----
  # SFILES is used in building the distribution archive.
  
  SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
! 	ax-general.c ax-gdb.c \
! 	bcache.c blockframe.c breakpoint.c buildsym.c builtin-regs.c \
! 	c-exp.y c-lang.c c-typeprint.c c-valprint.c \
! 	charset.c cli-out.c coffread.c complaints.c completer.c corefile.c \
! 	cp-abi.c cp-support.c cp-valprint.c \
! 	dbxread.c demangle.c disasm.c doublest.c dwarfread.c dwarf2read.c \
! 	elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
! 	f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
! 	gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
! 	hpacc-abi.c \
! 	inf-loop.c infcmd.c inflow.c infrun.c \
  	jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
! 	kod.c kod-cisco.c \
! 	language.c linespec.c \
! 	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
! 	macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
! 	mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c \
! 	nlmread.c \
! 	objfiles.c osabi.c \
! 	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
! 	regcache.c remote.c \
! 	scm-exp.c scm-lang.c scm-valprint.c serial.c ser-unix.c source.c \
! 	stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \
! 	target.c thread.c top.c tracepoint.c typeprint.c \
  	tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \
  	tui/tuiData.c tui/tuiData.h tui/tuiDataWin.c tui/tuiDataWin.h \
  	tui/tuiDisassem.c tui/tuiDisassem.h tui/tuiGeneralWin.c \
*************** SFILES = ada-exp.y ada-lang.c ada-typepr
*** 561,570 ****
  	tui/tuiSource.h tui/tuiSourceWin.c tui/tuiSourceWin.h \
  	tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
  	tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \
! 	ui-file.h ui-file.c \
! 	frame.c doublest.c \
! 	builtin-regs.c std-regs.c \
! 	gnu-v2-abi.c gnu-v3-abi.c hpacc-abi.c cp-abi.c cp-support.c
  
  LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
  
--- 562,570 ----
  	tui/tuiSource.h tui/tuiSourceWin.c tui/tuiSourceWin.h \
  	tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \
  	tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \
! 	ui-out.c utils.c ui-file.h ui-file.c \
! 	valarith.c valops.c valprint.c values.c varobj.c \
! 	wrapper.c
  
  LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
  
*************** dcache_h = dcache.h
*** 637,642 ****
--- 637,643 ----
  defs_h = defs.h $(config_h) $(gdb_locale_h) $(gdb_signals_h) $(ansidecl_h) \
  	$(libiberty_h) $(progress_h) $(bfd_h) $(tui_h) $(ui_file_h) $(xm_h) \
  	$(nm_h) $(tm_h) $(fopen_same_h) $(gdbarch_h) $(arch_utils_h)
+ disasm_h = disasm.h
  doublest_h = doublest.h $(floatformat_h)
  dst_h = dst.h
  dwarf2cfi_h = dwarf2cfi.h
*************** TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_
*** 827,833 ****
  TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
  
  COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
! 	charset.o \
  	source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
  	expprint.o environ.o stack.o thread.o \
--- 828,834 ----
  TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
  
  COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
! 	charset.o disasm.o \
  	source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \
  	expprint.o environ.o stack.o thread.o \
*************** demangle.o: demangle.c $(defs_h) $(comma
*** 1617,1622 ****
--- 1618,1625 ----
  	$(gdb_string_h)
  dink32-rom.o: dink32-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
  	$(serial_h) $(symfile_h) $(inferior_h) $(regcache_h)
+ disasm.o: disasm.c $(defs_h) $(gdb_string_h) $(target_h) $(value_h) \
+ 	$(disasm_h) $(ui_out_h)
  doublest.o: doublest.c $(defs_h) $(doublest_h) $(floatformat_h) \
  	$(gdb_assert_h) $(gdb_string_h) $(gdbtypes_h)
  dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h)
*************** insight$(EXEEXT): gdbtk-main.o main.o li
*** 2373,2379 ****
  		$(CDEPS) $(TDEPLIBS)
  	rm -f insight$(EXEEXT)
  	$(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
! 		-o insight$(EXEEXT) gdbtk-main.o main.o libgdb.a $(CONFIG_OBS)\
  		$(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES)
  
  gdbres.o: $(srcdir)/gdbtk/gdb.rc $(srcdir)/gdbtk/gdbtool.ico
--- 2376,2382 ----
  		$(CDEPS) $(TDEPLIBS)
  	rm -f insight$(EXEEXT)
  	$(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
! 		-o insight$(EXEEXT) gdbtk-main.o main.o $(CONFIG_OBS) libgdb.a \
  		$(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES)
  
  gdbres.o: $(srcdir)/gdbtk/gdb.rc $(srcdir)/gdbtk/gdbtool.ico
*************** mi-cmd-break.o: $(srcdir)/mi/mi-cmd-brea
*** 2468,2474 ****
  	$(mi_getopt_h) $(gdb_events_h) $(gdb_h)
  	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-break.c
  mi-cmd-disas.o: $(srcdir)/mi/mi-cmd-disas.c $(defs_h) $(target_h) $(value_h) \
! 	$(mi_cmds_h) $(mi_getopt_h) $(ui_out_h) $(gdb_string_h)
  	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-disas.c
  mi-cmd-stack.o: $(srcdir)/mi/mi-cmd-stack.c $(defs_h) $(target_h) $(frame_h) \
  	$(value_h) $(mi_cmds_h) $(ui_out_h) $(symtab_h)
--- 2471,2477 ----
  	$(mi_getopt_h) $(gdb_events_h) $(gdb_h)
  	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-break.c
  mi-cmd-disas.o: $(srcdir)/mi/mi-cmd-disas.c $(defs_h) $(target_h) $(value_h) \
! 	$(mi_cmds_h) $(mi_getopt_h) $(ui_out_h) $(gdb_string_h) $(disasm_h)
  	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-disas.c
  mi-cmd-stack.o: $(srcdir)/mi/mi-cmd-stack.c $(defs_h) $(target_h) $(frame_h) \
  	$(value_h) $(mi_cmds_h) $(ui_out_h) $(symtab_h)

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