2003-01-13 Andrew Cagney <ac131313@redhat.com>
[platform/upstream/binutils.git] / gdb / disasm.c
1 /* Disassemble support for GDB.
2
3    Copyright 2000, 2001, 2002, 2003 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 2 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, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "target.h"
24 #include "value.h"
25 #include "ui-out.h"
26 #include "gdb_string.h"
27
28 #include "disasm.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 /* This variable determines where memory used for disassembly is read from. */
47 int gdb_disassemble_from_exec = -1;
48
49 /* This is the memory_read_func for gdb_disassemble when we are
50    disassembling from the exec file. */
51 static int
52 gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr,
53                          unsigned int len, disassemble_info * info)
54 {
55   extern struct target_ops exec_ops;
56   int res;
57
58   errno = 0;
59   res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops);
60
61   if (res == len)
62     return 0;
63   else if (errno == 0)
64     return EIO;
65   else
66     return errno;
67 }
68
69 static int
70 compare_lines (const void *mle1p, const void *mle2p)
71 {
72   struct dis_line_entry *mle1, *mle2;
73   int val;
74
75   mle1 = (struct dis_line_entry *) mle1p;
76   mle2 = (struct dis_line_entry *) mle2p;
77
78   val = mle1->line - mle2->line;
79
80   if (val != 0)
81     return val;
82
83   return mle1->start_pc - mle2->start_pc;
84 }
85
86 static int
87 dump_insns (struct ui_out *uiout, disassemble_info * di,
88             CORE_ADDR low, CORE_ADDR high,
89             int how_many, struct ui_stream *stb)
90 {
91   int num_displayed = 0;
92   CORE_ADDR pc;
93
94   /* parts of the symbolic representation of the address */
95   int unmapped;
96   char *filename = NULL;
97   char *name = NULL;
98   int offset;
99   int line;
100
101   for (pc = low; pc < high;)
102     {
103       QUIT;
104       if (how_many >= 0)
105         {
106           if (num_displayed >= how_many)
107             break;
108           else
109             num_displayed++;
110         }
111       ui_out_tuple_begin (uiout, NULL);
112       ui_out_field_core_addr (uiout, "address", pc);
113
114       if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
115                                    &line, &unmapped))
116         {
117           /* We don't care now about line, filename and
118              unmapped. But we might in the future. */
119           ui_out_text (uiout, " <");
120           ui_out_field_string (uiout, "func-name", name);
121           ui_out_text (uiout, "+");
122           ui_out_field_int (uiout, "offset", offset);
123           ui_out_text (uiout, ">:\t");
124         }
125       if (filename != NULL)
126         xfree (filename);
127       if (name != NULL)
128         xfree (name);
129
130       ui_file_rewind (stb->stream);
131       pc += TARGET_PRINT_INSN (pc, di);
132       ui_out_field_stream (uiout, "inst", stb);
133       ui_file_rewind (stb->stream);
134       ui_out_tuple_end (uiout);
135       ui_out_text (uiout, "\n");
136     }
137   return num_displayed;
138 }
139
140 /* The idea here is to present a source-O-centric view of a
141    function to the user.  This means that things are presented
142    in source order, with (possibly) out of order assembly
143    immediately following.  */
144 static void
145 do_mixed_source_and_assembly (struct ui_out *uiout,
146                               struct disassemble_info *di, int nlines,
147                               struct linetable_entry *le,
148                               CORE_ADDR low, CORE_ADDR high,
149                               struct symtab *symtab,
150                               int how_many, struct ui_stream *stb)
151 {
152   int newlines = 0;
153   struct dis_line_entry *mle;
154   struct symtab_and_line sal;
155   int i;
156   int out_of_order = 0;
157   int next_line = 0;
158   CORE_ADDR pc;
159   int num_displayed = 0;
160
161   mle = (struct dis_line_entry *) alloca (nlines
162                                           * sizeof (struct dis_line_entry));
163
164   /* Copy linetable entries for this function into our data
165      structure, creating end_pc's and setting out_of_order as
166      appropriate.  */
167
168   /* First, skip all the preceding functions.  */
169
170   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
171
172   /* Now, copy all entries before the end of this function.  */
173
174   for (; i < nlines - 1 && le[i].pc < high; i++)
175     {
176       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
177         continue;               /* Ignore duplicates */
178
179       /* Skip any end-of-function markers.  */
180       if (le[i].line == 0)
181         continue;
182
183       mle[newlines].line = le[i].line;
184       if (le[i].line > le[i + 1].line)
185         out_of_order = 1;
186       mle[newlines].start_pc = le[i].pc;
187       mle[newlines].end_pc = le[i + 1].pc;
188       newlines++;
189     }
190
191   /* If we're on the last line, and it's part of the function,
192      then we need to get the end pc in a special way.  */
193
194   if (i == nlines - 1 && le[i].pc < high)
195     {
196       mle[newlines].line = le[i].line;
197       mle[newlines].start_pc = le[i].pc;
198       sal = find_pc_line (le[i].pc, 0);
199       mle[newlines].end_pc = sal.end;
200       newlines++;
201     }
202
203   /* Now, sort mle by line #s (and, then by addresses within
204      lines). */
205
206   if (out_of_order)
207     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
208
209   /* Now, for each line entry, emit the specified lines (unless
210      they have been emitted before), followed by the assembly code
211      for that line.  */
212
213   ui_out_list_begin (uiout, "asm_insns");
214
215   for (i = 0; i < newlines; i++)
216     {
217       int close_list = 1;
218       /* Print out everything from next_line to the current line.  */
219       if (mle[i].line >= next_line)
220         {
221           if (next_line != 0)
222             {
223               /* Just one line to print. */
224               if (next_line == mle[i].line)
225                 {
226                   ui_out_tuple_begin (uiout, "src_and_asm_line");
227                   print_source_lines (symtab, next_line, mle[i].line + 1, 0);
228                 }
229               else
230                 {
231                   /* Several source lines w/o asm instructions associated. */
232                   for (; next_line < mle[i].line; next_line++)
233                     {
234                       ui_out_tuple_begin (uiout, "src_and_asm_line");
235                       print_source_lines (symtab, next_line, next_line + 1,
236                                           0);
237                       ui_out_list_begin (uiout, "line_asm_insn");
238                       ui_out_list_end (uiout);
239                       ui_out_tuple_end (uiout);
240                     }
241                   /* Print the last line and leave list open for
242                      asm instructions to be added. */
243                   ui_out_tuple_begin (uiout, "src_and_asm_line");
244                   print_source_lines (symtab, next_line, mle[i].line + 1, 0);
245                 }
246             }
247           else
248             {
249               ui_out_tuple_begin (uiout, "src_and_asm_line");
250               print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
251             }
252
253           next_line = mle[i].line + 1;
254           ui_out_list_begin (uiout, "line_asm_insn");
255           /* Don't close the list if the lines are not in order. */
256           if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line)
257             close_list = 0;
258         }
259
260       num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc,
261                                    how_many, stb);
262       if (close_list)
263         {
264           ui_out_list_end (uiout);
265           ui_out_tuple_end (uiout);
266           ui_out_text (uiout, "\n");
267           close_list = 0;
268         }
269       if (how_many >= 0)
270         if (num_displayed >= how_many)
271           break;
272     }
273   ui_out_list_end (uiout);
274 }
275
276
277 static void
278 do_assembly_only (struct ui_out *uiout, disassemble_info * di,
279                   CORE_ADDR low, CORE_ADDR high,
280                   int how_many, struct ui_stream *stb)
281 {
282   int num_displayed = 0;
283
284   ui_out_list_begin (uiout, "asm_insns");
285
286   num_displayed = dump_insns (uiout, di, low, high, how_many, stb);
287
288   ui_out_list_end (uiout);
289 }
290
291 void
292 gdb_disassembly (struct ui_out *uiout,
293                 char *file_string,
294                 int line_num,
295                 int mixed_source_and_assembly,
296                 int how_many, CORE_ADDR low, CORE_ADDR high)
297 {
298   static disassemble_info di;
299   static int di_initialized;
300   /* To collect the instruction outputted from opcodes. */
301   static struct ui_stream *stb = NULL;
302   struct symtab *symtab = NULL;
303   struct linetable_entry *le = NULL;
304   int nlines = -1;
305
306   if (!di_initialized)
307     {
308       /* We don't add a cleanup for this, because the allocation of
309          the stream is done once only for each gdb run, and we need to
310          keep it around until the end. Hopefully there won't be any
311          errors in the init code below, that make this function bail
312          out. */
313       stb = ui_out_stream_new (uiout);
314       INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
315                                      (fprintf_ftype) fprintf_unfiltered);
316       di.flavour = bfd_target_unknown_flavour;
317       di.memory_error_func = dis_asm_memory_error;
318       di.print_address_func = dis_asm_print_address;
319       di_initialized = 1;
320     }
321
322   di.mach = TARGET_PRINT_INSN_INFO->mach;
323   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
324     di.endian = BFD_ENDIAN_BIG;
325   else
326     di.endian = BFD_ENDIAN_LITTLE;
327
328   /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
329      determine whether or not to do disassembly from target memory or from the
330      exec file:
331
332      If we're debugging a local process, read target memory, instead of the
333      exec file.  This makes disassembly of functions in shared libs work
334      correctly.  Also, read target memory if we are debugging native threads.
335
336      Else, we're debugging a remote process, and should disassemble from the
337      exec file for speed.  However, this is no good if the target modifies its
338      code (for relocation, or whatever).  */
339
340   if (gdb_disassemble_from_exec == -1)
341     {
342       if (strcmp (target_shortname, "child") == 0
343           || strcmp (target_shortname, "procfs") == 0
344           || strcmp (target_shortname, "vxprocess") == 0
345           || strstr (target_shortname, "-threads") != NULL)
346         gdb_disassemble_from_exec = 0;  /* It's a child process, read inferior mem */
347       else
348         gdb_disassemble_from_exec = 1;  /* It's remote, read the exec file */
349     }
350
351   if (gdb_disassemble_from_exec)
352     di.read_memory_func = gdb_dis_asm_read_memory;
353   else
354     di.read_memory_func = dis_asm_read_memory;
355
356   /* Assume symtab is valid for whole PC range */
357   symtab = find_pc_symtab (low);
358
359   if (symtab != NULL && symtab->linetable != NULL)
360     {
361       /* Convert the linetable to a bunch of my_line_entry's.  */
362       le = symtab->linetable->item;
363       nlines = symtab->linetable->nitems;
364     }
365
366   if (!mixed_source_and_assembly || nlines <= 0
367       || symtab == NULL || symtab->linetable == NULL)
368     do_assembly_only (uiout, &di, low, high, how_many, stb);
369
370   else if (mixed_source_and_assembly)
371     do_mixed_source_and_assembly (uiout, &di, nlines, le, low,
372                                   high, symtab, how_many, stb);
373
374   gdb_flush (gdb_stdout);
375 }