2003-04-16 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.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 int offset;
97 int line;
98 struct cleanup *ui_out_chain;
99
100 for (pc = low; pc < high;)
101 {
102 char *filename = NULL;
103 char *name = NULL;
104
105 QUIT;
106 if (how_many >= 0)
107 {
108 if (num_displayed >= how_many)
109 break;
110 else
111 num_displayed++;
112 }
113 ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
114 ui_out_field_core_addr (uiout, "address", pc);
115
116 if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
117 &line, &unmapped))
118 {
119 /* We don't care now about line, filename and
120 unmapped. But we might in the future. */
121 ui_out_text (uiout, " <");
122 ui_out_field_string (uiout, "func-name", name);
123 ui_out_text (uiout, "+");
124 ui_out_field_int (uiout, "offset", offset);
125 ui_out_text (uiout, ">:\t");
126 }
127 if (filename != NULL)
128 xfree (filename);
129 if (name != NULL)
130 xfree (name);
131
132 ui_file_rewind (stb->stream);
133 pc += TARGET_PRINT_INSN (pc, di);
134 ui_out_field_stream (uiout, "inst", stb);
135 ui_file_rewind (stb->stream);
136 do_cleanups (ui_out_chain);
137 ui_out_text (uiout, "\n");
138 }
139 return num_displayed;
140 }
141
142 /* The idea here is to present a source-O-centric view of a
143 function to the user. This means that things are presented
144 in source order, with (possibly) out of order assembly
145 immediately following. */
146 static void
147 do_mixed_source_and_assembly (struct ui_out *uiout,
148 struct disassemble_info *di, int nlines,
149 struct linetable_entry *le,
150 CORE_ADDR low, CORE_ADDR high,
151 struct symtab *symtab,
152 int how_many, struct ui_stream *stb)
153 {
154 int newlines = 0;
155 struct dis_line_entry *mle;
156 struct symtab_and_line sal;
157 int i;
158 int out_of_order = 0;
159 int next_line = 0;
160 CORE_ADDR pc;
161 int num_displayed = 0;
162 struct cleanup *ui_out_chain;
163
164 mle = (struct dis_line_entry *) alloca (nlines
165 * sizeof (struct dis_line_entry));
166
167 /* Copy linetable entries for this function into our data
168 structure, creating end_pc's and setting out_of_order as
169 appropriate. */
170
171 /* First, skip all the preceding functions. */
172
173 for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
174
175 /* Now, copy all entries before the end of this function. */
176
177 for (; i < nlines - 1 && le[i].pc < high; i++)
178 {
179 if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
180 continue; /* Ignore duplicates */
181
182 /* Skip any end-of-function markers. */
183 if (le[i].line == 0)
184 continue;
185
186 mle[newlines].line = le[i].line;
187 if (le[i].line > le[i + 1].line)
188 out_of_order = 1;
189 mle[newlines].start_pc = le[i].pc;
190 mle[newlines].end_pc = le[i + 1].pc;
191 newlines++;
192 }
193
194 /* If we're on the last line, and it's part of the function,
195 then we need to get the end pc in a special way. */
196
197 if (i == nlines - 1 && le[i].pc < high)
198 {
199 mle[newlines].line = le[i].line;
200 mle[newlines].start_pc = le[i].pc;
201 sal = find_pc_line (le[i].pc, 0);
202 mle[newlines].end_pc = sal.end;
203 newlines++;
204 }
205
206 /* Now, sort mle by line #s (and, then by addresses within
207 lines). */
208
209 if (out_of_order)
210 qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
211
212 /* Now, for each line entry, emit the specified lines (unless
213 they have been emitted before), followed by the assembly code
214 for that line. */
215
216 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
217
218 for (i = 0; i < newlines; i++)
219 {
220 struct cleanup *ui_out_tuple_chain = NULL;
221 struct cleanup *ui_out_list_chain = NULL;
222 int close_list = 1;
223
224 /* Print out everything from next_line to the current line. */
225 if (mle[i].line >= next_line)
226 {
227 if (next_line != 0)
228 {
229 /* Just one line to print. */
230 if (next_line == mle[i].line)
231 {
232 ui_out_tuple_chain
233 = make_cleanup_ui_out_tuple_begin_end (uiout,
234 "src_and_asm_line");
235 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
236 }
237 else
238 {
239 /* Several source lines w/o asm instructions associated. */
240 for (; next_line < mle[i].line; next_line++)
241 {
242 struct cleanup *ui_out_list_chain_line;
243 struct cleanup *ui_out_tuple_chain_line;
244
245 ui_out_tuple_chain_line
246 = make_cleanup_ui_out_tuple_begin_end (uiout,
247 "src_and_asm_line");
248 print_source_lines (symtab, next_line, next_line + 1,
249 0);
250 ui_out_list_chain_line
251 = make_cleanup_ui_out_list_begin_end (uiout,
252 "line_asm_insn");
253 do_cleanups (ui_out_list_chain_line);
254 do_cleanups (ui_out_tuple_chain_line);
255 }
256 /* Print the last line and leave list open for
257 asm instructions to be added. */
258 ui_out_tuple_chain
259 = make_cleanup_ui_out_tuple_begin_end (uiout,
260 "src_and_asm_line");
261 print_source_lines (symtab, next_line, mle[i].line + 1, 0);
262 }
263 }
264 else
265 {
266 ui_out_tuple_chain
267 = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
268 print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
269 }
270
271 next_line = mle[i].line + 1;
272 ui_out_list_chain
273 = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
274 /* Don't close the list if the lines are not in order. */
275 if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line)
276 close_list = 0;
277 }
278
279 num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc,
280 how_many, stb);
281 if (close_list)
282 {
283 do_cleanups (ui_out_list_chain);
284 do_cleanups (ui_out_tuple_chain);
285 ui_out_text (uiout, "\n");
286 close_list = 0;
287 }
288 if (how_many >= 0)
289 if (num_displayed >= how_many)
290 break;
291 }
292 do_cleanups (ui_out_chain);
293 }
294
295
296 static void
297 do_assembly_only (struct ui_out *uiout, disassemble_info * di,
298 CORE_ADDR low, CORE_ADDR high,
299 int how_many, struct ui_stream *stb)
300 {
301 int num_displayed = 0;
302 struct cleanup *ui_out_chain;
303
304 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
305
306 num_displayed = dump_insns (uiout, di, low, high, how_many, stb);
307
308 do_cleanups (ui_out_chain);
309 }
310
311 void
312 gdb_disassembly (struct ui_out *uiout,
313 char *file_string,
314 int line_num,
315 int mixed_source_and_assembly,
316 int how_many, CORE_ADDR low, CORE_ADDR high)
317 {
318 static disassemble_info di;
319 static int di_initialized;
320 /* To collect the instruction outputted from opcodes. */
321 static struct ui_stream *stb = NULL;
322 struct symtab *symtab = NULL;
323 struct linetable_entry *le = NULL;
324 int nlines = -1;
325
326 if (!di_initialized)
327 {
328 /* We don't add a cleanup for this, because the allocation of
329 the stream is done once only for each gdb run, and we need to
330 keep it around until the end. Hopefully there won't be any
331 errors in the init code below, that make this function bail
332 out. */
333 stb = ui_out_stream_new (uiout);
334 INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream,
335 (fprintf_ftype) fprintf_unfiltered);
336 di.flavour = bfd_target_unknown_flavour;
337 di.memory_error_func = dis_asm_memory_error;
338 di.print_address_func = dis_asm_print_address;
339 di_initialized = 1;
340 }
341
342 di.mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
343 di.endian = gdbarch_byte_order (current_gdbarch);
344
345 /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
346 determine whether or not to do disassembly from target memory or from the
347 exec file:
348
349 If we're debugging a local process, read target memory, instead of the
350 exec file. This makes disassembly of functions in shared libs work
351 correctly. Also, read target memory if we are debugging native threads.
352
353 Else, we're debugging a remote process, and should disassemble from the
354 exec file for speed. However, this is no good if the target modifies its
355 code (for relocation, or whatever). */
356
357 if (gdb_disassemble_from_exec == -1)
358 {
359 if (strcmp (target_shortname, "child") == 0
360 || strcmp (target_shortname, "procfs") == 0
361 || strcmp (target_shortname, "vxprocess") == 0
362 || strcmp (target_shortname, "core") == 0
363 || strstr (target_shortname, "-thread") != NULL)
364 gdb_disassemble_from_exec = 0; /* It's a child process, read inferior mem */
365 else
366 gdb_disassemble_from_exec = 1; /* It's remote, read the exec file */
367 }
368
369 if (gdb_disassemble_from_exec)
370 di.read_memory_func = gdb_dis_asm_read_memory;
371 else
372 di.read_memory_func = dis_asm_read_memory;
373
374 /* Assume symtab is valid for whole PC range */
375 symtab = find_pc_symtab (low);
376
377 if (symtab != NULL && symtab->linetable != NULL)
378 {
379 /* Convert the linetable to a bunch of my_line_entry's. */
380 le = symtab->linetable->item;
381 nlines = symtab->linetable->nitems;
382 }
383
384 if (!mixed_source_and_assembly || nlines <= 0
385 || symtab == NULL || symtab->linetable == NULL)
386 do_assembly_only (uiout, &di, low, high, how_many, stb);
387
388 else if (mixed_source_and_assembly)
389 do_mixed_source_and_assembly (uiout, &di, nlines, le, low,
390 high, symtab, how_many, stb);
391
392 gdb_flush (gdb_stdout);
393 }
This page took 0.036754 seconds and 4 git commands to generate.