1130803Smarcel/* Disassemble support for GDB. 2130803Smarcel 3130803Smarcel Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel#include "defs.h" 23130803Smarcel#include "target.h" 24130803Smarcel#include "value.h" 25130803Smarcel#include "ui-out.h" 26130803Smarcel#include "gdb_string.h" 27130803Smarcel#include "disasm.h" 28130803Smarcel#include "gdbcore.h" 29130803Smarcel#include "dis-asm.h" 30130803Smarcel 31130803Smarcel/* Disassemble functions. 32130803Smarcel FIXME: We should get rid of all the duplicate code in gdb that does 33130803Smarcel the same thing: disassemble_command() and the gdbtk variation. */ 34130803Smarcel 35130803Smarcel/* This Structure is used to store line number information. 36130803Smarcel We need a different sort of line table from the normal one cuz we can't 37130803Smarcel depend upon implicit line-end pc's for lines to do the 38130803Smarcel reordering in this function. */ 39130803Smarcel 40130803Smarcelstruct dis_line_entry 41130803Smarcel{ 42130803Smarcel int line; 43130803Smarcel CORE_ADDR start_pc; 44130803Smarcel CORE_ADDR end_pc; 45130803Smarcel}; 46130803Smarcel 47130803Smarcel/* Like target_read_memory, but slightly different parameters. */ 48130803Smarcelstatic int 49130803Smarceldis_asm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int len, 50130803Smarcel struct disassemble_info *info) 51130803Smarcel{ 52130803Smarcel return target_read_memory (memaddr, (char *) myaddr, len); 53130803Smarcel} 54130803Smarcel 55130803Smarcel/* Like memory_error with slightly different parameters. */ 56130803Smarcelstatic void 57130803Smarceldis_asm_memory_error (int status, bfd_vma memaddr, 58130803Smarcel struct disassemble_info *info) 59130803Smarcel{ 60130803Smarcel memory_error (status, memaddr); 61130803Smarcel} 62130803Smarcel 63130803Smarcel/* Like print_address with slightly different parameters. */ 64130803Smarcelstatic void 65130803Smarceldis_asm_print_address (bfd_vma addr, struct disassemble_info *info) 66130803Smarcel{ 67130803Smarcel print_address (addr, info->stream); 68130803Smarcel} 69130803Smarcel 70130803Smarcelstatic int 71130803Smarcelcompare_lines (const void *mle1p, const void *mle2p) 72130803Smarcel{ 73130803Smarcel struct dis_line_entry *mle1, *mle2; 74130803Smarcel int val; 75130803Smarcel 76130803Smarcel mle1 = (struct dis_line_entry *) mle1p; 77130803Smarcel mle2 = (struct dis_line_entry *) mle2p; 78130803Smarcel 79130803Smarcel val = mle1->line - mle2->line; 80130803Smarcel 81130803Smarcel if (val != 0) 82130803Smarcel return val; 83130803Smarcel 84130803Smarcel return mle1->start_pc - mle2->start_pc; 85130803Smarcel} 86130803Smarcel 87130803Smarcelstatic int 88130803Smarceldump_insns (struct ui_out *uiout, struct disassemble_info * di, 89130803Smarcel CORE_ADDR low, CORE_ADDR high, 90130803Smarcel int how_many, struct ui_stream *stb) 91130803Smarcel{ 92130803Smarcel int num_displayed = 0; 93130803Smarcel CORE_ADDR pc; 94130803Smarcel 95130803Smarcel /* parts of the symbolic representation of the address */ 96130803Smarcel int unmapped; 97130803Smarcel int offset; 98130803Smarcel int line; 99130803Smarcel struct cleanup *ui_out_chain; 100130803Smarcel 101130803Smarcel for (pc = low; pc < high;) 102130803Smarcel { 103130803Smarcel char *filename = NULL; 104130803Smarcel char *name = NULL; 105130803Smarcel 106130803Smarcel QUIT; 107130803Smarcel if (how_many >= 0) 108130803Smarcel { 109130803Smarcel if (num_displayed >= how_many) 110130803Smarcel break; 111130803Smarcel else 112130803Smarcel num_displayed++; 113130803Smarcel } 114130803Smarcel ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); 115130803Smarcel ui_out_field_core_addr (uiout, "address", pc); 116130803Smarcel 117130803Smarcel if (!build_address_symbolic (pc, 0, &name, &offset, &filename, 118130803Smarcel &line, &unmapped)) 119130803Smarcel { 120130803Smarcel /* We don't care now about line, filename and 121130803Smarcel unmapped. But we might in the future. */ 122130803Smarcel ui_out_text (uiout, " <"); 123130803Smarcel ui_out_field_string (uiout, "func-name", name); 124130803Smarcel ui_out_text (uiout, "+"); 125130803Smarcel ui_out_field_int (uiout, "offset", offset); 126130803Smarcel ui_out_text (uiout, ">:\t"); 127130803Smarcel } 128130803Smarcel else 129130803Smarcel ui_out_text (uiout, ":\t"); 130130803Smarcel 131130803Smarcel if (filename != NULL) 132130803Smarcel xfree (filename); 133130803Smarcel if (name != NULL) 134130803Smarcel xfree (name); 135130803Smarcel 136130803Smarcel ui_file_rewind (stb->stream); 137130803Smarcel pc += TARGET_PRINT_INSN (pc, di); 138130803Smarcel ui_out_field_stream (uiout, "inst", stb); 139130803Smarcel ui_file_rewind (stb->stream); 140130803Smarcel do_cleanups (ui_out_chain); 141130803Smarcel ui_out_text (uiout, "\n"); 142130803Smarcel } 143130803Smarcel return num_displayed; 144130803Smarcel} 145130803Smarcel 146130803Smarcel/* The idea here is to present a source-O-centric view of a 147130803Smarcel function to the user. This means that things are presented 148130803Smarcel in source order, with (possibly) out of order assembly 149130803Smarcel immediately following. */ 150130803Smarcelstatic void 151130803Smarceldo_mixed_source_and_assembly (struct ui_out *uiout, 152130803Smarcel struct disassemble_info *di, int nlines, 153130803Smarcel struct linetable_entry *le, 154130803Smarcel CORE_ADDR low, CORE_ADDR high, 155130803Smarcel struct symtab *symtab, 156130803Smarcel int how_many, struct ui_stream *stb) 157130803Smarcel{ 158130803Smarcel int newlines = 0; 159130803Smarcel struct dis_line_entry *mle; 160130803Smarcel struct symtab_and_line sal; 161130803Smarcel int i; 162130803Smarcel int out_of_order = 0; 163130803Smarcel int next_line = 0; 164130803Smarcel CORE_ADDR pc; 165130803Smarcel int num_displayed = 0; 166130803Smarcel struct cleanup *ui_out_chain; 167130803Smarcel struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0); 168130803Smarcel struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0); 169130803Smarcel 170130803Smarcel mle = (struct dis_line_entry *) alloca (nlines 171130803Smarcel * sizeof (struct dis_line_entry)); 172130803Smarcel 173130803Smarcel /* Copy linetable entries for this function into our data 174130803Smarcel structure, creating end_pc's and setting out_of_order as 175130803Smarcel appropriate. */ 176130803Smarcel 177130803Smarcel /* First, skip all the preceding functions. */ 178130803Smarcel 179130803Smarcel for (i = 0; i < nlines - 1 && le[i].pc < low; i++); 180130803Smarcel 181130803Smarcel /* Now, copy all entries before the end of this function. */ 182130803Smarcel 183130803Smarcel for (; i < nlines - 1 && le[i].pc < high; i++) 184130803Smarcel { 185130803Smarcel if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) 186130803Smarcel continue; /* Ignore duplicates */ 187130803Smarcel 188130803Smarcel /* Skip any end-of-function markers. */ 189130803Smarcel if (le[i].line == 0) 190130803Smarcel continue; 191130803Smarcel 192130803Smarcel mle[newlines].line = le[i].line; 193130803Smarcel if (le[i].line > le[i + 1].line) 194130803Smarcel out_of_order = 1; 195130803Smarcel mle[newlines].start_pc = le[i].pc; 196130803Smarcel mle[newlines].end_pc = le[i + 1].pc; 197130803Smarcel newlines++; 198130803Smarcel } 199130803Smarcel 200130803Smarcel /* If we're on the last line, and it's part of the function, 201130803Smarcel then we need to get the end pc in a special way. */ 202130803Smarcel 203130803Smarcel if (i == nlines - 1 && le[i].pc < high) 204130803Smarcel { 205130803Smarcel mle[newlines].line = le[i].line; 206130803Smarcel mle[newlines].start_pc = le[i].pc; 207130803Smarcel sal = find_pc_line (le[i].pc, 0); 208130803Smarcel mle[newlines].end_pc = sal.end; 209130803Smarcel newlines++; 210130803Smarcel } 211130803Smarcel 212130803Smarcel /* Now, sort mle by line #s (and, then by addresses within 213130803Smarcel lines). */ 214130803Smarcel 215130803Smarcel if (out_of_order) 216130803Smarcel qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); 217130803Smarcel 218130803Smarcel /* Now, for each line entry, emit the specified lines (unless 219130803Smarcel they have been emitted before), followed by the assembly code 220130803Smarcel for that line. */ 221130803Smarcel 222130803Smarcel ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); 223130803Smarcel 224130803Smarcel for (i = 0; i < newlines; i++) 225130803Smarcel { 226130803Smarcel /* Print out everything from next_line to the current line. */ 227130803Smarcel if (mle[i].line >= next_line) 228130803Smarcel { 229130803Smarcel if (next_line != 0) 230130803Smarcel { 231130803Smarcel /* Just one line to print. */ 232130803Smarcel if (next_line == mle[i].line) 233130803Smarcel { 234130803Smarcel ui_out_tuple_chain 235130803Smarcel = make_cleanup_ui_out_tuple_begin_end (uiout, 236130803Smarcel "src_and_asm_line"); 237130803Smarcel print_source_lines (symtab, next_line, mle[i].line + 1, 0); 238130803Smarcel } 239130803Smarcel else 240130803Smarcel { 241130803Smarcel /* Several source lines w/o asm instructions associated. */ 242130803Smarcel for (; next_line < mle[i].line; next_line++) 243130803Smarcel { 244130803Smarcel struct cleanup *ui_out_list_chain_line; 245130803Smarcel struct cleanup *ui_out_tuple_chain_line; 246130803Smarcel 247130803Smarcel ui_out_tuple_chain_line 248130803Smarcel = make_cleanup_ui_out_tuple_begin_end (uiout, 249130803Smarcel "src_and_asm_line"); 250130803Smarcel print_source_lines (symtab, next_line, next_line + 1, 251130803Smarcel 0); 252130803Smarcel ui_out_list_chain_line 253130803Smarcel = make_cleanup_ui_out_list_begin_end (uiout, 254130803Smarcel "line_asm_insn"); 255130803Smarcel do_cleanups (ui_out_list_chain_line); 256130803Smarcel do_cleanups (ui_out_tuple_chain_line); 257130803Smarcel } 258130803Smarcel /* Print the last line and leave list open for 259130803Smarcel asm instructions to be added. */ 260130803Smarcel ui_out_tuple_chain 261130803Smarcel = make_cleanup_ui_out_tuple_begin_end (uiout, 262130803Smarcel "src_and_asm_line"); 263130803Smarcel print_source_lines (symtab, next_line, mle[i].line + 1, 0); 264130803Smarcel } 265130803Smarcel } 266130803Smarcel else 267130803Smarcel { 268130803Smarcel ui_out_tuple_chain 269130803Smarcel = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); 270130803Smarcel print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); 271130803Smarcel } 272130803Smarcel 273130803Smarcel next_line = mle[i].line + 1; 274130803Smarcel ui_out_list_chain 275130803Smarcel = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); 276130803Smarcel } 277130803Smarcel 278130803Smarcel num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc, 279130803Smarcel how_many, stb); 280130803Smarcel 281130803Smarcel /* When we've reached the end of the mle array, or we've seen the last 282130803Smarcel assembly range for this source line, close out the list/tuple. */ 283130803Smarcel if (i == (newlines - 1) || mle[i + 1].line > mle[i].line) 284130803Smarcel { 285130803Smarcel do_cleanups (ui_out_list_chain); 286130803Smarcel do_cleanups (ui_out_tuple_chain); 287130803Smarcel ui_out_tuple_chain = make_cleanup (null_cleanup, 0); 288130803Smarcel ui_out_list_chain = make_cleanup (null_cleanup, 0); 289130803Smarcel ui_out_text (uiout, "\n"); 290130803Smarcel } 291130803Smarcel if (how_many >= 0 && num_displayed >= how_many) 292130803Smarcel break; 293130803Smarcel } 294130803Smarcel do_cleanups (ui_out_chain); 295130803Smarcel} 296130803Smarcel 297130803Smarcel 298130803Smarcelstatic void 299130803Smarceldo_assembly_only (struct ui_out *uiout, struct disassemble_info * di, 300130803Smarcel CORE_ADDR low, CORE_ADDR high, 301130803Smarcel int how_many, struct ui_stream *stb) 302130803Smarcel{ 303130803Smarcel int num_displayed = 0; 304130803Smarcel struct cleanup *ui_out_chain; 305130803Smarcel 306130803Smarcel ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); 307130803Smarcel 308130803Smarcel num_displayed = dump_insns (uiout, di, low, high, how_many, stb); 309130803Smarcel 310130803Smarcel do_cleanups (ui_out_chain); 311130803Smarcel} 312130803Smarcel 313130803Smarcel/* Initialize the disassemble info struct ready for the specified 314130803Smarcel stream. */ 315130803Smarcel 316130803Smarcelstatic int 317130803Smarcelfprintf_disasm (void *stream, const char *format, ...) 318130803Smarcel{ 319130803Smarcel va_list args; 320130803Smarcel va_start (args, format); 321130803Smarcel vfprintf_filtered (stream, format, args); 322130803Smarcel va_end (args); 323130803Smarcel /* Something non -ve. */ 324130803Smarcel return 0; 325130803Smarcel} 326130803Smarcel 327130803Smarcelstatic struct disassemble_info 328130803Smarcelgdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) 329130803Smarcel{ 330130803Smarcel struct disassemble_info di; 331130803Smarcel init_disassemble_info (&di, file, fprintf_disasm); 332130803Smarcel di.flavour = bfd_target_unknown_flavour; 333130803Smarcel di.memory_error_func = dis_asm_memory_error; 334130803Smarcel di.print_address_func = dis_asm_print_address; 335130803Smarcel /* NOTE: cagney/2003-04-28: The original code, from the old Insight 336130803Smarcel disassembler had a local optomization here. By default it would 337130803Smarcel access the executable file, instead of the target memory (there 338130803Smarcel was a growing list of exceptions though). Unfortunately, the 339130803Smarcel heuristic was flawed. Commands like "disassemble &variable" 340130803Smarcel didn't work as they relied on the access going to the target. 341130803Smarcel Further, it has been supperseeded by trust-read-only-sections 342130803Smarcel (although that should be superseeded by target_trust..._p()). */ 343130803Smarcel di.read_memory_func = dis_asm_read_memory; 344130803Smarcel di.arch = gdbarch_bfd_arch_info (gdbarch)->arch; 345130803Smarcel di.mach = gdbarch_bfd_arch_info (gdbarch)->mach; 346130803Smarcel di.endian = gdbarch_byte_order (gdbarch); 347130803Smarcel return di; 348130803Smarcel} 349130803Smarcel 350130803Smarcelvoid 351130803Smarcelgdb_disassembly (struct ui_out *uiout, 352130803Smarcel char *file_string, 353130803Smarcel int line_num, 354130803Smarcel int mixed_source_and_assembly, 355130803Smarcel int how_many, CORE_ADDR low, CORE_ADDR high) 356130803Smarcel{ 357130803Smarcel struct ui_stream *stb = ui_out_stream_new (uiout); 358130803Smarcel struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); 359130803Smarcel struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stb->stream); 360130803Smarcel /* To collect the instruction outputted from opcodes. */ 361130803Smarcel struct symtab *symtab = NULL; 362130803Smarcel struct linetable_entry *le = NULL; 363130803Smarcel int nlines = -1; 364130803Smarcel 365130803Smarcel /* Assume symtab is valid for whole PC range */ 366130803Smarcel symtab = find_pc_symtab (low); 367130803Smarcel 368130803Smarcel if (symtab != NULL && symtab->linetable != NULL) 369130803Smarcel { 370130803Smarcel /* Convert the linetable to a bunch of my_line_entry's. */ 371130803Smarcel le = symtab->linetable->item; 372130803Smarcel nlines = symtab->linetable->nitems; 373130803Smarcel } 374130803Smarcel 375130803Smarcel if (!mixed_source_and_assembly || nlines <= 0 376130803Smarcel || symtab == NULL || symtab->linetable == NULL) 377130803Smarcel do_assembly_only (uiout, &di, low, high, how_many, stb); 378130803Smarcel 379130803Smarcel else if (mixed_source_and_assembly) 380130803Smarcel do_mixed_source_and_assembly (uiout, &di, nlines, le, low, 381130803Smarcel high, symtab, how_many, stb); 382130803Smarcel 383130803Smarcel do_cleanups (cleanups); 384130803Smarcel gdb_flush (gdb_stdout); 385130803Smarcel} 386130803Smarcel 387130803Smarcel/* Print the instruction at address MEMADDR in debugged memory, 388130803Smarcel on STREAM. Returns length of the instruction, in bytes. */ 389130803Smarcel 390130803Smarcelint 391130803Smarcelgdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream) 392130803Smarcel{ 393130803Smarcel struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream); 394130803Smarcel return TARGET_PRINT_INSN (memaddr, &di); 395130803Smarcel} 396