From patchwork Fri Jul 18 19:27:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 2116 Received: (qmail 540 invoked by alias); 18 Jul 2014 19:45:15 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 507 invoked by uid 89); 18 Jul 2014 19:45:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 18 Jul 2014 19:45:12 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s6IJRKbo020418 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 18 Jul 2014 15:27:20 -0400 Received: from barimba.redhat.com (ovpn-113-27.phx2.redhat.com [10.3.113.27]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s6IJRHfw019114; Fri, 18 Jul 2014 15:27:20 -0400 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 4/4] convert corelow to to_xclose Date: Fri, 18 Jul 2014 13:27:15 -0600 Message-Id: <1405711635-1102-5-git-send-email-tromey@redhat.com> In-Reply-To: <1405711635-1102-1-git-send-email-tromey@redhat.com> References: <1405711635-1102-1-git-send-email-tromey@redhat.com> 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-18 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/ChangeLog | 19 +++++++ gdb/corelow.c | 175 +++++++++++++++++++++++++++++++++++----------------------- gdb/target.c | 20 +++++++ gdb/target.h | 15 +++++ 4 files changed, 160 insertions(+), 69 deletions(-) diff --git a/gdb/corelow.c b/gdb/corelow.c index 1775a66..212665d 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -60,34 +60,39 @@ 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. */ + + struct gdbarch *core_gdbarch; + + /* 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 struct core_fns *sniff_core_bfd (bfd *); +static void core_files_info (struct target_ops *); static int gdb_check_format (bfd *); static void core_open (char *, int); -static void core_close (struct target_ops *self); - static void core_close_cleanup (void *ignore); static void add_to_thread_list (bfd *, asection *, void *); @@ -131,7 +136,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; @@ -189,12 +194,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); @@ -207,24 +235,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 @@ -285,6 +307,7 @@ core_open (char *filename, int from_tty) int scratch_chan; int flags; volatile struct gdb_exception except; + struct core_target_ops_with_data *cops; target_preopen (from_tty); if (!filename) @@ -340,21 +363,21 @@ core_open (char *filename, 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 ())); @@ -365,7 +388,7 @@ core_open (char *filename, 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 @@ -410,7 +433,7 @@ core_open (char *filename, 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 @@ -440,11 +463,11 @@ core_open (char *filename, 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)); @@ -502,6 +525,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); @@ -530,11 +554,12 @@ get_core_register_section (struct regcache *regcache, return; } - if (core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch)) + if (cops->core_gdbarch + && gdbarch_regset_from_core_section_p (cops->core_gdbarch)) { const struct regset *regset; - regset = gdbarch_regset_from_core_section (core_gdbarch, + regset = gdbarch_regset_from_core_section (cops->core_gdbarch, name, size); if (regset == NULL) { @@ -548,10 +573,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))); } @@ -568,9 +593,12 @@ get_core_registers (struct target_ops *ops, { struct core_regset_section *sect_list; int i; + struct core_target_ops_with_data *cops = get_core_target_ops (); - if (!(core_gdbarch && gdbarch_regset_from_core_section_p (core_gdbarch)) - && (core_vec == NULL || core_vec->core_read_registers == NULL)) + if (!(cops->core_gdbarch + && gdbarch_regset_from_core_section_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"); @@ -611,7 +639,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 @@ -679,13 +709,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: @@ -759,16 +791,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; @@ -779,15 +812,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); @@ -913,11 +946,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; @@ -932,12 +968,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. */ @@ -1000,7 +1037,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 6a10c04..6f5396f 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -586,6 +586,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 58c7b30..60dc287 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -2091,6 +2091,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);