From 92df71f044d9a17e6244ee33370f53638c818b9c Mon Sep 17 00:00:00 2001 From: Fernando Nasser Date: Mon, 30 Sep 2002 15:57:26 +0000 Subject: * disasm.c: New file. * disasm.h: New file. * mi/mi-cmd-disas.c (gdb_dis_asm_read_memory): Moved to disasm.c. (compare_lines): Ditto. (dump_insns): Ditto. (do_mixed_source_and_assembly): Moved to disasm.c. Added uiout argument. (do_assembly_only): Ditto. (do_disassembly): Renamed to gdb_disassembly and moved to disasm.c. Sdded uiout argument. * Makefile.in: Add new files. Reorder SFILES list. Update dependencies. Include libgdb.a later in the insight executable. --- gdb/ChangeLog | 14 ++ gdb/Makefile.in | 61 ++++---- gdb/disasm.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/disasm.h | 29 ++++ gdb/mi/mi-cmd-disas.c | 358 ++--------------------------------------------- 5 files changed, 457 insertions(+), 379 deletions(-) create mode 100644 gdb/disasm.c create mode 100644 gdb/disasm.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7f2565c..2638d9f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2002-09-30 Fernando Nasser + + * disasm.c: New file. + * disasm.h: New file. + * mi/mi-cmd-disas.c (gdb_dis_asm_read_memory): Moved to disasm.c. + (compare_lines): Ditto. + (dump_insns): Ditto. + (do_mixed_source_and_assembly): Moved to disasm.c. Added uiout argument. + (do_assembly_only): Ditto. + (do_disassembly): Renamed to gdb_disassembly and moved to disasm.c. + Sdded uiout argument. + * Makefile.in: Add new files. Reorder SFILES list. Update dependencies. + Include libgdb.a later in the insight executable. + 2002-09-29 Andrew Cagney * config/djgpp/fnchange.lst: Rename bfd/elf64-alpha.c and diff --git a/gdb/Makefile.in b/gdb/Makefile.in index b56732d..6635227 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -530,29 +530,30 @@ TARGET_FLAGS_TO_PASS = \ # SFILES is used in building the distribution archive. SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ - ax-general.c ax-gdb.c bcache.c blockframe.c breakpoint.c \ - charset.c \ - buildsym.c c-exp.y c-lang.c c-typeprint.c c-valprint.c \ - coffread.c \ - complaints.c completer.c corefile.c cp-valprint.c dbxread.c \ - demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \ - event-loop.c event-top.c \ - expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \ - findvar.c regcache.c gdbarch.c arch-utils.c gdbtypes.c osabi.c \ - inf-loop.c infcmd.c inflow.c infrun.c language.c \ - kod.c kod-cisco.c \ - ui-out.c cli-out.c \ - varobj.c wrapper.c \ + ax-general.c ax-gdb.c \ + bcache.c blockframe.c breakpoint.c buildsym.c builtin-regs.c \ + c-exp.y c-lang.c c-typeprint.c c-valprint.c \ + charset.c cli-out.c coffread.c complaints.c completer.c corefile.c \ + cp-abi.c cp-support.c cp-valprint.c \ + dbxread.c demangle.c disasm.c doublest.c dwarfread.c dwarf2read.c \ + elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \ + f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \ + gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \ + hpacc-abi.c \ + inf-loop.c infcmd.c inflow.c infrun.c \ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ - m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \ - memattr.c mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c \ - p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c \ - macrotab.c macroexp.c macrocmd.c macroscope.c \ - printcmd.c remote.c scm-exp.c scm-lang.c \ - scm-valprint.c source.c stabsread.c stack.c symfile.c \ - symmisc.c symtab.c linespec.c target.c thread.c top.c tracepoint.c \ - typeprint.c utils.c valarith.c valops.c valprint.c values.c \ - serial.c ser-unix.c mdebugread.c \ + kod.c kod-cisco.c \ + language.c linespec.c \ + m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \ + macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \ + mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c \ + nlmread.c \ + objfiles.c osabi.c \ + p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \ + regcache.c remote.c \ + scm-exp.c scm-lang.c scm-valprint.c serial.c ser-unix.c source.c \ + stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \ + target.c thread.c top.c tracepoint.c typeprint.c \ tui/tui.c tui/tui.h tui/tuiCommand.c tui/tuiCommand.h \ tui/tuiData.c tui/tuiData.h tui/tuiDataWin.c tui/tuiDataWin.h \ tui/tuiDisassem.c tui/tuiDisassem.h tui/tuiGeneralWin.c \ @@ -561,10 +562,9 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ tui/tuiSource.h tui/tuiSourceWin.c tui/tuiSourceWin.h \ tui/tuiStack.c tui/tuiStack.h tui/tuiWin.c tui/tuiWin.h \ tui/tui-file.h tui/tui-file.c tui/tui-out.c tui/tui-hooks.c \ - ui-file.h ui-file.c \ - frame.c doublest.c \ - builtin-regs.c std-regs.c \ - gnu-v2-abi.c gnu-v3-abi.c hpacc-abi.c cp-abi.c cp-support.c + ui-out.c utils.c ui-file.h ui-file.c \ + valarith.c valops.c valprint.c values.c varobj.c \ + wrapper.c LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -637,6 +637,7 @@ dcache_h = dcache.h defs_h = defs.h $(config_h) $(gdb_locale_h) $(gdb_signals_h) $(ansidecl_h) \ $(libiberty_h) $(progress_h) $(bfd_h) $(tui_h) $(ui_file_h) $(xm_h) \ $(nm_h) $(tm_h) $(fopen_same_h) $(gdbarch_h) $(arch_utils_h) +disasm_h = disasm.h doublest_h = doublest.h $(floatformat_h) dst_h = dst.h dwarf2cfi_h = dwarf2cfi.h @@ -827,7 +828,7 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_NO_SRCDIR) $(ALLDEPFILES) \ TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR) COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o regcache.o \ - charset.o \ + charset.o disasm.o \ source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \ symtab.o symfile.o symmisc.o linespec.o infcmd.o infrun.o \ expprint.o environ.o stack.o thread.o \ @@ -1617,6 +1618,8 @@ demangle.o: demangle.c $(defs_h) $(command_h) $(gdbcmd_h) $(demangle_h) \ $(gdb_string_h) dink32-rom.o: dink32-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ $(serial_h) $(symfile_h) $(inferior_h) $(regcache_h) +disasm.o: disasm.c $(defs_h) $(gdb_string_h) $(target_h) $(value_h) \ + $(disasm_h) $(ui_out_h) doublest.o: doublest.c $(defs_h) $(doublest_h) $(floatformat_h) \ $(gdb_assert_h) $(gdb_string_h) $(gdbtypes_h) dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) $(gdb_string_h) @@ -2374,7 +2377,7 @@ insight$(EXEEXT): gdbtk-main.o main.o libgdb.a $(CONFIG_OBS) $(ADD_DEPS) \ $(CDEPS) $(TDEPLIBS) rm -f insight$(EXEEXT) $(HLDENV) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \ - -o insight$(EXEEXT) gdbtk-main.o main.o libgdb.a $(CONFIG_OBS)\ + -o insight$(EXEEXT) gdbtk-main.o main.o $(CONFIG_OBS) libgdb.a \ $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) gdbres.o: $(srcdir)/gdbtk/gdb.rc $(srcdir)/gdbtk/gdbtool.ico @@ -2469,7 +2472,7 @@ mi-cmd-break.o: $(srcdir)/mi/mi-cmd-break.c $(defs_h) $(mi_cmds_h) \ $(mi_getopt_h) $(gdb_events_h) $(gdb_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-break.c mi-cmd-disas.o: $(srcdir)/mi/mi-cmd-disas.c $(defs_h) $(target_h) $(value_h) \ - $(mi_cmds_h) $(mi_getopt_h) $(ui_out_h) $(gdb_string_h) + $(mi_cmds_h) $(mi_getopt_h) $(ui_out_h) $(gdb_string_h) $(disasm_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/mi/mi-cmd-disas.c mi-cmd-stack.o: $(srcdir)/mi/mi-cmd-stack.c $(defs_h) $(target_h) $(frame_h) \ $(value_h) $(mi_cmds_h) $(ui_out_h) $(symtab_h) diff --git a/gdb/disasm.c b/gdb/disasm.c new file mode 100644 index 0000000..8ce9a15 --- /dev/null +++ b/gdb/disasm.c @@ -0,0 +1,374 @@ +/* Disassemble support for GDB. + Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "target.h" +#include "value.h" +#include "ui-out.h" +#include "gdb_string.h" + +#include "disasm.h" + +/* Disassemble functions. + FIXME: We should get rid of all the duplicate code in gdb that does + the same thing: disassemble_command() and the gdbtk variation. */ + +/* This Structure is used to store line number information. + We need a different sort of line table from the normal one cuz we can't + depend upon implicit line-end pc's for lines to do the + reordering in this function. */ + +struct dis_line_entry +{ + int line; + CORE_ADDR start_pc; + CORE_ADDR end_pc; +}; + +/* This variable determines where memory used for disassembly is read from. */ +int gdb_disassemble_from_exec = -1; + +/* This is the memory_read_func for gdb_disassemble when we are + disassembling from the exec file. */ +static int +gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, + unsigned int len, disassemble_info * info) +{ + extern struct target_ops exec_ops; + int res; + + errno = 0; + res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops); + + if (res == len) + return 0; + else if (errno == 0) + return EIO; + else + return errno; +} + +static int +compare_lines (const PTR mle1p, const PTR mle2p) +{ + struct dis_line_entry *mle1, *mle2; + int val; + + mle1 = (struct dis_line_entry *) mle1p; + mle2 = (struct dis_line_entry *) mle2p; + + val = mle1->line - mle2->line; + + if (val != 0) + return val; + + return mle1->start_pc - mle2->start_pc; +} + +static int +dump_insns (struct ui_out *uiout, disassemble_info * di, + CORE_ADDR low, CORE_ADDR high, + int how_many, struct ui_stream *stb) +{ + int num_displayed = 0; + CORE_ADDR pc; + + /* parts of the symbolic representation of the address */ + int unmapped; + char *filename = NULL; + char *name = NULL; + int offset; + int line; + + for (pc = low; pc < high;) + { + QUIT; + if (how_many >= 0) + { + if (num_displayed >= how_many) + break; + else + num_displayed++; + } + ui_out_tuple_begin (uiout, NULL); + ui_out_field_core_addr (uiout, "address", pc); + + if (!build_address_symbolic (pc, 0, &name, &offset, &filename, + &line, &unmapped)) + { + /* We don't care now about line, filename and + unmapped. But we might in the future. */ + ui_out_text (uiout, " <"); + ui_out_field_string (uiout, "func-name", name); + ui_out_text (uiout, "+"); + ui_out_field_int (uiout, "offset", offset); + ui_out_text (uiout, ">:\t"); + } + if (filename != NULL) + xfree (filename); + if (name != NULL) + xfree (name); + + ui_file_rewind (stb->stream); + pc += TARGET_PRINT_INSN (pc, di); + ui_out_field_stream (uiout, "inst", stb); + ui_file_rewind (stb->stream); + ui_out_tuple_end (uiout); + ui_out_text (uiout, "\n"); + } + return num_displayed; +} + +/* The idea here is to present a source-O-centric view of a + function to the user. This means that things are presented + in source order, with (possibly) out of order assembly + immediately following. */ +static void +do_mixed_source_and_assembly (struct ui_out *uiout, + struct disassemble_info *di, int nlines, + struct linetable_entry *le, + CORE_ADDR low, CORE_ADDR high, + struct symtab *symtab, + int how_many, struct ui_stream *stb) +{ + int newlines = 0; + struct dis_line_entry *mle; + struct symtab_and_line sal; + int i; + int out_of_order = 0; + int next_line = 0; + CORE_ADDR pc; + int num_displayed = 0; + + mle = (struct dis_line_entry *) alloca (nlines + * sizeof (struct dis_line_entry)); + + /* Copy linetable entries for this function into our data + structure, creating end_pc's and setting out_of_order as + appropriate. */ + + /* First, skip all the preceding functions. */ + + for (i = 0; i < nlines - 1 && le[i].pc < low; i++); + + /* Now, copy all entries before the end of this function. */ + + for (; i < nlines - 1 && le[i].pc < high; i++) + { + if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) + continue; /* Ignore duplicates */ + + /* Skip any end-of-function markers. */ + if (le[i].line == 0) + continue; + + mle[newlines].line = le[i].line; + if (le[i].line > le[i + 1].line) + out_of_order = 1; + mle[newlines].start_pc = le[i].pc; + mle[newlines].end_pc = le[i + 1].pc; + newlines++; + } + + /* If we're on the last line, and it's part of the function, + then we need to get the end pc in a special way. */ + + if (i == nlines - 1 && le[i].pc < high) + { + mle[newlines].line = le[i].line; + mle[newlines].start_pc = le[i].pc; + sal = find_pc_line (le[i].pc, 0); + mle[newlines].end_pc = sal.end; + newlines++; + } + + /* Now, sort mle by line #s (and, then by addresses within + lines). */ + + if (out_of_order) + qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); + + /* Now, for each line entry, emit the specified lines (unless + they have been emitted before), followed by the assembly code + for that line. */ + + ui_out_list_begin (uiout, "asm_insns"); + + for (i = 0; i < newlines; i++) + { + int close_list = 1; + /* Print out everything from next_line to the current line. */ + if (mle[i].line >= next_line) + { + if (next_line != 0) + { + /* Just one line to print. */ + if (next_line == mle[i].line) + { + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, next_line, mle[i].line + 1, 0); + } + else + { + /* Several source lines w/o asm instructions associated. */ + for (; next_line < mle[i].line; next_line++) + { + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, next_line, next_line + 1, + 0); + ui_out_list_begin (uiout, "line_asm_insn"); + ui_out_list_end (uiout); + ui_out_tuple_end (uiout); + } + /* Print the last line and leave list open for + asm instructions to be added. */ + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, next_line, mle[i].line + 1, 0); + } + } + else + { + ui_out_tuple_begin (uiout, "src_and_asm_line"); + print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); + } + + next_line = mle[i].line + 1; + ui_out_list_begin (uiout, "line_asm_insn"); + /* Don't close the list if the lines are not in order. */ + if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line) + close_list = 0; + } + + num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc, + how_many, stb); + if (close_list) + { + ui_out_list_end (uiout); + ui_out_tuple_end (uiout); + ui_out_text (uiout, "\n"); + close_list = 0; + } + if (how_many >= 0) + if (num_displayed >= how_many) + break; + } + ui_out_list_end (uiout); +} + + +static void +do_assembly_only (struct ui_out *uiout, disassemble_info * di, + CORE_ADDR low, CORE_ADDR high, + int how_many, struct ui_stream *stb) +{ + int num_displayed = 0; + + ui_out_list_begin (uiout, "asm_insns"); + + num_displayed = dump_insns (uiout, di, low, high, how_many, stb); + + ui_out_list_end (uiout); +} + +void +gdb_disassembly (struct ui_out *uiout, + char *file_string, + int line_num, + int mixed_source_and_assembly, + int how_many, CORE_ADDR low, CORE_ADDR high) +{ + static disassemble_info di; + static int di_initialized; + /* To collect the instruction outputted from opcodes. */ + static struct ui_stream *stb = NULL; + struct symtab *symtab = NULL; + struct linetable_entry *le = NULL; + int nlines = -1; + + if (!di_initialized) + { + /* We don't add a cleanup for this, because the allocation of + the stream is done once only for each gdb run, and we need to + keep it around until the end. Hopefully there won't be any + errors in the init code below, that make this function bail + out. */ + stb = ui_out_stream_new (uiout); + INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream, + (fprintf_ftype) fprintf_unfiltered); + di.flavour = bfd_target_unknown_flavour; + di.memory_error_func = dis_asm_memory_error; + di.print_address_func = dis_asm_print_address; + di_initialized = 1; + } + + di.mach = TARGET_PRINT_INSN_INFO->mach; + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + di.endian = BFD_ENDIAN_BIG; + else + di.endian = BFD_ENDIAN_LITTLE; + + /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to + determine whether or not to do disassembly from target memory or from the + exec file: + + If we're debugging a local process, read target memory, instead of the + exec file. This makes disassembly of functions in shared libs work + correctly. Also, read target memory if we are debugging native threads. + + Else, we're debugging a remote process, and should disassemble from the + exec file for speed. However, this is no good if the target modifies its + code (for relocation, or whatever). */ + + if (gdb_disassemble_from_exec == -1) + { + if (strcmp (target_shortname, "child") == 0 + || strcmp (target_shortname, "procfs") == 0 + || strcmp (target_shortname, "vxprocess") == 0 + || strstr (target_shortname, "-threads") != NULL) + gdb_disassemble_from_exec = 0; /* It's a child process, read inferior mem */ + else + gdb_disassemble_from_exec = 1; /* It's remote, read the exec file */ + } + + if (gdb_disassemble_from_exec) + di.read_memory_func = gdb_dis_asm_read_memory; + else + di.read_memory_func = dis_asm_read_memory; + + /* Assume symtab is valid for whole PC range */ + symtab = find_pc_symtab (low); + + if (symtab != NULL && symtab->linetable != NULL) + { + /* Convert the linetable to a bunch of my_line_entry's. */ + le = symtab->linetable->item; + nlines = symtab->linetable->nitems; + } + + if (!mixed_source_and_assembly || nlines <= 0 + || symtab == NULL || symtab->linetable == NULL) + do_assembly_only (uiout, &di, low, high, how_many, stb); + + else if (mixed_source_and_assembly) + do_mixed_source_and_assembly (uiout, &di, nlines, le, low, + high, symtab, how_many, stb); + + gdb_flush (gdb_stdout); +} diff --git a/gdb/disasm.h b/gdb/disasm.h new file mode 100644 index 0000000..beaaf4a --- /dev/null +++ b/gdb/disasm.h @@ -0,0 +1,29 @@ +/* Disassemble support for GDB. + Copyright 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef DISASM_H +#define DISASM_H + +extern void gdb_disassembly (struct ui_out *uiout, + char *file_string, + int line_num, + int mixed_source_and_assembly, + int how_many, CORE_ADDR low, CORE_ADDR high); +#endif diff --git a/gdb/mi/mi-cmd-disas.c b/gdb/mi/mi-cmd-disas.c index 85328d7..168ca17 100644 --- a/gdb/mi/mi-cmd-disas.c +++ b/gdb/mi/mi-cmd-disas.c @@ -24,353 +24,9 @@ #include "value.h" #include "mi-cmds.h" #include "mi-getopt.h" -#include "ui-out.h" #include "gdb_string.h" - -/* Disassemble functions. FIXME: these do not really belong here. We - should get rid of all the duplicate code in gdb that does the same - thing: disassemble_command() and the gdbtk variation. */ - -/* This Structure is used in mi_cmd_disassemble. - We need a different sort of line table from the normal one cuz we can't - depend upon implicit line-end pc's for lines to do the - reordering in this function. */ - -struct dis_line_entry -{ - int line; - CORE_ADDR start_pc; - CORE_ADDR end_pc; -}; - -/* This variable determines where memory used for disassembly is read from. */ -int gdb_disassemble_from_exec = -1; - -/* This is the memory_read_func for gdb_disassemble when we are - disassembling from the exec file. */ -static int -gdb_dis_asm_read_memory (bfd_vma memaddr, bfd_byte * myaddr, - unsigned int len, disassemble_info * info) -{ - extern struct target_ops exec_ops; - int res; - - errno = 0; - res = xfer_memory (memaddr, myaddr, len, 0, 0, &exec_ops); - - if (res == len) - return 0; - else if (errno == 0) - return EIO; - else - return errno; -} - -static int -compare_lines (const PTR mle1p, const PTR mle2p) -{ - struct dis_line_entry *mle1, *mle2; - int val; - - mle1 = (struct dis_line_entry *) mle1p; - mle2 = (struct dis_line_entry *) mle2p; - - val = mle1->line - mle2->line; - - if (val != 0) - return val; - - return mle1->start_pc - mle2->start_pc; -} - -static int -dump_insns (disassemble_info * di, CORE_ADDR low, CORE_ADDR high, - int how_many, struct ui_stream *stb) -{ - int num_displayed = 0; - CORE_ADDR pc; - - /* parts of the symbolic representation of the address */ - int unmapped; - char *filename = NULL; - char *name = NULL; - int offset; - int line; - - for (pc = low; pc < high;) - { - QUIT; - if (how_many >= 0) - { - if (num_displayed >= how_many) - break; - else - num_displayed++; - } - ui_out_tuple_begin (uiout, NULL); - ui_out_field_core_addr (uiout, "address", pc); - - if (!build_address_symbolic (pc, 0, &name, &offset, &filename, - &line, &unmapped)) - { - /* We don't care now about line, filename and - unmapped. But we might in the future. */ - ui_out_text (uiout, " <"); - ui_out_field_string (uiout, "func-name", name); - ui_out_text (uiout, "+"); - ui_out_field_int (uiout, "offset", offset); - ui_out_text (uiout, ">:\t"); - } - if (filename != NULL) - xfree (filename); - if (name != NULL) - xfree (name); - - ui_file_rewind (stb->stream); - pc += TARGET_PRINT_INSN (pc, di); - ui_out_field_stream (uiout, "inst", stb); - ui_file_rewind (stb->stream); - ui_out_tuple_end (uiout); - ui_out_text (uiout, "\n"); - } - return num_displayed; -} - -/* The idea here is to present a source-O-centric view of a - function to the user. This means that things are presented - in source order, with (possibly) out of order assembly - immediately following. */ -static void -do_mixed_source_and_assembly (struct disassemble_info *di, int nlines, - struct linetable_entry *le, - CORE_ADDR low, CORE_ADDR high, - struct symtab *symtab, - int how_many, struct ui_stream *stb) -{ - int newlines = 0; - struct dis_line_entry *mle; - struct symtab_and_line sal; - int i; - int out_of_order = 0; - int next_line = 0; - CORE_ADDR pc; - int num_displayed = 0; - - mle = (struct dis_line_entry *) alloca (nlines - * sizeof (struct dis_line_entry)); - - /* Copy linetable entries for this function into our data - structure, creating end_pc's and setting out_of_order as - appropriate. */ - - /* First, skip all the preceding functions. */ - - for (i = 0; i < nlines - 1 && le[i].pc < low; i++); - - /* Now, copy all entries before the end of this function. */ - - for (; i < nlines - 1 && le[i].pc < high; i++) - { - if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) - continue; /* Ignore duplicates */ - - /* Skip any end-of-function markers. */ - if (le[i].line == 0) - continue; - - mle[newlines].line = le[i].line; - if (le[i].line > le[i + 1].line) - out_of_order = 1; - mle[newlines].start_pc = le[i].pc; - mle[newlines].end_pc = le[i + 1].pc; - newlines++; - } - - /* If we're on the last line, and it's part of the function, - then we need to get the end pc in a special way. */ - - if (i == nlines - 1 && le[i].pc < high) - { - mle[newlines].line = le[i].line; - mle[newlines].start_pc = le[i].pc; - sal = find_pc_line (le[i].pc, 0); - mle[newlines].end_pc = sal.end; - newlines++; - } - - /* Now, sort mle by line #s (and, then by addresses within - lines). */ - - if (out_of_order) - qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); - - /* Now, for each line entry, emit the specified lines (unless - they have been emitted before), followed by the assembly code - for that line. */ - - ui_out_list_begin (uiout, "asm_insns"); - - for (i = 0; i < newlines; i++) - { - int close_list = 1; - /* Print out everything from next_line to the current line. */ - if (mle[i].line >= next_line) - { - if (next_line != 0) - { - /* Just one line to print. */ - if (next_line == mle[i].line) - { - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, next_line, mle[i].line + 1, 0); - } - else - { - /* Several source lines w/o asm instructions associated. */ - for (; next_line < mle[i].line; next_line++) - { - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, next_line, next_line + 1, - 0); - ui_out_list_begin (uiout, "line_asm_insn"); - ui_out_list_end (uiout); - ui_out_tuple_end (uiout); - } - /* Print the last line and leave list open for - asm instructions to be added. */ - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, next_line, mle[i].line + 1, 0); - } - } - else - { - ui_out_tuple_begin (uiout, "src_and_asm_line"); - print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); - } - - next_line = mle[i].line + 1; - ui_out_list_begin (uiout, "line_asm_insn"); - /* Don't close the list if the lines are not in order. */ - if (i < (newlines - 1) && mle[i + 1].line <= mle[i].line) - close_list = 0; - } - - num_displayed += dump_insns (di, mle[i].start_pc, mle[i].end_pc, - how_many, stb); - if (close_list) - { - ui_out_list_end (uiout); - ui_out_tuple_end (uiout); - ui_out_text (uiout, "\n"); - close_list = 0; - } - if (how_many >= 0) - if (num_displayed >= how_many) - break; - } - ui_out_list_end (uiout); -} - - -static void -do_assembly_only (disassemble_info * di, CORE_ADDR low, - CORE_ADDR high, int how_many, struct ui_stream *stb) -{ - int num_displayed = 0; - - ui_out_list_begin (uiout, "asm_insns"); - - num_displayed = dump_insns (di, low, high, how_many, stb); - - ui_out_list_end (uiout); -} - -enum mi_cmd_result -do_disassembly (char *file_string, - int line_num, - int mixed_source_and_assembly, - int how_many, CORE_ADDR low, CORE_ADDR high) -{ - static disassemble_info di; - static int di_initialized; - /* To collect the instruction outputted from opcodes. */ - static struct ui_stream *stb = NULL; - struct symtab *symtab = NULL; - struct linetable_entry *le = NULL; - int nlines = -1; - - if (!di_initialized) - { - /* We don't add a cleanup for this, because the allocation of - the stream is done once only for each gdb run, and we need to - keep it around until the end. Hopefully there won't be any - errors in the init code below, that make this function bail - out. */ - stb = ui_out_stream_new (uiout); - INIT_DISASSEMBLE_INFO_NO_ARCH (di, stb->stream, - (fprintf_ftype) fprintf_unfiltered); - di.flavour = bfd_target_unknown_flavour; - di.memory_error_func = dis_asm_memory_error; - di.print_address_func = dis_asm_print_address; - di_initialized = 1; - } - - di.mach = TARGET_PRINT_INSN_INFO->mach; - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) - di.endian = BFD_ENDIAN_BIG; - else - di.endian = BFD_ENDIAN_LITTLE; - - /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to - determine whether or not to do disassembly from target memory or from the - exec file: - - If we're debugging a local process, read target memory, instead of the - exec file. This makes disassembly of functions in shared libs work - correctly. Also, read target memory if we are debugging native threads. - - Else, we're debugging a remote process, and should disassemble from the - exec file for speed. However, this is no good if the target modifies its - code (for relocation, or whatever). */ - - if (gdb_disassemble_from_exec == -1) - { - if (strcmp (target_shortname, "child") == 0 - || strcmp (target_shortname, "procfs") == 0 - || strcmp (target_shortname, "vxprocess") == 0 - || strstr (target_shortname, "-threads") != NULL) - gdb_disassemble_from_exec = 0; /* It's a child process, read inferior mem */ - else - gdb_disassemble_from_exec = 1; /* It's remote, read the exec file */ - } - - if (gdb_disassemble_from_exec) - di.read_memory_func = gdb_dis_asm_read_memory; - else - di.read_memory_func = dis_asm_read_memory; - - /* Assume symtab is valid for whole PC range */ - symtab = find_pc_symtab (low); - - if (symtab != NULL && symtab->linetable != NULL) - { - /* Convert the linetable to a bunch of my_line_entry's. */ - le = symtab->linetable->item; - nlines = symtab->linetable->nitems; - } - - if (!mixed_source_and_assembly || nlines <= 0 - || symtab == NULL || symtab->linetable == NULL) - do_assembly_only (&di, low, high, how_many, stb); - - else if (mixed_source_and_assembly) - do_mixed_source_and_assembly (&di, nlines, le, low, - high, symtab, how_many, stb); - - gdb_flush (gdb_stdout); - - return MI_CMD_DONE; -} +#include "ui-out.h" +#include "disasm.h" /* The arguments to be passed on the command line and parsed here are: @@ -498,8 +154,10 @@ mi_cmd_disassemble (char *command, char **argv, int argc) error ("mi_cmd_disassemble: No function contains specified address"); } - retval = do_disassembly (file_string, - line_num, - mixed_source_and_assembly, how_many, low, high); - return retval; + gdb_disassembly (uiout, + file_string, + line_num, + mixed_source_and_assembly, how_many, low, high); + + return MI_CMD_DONE; } -- cgit v1.1