2002-04-07 Elena Zannoni <ezannoni@redhat.com>
authorElena Zannoni <ezannoni@kwikemart.cygnus.com>
Mon, 8 Apr 2002 00:38:10 +0000 (00:38 +0000)
committerElena Zannoni <ezannoni@kwikemart.cygnus.com>
Mon, 8 Apr 2002 00:38:10 +0000 (00:38 +0000)
        * mi-cmd-disas.c (dump_insns): New function.
        (do_mixed_source_and_assembly): New function.
        (do_assembly_only): New function.
        (do_disassembly): New function.
        (mi_cmd_disassemble): Rewrite using smaller, more modular
        functions.

gdb/mi/ChangeLog
gdb/mi/mi-cmd-disas.c

index b810a57256c8c4432bfce365d814e74d7ef3c69a..35e6ef6ad556691536bdc270c6fe9207c3b11035 100644 (file)
@@ -1,3 +1,12 @@
+2002-04-07  Elena Zannoni  <ezannoni@redhat.com>
+
+        * mi-cmd-disas.c (dump_insns): New function.
+        (do_mixed_source_and_assembly): New function.
+        (do_assembly_only): New function.
+        (do_disassembly): New function.
+        (mi_cmd_disassemble): Rewrite using smaller, more modular
+        functions.
+
 2002-04-05  Jim Blandy  <jimb@redhat.com>
 
        * mi-cmd-stack.c (list_args_or_locals): Pass new arg to
index 3db8b0022973968e3f73333fe888acb982c1b6ab..7d8815d1ceca89daf143c1194ee3865e154e6cf4 100644 (file)
 #include "mi-getopt.h"
 #include "ui-out.h"
 
-static int gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, unsigned int len,
-                                   disassemble_info * info);
-static int compare_lines (const PTR mle1p, const PTR mle2p);
-
 /* 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. */
@@ -86,6 +82,293 @@ compare_lines (const PTR mle1p, const PTR mle2p)
   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_field_string (uiout, "func-name", name);
+         ui_out_field_int (uiout, "offset", offset);
+       }
+      if (filename != NULL)
+       xfree (filename);
+      if (name != NULL)
+       xfree (name);
+
+      ui_file_rewind (stb->stream);
+      pc += (*tm_print_insn) (pc, di);
+      ui_out_field_stream (uiout, "inst", stb);
+      ui_file_rewind (stb->stream);
+      ui_out_tuple_end (uiout);
+    }
+  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);
+         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:
 
    either:
@@ -106,30 +389,15 @@ compare_lines (const PTR mle1p, const PTR mle2p)
 
    MODE: 0 or 1 for disassembly only, or mixed source and disassembly,
    respectively. */
-
 enum mi_cmd_result
 mi_cmd_disassemble (char *command, char **argv, int argc)
 {
-  CORE_ADDR pc;
+  enum mi_cmd_result retval;
   CORE_ADDR start;
 
   int mixed_source_and_assembly;
-  int num_displayed;
-  static disassemble_info di;
-  static int di_initialized;
-
   struct symtab *s;
 
-  /* To collect the instruction outputted from opcodes. */
-  static struct ui_stream *stb = NULL;
-
-  /* parts of the symbolic representation of the address */
-  int line;
-  int offset;
-  int unmapped;
-  char *filename = NULL;
-  char *name = NULL;
-
   /* Which options have we processed ... */
   int file_seen = 0;
   int line_seen = 0;
@@ -211,6 +479,7 @@ mi_cmd_disassemble (char *command, char **argv, int argc)
   if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1))
     error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.");
 
+
   /* We must get the function beginning and end where line_num is
      contained. */
 
@@ -225,275 +494,11 @@ mi_cmd_disassemble (char *command, char **argv, int argc)
        error ("mi_cmd_disassemble: No function contains specified address");
     }
 
-  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;
-
-  /* If just doing straight assembly, all we need to do is disassemble
-     everything between low and high.  If doing mixed source/assembly,
-     we've got a totally different path to follow.  */
-
-  if (mixed_source_and_assembly)
-    {
-      /* Come here for mixed source/assembly */
-      /* 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.  */
-      struct symtab *symtab;
-      struct linetable_entry *le;
-      int nlines;
-      int newlines;
-      struct dis_line_entry *mle;
-      struct symtab_and_line sal;
-      int i;
-      int out_of_order;
-      int next_line;
-
-      /* Assume symtab is valid for whole PC range */
-      symtab = find_pc_symtab (low);
-
-      if (!symtab || !symtab->linetable)
-       goto assembly_only;
-
-      /* First, convert the linetable to a bunch of my_line_entry's.  */
-
-      le = symtab->linetable->item;
-      nlines = symtab->linetable->nitems;
-
-      if (nlines <= 0)
-       goto assembly_only;
-
-      mle = (struct dis_line_entry *) alloca (nlines * sizeof (struct dis_line_entry));
-
-      out_of_order = 0;
-
-      /* 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.  */
-
-      newlines = 0;
-      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.  */
-
-      next_line = 0;           /* Force out first line */
-      ui_out_list_begin (uiout, "asm_insns");
-      num_displayed = 0;
-      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, mle[i].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");
-             if (i + 1 < newlines && mle[i + 1].line <= mle[i].line)
-               close_list = 0;
-           }
-         for (pc = mle[i].start_pc; pc < mle[i].end_pc;)
-           {
-             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_field_string (uiout, "func-name", name);
-                 ui_out_field_int (uiout, "offset", offset);
-               }
-             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);
-           }
-         if (close_list)
-           {
-             ui_out_list_end (uiout);
-             ui_out_tuple_end (uiout);
-             close_list = 0;
-           }
-         if (how_many >= 0)
-           if (num_displayed >= how_many)
-             break;
-       }
-      ui_out_list_end (uiout);
-    }
-  else
-    {
-    assembly_only:
-      ui_out_list_begin (uiout, "asm_insns");
-      num_displayed = 0;
-      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_field_string (uiout, "func-name", name);
-             ui_out_field_int (uiout, "offset", offset);
-           }
-         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_list_end (uiout);
-    }
-  gdb_flush (gdb_stdout);
-
-  return MI_CMD_DONE;
+   retval = do_disassembly (file_string,
+                           line_num,
+                           mixed_source_and_assembly,
+                           how_many,
+                           low,
+                           high);
+   return retval;
 }