static void inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty) { char *exec_file; pid_t pid; struct inferior *inf; /* Do not change either targets above or the same target if already present. The reason is the target stack is shared across multiple inferiors. */ int ops_already_pushed = target_is_pushed (ops); struct cleanup *back_to = NULL; pid = parse_pid_to_attach (args); if (pid == getpid ()) /* Trying to m********e? */ error (_("I refuse to debug myself!")); if (! ops_already_pushed) { /* target_pid_to_str already uses the target. Also clear possible core file with its process_stratum. */ push_target (ops); back_to = make_cleanup_unpush_target (ops); } if (from_tty) { exec_file = get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered (_("Attaching to %s\n"), target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } #ifdef PT_ATTACH errno = 0; ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0); if (errno != 0) perror_with_name (("ptrace")); #else error (_("This system does not support attaching to a process")); #endif inf = current_inferior (); inferior_appeared (inf, pid); inf->attach_flag = 1; inferior_ptid = pid_to_ptid (pid); /* Always add a main thread. If some target extends the ptrace target, it should decorate the ptid later with more info. */ add_thread_silent (inferior_ptid); if (! ops_already_pushed) discard_cleanups (back_to); }
static LdInfo * rs6000_core_ldinfo (bfd *abfd) { struct bfd_section *ldinfo_sec; int ldinfo_size; gdb_byte *ldinfo_buf; struct cleanup *cleanup; ldinfo_sec = bfd_get_section_by_name (abfd, ".ldinfo"); if (ldinfo_sec == NULL) error (_("cannot find .ldinfo section from core file: %s\n"), bfd_errmsg (bfd_get_error ())); ldinfo_size = bfd_get_section_size (ldinfo_sec); ldinfo_buf = xmalloc (ldinfo_size); cleanup = make_cleanup (xfree, ldinfo_buf); if (! bfd_get_section_contents (abfd, ldinfo_sec, ldinfo_buf, 0, ldinfo_size)) error (_("unable to read .ldinfo section from core file: %s\n"), bfd_errmsg (bfd_get_error ())); discard_cleanups (cleanup); return (LdInfo *) ldinfo_buf; }
static void inf_ptrace_create_inferior (struct target_ops *ops, char *exec_file, char *allargs, char **env, int from_tty) { int pid; /* Do not change either targets above or the same target if already present. The reason is the target stack is shared across multiple inferiors. */ int ops_already_pushed = target_is_pushed (ops); struct cleanup *back_to = NULL; if (! ops_already_pushed) { /* Clear possible core file with its process_stratum. */ push_target (ops); back_to = make_cleanup_unpush_target (ops); } pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL, NULL, NULL, NULL); if (! ops_already_pushed) discard_cleanups (back_to); startup_inferior (START_INFERIOR_TRAPS_EXPECTED); /* On some targets, there must be some explicit actions taken after the inferior has been started up. */ target_post_startup_inferior (pid_to_ptid (pid)); }
static struct so_list * aix5_current_sos (void) { struct cleanup *old_chain = make_cleanup (null_cleanup, 0); struct so_list *sos; /* Fetch the list of mappings, excluding the main executable. */ sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_MAINEXEC, 0); /* Reverse the list; it looks nicer when we print it if the mappings are in the same order as in the map file. */ if (sos) { struct so_list *next = sos->next; sos->next = 0; while (next) { struct so_list *prev = sos; sos = next; next = next->next; sos->next = prev; } } discard_cleanups (old_chain); return sos; }
static PyObject * create_inferior_call_event_object (inferior_call_kind flag, ptid_t ptid, CORE_ADDR addr) { int pid; long tid, lwp; PyObject *event; PyObject *ptid_obj = NULL; PyObject *addr_obj = NULL; int failed; struct cleanup *cleanups; struct cleanup *member_cleanups; switch (flag) { case INFERIOR_CALL_PRE: event = create_event_object (&inferior_call_pre_event_object_type); break; case INFERIOR_CALL_POST: event = create_event_object (&inferior_call_post_event_object_type); break; default: return NULL; } cleanups = make_cleanup_py_decref (event); ptid_obj = gdbpy_create_ptid_object (ptid); if (ptid_obj == NULL) goto fail; member_cleanups = make_cleanup_py_decref (ptid_obj); failed = evpy_add_attribute (event, "ptid", ptid_obj) < 0; if (failed) goto fail; addr_obj = PyLong_FromLongLong (addr); if (addr_obj == NULL) goto fail; make_cleanup_py_decref (addr_obj); failed = evpy_add_attribute (event, "address", addr_obj) < 0; if (failed) goto fail; do_cleanups (member_cleanups); discard_cleanups (cleanups); return event; fail: do_cleanups (cleanups); return NULL; }
struct notif_event * remote_notif_parse (struct notif_client *nc, char *buf) { struct notif_event *event = nc->alloc_event (); struct cleanup *old_chain = make_cleanup (do_notif_event_xfree, event); if (notif_debug) fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name); nc->parse (nc, buf, event); discard_cleanups (old_chain); return event; }
void remote_notif_ack (struct notif_client *nc, char *buf) { struct notif_event *event = nc->alloc_event (); struct cleanup *old_chain = make_cleanup (do_notif_event_xfree, event); if (notif_debug) fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n", nc->ack_command); nc->parse (nc, buf, event); nc->ack (nc, buf, event); discard_cleanups (old_chain); }
static PyObject * create_register_changed_event_object (struct frame_info *frame, int regnum) { PyObject *event; PyObject *frame_obj = NULL; PyObject *regnum_obj = NULL; int failed; struct cleanup *cleanups; struct cleanup *member_cleanups; event = create_event_object (®ister_changed_event_object_type); if (event == NULL) return NULL; cleanups = make_cleanup_py_decref (event); frame_obj = frame_info_to_frame_object (frame); if (frame_obj == NULL) goto fail; member_cleanups = make_cleanup_py_decref (frame_obj); failed = evpy_add_attribute (event, "frame", frame_obj) < 0; if (failed) goto fail; regnum_obj = PyLong_FromLongLong (regnum); if (regnum_obj == NULL) goto fail; make_cleanup_py_decref (regnum_obj); failed = evpy_add_attribute (event, "regnum", regnum_obj) < 0; if (failed) goto fail; do_cleanups (member_cleanups); discard_cleanups (cleanups); return event; fail: do_cleanups (cleanups); return NULL; }
static PyObject * create_memory_changed_event_object (CORE_ADDR addr, ssize_t len) { PyObject *event; PyObject *addr_obj = NULL; PyObject *len_obj = NULL; int failed; struct cleanup *cleanups; struct cleanup *member_cleanups; event = create_event_object (&memory_changed_event_object_type); if (event == NULL) return NULL; cleanups = make_cleanup_py_decref (event); addr_obj = PyLong_FromLongLong (addr); if (addr_obj == NULL) goto fail; member_cleanups = make_cleanup_py_decref (addr_obj); failed = evpy_add_attribute (event, "address", addr_obj) < 0; if (failed) goto fail; len_obj = PyLong_FromLong (len); if (len_obj == NULL) goto fail; make_cleanup_py_decref (len_obj); failed = evpy_add_attribute (event, "length", len_obj) < 0; if (failed) goto fail; do_cleanups (member_cleanups); discard_cleanups (cleanups); return event; fail: do_cleanups (cleanups); return NULL; }
static void gcore_command (char *args, int from_tty) { struct cleanup *filename_chain; struct cleanup *bfd_chain; char *corefilename; bfd *obfd; /* No use generating a corefile without a target process. */ if (!target_has_execution) noprocess (); if (args && *args) corefilename = tilde_expand (args); else { /* Default corefile name is "core.PID". */ corefilename = xstrprintf ("core.%d", ptid_get_pid (inferior_ptid)); } filename_chain = make_cleanup (xfree, corefilename); if (info_verbose) fprintf_filtered (gdb_stdout, "Opening corefile '%s' for output.\n", corefilename); /* Open the output file. */ obfd = create_gcore_bfd (corefilename); /* Need a cleanup that will close and delete the file. */ bfd_chain = make_cleanup (do_bfd_delete_cleanup, obfd); /* Call worker function. */ write_gcore_file (obfd); /* Succeeded. */ discard_cleanups (bfd_chain); gdb_bfd_unref (obfd); fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename); do_cleanups (filename_chain); }
char * macro_expand_next (char **lexptr, macro_lookup_ftype *lookup_func, void *lookup_baton) { struct macro_buffer src, dest, tok; struct cleanup *back_to; /* Set up SRC to refer to the input text, pointed to by *lexptr. */ init_shared_buffer (&src, *lexptr, strlen (*lexptr)); /* Set up DEST to receive the expansion, if there is one. */ init_buffer (&dest, 0); dest.last_token = 0; back_to = make_cleanup (cleanup_macro_buffer, &dest); /* Get the text's first preprocessing token. */ if (! get_token (&tok, &src)) { do_cleanups (back_to); return 0; } /* If it's a macro invocation, expand it. */ if (maybe_expand (&dest, &tok, &src, 0, lookup_func, lookup_baton)) { /* It was a macro invocation! Package up the expansion as a null-terminated string and return it. Set *lexptr to the start of the next token in the input. */ appendc (&dest, '\0'); discard_cleanups (back_to); *lexptr = src.text; return dest.text; } else { /* It wasn't a macro invocation. */ do_cleanups (back_to); return 0; } }
char * macro_expand (const char *source, macro_lookup_ftype *lookup_func, void *lookup_func_baton) { struct macro_buffer src, dest; struct cleanup *back_to; init_shared_buffer (&src, (char *) source, strlen (source)); init_buffer (&dest, 0); dest.last_token = 0; back_to = make_cleanup (cleanup_macro_buffer, &dest); scan (&dest, &src, 0, lookup_func, lookup_func_baton); appendc (&dest, '\0'); discard_cleanups (back_to); return dest.text; }
static void gcore_command (char *args, int from_tty) { struct cleanup *old_chain; char *corefilename, corefilename_buffer[40]; bfd *obfd; /* No use generating a corefile without a target process. */ if (!target_has_execution) noprocess (); if (args && *args) corefilename = args; else { /* Default corefile name is "core.PID". */ xsnprintf (corefilename_buffer, sizeof (corefilename_buffer), "core.%d", PIDGET (inferior_ptid)); corefilename = corefilename_buffer; } if (info_verbose) fprintf_filtered (gdb_stdout, "Opening corefile '%s' for output.\n", corefilename); /* Open the output file. */ obfd = create_gcore_bfd (corefilename); /* Need a cleanup that will close and delete the file. */ old_chain = make_cleanup (do_bfd_delete_cleanup, obfd); /* Call worker function. */ write_gcore_file (obfd); /* Succeeded. */ fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename); discard_cleanups (old_chain); gdb_bfd_unref (obfd); }
static void record_btrace_open (char *args, int from_tty) { struct cleanup *disable_chain; struct thread_info *tp; DEBUG ("open"); record_preopen (); if (!target_has_execution) error (_("The program is not being run.")); if (!target_supports_btrace ()) error (_("Target does not support branch tracing.")); if (non_stop) error (_("Record btrace can't debug inferior in non-stop mode.")); gdb_assert (record_btrace_thread_observer == NULL); disable_chain = make_cleanup (null_cleanup, NULL); ALL_THREADS (tp) if (args == NULL || *args == 0 || number_is_in_list (args, tp->num)) { btrace_enable (tp); make_cleanup (record_btrace_disable_callback, tp); } record_btrace_auto_enable (); push_target (&record_btrace_ops); observer_notify_record_changed (current_inferior (), 1); discard_cleanups (disable_chain); }
struct command_line * get_command_line (enum command_control_type type, char *arg) { struct command_line *cmd; struct cleanup *old_chain = NULL; /* Allocate and build a new command line structure. */ cmd = build_command_line (type, arg); old_chain = make_cleanup_free_command_lines (&cmd); /* Read in the body of this command. */ if (recurse_read_control_structure (read_next_line, cmd, 0, 0) == invalid_control) { warning (_("Error reading in canned sequence of commands.")); do_cleanups (old_chain); return NULL; } discard_cleanups (old_chain); return cmd; }
static struct so_list * darwin_current_sos (void) { struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); int ptr_len = TYPE_LENGTH (ptr_type); unsigned int image_info_size; struct so_list *head = NULL; struct so_list *tail = NULL; int i; struct darwin_info *info = get_darwin_info (); /* Be sure image infos are loaded. */ darwin_load_image_infos (info); if (!darwin_dyld_version_ok (info)) return NULL; image_info_size = ptr_len * 3; /* Read infos for each solib. The first entry was rumored to be the executable itself, but this is not true when a large number of shared libraries are used (table expanded ?). We now check all entries, but discard executable images. */ for (i = 0; i < info->all_image.count; i++) { CORE_ADDR iinfo = info->all_image.info + i * image_info_size; gdb_byte buf[image_info_size]; CORE_ADDR load_addr; CORE_ADDR path_addr; struct mach_o_header_external hdr; unsigned long hdr_val; char *file_path; int errcode; struct darwin_so_list *dnew; struct so_list *newobj; struct cleanup *old_chain; /* Read image info from inferior. */ if (target_read_memory (iinfo, buf, image_info_size)) break; load_addr = extract_typed_address (buf, ptr_type); path_addr = extract_typed_address (buf + ptr_len, ptr_type); /* Read Mach-O header from memory. */ if (target_read_memory (load_addr, (gdb_byte *) &hdr, sizeof (hdr) - 4)) break; /* Discard wrong magic numbers. Shouldn't happen. */ hdr_val = extract_unsigned_integer (hdr.magic, sizeof (hdr.magic), byte_order); if (hdr_val != BFD_MACH_O_MH_MAGIC && hdr_val != BFD_MACH_O_MH_MAGIC_64) continue; /* Discard executable. Should happen only once. */ hdr_val = extract_unsigned_integer (hdr.filetype, sizeof (hdr.filetype), byte_order); if (hdr_val == BFD_MACH_O_MH_EXECUTE) continue; target_read_string (path_addr, &file_path, SO_NAME_MAX_PATH_SIZE - 1, &errcode); if (errcode) break; /* Create and fill the new so_list element. */ dnew = XCNEW (struct darwin_so_list); newobj = &dnew->sl; old_chain = make_cleanup (xfree, dnew); newobj->lm_info = &dnew->li; strncpy (newobj->so_name, file_path, SO_NAME_MAX_PATH_SIZE - 1); newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; strcpy (newobj->so_original_name, newobj->so_name); xfree (file_path); newobj->lm_info->lm_addr = load_addr; if (head == NULL) head = newobj; else tail->next = newobj; tail = newobj; discard_cleanups (old_chain); } return head; }
static void core_open (const char *arg, int from_tty) { const char *p; int siggy; struct cleanup *old_chain; char *temp; int scratch_chan; int flags; char *filename; target_preopen (from_tty); if (!arg) { if (core_bfd) error (_("No core file specified. (Use `detach' " "to stop debugging a core file.)")); else error (_("No core file specified.")); } filename = tilde_expand (arg); if (!IS_ABSOLUTE_PATH (filename)) { temp = concat (current_directory, "/", filename, (char *) NULL); xfree (filename); filename = temp; } old_chain = make_cleanup (xfree, filename); flags = O_BINARY | O_LARGEFILE; if (write_files) flags |= O_RDWR; else flags |= O_RDONLY; scratch_chan = gdb_open_cloexec (filename, flags, 0); if (scratch_chan < 0) perror_with_name (filename); gdb_bfd_ref_ptr temp_bfd (gdb_bfd_fopen (filename, gnutarget, write_files ? FOPEN_RUB : FOPEN_RB, scratch_chan)); if (temp_bfd == NULL) perror_with_name (filename); if (!bfd_check_format (temp_bfd.get (), bfd_core) && !gdb_check_format (temp_bfd.get ())) { /* Do it after the err msg */ /* FIXME: should be checking for errors from bfd_close (for one thing, on error it does not free all the storage associated with the bfd). */ error (_("\"%s\" is not a core dump: %s"), filename, bfd_errmsg (bfd_get_error ())); } /* Looks semi-reasonable. Toss the old core file and work on the new. */ do_cleanups (old_chain); unpush_target (&core_ops); core_bfd = temp_bfd.release (); old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/); core_gdbarch = gdbarch_from_bfd (core_bfd); /* Find a suitable core file handler to munch on core_bfd */ core_vec = sniff_core_bfd (core_bfd); validate_files (); core_data = XCNEW (struct target_section_table); /* Find the data section */ if (build_section_table (core_bfd, &core_data->sections, &core_data->sections_end)) error (_("\"%s\": Can't find sections: %s"), bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); /* If we have no exec file, try to set the architecture from the core file. We don't do this unconditionally since an exec file typically contains more information that helps us determine the architecture than a core file. */ if (!exec_bfd) set_gdbarch_from_file (core_bfd); push_target (&core_ops); discard_cleanups (old_chain); /* Do this before acknowledging the inferior, so if post_create_inferior throws (can happen easilly if you're loading a core file with the wrong exec), we aren't left with threads from the previous inferior. */ init_thread_list (); inferior_ptid = null_ptid; /* Need to flush the register cache (and the frame cache) from a previous debug session. If inferior_ptid ends up the same as the last debug session --- e.g., b foo; run; gcore core1; step; gcore core2; core core1; core core2 --- then there's potential for get_current_regcache to return the cached regcache of the previous session, and the frame cache being stale. */ registers_changed (); /* Build up thread list from BFD sections, and possibly set the current thread to the .reg/NN section matching the .reg section. */ bfd_map_over_sections (core_bfd, add_to_thread_list, bfd_get_section_by_name (core_bfd, ".reg")); if (ptid_equal (inferior_ptid, null_ptid)) { /* Either we found no .reg/NN section, and hence we have a non-threaded core (single-threaded, from gdb's perspective), or for some reason add_to_thread_list couldn't determine which was the "main" thread. The latter case shouldn't usually happen, but we're dealing with input here, which can always be broken in different ways. */ struct thread_info *thread = first_thread_of_process (-1); if (thread == NULL) { inferior_appeared (current_inferior (), CORELOW_PID); inferior_ptid = pid_to_ptid (CORELOW_PID); add_thread_silent (inferior_ptid); } else switch_to_thread (thread->ptid); } post_create_inferior (&core_ops, from_tty); /* Now go through the target stack looking for threads since there may be a thread_stratum target loaded on top of target core by now. The layer above should claim threads found in the BFD sections. */ TRY { target_update_thread_list (); } CATCH (except, RETURN_MASK_ERROR) { exception_print (gdb_stderr, except); }
/* Implementation of gdb.read_memory (address, length). Returns a Python buffer object with LENGTH bytes of the inferior's memory at ADDRESS. Both arguments are integers. */ static PyObject * infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) { int error = 0; CORE_ADDR addr, length; void *buffer = NULL; membuf_object *membuf_obj; PyObject *addr_obj, *length_obj; struct cleanup *cleanups; volatile struct gdb_exception except; static char *keywords[] = { "address", "length", NULL }; if (! PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords, &addr_obj, &length_obj)) return NULL; cleanups = make_cleanup (null_cleanup, NULL); TRY_CATCH (except, RETURN_MASK_ALL) { if (!get_addr_from_python (addr_obj, &addr) || !get_addr_from_python (length_obj, &length)) { error = 1; break; } buffer = xmalloc (length); make_cleanup (xfree, buffer); read_memory (addr, buffer, length); } if (except.reason < 0) { do_cleanups (cleanups); GDB_PY_HANDLE_EXCEPTION (except); } if (error) { do_cleanups (cleanups); return NULL; } membuf_obj = PyObject_New (membuf_object, &membuf_object_type); if (membuf_obj == NULL) { PyErr_SetString (PyExc_MemoryError, _("Could not allocate memory buffer object.")); do_cleanups (cleanups); return NULL; } discard_cleanups (cleanups); membuf_obj->buffer = buffer; membuf_obj->addr = addr; membuf_obj->length = length; return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0, Py_END_OF_BUFFER); }
static void parse_find_args (char *args, ULONGEST *max_countp, char **pattern_bufp, ULONGEST *pattern_lenp, CORE_ADDR *start_addrp, ULONGEST *search_space_lenp, bfd_boolean big_p) { /* Default to using the specified type. */ char size = '\0'; ULONGEST max_count = ~(ULONGEST) 0; /* Buffer to hold the search pattern. */ char *pattern_buf; /* Current size of search pattern buffer. We realloc space as needed. */ #define INITIAL_PATTERN_BUF_SIZE 100 ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE; /* Pointer to one past the last in-use part of pattern_buf. */ char *pattern_buf_end; ULONGEST pattern_len; CORE_ADDR start_addr; ULONGEST search_space_len; char *s = args; struct cleanup *old_cleanups; struct value *v; if (args == NULL) error (_("Missing search parameters.")); pattern_buf = xmalloc (pattern_buf_size); pattern_buf_end = pattern_buf; old_cleanups = make_cleanup (free_current_contents, &pattern_buf); /* Get search granularity and/or max count if specified. They may be specified in either order, together or separately. */ while (*s == '/') { ++s; while (*s != '\0' && *s != '/' && !isspace (*s)) { if (isdigit (*s)) { max_count = atoi (s); while (isdigit (*s)) ++s; continue; } switch (*s) { case 'b': case 'h': case 'w': case 'g': size = *s++; break; default: error (_("Invalid size granularity.")); } } while (isspace (*s)) ++s; } /* Get the search range. */ v = parse_to_comma_and_eval (&s); start_addr = value_as_address (v); if (*s == ',') ++s; while (isspace (*s)) ++s; if (*s == '+') { LONGEST len; ++s; v = parse_to_comma_and_eval (&s); len = value_as_long (v); if (len == 0) { printf_filtered (_("Empty search range.\n")); return; } if (len < 0) error (_("Invalid length.")); /* Watch for overflows. */ if (len > CORE_ADDR_MAX || (start_addr + len - 1) < start_addr) error (_("Search space too large.")); search_space_len = len; } else { CORE_ADDR end_addr; v = parse_to_comma_and_eval (&s); end_addr = value_as_address (v); if (start_addr > end_addr) error (_("Invalid search space, end preceeds start.")); search_space_len = end_addr - start_addr + 1; /* We don't support searching all of memory (i.e. start=0, end = 0xff..ff). Bail to avoid overflows later on. */ if (search_space_len == 0) error (_("Overflow in address range computation, choose smaller range.")); } if (*s == ',') ++s; /* Fetch the search string. */ while (*s != '\0') { LONGEST x; int val_bytes; while (isspace (*s)) ++s; v = parse_to_comma_and_eval (&s); val_bytes = TYPE_LENGTH (value_type (v)); /* Keep it simple and assume size == 'g' when watching for when we need to grow the pattern buf. */ if ((pattern_buf_end - pattern_buf + max (val_bytes, sizeof (int64_t))) > pattern_buf_size) { size_t current_offset = pattern_buf_end - pattern_buf; pattern_buf_size *= 2; pattern_buf = xrealloc (pattern_buf, pattern_buf_size); pattern_buf_end = pattern_buf + current_offset; } if (size != '\0') { x = value_as_long (v); switch (size) { case 'b': *pattern_buf_end++ = x; break; case 'h': put_bits (x, pattern_buf_end, 16, big_p); pattern_buf_end += sizeof (int16_t); break; case 'w': put_bits (x, pattern_buf_end, 32, big_p); pattern_buf_end += sizeof (int32_t); break; case 'g': put_bits (x, pattern_buf_end, 64, big_p); pattern_buf_end += sizeof (int64_t); break; } } else { memcpy (pattern_buf_end, value_contents_raw (v), val_bytes); pattern_buf_end += val_bytes; } if (*s == ',') ++s; while (isspace (*s)) ++s; } if (pattern_buf_end == pattern_buf) error (_("Missing search pattern.")); pattern_len = pattern_buf_end - pattern_buf; if (search_space_len < pattern_len) error (_("Search space too small to contain pattern.")); *max_countp = max_count; *pattern_bufp = pattern_buf; *pattern_lenp = pattern_len; *start_addrp = start_addr; *search_space_lenp = search_space_len; /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF to the caller now. */ discard_cleanups (old_cleanups); }
static struct block_symbol cp_lookup_symbol_via_imports (const char *scope, const char *name, const struct block *block, const domain_enum domain, const int search_scope_first, const int declaration_only, const int search_parents) { struct using_direct *current; struct block_symbol sym; int len; int directive_match; struct cleanup *searched_cleanup; sym.symbol = NULL; sym.block = NULL; /* First, try to find the symbol in the given namespace if requested. */ if (search_scope_first) sym = cp_lookup_symbol_in_namespace (scope, name, block, domain, 1); if (sym.symbol != NULL) return sym; /* Go through the using directives. If any of them add new names to the namespace we're searching in, see if we can find a match by applying them. */ for (current = block_using (block); current != NULL; current = current->next) { const char **excludep; len = strlen (current->import_dest); directive_match = (search_parents ? (startswith (scope, current->import_dest) && (len == 0 || scope[len] == ':' || scope[len] == '\0')) : strcmp (scope, current->import_dest) == 0); /* If the import destination is the current scope or one of its ancestors then it is applicable. */ if (directive_match && !current->searched) { /* Mark this import as searched so that the recursive call does not search it again. */ current->searched = 1; searched_cleanup = make_cleanup (reset_directive_searched, current); /* If there is an import of a single declaration, compare the imported declaration (after optional renaming by its alias) with the sought out name. If there is a match pass current->import_src as NAMESPACE to direct the search towards the imported namespace. */ if (current->declaration && strcmp (name, current->alias ? current->alias : current->declaration) == 0) sym = cp_lookup_symbol_in_namespace (current->import_src, current->declaration, block, domain, 1); /* If this is a DECLARATION_ONLY search or a symbol was found or this import statement was an import declaration, the search of this import is complete. */ if (declaration_only || sym.symbol != NULL || current->declaration) { current->searched = 0; discard_cleanups (searched_cleanup); if (sym.symbol != NULL) return sym; continue; } /* Do not follow CURRENT if NAME matches its EXCLUDES. */ for (excludep = current->excludes; *excludep; excludep++) if (strcmp (name, *excludep) == 0) break; if (*excludep) { discard_cleanups (searched_cleanup); continue; } if (current->alias != NULL && strcmp (name, current->alias) == 0) /* If the import is creating an alias and the alias matches the sought name. Pass current->import_src as the NAME to direct the search towards the aliased namespace. */ { sym = cp_lookup_symbol_in_namespace (scope, current->import_src, block, domain, 1); } else if (current->alias == NULL) { /* If this import statement creates no alias, pass current->inner as NAMESPACE to direct the search towards the imported namespace. */ sym = cp_lookup_symbol_via_imports (current->import_src, name, block, domain, 1, 0, 0); } current->searched = 0; discard_cleanups (searched_cleanup); if (sym.symbol != NULL) return sym; } } return null_block_symbol; }
struct event_location * string_to_explicit_location (const char **argp, const struct language_defn *language, int dont_throw) { struct cleanup *cleanup; struct event_location *location; /* It is assumed that input beginning with '-' and a non-digit character is an explicit location. "-p" is reserved, though, for probe locations. */ if (argp == NULL || *argp == '\0' || *argp[0] != '-' || !isalpha ((*argp)[1]) || ((*argp)[0] == '-' && (*argp)[1] == 'p')) return NULL; location = new_explicit_location (NULL); cleanup = make_cleanup_delete_event_location (location); /* Process option/argument pairs. dprintf_command requires that processing stop on ','. */ while ((*argp)[0] != '\0' && (*argp)[0] != ',') { int len; char *opt, *oarg; const char *start; struct cleanup *opt_cleanup, *oarg_cleanup; /* If *ARGP starts with a keyword, stop processing options. */ if (linespec_lexer_lex_keyword (*argp) != NULL) break; /* Mark the start of the string in case we need to rewind. */ start = *argp; /* Get the option string. */ opt = explicit_location_lex_one (argp, language); opt_cleanup = make_cleanup (xfree, opt); *argp = skip_spaces_const (*argp); /* Get the argument string. */ oarg = explicit_location_lex_one (argp, language); oarg_cleanup = make_cleanup (xfree, oarg); *argp = skip_spaces_const (*argp); /* Use the length of the option to allow abbreviations. */ len = strlen (opt); /* All options have a required argument. Checking for this required argument is deferred until later. */ if (strncmp (opt, "-source", len) == 0) EL_EXPLICIT (location)->source_filename = oarg; else if (strncmp (opt, "-function", len) == 0) EL_EXPLICIT (location)->function_name = oarg; else if (strncmp (opt, "-line", len) == 0) { if (oarg != NULL) { EL_EXPLICIT (location)->line_offset = linespec_parse_line_offset (oarg); do_cleanups (oarg_cleanup); do_cleanups (opt_cleanup); continue; } } else if (strncmp (opt, "-label", len) == 0) EL_EXPLICIT (location)->label_name = oarg; /* Only emit an "invalid argument" error for options that look like option strings. */ else if (opt[0] == '-' && !isdigit (opt[1])) { if (!dont_throw) error (_("invalid explicit location argument, \"%s\""), opt); } else { /* End of the explicit location specification. Stop parsing and return whatever explicit location was parsed. */ *argp = start; discard_cleanups (oarg_cleanup); do_cleanups (opt_cleanup); discard_cleanups (cleanup); return location; } /* It's a little lame to error after the fact, but in this case, it provides a much better user experience to issue the "invalid argument" error before any missing argument error. */ if (oarg == NULL && !dont_throw) error (_("missing argument for \"%s\""), opt); /* The option/argument pair was successfully processed; oarg belongs to the explicit location, and opt should be freed. */ discard_cleanups (oarg_cleanup); do_cleanups (opt_cleanup); } /* One special error check: If a source filename was given without offset, function, or label, issue an error. */ if (EL_EXPLICIT (location)->source_filename != NULL && EL_EXPLICIT (location)->function_name == NULL && EL_EXPLICIT (location)->label_name == NULL && (EL_EXPLICIT (location)->line_offset.sign == LINE_OFFSET_UNKNOWN) && !dont_throw) { error (_("Source filename requires function, label, or " "line offset.")); } discard_cleanups (cleanup); return location; }
static struct block_symbol d_lookup_symbol_imports (const char *scope, const char *name, const struct block *block, const domain_enum domain) { struct using_direct *current; struct block_symbol sym; struct cleanup *searched_cleanup; /* First, try to find the symbol in the given module. */ sym = d_lookup_symbol_in_module (scope, name, block, domain, 1); if (sym.symbol != NULL) return sym; /* Go through the using directives. If any of them add new names to the module we're searching in, see if we can find a match by applying them. */ for (current = block_using (block); current != NULL; current = current->next) { const char **excludep; /* If the import destination is the current scope then search it. */ if (!current->searched && strcmp (scope, current->import_dest) == 0) { /* Mark this import as searched so that the recursive call does not search it again. */ current->searched = 1; searched_cleanup = make_cleanup (reset_directive_searched, current); /* If there is an import of a single declaration, compare the imported declaration (after optional renaming by its alias) with the sought out name. If there is a match pass current->import_src as MODULE to direct the search towards the imported module. */ if (current->declaration && strcmp (name, current->alias ? current->alias : current->declaration) == 0) sym = d_lookup_symbol_in_module (current->import_src, current->declaration, block, domain, 1); /* If a symbol was found or this import statement was an import declaration, the search of this import is complete. */ if (sym.symbol != NULL || current->declaration) { current->searched = 0; discard_cleanups (searched_cleanup); if (sym.symbol != NULL) return sym; continue; } /* Do not follow CURRENT if NAME matches its EXCLUDES. */ for (excludep = current->excludes; *excludep; excludep++) if (strcmp (name, *excludep) == 0) break; if (*excludep) { discard_cleanups (searched_cleanup); continue; } /* If the import statement is creating an alias. */ if (current->alias != NULL) { if (strcmp (name, current->alias) == 0) { /* If the alias matches the sought name. Pass current->import_src as the NAME to direct the search towards the aliased module. */ sym = lookup_module_scope (NULL, current->import_src, block, domain, scope, 0); } else { /* If the alias matches the first component of the sought name, pass current->import_src as MODULE to direct the search, skipping over the aliased component in NAME. */ int name_scope = d_find_first_component (name); if (name[name_scope] != '\0' && strncmp (name, current->alias, name_scope) == 0) { /* Skip the '.' */ name_scope++; sym = d_lookup_symbol_imports (current->import_src, name + name_scope, block, domain); } } } else { /* If this import statement creates no alias, pass current->import_src as MODULE to direct the search towards the imported module. */ sym = d_lookup_symbol_imports (current->import_src, name, block, domain); } current->searched = 0; discard_cleanups (searched_cleanup); if (sym.symbol != NULL) return sym; } } return null_block_symbol; }
struct compile_module * compile_object_load (const char *object_file, const char *source_file) { struct cleanup *cleanups, *cleanups_free_objfile; bfd *abfd; struct setup_sections_data setup_sections_data; CORE_ADDR addr, func_addr, regs_addr; struct bound_minimal_symbol bmsym; long storage_needed; asymbol **symbol_table, **symp; long number_of_symbols, missing_symbols; struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; unsigned dptr_type_len = TYPE_LENGTH (dptr_type); struct compile_module *retval; struct type *regs_type; char *filename, **matching; struct objfile *objfile; filename = tilde_expand (object_file); cleanups = make_cleanup (xfree, filename); abfd = gdb_bfd_open (filename, gnutarget, -1); if (abfd == NULL) error (_("\"%s\": could not open as compiled module: %s"), filename, bfd_errmsg (bfd_get_error ())); make_cleanup_bfd_unref (abfd); if (!bfd_check_format_matches (abfd, bfd_object, &matching)) error (_("\"%s\": not in loadable format: %s"), filename, gdb_bfd_errmsg (bfd_get_error (), matching)); if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0) error (_("\"%s\": not in object format."), filename); setup_sections_data.last_size = 0; setup_sections_data.last_section_first = abfd->sections; setup_sections_data.last_prot = -1; setup_sections_data.last_max_alignment = 1; bfd_map_over_sections (abfd, setup_sections, &setup_sections_data); setup_sections (abfd, NULL, &setup_sections_data); storage_needed = bfd_get_symtab_upper_bound (abfd); if (storage_needed < 0) error (_("Cannot read symbols of compiled module \"%s\": %s"), filename, bfd_errmsg (bfd_get_error ())); /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in "Reading symbols from ..." message for automatically generated file. */ objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL); cleanups_free_objfile = make_cleanup_free_objfile (objfile); bmsym = lookup_minimal_symbol_text (GCC_FE_WRAPPER_FUNCTION, objfile); if (bmsym.minsym == NULL || MSYMBOL_TYPE (bmsym.minsym) == mst_file_text) error (_("Could not find symbol \"%s\" of compiled module \"%s\"."), GCC_FE_WRAPPER_FUNCTION, filename); func_addr = BMSYMBOL_VALUE_ADDRESS (bmsym); /* The memory may be later needed by bfd_generic_get_relocated_section_contents called from default_symfile_relocate. */ symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); if (number_of_symbols < 0) error (_("Cannot parse symbols of compiled module \"%s\": %s"), filename, bfd_errmsg (bfd_get_error ())); missing_symbols = 0; for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++) { asymbol *sym = *symp; if (sym->flags != 0) continue; if (compile_debug) fprintf_unfiltered (gdb_stdout, "lookup undefined ELF symbol \"%s\"\n", sym->name); sym->flags = BSF_GLOBAL; sym->section = bfd_abs_section_ptr; if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0) { sym->value = 0; continue; } bmsym = lookup_minimal_symbol (sym->name, NULL, NULL); switch (bmsym.minsym == NULL ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym)) { case mst_text: sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym); break; default: warning (_("Could not find symbol \"%s\" " "for compiled module \"%s\"."), sym->name, filename); missing_symbols++; } } if (missing_symbols) error (_("%ld symbols were missing, cannot continue."), missing_symbols); bfd_map_over_sections (abfd, copy_sections, symbol_table); regs_type = get_regs_type (objfile); if (regs_type == NULL) regs_addr = 0; else { /* Use read-only non-executable memory protection. */ regs_addr = gdbarch_infcall_mmap (target_gdbarch (), TYPE_LENGTH (regs_type), GDB_MMAP_PROT_READ); gdb_assert (regs_addr != 0); store_regs (regs_type, regs_addr); } discard_cleanups (cleanups_free_objfile); do_cleanups (cleanups); retval = xmalloc (sizeof (*retval)); retval->objfile = objfile; retval->source_file = xstrdup (source_file); retval->func_addr = func_addr; retval->regs_addr = regs_addr; return retval; }
/* General function to handle events in the inferior. So far it just takes care of detecting errors reported by select() or poll(), otherwise it assumes that all is OK, and goes on reading data from the fd. This however may not always be what we want to do. */ void inferior_event_handler (enum inferior_event_type event_type, gdb_client_data client_data) { struct cleanup *cleanup_if_error = make_bpstat_clear_actions_cleanup (); switch (event_type) { case INF_REG_EVENT: /* Use catch errors for now, until the inner layers of fetch_inferior_event (i.e. readchar) can return meaningful error status. If an error occurs while getting an event from the target, just cancel the current command. */ if (!catch_errors (fetch_inferior_event_wrapper, client_data, "", RETURN_MASK_ALL)) { bpstat_clear_actions (); do_all_intermediate_continuations (1); do_all_continuations (1); async_enable_stdin (); display_gdb_prompt (0); } break; case INF_EXEC_COMPLETE: if (!non_stop) { /* Unregister the inferior from the event loop. This is done so that when the inferior is not running we don't get distracted by spurious inferior output. */ if (target_has_execution) target_async (NULL, 0); } /* Do all continuations associated with the whole inferior (not a particular thread). */ if (!ptid_equal (inferior_ptid, null_ptid)) do_all_inferior_continuations (0); /* If we were doing a multi-step (eg: step n, next n), but it got interrupted by a breakpoint, still do the pending continuations. The continuation itself is responsible for distinguishing the cases. The continuations are allowed to touch the inferior memory, e.g. to remove breakpoints, so run them before running breakpoint commands, which may resume the target. */ if (non_stop && target_has_execution && !ptid_equal (inferior_ptid, null_ptid)) do_all_intermediate_continuations_thread (inferior_thread (), 0); else do_all_intermediate_continuations (0); /* Always finish the previous command before running any breakpoint commands. Any stop cancels the previous command. E.g. a "finish" or "step-n" command interrupted by an unrelated breakpoint is canceled. */ if (non_stop && target_has_execution && !ptid_equal (inferior_ptid, null_ptid)) do_all_continuations_thread (inferior_thread (), 0); else do_all_continuations (0); /* When running a command list (from a user command, say), these are only run when the command list is all done. */ if (interpreter_async) { volatile struct gdb_exception e; check_frame_language_change (); /* Don't propagate breakpoint commands errors. Either we're stopping or some command resumes the inferior. The user will be informed. */ TRY_CATCH (e, RETURN_MASK_ALL) { bpstat_do_actions (); } exception_print (gdb_stderr, e); } break; case INF_EXEC_CONTINUE: /* Is there anything left to do for the command issued to complete? */ if (non_stop) do_all_intermediate_continuations_thread (inferior_thread (), 0); else do_all_intermediate_continuations (0); break; case INF_TIMER: default: printf_unfiltered (_("Event type not recognized.\n")); break; } discard_cleanups (cleanup_if_error); }
static void tfile_open (const char *arg, int from_tty) { char *temp; struct cleanup *old_chain; int flags; int scratch_chan; char header[TRACE_HEADER_SIZE]; char linebuf[1000]; /* Should be max remote packet size or so. */ gdb_byte byte; int bytes, i; struct trace_status *ts; struct uploaded_tp *uploaded_tps = NULL; struct uploaded_tsv *uploaded_tsvs = NULL; char *filename; target_preopen (from_tty); if (!arg) error (_("No trace file specified.")); filename = tilde_expand (arg); if (!IS_ABSOLUTE_PATH(filename)) { temp = concat (current_directory, "/", filename, (char *) NULL); xfree (filename); filename = temp; } old_chain = make_cleanup (xfree, filename); flags = O_BINARY | O_LARGEFILE; flags |= O_RDONLY; scratch_chan = gdb_open_cloexec (filename, flags, 0); if (scratch_chan < 0) perror_with_name (filename); /* Looks semi-reasonable. Toss the old trace file and work on the new. */ discard_cleanups (old_chain); /* Don't free filename any more. */ unpush_target (&tfile_ops); trace_filename = xstrdup (filename); trace_fd = scratch_chan; /* Make sure this is clear. */ buffer_free (&trace_tdesc); bytes = 0; /* Read the file header and test for validity. */ tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE); bytes += TRACE_HEADER_SIZE; if (!(header[0] == 0x7f && (startswith (header + 1, "TRACE0\n")))) error (_("File is not a valid trace file.")); push_target (&tfile_ops); trace_regblock_size = 0; ts = current_trace_status (); /* We know we're working with a file. Record its name. */ ts->filename = trace_filename; /* Set defaults in case there is no status line. */ ts->running_known = 0; ts->stop_reason = trace_stop_reason_unknown; ts->traceframe_count = -1; ts->buffer_free = 0; ts->disconnected_tracing = 0; ts->circular_buffer = 0; TRY { /* Read through a section of newline-terminated lines that define things like tracepoints. */ i = 0; while (1) { tfile_read (&byte, 1); ++bytes; if (byte == '\n') { /* Empty line marks end of the definition section. */ if (i == 0) break; linebuf[i] = '\0'; i = 0; tfile_interp_line (linebuf, &uploaded_tps, &uploaded_tsvs); } else linebuf[i++] = byte; if (i >= 1000) error (_("Excessively long lines in trace file")); } /* By now, tdesc lines have been read from tfile - let's parse them. */ target_find_description (); /* Record the starting offset of the binary trace data. */ trace_frames_offset = bytes; /* If we don't have a blocksize, we can't interpret the traceframes. */ if (trace_regblock_size == 0) error (_("No register block size recorded in trace file")); } CATCH (ex, RETURN_MASK_ALL) { /* Remove the partially set up target. */ unpush_target (&tfile_ops); throw_exception (ex); }
struct compile_module * compile_object_load (const char *object_file, const char *source_file, enum compile_i_scope_types scope, void *scope_data) { struct cleanup *cleanups, *cleanups_free_objfile; bfd *abfd; struct setup_sections_data setup_sections_data; CORE_ADDR addr, regs_addr, out_value_addr = 0; struct symbol *func_sym; struct type *func_type; struct bound_minimal_symbol bmsym; long storage_needed; asymbol **symbol_table, **symp; long number_of_symbols, missing_symbols; struct type *dptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; unsigned dptr_type_len = TYPE_LENGTH (dptr_type); struct compile_module *retval; struct type *regs_type, *out_value_type = NULL; char *filename, **matching; struct objfile *objfile; int expect_parameters; struct type *expect_return_type; struct munmap_list *munmap_list_head = NULL; filename = tilde_expand (object_file); cleanups = make_cleanup (xfree, filename); abfd = gdb_bfd_open (filename, gnutarget, -1); if (abfd == NULL) error (_("\"%s\": could not open as compiled module: %s"), filename, bfd_errmsg (bfd_get_error ())); make_cleanup_bfd_unref (abfd); if (!bfd_check_format_matches (abfd, bfd_object, &matching)) error (_("\"%s\": not in loadable format: %s"), filename, gdb_bfd_errmsg (bfd_get_error (), matching)); if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) != 0) error (_("\"%s\": not in object format."), filename); setup_sections_data.last_size = 0; setup_sections_data.last_section_first = abfd->sections; setup_sections_data.last_prot = -1; setup_sections_data.last_max_alignment = 1; setup_sections_data.munmap_list_headp = &munmap_list_head; make_cleanup (munmap_listp_free_cleanup, &munmap_list_head); bfd_map_over_sections (abfd, setup_sections, &setup_sections_data); setup_sections (abfd, NULL, &setup_sections_data); storage_needed = bfd_get_symtab_upper_bound (abfd); if (storage_needed < 0) error (_("Cannot read symbols of compiled module \"%s\": %s"), filename, bfd_errmsg (bfd_get_error ())); /* SYMFILE_VERBOSE is not passed even if FROM_TTY, user is not interested in "Reading symbols from ..." message for automatically generated file. */ objfile = symbol_file_add_from_bfd (abfd, filename, 0, NULL, 0, NULL); cleanups_free_objfile = make_cleanup_free_objfile (objfile); func_sym = lookup_global_symbol_from_objfile (objfile, GCC_FE_WRAPPER_FUNCTION, VAR_DOMAIN).symbol; if (func_sym == NULL) error (_("Cannot find function \"%s\" in compiled module \"%s\"."), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); func_type = SYMBOL_TYPE (func_sym); if (TYPE_CODE (func_type) != TYPE_CODE_FUNC) error (_("Invalid type code %d of function \"%s\" in compiled " "module \"%s\"."), TYPE_CODE (func_type), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); switch (scope) { case COMPILE_I_SIMPLE_SCOPE: expect_parameters = 1; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; case COMPILE_I_RAW_SCOPE: expect_parameters = 0; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; case COMPILE_I_PRINT_ADDRESS_SCOPE: case COMPILE_I_PRINT_VALUE_SCOPE: expect_parameters = 2; expect_return_type = builtin_type (target_gdbarch ())->builtin_void; break; default: internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope); } if (TYPE_NFIELDS (func_type) != expect_parameters) error (_("Invalid %d parameters of function \"%s\" in compiled " "module \"%s\"."), TYPE_NFIELDS (func_type), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); if (!types_deeply_equal (expect_return_type, TYPE_TARGET_TYPE (func_type))) error (_("Invalid return type of function \"%s\" in compiled " "module \"%s\"."), GCC_FE_WRAPPER_FUNCTION, objfile_name (objfile)); /* The memory may be later needed by bfd_generic_get_relocated_section_contents called from default_symfile_relocate. */ symbol_table = obstack_alloc (&objfile->objfile_obstack, storage_needed); number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); if (number_of_symbols < 0) error (_("Cannot parse symbols of compiled module \"%s\": %s"), filename, bfd_errmsg (bfd_get_error ())); missing_symbols = 0; for (symp = symbol_table; symp < symbol_table + number_of_symbols; symp++) { asymbol *sym = *symp; if (sym->flags != 0) continue; sym->flags = BSF_GLOBAL; sym->section = bfd_abs_section_ptr; if (strcmp (sym->name, "_GLOBAL_OFFSET_TABLE_") == 0) { if (compile_debug) fprintf_unfiltered (gdb_stdlog, "ELF symbol \"%s\" relocated to zero\n", sym->name); /* It seems to be a GCC bug, with -mcmodel=large there should be no need for _GLOBAL_OFFSET_TABLE_. Together with -fPIE the data remain PC-relative even with _GLOBAL_OFFSET_TABLE_ as zero. */ sym->value = 0; continue; } bmsym = lookup_minimal_symbol (sym->name, NULL, NULL); switch (bmsym.minsym == NULL ? mst_unknown : MSYMBOL_TYPE (bmsym.minsym)) { case mst_text: sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "ELF mst_text symbol \"%s\" relocated to %s\n", sym->name, paddress (target_gdbarch (), sym->value)); break; case mst_text_gnu_ifunc: sym->value = gnu_ifunc_resolve_addr (target_gdbarch (), BMSYMBOL_VALUE_ADDRESS (bmsym)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "ELF mst_text_gnu_ifunc symbol \"%s\" " "relocated to %s\n", sym->name, paddress (target_gdbarch (), sym->value)); break; default: warning (_("Could not find symbol \"%s\" " "for compiled module \"%s\"."), sym->name, filename); missing_symbols++; } } if (missing_symbols) error (_("%ld symbols were missing, cannot continue."), missing_symbols); bfd_map_over_sections (abfd, copy_sections, symbol_table); regs_type = get_regs_type (func_sym, objfile); if (regs_type == NULL) regs_addr = 0; else { /* Use read-only non-executable memory protection. */ regs_addr = gdbarch_infcall_mmap (target_gdbarch (), TYPE_LENGTH (regs_type), GDB_MMAP_PROT_READ); gdb_assert (regs_addr != 0); munmap_list_add (&munmap_list_head, regs_addr, TYPE_LENGTH (regs_type)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s for registers\n", paddress (target_gdbarch (), TYPE_LENGTH (regs_type)), paddress (target_gdbarch (), regs_addr)); store_regs (regs_type, regs_addr); } if (scope == COMPILE_I_PRINT_ADDRESS_SCOPE || scope == COMPILE_I_PRINT_VALUE_SCOPE) { out_value_type = get_out_value_type (func_sym, objfile, scope); if (out_value_type == NULL) { do_cleanups (cleanups); return NULL; } check_typedef (out_value_type); out_value_addr = gdbarch_infcall_mmap (target_gdbarch (), TYPE_LENGTH (out_value_type), (GDB_MMAP_PROT_READ | GDB_MMAP_PROT_WRITE)); gdb_assert (out_value_addr != 0); munmap_list_add (&munmap_list_head, out_value_addr, TYPE_LENGTH (out_value_type)); if (compile_debug) fprintf_unfiltered (gdb_stdlog, "allocated %s bytes at %s for printed value\n", paddress (target_gdbarch (), TYPE_LENGTH (out_value_type)), paddress (target_gdbarch (), out_value_addr)); } discard_cleanups (cleanups_free_objfile); retval = xmalloc (sizeof (*retval)); retval->objfile = objfile; retval->source_file = xstrdup (source_file); retval->func_sym = func_sym; retval->regs_addr = regs_addr; retval->scope = scope; retval->scope_data = scope_data; retval->out_value_type = out_value_type; retval->out_value_addr = out_value_addr; /* CLEANUPS will free MUNMAP_LIST_HEAD. */ retval->munmap_list_head = munmap_list_head; munmap_list_head = NULL; do_cleanups (cleanups); return retval; }
static void kgdb_trgt_open(char *filename, int from_tty) { struct cleanup *old_chain; struct thread_info *ti; struct kthr *kt; kvm_t *nkvm; char *temp; int ontop; target_preopen (from_tty); if (!filename) error ("No vmcore file specified."); if (!exec_bfd) error ("Can't open a vmcore without a kernel"); filename = tilde_expand (filename); if (filename[0] != '/') { temp = concat (current_directory, "/", filename, NULL); xfree(filename); filename = temp; } old_chain = make_cleanup (xfree, filename); nkvm = kvm_openfiles(bfd_get_filename(exec_bfd), filename, NULL, write_files ? O_RDWR : O_RDONLY, kvm_err); if (nkvm == NULL) error ("Failed to open vmcore: %s", kvm_err); /* Don't free the filename now and close any previous vmcore. */ discard_cleanups(old_chain); unpush_target(&kgdb_trgt_ops); kvm = nkvm; vmcore = filename; old_chain = make_cleanup(kgdb_core_cleanup, NULL); ontop = !push_target (&kgdb_trgt_ops); discard_cleanups (old_chain); kgdb_dmesg(); init_thread_list(); kt = kgdb_thr_init(); while (kt != NULL) { ti = add_thread(pid_to_ptid(kt->tid)); kt = kgdb_thr_next(kt); } if (curkthr != 0) inferior_ptid = pid_to_ptid(curkthr->tid); if (ontop) { /* XXX: fetch registers? */ kld_init(); flush_cached_frames(); select_frame (get_current_frame()); print_stack_frame(get_selected_frame(), frame_relative_level(get_selected_frame()), 1); } else warning( "you won't be able to access this vmcore until you terminate\n\ your %s; do ``info files''", target_longname); }
static struct macro_buffer * gather_arguments (const char *name, struct macro_buffer *src, int nargs, int *argc_p) { struct macro_buffer tok; int args_len, args_size; struct macro_buffer *args = NULL; struct cleanup *back_to = make_cleanup (free_current_contents, &args); /* Does SRC start with an opening paren token? Read from a copy of SRC, so SRC itself is unaffected if we don't find an opening paren. */ { struct macro_buffer temp; init_shared_buffer (&temp, src->text, src->len); if (! get_token (&tok, &temp) || tok.len != 1 || tok.text[0] != '(') { discard_cleanups (back_to); return 0; } } /* Consume SRC's opening paren. */ get_token (&tok, src); args_len = 0; args_size = 6; args = (struct macro_buffer *) xmalloc (sizeof (*args) * args_size); for (;;) { struct macro_buffer *arg; int depth; /* Make sure we have room for the next argument. */ if (args_len >= args_size) { args_size *= 2; args = xrealloc (args, sizeof (*args) * args_size); } /* Initialize the next argument. */ arg = &args[args_len++]; set_token (arg, src->text, src->text); /* Gather the argument's tokens. */ depth = 0; for (;;) { if (! get_token (&tok, src)) error (_("Malformed argument list for macro `%s'."), name); /* Is tok an opening paren? */ if (tok.len == 1 && tok.text[0] == '(') depth++; /* Is tok is a closing paren? */ else if (tok.len == 1 && tok.text[0] == ')') { /* If it's a closing paren at the top level, then that's the end of the argument list. */ if (depth == 0) { /* In the varargs case, the last argument may be missing. Add an empty argument in this case. */ if (nargs != -1 && args_len == nargs - 1) { /* Make sure we have room for the argument. */ if (args_len >= args_size) { args_size++; args = xrealloc (args, sizeof (*args) * args_size); } arg = &args[args_len++]; set_token (arg, src->text, src->text); } discard_cleanups (back_to); *argc_p = args_len; return args; } depth--; } /* If tok is a comma at top level, then that's the end of the current argument. However, if we are handling a variadic macro and we are computing the last argument, we want to include the comma and remaining tokens. */ else if (tok.len == 1 && tok.text[0] == ',' && depth == 0 && (nargs == -1 || args_len < nargs)) break; /* Extend the current argument to enclose this token. If this is the current argument's first token, leave out any leading whitespace, just for aesthetics. */ if (arg->len == 0) { arg->text = tok.text; arg->len = tok.len; arg->last_token = 0; } else { arg->len = (tok.text + tok.len) - arg->text; arg->last_token = tok.text - arg->text; } } } }
static void core_open (char *filename, int from_tty) { const char *p; int siggy; struct cleanup *old_chain; char *temp; bfd *temp_bfd; int scratch_chan; int flags; volatile struct gdb_exception except; target_preopen (from_tty); if (!filename) { if (core_bfd) error (_("No core file specified. (Use `detach' " "to stop debugging a core file.)")); else error (_("No core file specified.")); } filename = tilde_expand (filename); if (!IS_ABSOLUTE_PATH (filename)) { temp = concat (current_directory, "/", filename, (char *) NULL); xfree (filename); filename = temp; } old_chain = make_cleanup (xfree, filename); flags = O_BINARY | O_LARGEFILE; if (write_files) flags |= O_RDWR; else flags |= O_RDONLY; scratch_chan = open (filename, flags, 0); if (scratch_chan < 0) perror_with_name (filename); temp_bfd = bfd_fopen (filename, gnutarget, write_files ? FOPEN_RUB : FOPEN_RB, scratch_chan); if (temp_bfd == NULL) perror_with_name (filename); if (!bfd_check_format (temp_bfd, bfd_core) && !gdb_check_format (temp_bfd)) { /* Do it after the err msg */ /* FIXME: should be checking for errors from bfd_close (for one thing, on error it does not free all the storage associated with the bfd). */ make_cleanup_bfd_close (temp_bfd); error (_("\"%s\" is not a core dump: %s"), filename, bfd_errmsg (bfd_get_error ())); } /* Looks semi-reasonable. Toss the old core file and work on the new. */ discard_cleanups (old_chain); /* Don't free filename any more */ unpush_target (&core_ops); core_bfd = temp_bfd; old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/); /* FIXME: kettenis/20031023: This is very dangerous. The CORE_GDBARCH that results from this call may very well be different from CURRENT_GDBARCH. However, its methods may only work if it is selected as the current architecture, because they rely on swapped data (see gdbarch.c). We should get rid of that swapped data. */ core_gdbarch = gdbarch_from_bfd (core_bfd); /* Find a suitable core file handler to munch on core_bfd */ core_vec = sniff_core_bfd (core_bfd); validate_files (); core_data = XZALLOC (struct target_section_table); /* Find the data section */ if (build_section_table (core_bfd, &core_data->sections, &core_data->sections_end)) error (_("\"%s\": Can't find sections: %s"), bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); /* If we have no exec file, try to set the architecture from the core file. We don't do this unconditionally since an exec file typically contains more information that helps us determine the architecture than a core file. */ if (!exec_bfd) set_gdbarch_from_file (core_bfd); push_target (&core_ops); discard_cleanups (old_chain); /* Do this before acknowledging the inferior, so if post_create_inferior throws (can happen easilly if you're loading a core file with the wrong exec), we aren't left with threads from the previous inferior. */ init_thread_list (); inferior_ptid = null_ptid; /* Need to flush the register cache (and the frame cache) from a previous debug session. If inferior_ptid ends up the same as the last debug session --- e.g., b foo; run; gcore core1; step; gcore core2; core core1; core core2 --- then there's potential for get_current_regcache to return the cached regcache of the previous session, and the frame cache being stale. */ registers_changed (); /* Build up thread list from BFD sections, and possibly set the current thread to the .reg/NN section matching the .reg section. */ bfd_map_over_sections (core_bfd, add_to_thread_list, bfd_get_section_by_name (core_bfd, ".reg")); if (ptid_equal (inferior_ptid, null_ptid)) { /* Either we found no .reg/NN section, and hence we have a non-threaded core (single-threaded, from gdb's perspective), or for some reason add_to_thread_list couldn't determine which was the "main" thread. The latter case shouldn't usually happen, but we're dealing with input here, which can always be broken in different ways. */ struct thread_info *thread = first_thread_of_process (-1); if (thread == NULL) { inferior_appeared (current_inferior (), CORELOW_PID); inferior_ptid = pid_to_ptid (CORELOW_PID); add_thread_silent (inferior_ptid); } else switch_to_thread (thread->ptid); } post_create_inferior (&core_ops, from_tty); /* Now go through the target stack looking for threads since there may be a thread_stratum target loaded on top of target core by now. The layer above should claim threads found in the BFD sections. */ TRY_CATCH (except, RETURN_MASK_ERROR) { target_find_new_threads (); } if (except.reason < 0) exception_print (gdb_stderr, except); p = bfd_core_file_failing_command (core_bfd); if (p) printf_filtered (_("Core was generated by `%s'.\n"), p); siggy = bfd_core_file_failing_signal (core_bfd); if (siggy > 0) { /* If we don't have a CORE_GDBARCH to work with, assume a native core (map gdb_signal from host signals). If we do have CORE_GDBARCH to work with, but no gdb_signal_from_target implementation for that gdbarch, as a fallback measure, assume the host signal mapping. It'll be correct for native cores, but most likely incorrect for cross-cores. */ enum gdb_signal sig = (core_gdbarch != NULL && gdbarch_gdb_signal_from_target_p (core_gdbarch) ? gdbarch_gdb_signal_from_target (core_gdbarch, siggy) : gdb_signal_from_host (siggy)); printf_filtered (_("Program terminated with signal %d, %s.\n"), siggy, gdb_signal_to_string (sig)); } /* Fetch all registers from core file. */ target_fetch_registers (get_current_regcache (), -1); /* Now, set up the frame cache, and print the top of stack. */ reinit_frame_cache (); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); }
static void kgdb_trgt_open(char *filename, int from_tty) { struct cleanup *old_chain; struct kthr *kt; struct inferior *inf8; struct program_space *pspace; kvm_t *nkvm; char *temp; int first_inferior = 1; target_preopen (from_tty); if (!filename) error ("No vmcore file specified."); if (!exec_bfd) error ("Can't open a vmcore without a kernel"); filename = tilde_expand (filename); if (filename[0] != '/') { temp = concat (current_directory, "/", filename, NULL); xfree(filename); filename = temp; } old_chain = make_cleanup (xfree, filename); nkvm = kvm_openfiles(bfd_get_filename(exec_bfd), filename, NULL, write_files ? O_RDWR : O_RDONLY, kvm_err); if (nkvm == NULL) error ("Failed to open vmcore: %s", kvm_err); /* Don't free the filename now and close any previous vmcore. */ discard_cleanups(old_chain); unpush_target(&kgdb_trgt_ops); kvm = nkvm; vmcore = filename; old_chain = make_cleanup(kgdb_core_cleanup, NULL); push_target (&kgdb_trgt_ops); discard_cleanups (old_chain); kgdb_dmesg(); init_thread_list(); kt = kgdb_thr_init(); while (kt != NULL) { if (!in_inferior_list(kt->pid)) { if (first_inferior) { first_inferior = 0; inf8 = current_inferior(); inf8->pid = kt->pid; inferior_appeared (inf8, kt->pid); pspace = current_program_space; pspace->ebfd = 0; pspace->ebfd_mtime = 0; } else { inf8 = add_inferior(kt->pid); pspace = add_program_space(new_address_space()); pspace->symfile_object_file = symfile_objfile; pspace->objfiles = object_files; } inf8->pspace = pspace; inf8->aspace = pspace->aspace; } add_thread(ptid_build(kt->pid, 0, kt->tid)); kt = kgdb_thr_next(kt); } if (curkthr != 0) inferior_ptid = ptid_build(curkthr->pid, 0, curkthr->tid); frame_unwind_prepend_unwinder(get_frame_arch(get_current_frame()), &kgdb_trgt_trapframe_unwind); /* XXX: fetch registers? */ kld_init(); reinit_frame_cache(); select_frame (get_current_frame()); print_stack_frame(get_selected_frame(NULL), frame_relative_level(get_selected_frame(NULL)), 1); }