http://sourceware.org/ml/gdb-patches/2010-12/msg00299.html
[external/binutils.git] / gdb / disasm.c
1 /* Disassemble support for GDB.
2
3    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
4    2011 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "target.h"
23 #include "value.h"
24 #include "ui-out.h"
25 #include "gdb_string.h"
26 #include "disasm.h"
27 #include "gdbcore.h"
28 #include "dis-asm.h"
29
30 /* Disassemble functions.
31    FIXME: We should get rid of all the duplicate code in gdb that does
32    the same thing: disassemble_command() and the gdbtk variation.  */
33
34 /* This Structure is used to store line number information.
35    We need a different sort of line table from the normal one cuz we can't
36    depend upon implicit line-end pc's for lines to do the
37    reordering in this function.  */
38
39 struct dis_line_entry
40 {
41   int line;
42   CORE_ADDR start_pc;
43   CORE_ADDR end_pc;
44 };
45
46 /* Like target_read_memory, but slightly different parameters.  */
47 static int
48 dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
49                      struct disassemble_info *info)
50 {
51   return target_read_memory (memaddr, myaddr, len);
52 }
53
54 /* Like memory_error with slightly different parameters.  */
55 static void
56 dis_asm_memory_error (int status, bfd_vma memaddr,
57                       struct disassemble_info *info)
58 {
59   memory_error (status, memaddr);
60 }
61
62 /* Like print_address with slightly different parameters.  */
63 static void
64 dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
65 {
66   struct gdbarch *gdbarch = info->application_data;
67
68   print_address (gdbarch, addr, info->stream);
69 }
70
71 static int
72 compare_lines (const void *mle1p, const void *mle2p)
73 {
74   struct dis_line_entry *mle1, *mle2;
75   int val;
76
77   mle1 = (struct dis_line_entry *) mle1p;
78   mle2 = (struct dis_line_entry *) mle2p;
79
80   val = mle1->line - mle2->line;
81
82   if (val != 0)
83     return val;
84
85   return mle1->start_pc - mle2->start_pc;
86 }
87
88 static int
89 dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
90             struct disassemble_info * di,
91             CORE_ADDR low, CORE_ADDR high,
92             int how_many, int flags, struct ui_stream *stb)
93 {
94   int num_displayed = 0;
95   CORE_ADDR pc;
96
97   /* parts of the symbolic representation of the address */
98   int unmapped;
99   int offset;
100   int line;
101   struct cleanup *ui_out_chain;
102
103   for (pc = low; pc < high;)
104     {
105       char *filename = NULL;
106       char *name = NULL;
107
108       QUIT;
109       if (how_many >= 0)
110         {
111           if (num_displayed >= how_many)
112             break;
113           else
114             num_displayed++;
115         }
116       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
117       ui_out_text (uiout, pc_prefix (pc));
118       ui_out_field_core_addr (uiout, "address", gdbarch, pc);
119
120       if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
121                                    &line, &unmapped))
122         {
123           /* We don't care now about line, filename and
124              unmapped. But we might in the future.  */
125           ui_out_text (uiout, " <");
126           if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
127             ui_out_field_string (uiout, "func-name", name);
128           ui_out_text (uiout, "+");
129           ui_out_field_int (uiout, "offset", offset);
130           ui_out_text (uiout, ">:\t");
131         }
132       else
133         ui_out_text (uiout, ":\t");
134
135       if (filename != NULL)
136         xfree (filename);
137       if (name != NULL)
138         xfree (name);
139
140       ui_file_rewind (stb->stream);
141       if (flags & DISASSEMBLY_RAW_INSN)
142         {
143           CORE_ADDR old_pc = pc;
144           bfd_byte data;
145           int status;
146           const char *spacer = "";
147
148           /* Build the opcodes using a temporary stream so we can
149              write them out in a single go for the MI.  */
150           struct ui_stream *opcode_stream = ui_out_stream_new (uiout);
151           struct cleanup *cleanups =
152             make_cleanup_ui_out_stream_delete (opcode_stream);
153
154           pc += gdbarch_print_insn (gdbarch, pc, di);
155           for (;old_pc < pc; old_pc++)
156             {
157               status = (*di->read_memory_func) (old_pc, &data, 1, di);
158               if (status != 0)
159                 (*di->memory_error_func) (status, old_pc, di);
160               fprintf_filtered (opcode_stream->stream, "%s%02x",
161                                 spacer, (unsigned) data);
162               spacer = " ";
163             }
164           ui_out_field_stream (uiout, "opcodes", opcode_stream);
165           ui_out_text (uiout, "\t");
166
167           do_cleanups (cleanups);
168         }
169       else
170         pc += gdbarch_print_insn (gdbarch, pc, di);
171       ui_out_field_stream (uiout, "inst", stb);
172       ui_file_rewind (stb->stream);
173       do_cleanups (ui_out_chain);
174       ui_out_text (uiout, "\n");
175     }
176   return num_displayed;
177 }
178
179 /* The idea here is to present a source-O-centric view of a
180    function to the user.  This means that things are presented
181    in source order, with (possibly) out of order assembly
182    immediately following.  */
183
184 static void
185 do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
186                               struct disassemble_info *di, int nlines,
187                               struct linetable_entry *le,
188                               CORE_ADDR low, CORE_ADDR high,
189                               struct symtab *symtab,
190                               int how_many, int flags, struct ui_stream *stb)
191 {
192   int newlines = 0;
193   struct dis_line_entry *mle;
194   struct symtab_and_line sal;
195   int i;
196   int out_of_order = 0;
197   int next_line = 0;
198   int num_displayed = 0;
199   struct cleanup *ui_out_chain;
200   struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
201   struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
202
203   mle = (struct dis_line_entry *) alloca (nlines
204                                           * sizeof (struct dis_line_entry));
205
206   /* Copy linetable entries for this function into our data
207      structure, creating end_pc's and setting out_of_order as
208      appropriate.  */
209
210   /* First, skip all the preceding functions.  */
211
212   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
213
214   /* Now, copy all entries before the end of this function.  */
215
216   for (; i < nlines - 1 && le[i].pc < high; i++)
217     {
218       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
219         continue;               /* Ignore duplicates.  */
220
221       /* Skip any end-of-function markers.  */
222       if (le[i].line == 0)
223         continue;
224
225       mle[newlines].line = le[i].line;
226       if (le[i].line > le[i + 1].line)
227         out_of_order = 1;
228       mle[newlines].start_pc = le[i].pc;
229       mle[newlines].end_pc = le[i + 1].pc;
230       newlines++;
231     }
232
233   /* If we're on the last line, and it's part of the function,
234      then we need to get the end pc in a special way.  */
235
236   if (i == nlines - 1 && le[i].pc < high)
237     {
238       mle[newlines].line = le[i].line;
239       mle[newlines].start_pc = le[i].pc;
240       sal = find_pc_line (le[i].pc, 0);
241       mle[newlines].end_pc = sal.end;
242       newlines++;
243     }
244
245   /* Now, sort mle by line #s (and, then by addresses within
246      lines).  */
247
248   if (out_of_order)
249     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
250
251   /* Now, for each line entry, emit the specified lines (unless
252      they have been emitted before), followed by the assembly code
253      for that line.  */
254
255   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
256
257   for (i = 0; i < newlines; i++)
258     {
259       /* Print out everything from next_line to the current line.  */
260       if (mle[i].line >= next_line)
261         {
262           if (next_line != 0)
263             {
264               /* Just one line to print.  */
265               if (next_line == mle[i].line)
266                 {
267                   ui_out_tuple_chain
268                     = make_cleanup_ui_out_tuple_begin_end (uiout,
269                                                            "src_and_asm_line");
270                   print_source_lines (symtab, next_line, mle[i].line + 1, 0);
271                 }
272               else
273                 {
274                   /* Several source lines w/o asm instructions associated.  */
275                   for (; next_line < mle[i].line; next_line++)
276                     {
277                       struct cleanup *ui_out_list_chain_line;
278                       struct cleanup *ui_out_tuple_chain_line;
279                       
280                       ui_out_tuple_chain_line
281                         = make_cleanup_ui_out_tuple_begin_end (uiout,
282                                                                "src_and_asm_line");
283                       print_source_lines (symtab, next_line, next_line + 1,
284                                           0);
285                       ui_out_list_chain_line
286                         = make_cleanup_ui_out_list_begin_end (uiout,
287                                                               "line_asm_insn");
288                       do_cleanups (ui_out_list_chain_line);
289                       do_cleanups (ui_out_tuple_chain_line);
290                     }
291                   /* Print the last line and leave list open for
292                      asm instructions to be added.  */
293                   ui_out_tuple_chain
294                     = make_cleanup_ui_out_tuple_begin_end (uiout,
295                                                            "src_and_asm_line");
296                   print_source_lines (symtab, next_line, mle[i].line + 1, 0);
297                 }
298             }
299           else
300             {
301               ui_out_tuple_chain
302                 = make_cleanup_ui_out_tuple_begin_end (uiout,
303                                                        "src_and_asm_line");
304               print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
305             }
306
307           next_line = mle[i].line + 1;
308           ui_out_list_chain
309             = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
310         }
311
312       num_displayed += dump_insns (gdbarch, uiout, di,
313                                    mle[i].start_pc, mle[i].end_pc,
314                                    how_many, flags, stb);
315
316       /* When we've reached the end of the mle array, or we've seen the last
317          assembly range for this source line, close out the list/tuple.  */
318       if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
319         {
320           do_cleanups (ui_out_list_chain);
321           do_cleanups (ui_out_tuple_chain);
322           ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
323           ui_out_list_chain = make_cleanup (null_cleanup, 0);
324           ui_out_text (uiout, "\n");
325         }
326       if (how_many >= 0 && num_displayed >= how_many)
327         break;
328     }
329   do_cleanups (ui_out_chain);
330 }
331
332
333 static void
334 do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
335                   struct disassemble_info * di,
336                   CORE_ADDR low, CORE_ADDR high,
337                   int how_many, int flags, struct ui_stream *stb)
338 {
339   int num_displayed = 0;
340   struct cleanup *ui_out_chain;
341
342   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
343
344   num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
345                               flags, stb);
346
347   do_cleanups (ui_out_chain);
348 }
349
350 /* Initialize the disassemble info struct ready for the specified
351    stream.  */
352
353 static int ATTRIBUTE_PRINTF (2, 3)
354 fprintf_disasm (void *stream, const char *format, ...)
355 {
356   va_list args;
357
358   va_start (args, format);
359   vfprintf_filtered (stream, format, args);
360   va_end (args);
361   /* Something non -ve.  */
362   return 0;
363 }
364
365 static struct disassemble_info
366 gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
367 {
368   struct disassemble_info di;
369
370   init_disassemble_info (&di, file, fprintf_disasm);
371   di.flavour = bfd_target_unknown_flavour;
372   di.memory_error_func = dis_asm_memory_error;
373   di.print_address_func = dis_asm_print_address;
374   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
375      disassembler had a local optomization here.  By default it would
376      access the executable file, instead of the target memory (there
377      was a growing list of exceptions though).  Unfortunately, the
378      heuristic was flawed.  Commands like "disassemble &variable"
379      didn't work as they relied on the access going to the target.
380      Further, it has been supperseeded by trust-read-only-sections
381      (although that should be superseeded by target_trust..._p()).  */
382   di.read_memory_func = dis_asm_read_memory;
383   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
384   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
385   di.endian = gdbarch_byte_order (gdbarch);
386   di.endian_code = gdbarch_byte_order_for_code (gdbarch);
387   di.application_data = gdbarch;
388   disassemble_init_for_target (&di);
389   return di;
390 }
391
392 void
393 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
394                  char *file_string, int flags, int how_many,
395                  CORE_ADDR low, CORE_ADDR high)
396 {
397   struct ui_stream *stb = ui_out_stream_new (uiout);
398   struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
399   struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream);
400   /* To collect the instruction outputted from opcodes.  */
401   struct symtab *symtab = NULL;
402   struct linetable_entry *le = NULL;
403   int nlines = -1;
404
405   /* Assume symtab is valid for whole PC range.  */
406   symtab = find_pc_symtab (low);
407
408   if (symtab != NULL && symtab->linetable != NULL)
409     {
410       /* Convert the linetable to a bunch of my_line_entry's.  */
411       le = symtab->linetable->item;
412       nlines = symtab->linetable->nitems;
413     }
414
415   if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
416       || symtab == NULL || symtab->linetable == NULL)
417     do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
418
419   else if (flags & DISASSEMBLY_SOURCE)
420     do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
421                                   high, symtab, how_many, flags, stb);
422
423   do_cleanups (cleanups);
424   gdb_flush (gdb_stdout);
425 }
426
427 /* Print the instruction at address MEMADDR in debugged memory,
428    on STREAM.  Returns the length of the instruction, in bytes,
429    and, if requested, the number of branch delay slot instructions.  */
430
431 int
432 gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
433                 struct ui_file *stream, int *branch_delay_insns)
434 {
435   struct disassemble_info di;
436   int length;
437
438   di = gdb_disassemble_info (gdbarch, stream);
439   length = gdbarch_print_insn (gdbarch, memaddr, &di);
440   if (branch_delay_insns)
441     {
442       if (di.insn_info_valid)
443         *branch_delay_insns = di.branch_delay_insns;
444       else
445         *branch_delay_insns = 0;
446     }
447   return length;
448 }
449
450 static void
451 do_ui_file_delete (void *arg)
452 {
453   ui_file_delete (arg);
454 }
455
456 /* Return the length in bytes of the instruction at address MEMADDR in
457    debugged memory.  */
458
459 int
460 gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
461 {
462   static struct ui_file *null_stream = NULL;
463
464   /* Dummy file descriptor for the disassembler.  */
465   if (!null_stream)
466     {
467       null_stream = ui_file_new ();
468       make_final_cleanup (do_ui_file_delete, null_stream);
469     }
470
471   return gdb_print_insn (gdbarch, addr, null_stream, NULL);
472 }
473
474 /* fprintf-function for gdb_buffered_insn_length.  This function is a
475    nop, we don't want to print anything, we just want to compute the
476    length of the insn.  */
477
478 static int ATTRIBUTE_PRINTF (2, 3)
479 gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
480 {
481   return 0;
482 }
483
484 /* Initialize a struct disassemble_info for gdb_buffered_insn_length.  */
485
486 static void
487 gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
488                                    struct disassemble_info *di,
489                                    const gdb_byte *insn, int max_len,
490                                    CORE_ADDR addr)
491 {
492   init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
493
494   /* init_disassemble_info installs buffer_read_memory, etc.
495      so we don't need to do that here.
496      The cast is necessary until disassemble_info is const-ified.  */
497   di->buffer = (gdb_byte *) insn;
498   di->buffer_length = max_len;
499   di->buffer_vma = addr;
500
501   di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
502   di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
503   di->endian = gdbarch_byte_order (gdbarch);
504   di->endian_code = gdbarch_byte_order_for_code (gdbarch);
505
506   disassemble_init_for_target (di);
507 }
508
509 /* Return the length in bytes of INSN.  MAX_LEN is the size of the
510    buffer containing INSN.  */
511
512 int
513 gdb_buffered_insn_length (struct gdbarch *gdbarch,
514                           const gdb_byte *insn, int max_len, CORE_ADDR addr)
515 {
516   struct disassemble_info di;
517
518   gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
519
520   return gdbarch_print_insn (gdbarch, addr, &di);
521 }