Esempio n. 1
0
File: disasm.c Progetto: 0mp/freebsd
static void
do_assembly_only (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;
  struct cleanup *ui_out_chain;

  ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");

  num_displayed = dump_insns (uiout, di, low, high, how_many, stb);

  do_cleanups (ui_out_chain);
}
Esempio n. 2
0
/* 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 gdbarch *gdbarch, 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, int flags, 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;
  struct cleanup *ui_out_chain;
  struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
  struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 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_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");

  for (i = 0; i < newlines; i++)
    {
      /* 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_chain
		    = make_cleanup_ui_out_tuple_begin_end (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++)
		    {
		      struct cleanup *ui_out_list_chain_line;
		      struct cleanup *ui_out_tuple_chain_line;
		      
		      ui_out_tuple_chain_line
			= make_cleanup_ui_out_tuple_begin_end (uiout,
							       "src_and_asm_line");
		      print_source_lines (symtab, next_line, next_line + 1,
					  0);
		      ui_out_list_chain_line
			= make_cleanup_ui_out_list_begin_end (uiout,
							      "line_asm_insn");
		      do_cleanups (ui_out_list_chain_line);
		      do_cleanups (ui_out_tuple_chain_line);
		    }
		  /* Print the last line and leave list open for
		     asm instructions to be added. */
		  ui_out_tuple_chain
		    = make_cleanup_ui_out_tuple_begin_end (uiout,
							   "src_and_asm_line");
		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
		}
	    }
	  else
	    {
	      ui_out_tuple_chain
		= make_cleanup_ui_out_tuple_begin_end (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_chain
	    = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
	}

      num_displayed += dump_insns (gdbarch, uiout, di,
				   mle[i].start_pc, mle[i].end_pc,
				   how_many, flags, stb);

      /* When we've reached the end of the mle array, or we've seen the last
         assembly range for this source line, close out the list/tuple.  */
      if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
	{
	  do_cleanups (ui_out_list_chain);
	  do_cleanups (ui_out_tuple_chain);
	  ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
	  ui_out_list_chain = make_cleanup (null_cleanup, 0);
	  ui_out_text (uiout, "\n");
	}
      if (how_many >= 0 && num_displayed >= how_many)
	break;
    }
  do_cleanups (ui_out_chain);
}
Esempio n. 3
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;
}