btrace, testsuite: fix extended-remote fail
[deliverable/binutils-gdb.git] / gdb / disasm.c
CommitLineData
92df71f0 1/* Disassemble support for GDB.
1bac305b 2
61baf725 3 Copyright (C) 2000-2017 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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
92df71f0
FN
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
92df71f0
FN
19
20#include "defs.h"
21#include "target.h"
22#include "value.h"
23#include "ui-out.h"
92df71f0 24#include "disasm.h"
810ecf9f 25#include "gdbcore.h"
a89aa300 26#include "dis-asm.h"
6ff0ba5f 27#include "source.h"
325fac50 28#include <algorithm>
92df71f0
FN
29
30/* Disassemble functions.
31 FIXME: We should get rid of all the duplicate code in gdb that does
0963b4bd 32 the same thing: disassemble_command() and the gdbtk variation. */
92df71f0 33
6ff0ba5f
DE
34/* This structure is used to store line number information for the
35 deprecated /m option.
92df71f0
FN
36 We need a different sort of line table from the normal one cuz we can't
37 depend upon implicit line-end pc's for lines to do the
38 reordering in this function. */
39
6ff0ba5f 40struct deprecated_dis_line_entry
92df71f0
FN
41{
42 int line;
43 CORE_ADDR start_pc;
44 CORE_ADDR end_pc;
45};
46
6ff0ba5f
DE
47/* This Structure is used to store line number information.
48 We need a different sort of line table from the normal one cuz we can't
49 depend upon implicit line-end pc's for lines to do the
50 reordering in this function. */
51
52struct dis_line_entry
53{
54 struct symtab *symtab;
55 int line;
56};
57
58/* Hash function for dis_line_entry. */
59
60static hashval_t
61hash_dis_line_entry (const void *item)
62{
9a3c8263 63 const struct dis_line_entry *dle = (const struct dis_line_entry *) item;
6ff0ba5f
DE
64
65 return htab_hash_pointer (dle->symtab) + dle->line;
66}
67
68/* Equal function for dis_line_entry. */
69
70static int
71eq_dis_line_entry (const void *item_lhs, const void *item_rhs)
72{
9a3c8263
SM
73 const struct dis_line_entry *lhs = (const struct dis_line_entry *) item_lhs;
74 const struct dis_line_entry *rhs = (const struct dis_line_entry *) item_rhs;
6ff0ba5f
DE
75
76 return (lhs->symtab == rhs->symtab
77 && lhs->line == rhs->line);
78}
79
80/* Create the table to manage lines for mixed source/disassembly. */
81
82static htab_t
83allocate_dis_line_table (void)
84{
85 return htab_create_alloc (41,
86 hash_dis_line_entry, eq_dis_line_entry,
87 xfree, xcalloc, xfree);
88}
89
4a099de2 90/* Add a new dis_line_entry containing SYMTAB and LINE to TABLE. */
6ff0ba5f
DE
91
92static void
4a099de2 93add_dis_line_entry (htab_t table, struct symtab *symtab, int line)
6ff0ba5f
DE
94{
95 void **slot;
96 struct dis_line_entry dle, *dlep;
97
98 dle.symtab = symtab;
99 dle.line = line;
100 slot = htab_find_slot (table, &dle, INSERT);
101 if (*slot == NULL)
102 {
103 dlep = XNEW (struct dis_line_entry);
104 dlep->symtab = symtab;
105 dlep->line = line;
106 *slot = dlep;
107 }
108}
109
110/* Return non-zero if SYMTAB, LINE are in TABLE. */
111
112static int
113line_has_code_p (htab_t table, struct symtab *symtab, int line)
114{
115 struct dis_line_entry dle;
116
117 dle.symtab = symtab;
118 dle.line = line;
119 return htab_find (table, &dle) != NULL;
120}
121
e47ad6c0
YQ
122/* Wrapper of target_read_code. */
123
124int
125gdb_disassembler::dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr,
126 unsigned int len,
127 struct disassemble_info *info)
810ecf9f 128{
283f7163 129 return target_read_code (memaddr, myaddr, len);
810ecf9f
AC
130}
131
e47ad6c0
YQ
132/* Wrapper of memory_error. */
133
134void
135gdb_disassembler::dis_asm_memory_error (int err, bfd_vma memaddr,
136 struct disassemble_info *info)
810ecf9f 137{
d8b49cf0
YQ
138 gdb_disassembler *self
139 = static_cast<gdb_disassembler *>(info->application_data);
140
141 self->m_err_memaddr = memaddr;
810ecf9f
AC
142}
143
e47ad6c0
YQ
144/* Wrapper of print_address. */
145
146void
147gdb_disassembler::dis_asm_print_address (bfd_vma addr,
148 struct disassemble_info *info)
810ecf9f 149{
e47ad6c0
YQ
150 gdb_disassembler *self
151 = static_cast<gdb_disassembler *>(info->application_data);
9a619af0 152
e47ad6c0 153 print_address (self->arch (), addr, self->stream ());
810ecf9f
AC
154}
155
92df71f0 156static int
bde58177 157compare_lines (const void *mle1p, const void *mle2p)
92df71f0 158{
6ff0ba5f 159 struct deprecated_dis_line_entry *mle1, *mle2;
92df71f0
FN
160 int val;
161
6ff0ba5f
DE
162 mle1 = (struct deprecated_dis_line_entry *) mle1p;
163 mle2 = (struct deprecated_dis_line_entry *) mle2p;
92df71f0 164
9011945e
AB
165 /* End of sequence markers have a line number of 0 but don't want to
166 be sorted to the head of the list, instead sort by PC. */
167 if (mle1->line == 0 || mle2->line == 0)
168 {
169 val = mle1->start_pc - mle2->start_pc;
170 if (val == 0)
171 val = mle1->line - mle2->line;
172 }
173 else
174 {
175 val = mle1->line - mle2->line;
176 if (val == 0)
177 val = mle1->start_pc - mle2->start_pc;
178 }
179 return val;
92df71f0
FN
180}
181
a50a4026 182/* See disasm.h. */
af70908d 183
a50a4026 184int
e47ad6c0
YQ
185gdb_disassembler::pretty_print_insn (struct ui_out *uiout,
186 const struct disasm_insn *insn,
187 int flags)
92df71f0 188{
92df71f0
FN
189 /* parts of the symbolic representation of the address */
190 int unmapped;
92df71f0
FN
191 int offset;
192 int line;
af70908d 193 int size;
3b31d625 194 struct cleanup *ui_out_chain;
af70908d
MM
195 char *filename = NULL;
196 char *name = NULL;
a50a4026 197 CORE_ADDR pc;
e47ad6c0
YQ
198 struct ui_file *stb = stream ();
199 struct gdbarch *gdbarch = arch ();
af70908d
MM
200
201 ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
a50a4026
MM
202 pc = insn->addr;
203
204 if (insn->number != 0)
205 {
112e8700
SM
206 uiout->field_fmt ("insn-number", "%u", insn->number);
207 uiout->text ("\t");
a50a4026 208 }
92df71f0 209
a50a4026
MM
210 if ((flags & DISASSEMBLY_SPECULATIVE) != 0)
211 {
212 if (insn->is_speculative)
213 {
112e8700 214 uiout->field_string ("is-speculative", "?");
a50a4026
MM
215
216 /* The speculative execution indication overwrites the first
217 character of the PC prefix.
218 We assume a PC prefix length of 3 characters. */
219 if ((flags & DISASSEMBLY_OMIT_PC) == 0)
112e8700 220 uiout->text (pc_prefix (pc) + 1);
a50a4026 221 else
112e8700 222 uiout->text (" ");
a50a4026
MM
223 }
224 else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
112e8700 225 uiout->text (pc_prefix (pc));
a50a4026 226 else
112e8700 227 uiout->text (" ");
a50a4026
MM
228 }
229 else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
112e8700
SM
230 uiout->text (pc_prefix (pc));
231 uiout->field_core_addr ("address", gdbarch, pc);
af70908d
MM
232
233 if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
234 &line, &unmapped))
92df71f0 235 {
af70908d
MM
236 /* We don't care now about line, filename and unmapped. But we might in
237 the future. */
112e8700 238 uiout->text (" <");
af70908d 239 if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
112e8700
SM
240 uiout->field_string ("func-name", name);
241 uiout->text ("+");
242 uiout->field_int ("offset", offset);
243 uiout->text (">:\t");
af70908d
MM
244 }
245 else
112e8700 246 uiout->text (":\t");
1211bce3 247
af70908d
MM
248 if (filename != NULL)
249 xfree (filename);
250 if (name != NULL)
251 xfree (name);
252
253 ui_file_rewind (stb);
254 if (flags & DISASSEMBLY_RAW_INSN)
255 {
256 CORE_ADDR end_pc;
257 bfd_byte data;
258 int err;
259 const char *spacer = "";
260
261 /* Build the opcodes using a temporary stream so we can
262 write them out in a single go for the MI. */
263 struct ui_file *opcode_stream = mem_fileopen ();
264 struct cleanup *cleanups =
265 make_cleanup_ui_file_delete (opcode_stream);
946287b7 266
e47ad6c0 267 size = print_insn (pc);
af70908d 268 end_pc = pc + size;
92df71f0 269
af70908d 270 for (;pc < end_pc; ++pc)
92df71f0 271 {
e47ad6c0 272 err = m_di.read_memory_func (pc, &data, 1, &m_di);
af70908d 273 if (err != 0)
e47ad6c0 274 m_di.memory_error_func (err, pc, &m_di);
af70908d
MM
275 fprintf_filtered (opcode_stream, "%s%02x",
276 spacer, (unsigned) data);
277 spacer = " ";
92df71f0 278 }
af70908d 279
112e8700
SM
280 uiout->field_stream ("opcodes", opcode_stream);
281 uiout->text ("\t");
af70908d
MM
282
283 do_cleanups (cleanups);
284 }
285 else
e47ad6c0 286 size = print_insn (pc);
af70908d 287
112e8700 288 uiout->field_stream ("inst", stb);
af70908d
MM
289 ui_file_rewind (stb);
290 do_cleanups (ui_out_chain);
112e8700 291 uiout->text ("\n");
af70908d
MM
292
293 return size;
294}
295
296static int
e47ad6c0 297dump_insns (struct ui_out *uiout, gdb_disassembler *di,
af70908d 298 CORE_ADDR low, CORE_ADDR high,
e47ad6c0 299 int how_many, int flags,
af70908d
MM
300 CORE_ADDR *end_pc)
301{
a50a4026 302 struct disasm_insn insn;
af70908d
MM
303 int num_displayed = 0;
304
a50a4026
MM
305 memset (&insn, 0, sizeof (insn));
306 insn.addr = low;
307
308 while (insn.addr < high && (how_many < 0 || num_displayed < how_many))
af70908d
MM
309 {
310 int size;
311
e47ad6c0 312 size = di->pretty_print_insn (uiout, &insn, flags);
af70908d
MM
313 if (size <= 0)
314 break;
315
316 ++num_displayed;
a50a4026 317 insn.addr += size;
af70908d
MM
318
319 /* Allow user to bail out with ^C. */
320 QUIT;
92df71f0 321 }
6ff0ba5f
DE
322
323 if (end_pc != NULL)
a50a4026 324 *end_pc = insn.addr;
af70908d 325
92df71f0
FN
326 return num_displayed;
327}
328
329/* The idea here is to present a source-O-centric view of a
330 function to the user. This means that things are presented
331 in source order, with (possibly) out of order assembly
6ff0ba5f
DE
332 immediately following.
333
334 N.B. This view is deprecated. */
0963b4bd 335
92df71f0 336static void
6ff0ba5f 337do_mixed_source_and_assembly_deprecated
e47ad6c0
YQ
338 (struct ui_out *uiout,
339 gdb_disassembler *di, struct symtab *symtab,
6ff0ba5f 340 CORE_ADDR low, CORE_ADDR high,
e47ad6c0 341 int how_many, int flags)
92df71f0
FN
342{
343 int newlines = 0;
6ff0ba5f
DE
344 int nlines;
345 struct linetable_entry *le;
346 struct deprecated_dis_line_entry *mle;
92df71f0
FN
347 struct symtab_and_line sal;
348 int i;
349 int out_of_order = 0;
350 int next_line = 0;
92df71f0 351 int num_displayed = 0;
8d297bbf 352 print_source_lines_flags psl_flags = 0;
3b31d625 353 struct cleanup *ui_out_chain;
0127c0d3
JJ
354 struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
355 struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
92df71f0 356
6ff0ba5f
DE
357 gdb_assert (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL);
358
359 nlines = SYMTAB_LINETABLE (symtab)->nitems;
360 le = SYMTAB_LINETABLE (symtab)->item;
361
4cd29721
MM
362 if (flags & DISASSEMBLY_FILENAME)
363 psl_flags |= PRINT_SOURCE_LINES_FILENAME;
364
6ff0ba5f
DE
365 mle = (struct deprecated_dis_line_entry *)
366 alloca (nlines * sizeof (struct deprecated_dis_line_entry));
92df71f0
FN
367
368 /* Copy linetable entries for this function into our data
369 structure, creating end_pc's and setting out_of_order as
370 appropriate. */
371
372 /* First, skip all the preceding functions. */
373
374 for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
375
376 /* Now, copy all entries before the end of this function. */
377
378 for (; i < nlines - 1 && le[i].pc < high; i++)
379 {
380 if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
0963b4bd 381 continue; /* Ignore duplicates. */
92df71f0
FN
382
383 /* Skip any end-of-function markers. */
384 if (le[i].line == 0)
385 continue;
386
387 mle[newlines].line = le[i].line;
388 if (le[i].line > le[i + 1].line)
389 out_of_order = 1;
390 mle[newlines].start_pc = le[i].pc;
391 mle[newlines].end_pc = le[i + 1].pc;
392 newlines++;
393 }
394
395 /* If we're on the last line, and it's part of the function,
396 then we need to get the end pc in a special way. */
397
398 if (i == nlines - 1 && le[i].pc < high)
399 {
400 mle[newlines].line = le[i].line;
401 mle[newlines].start_pc = le[i].pc;
402 sal = find_pc_line (le[i].pc, 0);
403 mle[newlines].end_pc = sal.end;
404 newlines++;
405 }
406
6ff0ba5f 407 /* Now, sort mle by line #s (and, then by addresses within lines). */
92df71f0
FN
408
409 if (out_of_order)
6ff0ba5f
DE
410 qsort (mle, newlines, sizeof (struct deprecated_dis_line_entry),
411 compare_lines);
92df71f0
FN
412
413 /* Now, for each line entry, emit the specified lines (unless
414 they have been emitted before), followed by the assembly code
415 for that line. */
416
3b31d625 417 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
92df71f0
FN
418
419 for (i = 0; i < newlines; i++)
420 {
92df71f0
FN
421 /* Print out everything from next_line to the current line. */
422 if (mle[i].line >= next_line)
423 {
424 if (next_line != 0)
425 {
0963b4bd 426 /* Just one line to print. */
92df71f0
FN
427 if (next_line == mle[i].line)
428 {
3b31d625
EZ
429 ui_out_tuple_chain
430 = make_cleanup_ui_out_tuple_begin_end (uiout,
431 "src_and_asm_line");
4cd29721 432 print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
92df71f0
FN
433 }
434 else
435 {
0963b4bd 436 /* Several source lines w/o asm instructions associated. */
92df71f0
FN
437 for (; next_line < mle[i].line; next_line++)
438 {
3b31d625
EZ
439 struct cleanup *ui_out_list_chain_line;
440 struct cleanup *ui_out_tuple_chain_line;
441
442 ui_out_tuple_chain_line
443 = make_cleanup_ui_out_tuple_begin_end (uiout,
444 "src_and_asm_line");
92df71f0 445 print_source_lines (symtab, next_line, next_line + 1,
4cd29721 446 psl_flags);
3b31d625
EZ
447 ui_out_list_chain_line
448 = make_cleanup_ui_out_list_begin_end (uiout,
449 "line_asm_insn");
450 do_cleanups (ui_out_list_chain_line);
451 do_cleanups (ui_out_tuple_chain_line);
92df71f0
FN
452 }
453 /* Print the last line and leave list open for
0963b4bd 454 asm instructions to be added. */
3b31d625
EZ
455 ui_out_tuple_chain
456 = make_cleanup_ui_out_tuple_begin_end (uiout,
457 "src_and_asm_line");
4cd29721 458 print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
92df71f0
FN
459 }
460 }
461 else
462 {
3b31d625 463 ui_out_tuple_chain
3e43a32a
MS
464 = make_cleanup_ui_out_tuple_begin_end (uiout,
465 "src_and_asm_line");
4cd29721 466 print_source_lines (symtab, mle[i].line, mle[i].line + 1, psl_flags);
92df71f0
FN
467 }
468
469 next_line = mle[i].line + 1;
3b31d625
EZ
470 ui_out_list_chain
471 = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
92df71f0
FN
472 }
473
e47ad6c0 474 num_displayed += dump_insns (uiout, di,
13274fc3 475 mle[i].start_pc, mle[i].end_pc,
e47ad6c0 476 how_many, flags, NULL);
0127c0d3
JJ
477
478 /* When we've reached the end of the mle array, or we've seen the last
479 assembly range for this source line, close out the list/tuple. */
480 if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
92df71f0 481 {
3b31d625
EZ
482 do_cleanups (ui_out_list_chain);
483 do_cleanups (ui_out_tuple_chain);
0127c0d3
JJ
484 ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
485 ui_out_list_chain = make_cleanup (null_cleanup, 0);
112e8700 486 uiout->text ("\n");
92df71f0 487 }
0127c0d3
JJ
488 if (how_many >= 0 && num_displayed >= how_many)
489 break;
92df71f0 490 }
3b31d625 491 do_cleanups (ui_out_chain);
92df71f0
FN
492}
493
6ff0ba5f
DE
494/* The idea here is to present a source-O-centric view of a
495 function to the user. This means that things are presented
496 in source order, with (possibly) out of order assembly
497 immediately following. */
498
499static void
e47ad6c0
YQ
500do_mixed_source_and_assembly (struct gdbarch *gdbarch,
501 struct ui_out *uiout,
502 gdb_disassembler *di,
6ff0ba5f
DE
503 struct symtab *main_symtab,
504 CORE_ADDR low, CORE_ADDR high,
e47ad6c0 505 int how_many, int flags)
6ff0ba5f 506{
6ff0ba5f 507 const struct linetable_entry *le, *first_le;
6ff0ba5f 508 int i, nlines;
6ff0ba5f 509 int num_displayed = 0;
8d297bbf 510 print_source_lines_flags psl_flags = 0;
6ff0ba5f
DE
511 struct cleanup *ui_out_chain;
512 struct cleanup *ui_out_tuple_chain;
513 struct cleanup *ui_out_list_chain;
514 CORE_ADDR pc;
515 struct symtab *last_symtab;
516 int last_line;
6ff0ba5f
DE
517
518 gdb_assert (main_symtab != NULL && SYMTAB_LINETABLE (main_symtab) != NULL);
519
520 /* First pass: collect the list of all source files and lines.
521 We do this so that we can only print lines containing code once.
522 We try to print the source text leading up to the next instruction,
523 but if that text is for code that will be disassembled later, then
524 we'll want to defer printing it until later with its associated code. */
525
fc4007c9 526 htab_up dis_line_table (allocate_dis_line_table ());
6ff0ba5f
DE
527
528 pc = low;
529
530 /* The prologue may be empty, but there may still be a line number entry
531 for the opening brace which is distinct from the first line of code.
532 If the prologue has been eliminated find_pc_line may return the source
533 line after the opening brace. We still want to print this opening brace.
534 first_le is used to implement this. */
535
536 nlines = SYMTAB_LINETABLE (main_symtab)->nitems;
537 le = SYMTAB_LINETABLE (main_symtab)->item;
538 first_le = NULL;
539
540 /* Skip all the preceding functions. */
541 for (i = 0; i < nlines && le[i].pc < low; i++)
542 continue;
543
544 if (i < nlines && le[i].pc < high)
545 first_le = &le[i];
546
547 /* Add lines for every pc value. */
548 while (pc < high)
549 {
550 struct symtab_and_line sal;
551 int length;
552
553 sal = find_pc_line (pc, 0);
554 length = gdb_insn_length (gdbarch, pc);
555 pc += length;
556
557 if (sal.symtab != NULL)
fc4007c9 558 add_dis_line_entry (dis_line_table.get (), sal.symtab, sal.line);
6ff0ba5f
DE
559 }
560
561 /* Second pass: print the disassembly.
562
563 Output format, from an MI perspective:
564 The result is a ui_out list, field name "asm_insns", where elements have
565 name "src_and_asm_line".
566 Each element is a tuple of source line specs (field names line, file,
567 fullname), and field "line_asm_insn" which contains the disassembly.
568 Field "line_asm_insn" is a list of tuples: address, func-name, offset,
569 opcodes, inst.
570
571 CLI output works on top of this because MI ignores ui_out_text output,
572 which is where we put file name and source line contents output.
573
574 Cleanup usage:
6ff0ba5f
DE
575 ui_out_chain
576 Handles the outer "asm_insns" list.
577 ui_out_tuple_chain
578 The tuples for each group of consecutive disassemblies.
579 ui_out_list_chain
580 List of consecutive source lines or disassembled insns. */
581
582 if (flags & DISASSEMBLY_FILENAME)
583 psl_flags |= PRINT_SOURCE_LINES_FILENAME;
584
585 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
586
587 ui_out_tuple_chain = NULL;
588 ui_out_list_chain = NULL;
589
590 last_symtab = NULL;
591 last_line = 0;
592 pc = low;
593
594 while (pc < high)
595 {
6ff0ba5f
DE
596 struct symtab_and_line sal;
597 CORE_ADDR end_pc;
598 int start_preceding_line_to_display = 0;
599 int end_preceding_line_to_display = 0;
600 int new_source_line = 0;
601
602 sal = find_pc_line (pc, 0);
603
604 if (sal.symtab != last_symtab)
605 {
606 /* New source file. */
607 new_source_line = 1;
608
609 /* If this is the first line of output, check for any preceding
610 lines. */
611 if (last_line == 0
612 && first_le != NULL
613 && first_le->line < sal.line)
614 {
615 start_preceding_line_to_display = first_le->line;
616 end_preceding_line_to_display = sal.line;
617 }
618 }
619 else
620 {
621 /* Same source file as last time. */
622 if (sal.symtab != NULL)
623 {
624 if (sal.line > last_line + 1 && last_line != 0)
625 {
626 int l;
627
628 /* Several preceding source lines. Print the trailing ones
629 not associated with code that we'll print later. */
630 for (l = sal.line - 1; l > last_line; --l)
631 {
fc4007c9
TT
632 if (line_has_code_p (dis_line_table.get (),
633 sal.symtab, l))
6ff0ba5f
DE
634 break;
635 }
636 if (l < sal.line - 1)
637 {
638 start_preceding_line_to_display = l + 1;
639 end_preceding_line_to_display = sal.line;
640 }
641 }
642 if (sal.line != last_line)
643 new_source_line = 1;
644 else
645 {
646 /* Same source line as last time. This can happen, depending
647 on the debug info. */
648 }
649 }
650 }
651
652 if (new_source_line)
653 {
654 /* Skip the newline if this is the first instruction. */
655 if (pc > low)
112e8700 656 uiout->text ("\n");
6ff0ba5f
DE
657 if (ui_out_tuple_chain != NULL)
658 {
659 gdb_assert (ui_out_list_chain != NULL);
660 do_cleanups (ui_out_list_chain);
661 do_cleanups (ui_out_tuple_chain);
662 }
663 if (sal.symtab != last_symtab
664 && !(flags & DISASSEMBLY_FILENAME))
665 {
666 /* Remember MI ignores ui_out_text.
667 We don't have to do anything here for MI because MI
668 output includes the source specs for each line. */
669 if (sal.symtab != NULL)
670 {
112e8700 671 uiout->text (symtab_to_filename_for_display (sal.symtab));
6ff0ba5f
DE
672 }
673 else
112e8700
SM
674 uiout->text ("unknown");
675 uiout->text (":\n");
6ff0ba5f
DE
676 }
677 if (start_preceding_line_to_display > 0)
678 {
679 /* Several source lines w/o asm instructions associated.
680 We need to preserve the structure of the output, so output
681 a bunch of line tuples with no asm entries. */
682 int l;
683 struct cleanup *ui_out_list_chain_line;
684 struct cleanup *ui_out_tuple_chain_line;
685
686 gdb_assert (sal.symtab != NULL);
687 for (l = start_preceding_line_to_display;
688 l < end_preceding_line_to_display;
689 ++l)
690 {
691 ui_out_tuple_chain_line
692 = make_cleanup_ui_out_tuple_begin_end (uiout,
693 "src_and_asm_line");
694 print_source_lines (sal.symtab, l, l + 1, psl_flags);
695 ui_out_list_chain_line
696 = make_cleanup_ui_out_list_begin_end (uiout,
697 "line_asm_insn");
698 do_cleanups (ui_out_list_chain_line);
699 do_cleanups (ui_out_tuple_chain_line);
700 }
701 }
702 ui_out_tuple_chain
703 = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
704 if (sal.symtab != NULL)
705 print_source_lines (sal.symtab, sal.line, sal.line + 1, psl_flags);
706 else
112e8700 707 uiout->text (_("--- no source info for this pc ---\n"));
6ff0ba5f
DE
708 ui_out_list_chain
709 = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
710 }
711 else
712 {
713 /* Here we're appending instructions to an existing line.
714 By construction the very first insn will have a symtab
715 and follow the new_source_line path above. */
716 gdb_assert (ui_out_tuple_chain != NULL);
717 gdb_assert (ui_out_list_chain != NULL);
718 }
719
720 if (sal.end != 0)
325fac50 721 end_pc = std::min (sal.end, high);
6ff0ba5f
DE
722 else
723 end_pc = pc + 1;
e47ad6c0
YQ
724 num_displayed += dump_insns (uiout, di, pc, end_pc,
725 how_many, flags, &end_pc);
6ff0ba5f
DE
726 pc = end_pc;
727
728 if (how_many >= 0 && num_displayed >= how_many)
729 break;
730
731 last_symtab = sal.symtab;
732 last_line = sal.line;
733 }
734
735 do_cleanups (ui_out_chain);
6ff0ba5f 736}
92df71f0
FN
737
738static void
e47ad6c0
YQ
739do_assembly_only (struct ui_out *uiout,
740 gdb_disassembler *di,
92df71f0 741 CORE_ADDR low, CORE_ADDR high,
e47ad6c0 742 int how_many, int flags)
92df71f0 743{
3b31d625 744 struct cleanup *ui_out_chain;
92df71f0 745
3b31d625 746 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
92df71f0 747
e47ad6c0 748 dump_insns (uiout, di, low, high, how_many, flags, NULL);
92df71f0 749
3b31d625 750 do_cleanups (ui_out_chain);
92df71f0
FN
751}
752
92bf2b80
AC
753/* Initialize the disassemble info struct ready for the specified
754 stream. */
755
a0b31db1 756static int ATTRIBUTE_PRINTF (2, 3)
242e8be5
AC
757fprintf_disasm (void *stream, const char *format, ...)
758{
759 va_list args;
9a619af0 760
242e8be5 761 va_start (args, format);
9a3c8263 762 vfprintf_filtered ((struct ui_file *) stream, format, args);
242e8be5
AC
763 va_end (args);
764 /* Something non -ve. */
765 return 0;
766}
767
e47ad6c0
YQ
768gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
769 struct ui_file *file,
770 di_read_memory_ftype read_memory_func)
d8b49cf0
YQ
771 : m_gdbarch (gdbarch),
772 m_err_memaddr (0)
92df71f0 773{
e47ad6c0
YQ
774 init_disassemble_info (&m_di, file, fprintf_disasm);
775 m_di.flavour = bfd_target_unknown_flavour;
776 m_di.memory_error_func = dis_asm_memory_error;
777 m_di.print_address_func = dis_asm_print_address;
2b6fd0d8
AC
778 /* NOTE: cagney/2003-04-28: The original code, from the old Insight
779 disassembler had a local optomization here. By default it would
780 access the executable file, instead of the target memory (there
ce2826aa 781 was a growing list of exceptions though). Unfortunately, the
2b6fd0d8
AC
782 heuristic was flawed. Commands like "disassemble &variable"
783 didn't work as they relied on the access going to the target.
784 Further, it has been supperseeded by trust-read-only-sections
785 (although that should be superseeded by target_trust..._p()). */
e47ad6c0
YQ
786 m_di.read_memory_func = read_memory_func;
787 m_di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
788 m_di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
789 m_di.endian = gdbarch_byte_order (gdbarch);
790 m_di.endian_code = gdbarch_byte_order_for_code (gdbarch);
791 m_di.application_data = this;
792 disassemble_init_for_target (&m_di);
793}
794
795int
796gdb_disassembler::print_insn (CORE_ADDR memaddr,
797 int *branch_delay_insns)
798{
d8b49cf0
YQ
799 m_err_memaddr = 0;
800
e47ad6c0
YQ
801 int length = gdbarch_print_insn (arch (), memaddr, &m_di);
802
d8b49cf0
YQ
803 if (length < 0)
804 memory_error (TARGET_XFER_E_IO, m_err_memaddr);
805
e47ad6c0
YQ
806 if (branch_delay_insns != NULL)
807 {
808 if (m_di.insn_info_valid)
809 *branch_delay_insns = m_di.branch_delay_insns;
810 else
811 *branch_delay_insns = 0;
812 }
813 return length;
92bf2b80
AC
814}
815
816void
13274fc3 817gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
9c419145
PP
818 char *file_string, int flags, int how_many,
819 CORE_ADDR low, CORE_ADDR high)
92bf2b80 820{
f99d8bf4
PA
821 struct ui_file *stb = mem_fileopen ();
822 struct cleanup *cleanups = make_cleanup_ui_file_delete (stb);
e47ad6c0 823 gdb_disassembler di (gdbarch, stb);
34248c3a 824 struct symtab *symtab;
92bf2b80 825 int nlines = -1;
92df71f0 826
0963b4bd 827 /* Assume symtab is valid for whole PC range. */
34248c3a 828 symtab = find_pc_line_symtab (low);
92df71f0 829
8435453b 830 if (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL)
6ff0ba5f 831 nlines = SYMTAB_LINETABLE (symtab)->nitems;
92df71f0 832
6ff0ba5f
DE
833 if (!(flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
834 || nlines <= 0)
e47ad6c0 835 do_assembly_only (uiout, &di, low, high, how_many, flags);
92df71f0 836
e6158f16 837 else if (flags & DISASSEMBLY_SOURCE)
6ff0ba5f 838 do_mixed_source_and_assembly (gdbarch, uiout, &di, symtab, low, high,
e47ad6c0 839 how_many, flags);
6ff0ba5f
DE
840
841 else if (flags & DISASSEMBLY_SOURCE_DEPRECATED)
e47ad6c0
YQ
842 do_mixed_source_and_assembly_deprecated (uiout, &di, symtab,
843 low, high, how_many, flags);
92df71f0 844
2b6fd0d8 845 do_cleanups (cleanups);
92df71f0
FN
846 gdb_flush (gdb_stdout);
847}
810ecf9f 848
92bf2b80 849/* Print the instruction at address MEMADDR in debugged memory,
a4642986
MR
850 on STREAM. Returns the length of the instruction, in bytes,
851 and, if requested, the number of branch delay slot instructions. */
92bf2b80
AC
852
853int
13274fc3
UW
854gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
855 struct ui_file *stream, int *branch_delay_insns)
92bf2b80 856{
a4642986 857
e47ad6c0
YQ
858 gdb_disassembler di (gdbarch, stream);
859
860 return di.print_insn (memaddr, branch_delay_insns);
92bf2b80 861}
eda5a4d7 862
eda5a4d7
PA
863/* Return the length in bytes of the instruction at address MEMADDR in
864 debugged memory. */
865
866int
867gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
868{
80d75874 869 return gdb_print_insn (gdbarch, addr, null_stream (), NULL);
eda5a4d7
PA
870}
871
872/* fprintf-function for gdb_buffered_insn_length. This function is a
873 nop, we don't want to print anything, we just want to compute the
874 length of the insn. */
875
876static int ATTRIBUTE_PRINTF (2, 3)
877gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
878{
879 return 0;
880}
881
882/* Initialize a struct disassemble_info for gdb_buffered_insn_length. */
883
884static void
885gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
886 struct disassemble_info *di,
887 const gdb_byte *insn, int max_len,
888 CORE_ADDR addr)
889{
890 init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
891
892 /* init_disassemble_info installs buffer_read_memory, etc.
893 so we don't need to do that here.
894 The cast is necessary until disassemble_info is const-ified. */
895 di->buffer = (gdb_byte *) insn;
896 di->buffer_length = max_len;
897 di->buffer_vma = addr;
898
899 di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
900 di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
901 di->endian = gdbarch_byte_order (gdbarch);
902 di->endian_code = gdbarch_byte_order_for_code (gdbarch);
903
904 disassemble_init_for_target (di);
905}
906
907/* Return the length in bytes of INSN. MAX_LEN is the size of the
908 buffer containing INSN. */
909
910int
911gdb_buffered_insn_length (struct gdbarch *gdbarch,
912 const gdb_byte *insn, int max_len, CORE_ADDR addr)
913{
914 struct disassemble_info di;
915
916 gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
917
918 return gdbarch_print_insn (gdbarch, addr, &di);
919}
This page took 0.969617 seconds and 4 git commands to generate.