GDB (API)
/home/stan/gdb/src/gdb/disasm.c
Go to the documentation of this file.
00001 /* Disassemble support for GDB.
00002 
00003    Copyright (C) 2000-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "target.h"
00022 #include "value.h"
00023 #include "ui-out.h"
00024 #include "gdb_string.h"
00025 #include "disasm.h"
00026 #include "gdbcore.h"
00027 #include "dis-asm.h"
00028 
00029 /* Disassemble functions.
00030    FIXME: We should get rid of all the duplicate code in gdb that does
00031    the same thing: disassemble_command() and the gdbtk variation.  */
00032 
00033 /* This Structure is used to store line number information.
00034    We need a different sort of line table from the normal one cuz we can't
00035    depend upon implicit line-end pc's for lines to do the
00036    reordering in this function.  */
00037 
00038 struct dis_line_entry
00039 {
00040   int line;
00041   CORE_ADDR start_pc;
00042   CORE_ADDR end_pc;
00043 };
00044 
00045 /* Like target_read_memory, but slightly different parameters.  */
00046 static int
00047 dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
00048                      struct disassemble_info *info)
00049 {
00050   return target_read_memory (memaddr, myaddr, len);
00051 }
00052 
00053 /* Like memory_error with slightly different parameters.  */
00054 static void
00055 dis_asm_memory_error (int status, bfd_vma memaddr,
00056                       struct disassemble_info *info)
00057 {
00058   memory_error (status, memaddr);
00059 }
00060 
00061 /* Like print_address with slightly different parameters.  */
00062 static void
00063 dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
00064 {
00065   struct gdbarch *gdbarch = info->application_data;
00066 
00067   print_address (gdbarch, addr, info->stream);
00068 }
00069 
00070 static int
00071 compare_lines (const void *mle1p, const void *mle2p)
00072 {
00073   struct dis_line_entry *mle1, *mle2;
00074   int val;
00075 
00076   mle1 = (struct dis_line_entry *) mle1p;
00077   mle2 = (struct dis_line_entry *) mle2p;
00078 
00079   /* End of sequence markers have a line number of 0 but don't want to
00080      be sorted to the head of the list, instead sort by PC.  */
00081   if (mle1->line == 0 || mle2->line == 0)
00082     {
00083       val = mle1->start_pc - mle2->start_pc;
00084       if (val == 0)
00085         val = mle1->line - mle2->line;
00086     }
00087   else
00088     {
00089       val = mle1->line - mle2->line;
00090       if (val == 0)
00091         val = mle1->start_pc - mle2->start_pc;
00092     }
00093   return val;
00094 }
00095 
00096 static int
00097 dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
00098             struct disassemble_info * di,
00099             CORE_ADDR low, CORE_ADDR high,
00100             int how_many, int flags, struct ui_file *stb)
00101 {
00102   int num_displayed = 0;
00103   CORE_ADDR pc;
00104 
00105   /* parts of the symbolic representation of the address */
00106   int unmapped;
00107   int offset;
00108   int line;
00109   struct cleanup *ui_out_chain;
00110 
00111   for (pc = low; pc < high;)
00112     {
00113       char *filename = NULL;
00114       char *name = NULL;
00115 
00116       QUIT;
00117       if (how_many >= 0)
00118         {
00119           if (num_displayed >= how_many)
00120             break;
00121           else
00122             num_displayed++;
00123         }
00124       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
00125 
00126       if ((flags & DISASSEMBLY_OMIT_PC) == 0)
00127         ui_out_text (uiout, pc_prefix (pc));
00128       ui_out_field_core_addr (uiout, "address", gdbarch, pc);
00129 
00130       if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
00131                                    &line, &unmapped))
00132         {
00133           /* We don't care now about line, filename and
00134              unmapped. But we might in the future.  */
00135           ui_out_text (uiout, " <");
00136           if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
00137             ui_out_field_string (uiout, "func-name", name);
00138           ui_out_text (uiout, "+");
00139           ui_out_field_int (uiout, "offset", offset);
00140           ui_out_text (uiout, ">:\t");
00141         }
00142       else
00143         ui_out_text (uiout, ":\t");
00144 
00145       if (filename != NULL)
00146         xfree (filename);
00147       if (name != NULL)
00148         xfree (name);
00149 
00150       ui_file_rewind (stb);
00151       if (flags & DISASSEMBLY_RAW_INSN)
00152         {
00153           CORE_ADDR old_pc = pc;
00154           bfd_byte data;
00155           int status;
00156           const char *spacer = "";
00157 
00158           /* Build the opcodes using a temporary stream so we can
00159              write them out in a single go for the MI.  */
00160           struct ui_file *opcode_stream = mem_fileopen ();
00161           struct cleanup *cleanups =
00162             make_cleanup_ui_file_delete (opcode_stream);
00163 
00164           pc += gdbarch_print_insn (gdbarch, pc, di);
00165           for (;old_pc < pc; old_pc++)
00166             {
00167               status = (*di->read_memory_func) (old_pc, &data, 1, di);
00168               if (status != 0)
00169                 (*di->memory_error_func) (status, old_pc, di);
00170               fprintf_filtered (opcode_stream, "%s%02x",
00171                                 spacer, (unsigned) data);
00172               spacer = " ";
00173             }
00174           ui_out_field_stream (uiout, "opcodes", opcode_stream);
00175           ui_out_text (uiout, "\t");
00176 
00177           do_cleanups (cleanups);
00178         }
00179       else
00180         pc += gdbarch_print_insn (gdbarch, pc, di);
00181       ui_out_field_stream (uiout, "inst", stb);
00182       ui_file_rewind (stb);
00183       do_cleanups (ui_out_chain);
00184       ui_out_text (uiout, "\n");
00185     }
00186   return num_displayed;
00187 }
00188 
00189 /* The idea here is to present a source-O-centric view of a
00190    function to the user.  This means that things are presented
00191    in source order, with (possibly) out of order assembly
00192    immediately following.  */
00193 
00194 static void
00195 do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
00196                               struct disassemble_info *di, int nlines,
00197                               struct linetable_entry *le,
00198                               CORE_ADDR low, CORE_ADDR high,
00199                               struct symtab *symtab,
00200                               int how_many, int flags, struct ui_file *stb)
00201 {
00202   int newlines = 0;
00203   struct dis_line_entry *mle;
00204   struct symtab_and_line sal;
00205   int i;
00206   int out_of_order = 0;
00207   int next_line = 0;
00208   int num_displayed = 0;
00209   enum print_source_lines_flags psl_flags = 0;
00210   struct cleanup *ui_out_chain;
00211   struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
00212   struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
00213 
00214   if (flags & DISASSEMBLY_FILENAME)
00215     psl_flags |= PRINT_SOURCE_LINES_FILENAME;
00216 
00217   mle = (struct dis_line_entry *) alloca (nlines
00218                                           * sizeof (struct dis_line_entry));
00219 
00220   /* Copy linetable entries for this function into our data
00221      structure, creating end_pc's and setting out_of_order as
00222      appropriate.  */
00223 
00224   /* First, skip all the preceding functions.  */
00225 
00226   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
00227 
00228   /* Now, copy all entries before the end of this function.  */
00229 
00230   for (; i < nlines - 1 && le[i].pc < high; i++)
00231     {
00232       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
00233         continue;               /* Ignore duplicates.  */
00234 
00235       /* Skip any end-of-function markers.  */
00236       if (le[i].line == 0)
00237         continue;
00238 
00239       mle[newlines].line = le[i].line;
00240       if (le[i].line > le[i + 1].line)
00241         out_of_order = 1;
00242       mle[newlines].start_pc = le[i].pc;
00243       mle[newlines].end_pc = le[i + 1].pc;
00244       newlines++;
00245     }
00246 
00247   /* If we're on the last line, and it's part of the function,
00248      then we need to get the end pc in a special way.  */
00249 
00250   if (i == nlines - 1 && le[i].pc < high)
00251     {
00252       mle[newlines].line = le[i].line;
00253       mle[newlines].start_pc = le[i].pc;
00254       sal = find_pc_line (le[i].pc, 0);
00255       mle[newlines].end_pc = sal.end;
00256       newlines++;
00257     }
00258 
00259   /* Now, sort mle by line #s (and, then by addresses within
00260      lines).  */
00261 
00262   if (out_of_order)
00263     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
00264 
00265   /* Now, for each line entry, emit the specified lines (unless
00266      they have been emitted before), followed by the assembly code
00267      for that line.  */
00268 
00269   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
00270 
00271   for (i = 0; i < newlines; i++)
00272     {
00273       /* Print out everything from next_line to the current line.  */
00274       if (mle[i].line >= next_line)
00275         {
00276           if (next_line != 0)
00277             {
00278               /* Just one line to print.  */
00279               if (next_line == mle[i].line)
00280                 {
00281                   ui_out_tuple_chain
00282                     = make_cleanup_ui_out_tuple_begin_end (uiout,
00283                                                            "src_and_asm_line");
00284                   print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
00285                 }
00286               else
00287                 {
00288                   /* Several source lines w/o asm instructions associated.  */
00289                   for (; next_line < mle[i].line; next_line++)
00290                     {
00291                       struct cleanup *ui_out_list_chain_line;
00292                       struct cleanup *ui_out_tuple_chain_line;
00293                       
00294                       ui_out_tuple_chain_line
00295                         = make_cleanup_ui_out_tuple_begin_end (uiout,
00296                                                                "src_and_asm_line");
00297                       print_source_lines (symtab, next_line, next_line + 1,
00298                                           psl_flags);
00299                       ui_out_list_chain_line
00300                         = make_cleanup_ui_out_list_begin_end (uiout,
00301                                                               "line_asm_insn");
00302                       do_cleanups (ui_out_list_chain_line);
00303                       do_cleanups (ui_out_tuple_chain_line);
00304                     }
00305                   /* Print the last line and leave list open for
00306                      asm instructions to be added.  */
00307                   ui_out_tuple_chain
00308                     = make_cleanup_ui_out_tuple_begin_end (uiout,
00309                                                            "src_and_asm_line");
00310                   print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
00311                 }
00312             }
00313           else
00314             {
00315               ui_out_tuple_chain
00316                 = make_cleanup_ui_out_tuple_begin_end (uiout,
00317                                                        "src_and_asm_line");
00318               print_source_lines (symtab, mle[i].line, mle[i].line + 1, psl_flags);
00319             }
00320 
00321           next_line = mle[i].line + 1;
00322           ui_out_list_chain
00323             = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
00324         }
00325 
00326       num_displayed += dump_insns (gdbarch, uiout, di,
00327                                    mle[i].start_pc, mle[i].end_pc,
00328                                    how_many, flags, stb);
00329 
00330       /* When we've reached the end of the mle array, or we've seen the last
00331          assembly range for this source line, close out the list/tuple.  */
00332       if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
00333         {
00334           do_cleanups (ui_out_list_chain);
00335           do_cleanups (ui_out_tuple_chain);
00336           ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
00337           ui_out_list_chain = make_cleanup (null_cleanup, 0);
00338           ui_out_text (uiout, "\n");
00339         }
00340       if (how_many >= 0 && num_displayed >= how_many)
00341         break;
00342     }
00343   do_cleanups (ui_out_chain);
00344 }
00345 
00346 
00347 static void
00348 do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
00349                   struct disassemble_info * di,
00350                   CORE_ADDR low, CORE_ADDR high,
00351                   int how_many, int flags, struct ui_file *stb)
00352 {
00353   int num_displayed = 0;
00354   struct cleanup *ui_out_chain;
00355 
00356   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
00357 
00358   num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
00359                               flags, stb);
00360 
00361   do_cleanups (ui_out_chain);
00362 }
00363 
00364 /* Initialize the disassemble info struct ready for the specified
00365    stream.  */
00366 
00367 static int ATTRIBUTE_PRINTF (2, 3)
00368 fprintf_disasm (void *stream, const char *format, ...)
00369 {
00370   va_list args;
00371 
00372   va_start (args, format);
00373   vfprintf_filtered (stream, format, args);
00374   va_end (args);
00375   /* Something non -ve.  */
00376   return 0;
00377 }
00378 
00379 static struct disassemble_info
00380 gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
00381 {
00382   struct disassemble_info di;
00383 
00384   init_disassemble_info (&di, file, fprintf_disasm);
00385   di.flavour = bfd_target_unknown_flavour;
00386   di.memory_error_func = dis_asm_memory_error;
00387   di.print_address_func = dis_asm_print_address;
00388   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
00389      disassembler had a local optomization here.  By default it would
00390      access the executable file, instead of the target memory (there
00391      was a growing list of exceptions though).  Unfortunately, the
00392      heuristic was flawed.  Commands like "disassemble &variable"
00393      didn't work as they relied on the access going to the target.
00394      Further, it has been supperseeded by trust-read-only-sections
00395      (although that should be superseeded by target_trust..._p()).  */
00396   di.read_memory_func = dis_asm_read_memory;
00397   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
00398   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
00399   di.endian = gdbarch_byte_order (gdbarch);
00400   di.endian_code = gdbarch_byte_order_for_code (gdbarch);
00401   di.application_data = gdbarch;
00402   disassemble_init_for_target (&di);
00403   return di;
00404 }
00405 
00406 void
00407 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
00408                  char *file_string, int flags, int how_many,
00409                  CORE_ADDR low, CORE_ADDR high)
00410 {
00411   struct ui_file *stb = mem_fileopen ();
00412   struct cleanup *cleanups = make_cleanup_ui_file_delete (stb);
00413   struct disassemble_info di = gdb_disassemble_info (gdbarch, stb);
00414   /* To collect the instruction outputted from opcodes.  */
00415   struct symtab *symtab = NULL;
00416   struct linetable_entry *le = NULL;
00417   int nlines = -1;
00418 
00419   /* Assume symtab is valid for whole PC range.  */
00420   symtab = find_pc_symtab (low);
00421 
00422   if (symtab != NULL && symtab->linetable != NULL)
00423     {
00424       /* Convert the linetable to a bunch of my_line_entry's.  */
00425       le = symtab->linetable->item;
00426       nlines = symtab->linetable->nitems;
00427     }
00428 
00429   if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
00430       || symtab == NULL || symtab->linetable == NULL)
00431     do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
00432 
00433   else if (flags & DISASSEMBLY_SOURCE)
00434     do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
00435                                   high, symtab, how_many, flags, stb);
00436 
00437   do_cleanups (cleanups);
00438   gdb_flush (gdb_stdout);
00439 }
00440 
00441 /* Print the instruction at address MEMADDR in debugged memory,
00442    on STREAM.  Returns the length of the instruction, in bytes,
00443    and, if requested, the number of branch delay slot instructions.  */
00444 
00445 int
00446 gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
00447                 struct ui_file *stream, int *branch_delay_insns)
00448 {
00449   struct disassemble_info di;
00450   int length;
00451 
00452   di = gdb_disassemble_info (gdbarch, stream);
00453   length = gdbarch_print_insn (gdbarch, memaddr, &di);
00454   if (branch_delay_insns)
00455     {
00456       if (di.insn_info_valid)
00457         *branch_delay_insns = di.branch_delay_insns;
00458       else
00459         *branch_delay_insns = 0;
00460     }
00461   return length;
00462 }
00463 
00464 static void
00465 do_ui_file_delete (void *arg)
00466 {
00467   ui_file_delete (arg);
00468 }
00469 
00470 /* Return the length in bytes of the instruction at address MEMADDR in
00471    debugged memory.  */
00472 
00473 int
00474 gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
00475 {
00476   static struct ui_file *null_stream = NULL;
00477 
00478   /* Dummy file descriptor for the disassembler.  */
00479   if (!null_stream)
00480     {
00481       null_stream = ui_file_new ();
00482       make_final_cleanup (do_ui_file_delete, null_stream);
00483     }
00484 
00485   return gdb_print_insn (gdbarch, addr, null_stream, NULL);
00486 }
00487 
00488 /* fprintf-function for gdb_buffered_insn_length.  This function is a
00489    nop, we don't want to print anything, we just want to compute the
00490    length of the insn.  */
00491 
00492 static int ATTRIBUTE_PRINTF (2, 3)
00493 gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
00494 {
00495   return 0;
00496 }
00497 
00498 /* Initialize a struct disassemble_info for gdb_buffered_insn_length.  */
00499 
00500 static void
00501 gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
00502                                    struct disassemble_info *di,
00503                                    const gdb_byte *insn, int max_len,
00504                                    CORE_ADDR addr)
00505 {
00506   init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
00507 
00508   /* init_disassemble_info installs buffer_read_memory, etc.
00509      so we don't need to do that here.
00510      The cast is necessary until disassemble_info is const-ified.  */
00511   di->buffer = (gdb_byte *) insn;
00512   di->buffer_length = max_len;
00513   di->buffer_vma = addr;
00514 
00515   di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
00516   di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
00517   di->endian = gdbarch_byte_order (gdbarch);
00518   di->endian_code = gdbarch_byte_order_for_code (gdbarch);
00519 
00520   disassemble_init_for_target (di);
00521 }
00522 
00523 /* Return the length in bytes of INSN.  MAX_LEN is the size of the
00524    buffer containing INSN.  */
00525 
00526 int
00527 gdb_buffered_insn_length (struct gdbarch *gdbarch,
00528                           const gdb_byte *insn, int max_len, CORE_ADDR addr)
00529 {
00530   struct disassemble_info di;
00531 
00532   gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
00533 
00534   return gdbarch_print_insn (gdbarch, addr, &di);
00535 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines