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