static int dump_insns(struct ui_out *uiout, struct 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; int offset; int line; struct cleanup *ui_out_chain; for (pc = low; pc < high;) { char *filename = NULL; char *name = NULL; QUIT; if (how_many >= 0) { if (num_displayed >= how_many) break; else num_displayed++; } ui_out_chain = make_cleanup_ui_out_tuple_begin_end (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"); } else 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); do_cleanups (ui_out_chain); ui_out_text (uiout, "\n"); } return num_displayed; }
int gdb_print_insn (CORE_ADDR memaddr, struct ui_file *stream) { struct ui_stream *stb = ui_out_stream_new (uiout); struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stb->stream); // struct disassemble_info di = gdb_disassemble_info (current_gdbarch, stream); struct disassemble_info * di2 = &di; struct cleanup *ui_out_chain; ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); int i; CORE_ADDR old_pc = memaddr; CORE_ADDR oldmemaddr = memaddr; bfd_byte data; int status; ui_file_rewind (stb->stream); memaddr = TARGET_PRINT_INSN (memaddr, &di); oldmemaddr += memaddr; for (; old_pc < oldmemaddr; old_pc ++) { status = (*di2->read_memory_func) (old_pc, &data, 1, di2); if (status != 0) (*di2->memory_error_func) (status, old_pc, di2); ui_out_message (uiout, 0, " %02x", (unsigned)data); } i = memaddr; for (; i<10; i++) ui_out_text(uiout, " "); ui_out_text (uiout, " "); ui_out_field_stream(uiout, "inst", stb); ui_file_rewind (stb->stream); do_cleanups (ui_out_chain); return memaddr; // return TARGET_PRINT_INSN (memaddr, &di); }
int gdb_print_insn(CORE_ADDR memaddr, struct ui_file *stream) { struct disassemble_info di = gdb_disassemble_info(current_gdbarch, stream); return TARGET_PRINT_INSN(memaddr, &di); }
int find_pc_offset(CORE_ADDR start, CORE_ADDR *result, int offset, int funclimit, int peeklimit) { CORE_ADDR low = INVALID_ADDRESS; CORE_ADDR high = INVALID_ADDRESS; CORE_ADDR cur; CORE_ADDR constrained; int length; struct disassemble_info di = gdb_disassemble_info_null(current_gdbarch); CORE_ADDR *addrs = NULL; unsigned int index; struct cleanup *cleanup = NULL; *result = INVALID_ADDRESS; cur = start; /* If we are constraining the address to stay in the same function, we need to be able to find its boundaries. */ if (funclimit) { if (find_pc_partial_function_no_inlined(start, NULL, &low, &high) == 0) { /* We were unable to find the start of the function. */ return -1; } } /* If the architecture has fixed-sized instructions, just use simple arithmetic. */ length = gdbarch_instruction_length(current_gdbarch); if (length > 0) { cur = (start + (length * offset)); /* Constrain to be within the function limits if appropriate. */ if (funclimit && (cur > high)) constrained = high; else if (funclimit && (cur < low)) constrained = low; else constrained = cur; /* Return 1 if we constrained the address; 0 otherwise. */ *result = constrained; return (constrained != cur); } /* From here, we must assume variable-sized instructions. */ if ((! funclimit) && (offset < 0)) { /* FIXME: We don't support seeking backwards past the beginning of a function. */ return -1; } /* If we have a positive offset, start seeking forward until we are either done, or reach the end of the function. */ cur = start; while (offset > 0) { cur += TARGET_PRINT_INSN(cur, &di); offset--; if (funclimit && (cur > high)) { /* We went past the end of the function without ever reaching the purportedly final instruction. */ return -1; } if (funclimit && (cur == high)) { /* We reached the end of the function. Return 1 if we had to constrain the address; 0 otherwise. */ *result = cur; return (offset > 0); } } if (offset == 0) { *result = cur; return 0; } /* From here out we can assume we are doing a negative offset. */ gdb_assert(low <= start); gdb_assert(offset < 0); /* A sanity check: If we've stepped into some area of memory where gdb doesn't have symbols and the GUI requests we disassemble from $pc, gdb can come up with very large LOW-HIGH regions of memory to disassemble through. As a sanity check, if this function starts four pages before the given $pc and we're in MI mode (so we have a GUI that may be requesting nonsensical things), shortcircuit this operation. */ if (((off_t)(start - low) > -offset) && ((start - low) > 16384) && ui_out_is_mi_like_p(uiout)) { *result = start; return 1; } /* There's no point searching for more instructions slots than there are bytes. If we were given a PEEKLIMIT of -1, or a PEEKLIMIT higher than we need, set it to the number of bytes from the start of the function. */ if ((peeklimit < 0) || ((CORE_ADDR)peeklimit > (start - low))) peeklimit = (int)(start - low); /* If PEEKLIMIT is less than (start - low), we can still attempt the search --- maybe enough of the instruction stream will be multi-byte that we'll find our address regardless. */ addrs = (CORE_ADDR *)xmalloc(peeklimit * sizeof(CORE_ADDR)); cleanup = make_cleanup(xfree, addrs); /* We can assume that we are constrained to the current function at this point (see the comment above). */ gdb_assert(funclimit); cur = low; index = 0; /* Seek forward until we either reach our starting point, or reach PEEKLIMIT. */ for (;;) { if (cur >= start) break; if (index >= (unsigned int)peeklimit) break; gdb_assert((int)index < peeklimit); addrs[index++] = cur; cur += TARGET_PRINT_INSN(cur, &di); } if (cur == start) { /* We were able to seek all the way forward to the start address. */ gdb_assert(funclimit); gdb_assert(offset < 0); if ((off_t)index < -offset) { /* We weren't able to go far enough back; return the earliest instruction of the function. */ *result = low; do_cleanups(cleanup); return 1; } else { *result = addrs[index + offset]; do_cleanups(cleanup); return 0; } } if (cur > start) { /* We seeked forward right past the start address, without ever hitting it. */ do_cleanups(cleanup); return -1; } if (index >= (unsigned int)peeklimit) { /* We went past PEEKLIMIT instructions, and hence, weren't able to complete the backwards seek. */ do_cleanups(cleanup); return -1; } internal_error(__FILE__, __LINE__, "should never have reached here"); do_cleanups(cleanup); return -1; }
static int dump_insns (struct ui_out *uiout, struct 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; int offset; int line; struct cleanup *ui_out_chain; struct cleanup *table_chain; struct cleanup *tuple_chain; for (pc = low; pc < high;) { char *filename = NULL; char *name = NULL; QUIT; if (how_many >= 0) { if (num_displayed >= how_many) break; else num_displayed++; } ui_out_chain = make_cleanup_ui_out_tuple_begin_end (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, ">: "); } else ui_out_text (uiout, ": "); if (filename != NULL) xfree (filename); if (name != NULL) xfree (name); ui_file_rewind (stb->stream); // dump the disassembly raw bytes - ripped from gnu gdb latest cvs version // fG! - 12/08/2009 // save the initial disassembly address CORE_ADDR old_pc = pc; bfd_byte data; int status; int i; // this will return the disassembled instructions, but it will be buffered into the stream // pc will hold the final address after the disassembly, so we can compute the length of the instruction // the macro returns the number of bytes disassembled pc += TARGET_PRINT_INSN (pc, di); i = pc - old_pc; // read the bytes from the initial address to the final address for (; old_pc < pc; old_pc++) { status = (*di->read_memory_func) (old_pc, &data, 1, di); if (status != 0) (*di->memory_error_func) (status, old_pc, di); // print the raw bytes ui_out_message (uiout, 0, " %02x", (unsigned)data); } // to align the output... gdb tables don't work correctly :( for (; i < 10 ; i++) ui_out_text(uiout, " "); ui_out_text(uiout, " "); // now we can finally print the buffered stream ui_out_field_stream (uiout, "inst", stb); ui_file_rewind (stb->stream); do_cleanups (ui_out_chain); ui_out_text (uiout, "\n"); } return num_displayed; }