static int target_event_stop_handler(struct target *target) { int cnt; enum app_type_t app_type = target->app_type; LOGI("target[%p] close, pid(%d) : (remaining %d target)\n", target, target_get_pid(target), target_cnt_get() - 1); ecore_main_fd_handler_del(target->handler); target_wait(target); target_dtor(target); // all target client are closed cnt = target_cnt_sub_and_fetch(); if (0 == cnt) { switch (app_type) { case APP_TYPE_TIZEN: case APP_TYPE_COMMON: LOGI("all targets are stopped\n"); if (stop_all() != ERR_NO) LOGE("Stop failed\n"); return -11; } } return 0; }
/* When running a stand-alone SPE executable, we may need to skip one more exec event on startup, to get past the binfmt_misc loader. */ static void spu_skip_standalone_loader (void) { if (target_has_execution && !current_inferior ()->attach_flag) { struct target_waitstatus ws; /* Only some kernels report an extra SIGTRAP with the binfmt_misc loader; others do not. In addition, if we have attached to an already running inferior instead of starting a new one, we will not see the extra SIGTRAP -- and we cannot readily distinguish the two cases, in particular with the extended-remote target. Thus we issue a single-step here. If no extra SIGTRAP was pending, this will step past the first instruction of the stand-alone SPE executable loader, but we don't care about that. */ inferior_thread ()->control.in_infcall = 1; /* Suppress MI messages. */ target_resume (inferior_ptid, 1, GDB_SIGNAL_0); target_wait (minus_one_ptid, &ws, 0); set_executing (minus_one_ptid, 0); inferior_thread ()->control.in_infcall = 0; } }
void target_wait_all(void) { int i; struct target *t; target_array_lock(); for (i = 0; i < MAX_TARGET_COUNT; ++i) { if (target_use[i] == 0) continue; t = target_get(i); LOGI("join recv thread [%d] is started\n", i); target_wait(t); LOGI("join recv thread %d. done\n", i); } target_array_unlock(); }
/* Called when going to wait for the target. Leave curses mode and setup program mode. */ static ptid_t tui_target_wait_hook (ptid_t pid, struct target_waitstatus *status) { ptid_t res; /* Leave tui mode (optional). */ #if 0 if (tui_active) { target_terminal_ours (); endwin (); target_terminal_inferior (); } #endif tui_target_has_run = 1; res = target_wait (pid, status); if (tui_active) { /* TODO: need to refresh (optional). */ } return res; }
void startup_inferior (int ntraps) { int pending_execs = ntraps; int terminal_initted = 0; ptid_t resume_ptid; if (target_supports_multi_process ()) resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); else resume_ptid = minus_one_ptid; /* The process was started by the fork that created it, but it will have stopped one instruction after execing the shell. Here we must get it up to actual execution of the real program. */ if (exec_wrapper) pending_execs++; while (1) { enum target_signal resume_signal = TARGET_SIGNAL_0; ptid_t event_ptid; struct target_waitstatus ws; memset (&ws, 0, sizeof (ws)); event_ptid = target_wait (resume_ptid, &ws, 0); if (ws.kind == TARGET_WAITKIND_IGNORE) /* The inferior didn't really stop, keep waiting. */ continue; switch (ws.kind) { case TARGET_WAITKIND_SPURIOUS: case TARGET_WAITKIND_LOADED: case TARGET_WAITKIND_FORKED: case TARGET_WAITKIND_VFORKED: case TARGET_WAITKIND_SYSCALL_ENTRY: case TARGET_WAITKIND_SYSCALL_RETURN: /* Ignore gracefully during startup of the inferior. */ switch_to_thread (event_ptid); break; case TARGET_WAITKIND_SIGNALLED: target_terminal_ours (); target_mourn_inferior (); error (_("During startup program terminated with signal %s, %s."), target_signal_to_name (ws.value.sig), target_signal_to_string (ws.value.sig)); return; case TARGET_WAITKIND_EXITED: target_terminal_ours (); target_mourn_inferior (); if (ws.value.integer) error (_("During startup program exited with code %d."), ws.value.integer); else error (_("During startup program exited normally.")); return; case TARGET_WAITKIND_EXECD: /* Handle EXEC signals as if they were SIGTRAP signals. */ xfree (ws.value.execd_pathname); resume_signal = TARGET_SIGNAL_TRAP; switch_to_thread (event_ptid); break; case TARGET_WAITKIND_STOPPED: resume_signal = ws.value.sig; switch_to_thread (event_ptid); break; } if (resume_signal != TARGET_SIGNAL_TRAP) { /* Let shell child handle its own signals in its own way. */ target_resume (resume_ptid, 0, resume_signal); } else { /* We handle SIGTRAP, however; it means child did an exec. */ if (!terminal_initted) { /* Now that the child has exec'd we know it has already set its process group. On POSIX systems, tcsetpgrp will fail with EPERM if we try it before the child's setpgid. */ /* Set up the "saved terminal modes" of the inferior based on what modes we are starting it with. */ target_terminal_init (); /* Install inferior's terminal modes. */ target_terminal_inferior (); terminal_initted = 1; } if (--pending_execs == 0) break; /* Just make it go on. */ target_resume (resume_ptid, 0, TARGET_SIGNAL_0); } } /* Mark all threads non-executing. */ set_executing (resume_ptid, 0); }
int agent_run_command (int pid, const char *cmd, int len) { int fd; int tid = agent_get_helper_thread_id (); ptid_t ptid = ptid_build (pid, tid, 0); #ifdef GDBSERVER int ret = write_inferior_memory (ipa_sym_addrs.addr_cmd_buf, (const unsigned char *) cmd, len); #else int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf, cmd, len); #endif if (ret != 0) { warning (_("unable to write")); return -1; } DEBUG_AGENT ("agent: resumed helper thread\n"); /* Resume helper thread. */ #ifdef GDBSERVER { struct thread_resume resume_info; resume_info.thread = ptid; resume_info.kind = resume_continue; resume_info.sig = GDB_SIGNAL_0; (*the_target->resume) (&resume_info, 1); } #else target_resume (ptid, 0, GDB_SIGNAL_0); #endif fd = gdb_connect_sync_socket (pid); if (fd >= 0) { char buf[1] = ""; int ret; DEBUG_AGENT ("agent: signalling helper thread\n"); do { ret = write (fd, buf, 1); } while (ret == -1 && errno == EINTR); DEBUG_AGENT ("agent: waiting for helper thread's response\n"); do { ret = read (fd, buf, 1); } while (ret == -1 && errno == EINTR); close (fd); DEBUG_AGENT ("agent: helper thread's response received\n"); } else return -1; /* Need to read response with the inferior stopped. */ if (!ptid_equal (ptid, null_ptid)) { struct target_waitstatus status; int was_non_stop = non_stop; /* Stop thread PTID. */ DEBUG_AGENT ("agent: stop helper thread\n"); #ifdef GDBSERVER { struct thread_resume resume_info; resume_info.thread = ptid; resume_info.kind = resume_stop; resume_info.sig = GDB_SIGNAL_0; (*the_target->resume) (&resume_info, 1); } non_stop = 1; mywait (ptid, &status, 0, 0); #else non_stop = 1; target_stop (ptid); memset (&status, 0, sizeof (status)); target_wait (ptid, &status, 0); #endif non_stop = was_non_stop; } if (fd >= 0) { #ifdef GDBSERVER if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf, (unsigned char *) cmd, IPA_CMD_BUF_SIZE)) #else if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd, IPA_CMD_BUF_SIZE)) #endif { warning (_("Error reading command response")); return -1; } } return 0; }