static void print_flush (void) { struct serial *gdb_stdout_serial; if (deprecated_error_begin_hook) deprecated_error_begin_hook (); if (target_supports_terminal_ours ()) target_terminal_ours (); /* We want all output to appear now, before we print the error. We have 3 levels of buffering we have to flush (it's possible that some of these should be changed to flush the lower-level ones too): */ /* 1. The _filtered buffer. */ if (filtered_printing_initialized ()) wrap_here (""); /* 2. The stdio buffer. */ gdb_flush (gdb_stdout); gdb_flush (gdb_stderr); /* 3. The system-level buffer. */ gdb_stdout_serial = serial_fdopen (1); if (gdb_stdout_serial) { serial_drain_output (gdb_stdout_serial); serial_un_fdopen (gdb_stdout_serial); } annotate_error_begin (); }
static void mi_breakpoint_modified (struct breakpoint *b) { struct mi_interp *mi = top_level_interpreter_data (); struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); volatile struct gdb_exception e; if (mi_suppress_notification.breakpoint) return; if (b->number <= 0) return; target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "breakpoint-modified"); /* We want the output from gdb_breakpoint_query to go to mi->event_channel. One approach would be to just call gdb_breakpoint_query, and then use mi_out_put to send the current content of mi_outout into mi->event_channel. However, that will break if anything is output to mi_uiout prior to calling the breakpoint_created notifications. So, we use ui_out_redirect. */ ui_out_redirect (mi_uiout, mi->event_channel); TRY_CATCH (e, RETURN_MASK_ERROR) gdb_breakpoint_query (mi_uiout, b->number, NULL); ui_out_redirect (mi_uiout, NULL); gdb_flush (mi->event_channel); }
static void mi_solib_loaded (struct so_list *solib) { struct mi_interp *mi = top_level_interpreter_data (); struct ui_out *uiout = interp_ui_out (top_level_interpreter ()); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "library-loaded"); ui_out_redirect (uiout, mi->event_channel); ui_out_field_string (uiout, "id", solib->so_original_name); ui_out_field_string (uiout, "target-name", solib->so_original_name); ui_out_field_string (uiout, "host-name", solib->so_name); ui_out_field_int (uiout, "symbols-loaded", solib->symbols_loaded); if (!gdbarch_has_global_solist (target_gdbarch ())) { ui_out_field_fmt (uiout, "thread-group", "i%d", current_inferior ()->num); } ui_out_redirect (uiout, NULL); gdb_flush (mi->event_channel); }
void annotate_frames_invalid(void) { if (annotation_level > 1) { target_terminal_ours(); printf_unfiltered(("\n\032\032frames-invalid\n")); } }
void async_enable_stdin (void *dummy) { /* See NOTE in async_disable_stdin() */ /* FIXME: cagney/1999-09-27: Call this before clearing sync_execution. Current target_terminal_ours() implementations check for sync_execution before switching the terminal. */ target_terminal_ours (); pop_prompt (); sync_execution = 0; }
void breakpoints_changed(void) { if (annotation_level > 1) { target_terminal_ours(); printf_unfiltered(("\n\032\032breakpoints-invalid\n")); if (ignore_count_changed) ignore_count_changed = 0; /* Avoid multiple break annotations. */ } }
static void mi_inferior_removed (struct inferior *inf) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "thread-group-removed,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); }
static void annotate_breakpoints_invalid (void) { if (annotation_level == 2 && (!breakpoints_invalid_emitted || async_background_execution_p ())) { target_terminal_ours (); printf_unfiltered (("\n\032\032breakpoints-invalid\n")); breakpoints_invalid_emitted = 1; } }
void async_enable_stdin (void) { struct ui *ui = current_ui; if (ui->prompt_state == PROMPT_BLOCKED) { target_terminal_ours (); ui_register_input_event_handler (ui); ui->prompt_state = PROMPT_NEEDED; } }
static void mi_tsv_created (const struct trace_state_variable *tsv) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "tsv-created," "name=\"%s\",initial=\"%s\"\n", tsv->name, plongest (tsv->initial_value)); gdb_flush (mi->event_channel); }
static void tui_about_to_proceed (void) { /* Leave tui mode (optional). */ #if 0 if (tui_active) { target_terminal_ours (); endwin (); target_terminal_inferior (); } #endif tui_target_has_run = 1; }
static void mi_tsv_deleted (const struct trace_state_variable *tsv) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); if (tsv != NULL) fprintf_unfiltered (mi->event_channel, "tsv-deleted," "name=\"%s\"\n", tsv->name); else fprintf_unfiltered (mi->event_channel, "tsv-deleted\n"); gdb_flush (mi->event_channel); }
static void mi_inferior_exit (struct inferior *inf) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); if (inf->has_exit_code) fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"i%d\",exit-code=\"%s\"", inf->num, int_string (inf->exit_code, 8, 0, 0, 1)); else fprintf_unfiltered (mi->event_channel, "thread-group-exited,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); }
static int report_initial_inferior (struct inferior *inf, void *closure) { /* This function is called from mi_intepreter_init, and since mi_inferior_added assumes that inferior is fully initialized and top_level_interpreter_data is set, we cannot call it here. */ struct mi_interp *mi = closure; target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "thread-group-added,id=\"i%d\"", inf->num); gdb_flush (mi->event_channel); return 0; }
static void print_any_exception (struct ui_file *file, const char *prefix, struct gdb_exception e) { if (e.reason < 0 && e.message != NULL) { target_terminal_ours (); wrap_here (""); /* Force out any buffered output. */ gdb_flush (gdb_stdout); annotate_error_begin (); /* Print the prefix. */ if (prefix != NULL && prefix[0] != '\0') fputs_filtered (prefix, file); print_exception (file, e); } }
static void mi_breakpoint_deleted (struct breakpoint *b) { struct mi_interp *mi = top_level_interpreter_data (); if (mi_suppress_notification.breakpoint) return; if (b->number <= 0) return; target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"", b->number); gdb_flush (mi->event_channel); }
static void mi_thread_exit (struct thread_info *t, int silent) { struct mi_interp *mi; struct inferior *inf; if (silent) return; inf = find_inferior_pid (ptid_get_pid (t->ptid)); mi = top_level_interpreter_data (); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\",group-id=\"i%d\"", t->num, inf->num); gdb_flush (mi->event_channel); }
static void mi_traceframe_changed (int tfnum, int tpnum) { struct mi_interp *mi = top_level_interpreter_data (); if (mi_suppress_notification.traceframe) return; target_terminal_ours (); if (tfnum >= 0) fprintf_unfiltered (mi->event_channel, "traceframe-changed," "num=\"%d\",tracepoint=\"%d\"\n", tfnum, tpnum); else fprintf_unfiltered (mi->event_channel, "traceframe-changed,end"); gdb_flush (mi->event_channel); }
void async_enable_stdin (void *dummy) { if (stdin_enabled) return; stdin_enabled = 1; /* See NOTE in async_disable_stdin() */ /* FIXME: cagney/1999-09-27: Call this before clearing sync_execution. Current target_terminal_ours() implementations check for sync_execution before switching the terminal. */ target_terminal_ours (); pop_prompt (); /* This is bogus... We shouldn't have to lie about the type of execution in order to implement the terminal_ours... sync_execution = 0; */ }
static void mi_solib_unloaded (struct so_list *solib) { struct mi_interp *mi = top_level_interpreter_data (); target_terminal_ours (); if (gdbarch_has_global_solist (target_gdbarch ())) fprintf_unfiltered (mi->event_channel, "library-unloaded,id=\"%s\",target-name=\"%s\"," "host-name=\"%s\"", solib->so_original_name, solib->so_original_name, solib->so_name); else fprintf_unfiltered (mi->event_channel, "library-unloaded,id=\"%s\",target-name=\"%s\"," "host-name=\"%s\",thread-group=\"i%d\"", solib->so_original_name, solib->so_original_name, solib->so_name, current_inferior ()->num); gdb_flush (mi->event_channel); }
static void mi_thread_exit (struct thread_info *t, int silent) { struct mi_interp *mi; struct inferior *inf; struct cleanup *old_chain; if (silent) return; inf = find_inferior_ptid (t->ptid); mi = top_level_interpreter_data (); old_chain = make_cleanup_restore_target_terminal (); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\",group-id=\"i%d\"", t->num, inf->num); gdb_flush (mi->event_channel); do_cleanups (old_chain); }
static void mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr, ssize_t len, const bfd_byte *myaddr) { struct mi_interp *mi = top_level_interpreter_data (); struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); struct obj_section *sec; if (mi_suppress_notification.memory) return; target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "memory-changed"); ui_out_redirect (mi_uiout, mi->event_channel); ui_out_field_fmt (mi_uiout, "thread-group", "i%d", inferior->num); ui_out_field_core_addr (mi_uiout, "addr", target_gdbarch (), memaddr); ui_out_field_fmt (mi_uiout, "len", "%s", hex_string (len)); /* Append 'type=code' into notification if MEMADDR falls in the range of sections contain code. */ sec = find_pc_section (memaddr); if (sec != NULL && sec->objfile != NULL) { flagword flags = bfd_get_section_flags (sec->objfile->obfd, sec->the_bfd_section); if (flags & SEC_CODE) ui_out_field_string (mi_uiout, "type", "code"); } ui_out_redirect (mi_uiout, NULL); gdb_flush (mi->event_channel); }
/* 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; }
static void mi_command_param_changed (const char *param, const char *value) { struct mi_interp *mi = top_level_interpreter_data (); struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); if (mi_suppress_notification.cmd_param_changed) return; target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "cmd-param-changed"); ui_out_redirect (mi_uiout, mi->event_channel); ui_out_field_string (mi_uiout, "param", param); ui_out_field_string (mi_uiout, "value", value); ui_out_redirect (mi_uiout, NULL); gdb_flush (mi->event_channel); }
static void mi_tsv_modified (const struct trace_state_variable *tsv) { struct mi_interp *mi = top_level_interpreter_data (); struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); target_terminal_ours (); fprintf_unfiltered (mi->event_channel, "tsv-modified"); ui_out_redirect (mi_uiout, mi->event_channel); ui_out_field_string (mi_uiout, "name", tsv->name); ui_out_field_string (mi_uiout, "initial", plongest (tsv->initial_value)); if (tsv->value_known) ui_out_field_string (mi_uiout, "current", plongest (tsv->value)); ui_out_redirect (mi_uiout, NULL); gdb_flush (mi->event_channel); }
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); }
/* Displays the prompt. The prompt that is displayed is the current top of the prompt stack, if the argument NEW_PROMPT is 0. Otherwise, it displays whatever NEW_PROMPT is. This is used after each gdb command has completed, and in the following cases: 1. when the user enters a command line which is ended by '\' indicating that the command will continue on the next line. In that case the prompt that is displayed is the empty string. 2. When the user is entering 'commands' for a breakpoint, or actions for a tracepoint. In this case the prompt will be '>' 3. Other???? FIXME: 2. & 3. not implemented yet for async. */ void display_gdb_prompt (char *new_prompt) { int prompt_length = 0; char *gdb_prompt = get_prompt (); static int stdin_handler_removed = 0; /* APPLE LOCAL begin Inform user about debugging optimized code */ if (strcmp (gdb_prompt, "") != 0) { adjust_prompts_for_optimized_code (); gdb_prompt = get_prompt (); } /* APPLE LOCAL end Inform user about debugging optimized code */ /* Each interpreter has its own rules on displaying the command prompt. */ if (!current_interp_display_prompt_p ()) return; if (target_executing && sync_execution) { /* This is to trick readline into not trying to display the prompt. Even though we display the prompt using this function, readline still tries to do its own display if we don't call rl_callback_handler_install and rl_callback_handler_remove (which readline detects because a global variable is not set). If readline did that, it could mess up gdb signal handlers for SIGINT. Readline assumes that between calls to rl_set_signals and rl_clear_signals gdb doesn't do anything with the signal handlers. Well, that's not the case, because when the target executes we change the SIGINT signal handler. If we allowed readline to display the prompt, the signal handler change would happen exactly between the calls to the above two functions. Calling rl_callback_handler_remove(), does the job. */ delete_file_handler (input_fd); stdin_handler_removed = 1; rl_callback_handler_remove (); return; } if (!new_prompt) { /* Just use the top of the prompt stack. */ prompt_length = strlen (PREFIX (0)) + strlen (SUFFIX (0)) + strlen (gdb_prompt) + 1; new_prompt = (char *) alloca (prompt_length); /* Prefix needs to have new line at end. */ strcpy (new_prompt, PREFIX (0)); strcat (new_prompt, gdb_prompt); /* Suffix needs to have a new line at end and \032 \032 at beginning. */ strcat (new_prompt, SUFFIX (0)); } if (async_command_editing_p) { /* Claim the terminal before we reset it. It is quick if the terminal is already ours, and if not, we are going to lose when we try to install the callback handler otherwise. We can get here with the terminal still belonging to the inferior if it dies an unexpected death, and somebody forgets to clean up properly. Better safe than sorry... */ target_terminal_ours (); if (stdin_handler_removed) { add_file_handler (input_fd, stdin_event_handler, 0); stdin_handler_removed = 0; } rl_callback_handler_remove (); rl_callback_handler_install (new_prompt, input_handler); } /* new_prompt at this point can be the top of the stack or the one passed in */ else if (new_prompt) { /* Don't use a _filtered function here. It causes the assumed character position to be off, since the newline we read from the user is not accounted for. */ fputs_unfiltered (new_prompt, gdb_stdout); gdb_flush (gdb_stdout); } }