* dwarf2read.c (dwarf2_symbol_mark_computed): Handle corrupted
[platform/upstream/binutils.git] / gdb / disasm.c
1 /* Disassemble support for GDB.
2
3    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
4    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 2 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, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301, USA.  */
22
23 #include "defs.h"
24 #include "target.h"
25 #include "value.h"
26 #include "ui-out.h"
27 #include "gdb_string.h"
28 #include "disasm.h"
29 #include "gdbcore.h"
30 #include "dis-asm.h"
31
32 /* Disassemble functions.
33    FIXME: We should get rid of all the duplicate code in gdb that does
34    the same thing: disassemble_command() and the gdbtk variation. */
35
36 /* This Structure is used to store line number information.
37    We need a different sort of line table from the normal one cuz we can't
38    depend upon implicit line-end pc's for lines to do the
39    reordering in this function.  */
40
41 struct dis_line_entry
42 {
43   int line;
44   CORE_ADDR start_pc;
45   CORE_ADDR end_pc;
46 };
47
48 /* Like target_read_memory, but slightly different parameters.  */
49 static int
50 dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
51                      struct disassemble_info *info)
52 {
53   return target_read_memory (memaddr, myaddr, len);
54 }
55
56 /* Like memory_error with slightly different parameters.  */
57 static void
58 dis_asm_memory_error (int status, bfd_vma memaddr,
59                       struct disassemble_info *info)
60 {
61   memory_error (status, memaddr);
62 }
63
64 /* Like print_address with slightly different parameters.  */
65 static void
66 dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
67 {
68   print_address (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 ui_out *uiout, struct disassemble_info * di,
90             CORE_ADDR low, CORE_ADDR high,
91             int how_many, struct ui_stream *stb)
92 {
93   int num_displayed = 0;
94   CORE_ADDR pc;
95
96   /* parts of the symbolic representation of the address */
97   int unmapped;
98   int offset;
99   int line;
100   struct cleanup *ui_out_chain;
101
102   for (pc = low; pc < high;)
103     {
104       char *filename = NULL;
105       char *name = NULL;
106
107       QUIT;
108       if (how_many >= 0)
109         {
110           if (num_displayed >= how_many)
111             break;
112           else
113             num_displayed++;
114         }
115       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
116       ui_out_field_core_addr (uiout, "address", pc);
117
118       if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
119                                    &line, &unmapped))
120         {
121           /* We don't care now about line, filename and
122              unmapped. But we might in the future. */
123           ui_out_text (uiout, " <");
124           ui_out_field_string (uiout, "func-name", name);
125           ui_out_text (uiout, "+");
126           ui_out_field_int (uiout, "offset", offset);
127           ui_out_text (uiout, ">:\t");
128         }
129       else
130         ui_out_text (uiout, ":\t");
131
132       if (filename != NULL)
133         xfree (filename);
134       if (name != NULL)
135         xfree (name);
136
137       ui_file_rewind (stb->stream);
138       pc += TARGET_PRINT_INSN (pc, di);
139       ui_out_field_stream (uiout, "inst", stb);
140       ui_file_rewind (stb->stream);
141       do_cleanups (ui_out_chain);
142       ui_out_text (uiout, "\n");
143     }
144   return num_displayed;
145 }
146
147 /* The idea here is to present a source-O-centric view of a
148    function to the user.  This means that things are presented
149    in source order, with (possibly) out of order assembly
150    immediately following.  */
151 static void
152 do_mixed_source_and_assembly (struct ui_out *uiout,
153                               struct disassemble_info *di, int nlines,
154                               struct linetable_entry *le,
155                               CORE_ADDR low, CORE_ADDR high,
156                               struct symtab *symtab,
157                               int how_many, struct ui_stream *stb)
158 {
159   int newlines = 0;
160   struct dis_line_entry *mle;
161   struct symtab_and_line sal;
162   int i;
163   int out_of_order = 0;
164   int next_line = 0;
165   CORE_ADDR pc;
166   int num_displayed = 0;
167   struct cleanup *ui_out_chain;
168   struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
169   struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
170
171   mle = (struct dis_line_entry *) alloca (nlines
172                                           * sizeof (struct dis_line_entry));
173
174   /* Copy linetable entries for this function into our data
175      structure, creating end_pc's and setting out_of_order as
176      appropriate.  */
177
178   /* First, skip all the preceding functions.  */
179
180   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
181
182   /* Now, copy all entries before the end of this function.  */
183
184   for (; i < nlines - 1 && le[i].pc < high; i++)
185     {
186       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
187         continue;               /* Ignore duplicates */
188
189       /* Skip any end-of-function markers.  */
190       if (le[i].line == 0)
191         continue;
192
193       mle[newlines].line = le[i].line;
194       if (le[i].line > le[i + 1].line)
195         out_of_order = 1;
196       mle[newlines].start_pc = le[i].pc;
197       mle[newlines].end_pc = le[i + 1].pc;
198       newlines++;
199     }
200
201   /* If we're on the last line, and it's part of the function,
202      then we need to get the end pc in a special way.  */
203
204   if (i == nlines - 1 && le[i].pc < high)
205     {
206       mle[newlines].line = le[i].line;
207       mle[newlines].start_pc = le[i].pc;
208       sal = find_pc_line (le[i].pc, 0);
209       mle[newlines].end_pc = sal.end;
210       newlines++;
211     }
212
213   /* Now, sort mle by line #s (and, then by addresses within
214      lines). */
215
216   if (out_of_order)
217     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
218
219   /* Now, for each line entry, emit the specified lines (unless
220      they have been emitted before), followed by the assembly code
221      for that line.  */
222
223   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
224
225   for (i = 0; i < newlines; i++)
226     {
227       /* Print out everything from next_line to the current line.  */
228       if (mle[i].line >= next_line)
229         {
230           if (next_line != 0)
231             {
232               /* Just one line to print. */
233               if (next_line == mle[i].line)
234                 {
235                   ui_out_tuple_chain
236                     = make_cleanup_ui_out_tuple_begin_end (uiout,
237                                                            "src_and_asm_line");
238                   print_source_lines (symtab, next_line, mle[i].line + 1, 0);
239                 }
240               else
241                 {
242                   /* Several source lines w/o asm instructions associated. */
243                   for (; next_line < mle[i].line; next_line++)
244                     {
245                       struct cleanup *ui_out_list_chain_line;
246                       struct cleanup *ui_out_tuple_chain_line;
247                       
248                       ui_out_tuple_chain_line
249                         = make_cleanup_ui_out_tuple_begin_end (uiout,
250                                                                "src_and_asm_line");
251                       print_source_lines (symtab, next_line, next_line + 1,
252                                           0);
253                       ui_out_list_chain_line
254                         = make_cleanup_ui_out_list_begin_end (uiout,
255                                                               "line_asm_insn");
256                       do_cleanups (ui_out_list_chain_line);
257                       do_cleanups (ui_out_tuple_chain_line);
258                     }
259                   /* Print the last line and leave list open for
260                      asm instructions to be added. */
261                   ui_out_tuple_chain
262                     = make_cleanup_ui_out_tuple_begin_end (uiout,
263                                                            "src_and_asm_line");
264                   print_source_lines (symtab, next_line, mle[i].line + 1, 0);
265                 }
266             }
267           else
268             {
269               ui_out_tuple_chain
270                 = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
271               print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
272             }
273
274           next_line = mle[i].line + 1;
275           ui_out_list_chain
276             = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
277         }
278
279       num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc,
280                                    how_many, stb);
281
282       /* When we've reached the end of the mle array, or we've seen the last
283          assembly range for this source line, close out the list/tuple.  */
284       if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
285         {
286           do_cleanups (ui_out_list_chain);
287           do_cleanups (ui_out_tuple_chain);
288           ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
289           ui_out_list_chain = make_cleanup (null_cleanup, 0);
290           ui_out_text (uiout, "\n");
291         }
292       if (how_many >= 0 && num_displayed >= how_many)
293         break;
294     }
295   do_cleanups (ui_out_chain);
296 }
297
298
299 static void
300 do_assembly_only (struct ui_out *uiout, struct disassemble_info * di,
301                   CORE_ADDR low, CORE_ADDR high,
302                   int how_many, struct ui_stream *stb)
303 {
304   int num_displayed = 0;
305   struct cleanup *ui_out_chain;
306
307   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
308
309   num_displayed = dump_insns (uiout, di, low, high, how_many, stb);
310
311   do_cleanups (ui_out_chain);
312 }
313
314 /* Initialize the disassemble info struct ready for the specified
315    stream.  */
316
317 static int ATTR_FORMAT (printf, 2, 3)
318 fprintf_disasm (void *stream, const char *format, ...)
319 {
320   va_list args;
321   va_start (args, format);
322   vfprintf_filtered (stream, format, args);
323   va_end (args);
324   /* Something non -ve.  */
325   return 0;
326 }
327
328 static struct disassemble_info
329 gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
330 {
331   struct disassemble_info di;
332   init_disassemble_info (&di, file, fprintf_disasm);
333   di.flavour = bfd_target_unknown_flavour;
334   di.memory_error_func = dis_asm_memory_error;
335   di.print_address_func = dis_asm_print_address;
336   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
337      disassembler had a local optomization here.  By default it would
338      access the executable file, instead of the target memory (there
339      was a growing list of exceptions though).  Unfortunately, the
340      heuristic was flawed.  Commands like "disassemble &variable"
341      didn't work as they relied on the access going to the target.
342      Further, it has been supperseeded by trust-read-only-sections
343      (although that should be superseeded by target_trust..._p()).  */
344   di.read_memory_func = dis_asm_read_memory;
345   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
346   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
347   di.endian = gdbarch_byte_order (gdbarch);
348   disassemble_init_for_target (&di);
349   return di;
350 }
351
352 void
353 gdb_disassembly (struct ui_out *uiout,
354                 char *file_string,
355                 int line_num,
356                 int mixed_source_and_assembly,
357                 int how_many, CORE_ADDR low, CORE_ADDR high)
358 {
359   struct ui_stream *stb = ui_out_stream_new (uiout);
360   struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
361   struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stb->stream);
362   /* To collect the instruction outputted from opcodes. */
363   struct symtab *symtab = NULL;
364   struct linetable_entry *le = NULL;
365   int nlines = -1;
366
367   /* Assume symtab is valid for whole PC range */
368   symtab = find_pc_symtab (low);
369
370   if (symtab != NULL && symtab->linetable != NULL)
371     {
372       /* Convert the linetable to a bunch of my_line_entry's.  */
373       le = symtab->linetable->item;
374       nlines = symtab->linetable->nitems;
375     }
376
377   if (!mixed_source_and_assembly || nlines <= 0
378       || symtab == NULL || symtab->linetable == NULL)
379     do_assembly_only (uiout, &di, low, high, how_many, stb);
380
381   else if (mixed_source_and_assembly)
382     do_mixed_source_and_assembly (uiout, &di, nlines, le, low,
383                                   high, symtab, how_many, stb);
384
385   do_cleanups (cleanups);
386   gdb_flush (gdb_stdout);
387 }
388
389 /* Print the instruction at address MEMADDR in debugged memory,
390    on STREAM.  Returns length of the instruction, in bytes.  */
391
392 int
393 gdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream)
394 {
395   struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream);
396   return TARGET_PRINT_INSN (memaddr, &di);
397 }