From f218947cb8901642879d499fc63dd2bd32b5cb03 Mon Sep 17 00:00:00 2001 From: Paul Koning Date: Thu, 15 Oct 2015 16:25:49 -0400 Subject: convert corelow to to_xclose This converts corelow to be a to_xclose target. It moves all the corelow-related globals into a new subclass of target_ops and arranges for core_open to push an instance of this. This is preparatory work for multi-target. After this patch, corelow doesn't rely on global state and multiple instances can readily be instantiated. 2014-07-29 Tom Tromey * corelow.c (struct core_target_ops_with_data): New struct. (core_vec, core_gdbarch, core_data): Remove. Now fields of core_target_ops_with_data. (sniff_core_bfd): Add core_gdbarch parameter. (get_core_target_ops): New function. (core_xclose): Rename from core_close. Update for core_target_ops_with_data. Free the target. (core_close_cleanup): Rename parameter. Update. (core_open): Use TARGET_NEW. Update. (get_core_register_section, get_core_registers, core_files_info) (core_xfer_partial, core_read_description, core_pid_to_str): Use get_core_target_ops. Update. (init_core_ops): Set to_xclose, not to_close. * target.c (allocate_target): New function. * target.h (allocate_target): Declare. (TARGET_NEW): New macro. --- gdb/corelow.c | 184 +++++++++++++++++++++++++++++++++++----------------------- gdb/target.c | 20 +++++++ gdb/target.h | 15 +++++ 3 files changed, 146 insertions(+), 73 deletions(-) diff --git a/gdb/corelow.c b/gdb/corelow.c index f7a8bb3..c0b636f 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -56,31 +56,36 @@ static struct core_fns *core_file_fns = NULL; -/* The core_fns for a core file handler that is prepared to read the - core file currently open on core_bfd. */ +/* A subclass of target_ops that also holds data for a core + target. */ -static struct core_fns *core_vec = NULL; +struct core_target_ops_with_data +{ + /* The base class. */ -/* FIXME: kettenis/20031023: Eventually this variable should - disappear. */ + struct target_ops base; -static struct gdbarch *core_gdbarch = NULL; + /* The core_fns for a core file handler that is prepared to read the + core file currently open on core_bfd. */ -/* Per-core data. Currently, only the section table. Note that these - target sections are *not* mapped in the current address spaces' set - of target sections --- those should come only from pure executable - or shared library bfds. The core bfd sections are an - implementation detail of the core target, just like ptrace is for - unix child targets. */ -static struct target_section_table *core_data; + struct core_fns *core_vec; -static void core_files_info (struct target_ops *); + /* FIXME: kettenis/20031023: Eventually this variable should + disappear. */ -static struct core_fns *sniff_core_bfd (bfd *); + struct gdbarch *core_gdbarch; -static int gdb_check_format (bfd *); + /* The section table. Note that these target sections are *not* + mapped in the current address spaces' set of target sections --- + those should come only from pure executable or shared library + bfds. The core bfd sections are an implementation detail of the + core target, just like ptrace is for unix child targets. */ + struct target_section_table core_data; +}; -static void core_close (struct target_ops *self); +static void core_files_info (struct target_ops *); + +static int gdb_check_format (bfd *); static void core_close_cleanup (void *ignore); @@ -125,7 +130,7 @@ default_core_sniffer (struct core_fns *our_fns, bfd *abfd) selected. */ static struct core_fns * -sniff_core_bfd (bfd *abfd) +sniff_core_bfd (bfd *abfd, struct gdbarch *core_gdbarch) { struct core_fns *cf; struct core_fns *yummy = NULL; @@ -183,12 +188,35 @@ gdb_check_format (bfd *abfd) return (0); } + + +/* Return the core_target_ops_with_data for the current target stack, + if any. */ + +static struct core_target_ops_with_data * +get_core_target_ops (void) +{ + struct target_ops *targ = find_target_at (process_stratum); + + if (targ == NULL || targ->to_identity != &core_ops) + return NULL; + + /* Downcast. */ + return (struct core_target_ops_with_data *) targ; +} + /* Discard all vestiges of any previous core file and mark data and stack spaces as empty. */ static void -core_close (struct target_ops *self) +core_xclose (struct target_ops *self) { + /* Downcast. */ + struct core_target_ops_with_data *cops + = (struct core_target_ops_with_data *) self; + + gdb_assert (self->to_identity == &core_ops); + if (core_bfd) { int pid = ptid_get_pid (inferior_ptid); @@ -201,24 +229,18 @@ core_close (struct target_ops *self) comments in clear_solib in solib.c. */ clear_solib (); - if (core_data) - { - xfree (core_data->sections); - xfree (core_data); - core_data = NULL; - } - gdb_bfd_unref (core_bfd); core_bfd = NULL; } - core_vec = NULL; - core_gdbarch = NULL; + + xfree (cops->core_data.sections); + xfree (cops); } static void -core_close_cleanup (void *ignore) +core_close_cleanup (void *arg) { - core_close (NULL); + core_xclose (arg); } /* Look for sections whose names start with `.reg/' so that we can @@ -278,7 +300,9 @@ core_open (const char *arg, int from_tty) bfd *temp_bfd; int scratch_chan; int flags; + volatile struct gdb_exception except; char *filename; + struct core_target_ops_with_data *cops; target_preopen (from_tty); if (!arg) @@ -334,21 +358,21 @@ core_open (const char *arg, int from_tty) do_cleanups (old_chain); unpush_target (&core_ops); core_bfd = temp_bfd; - old_chain = make_cleanup (core_close_cleanup, 0 /*ignore*/); - core_gdbarch = gdbarch_from_bfd (core_bfd); + cops = TARGET_NEW (struct core_target_ops_with_data, &core_ops); + old_chain = make_cleanup (core_close_cleanup, cops); + + cops->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); + cops->core_vec = sniff_core_bfd (core_bfd, cops->core_gdbarch); 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)) + &cops->core_data.sections, + &cops->core_data.sections_end)) error (_("\"%s\": Can't find sections: %s"), bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ())); @@ -359,7 +383,7 @@ core_open (const char *arg, int from_tty) if (!exec_bfd) set_gdbarch_from_file (core_bfd); - push_target (&core_ops); + push_target (&cops->base); discard_cleanups (old_chain); /* Do this before acknowledging the inferior, so if @@ -404,7 +428,7 @@ core_open (const char *arg, int from_tty) switch_to_thread (thread->ptid); } - post_create_inferior (&core_ops, from_tty); + post_create_inferior (&cops->base, 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 @@ -437,11 +461,11 @@ core_open (const char *arg, int from_tty) 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)); + enum gdb_signal sig + = (cops->core_gdbarch != NULL + && gdbarch_gdb_signal_from_target_p (cops->core_gdbarch) + ? gdbarch_gdb_signal_from_target (cops->core_gdbarch, siggy) + : gdb_signal_from_host (siggy)); printf_filtered (_("Program terminated with signal %s, %s.\n"), gdb_signal_to_name (sig), gdb_signal_to_string (sig)); @@ -517,6 +541,7 @@ get_core_register_section (struct regcache *regcache, struct bfd_section *section; bfd_size_type size; char *contents; + struct core_target_ops_with_data *cops = get_core_target_ops (); xfree (section_name); @@ -544,10 +569,12 @@ get_core_register_section (struct regcache *regcache, if (size != min_size && !(regset->flags & REGSET_VARIABLE_SIZE)) { warning (_("Unexpected size of section `%s' in core file."), - section_name); + section_name); } contents = (char *) alloca (size); + + contents = alloca (size); if (! bfd_get_section_contents (core_bfd, section, contents, (file_ptr) 0, size)) { @@ -562,10 +589,10 @@ get_core_register_section (struct regcache *regcache, return; } - gdb_assert (core_vec); - core_vec->core_read_registers (regcache, contents, size, which, - ((CORE_ADDR) - bfd_section_vma (core_bfd, section))); + gdb_assert (cops->core_vec); + cops->core_vec->core_read_registers (regcache, contents, size, which, + ((CORE_ADDR) + bfd_section_vma (core_bfd, section))); } /* Callback for get_core_registers that handles a single core file @@ -608,20 +635,22 @@ static void get_core_registers (struct target_ops *ops, struct regcache *regcache, int regno) { + struct core_regset_section *sect_list; int i; - struct gdbarch *gdbarch; + struct core_target_ops_with_data *cops = get_core_target_ops (); - if (!(core_gdbarch && gdbarch_iterate_over_regset_sections_p (core_gdbarch)) - && (core_vec == NULL || core_vec->core_read_registers == NULL)) + if (!(cops->core_gdbarch + && gdbarch_iterate_over_regset_sections_p (cops->core_gdbarch)) + && (cops->core_vec == NULL + || cops->core_vec->core_read_registers == NULL)) { fprintf_filtered (gdb_stderr, "Can't fetch registers from this type of core file\n"); return; } - gdbarch = get_regcache_arch (regcache); - if (gdbarch_iterate_over_regset_sections_p (gdbarch)) - gdbarch_iterate_over_regset_sections (gdbarch, + if (gdbarch_iterate_over_regset_sections_p (cops->core_gdbarch)) + gdbarch_iterate_over_regset_sections (cops->core_gdbarch, get_core_registers_cb, (void *) regcache, NULL); else @@ -641,7 +670,9 @@ get_core_registers (struct target_ops *ops, static void core_files_info (struct target_ops *t) { - print_section_info (core_data, core_bfd); + struct core_target_ops_with_data *cops = get_core_target_ops (); + + print_section_info (&cops->core_data, core_bfd); } struct spuid_list @@ -709,13 +740,15 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { + struct core_target_ops_with_data *cops = get_core_target_ops (); + switch (object) { case TARGET_OBJECT_MEMORY: return section_table_xfer_memory_partial (readbuf, writebuf, offset, len, xfered_len, - core_data->sections, - core_data->sections_end, + cops->core_data.sections, + cops->core_data.sections_end, NULL); case TARGET_OBJECT_AUXV: @@ -789,16 +822,17 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, return TARGET_XFER_E_IO; case TARGET_OBJECT_LIBRARIES: - if (core_gdbarch - && gdbarch_core_xfer_shared_libraries_p (core_gdbarch)) + if (cops->core_gdbarch + && gdbarch_core_xfer_shared_libraries_p (cops->core_gdbarch)) { if (writebuf) return TARGET_XFER_E_IO; else { - *xfered_len = gdbarch_core_xfer_shared_libraries (core_gdbarch, - readbuf, - offset, len); + *xfered_len + = gdbarch_core_xfer_shared_libraries (cops->core_gdbarch, + readbuf, + offset, len); if (*xfered_len == 0) return TARGET_XFER_EOF; @@ -809,15 +843,15 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, /* FALL THROUGH */ case TARGET_OBJECT_LIBRARIES_AIX: - if (core_gdbarch - && gdbarch_core_xfer_shared_libraries_aix_p (core_gdbarch)) + if (cops->core_gdbarch + && gdbarch_core_xfer_shared_libraries_aix_p (cops->core_gdbarch)) { if (writebuf) return TARGET_XFER_E_IO; else { *xfered_len - = gdbarch_core_xfer_shared_libraries_aix (core_gdbarch, + = gdbarch_core_xfer_shared_libraries_aix (cops->core_gdbarch, readbuf, offset, len); @@ -941,11 +975,14 @@ core_thread_alive (struct target_ops *ops, ptid_t ptid) static const struct target_desc * core_read_description (struct target_ops *target) { - if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch)) + struct core_target_ops_with_data *cops = get_core_target_ops (); + + if (cops->core_gdbarch + && gdbarch_core_read_description_p (cops->core_gdbarch)) { const struct target_desc *result; - result = gdbarch_core_read_description (core_gdbarch, + result = gdbarch_core_read_description (cops->core_gdbarch, target, core_bfd); if (result != NULL) return result; @@ -960,12 +997,13 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid) static char buf[64]; struct inferior *inf; int pid; + struct core_target_ops_with_data *cops = get_core_target_ops (); /* The preferred way is to have a gdbarch/OS specific implementation. */ - if (core_gdbarch - && gdbarch_core_pid_to_str_p (core_gdbarch)) - return gdbarch_core_pid_to_str (core_gdbarch, ptid); + if (cops->core_gdbarch + && gdbarch_core_pid_to_str_p (cops->core_gdbarch)) + return gdbarch_core_pid_to_str (cops->core_gdbarch, ptid); /* Otherwise, if we don't have one, we'll just fallback to "process", with normal_pid_to_str. */ @@ -977,7 +1015,7 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid) /* Otherwise, this isn't a "threaded" core -- use the PID field, but only if it isn't a fake PID. */ - inf = find_inferior_ptid (ptid); + inf = find_inferior_pid (ptid_get_pid (ptid)); if (inf != NULL && !inf->fake_pid_p) return normal_pid_to_str (ptid); @@ -1028,7 +1066,7 @@ init_core_ops (void) core_ops.to_doc = "Use a core file as a target. Specify the filename of the core file."; core_ops.to_open = core_open; - core_ops.to_close = core_close; + core_ops.to_xclose = core_xclose; core_ops.to_detach = core_detach; core_ops.to_fetch_registers = get_core_registers; core_ops.to_xfer_partial = core_xfer_partial; diff --git a/gdb/target.c b/gdb/target.c index 1a3d417..c791aa5 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -706,6 +706,26 @@ push_target (struct target_ops *t) update_current_target (); } +/* See target.h. */ + +struct target_ops * +allocate_target (struct target_ops *ops, size_t alloc) +{ + char *mem; + + gdb_assert (ops->to_identity != NULL); + gdb_assert (ops->to_xclose != NULL); + gdb_assert (alloc >= sizeof (struct target_ops)); + + mem = xmalloc (alloc); + memcpy (mem, ops, sizeof (struct target_ops)); + if (alloc > sizeof (struct target_ops)) + memset (&mem[sizeof (struct target_ops)], 0, + alloc - sizeof (struct target_ops)); + + return (struct target_ops *) mem; +} + /* Remove a target_ops vector from the stack, wherever it may be. Return how many times it was removed (0 or 1). */ diff --git a/gdb/target.h b/gdb/target.h index 804b579..fce4046 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -2289,6 +2289,21 @@ extern void push_target (struct target_ops *); extern int unpush_target (struct target_ops *); +/* Allocate a new target object. OPS is the "prototype" + implementation of the new target; it is copied into the new object. + ALLOC is the number of bytes to allocate. It may be larger than + sizeof (struct target_ops) if the target subclasses target_ops to + store extra data. Returns the new target object. Extra space + beyond the initial OPS component of the result is zeroed. */ + +extern struct target_ops *allocate_target (struct target_ops *ops, + size_t alloc); + +/* A typed convenience wrapper for allocate_target. T is the type of + the subclass of target_ops to allocate. */ + +#define TARGET_NEW(T, OPS) ((T *) (allocate_target ((OPS), sizeof (T)))) + extern void target_pre_inferior (int); extern void target_preopen (int); -- cgit v1.1