Esempio n. 1
0
ATF_TC_BODY(signal_forward, tc)
{
	struct proc_handle *phdl;
	int state, status;

	phdl = start_prog(tc, true);
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	/* The process should have been interrupted by a signal. */
	state = proc_wstatus(phdl);
	ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d",
	    state);

	/* Continue execution and allow the signal to be delivered. */
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	/*
	 * Make sure the process exited with status 0. If it didn't receive the
	 * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit
	 * status, causing the test to fail.
	 */
	state = proc_wstatus(phdl);
	ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d",
	    state);

	status = proc_getwstat(phdl);
	ATF_REQUIRE(status >= 0);
	ATF_REQUIRE(WIFEXITED(status));
	ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);

	proc_free(phdl);
}
Esempio n. 2
0
ATF_TC_BODY(symbol_lookup, tc)
{
	GElf_Sym main_sym, r_debug_state_sym;
	struct proc_handle *phdl;
	u_long saved;
	int error;

	phdl = start_prog(tc, false);

	error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'");

	error = proc_name2sym(phdl, ldelf_object, "r_debug_state",
	    &r_debug_state_sym, NULL);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'");

	set_bkpt(phdl, r_debug_state_sym.st_value, &saved);
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
	verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object);
	remove_bkpt(phdl, r_debug_state_sym.st_value, saved);

	set_bkpt(phdl, main_sym.st_value, &saved);
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
	verify_bkpt(phdl, &main_sym, "main", target_prog_file);
	remove_bkpt(phdl, main_sym.st_value, saved);

	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	proc_free(phdl);
}
Esempio n. 3
0
ATF_TC_BODY(symbol_lookup, tc)
{
	GElf_Sym main_sym, r_debug_state_sym;
	struct proc_handle *phdl;
	proc_breakpoint_t saved;
	int error;

	phdl = start_prog(tc, false);

	error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'");

	error = proc_name2sym(phdl, ldelf_object, r_debug_state,
	    &r_debug_state_sym, NULL);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up '%s'", r_debug_state);

	set_bkpt(phdl, (uintptr_t)r_debug_state_sym.st_value, &saved);
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
	verify_bkpt(phdl, &r_debug_state_sym, r_debug_state, ldelf_object);
	remove_bkpt(phdl, (uintptr_t)r_debug_state_sym.st_value, &saved);

	set_bkpt(phdl, (uintptr_t)main_sym.st_value, &saved);
	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
	verify_bkpt(phdl, &main_sym, "main", target_prog_file);
	remove_bkpt(phdl, (uintptr_t)main_sym.st_value, &saved);

	ATF_CHECK_EQ_MSG(proc_detach(phdl, PRELEASE_HANG), 0, "failed to detach");

	proc_free(phdl);
}
Esempio n. 4
0
ATF_TC_BODY(symbol_lookup_fail, tc)
{
	char symname[32];
	GElf_Sym sym;
	struct proc_handle *phdl;
	prmap_t *map;
	int error;

	phdl = start_prog(tc, false);

	/* Initialize the rtld_db handle. */
	(void)proc_rdagent(phdl);

	map = proc_name2map(phdl, target_prog_file);
	ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'",
	    target_prog_file);

	/*
	 * We shouldn't be able to find symbols at the beginning of a mapped
	 * file.
	 */
	error = proc_addr2sym(phdl, map->pr_vaddr, symname, sizeof(symname),
	    &sym);
	ATF_REQUIRE_MSG(error != 0, "unexpectedly found a symbol");

	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	proc_free(phdl);
}
Esempio n. 5
0
ATF_TC_BODY(map_alias_name2sym, tc)
{
	GElf_Sym sym1, sym2;
	prsyminfo_t si1, si2;
	struct proc_handle *phdl;
	int error;

	phdl = start_prog(tc, false);

	/* Initialize the rtld_db handle. */
	(void)proc_rdagent(phdl);

	/*
	 * Make sure that "target_prog:main" and "a.out:main" return the same
	 * symbol.
	 */
	error = proc_name2sym(phdl, target_prog_file, "main", &sym1, &si1);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
	    target_prog_file);
	error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2);
	ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
	    aout_object);

	ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0);
	ATF_CHECK_EQ(si1.prs_id, si2.prs_id);

	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	proc_free(phdl);
}
Esempio n. 6
0
int
t1_bkpt_d()
{
	struct proc_handle *phdl;
	char *targv[] = { "t1-bkpt-t", NULL};
	unsigned long saved;

	proc_create("./t1-bkpt", targv, NULL, NULL, &phdl);
	assert(proc_bkptset(phdl, (uintptr_t)t1_bkpt_t, &saved) == 0);
	proc_continue(phdl);
	assert(proc_wstatus(phdl) == PS_STOP);
	proc_bkptexec(phdl, saved);
	proc_continue(phdl);
	proc_wstatus(phdl);
	proc_free(phdl);
}
Esempio n. 7
0
int
proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
    unsigned long saved)
{
	struct ptrace_io_desc piod;
	uintptr_t caddr;
	int ret = 0, stopped;
	instr_t instr;

	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
	    phdl->status == PS_IDLE) {
		errno = ENOENT;
		return (-1);
	}

	DPRINTFX("removing breakpoint at 0x%lx", address);

	stopped = 0;
	if (phdl->status != PS_STOP) {
		if (proc_stop(phdl) != 0)
			return (-1);
		stopped = 1;
	}

	/*
	 * Overwrite the breakpoint instruction that we setup previously.
	 */
	caddr = address;
	instr = saved;
	piod.piod_op = PIOD_WRITE_I;
	piod.piod_offs = (void *)caddr;
	piod.piod_addr = &instr;
	piod.piod_len  = BREAKPOINT_INSTR_SZ;
	if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
		DPRINTF("ERROR: couldn't write instruction at address 0x%"
		    PRIuPTR, address);
		ret = -1;
	}

	if (stopped)
		/* Restart the process if we had to stop it. */
		proc_continue(phdl);
 
	return (ret);
}
Esempio n. 8
0
ATF_TC_BODY(map_prefix_name2map, tc)
{
	struct proc_handle *phdl;
	prmap_t *map1, *map2;

	phdl = start_prog(tc, false);

	/* Initialize the rtld_db handle. */
	(void)proc_rdagent(phdl);

	/* Make sure that "ld-elf" and "ld-elf.so" return the same map. */
	map1 = proc_name2map(phdl, "ld-elf");
	ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'");
	map2 = proc_name2map(phdl, "ld-elf.so");
	ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'");
	ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);

	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	proc_free(phdl);
}
Esempio n. 9
0
ATF_TC_BODY(map_alias_name2map, tc)
{
	struct proc_handle *phdl;
	prmap_t *map1, *map2;

	phdl = start_prog(tc, false);

	/* Initialize the rtld_db handle. */
	(void)proc_rdagent(phdl);

	/* Ensure that "target_prog" and "a.out" return the same map. */
	map1 = proc_name2map(phdl, target_prog_file);
	ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'",
	    target_prog_file);
	map2 = proc_name2map(phdl, aout_object);
	ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'",
	    aout_object);
	ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);

	ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");

	proc_free(phdl);
}
int	init_loop(tracee_t* tracee, addr_t* will_start)
{
  int		signal, ret, brk_set = 0;
  list_t*	cur;
  brkp_t*	brkp;

  /*
  ** Address where the tracing will start.
  */
  *will_start = 0;
  /*
  ** Init binaries.
  */
  tracee->binh = bin_create_handler(tracee->proc->path);
  if (tracee->binh == NULL)
    errexit("ftrace: bin_create_handler, %s", ftrace_strerror(errno));
  bin_refresh_depends_list(proc_get_depends_list(tracee->proc), tracee->binh);
  /*
  ** Inject breakpoints.
  */
  brkps_inject(tracee);
  /*
  ** Waiting for breakpoint ?
  */
  for (cur = tracee->brkps; cur; cur = cur->next)
    {
      if (((brkp_t*) cur->value)->set)
	{
	  brk_set = 1;
	  break;
	}
      if (cur == tracee->brkps->prev)
	break;
    }
  /*
  ** No breakpoint setted, trace !
  */
  if (!brk_set && !tracee->brkps_toset)
    {
      /*
      ** Remove FTrace breakpoints
      */
      for (cur = tracee->fbrkps; cur; cur = cur->next)
	{
	  if (((brkp_t*) cur->value)->set)
	    {
	      if (proc_unset_breakpoint(tracee->proc, (brkp_t*) cur->value) == -1)
		errexit("ftrace: proc_unset_breakpoint, %s", ftrace_strerror(errno));
	    }
	  if (cur == tracee->fbrkps->prev)
	    break;
	}
      return (TRACEE_OK);
    }
  /*
  ** Else wait for breakpoint hit.
  */
  tracee->status = RUN;
  if (proc_continue(tracee->proc, 0) == -1)
    errexit("ftrace: proc_continue, %s", ftrace_strerror(errno));
  while (1)
    {
      ret = proc_wait_debug_event(tracee->proc, &signal);
      if (ret == -1)
	errexit("ftrace: proc_wait_debug_event, %s", ftrace_strerror(errno));
      switch (ret)
	{
	case DEBUG_EVENT:
	  if (tracer_quit)
	    return (0);
	  /*
	  ** if ftrace breakpoint:
	  */
	  brkp = proc_seek_brkps(tracee->proc, tracee->fbrkps);
	  if (brkp && brkp->set)
	    {
	      /*
	      ** Lookup if any shared objects has been load.
	      ** If there is a new so, try de resolve unsolved user breakpoint.
	      */
	      if (bin_refresh_depends_list(proc_get_depends_list(tracee->proc), tracee->binh))
		brkps_try_resolved(tracee);
	      /*
	      ** Unset ftrace one shot breakpoint
	      */
	      if (proc_unset_breakpoint(tracee->proc, brkp) == -1)
		errexit("ftrace: proc_unset_breakpoint, %s", ftrace_strerror(errno));
	      /*
	      ** Step back after restore and continue to seek user breakpoint.
	      */
	      if (proc_step_addr(tracee->proc, brkp->addr, 0) == -1)
		errexit("ftrace: proc_step_addr, %s", ftrace_strerror(errno));
	      break;
	    }
	  /*
	  ** if user breakpoint:
	  */
	  brkp = proc_seek_brkps(tracee->proc, tracee->brkps);
	  if (brkp && brkp->set)
	    {
	      /*
	      ** Breakpoint hit!
	      ** Remove every breakpoints and start tracing !
	      */
	      /*
	      ** Remove user breakpoints.
	      */
	      for (cur = tracee->brkps; cur; cur = cur->next)
		{
		  if (((brkp_t*) cur->value)->set)
		    {
		      if (proc_unset_breakpoint(tracee->proc, (brkp_t*) cur->value) == -1)
			errexit("ftrace: proc_unset_breakpoint, %s", ftrace_strerror(errno));
		    }
		  if (cur == tracee->brkps->prev)
		    break;
		}
	      /*
	      ** Remove ftrace breakpoints.
	      */
	      for (cur = tracee->fbrkps; cur; cur = cur->next)
		{
		  if (((brkp_t*) cur->value)->set)
		    {
		      if (proc_unset_breakpoint(tracee->proc, (brkp_t*) cur->value) == -1)
			errexit("ftrace: proc_unset_breakpoint, %s", ftrace_strerror(errno));
		    }
		  if (cur == tracee->fbrkps->prev)
		    break;
		}
	      /*
	      ** Step back after restore.
	      */
	      if (proc_step_addr(tracee->proc, brkp->addr, 0) == -1)
		errexit("ftrace: proc_step_addr, %s", ftrace_strerror(errno));
	      *will_start = brkp->addr;
	      return (TRACEE_OK);
	    }
	  if (proc_continue(tracee->proc, 0) == -1)
	    errexit("ftrace: proc_continue, %s", ftrace_strerror(errno));
	  break;
	case SIGNAL_EVENT:
	  pwarn("Program received signal %d, %s\n", signal, sys_siglist[signal]);
	  if (proc_continue(tracee->proc, signal) == -1)
	    errexit("ftrace: proc_continue, %s", ftrace_strerror(errno));
	  break;
	case EXIT_EVENT:
	  pverbose(1, "\nProgram exited normally.\n");
	  return (TRACEE_EXIT);
	  break;
	case EXIT_SIGNALED_EVENT:
	  pverbose(1, "Program exited with signal %d, %s\n", signal, sys_siglist[signal]);
	  return (TRACEE_EXIT);
	  break;
	default:
	  errexit("ftrace: proc_wait_debug_event, Unknow Error !");
	}
    }
  return (-1);
}
Esempio n. 11
0
int
proc_bkptset(struct proc_handle *phdl, uintptr_t address,
    unsigned long *saved)
{
	struct ptrace_io_desc piod;
	uintptr_t caddr;
	int ret = 0, stopped;
	instr_t instr;

	*saved = 0;
	if (phdl->status == PS_DEAD || phdl->status == PS_UNDEAD ||
	    phdl->status == PS_IDLE) {
		errno = ENOENT;
		return (-1);
	}

	DPRINTFX("adding breakpoint at 0x%lx", address);

	stopped = 0;
	if (phdl->status != PS_STOP) {
		if (proc_stop(phdl) != 0)
			return (-1);
		stopped = 1;
	}

	/*
	 * Read the original instruction.
	 */
	caddr = address;
	instr = 0;
	piod.piod_op = PIOD_READ_I;
	piod.piod_offs = (void *)caddr;
	piod.piod_addr = &instr;
	piod.piod_len  = BREAKPOINT_INSTR_SZ;
	if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
		DPRINTF("ERROR: couldn't read instruction at address 0x%"
		    PRIuPTR, address);
		ret = -1;
		goto done;
	}
	*saved = instr;
	/*
	 * Write a breakpoint instruction to that address.
	 */
	caddr = address;
	instr = BREAKPOINT_INSTR;
	piod.piod_op = PIOD_WRITE_I;
	piod.piod_offs = (void *)caddr;
	piod.piod_addr = &instr;
	piod.piod_len  = BREAKPOINT_INSTR_SZ;
	if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
		DPRINTF("ERROR: couldn't write instruction at address 0x%"
		    PRIuPTR, address);
		ret = -1;
		goto done;
	}

done:
	if (stopped)
		/* Restart the process if we had to stop it. */
		proc_continue(phdl);

	return (ret);
}