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