예제 #1
0
파일: disasm.c 프로젝트: HoMeCracKeR/gdb-ng
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);
}
예제 #2
0
파일: disasm.c 프로젝트: GunioRobot/macgdb
static int
dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
	    struct disassemble_info * di,
	    CORE_ADDR low, CORE_ADDR high,
	    int how_many, int flags, 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", gdbarch, 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);
      if (flags & DISASSEMBLY_RAW_INSN)
        {
          CORE_ADDR old_pc = pc;
          bfd_byte data;
          int status;
          pc += gdbarch_print_insn (gdbarch, pc, di);
          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);
              ui_out_message (uiout, 0, " %02x", (unsigned)data);
            }
          ui_out_text (uiout, "\t");
        }
      else
        pc += gdbarch_print_insn (gdbarch, 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;
}
예제 #3
0
/*
 * Display a disassembled instruction with annotation
 */
static void print_one_insn(struct ca_dis_insn* insn, struct ui_out* uiout)
{
	int i, pos;
	struct ca_operand* dst_op;

	ui_out_text(uiout, insn->dis_string);

	pos = strlen(insn->dis_string);
	if (pos < MAX_SPACING)
		ui_out_spaces(uiout, MAX_SPACING - pos);
	ui_out_text(uiout, " ## ");

	if (insn->num_operand == 0)
	{
		ui_out_text(uiout, "\n");
		return;
	}

	// special case
	/*if (insn->call)
	{
		// reminder that $rax is set to return value after a "call" instruction
		// if the called function has an integer return value
		// (unfortunately return type is not known for a function)
		ui_out_text(uiout, "(%rax=? on return) ");
	}*/

	dst_op = &insn->operands[0];
	// annotation of object context
	if (insn->annotate)
	{
		size_t ptr_sz = g_ptr_bit >> 3;
		int has_value = 0;
		size_t val = 0xcdcdcdcd;
		int op_size = insn->op_size;
		const char* symname = NULL;
		struct win_type type = {0,0};
		int is_vptr         = 0;
		char* name_to_free = NULL;

		// update register context by "pc"
		set_current_reg_pointers(insn);

		// Get the instruction's destination value/symbol/type
		if (dst_op->type == CA_OP_MEMORY)
		{
			// if the destination is a known local variable
			if (is_stack_address(dst_op))
			{
				address_t addr = get_address(dst_op);
				struct ca_stack_var* sval = get_stack_var(addr);
				if (sval)
				{
					symname = sval->sym_name;
					type = sval->type;
				}
				else
				{
					/*struct symbol* sym;
					struct object_reference aref;
					memset(&aref, 0, sizeof(aref));
					aref.vaddr = addr;
					aref.value = 0;
					aref.target_index = -1;
					sym = get_stack_sym(&aref, NULL, NULL);
					if (sym)
					{
						symname = SYMBOL_PRINT_NAME (sym);
						type = SYMBOL_TYPE(sym);
					}*/
					get_stack_sym_and_type(addr, &symname, &type);
				}
			}
			// could it be a known heap object
			if (!symname && !type.mod_base)
			{
				// this function will allocate buffer for the symbol name if any, remember to free it
				get_op_symbol_type(dst_op, 0, &name_to_free, &type, NULL);
				symname = name_to_free;
			}
			// Since flag insn->annotate is set, dst_op's value should be calculated
			val = get_op_value(dst_op, op_size);
			has_value = 1;
		}
		else if (dst_op->type == CA_OP_REGISTER)
		{
			struct ca_reg_value* dst_reg = get_reg_at_pc(dst_op->reg.index, insn->pc);
			if (dst_reg)
			{
				symname = dst_reg->sym_name;
				type    = dst_reg->type;
				is_vptr = dst_reg->vptr;
				if (dst_reg->has_value)
				{
					has_value = 1;
					val = dst_reg->value;
				}
			}
		}
		else if (dst_op->type == CA_OP_IMMEDIATE)
		{
			val = get_op_value(dst_op, op_size);
			has_value = 1;
		}

		if (dst_op->type != CA_OP_IMMEDIATE)
		{
			// Name and value (if known) of destination
			print_one_operand(uiout, dst_op, op_size);
			if (has_value)
				ui_out_message(uiout, 0, "="PRINT_FORMAT_POINTER, val);
			else
				ui_out_text(uiout, "=?");
		}

		// Symbol or type of destination
		if (dst_op->type == CA_OP_REGISTER
			&& dst_op->reg.index == RSP)
		{
			if (val == g_debug_context.sp)
				ui_out_text(uiout, " End of function prologue");
			ui_out_text(uiout, "\n");
		}
		else
		{
			// symbol or type is known
			if (symname || type.mod_base)
			{
				ui_out_text(uiout, "(");
				if (symname)
				{
					ui_out_message(uiout, 0, "symbol=\"%s\"", symname);
				}
				if (type.mod_base)
				{
					//CHECK_TYPEDEF(type);
					if (symname)
						ui_out_text(uiout, " ");
					ui_out_text(uiout, "type=\"");
					/*if (is_vptr)
					{
						const char * type_name = type_name_no_tag(type);
						if (type_name)
							ui_out_message(uiout, 0, "vtable for %s", type_name);
						else
						{
							ui_out_text(uiout, "vtable for ");
							print_type_name (type);
						}
					}
					else*/
						print_type_name (type);
					ui_out_text(uiout, "\"");
				}
				ui_out_text(uiout, ")\n");
			}
			// whatever we can get form the value
			else
			{
				address_t location = 0;
				int offset = 0;

				//if (insn->num_operand > 1)
				//{
				//	struct ca_operand* src_op = &insn->operands[1];
				//	get_location(src_op, &location, &offset);
				//}

				print_op_value_context (val,
						op_size > 0 ? op_size : ptr_sz,
						location, offset, insn->lea);
			}
		}
		if (name_to_free)
			free (name_to_free);
	}
예제 #4
0
/*
 * First, disassemble all instructions of the function and store them in buffer
 * Second, follow and calculate register values at each instruction
 * Finally, display all disassembled instruction with annotation of object context
 */
int decode_insns(struct decode_control_block* decode_cb)
{
	unsigned int insn_index, i;
	int num_insns = 0;
	struct gdbarch *gdbarch = decode_cb->gdbarch;
	struct ui_out *uiout = decode_cb->uiout;

	// Disassemble the whole function even if user chooses
	// only a subset of it
	num_insns += dump_insns(decode_cb);

	// copy known function parameters
	init_reg_table(decode_cb->param_regs);
	init_stack_vars();

	g_reg_table.cur_regs[RIP]->has_value = 1;
	// Annotate the context of each instruction
	for (insn_index = 0; insn_index < g_num_insns; insn_index++)
	{
		int cur_insn = 0;
		struct ca_dis_insn* insn = &g_insns_buffer[insn_index];

		// update program counter for RIP-relative instruction
		// RIP points to the address of the next instruction before executing current one
		if (insn_index + 1 < g_num_insns)
			set_reg_value_at_pc(RIP, (insn+1)->pc, insn->pc);

		// user may set some register values deliberately
		if (decode_cb->user_regs)
		{
			if (insn->pc == decode_cb->low
				|| (insn_index + 1 < g_num_insns && g_insns_buffer[insn_index + 1].pc > decode_cb->low) )
			{
				if (insn->pc == decode_cb->func_start)
					set_reg_table_at_pc(decode_cb->user_regs, 0);
				else
					set_reg_table_at_pc(decode_cb->user_regs, insn->pc);
			}
		}

		// analyze and update register context affected by this instruction
		if (decode_cb->innermost_frame)
		{
			if (insn->pc == decode_cb->current)
				cur_insn = 1;
		}
		else if (insn_index + 1 < g_num_insns && g_insns_buffer[insn_index + 1].pc == decode_cb->current)
			cur_insn = 1;

		process_one_insn(insn, cur_insn);

		if (cur_insn)
		{
			// return the register context back to caller
			for (i = 0; i < TOTAL_REGS; i++)
			{
				struct ca_reg_value* reg = g_reg_table.cur_regs[i];
				if (reg->has_value)
				{
					// only pass on values, symbol may be out of context in another function
					struct ca_reg_value* dst = &decode_cb->param_regs[i];
					memcpy(dst, reg, sizeof(struct ca_reg_value));
					dst->sym_name = NULL;
				}
			}
		}
	}
	if (decode_cb->verbose)
		validate_reg_table();

	// display disassembled insns
	for (insn_index = 0; insn_index < g_num_insns; insn_index++)
	{
		struct ca_dis_insn* insn = &g_insns_buffer[insn_index];
		// parts of the symbolic representation of the address
		int unmapped;
		int offset;
		int line;
		char *filename = NULL;
		char *name = NULL;

		if (insn->pc >= decode_cb->high)
			break;
		else if (insn->pc >= decode_cb->low)
		{
			// instruction address + offset
			ui_out_text(uiout, pc_prefix(insn->pc));
			ui_out_field_core_addr(uiout, "address", gdbarch, insn->pc);

			if (!build_address_symbolic(gdbarch, insn->pc, 0, &name, &offset, &filename,
					&line, &unmapped))
			{
				ui_out_text(uiout, " <");
				//if (decode_cb->verbose)
				//	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_message(uiout, 0, "<+%ld>:\t", insn->pc - decode_cb->func_start);

			// disassembled instruction with annotation
			print_one_insn(insn, uiout);

			if (filename != NULL)
				free(filename);
			if (name != NULL)
				free(name);
		}
	}

	reset_reg_table();
	reset_stack_vars();

	return num_insns;
}
예제 #5
0
파일: disasm.c 프로젝트: HoMeCracKeR/gdb-ng
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;
}