* disasm.c: New file.
authorFernando Nasser <fnasser@redhat.com>
Mon, 30 Sep 2002 15:57:26 +0000 (15:57 +0000)
committerFernando Nasser <fnasser@redhat.com>
Mon, 30 Sep 2002 15:57:26 +0000 (15:57 +0000)
* 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): Moved to disasm.c. Added uiout argument. (do_assembly_only): Ditto.
(do_disassembly): Renamed to gdb_disassembly and moved to disasm.c.
Sdded uiout argument.
* Makefile.in: Add new files.  Reorder SFILES list. Update dependencies. Include libgdb.a later in the insight executable.

gdb/ChangeLog
gdb/Makefile.in
gdb/disasm.c [new file with mode: 0644]
gdb/disasm.h [new file with mode: 0644]
gdb/mi/mi-cmd-disas.c

index 7f2565ccf3655236d2b720d7821f9726004a322e..2638d9fd9cc73a491634e393d12a0fd78c4b7012 100644 (file)
@@ -1,3 +1,17 @@
+2002-09-30  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): Moved to disasm.c. Added uiout argument.
+       (do_assembly_only): Ditto.
+       (do_disassembly): Renamed to gdb_disassembly and moved to disasm.c.
+       Sdded uiout argument.
+       * Makefile.in: Add new files.  Reorder SFILES list. Update dependencies.
+       Include libgdb.a later in the insight executable. 
+
 2002-09-29  Andrew Cagney  <ac131313@redhat.com>
 
        * config/djgpp/fnchange.lst: Rename bfd/elf64-alpha.c and
index b56732def5810238e95ef36bd9dbaf76af96e387..66352277b6ca39992bd8eb2bed61c4155a588fd6 100644 (file)
@@ -530,29 +530,30 @@ TARGET_FLAGS_TO_PASS = \
 # 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 \
+       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 \
-       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 \
+       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 \
@@ -561,10 +562,9 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
        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
+       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
 
@@ -637,6 +637,7 @@ dcache_h = dcache.h
 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
@@ -827,7 +828,7 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_NO_SRCDIR) $(ALLDEPFILES) \
 TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
 
 COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \
-       charset.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 \
@@ -1617,6 +1618,8 @@ demangle.o: demangle.c $(defs_h) $(command_h) $(gdbcmd_h) $(demangle_h) \
        $(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)
@@ -2374,7 +2377,7 @@ insight$(EXEEXT): gdbtk-main.o main.o libgdb.a $(CONFIG_OBS) $(ADD_DEPS) \
                $(CDEPS) $(TDEPLIBS)
        rm -f insight$(EXEEXT)
        $(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
-               -o insight$(EXEEXT) gdbtk-main.o main.o libgdb.a $(CONFIG_OBS)\
+               -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
@@ -2469,7 +2472,7 @@ mi-cmd-break.o: $(srcdir)/mi/mi-cmd-break.c $(defs_h) $(mi_cmds_h) \
        $(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)
+       $(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)
diff --git a/gdb/disasm.c b/gdb/disasm.c
new file mode 100644 (file)
index 0000000..8ce9a15
--- /dev/null
@@ -0,0 +1,374 @@
+/* Disassemble support for GDB.
+   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+
+   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 (struct ui_out *uiout, 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 ui_out *uiout,
+                             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 (uiout, 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 (struct ui_out *uiout, 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 (uiout, di, low, high, how_many, stb);
+
+  ui_out_list_end (uiout);
+}
+
+void
+gdb_disassembly (struct ui_out *uiout,
+               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 (uiout, &di, low, high, how_many, stb);
+
+  else if (mixed_source_and_assembly)
+    do_mixed_source_and_assembly (uiout, &di, nlines, le, low,
+                                 high, symtab, how_many, stb);
+
+  gdb_flush (gdb_stdout);
+}
diff --git a/gdb/disasm.h b/gdb/disasm.h
new file mode 100644 (file)
index 0000000..beaaf4a
--- /dev/null
@@ -0,0 +1,29 @@
+/* Disassemble support for GDB.
+   Copyright 2002 Free Software Foundation, Inc.
+
+   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.  */
+
+#ifndef DISASM_H
+#define DISASM_H
+
+extern void gdb_disassembly (struct ui_out *uiout,
+                            char *file_string,
+                            int line_num,
+                            int mixed_source_and_assembly,
+                            int how_many, CORE_ADDR low, CORE_ADDR high);
+#endif
index 85328d7cc17091397462d0e19ef8ac24f1b14113..168ca17166681dcadd7add926158cd95bc5db44a 100644 (file)
 #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;
-}
+#include "ui-out.h"
+#include "disasm.h"
 
 /* The arguments to be passed on the command line and parsed here are:
 
@@ -498,8 +154,10 @@ mi_cmd_disassemble (char *command, char **argv, int argc)
        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;
+  gdb_disassembly (uiout,
+                  file_string,
+                  line_num,
+                  mixed_source_and_assembly, how_many, low, high);
+
+  return MI_CMD_DONE;
 }