예제 #1
0
/**
 * Install any breakpoints necessary to capture any interesting events
 * that cannot be captured by wrapping functions
 *
 * @param errmsg the errmsg populated on error
 *
 * @return 0 on success; non-zero on failure
 */
int install_event_breakpoints(udi_errmsg *errmsg) {
    int errnum = 0;

    do {
        // Exit cannot be wrappped because Linux executables can call it
        // directly and do not pass through the PLT
        exit_bp = create_breakpoint((udi_address)(unsigned long)exit);
        if ( exit_bp == NULL ) {
            udi_printf("%s\n", "failed to create exit breakpoint");
            errnum = -1;
            break;
        }

        errnum = install_breakpoint(exit_bp, errmsg);

        if ( errnum != 0 ) {
            udi_printf("%s\n", "failed to install exit breakpoint");
            errnum = -1;
            break;
        }

        if (get_multithread_capable()) {
            errnum = install_thread_event_breakpoints(errmsg);
        }

    } while(0);

    return errnum;
}
예제 #2
0
static SCM
gdbscm_register_breakpoint_x (SCM self)
{
    breakpoint_smob *bp_smob
        = bpscm_get_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
    volatile struct gdb_exception except;

    /* We only support registering breakpoints created with make-breakpoint.  */
    if (!bp_smob->is_scheme_bkpt)
        scm_misc_error (FUNC_NAME, _("not a Scheme breakpoint"), SCM_EOL);

    if (bpscm_is_valid (bp_smob))
        scm_misc_error (FUNC_NAME, _("breakpoint is already registered"), SCM_EOL);

    pending_breakpoint_scm = self;

    TRY_CATCH (except, RETURN_MASK_ALL)
    {
        char *location = bp_smob->spec.location;
        int internal = bp_smob->spec.is_internal;

        switch (bp_smob->spec.type)
        {
        case bp_breakpoint:
        {
            create_breakpoint (get_current_arch (),
                               location, NULL, -1, NULL,
                               0,
                               0, bp_breakpoint,
                               0,
                               AUTO_BOOLEAN_TRUE,
                               &bkpt_breakpoint_ops,
                               0, 1, internal, 0);
            break;
        }
        case bp_watchpoint:
        {
            enum target_hw_bp_type access_type = bp_smob->spec.access_type;

            if (access_type == hw_write)
                watch_command_wrapper (location, 0, internal);
            else if (access_type == hw_access)
                awatch_command_wrapper (location, 0, internal);
            else if (access_type == hw_read)
                rwatch_command_wrapper (location, 0, internal);
            else
                gdb_assert_not_reached ("invalid access type");
            break;
        }
        default:
            gdb_assert_not_reached ("invalid breakpoint type");
        }
    }
예제 #3
0
void run_debugger(pid_t child_pid)
{
    procmsg("debugger started\n");

    /* Wait for child to stop on its first instruction */
    wait(0);
    procmsg("child now at EIP = 0x%08x\n", get_child_eip(child_pid));

    /* Create breakpoint and run to it*/
    debug_breakpoint* bp = create_breakpoint(child_pid, (void*)0x080483b4);
    procmsg("breakpoint created\n");
    ptrace(PTRACE_CONT, child_pid, 0, 0);
    wait(0);

    /* Loop as long as the child didn't exit */
    while (1) {
        /* The child is stopped at a breakpoint here. Resume its
        ** execution until it either exits or hits the
        ** breakpoint again.
        */
        procmsg("child stopped at breakpoint. EIP = 0x%08X\n", get_child_eip(child_pid));
        procmsg("resuming\n");
        int rc = resume_from_breakpoint(child_pid, bp);

        if (rc == 0) {
            procmsg("child exited\n");
            break;
        }
        else if (rc == 1) {
            continue;
        }
        else {
            procmsg("unexpected: %d\n", rc);
            break;
        }
    }

    cleanup_breakpoint(bp);
}
static bool parse_breakpoint_call(PluginData* data, const char* res, int len, PDReader* reader, PDWriter* writer) {
    Breakpoint* bp = 0;

    (void)len;
    (void)reader;

    const char* breakStrOffset = strstr(res, "BREAK:");

    if (!breakStrOffset)
        return false;

    int id = atoi(breakStrOffset + 7);

    const char* address = strstr(breakStrOffset, "C:$");

    if (!find_breakpoint_by_id(data, &bp, id)) {
        bp = create_breakpoint();
        add_breakpoint(data, bp);
    }

    bp->id = id;

    if (address)
        bp->address = (uint16_t)strtol(address + 3, 0, 16);

    // add data or update existing

    PDWrite_event_begin(writer, PDEventType_ReplyBreakpoint);
    PDWrite_u64(writer, "address", bp->address);
    PDWrite_u32(writer, "id", (uint32_t)id);
    PDWrite_event_end(writer);

    log_debug("sending reply back: breakpoint %x - %d\n", bp->address, id);

    // make sure we got all dat;

    return strstr(breakStrOffset, "(C:$");
}
예제 #5
0
static void
mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
{
  char *address = NULL;
  int hardware = 0;
  int temp_p = 0;
  int thread = -1;
  int ignore_count = 0;
  char *condition = NULL;
  int pending = 0;
  int enabled = 1;
  int tracepoint = 0;
  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
  enum bptype type_wanted;
  struct breakpoint_ops *ops;
  char *extra_string = NULL;

  enum opt
    {
      HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
      IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
      TRACEPOINT_OPT,
    };
  static const struct mi_opt opts[] =
  {
    {"h", HARDWARE_OPT, 0},
    {"t", TEMP_OPT, 0},
    {"c", CONDITION_OPT, 1},
    {"i", IGNORE_COUNT_OPT, 1},
    {"p", THREAD_OPT, 1},
    {"f", PENDING_OPT, 0},
    {"d", DISABLE_OPT, 0},
    {"a", TRACEPOINT_OPT, 0},
    { 0, 0, 0 }
  };

  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
     to denote the end of the option list. */
  int oind = 0;
  char *oarg;

  while (1)
    {
      int opt = mi_getopt ("-break-insert", argc, argv,
			   opts, &oind, &oarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case TEMP_OPT:
	  temp_p = 1;
	  break;
	case HARDWARE_OPT:
	  hardware = 1;
	  break;
	case CONDITION_OPT:
	  condition = oarg;
	  break;
	case IGNORE_COUNT_OPT:
	  ignore_count = atol (oarg);
	  break;
	case THREAD_OPT:
	  thread = atol (oarg);
	  break;
	case PENDING_OPT:
	  pending = 1;
	  break;
	case DISABLE_OPT:
	  enabled = 0;
	  break;
	case TRACEPOINT_OPT:
	  tracepoint = 1;
	  break;
	}
    }

  if (oind >= argc)
    error (_("-%s-insert: Missing <location>"),
	   dprintf ? "dprintf" : "break");
  address = argv[oind];
  if (dprintf)
    {
      int format_num = oind + 1;

      if (hardware || tracepoint)
	error (_("-dprintf-insert: does not support -h or -a"));
      if (format_num >= argc)
	error (_("-dprintf-insert: Missing <format>"));

      extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
      make_cleanup (xfree, extra_string);
    }
  else
    {
      if (oind < argc - 1)
	error (_("-break-insert: Garbage following <location>"));
    }

  /* Now we have what we need, let's insert the breakpoint!  */
  setup_breakpoint_reporting ();

  if (tracepoint)
    {
      /* Note that to request a fast tracepoint, the client uses the
	 "hardware" flag, although there's nothing of hardware related to
	 fast tracepoints -- one can implement slow tracepoints with
	 hardware breakpoints, but fast tracepoints are always software.
	 "fast" is a misnomer, actually, "jump" would be more appropriate.
	 A simulator or an emulator could conceivably implement fast
	 regular non-jump based tracepoints.  */
      type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
      ops = &tracepoint_breakpoint_ops;
    }
  else if (dprintf)
    {
      type_wanted = bp_dprintf;
      ops = &dprintf_breakpoint_ops;
    }
  else
    {
      type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
      ops = &bkpt_breakpoint_ops;
    }

  create_breakpoint (get_current_arch (), address, condition, thread,
		     extra_string,
		     0 /* condition and thread are valid.  */,
		     temp_p, type_wanted,
		     ignore_count,
		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
		     ops, 0, enabled, 0, 0);
  do_cleanups (back_to);
}
예제 #6
0
static SCM
gdbscm_register_breakpoint_x (SCM self)
{
  breakpoint_smob *bp_smob
    = bpscm_get_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
  struct gdb_exception except = exception_none;
  char *location, *copy;
  struct event_location *eloc;
  struct cleanup *cleanup;

  /* We only support registering breakpoints created with make-breakpoint.  */
  if (!bp_smob->is_scheme_bkpt)
    scm_misc_error (FUNC_NAME, _("not a Scheme breakpoint"), SCM_EOL);

  if (bpscm_is_valid (bp_smob))
    scm_misc_error (FUNC_NAME, _("breakpoint is already registered"), SCM_EOL);

  pending_breakpoint_scm = self;
  location = bp_smob->spec.location;
  copy = location;
  eloc = new_linespec_location (&copy);
  cleanup = make_cleanup_delete_event_location (eloc);

  TRY
    {
      int internal = bp_smob->spec.is_internal;

      switch (bp_smob->spec.type)
	{
	case bp_breakpoint:
	  {
	    create_breakpoint (get_current_arch (),
			       eloc, NULL, -1, NULL,
			       0,
			       0, bp_breakpoint,
			       0,
			       AUTO_BOOLEAN_TRUE,
			       &bkpt_breakpoint_ops,
			       0, 1, internal, 0);
	    break;
	  }
	case bp_watchpoint:
	  {
	    enum target_hw_bp_type access_type = bp_smob->spec.access_type;

	    if (access_type == hw_write)
	      watch_command_wrapper (location, 0, internal);
	    else if (access_type == hw_access)
	      awatch_command_wrapper (location, 0, internal);
	    else if (access_type == hw_read)
	      rwatch_command_wrapper (location, 0, internal);
	    else
	      gdb_assert_not_reached ("invalid access type");
	    break;
	  }
	default:
	  gdb_assert_not_reached ("invalid breakpoint type");
	}
    }
  CATCH (ex, RETURN_MASK_ALL)
    {
      except = ex;
    }
  END_CATCH

  /* Ensure this gets reset, even if there's an error.  */
  pending_breakpoint_scm = SCM_BOOL_F;
  GDBSCM_HANDLE_GDB_EXCEPTION (except);
  do_cleanups (cleanup);

  return SCM_UNSPECIFIED;
}
예제 #7
0
static void
mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
{
  char *address = NULL;
  int hardware = 0;
  int temp_p = 0;
  int thread = -1;
  int ignore_count = 0;
  char *condition = NULL;
  int pending = 0;
  int enabled = 1;
  int tracepoint = 0;
  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
  enum bptype type_wanted;
  struct event_location *location;
  struct breakpoint_ops *ops;
  int is_explicit = 0;
  struct explicit_location explicit_loc;
  char *extra_string = NULL;

  enum opt
    {
      HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
      IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
      TRACEPOINT_OPT,
      EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
      EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
    };
  static const struct mi_opt opts[] =
  {
    {"h", HARDWARE_OPT, 0},
    {"t", TEMP_OPT, 0},
    {"c", CONDITION_OPT, 1},
    {"i", IGNORE_COUNT_OPT, 1},
    {"p", THREAD_OPT, 1},
    {"f", PENDING_OPT, 0},
    {"d", DISABLE_OPT, 0},
    {"a", TRACEPOINT_OPT, 0},
    {"-source" , EXPLICIT_SOURCE_OPT, 1},
    {"-function", EXPLICIT_FUNC_OPT, 1},
    {"-label", EXPLICIT_LABEL_OPT, 1},
    {"-line", EXPLICIT_LINE_OPT, 1},
    { 0, 0, 0 }
  };

  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
     to denote the end of the option list. */
  int oind = 0;
  char *oarg;

  initialize_explicit_location (&explicit_loc);

  while (1)
    {
      int opt = mi_getopt ("-break-insert", argc, argv,
			   opts, &oind, &oarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case TEMP_OPT:
	  temp_p = 1;
	  break;
	case HARDWARE_OPT:
	  hardware = 1;
	  break;
	case CONDITION_OPT:
	  condition = oarg;
	  break;
	case IGNORE_COUNT_OPT:
	  ignore_count = atol (oarg);
	  break;
	case THREAD_OPT:
	  thread = atol (oarg);
	  break;
	case PENDING_OPT:
	  pending = 1;
	  break;
	case DISABLE_OPT:
	  enabled = 0;
	  break;
	case TRACEPOINT_OPT:
	  tracepoint = 1;
	  break;
	case EXPLICIT_SOURCE_OPT:
	  is_explicit = 1;
	  explicit_loc.source_filename = oarg;
	  break;
	case EXPLICIT_FUNC_OPT:
	  is_explicit = 1;
	  explicit_loc.function_name = oarg;
	  break;
	case EXPLICIT_LABEL_OPT:
	  is_explicit = 1;
	  explicit_loc.label_name = oarg;
	  break;
	case EXPLICIT_LINE_OPT:
	  is_explicit = 1;
	  explicit_loc.line_offset = linespec_parse_line_offset (oarg);
	  break;
	}
    }

  if (oind >= argc && !is_explicit)
    error (_("-%s-insert: Missing <location>"),
	   dprintf ? "dprintf" : "break");
  if (dprintf)
    {
      int format_num = is_explicit ? oind : oind + 1;

      if (hardware || tracepoint)
	error (_("-dprintf-insert: does not support -h or -a"));
      if (format_num >= argc)
	error (_("-dprintf-insert: Missing <format>"));

      extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
      make_cleanup (xfree, extra_string);
      address = argv[oind];
    }
  else
    {
      if (is_explicit)
	{
	  if (oind < argc)
	    error (_("-break-insert: Garbage following explicit location"));
	}
      else
	{
	  if (oind < argc - 1)
	    error (_("-break-insert: Garbage following <location>"));
	  address = argv[oind];
	}
    }

  /* Now we have what we need, let's insert the breakpoint!  */
  setup_breakpoint_reporting ();

  if (tracepoint)
    {
      /* Note that to request a fast tracepoint, the client uses the
	 "hardware" flag, although there's nothing of hardware related to
	 fast tracepoints -- one can implement slow tracepoints with
	 hardware breakpoints, but fast tracepoints are always software.
	 "fast" is a misnomer, actually, "jump" would be more appropriate.
	 A simulator or an emulator could conceivably implement fast
	 regular non-jump based tracepoints.  */
      type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
      ops = &tracepoint_breakpoint_ops;
    }
  else if (dprintf)
    {
      type_wanted = bp_dprintf;
      ops = &dprintf_breakpoint_ops;
    }
  else
    {
      type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
      ops = &bkpt_breakpoint_ops;
    }

  if (is_explicit)
    {
      /* Error check -- we must have one of the other
	 parameters specified.  */
      if (explicit_loc.source_filename != NULL
	  && explicit_loc.function_name == NULL
	  && explicit_loc.label_name == NULL
	  && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
	error (_("-%s-insert: --source option requires --function, --label,"
		 " or --line"), dprintf ? "dprintf" : "break");

      location = new_explicit_location (&explicit_loc);
    }
  else
    {
      location = string_to_event_location_basic (&address, current_language);
      if (*address)
	{
	  delete_event_location (location);
	  error (_("Garbage '%s' at end of location"), address);
	}
    }

  make_cleanup_delete_event_location (location);

  create_breakpoint (get_current_arch (), location, condition, thread,
		     extra_string,
		     0 /* condition and thread are valid.  */,
		     temp_p, type_wanted,
		     ignore_count,
		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
		     ops, 0, enabled, 0, 0);
  do_cleanups (back_to);
}
예제 #8
0
void
mi_cmd_break_insert (char *command, char **argv, int argc)
{
  char *address = NULL;
  int hardware = 0;
  int temp_p = 0;
  int thread = -1;
  int ignore_count = 0;
  char *condition = NULL;
  int pending = 0;
  int enabled = 1;
  int tracepoint = 0;
  struct cleanup *back_to;
  enum bptype type_wanted;

  enum opt
    {
      HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
      IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
      TRACEPOINT_OPT,
    };
  static const struct mi_opt opts[] =
  {
    {"h", HARDWARE_OPT, 0},
    {"t", TEMP_OPT, 0},
    {"c", CONDITION_OPT, 1},
    {"i", IGNORE_COUNT_OPT, 1},
    {"p", THREAD_OPT, 1},
    {"f", PENDING_OPT, 0},
    {"d", DISABLE_OPT, 0},
    {"a", TRACEPOINT_OPT, 0},
    { 0, 0, 0 }
  };

  /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
     to denote the end of the option list. */
  int oind = 0;
  char *oarg;

  while (1)
    {
      int opt = mi_getopt ("-break-insert", argc, argv,
			   opts, &oind, &oarg);
      if (opt < 0)
	break;
      switch ((enum opt) opt)
	{
	case TEMP_OPT:
	  temp_p = 1;
	  break;
	case HARDWARE_OPT:
	  hardware = 1;
	  break;
	case CONDITION_OPT:
	  condition = oarg;
	  break;
	case IGNORE_COUNT_OPT:
	  ignore_count = atol (oarg);
	  break;
	case THREAD_OPT:
	  thread = atol (oarg);
	  break;
	case PENDING_OPT:
	  pending = 1;
	  break;
	case DISABLE_OPT:
	  enabled = 0;
	  break;
	case TRACEPOINT_OPT:
	  tracepoint = 1;
	  break;
	}
    }

  if (oind >= argc)
    error (_("-break-insert: Missing <location>"));
  if (oind < argc - 1)
    error (_("-break-insert: Garbage following <location>"));
  address = argv[oind];

  /* Now we have what we need, let's insert the breakpoint!  */
  if (! mi_breakpoint_observers_installed)
    {
      observer_attach_breakpoint_created (breakpoint_notify);
      mi_breakpoint_observers_installed = 1;
    }

  back_to = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
  mi_can_breakpoint_notify = 1;

  /* Note that to request a fast tracepoint, the client uses the
     "hardware" flag, although there's nothing of hardware related to
     fast tracepoints -- one can implement slow tracepoints with
     hardware breakpoints, but fast tracepoints are always software.
     "fast" is a misnomer, actually, "jump" would be more appropriate.
     A simulator or an emulator could conceivably implement fast
     regular non-jump based tracepoints.  */
  type_wanted = (tracepoint
		 ? (hardware ? bp_fast_tracepoint : bp_tracepoint)
		 : (hardware ? bp_hardware_breakpoint : bp_breakpoint));

  create_breakpoint (get_current_arch (), address, condition, thread,
		     NULL,
		     0 /* condition and thread are valid.  */,
		     temp_p, type_wanted,
		     ignore_count,
		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
		     &bkpt_breakpoint_ops, 0, enabled, 0, 0);
  do_cleanups (back_to);

}