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