1187767Sluigi/* Disassemble support for GDB. 2187767Sluigi 3187767Sluigi Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 4187767Sluigi 5187767Sluigi This file is part of GDB. 6187767Sluigi 7187767Sluigi This program is free software; you can redistribute it and/or modify 8187767Sluigi it under the terms of the GNU General Public License as published by 9187767Sluigi the Free Software Foundation; either version 2 of the License, or 10187767Sluigi (at your option) any later version. 11187767Sluigi 12187767Sluigi This program is distributed in the hope that it will be useful, 13187767Sluigi but WITHOUT ANY WARRANTY; without even the implied warranty of 14187767Sluigi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15187767Sluigi GNU General Public License for more details. 16187767Sluigi 17187767Sluigi You should have received a copy of the GNU General Public License 18187767Sluigi along with this program; if not, write to the Free Software 19187767Sluigi Foundation, Inc., 59 Temple Place - Suite 330, 20187767Sluigi Boston, MA 02111-1307, USA. */ 21187767Sluigi 22187767Sluigi#include "defs.h" 23187767Sluigi#include "target.h" 24187767Sluigi#include "value.h" 25187767Sluigi#include "ui-out.h" 26187767Sluigi#include "gdb_string.h" 27187767Sluigi#include "disasm.h" 28187767Sluigi#include "gdbcore.h" 29187767Sluigi#include "dis-asm.h" 30187767Sluigi 31187767Sluigi/* Disassemble functions. 32187767Sluigi FIXME: We should get rid of all the duplicate code in gdb that does 33187767Sluigi the same thing: disassemble_command() and the gdbtk variation. */ 34187767Sluigi 35187767Sluigi/* This Structure is used to store line number information. 36187767Sluigi We need a different sort of line table from the normal one cuz we can't 37187767Sluigi depend upon implicit line-end pc's for lines to do the 38204591Sluigi reordering in this function. */ 39187767Sluigi 40187767Sluigistruct dis_line_entry 41187767Sluigi{ 42187767Sluigi int line; 43187767Sluigi CORE_ADDR start_pc; 44187767Sluigi CORE_ADDR end_pc; 45187767Sluigi}; 46187767Sluigi 47187767Sluigi/* Like target_read_memory, but slightly different parameters. */ 48187767Sluigistatic int 49187767Sluigidis_asm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int len, 50187767Sluigi struct disassemble_info *info) 51187767Sluigi{ 52187767Sluigi return target_read_memory (memaddr, (char *) myaddr, len); 53187767Sluigi} 54187767Sluigi 55187767Sluigi/* Like memory_error with slightly different parameters. */ 56187767Sluigistatic void 57187767Sluigidis_asm_memory_error (int status, bfd_vma memaddr, 58187767Sluigi struct disassemble_info *info) 59187767Sluigi{ 60187767Sluigi memory_error (status, memaddr); 61187767Sluigi} 62187767Sluigi 63187767Sluigi/* Like print_address with slightly different parameters. */ 64187767Sluigistatic void 65187767Sluigidis_asm_print_address (bfd_vma addr, struct disassemble_info *info) 66187767Sluigi{ 67187767Sluigi print_address (addr, info->stream); 68187767Sluigi} 69187767Sluigi 70187767Sluigistatic int 71187767Sluigicompare_lines (const void *mle1p, const void *mle2p) 72187767Sluigi{ 73187767Sluigi struct dis_line_entry *mle1, *mle2; 74270424Smelifaro int val; 75270424Smelifaro 76187769Sluigi mle1 = (struct dis_line_entry *) mle1p; 77187769Sluigi mle2 = (struct dis_line_entry *) mle2p; 78187769Sluigi 79187769Sluigi val = mle1->line - mle2->line; 80187769Sluigi 81187769Sluigi if (val != 0) 82187769Sluigi return val; 83187769Sluigi 84187769Sluigi return mle1->start_pc - mle2->start_pc; 85187769Sluigi} 86298016Sae 87187769Sluigistatic int 88204591Sluigidump_insns (struct ui_out *uiout, struct disassemble_info * di, 89187769Sluigi CORE_ADDR low, CORE_ADDR high, 90204591Sluigi int how_many, struct ui_stream *stb) 91204591Sluigi{ 92187769Sluigi int num_displayed = 0; 93187769Sluigi CORE_ADDR pc; 94187769Sluigi 95187769Sluigi /* parts of the symbolic representation of the address */ 96187769Sluigi int unmapped; 97187769Sluigi int offset; 98187769Sluigi int line; 99187769Sluigi struct cleanup *ui_out_chain; 100187769Sluigi 101187769Sluigi for (pc = low; pc < high;) 102187769Sluigi { 103187769Sluigi char *filename = NULL; 104190633Spiso char *name = NULL; 105223666Sae 106223666Sae QUIT; 107187769Sluigi if (how_many >= 0) 108187769Sluigi { 109187769Sluigi if (num_displayed >= how_many) 110187769Sluigi break; 111187769Sluigi else 112187769Sluigi num_displayed++; 113187769Sluigi } 114187769Sluigi ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); 115187769Sluigi ui_out_field_core_addr (uiout, "address", pc); 116187769Sluigi 117187769Sluigi if (!build_address_symbolic (pc, 0, &name, &offset, &filename, 118187769Sluigi &line, &unmapped)) 119187769Sluigi { 120187769Sluigi /* We don't care now about line, filename and 121187769Sluigi unmapped. But we might in the future. */ 122187769Sluigi ui_out_text (uiout, " <"); 123187769Sluigi ui_out_field_string (uiout, "func-name", name); 124187769Sluigi ui_out_text (uiout, "+"); 125187769Sluigi ui_out_field_int (uiout, "offset", offset); 126187769Sluigi ui_out_text (uiout, ">:\t"); 127187769Sluigi } 128187769Sluigi else 129187769Sluigi ui_out_text (uiout, ":\t"); 130187769Sluigi 131187769Sluigi if (filename != NULL) 132187769Sluigi xfree (filename); 133205169Sluigi if (name != NULL) 134187769Sluigi xfree (name); 135187769Sluigi 136187769Sluigi ui_file_rewind (stb->stream); 137187769Sluigi pc += TARGET_PRINT_INSN (pc, di); 138187769Sluigi ui_out_field_stream (uiout, "inst", stb); 139187769Sluigi ui_file_rewind (stb->stream); 140187769Sluigi do_cleanups (ui_out_chain); 141187769Sluigi ui_out_text (uiout, "\n"); 142187769Sluigi } 143187769Sluigi return num_displayed; 144187769Sluigi} 145187769Sluigi 146187769Sluigi/* The idea here is to present a source-O-centric view of a 147187769Sluigi function to the user. This means that things are presented 148187769Sluigi in source order, with (possibly) out of order assembly 149187769Sluigi immediately following. */ 150187769Sluigistatic void 151187769Sluigido_mixed_source_and_assembly (struct ui_out *uiout, 152187769Sluigi struct disassemble_info *di, int nlines, 153187769Sluigi struct linetable_entry *le, 154187769Sluigi CORE_ADDR low, CORE_ADDR high, 155187769Sluigi struct symtab *symtab, 156187769Sluigi int how_many, struct ui_stream *stb) 157187769Sluigi{ 158187769Sluigi int newlines = 0; 159187769Sluigi struct dis_line_entry *mle; 160187769Sluigi struct symtab_and_line sal; 161187769Sluigi int i; 162187769Sluigi int out_of_order = 0; 163204591Sluigi int next_line = 0; 164204591Sluigi CORE_ADDR pc; 165187769Sluigi int num_displayed = 0; 166187769Sluigi struct cleanup *ui_out_chain; 167204591Sluigi struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0); 168194930Soleg struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0); 169187769Sluigi 170187769Sluigi mle = (struct dis_line_entry *) alloca (nlines 171266941Shiren * sizeof (struct dis_line_entry)); 172187769Sluigi 173187769Sluigi /* Copy linetable entries for this function into our data 174300779Struckman structure, creating end_pc's and setting out_of_order as 175300779Struckman appropriate. */ 176300779Struckman 177300779Struckman /* First, skip all the preceding functions. */ 178300779Struckman 179300779Struckman for (i = 0; i < nlines - 1 && le[i].pc < low; i++); 180300779Struckman 181300779Struckman /* Now, copy all entries before the end of this function. */ 182300779Struckman 183300779Struckman for (; i < nlines - 1 && le[i].pc < high; i++) 184300779Struckman { 185300779Struckman if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) 186300779Struckman continue; /* Ignore duplicates */ 187300779Struckman 188300779Struckman /* Skip any end-of-function markers. */ 189300779Struckman if (le[i].line == 0) 190300779Struckman continue; 191300779Struckman 192300779Struckman mle[newlines].line = le[i].line; 193300779Struckman if (le[i].line > le[i + 1].line) 194300779Struckman out_of_order = 1; 195300779Struckman mle[newlines].start_pc = le[i].pc; 196300779Struckman mle[newlines].end_pc = le[i + 1].pc; 197300779Struckman newlines++; 198300779Struckman } 199204591Sluigi 200187769Sluigi /* If we're on the last line, and it's part of the function, 201204591Sluigi then we need to get the end pc in a special way. */ 202204591Sluigi 203204591Sluigi if (i == nlines - 1 && le[i].pc < high) 204204591Sluigi { 205204591Sluigi mle[newlines].line = le[i].line; 206187769Sluigi mle[newlines].start_pc = le[i].pc; 207187769Sluigi sal = find_pc_line (le[i].pc, 0); 208187769Sluigi mle[newlines].end_pc = sal.end; 209187769Sluigi newlines++; 210187769Sluigi } 211187769Sluigi 212223080Sae /* Now, sort mle by line #s (and, then by addresses within 213187769Sluigi lines). */ 214187769Sluigi 215187769Sluigi if (out_of_order) 216187769Sluigi qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); 217187769Sluigi 218220804Sglebius /* Now, for each line entry, emit the specified lines (unless 219187769Sluigi they have been emitted before), followed by the assembly code 220187769Sluigi for that line. */ 221187769Sluigi 222187769Sluigi ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); 223187769Sluigi 224187769Sluigi for (i = 0; i < newlines; i++) 225187769Sluigi { 226187769Sluigi /* Print out everything from next_line to the current line. */ 227187769Sluigi if (mle[i].line >= next_line) 228187769Sluigi { 229187769Sluigi if (next_line != 0) 230187769Sluigi { 231187769Sluigi /* Just one line to print. */ 232187769Sluigi if (next_line == mle[i].line) 233200567Sluigi { 234215179Sluigi ui_out_tuple_chain 235248552Smelifaro = make_cleanup_ui_out_tuple_begin_end (uiout, 236272840Smelifaro "src_and_asm_line"); 237272840Smelifaro print_source_lines (symtab, next_line, mle[i].line + 1, 0); 238272840Smelifaro } 239272840Smelifaro else 240272840Smelifaro { 241272840Smelifaro /* Several source lines w/o asm instructions associated. */ 242272840Smelifaro for (; next_line < mle[i].line; next_line++) 243272840Smelifaro { 244272840Smelifaro struct cleanup *ui_out_list_chain_line; 245272840Smelifaro struct cleanup *ui_out_tuple_chain_line; 246272840Smelifaro 247272840Smelifaro ui_out_tuple_chain_line 248272840Smelifaro = make_cleanup_ui_out_tuple_begin_end (uiout, 249272840Smelifaro "src_and_asm_line"); 250272840Smelifaro print_source_lines (symtab, next_line, next_line + 1, 251272840Smelifaro 0); 252272840Smelifaro ui_out_list_chain_line 253272840Smelifaro = make_cleanup_ui_out_list_begin_end (uiout, 254272840Smelifaro "line_asm_insn"); 255272840Smelifaro do_cleanups (ui_out_list_chain_line); 256290330Sae do_cleanups (ui_out_tuple_chain_line); 257187769Sluigi } 258272840Smelifaro /* Print the last line and leave list open for 259187767Sluigi asm instructions to be added. */ 260187767Sluigi ui_out_tuple_chain 261187767Sluigi = make_cleanup_ui_out_tuple_begin_end (uiout, 262187767Sluigi "src_and_asm_line"); 263204591Sluigi print_source_lines (symtab, next_line, mle[i].line + 1, 0); 264204591Sluigi } 265187767Sluigi } 266270424Smelifaro else 267270424Smelifaro { 268270424Smelifaro ui_out_tuple_chain 269270424Smelifaro = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line"); 270270424Smelifaro print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); 271270424Smelifaro } 272270424Smelifaro 273187787Sluigi next_line = mle[i].line + 1; 274270424Smelifaro ui_out_list_chain 275270424Smelifaro = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); 276270424Smelifaro } 277270424Smelifaro 278270424Smelifaro num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc, 279270424Smelifaro how_many, stb); 280187767Sluigi 281187767Sluigi /* When we've reached the end of the mle array, or we've seen the last 282187767Sluigi assembly range for this source line, close out the list/tuple. */ 283187767Sluigi if (i == (newlines - 1) || mle[i + 1].line > mle[i].line) 284187770Sluigi { 285187767Sluigi do_cleanups (ui_out_list_chain); 286187769Sluigi do_cleanups (ui_out_tuple_chain); 287272840Smelifaro ui_out_tuple_chain = make_cleanup (null_cleanup, 0); 288187767Sluigi ui_out_list_chain = make_cleanup (null_cleanup, 0); 289187770Sluigi ui_out_text (uiout, "\n"); 290298016Sae } 291298016Sae if (how_many >= 0 && num_displayed >= how_many) 292298016Sae break; 293187770Sluigi } 294272840Smelifaro do_cleanups (ui_out_chain); 295272840Smelifaro} 296272840Smelifaro 297272840Smelifaro 298272840Smelifarostatic void 299187770Sluigido_assembly_only (struct ui_out *uiout, struct disassemble_info * di, 300272840Smelifaro CORE_ADDR low, CORE_ADDR high, 301187769Sluigi int how_many, struct ui_stream *stb) 302272840Smelifaro{ 303272840Smelifaro int num_displayed = 0; 304187769Sluigi struct cleanup *ui_out_chain; 305187769Sluigi 306187769Sluigi ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); 307187770Sluigi 308187769Sluigi num_displayed = dump_insns (uiout, di, low, high, how_many, stb); 309187819Sluigi 310187819Sluigi do_cleanups (ui_out_chain); 311187819Sluigi} 312187819Sluigi 313187819Sluigi/* Initialize the disassemble info struct ready for the specified 314187819Sluigi stream. */ 315187819Sluigi 316187819Sluigistatic int 317187819Sluigifprintf_disasm (void *stream, const char *format, ...) 318187983Sluigi{ 319187819Sluigi va_list args; 320187819Sluigi va_start (args, format); 321187819Sluigi vfprintf_filtered (stream, format, args); 322187769Sluigi va_end (args); 323187767Sluigi /* Something non -ve. */ 324187767Sluigi return 0; 325187767Sluigi} 326187767Sluigi 327187767Sluigistatic struct disassemble_info 328187767Sluigigdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) 329187767Sluigi{ 330187770Sluigi struct disassemble_info di; 331204591Sluigi init_disassemble_info (&di, file, fprintf_disasm); 332187767Sluigi di.flavour = bfd_target_unknown_flavour; 333187767Sluigi di.memory_error_func = dis_asm_memory_error; 334187767Sluigi di.print_address_func = dis_asm_print_address; 335204591Sluigi /* NOTE: cagney/2003-04-28: The original code, from the old Insight 336187767Sluigi disassembler had a local optomization here. By default it would 337204591Sluigi access the executable file, instead of the target memory (there 338204591Sluigi was a growing list of exceptions though). Unfortunately, the 339187767Sluigi heuristic was flawed. Commands like "disassemble &variable" 340187767Sluigi didn't work as they relied on the access going to the target. 341187767Sluigi Further, it has been supperseeded by trust-read-only-sections 342272840Smelifaro (although that should be superseeded by target_trust..._p()). */ 343298016Sae di.read_memory_func = dis_asm_read_memory; 344187767Sluigi di.arch = gdbarch_bfd_arch_info (gdbarch)->arch; 345261797Sglebius di.mach = gdbarch_bfd_arch_info (gdbarch)->mach; 346187983Sluigi di.endian = gdbarch_byte_order (gdbarch); 347187983Sluigi return di; 348187983Sluigi} 349270424Smelifaro 350261797Sglebiusvoid 351261797Sglebiusgdb_disassembly (struct ui_out *uiout, 352261797Sglebius char *file_string, 353187983Sluigi int line_num, 354187770Sluigi int mixed_source_and_assembly, 355204591Sluigi int how_many, CORE_ADDR low, CORE_ADDR high) 356204591Sluigi{ 357187769Sluigi struct ui_stream *stb = ui_out_stream_new (uiout); 358187769Sluigi struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); 359187770Sluigi struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stb->stream); 360297981Sae /* To collect the instruction outputted from opcodes. */ 361270424Smelifaro struct symtab *symtab = NULL; 362270424Smelifaro struct linetable_entry *le = NULL; 363270424Smelifaro int nlines = -1; 364270424Smelifaro 365187770Sluigi /* Assume symtab is valid for whole PC range */ 366247712Smelifaro symtab = find_pc_symtab (low); 367247712Smelifaro 368187770Sluigi if (symtab != NULL && symtab->linetable != NULL) 369247712Smelifaro { 370187770Sluigi /* Convert the linetable to a bunch of my_line_entry's. */ 371247712Smelifaro le = symtab->linetable->item; 372187819Sluigi nlines = symtab->linetable->nitems; 373272840Smelifaro } 374302979Sae 375302979Sae if (!mixed_source_and_assembly || nlines <= 0 376302979Sae || symtab == NULL || symtab->linetable == NULL) 377272840Smelifaro do_assembly_only (uiout, &di, low, high, how_many, stb); 378272840Smelifaro 379298016Sae else if (mixed_source_and_assembly) 380272840Smelifaro do_mixed_source_and_assembly (uiout, &di, nlines, le, low, 381272840Smelifaro high, symtab, how_many, stb); 382272840Smelifaro 383 do_cleanups (cleanups); 384 gdb_flush (gdb_stdout); 385} 386 387/* Print the instruction at address MEMADDR in debugged memory, 388 on STREAM. Returns length of the instruction, in bytes. */ 389 390int 391gdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream) 392{ 393 struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream); 394 return TARGET_PRINT_INSN (memaddr, &di); 395} 396