/* Function to set the disassembly window's content. Disassemble count lines starting at pc. Return address of the count'th instruction after pc. */ static CORE_ADDR tui_disassemble (struct tui_asm_line* asm_lines, CORE_ADDR pc, int count) { struct ui_file *gdb_dis_out; /* now init the ui_file structure */ gdb_dis_out = tui_sfileopen (256); /* Now construct each line */ for (; count > 0; count--, asm_lines++) { if (asm_lines->addr_string) xfree (asm_lines->addr_string); if (asm_lines->insn) xfree (asm_lines->insn); print_address (pc, gdb_dis_out); asm_lines->addr = pc; asm_lines->addr_string = xstrdup (tui_file_get_strbuf (gdb_dis_out)); ui_file_rewind (gdb_dis_out); pc = pc + gdb_print_insn (pc, gdb_dis_out); asm_lines->insn = xstrdup (tui_file_get_strbuf (gdb_dis_out)); /* reset the buffer to empty */ ui_file_rewind (gdb_dis_out); } ui_file_delete (gdb_dis_out); return pc; }
static void tui_restore_gdbout (void *ui) { ui_file_delete (gdb_stdout); gdb_stdout = (struct ui_file*) ui; pagination_enabled = 1; }
/* Get a printable name for the function at the address. The symbol name is demangled if demangling is turned on. Returns a pointer to a static area holding the result. */ static char* tui_get_function_from_frame (struct frame_info *fi) { static char name[256]; struct ui_file *stream = tui_sfileopen (256); char *p; print_address_symbolic (get_frame_pc (fi), stream, demangle, ""); p = tui_file_get_strbuf (stream); /* Use simple heuristics to isolate the function name. The symbol can be demangled and we can have function parameters. Remove them because the status line is too short to display them. */ if (*p == '<') p++; strncpy (name, p, sizeof (name)); p = strchr (name, '('); if (!p) p = strchr (name, '>'); if (p) *p = 0; p = strchr (name, '+'); if (p) *p = 0; ui_file_delete (stream); return name; }
/* Disable command input through the standard CLI channels. Used in the suspend proc for interpreters that use the standard gdb readline interface, like the cli & the mi. */ void gdb_disable_readline (void) { /* FIXME - It is too heavyweight to delete and remake these every time you run an interpreter that needs readline. It is probably better to have the interpreters cache these, which in turn means that this needs to be moved into interpreter specific code. */ #if 0 ui_file_delete (gdb_stdout); ui_file_delete (gdb_stderr); gdb_stdlog = NULL; gdb_stdtarg = NULL; #endif rl_callback_handler_remove (); delete_file_handler (input_fd); }
static void do_serial_close (struct serial *scb, int really_close) { struct serial *tmp_scb; last_serial_opened = NULL; if (serial_logfp) { fputs_unfiltered ("\nEnd of log\n", serial_logfp); serial_current_type = 0; /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ ui_file_delete (serial_logfp); serial_logfp = NULL; } /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you should fix your code instead. */ if (!scb) return; scb->refcnt--; if (scb->refcnt > 0) return; /* ensure that the FD has been taken out of async mode */ if (scb->async_handler != NULL) serial_async (scb, NULL, NULL); if (really_close) scb->ops->close (scb); if (scb->name) xfree (scb->name); if (scb_base == scb) scb_base = scb_base->next; else for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next) { if (tmp_scb->next != scb) continue; tmp_scb->next = tmp_scb->next->next; break; } xfree (scb); }
/* If we've pushed output files, close them and pop them. */ static void pop_output_files (void) { /* Only delete one of the files -- they are all set to the same value. */ ui_file_delete (gdb_stdout); gdb_stdout = saved_output.out; gdb_stderr = saved_output.err; gdb_stdlog = saved_output.log; gdb_stdtarg = saved_output.targ; saved_output.out = NULL; saved_output.err = NULL; saved_output.log = NULL; saved_output.targ = NULL; ui_out_redirect (uiout, NULL); }
static void do_serial_close (struct serial *scb, int really_close) { struct serial *tmp_scb; if (serial_logfp) { fputs_unfiltered ("\nEnd of log\n", serial_logfp); serial_current_type = 0; /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ ui_file_delete (serial_logfp); serial_logfp = NULL; } /* ensure that the FD has been taken out of async mode. */ if (scb->async_handler != NULL) serial_async (scb, NULL, NULL); if (really_close) scb->ops->close (scb); if (scb->name) xfree (scb->name); /* For serial_is_open. */ scb->bufp = NULL; if (scb_base == scb) scb_base = scb_base->next; else for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next) { if (tmp_scb->next != scb) continue; tmp_scb->next = tmp_scb->next->next; break; } serial_unref (scb); }
static int mi_set_logging (struct interp *interp, int start_log, struct ui_file *out, struct ui_file *logfile) { struct mi_interp *mi = interp_data (interp); if (!mi) return 0; if (start_log) { /* The tee created already is based on gdb_stdout, which for MI is a console and so we end up in an infinite loop of console writing to ui_file writing to console etc. So discard the existing tee (it hasn't been used yet, and MI won't ever use it), and create one based on raw_stdout instead. */ if (logfile) { ui_file_delete (out); out = tee_file_new (raw_stdout, 0, logfile, 0); } saved_raw_stdout = raw_stdout; raw_stdout = out; } else { raw_stdout = saved_raw_stdout; saved_raw_stdout = NULL; } mi_console_set_raw (mi->out, raw_stdout); mi_console_set_raw (mi->err, raw_stdout); mi_console_set_raw (mi->log, raw_stdout); mi_console_set_raw (mi->targ, raw_stdout); mi_console_set_raw (mi->event_channel, raw_stdout); return 1; }
static int frscm_print_frame_smob (SCM self, SCM port, scm_print_state *pstate) { frame_smob *f_smob = (frame_smob *) SCM_SMOB_DATA (self); struct ui_file *strfile; char *s; gdbscm_printf (port, "#<%s ", frame_smob_name); strfile = mem_fileopen (); fprint_frame_id (strfile, f_smob->frame_id); s = ui_file_xstrdup (strfile, NULL); gdbscm_printf (port, "%s", s); ui_file_delete (strfile); xfree (s); scm_puts (">", port); scm_remember_upto_here_1 (self); /* Non-zero means success. */ return 1; }
static void do_ui_file_delete (void *arg) { ui_file_delete (arg); }
/* Create the status line to display as much information as we can on this single line: target name, process number, current function, current line, current PC, SingleKey mode. */ static char* tui_make_status_line (struct tui_locator_element *loc) { char *string; char line_buf[50], *pname; char *buf; int status_size; int i, proc_width; const char *pid_name; const char *pc_buf; int target_width; int pid_width; int line_width; int pc_width; struct ui_file *pc_out; if (ptid_equal (inferior_ptid, null_ptid)) pid_name = "No process"; else pid_name = target_pid_to_str (inferior_ptid); target_width = strlen (target_shortname); if (target_width > MAX_TARGET_WIDTH) target_width = MAX_TARGET_WIDTH; pid_width = strlen (pid_name); if (pid_width > MAX_PID_WIDTH) pid_width = MAX_PID_WIDTH; status_size = tui_term_width (); string = (char *) xmalloc (status_size + 1); buf = (char*) alloca (status_size + 1); /* Translate line number and obtain its size. */ if (loc->line_no > 0) sprintf (line_buf, "%d", loc->line_no); else strcpy (line_buf, "??"); line_width = strlen (line_buf); if (line_width < MIN_LINE_WIDTH) line_width = MIN_LINE_WIDTH; /* Translate PC address. */ pc_out = tui_sfileopen (128); deprecated_print_address_numeric (loc->addr, 1, pc_out); pc_buf = tui_file_get_strbuf (pc_out); pc_width = strlen (pc_buf); /* First determine the amount of proc name width we have available. The +1 are for a space separator between fields. The -1 are to take into account the \0 counted by sizeof. */ proc_width = (status_size - (target_width + 1) - (pid_width + 1) - (sizeof (PROC_PREFIX) - 1 + 1) - (sizeof (LINE_PREFIX) - 1 + line_width + 1) - (sizeof (PC_PREFIX) - 1 + pc_width + 1) - (tui_current_key_mode == TUI_SINGLE_KEY_MODE ? (sizeof (SINGLE_KEY) - 1 + 1) : 0)); /* If there is no room to print the function name, try by removing some fields. */ if (proc_width < MIN_PROC_WIDTH) { proc_width += target_width + 1; target_width = 0; if (proc_width < MIN_PROC_WIDTH) { proc_width += pid_width + 1; pid_width = 0; if (proc_width <= MIN_PROC_WIDTH) { proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1; pc_width = 0; if (proc_width < 0) { proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1; line_width = 0; if (proc_width < 0) proc_width = 0; } } } } /* Now convert elements to string form. */ pname = loc->proc_name; /* Now create the locator line from the string version of the elements. We could use sprintf() here but that wouldn't ensure that we don't overrun the size of the allocated buffer. strcat_to_buf() will. */ *string = (char) 0; if (target_width > 0) { sprintf (buf, "%*.*s ", -target_width, target_width, target_shortname); strcat_to_buf (string, status_size, buf); } if (pid_width > 0) { sprintf (buf, "%*.*s ", -pid_width, pid_width, pid_name); strcat_to_buf (string, status_size, buf); } /* Show whether we are in SingleKey mode. */ if (tui_current_key_mode == TUI_SINGLE_KEY_MODE) { strcat_to_buf (string, status_size, SINGLE_KEY); strcat_to_buf (string, status_size, " "); } /* Procedure/class name. */ if (proc_width > 0) { if (strlen (pname) > proc_width) sprintf (buf, "%s%*.*s* ", PROC_PREFIX, 1 - proc_width, proc_width - 1, pname); else sprintf (buf, "%s%*.*s ", PROC_PREFIX, -proc_width, proc_width, pname); strcat_to_buf (string, status_size, buf); } if (line_width > 0) { sprintf (buf, "%s%*.*s ", LINE_PREFIX, -line_width, line_width, line_buf); strcat_to_buf (string, status_size, buf); } if (pc_width > 0) { strcat_to_buf (string, status_size, PC_PREFIX); strcat_to_buf (string, status_size, pc_buf); } for (i = strlen (string); i < status_size; i++) string[i] = ' '; string[status_size] = (char) 0; ui_file_delete (pc_out); return string; }
static PyObject * archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw) { static char *keywords[] = { "start_pc", "end_pc", "count", NULL }; CORE_ADDR start, end = 0; CORE_ADDR pc; gdb_py_ulongest start_temp; long count = 0, i; PyObject *result_list, *end_obj = NULL, *count_obj = NULL; struct gdbarch *gdbarch = NULL; ARCHPY_REQUIRE_VALID (self, gdbarch); if (!PyArg_ParseTupleAndKeywords (args, kw, GDB_PY_LLU_ARG "|OO", keywords, &start_temp, &end_obj, &count_obj)) return NULL; start = start_temp; if (end_obj) { if (PyLong_Check (end_obj)) end = PyLong_AsUnsignedLongLong (end_obj); else if (PyInt_Check (end_obj)) /* If the end_pc value is specified without a trailing 'L', end_obj will be an integer and not a long integer. */ end = PyInt_AsLong (end_obj); else { Py_DECREF (end_obj); Py_XDECREF (count_obj); PyErr_SetString (PyExc_TypeError, _("Argument 'end_pc' should be a (long) integer.")); return NULL; } if (end < start) { Py_DECREF (end_obj); Py_XDECREF (count_obj); PyErr_SetString (PyExc_ValueError, _("Argument 'end_pc' should be greater than or " "equal to the argument 'start_pc'.")); return NULL; } } if (count_obj) { count = PyInt_AsLong (count_obj); if (PyErr_Occurred () || count < 0) { Py_DECREF (count_obj); Py_XDECREF (end_obj); PyErr_SetString (PyExc_TypeError, _("Argument 'count' should be an non-negative " "integer.")); return NULL; } } result_list = PyList_New (0); if (result_list == NULL) return NULL; for (pc = start, i = 0; /* All args are specified. */ (end_obj && count_obj && pc <= end && i < count) /* end_pc is specified, but no count. */ || (end_obj && count_obj == NULL && pc <= end) /* end_pc is not specified, but a count is. */ || (end_obj == NULL && count_obj && i < count) /* Both end_pc and count are not specified. */ || (end_obj == NULL && count_obj == NULL && pc == start);) { int insn_len = 0; char *as = NULL; struct ui_file *memfile = mem_fileopen (); PyObject *insn_dict = PyDict_New (); volatile struct gdb_exception except; if (insn_dict == NULL) { Py_DECREF (result_list); ui_file_delete (memfile); return NULL; } if (PyList_Append (result_list, insn_dict)) { Py_DECREF (result_list); Py_DECREF (insn_dict); ui_file_delete (memfile); return NULL; /* PyList_Append Sets the exception. */ } TRY_CATCH (except, RETURN_MASK_ALL) { insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL); } if (except.reason < 0) { Py_DECREF (result_list); ui_file_delete (memfile); gdbpy_convert_exception (except); return NULL; } as = ui_file_xstrdup (memfile, NULL); if (PyDict_SetItemString (insn_dict, "addr", gdb_py_long_from_ulongest (pc)) || PyDict_SetItemString (insn_dict, "asm", PyString_FromString (*as ? as : "<unknown>")) || PyDict_SetItemString (insn_dict, "length", PyInt_FromLong (insn_len))) { Py_DECREF (result_list); ui_file_delete (memfile); xfree (as); return NULL; } pc += insn_len; i++; ui_file_delete (memfile); xfree (as); }
static int inspect_type (struct demangle_parse_info *info, struct demangle_component *ret_comp, canonicalization_ftype *finder, void *data) { int i; char *name; struct symbol *sym; /* Copy the symbol's name from RET_COMP and look it up in the symbol table. */ name = (char *) alloca (ret_comp->u.s_name.len + 1); memcpy (name, ret_comp->u.s_name.s, ret_comp->u.s_name.len); name[ret_comp->u.s_name.len] = '\0'; /* Ignore any typedefs that should not be substituted. */ for (i = 0; i < ARRAY_SIZE (ignore_typedefs); ++i) { if (strcmp (name, ignore_typedefs[i]) == 0) return 0; } sym = NULL; TRY { sym = lookup_symbol (name, 0, VAR_DOMAIN, 0); } CATCH (except, RETURN_MASK_ALL) { return 0; } END_CATCH if (sym != NULL) { struct type *otype = SYMBOL_TYPE (sym); if (finder != NULL) { const char *new_name = (*finder) (otype, data); if (new_name != NULL) { ret_comp->u.s_name.s = new_name; ret_comp->u.s_name.len = strlen (new_name); return 1; } return 0; } /* If the type is a typedef or namespace alias, replace it. */ if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF || TYPE_CODE (otype) == TYPE_CODE_NAMESPACE) { long len; int is_anon; struct type *type; struct demangle_parse_info *i; struct ui_file *buf; /* Get the real type of the typedef. */ type = check_typedef (otype); /* If the symbol is a namespace and its type name is no different than the name we looked up, this symbol is not a namespace alias and does not need to be substituted. */ if (TYPE_CODE (otype) == TYPE_CODE_NAMESPACE && strcmp (TYPE_NAME (type), name) == 0) return 0; is_anon = (TYPE_TAG_NAME (type) == NULL && (TYPE_CODE (type) == TYPE_CODE_ENUM || TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION)); if (is_anon) { struct type *last = otype; /* Find the last typedef for the type. */ while (TYPE_TARGET_TYPE (last) != NULL && (TYPE_CODE (TYPE_TARGET_TYPE (last)) == TYPE_CODE_TYPEDEF)) last = TYPE_TARGET_TYPE (last); /* If there is only one typedef for this anonymous type, do not substitute it. */ if (type == otype) return 0; else /* Use the last typedef seen as the type for this anonymous type. */ type = last; } buf = mem_fileopen (); TRY { type_print (type, "", buf, -1); } /* If type_print threw an exception, there is little point in continuing, so just bow out gracefully. */ CATCH (except, RETURN_MASK_ERROR) { ui_file_delete (buf); return 0; } END_CATCH name = ui_file_obsavestring (buf, &info->obstack, &len); ui_file_delete (buf); /* Turn the result into a new tree. Note that this tree will contain pointers into NAME, so NAME cannot be free'd until all typedef conversion is done and the final result is converted into a string. */ i = cp_demangled_name_to_comp (name, NULL); if (i != NULL) { /* Merge the two trees. */ cp_merge_demangle_parse_infos (info, ret_comp, i); /* Replace any newly introduced typedefs -- but not if the type is anonymous (that would lead to infinite looping). */ if (!is_anon) replace_typedefs (info, ret_comp, finder, data); } else { /* This shouldn't happen unless the type printer has output something that the name parser cannot grok. Nonetheless, an ounce of prevention... Canonicalize the name again, and store it in the current node (RET_COMP). */ char *canon = cp_canonicalize_string_no_typedefs (name); if (canon != NULL) { /* Copy the canonicalization into the obstack and free CANON. */ name = copy_string_to_obstack (&info->obstack, canon, &len); xfree (canon); } ret_comp->u.s_name.s = name; ret_comp->u.s_name.len = len; } return 1; }
void add_language (const struct language_defn *lang) { /* For the "set language" command. */ static const char **language_names = NULL; /* For the "help set language" command. */ char *language_set_doc = NULL; int i; struct ui_file *tmp_stream; if (lang->la_magic != LANG_MAGIC) { fprintf_unfiltered (gdb_stderr, "Magic number of %s language struct wrong\n", lang->la_name); internal_error (__FILE__, __LINE__, _("failed internal consistency check")); } if (!languages) { languages_allocsize = DEFAULT_ALLOCSIZE; languages = (const struct language_defn **) xmalloc (languages_allocsize * sizeof (*languages)); } if (languages_size >= languages_allocsize) { languages_allocsize *= 2; languages = (const struct language_defn **) xrealloc ((char *) languages, languages_allocsize * sizeof (*languages)); } languages[languages_size++] = lang; /* Build the language names array, to be used as enumeration in the set language" enum command. */ language_names = xrealloc (language_names, (languages_size + 1) * sizeof (const char *)); for (i = 0; i < languages_size; ++i) language_names[i] = languages[i]->la_name; language_names[i] = NULL; /* Build the "help set language" docs. */ tmp_stream = mem_fileopen (); fprintf_unfiltered (tmp_stream, _("Set the current source language.\n" "The currently understood settings are:\n\nlocal or " "auto Automatic setting based on source file\n")); for (i = 0; i < languages_size; ++i) { /* Already dealt with these above. */ if (languages[i]->la_language == language_unknown || languages[i]->la_language == language_auto) continue; /* FIXME: i18n: for now assume that the human-readable name is just a capitalization of the internal name. */ fprintf_unfiltered (tmp_stream, "%-16s Use the %c%s language\n", languages[i]->la_name, /* Capitalize first letter of language name. */ toupper (languages[i]->la_name[0]), languages[i]->la_name + 1); } language_set_doc = ui_file_xstrdup (tmp_stream, NULL); ui_file_delete (tmp_stream); add_setshow_enum_cmd ("language", class_support, (const char **) language_names, &language, language_set_doc, _("Show the current source language."), NULL, set_language_command, show_language_command, &setlist, &showlist); xfree (language_set_doc); }