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