2002-04-07 Elena Zannoni <ezannoni@redhat.com>
[deliverable/binutils-gdb.git] / gdb / mi / mi-cmd-disas.c
1 /* MI Command Set - disassemble commands.
2 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions (a Red Hat company).
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 "mi-cmds.h"
26 #include "mi-getopt.h"
27 #include "ui-out.h"
28
29 /* Disassemble functions. FIXME: these do not really belong here. We
30 should get rid of all the duplicate code in gdb that does the same
31 thing: disassemble_command() and the gdbtk variation. */
32
33 /* This Structure is used in mi_cmd_disassemble.
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 /* This variable determines where memory used for disassembly is read from. */
46 int gdb_disassemble_from_exec = -1;
47
48 /* This is the memory_read_func for gdb_disassemble when we are
49 disassembling from the exec file. */
50 static int
51 gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr,
52 unsigned int len, disassemble_info * info)
53 {
54 extern struct target_ops exec_ops;
55 int res;
56
57 errno = 0;
58 res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops);
59
60 if (res == len)
61 return 0;
62 else if (errno == 0)
63 return EIO;
64 else
65 return errno;
66 }
67
68 static int
69 compare_lines (const PTR mle1p, const PTR mle2p)
70 {
71 struct dis_line_entry *mle1, *mle2;
72 int val;
73
74 mle1 = (struct dis_line_entry *) mle1p;
75 mle2 = (struct dis_line_entry *) mle2p;
76
77 val = mle1->line - mle2->line;
78
79 if (val != 0)
80 return val;
81
82 return mle1->start_pc - mle2->start_pc;
83 }
84
85 static int
86 dump_insns (disassemble_info * di, CORE_ADDR low, CORE_ADDR high,
87 int how_many, struct ui_stream *stb)
88 {
89 int num_displayed = 0;
90 CORE_ADDR pc;
91
92 /* parts of the symbolic representation of the address */
93 int unmapped;
94 char *filename = NULL;
95 char *name = NULL;
96 int offset;
97 int line;
98
99 for (pc = low; pc < high;)
100 {
101 QUIT;
102 if (how_many >= 0)
103 {
104 if (num_displayed >= how_many)
105 break;
106 else
107 num_displayed++;
108 }
109 ui_out_tuple_begin (uiout, NULL);
110 ui_out_field_core_addr (uiout, "address", pc);
111
112 if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
113 &line, &unmapped))
114 {
115 /* We don't care now about line, filename and
116 unmapped. But we might in the future. */
117 ui_out_field_string (uiout, "func-name", name);
118 ui_out_field_int (uiout, "offset", offset);
119 }
120 if (filename != NULL)
121 xfree (filename);
122 if (name != NULL)
123 xfree (name);
124
125 ui_file_rewind (stb->stream);
126 pc += (*tm_print_insn) (pc, di);
127 ui_out_field_stream (uiout, "inst", stb);
128 ui_file_rewind (stb->stream);
129 ui_out_tuple_end (uiout);
130 }
131 return num_displayed;
132 }
133
134 /* The idea here is to present a source-O-centric view of a
135 function to the user. This means that things are presented
136 in source order, with (possibly) out of order assembly
137 immediately following. */
138 static void
139 do_mixed_source_and_assembly (struct disassemble_info *di, int nlines,
140 struct linetable_entry *le,
141 CORE_ADDR low, CORE_ADDR high,
142 struct symtab *symtab,
143 int how_many, struct ui_stream *stb)
144 {
145 int newlines = 0;
146 struct dis_line_entry *mle;
147 struct symtab_and_line sal;
148 int i;
149 int out_of_order = 0;
150 int next_line = 0;
151 CORE_ADDR pc;
152 int num_displayed = 0;
153
154 mle = (struct dis_line_entry *) alloca (nlines
155 * sizeof (struct dis_line_entry));
156
157 /* Copy linetable entries for this function into our data
158 structure, creating end_pc's and setting out_of_order as
159 appropriate. */
160
161 /* First, skip all the preceding functions. */
162
163 for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
164
165 /* Now, copy all entries before the end of this function. */
166
167 for (; i < nlines - 1 && le[i].pc < high; i++)
168 {
169 if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
170 continue; /* Ignore duplicates */
171
172 /* Skip any end-of-function markers. */
173 if (le[i].line == 0)
174 continue;
175
176 mle[newlines].line = le[i].line;
177 if (le[i].line > le[i + 1].line)
178 out_of_order = 1;
179 mle[newlines].start_pc = le[i].pc;
180 mle[newlines].end_pc = le[i + 1].pc;
181 newlines++;
182 }
183
184 /* If we're on the last line, and it's part of the function,
185 then we need to get the end pc in a special way. */
186
187 if (i == nlines - 1 && le[i].pc < high)
188 {
189 mle[newlines].line = le[i].line;
190 mle[newlines].start_pc = le[i].pc;
191 sal = find_pc_line (le[i].pc, 0);
192 mle[newlines].end_pc = sal.end;
193 newlines++;
194 }
195
196 /* Now, sort mle by line #s (and, then by addresses within
197 lines). */
198
199 if (out_of_order)
200 qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
201
202 /* Now, for each line entry, emit the specified lines (unless
203 they have been emitted before), followed by the assembly code
204 for that line. */
205
206 ui_out_list_begin (uiout, "asm_insns");
207
208 for (i = 0; i < newlines; i++)
209 {
210 int close_list = 1;
211 /* Print out everything from next_line to the current line. */
212 if (mle[i].line >= next_line)
213 {
214 if (next_line != 0)
215 {
216 /* Just one line to print. */
217 if (next_line == mle[i].line)
218 {
219 ui_out_tuple_begin (uiout, "src_and_asm_line");
220 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
221 }
222 else
223 {
224 /* Several source lines w/o asm instructions associated. */
225 for (; next_line < mle[i].line; next_line++)
226 {
227 ui_out_tuple_begin (uiout, "src_and_asm_line");
228 print_source_lines (symtab, next_line, next_line + 1,
229 0);
230 ui_out_list_begin (uiout, "line_asm_insn");
231 ui_out_list_end (uiout);
232 ui_out_tuple_end (uiout);
233 }
234 /* Print the last line and leave list open for
235 asm instructions to be added. */
236 ui_out_tuple_begin (uiout, "src_and_asm_line");
237 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
238 }
239 }
240 else
241 {
242 ui_out_tuple_begin (uiout, "src_and_asm_line");
243 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
244 }
245
246 next_line = mle[i].line + 1;
247 ui_out_list_begin (uiout, "line_asm_insn");
248 /* Don't close the list if the lines are not in order. */
249 if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line)
250 close_list = 0;
251 }
252
253 num_displayed += dump_insns (di, mle[i].start_pc, mle[i].end_pc,
254 how_many, stb);
255 if (close_list)
256 {
257 ui_out_list_end (uiout);
258 ui_out_tuple_end (uiout);
259 close_list = 0;
260 }
261 if (how_many >= 0)
262 if (num_displayed >= how_many)
263 break;
264 }
265 ui_out_list_end (uiout);
266 }
267
268
269 static void
270 do_assembly_only (disassemble_info * di, CORE_ADDR low,
271 CORE_ADDR high, int how_many, struct ui_stream *stb)
272 {
273 int num_displayed = 0;
274
275 ui_out_list_begin (uiout, "asm_insns");
276
277 num_displayed = dump_insns (di, low, high, how_many, stb);
278
279 ui_out_list_end (uiout);
280 }
281
282 enum mi_cmd_result
283 do_disassembly (char *file_string,
284 int line_num,
285 int mixed_source_and_assembly,
286 int how_many, CORE_ADDR low, CORE_ADDR high)
287 {
288 static disassemble_info di;
289 static int di_initialized;
290 /* To collect the instruction outputted from opcodes. */
291 static struct ui_stream *stb = NULL;
292 struct symtab *symtab = NULL;
293 struct linetable_entry *le = NULL;
294 int nlines = -1;
295
296 if (!di_initialized)
297 {
298 /* We don't add a cleanup for this, because the allocation of
299 the stream is done once only for each gdb run, and we need to
300 keep it around until the end. Hopefully there won't be any
301 errors in the init code below, that make this function bail
302 out. */
303 stb = ui_out_stream_new (uiout);
304 INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
305 (fprintf_ftype) fprintf_unfiltered);
306 di.flavour = bfd_target_unknown_flavour;
307 di.memory_error_func = dis_asm_memory_error;
308 di.print_address_func = dis_asm_print_address;
309 di_initialized = 1;
310 }
311
312 di.mach = TARGET_PRINT_INSN_INFO->mach;
313 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
314 di.endian = BFD_ENDIAN_BIG;
315 else
316 di.endian = BFD_ENDIAN_LITTLE;
317
318 /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
319 determine whether or not to do disassembly from target memory or from the
320 exec file:
321
322 If we're debugging a local process, read target memory, instead of the
323 exec file. This makes disassembly of functions in shared libs work
324 correctly. Also, read target memory if we are debugging native threads.
325
326 Else, we're debugging a remote process, and should disassemble from the
327 exec file for speed. However, this is no good if the target modifies its
328 code (for relocation, or whatever). */
329
330 if (gdb_disassemble_from_exec == -1)
331 {
332 if (strcmp (target_shortname, "child") == 0
333 || strcmp (target_shortname, "procfs") == 0
334 || strcmp (target_shortname, "vxprocess") == 0
335 || strstr (target_shortname, "-threads") != NULL)
336 gdb_disassemble_from_exec = 0; /* It's a child process, read inferior mem */
337 else
338 gdb_disassemble_from_exec = 1; /* It's remote, read the exec file */
339 }
340
341 if (gdb_disassemble_from_exec)
342 di.read_memory_func = gdb_dis_asm_read_memory;
343 else
344 di.read_memory_func = dis_asm_read_memory;
345
346 /* Assume symtab is valid for whole PC range */
347 symtab = find_pc_symtab (low);
348
349 if (symtab != NULL && symtab->linetable != NULL)
350 {
351 /* Convert the linetable to a bunch of my_line_entry's. */
352 le = symtab->linetable->item;
353 nlines = symtab->linetable->nitems;
354 }
355
356 if (!mixed_source_and_assembly || nlines <= 0
357 || symtab == NULL || symtab->linetable == NULL)
358 do_assembly_only (&di, low, high, how_many, stb);
359
360 else if (mixed_source_and_assembly)
361 do_mixed_source_and_assembly (&di, nlines, le, low,
362 high, symtab, how_many, stb);
363
364 gdb_flush (gdb_stdout);
365
366 return MI_CMD_DONE;
367 }
368
369 /* The arguments to be passed on the command line and parsed here are:
370
371 either:
372
373 START-ADDRESS: address to start the disassembly at.
374 END-ADDRESS: address to end the disassembly at.
375
376 or:
377
378 FILENAME: The name of the file where we want disassemble from.
379 LINE: The line around which we want to disassemble. It will
380 disassemble the function that contins that line.
381 HOW_MANY: Number of disassembly lines to display. In mixed mode, it
382 is the number of disassembly lines only, not counting the source
383 lines.
384
385 always required:
386
387 MODE: 0 or 1 for disassembly only, or mixed source and disassembly,
388 respectively. */
389 enum mi_cmd_result
390 mi_cmd_disassemble (char *command, char **argv, int argc)
391 {
392 enum mi_cmd_result retval;
393 CORE_ADDR start;
394
395 int mixed_source_and_assembly;
396 struct symtab *s;
397
398 /* Which options have we processed ... */
399 int file_seen = 0;
400 int line_seen = 0;
401 int num_seen = 0;
402 int start_seen = 0;
403 int end_seen = 0;
404
405 /* ... and their corresponding value. */
406 char *file_string = NULL;
407 int line_num = -1;
408 int how_many = -1;
409 CORE_ADDR low = 0;
410 CORE_ADDR high = 0;
411
412 /* Options processing stuff. */
413 int optind = 0;
414 char *optarg;
415 enum opt
416 {
417 FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT
418 };
419 static struct mi_opt opts[] = {
420 {"f", FILE_OPT, 1},
421 {"l", LINE_OPT, 1},
422 {"n", NUM_OPT, 1},
423 {"s", START_OPT, 1},
424 {"e", END_OPT, 1},
425 0
426 };
427
428 /* Get the options with their arguments. Keep track of what we
429 encountered. */
430 while (1)
431 {
432 int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts,
433 &optind, &optarg);
434 if (opt < 0)
435 break;
436 switch ((enum opt) opt)
437 {
438 case FILE_OPT:
439 file_string = xstrdup (optarg);
440 file_seen = 1;
441 break;
442 case LINE_OPT:
443 line_num = atoi (optarg);
444 line_seen = 1;
445 break;
446 case NUM_OPT:
447 how_many = atoi (optarg);
448 num_seen = 1;
449 break;
450 case START_OPT:
451 low = parse_and_eval_address (optarg);
452 start_seen = 1;
453 break;
454 case END_OPT:
455 high = parse_and_eval_address (optarg);
456 end_seen = 1;
457 break;
458 }
459 }
460 argv += optind;
461 argc -= optind;
462
463 /* Allow only filename + linenum (with how_many which is not
464 required) OR start_addr + and_addr */
465
466 if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen)
467 || (line_seen && file_seen && !num_seen && !start_seen && !end_seen)
468 || (!line_seen && !file_seen && !num_seen && start_seen && end_seen)))
469 error
470 ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode.");
471
472 if (argc != 1)
473 error
474 ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode.");
475
476 mixed_source_and_assembly = atoi (argv[0]);
477 if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1))
478 error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.");
479
480
481 /* We must get the function beginning and end where line_num is
482 contained. */
483
484 if (line_seen && file_seen)
485 {
486 s = lookup_symtab (file_string);
487 if (s == NULL)
488 error ("mi_cmd_disassemble: Invalid filename.");
489 if (!find_line_pc (s, line_num, &start))
490 error ("mi_cmd_disassemble: Invalid line number");
491 if (find_pc_partial_function (start, NULL, &low, &high) == 0)
492 error ("mi_cmd_disassemble: No function contains specified address");
493 }
494
495 retval = do_disassembly (file_string,
496 line_num,
497 mixed_source_and_assembly, how_many, low, high);
498 return retval;
499 }
This page took 0.042319 seconds and 5 git commands to generate.