From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3759 invoked by alias); 13 Dec 2013 22:07:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 3663 invoked by uid 89); 13 Dec 2013 22:07:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.0 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 ESMTP; Fri, 13 Dec 2013 22:07:11 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rBDM7AE2012371 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 13 Dec 2013 17:07:10 -0500 Received: from barimba (ovpn-113-93.phx2.redhat.com [10.3.113.93]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id rBDM716v001675 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Fri, 13 Dec 2013 17:07:02 -0500 From: Tom Tromey To: Pedro Alves Cc: gdb-patches@sourceware.org Subject: Re: [PATCH v4 3/9] add target method delegation References: <1382464769-2465-1-git-send-email-tromey@redhat.com> <1382464769-2465-4-git-send-email-tromey@redhat.com> <526E8B54.8040104@redhat.com> <87eh75cmig.fsf@fleche.redhat.com> <87a9htcme3.fsf@fleche.redhat.com> <87habz7q6g.fsf@fleche.redhat.com> <527D1A84.9040106@redhat.com> <87lhzr11wz.fsf@fleche.redhat.com> <87a9g623cw.fsf@fleche.redhat.com> Date: Fri, 13 Dec 2013 22:07:00 -0000 In-Reply-To: <87a9g623cw.fsf@fleche.redhat.com> (Tom Tromey's message of "Wed, 11 Dec 2013 19:46:23 -0700") Message-ID: <871u1gz9q2.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-SW-Source: 2013-12/txt/msg00549.txt.bz2 --=-=-= Content-Type: text/plain Content-length: 2611 >>>>> "Tom" == Tom Tromey writes: Tom> Since this is very repetitive I would consider doing it via a ".defs" Tom> file and then some macrology to reduce the amount of boilerplate. I tried this a bit and the result was pretty ugly. Instead I wrote a little script that can parse just enough of "struct target_ops" to auto-generate delegation methods when appropriate. See patch #1 attached below. This patch just converts the methods used by the record targets -- that is, it's just a replacement for patch #3 in this series. Note that the patch isn't ready as-is. The log entry is wrong and it does the wrong thing for a couple of the target methods. I'm curious to know what you think about the overall shape of it. As an example of the benefit of this approach, patch #2 converts to_detach to the new style. When examining this patch recall that target-delegates.c is auto-generated. You can see from this that the result is less code to maintain. I then went a little further. It seems to me that we also need a lot of boilerplate (not to mention the questionable casts there right now) to handle the dummy target methods. Patch #3 makes these into simple annotations in the target.h file, getting rid of the list of handled methods from make-target-delegates as well. Before reaching judgment on patch #3, see patch #4, which converts to_attach. I've written a few more like it. The long-term vision for this approach is to regularize all target methods according to these rules: 1. Each method will take a "struct target_ops *" as its first argument. 2. Nearly every method will be defaulted to the appropriate delegate_ method. There may be exceptions, coded into complete_target_initialization. 3. de_fault will be completely eliminated. INHERIT will be limited to the smallest possible list of fields, like to_shortname. Nearly every current_target method will simply delegate. 4. Target API users will call top-level target_* functions that will in most cases just call into current_target. 5. Any given to_* method implementation will be guaranteed to be called with the target_ops with which it was registered. (This rule is handy on multi-target, where I split out the target_ops vtable from the object itself.) Since I'm on a cleanup kick at the moment, and since a good amount of this is relevant to the multi-target work, I think it would be good to start the conversion shortly after 7.7 is branched. This is a bit difficult since I don't have access to many targets. I'm not sure what to do about this aspect. Tom --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0005-add-target-method-delegation.patch Content-Description: patch #1 Content-length: 41184 >From eb626875b5fce4e5d297da897379a0f0427fab1d Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 12 Jul 2013 13:00:34 -0600 Subject: [PATCH 05/11] add target method delegation MUST UPDATE This patch replaces some code in the record targets with target method delegation. record-full.c stores pointers to many target methods when the record target is pushed. Then it later delegates some calls via these. This is wrong because it violates the target stack contract. In particular it is ok to unpush a target at any stratum, but record-full does not keep track of this, so it could potentially call into an unpushed target. To fix the problem, this patch introduces a handful of target_delegate_* functions, which forward calls further down the target stack. 2013-10-30 Tom Tromey * record-full.c (record_full_beneath_to_resume_ops) (record_full_beneath_to_resume, record_full_beneath_to_wait_ops) (record_full_beneath_to_wait) (record_full_beneath_to_store_registers_ops) (record_full_beneath_to_store_registers) (record_full_beneath_to_xfer_partial_ops) (record_full_beneath_to_xfer_partial) (record_full_beneath_to_insert_breakpoint) (record_full_beneath_to_remove_breakpoint) (record_full_beneath_to_stopped_by_watchpoint) (record_full_beneath_to_stopped_data_address) (record_full_beneath_to_async, tmp_to_resume_ops, tmp_to_resume) (tmp_to_wait_ops, tmp_to_wait, tmp_to_store_registers_ops) (tmp_to_store_registers, tmp_to_xfer_partial_ops) (tmp_to_xfer_partial, tmp_to_insert_breakpoint) (tmp_to_remove_breakpoint, tmp_to_stopped_by_watchpoint) (tmp_to_stopped_data_address, tmp_to_async): Remove. (record_full_open_1, record_full_open): Update. Use RECORD_IS_USED. (record_full_resume, record_full_wait_1) (record_full_stopped_by_watchpoint, record_full_stopped_data_address) (record_full_store_registers, record_full_xfer_partial) (record_full_insert_breakpoint, record_full_remove_breakpoint) (record_full_async, record_full_can_async_p, record_full_is_async_p) (record_full_core_xfer_partial): Use target delegation. * target.c (update_current_target): Use target_delegate_xfer_partial. (target_delegate_xfer_partial): Now public. Renamed from... (current_xfer_partial): ...this. Remove. (target_delegate_async, target_delegate_is_async_p) (target_delegate_can_async_p, target_delegate_insert_breakpoint) (target_delegate_remove_breakpoint, target_delegate_wait) (target_delegate_resume, target_delegate_store_registers) (target_delegate_stopped_by_watchpoint) (target_delegate_stopped_data_address) (assert_delegation_failed): New functions. * target.h (target_delegate_async, target_delegate_is_async_p) (target_delegate_can_async_p, target_delegate_insert_breakpoint) (target_delegate_remove_breakpoint, target_delegate_wait) (target_delegate_resume, target_delegate_store_registers) (target_delegate_stopped_by_watchpoint) (target_delegate_stopped_data_address) (target_delegate_xfer_partial): Declare. --- gdb/ChangeLog | 44 +++++++++ gdb/make-target-delegates | 174 +++++++++++++++++++++++++++++++++ gdb/record-full.c | 239 ++++------------------------------------------ gdb/target-delegates.c | 108 +++++++++++++++++++++ gdb/target.c | 196 ++++++++++++++++++------------------- gdb/target.h | 5 +- 6 files changed, 444 insertions(+), 322 deletions(-) create mode 100755 gdb/make-target-delegates create mode 100644 gdb/target-delegates.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 001cce3..f87d015 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,49 @@ 2013-10-30 Tom Tromey + * record-full.c (record_full_beneath_to_resume_ops) + (record_full_beneath_to_resume, record_full_beneath_to_wait_ops) + (record_full_beneath_to_wait) + (record_full_beneath_to_store_registers_ops) + (record_full_beneath_to_store_registers) + (record_full_beneath_to_xfer_partial_ops) + (record_full_beneath_to_xfer_partial) + (record_full_beneath_to_insert_breakpoint) + (record_full_beneath_to_remove_breakpoint) + (record_full_beneath_to_stopped_by_watchpoint) + (record_full_beneath_to_stopped_data_address) + (record_full_beneath_to_async, tmp_to_resume_ops, tmp_to_resume) + (tmp_to_wait_ops, tmp_to_wait, tmp_to_store_registers_ops) + (tmp_to_store_registers, tmp_to_xfer_partial_ops) + (tmp_to_xfer_partial, tmp_to_insert_breakpoint) + (tmp_to_remove_breakpoint, tmp_to_stopped_by_watchpoint) + (tmp_to_stopped_data_address, tmp_to_async): Remove. + (record_full_open_1, record_full_open): Update. Use RECORD_IS_USED. + (record_full_resume, record_full_wait_1) + (record_full_stopped_by_watchpoint, record_full_stopped_data_address) + (record_full_store_registers, record_full_xfer_partial) + (record_full_insert_breakpoint, record_full_remove_breakpoint) + (record_full_async, record_full_can_async_p, record_full_is_async_p) + (record_full_core_xfer_partial): Use target delegation. + * target.c (update_current_target): Use target_delegate_xfer_partial. + (target_delegate_xfer_partial): Now public. Renamed from... + (current_xfer_partial): ...this. Remove. + (target_delegate_async, target_delegate_is_async_p) + (target_delegate_can_async_p, target_delegate_insert_breakpoint) + (target_delegate_remove_breakpoint, target_delegate_wait) + (target_delegate_resume, target_delegate_store_registers) + (target_delegate_stopped_by_watchpoint) + (target_delegate_stopped_data_address) + (assert_delegation_failed): New functions. + * target.h (target_delegate_async, target_delegate_is_async_p) + (target_delegate_can_async_p, target_delegate_insert_breakpoint) + (target_delegate_remove_breakpoint, target_delegate_wait) + (target_delegate_resume, target_delegate_store_registers) + (target_delegate_stopped_by_watchpoint) + (target_delegate_stopped_data_address) + (target_delegate_xfer_partial): Declare. + +2013-10-30 Tom Tromey + * record.c (find_record_target): Use find_target_at. * record.h (RECORD_IS_REPLAY): Use find_target_at. * target.c (find_target_at): New function. diff --git a/gdb/make-target-delegates b/gdb/make-target-delegates new file mode 100755 index 0000000..720ca13 --- /dev/null +++ b/gdb/make-target-delegates @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +# For the time being we only allow certain methods. +%OK = ( + 'to_resume' => 1, + 'to_wait' => 1, + 'to_store_registers' => 1, + 'to_insert_breakpoint' => 1, + 'to_remove_breakpoint' => 1, + 'to_can_async_p' => 1, + 'to_is_async_p' => 1, + 'to_async' => 1, + 'to_stopped_by_watchpoint' => 1, + 'to_stopped_data_address' => 1, + 'to_xfer_partial' => 1 +); + +# The line we search for in target.h that marks where we should start +# looking for methods. +$TRIGGER = qr,^struct target_ops$,; +# The end of the methods part. +$ENDER = qr,^\s*};$,; + +$SYMBOL = qr,[a-zA-Z0-9_]+,; +$NAME_PART = qr,\(\*(?${SYMBOL}+)\)\s,; +$ARGS_PART = qr,(?\(.*)$,; +$INTRO_PART = qr,^\s*,; + +$SIMPLE_RETURN_PART = qr,[^\(]+,; +$VEC_RETURN_PART = qr,VEC\s*\([^\)]+\)[^\(]*,; + +$METHOD = ($INTRO_PART . "(?" . $SIMPLE_RETURN_PART + . "|" . $VEC_RETURN_PART . ")" + . $NAME_PART . $ARGS_PART); + +sub trim($) { + my ($result) = @_; + $result =~ s,^\s*(\S*)\s*$,\1,; + return $result; +} + +# Read from the input files until we find the trigger line. +# Die if not found. +sub find_trigger() { + while (<>) { + chomp; + return if m/$TRIGGER/; + } + + die "could not find trigger line\n"; +} + +# Parse arguments into a list. +sub parse_argtypes($) { + my ($typestr) = @_; + + $typestr =~ s/^\((.*)\);$/\1/; + + my (@typelist) = split (/,\s*/, $typestr); + my (@result, $iter, $onetype); + + foreach $iter (@typelist) { + if ($iter =~ m/^(enum\s+${SYMBOL}\s*)(${SYMBOL})?$/) { + $onetype = $1; + } elsif ($iter =~ m/^(.*(enum\s+)?${SYMBOL}.*(\s|\*))${SYMBOL}+$/) { + $onetype = $1; + } elsif ($iter eq 'void') { + next; + } else { + $onetype = $iter; + } + push @result, trim ($onetype); + } + + return @result; +} + +sub dname($) { + my ($name) = @_; + $name =~ s/to_/delegate_/; + return $name; +} + +# Write out a delegation function. +sub write_delegator($$@) { + my ($name, $return_type, @argtypes) = @_; + + print "static " . $return_type . "\n"; + print dname ($name) . ' ('; + + my $iter; + my @argdecls; + my @actuals; + my $i = 0; + foreach $iter (@argtypes) { + my $val = $iter; + + if ($iter !~ m,\*$,) { + $val .= ' '; + } + + my $vname; + if ($i == 0) { + # Just a random nicety. + $vname = 'self'; + } else { + $vname .= "arg$i"; + } + $val .= $vname; + + push @argdecls, $val; + push @actuals, $vname; + ++$i; + } + + print join (', ', @argdecls) . ")\n"; + print "{\n"; + print " self = self->beneath;\n"; + print " "; + if ($return_type ne 'void') { + print "return "; + } + print "self->" . $name . " ("; + print join (', ', @actuals); + print ");\n"; + print "}\n\n"; +} + +print "/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */\n"; +print "/* vi:set ro: */\n\n"; +print "/* To regenerate this file, run:*/\n"; +print "/* make-target-delegates target.h > target-delegates.c */\n"; + +find_trigger(); + +@delegators = (); +$current_args = ''; +while (<>) { + chomp; + last if m/$ENDER/; + + if ($current_args ne '') { + s/^\s*//; + $current_args .= $_; + } elsif (m/$METHOD/) { + $name = $+{name}; + $current_args = $+{args}; + $return_type = trim ($+{return_type}); + } + + if ($current_args =~ /\);\s*$/) { + if (defined $OK{$name}) { + @argtypes = parse_argtypes ($current_args); + + # The first argument must be "this" to be delegatable. + if ($argtypes[0] =~ /\s*struct\s+target_ops\s*\*\s*/) { + write_delegator ($name, $return_type, @argtypes); + + push @delegators, $name; + } + } + + $current_args = ''; + } +} + +# Now the delegation code. +print "static void\ninstall_delegators (struct target_ops *ops)\n{\n"; + +for $iter (@delegators) { + print " if (ops->" . $iter . " == NULL)\n"; + print " ops->" . $iter . " = " . dname ($iter) . ";\n"; +} +print "}\n"; diff --git a/gdb/record-full.c b/gdb/record-full.c index f4d760a..1d66c6e 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -215,43 +215,6 @@ static struct cmd_list_element *show_record_full_cmdlist; /* Command list for "record full". */ static struct cmd_list_element *record_full_cmdlist; -/* The beneath function pointers. */ -static struct target_ops *record_full_beneath_to_resume_ops; -static void (*record_full_beneath_to_resume) (struct target_ops *, ptid_t, int, - enum gdb_signal); -static struct target_ops *record_full_beneath_to_wait_ops; -static ptid_t (*record_full_beneath_to_wait) (struct target_ops *, ptid_t, - struct target_waitstatus *, - int); -static struct target_ops *record_full_beneath_to_store_registers_ops; -static void (*record_full_beneath_to_store_registers) (struct target_ops *, - struct regcache *, - int regno); -static struct target_ops *record_full_beneath_to_xfer_partial_ops; -static LONGEST - (*record_full_beneath_to_xfer_partial) (struct target_ops *ops, - enum target_object object, - const char *annex, - gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, - LONGEST len); -static int - (*record_full_beneath_to_insert_breakpoint) (struct target_ops *, - struct gdbarch *, - struct bp_target_info *); -static int - (*record_full_beneath_to_remove_breakpoint) (struct target_ops *, - struct gdbarch *, - struct bp_target_info *); -static int (*record_full_beneath_to_stopped_by_watchpoint) (struct target_ops *); -static int (*record_full_beneath_to_stopped_data_address) (struct target_ops *, - CORE_ADDR *); -static void - (*record_full_beneath_to_async) (struct target_ops *, - void (*) (enum inferior_event_type, void *), - void *); - static void record_full_goto_insn (struct record_full_entry *entry, enum exec_direction_kind dir); static void record_full_save (const char *recfilename); @@ -798,36 +761,6 @@ record_full_exec_insn (struct regcache *regcache, } } -static struct target_ops *tmp_to_resume_ops; -static void (*tmp_to_resume) (struct target_ops *, ptid_t, int, - enum gdb_signal); -static struct target_ops *tmp_to_wait_ops; -static ptid_t (*tmp_to_wait) (struct target_ops *, ptid_t, - struct target_waitstatus *, - int); -static struct target_ops *tmp_to_store_registers_ops; -static void (*tmp_to_store_registers) (struct target_ops *, - struct regcache *, - int regno); -static struct target_ops *tmp_to_xfer_partial_ops; -static LONGEST (*tmp_to_xfer_partial) (struct target_ops *ops, - enum target_object object, - const char *annex, - gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, - LONGEST len); -static int (*tmp_to_insert_breakpoint) (struct target_ops *, - struct gdbarch *, - struct bp_target_info *); -static int (*tmp_to_remove_breakpoint) (struct target_ops *ops, - struct gdbarch *, - struct bp_target_info *); -static int (*tmp_to_stopped_by_watchpoint) (struct target_ops *); -static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *); -static void (*tmp_to_async) (struct target_ops *, - void (*) (enum inferior_event_type, void *), void *); - static void record_full_restore (void); /* Asynchronous signal handle registered as event loop source for when @@ -890,26 +823,6 @@ record_full_open_1 (char *name, int from_tty) error (_("Process record: the current architecture doesn't support " "record function.")); - if (!tmp_to_resume) - error (_("Could not find 'to_resume' method on the target stack.")); - if (!tmp_to_wait) - error (_("Could not find 'to_wait' method on the target stack.")); - if (!tmp_to_store_registers) - error (_("Could not find 'to_store_registers' " - "method on the target stack.")); - if (!tmp_to_insert_breakpoint) - error (_("Could not find 'to_insert_breakpoint' " - "method on the target stack.")); - if (!tmp_to_remove_breakpoint) - error (_("Could not find 'to_remove_breakpoint' " - "method on the target stack.")); - if (!tmp_to_stopped_by_watchpoint) - error (_("Could not find 'to_stopped_by_watchpoint' " - "method on the target stack.")); - if (!tmp_to_stopped_data_address) - error (_("Could not find 'to_stopped_data_address' " - "method on the target stack.")); - push_target (&record_full_ops); } @@ -926,83 +839,16 @@ record_full_open (char *name, int from_tty) fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n"); /* Check if record target is already running. */ - if (current_target.to_stratum == record_stratum) + if (RECORD_IS_USED) error (_("Process record target already running. Use \"record stop\" to " "stop record target first.")); - /* Reset the tmp beneath pointers. */ - tmp_to_resume_ops = NULL; - tmp_to_resume = NULL; - tmp_to_wait_ops = NULL; - tmp_to_wait = NULL; - tmp_to_store_registers_ops = NULL; - tmp_to_store_registers = NULL; - tmp_to_xfer_partial_ops = NULL; - tmp_to_xfer_partial = NULL; - tmp_to_insert_breakpoint = NULL; - tmp_to_remove_breakpoint = NULL; - tmp_to_stopped_by_watchpoint = NULL; - tmp_to_stopped_data_address = NULL; - tmp_to_async = NULL; - - /* Set the beneath function pointers. */ - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (!tmp_to_resume) - { - tmp_to_resume = t->to_resume; - tmp_to_resume_ops = t; - } - if (!tmp_to_wait) - { - tmp_to_wait = t->to_wait; - tmp_to_wait_ops = t; - } - if (!tmp_to_store_registers) - { - tmp_to_store_registers = t->to_store_registers; - tmp_to_store_registers_ops = t; - } - if (!tmp_to_xfer_partial) - { - tmp_to_xfer_partial = t->to_xfer_partial; - tmp_to_xfer_partial_ops = t; - } - if (!tmp_to_insert_breakpoint) - tmp_to_insert_breakpoint = t->to_insert_breakpoint; - if (!tmp_to_remove_breakpoint) - tmp_to_remove_breakpoint = t->to_remove_breakpoint; - if (!tmp_to_stopped_by_watchpoint) - tmp_to_stopped_by_watchpoint = t->to_stopped_by_watchpoint; - if (!tmp_to_stopped_data_address) - tmp_to_stopped_data_address = t->to_stopped_data_address; - if (!tmp_to_async) - tmp_to_async = t->to_async; - } - if (!tmp_to_xfer_partial) - error (_("Could not find 'to_xfer_partial' method on the target stack.")); - /* Reset */ record_full_insn_num = 0; record_full_insn_count = 0; record_full_list = &record_full_first; record_full_list->next = NULL; - /* Set the tmp beneath pointers to beneath pointers. */ - record_full_beneath_to_resume_ops = tmp_to_resume_ops; - record_full_beneath_to_resume = tmp_to_resume; - record_full_beneath_to_wait_ops = tmp_to_wait_ops; - record_full_beneath_to_wait = tmp_to_wait; - record_full_beneath_to_store_registers_ops = tmp_to_store_registers_ops; - record_full_beneath_to_store_registers = tmp_to_store_registers; - record_full_beneath_to_xfer_partial_ops = tmp_to_xfer_partial_ops; - record_full_beneath_to_xfer_partial = tmp_to_xfer_partial; - record_full_beneath_to_insert_breakpoint = tmp_to_insert_breakpoint; - record_full_beneath_to_remove_breakpoint = tmp_to_remove_breakpoint; - record_full_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint; - record_full_beneath_to_stopped_data_address = tmp_to_stopped_data_address; - record_full_beneath_to_async = tmp_to_async; - if (core_bfd) record_full_core_open_1 (name, from_tty); else @@ -1126,8 +972,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step, /* Make sure the target beneath reports all signals. */ target_pass_signals (0, NULL); - record_full_beneath_to_resume (record_full_beneath_to_resume_ops, - ptid, step, signal); + ops->beneath->to_resume (ops->beneath, ptid, step, signal); } /* We are about to start executing the inferior (or simulate it), @@ -1217,8 +1062,7 @@ record_full_wait_1 (struct target_ops *ops, if (record_full_resume_step) { /* This is a single step. */ - return record_full_beneath_to_wait (record_full_beneath_to_wait_ops, - ptid, status, options); + return ops->beneath->to_wait (ops->beneath, ptid, status, options); } else { @@ -1229,8 +1073,7 @@ record_full_wait_1 (struct target_ops *ops, while (1) { - ret = record_full_beneath_to_wait - (record_full_beneath_to_wait_ops, ptid, status, options); + ret = ops->beneath->to_wait (ops->beneath, ptid, status, options); if (status->kind == TARGET_WAITKIND_IGNORE) { if (record_debug) @@ -1314,9 +1157,8 @@ record_full_wait_1 (struct target_ops *ops, "Process record: record_full_wait " "issuing one more step in the " "target beneath\n"); - record_full_beneath_to_resume - (record_full_beneath_to_resume_ops, ptid, step, - GDB_SIGNAL_0); + ops->beneath->to_resume (ops->beneath, ptid, step, + GDB_SIGNAL_0); continue; } } @@ -1520,11 +1362,7 @@ record_full_stopped_by_watchpoint (struct target_ops *ops) if (RECORD_FULL_IS_REPLAY) return record_full_hw_watchpoint; else - { - struct target_ops *beneath = find_target_beneath (ops); - - return record_full_beneath_to_stopped_by_watchpoint (beneath); - } + return ops->beneath->to_stopped_by_watchpoint (ops->beneath); } static int @@ -1533,7 +1371,7 @@ record_full_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) if (RECORD_FULL_IS_REPLAY) return 0; else - return record_full_beneath_to_stopped_data_address (ops, addr_p); + return ops->beneath->to_stopped_data_address (ops->beneath, addr_p); } /* Record registers change (by user or by GDB) to list as an instruction. */ @@ -1636,8 +1474,7 @@ record_full_store_registers (struct target_ops *ops, record_full_registers_change (regcache, regno); } - record_full_beneath_to_store_registers - (record_full_beneath_to_store_registers_ops, regcache, regno); + ops->beneath->to_store_registers (ops->beneath, regcache, regno); } /* "to_xfer_partial" method. Behavior is conditional on @@ -1702,9 +1539,9 @@ record_full_xfer_partial (struct target_ops *ops, enum target_object object, record_full_insn_num++; } - return record_full_beneath_to_xfer_partial - (record_full_beneath_to_xfer_partial_ops, object, annex, - readbuf, writebuf, offset, len); + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, + len); } /* This structure represents a breakpoint inserted while the record @@ -1785,8 +1622,7 @@ record_full_insert_breakpoint (struct target_ops *ops, int ret; old_cleanups = record_full_gdb_operation_disable_set (); - ret = record_full_beneath_to_insert_breakpoint (find_target_beneath (ops), - gdbarch, bp_tgt); + ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt); do_cleanups (old_cleanups); if (ret != 0) @@ -1827,8 +1663,8 @@ record_full_remove_breakpoint (struct target_ops *ops, int ret; old_cleanups = record_full_gdb_operation_disable_set (); - ret = record_full_beneath_to_remove_breakpoint (find_target_beneath (ops), - gdbarch, bp_tgt); + ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, + bp_tgt); do_cleanups (old_cleanups); if (ret != 0) @@ -1902,32 +1738,6 @@ record_full_goto_bookmark (gdb_byte *raw_bookmark, int from_tty) return; } -static void -record_full_async (struct target_ops *ops, - void (*callback) (enum inferior_event_type event_type, - void *context), void *context) -{ - /* If we're on top of a line target (e.g., linux-nat, remote), then - set it to async mode as well. Will be NULL if we're sitting on - top of the core target, for "record restore". */ - if (record_full_beneath_to_async != NULL) - record_full_beneath_to_async (find_target_beneath (ops), callback, context); -} - -static int -record_full_can_async_p (struct target_ops *ops) -{ - /* We only enable async when the user specifically asks for it. */ - return target_async_permitted; -} - -static int -record_full_is_async_p (struct target_ops *ops) -{ - /* We only enable async when the user specifically asks for it. */ - return target_async_permitted; -} - static enum exec_direction_kind record_full_execution_direction (void) { @@ -2092,9 +1902,6 @@ init_record_full_ops (void) /* Add bookmark target methods. */ record_full_ops.to_get_bookmark = record_full_get_bookmark; record_full_ops.to_goto_bookmark = record_full_goto_bookmark; - record_full_ops.to_async = record_full_async; - record_full_ops.to_can_async_p = record_full_can_async_p; - record_full_ops.to_is_async_p = record_full_is_async_p; record_full_ops.to_execution_direction = record_full_execution_direction; record_full_ops.to_info_record = record_full_info; record_full_ops.to_save_record = record_full_save; @@ -2251,10 +2058,10 @@ record_full_core_xfer_partial (struct target_ops *ops, else { if (!entry) - return record_full_beneath_to_xfer_partial - (record_full_beneath_to_xfer_partial_ops, - object, annex, readbuf, writebuf, - offset, len); + return ops->beneath->to_xfer_partial (ops->beneath, + object, annex, + readbuf, writebuf, + offset, len); memcpy (readbuf, entry->buf + sec_offset, (size_t) len); @@ -2270,9 +2077,8 @@ record_full_core_xfer_partial (struct target_ops *ops, error (_("You can't do that without a process to debug.")); } - return record_full_beneath_to_xfer_partial - (record_full_beneath_to_xfer_partial_ops, object, annex, - readbuf, writebuf, offset, len); + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, len); } /* "to_insert_breakpoint" method for prec over corefile. */ @@ -2334,9 +2140,6 @@ init_record_full_core_ops (void) /* Add bookmark target methods. */ record_full_core_ops.to_get_bookmark = record_full_get_bookmark; record_full_core_ops.to_goto_bookmark = record_full_goto_bookmark; - record_full_core_ops.to_async = record_full_async; - record_full_core_ops.to_can_async_p = record_full_can_async_p; - record_full_core_ops.to_is_async_p = record_full_is_async_p; record_full_core_ops.to_execution_direction = record_full_execution_direction; record_full_core_ops.to_info_record = record_full_info; diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c new file mode 100644 index 0000000..60a28ca --- /dev/null +++ b/gdb/target-delegates.c @@ -0,0 +1,108 @@ +/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */ +/* vi:set ro: */ + +/* To regenerate this file, run:*/ +/* make-target-delegates target.h > target-delegates.c */ +static void +delegate_resume (struct target_ops *self, ptid_t arg1, int arg2, enum gdb_signal arg3) +{ + self = self->beneath; + self->to_resume (self, arg1, arg2, arg3); +} + +static ptid_t +delegate_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) +{ + self = self->beneath; + return self->to_wait (self, arg1, arg2, arg3); +} + +static void +delegate_store_registers (struct target_ops *self, struct regcache *arg1, int arg2) +{ + self = self->beneath; + self->to_store_registers (self, arg1, arg2); +} + +static int +delegate_insert_breakpoint (struct target_ops *self, struct gdbarch *arg1, struct bp_target_info *arg2) +{ + self = self->beneath; + return self->to_insert_breakpoint (self, arg1, arg2); +} + +static int +delegate_remove_breakpoint (struct target_ops *self, struct gdbarch *arg1, struct bp_target_info *arg2) +{ + self = self->beneath; + return self->to_remove_breakpoint (self, arg1, arg2); +} + +static int +delegate_stopped_by_watchpoint (struct target_ops *self) +{ + self = self->beneath; + return self->to_stopped_by_watchpoint (self); +} + +static int +delegate_stopped_data_address (struct target_ops *self, CORE_ADDR *arg1) +{ + self = self->beneath; + return self->to_stopped_data_address (self, arg1); +} + +static int +delegate_can_async_p (struct target_ops *self) +{ + self = self->beneath; + return self->to_can_async_p (self); +} + +static int +delegate_is_async_p (struct target_ops *self) +{ + self = self->beneath; + return self->to_is_async_p (self); +} + +static void +delegate_async (struct target_ops *self, async_callback_ftype *arg1, void *arg2) +{ + self = self->beneath; + self->to_async (self, arg1, arg2); +} + +static LONGEST +delegate_xfer_partial (struct target_ops *self, enum target_object arg1, const char *arg2, gdb_byte *arg3, const gdb_byte *arg4, ULONGEST arg5, LONGEST arg6) +{ + self = self->beneath; + return self->to_xfer_partial (self, arg1, arg2, arg3, arg4, arg5, arg6); +} + +static void +install_delegators (struct target_ops *ops) +{ + if (ops->to_resume == NULL) + ops->to_resume = delegate_resume; + if (ops->to_wait == NULL) + ops->to_wait = delegate_wait; + if (ops->to_store_registers == NULL) + ops->to_store_registers = delegate_store_registers; + if (ops->to_insert_breakpoint == NULL) + ops->to_insert_breakpoint = delegate_insert_breakpoint; + if (ops->to_remove_breakpoint == NULL) + ops->to_remove_breakpoint = delegate_remove_breakpoint; + if (ops->to_stopped_by_watchpoint == NULL) + ops->to_stopped_by_watchpoint = delegate_stopped_by_watchpoint; + if (ops->to_stopped_data_address == NULL) + ops->to_stopped_data_address = delegate_stopped_data_address; + if (ops->to_can_async_p == NULL) + ops->to_can_async_p = delegate_can_async_p; + if (ops->to_is_async_p == NULL) + ops->to_is_async_p = delegate_is_async_p; + if (ops->to_async == NULL) + ops->to_async = delegate_async; + if (ops->to_xfer_partial == NULL) + ops->to_xfer_partial = delegate_xfer_partial; +} diff --git a/gdb/target.c b/gdb/target.c index d2a40ee..e765700 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -45,6 +45,8 @@ #include "gdb/fileio.h" #include "agent.h" +#include "target-delegates.c" + static void target_info (char *, int); static void default_terminal_info (const char *, int); @@ -76,12 +78,6 @@ static LONGEST default_xfer_partial (struct target_ops *ops, const gdb_byte *writebuf, ULONGEST offset, LONGEST len); -static LONGEST current_xfer_partial (struct target_ops *ops, - enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, LONGEST len); - static struct gdbarch *default_thread_architecture (struct target_ops *ops, ptid_t ptid); @@ -352,6 +348,8 @@ complete_target_initialization (struct target_ops *t) if (t->to_has_execution == NULL) t->to_has_execution = (int (*) (struct target_ops *, ptid_t)) return_zero; + + install_delegators (t); } /* Add possible target architecture T to the list and add a new @@ -559,6 +557,9 @@ update_current_target (void) /* First, reset current's contents. */ memset (¤t_target, 0, sizeof (current_target)); + /* The newest approach is to auto-delegate some methods. */ + install_delegators (¤t_target); + #define INHERIT(FIELD, TARGET) \ if (!current_target.FIELD) \ current_target.FIELD = (TARGET)->FIELD @@ -582,8 +583,8 @@ update_current_target (void) INHERIT (to_prepare_to_store, t); INHERIT (deprecated_xfer_memory, t); INHERIT (to_files_info, t); - INHERIT (to_insert_breakpoint, t); - INHERIT (to_remove_breakpoint, t); + /* Do not inherit to_insert_breakpoint. */ + /* Do not inherit to_remove_breakpoint. */ INHERIT (to_can_use_hw_breakpoint, t); INHERIT (to_insert_hw_breakpoint, t); INHERIT (to_remove_hw_breakpoint, t); @@ -592,10 +593,10 @@ update_current_target (void) INHERIT (to_remove_watchpoint, t); /* Do not inherit to_insert_mask_watchpoint. */ /* Do not inherit to_remove_mask_watchpoint. */ - INHERIT (to_stopped_data_address, t); + /* Do not inherit to_stopped_data_address. */ INHERIT (to_have_steppable_watchpoint, t); INHERIT (to_have_continuable_watchpoint, t); - INHERIT (to_stopped_by_watchpoint, t); + /* Do not inherit to_stopped_by_watchpoint. */ INHERIT (to_watchpoint_addr_within_range, t); INHERIT (to_region_ok_for_hw_watchpoint, t); INHERIT (to_can_accel_watchpoint_condition, t); @@ -640,9 +641,9 @@ update_current_target (void) /* Do not inherit to_has_registers. */ /* Do not inherit to_has_execution. */ INHERIT (to_has_thread_control, t); - INHERIT (to_can_async_p, t); - INHERIT (to_is_async_p, t); - INHERIT (to_async, t); + /* Do not inherit to_can_async_p. */ + /* Do not inherit to_is_async_p. */ + /* Do not inherit to_async. */ INHERIT (to_find_memory_regions, t); INHERIT (to_make_corefile_notes, t); INHERIT (to_get_bookmark, t); @@ -742,12 +743,6 @@ update_current_target (void) de_fault (to_remove_watchpoint, (int (*) (CORE_ADDR, int, int, struct expression *)) return_minus_one); - de_fault (to_stopped_by_watchpoint, - (int (*) (struct target_ops *)) - return_zero); - de_fault (to_stopped_data_address, - (int (*) (struct target_ops *, CORE_ADDR *)) - return_zero); de_fault (to_watchpoint_addr_within_range, default_watchpoint_addr_within_range); de_fault (to_region_ok_for_hw_watchpoint, @@ -813,18 +808,12 @@ update_current_target (void) de_fault (to_stop, (void (*) (ptid_t)) target_ignore); - current_target.to_xfer_partial = current_xfer_partial; de_fault (to_rcmd, (void (*) (char *, struct ui_file *)) tcomplain); de_fault (to_pid_to_exec_file, (char *(*) (int)) return_zero); - de_fault (to_async, - (void (*) (struct target_ops *, - void (*) (enum inferior_event_type, void*), - void*)) - tcomplain); de_fault (to_thread_architecture, default_thread_architecture); current_target.to_read_description = NULL; @@ -1996,27 +1985,12 @@ default_xfer_partial (struct target_ops *ops, enum target_object object, else return -1; } - else if (ops->beneath != NULL) - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, - readbuf, writebuf, offset, len); - else - return -1; -} - -/* The xfer_partial handler for the topmost target. Unlike the default, - it does not need to handle memory specially; it just passes all - requests down the stack. */ - -static LONGEST -current_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, LONGEST len) -{ - if (ops->beneath != NULL) - return ops->beneath->to_xfer_partial (ops->beneath, object, annex, - readbuf, writebuf, offset, len); else - return -1; + { + gdb_assert (ops->beneath != NULL); + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, len); + } } /* Target vector read/write partial wrapper functions. */ @@ -2665,34 +2639,26 @@ ptid_t target_wait (ptid_t ptid, struct target_waitstatus *status, int options) { struct target_ops *t; + ptid_t retval = (current_target.to_wait) (¤t_target, ptid, + status, options); - for (t = current_target.beneath; t != NULL; t = t->beneath) + if (targetdebug) { - if (t->to_wait != NULL) - { - ptid_t retval = (*t->to_wait) (t, ptid, status, options); - - if (targetdebug) - { - char *status_string; - char *options_string; - - status_string = target_waitstatus_to_string (status); - options_string = target_options_to_string (options); - fprintf_unfiltered (gdb_stdlog, - "target_wait (%d, status, options={%s})" - " = %d, %s\n", - ptid_get_pid (ptid), options_string, - ptid_get_pid (retval), status_string); - xfree (status_string); - xfree (options_string); - } + char *status_string; + char *options_string; - return retval; - } + status_string = target_waitstatus_to_string (status); + options_string = target_options_to_string (options); + fprintf_unfiltered (gdb_stdlog, + "target_wait (%d, status, options={%s})" + " = %d, %s\n", + ptid_get_pid (ptid), options_string, + ptid_get_pid (retval), status_string); + xfree (status_string); + xfree (options_string); } - noprocess (); + return retval; } char * @@ -2730,26 +2696,17 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal) target_dcache_invalidate (); - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_resume != NULL) - { - t->to_resume (t, ptid, step, signal); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", - ptid_get_pid (ptid), - step ? "step" : "continue", - gdb_signal_to_name (signal)); - - registers_changed_ptid (ptid); - set_executing (ptid, 1); - set_running (ptid, 1); - clear_inline_frame_state (ptid); - return; - } - } + current_target.to_resume (¤t_target, ptid, step, signal); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n", + ptid_get_pid (ptid), + step ? "step" : "continue", + gdb_signal_to_name (signal)); - noprocess (); + registers_changed_ptid (ptid); + set_executing (ptid, 1); + set_running (ptid, 1); + clear_inline_frame_state (ptid); } void @@ -3146,7 +3103,7 @@ find_default_can_async_p (struct target_ops *ignore) configured with a native debugger, and target remote isn't connected yet. */ t = find_default_run_target (NULL); - if (t && t->to_can_async_p) + if (t) return (t->to_can_async_p) (t); return 0; } @@ -3161,7 +3118,7 @@ find_default_is_async_p (struct target_ops *ignore) configured with a native debugger, and target remote isn't connected yet. */ t = find_default_run_target (NULL); - if (t && t->to_is_async_p) + if (t) return (t->to_is_async_p) (t); return 0; } @@ -3716,6 +3673,46 @@ dummy_pid_to_str (struct target_ops *ops, ptid_t ptid) return normal_pid_to_str (ptid); } +static void +dummy_resume (struct target_ops *self, ptid_t ptid, int step, + enum gdb_signal signal) +{ + noprocess (); +} + +static ptid_t +dummy_wait (struct target_ops *self, ptid_t ptid, + struct target_waitstatus *status, int options) +{ + noprocess (); +} + +static void +dummy_store_registers (struct target_ops *self, + struct regcache *regcache, + int regno) +{ + noprocess (); +} + +static LONGEST +dummy_xfer_partial (struct target_ops *ops, + enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + return -1; +} + +static void +dummy_async (struct target_ops *self, + void (*callback) (enum inferior_event_type, void *), + void *datum) +{ + tcomplain (); +} + /* Error-catcher for target_find_memory_regions. */ static int dummy_find_memory_regions (find_memory_region_ftype ignore1, void *ignore2) @@ -3760,8 +3757,11 @@ init_dummy_target (void) dummy_target.to_detach = (void (*)(struct target_ops *, const char *, int))target_ignore; dummy_target.to_create_inferior = find_default_create_inferior; + dummy_target.to_resume = dummy_resume; + dummy_target.to_wait = dummy_wait; dummy_target.to_can_async_p = find_default_can_async_p; dummy_target.to_is_async_p = find_default_is_async_p; + dummy_target.to_async = dummy_async; dummy_target.to_supports_non_stop = find_default_supports_non_stop; dummy_target.to_supports_disable_randomization = find_default_supports_disable_randomization; @@ -3771,13 +3771,14 @@ init_dummy_target (void) dummy_target.to_make_corefile_notes = dummy_make_corefile_notes; dummy_target.to_get_bookmark = dummy_get_bookmark; dummy_target.to_goto_bookmark = dummy_goto_bookmark; - dummy_target.to_xfer_partial = default_xfer_partial; + dummy_target.to_xfer_partial = dummy_xfer_partial; dummy_target.to_has_all_memory = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_memory = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_stack = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_registers = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_execution = (int (*) (struct target_ops *, ptid_t)) return_zero; + dummy_target.to_store_registers = dummy_store_registers; dummy_target.to_stopped_by_watchpoint = (int (*) (struct target_ops *)) return_zero; dummy_target.to_stopped_data_address = @@ -3999,20 +4000,11 @@ target_store_registers (struct regcache *regcache, int regno) if (!may_write_registers) error (_("Writing to registers is not allowed (regno %d)"), regno); - for (t = current_target.beneath; t != NULL; t = t->beneath) + current_target.to_store_registers (¤t_target, regcache, regno); + if (targetdebug) { - if (t->to_store_registers != NULL) - { - t->to_store_registers (t, regcache, regno); - if (targetdebug) - { - debug_print_register ("target_store_registers", regcache, regno); - } - return; - } + debug_print_register ("target_store_registers", regcache, regno); } - - noprocess (); } int diff --git a/gdb/target.h b/gdb/target.h index b219cff..804e8e4 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -341,6 +341,8 @@ extern ULONGEST get_target_memory_unsigned (struct target_ops *ops, struct thread_info; /* fwd decl for parameter list below: */ +typedef void async_callback_ftype (enum inferior_event_type, void *); + struct target_ops { struct target_ops *beneath; /* To the target under this one. */ @@ -484,8 +486,7 @@ struct target_ops /* ASYNC target controls */ int (*to_can_async_p) (struct target_ops *); int (*to_is_async_p) (struct target_ops *); - void (*to_async) (struct target_ops *, - void (*) (enum inferior_event_type, void *), void *); + void (*to_async) (struct target_ops *, async_callback_ftype *, void *); int (*to_supports_non_stop) (void); /* find_memory_regions support method for gcore */ int (*to_find_memory_regions) (find_memory_region_ftype func, void *data); -- 1.8.1.4 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0007-convert-to_detach.patch Content-Description: patch #2 Content-length: 2431 >From 91fe0229e03f82921be927a66762bdc7d4e08d68 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 13 Dec 2013 13:33:08 -0700 Subject: [PATCH 07/11] convert to_detach --- gdb/make-target-delegates | 3 ++- gdb/target-delegates.c | 9 +++++++++ gdb/target.c | 17 ++++------------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/gdb/make-target-delegates b/gdb/make-target-delegates index 296ea5e..89a0920 100755 --- a/gdb/make-target-delegates +++ b/gdb/make-target-delegates @@ -13,7 +13,8 @@ 'to_stopped_by_watchpoint' => 1, 'to_stopped_data_address' => 1, 'to_xfer_partial' => 1, - 'to_supports_btrace' => 1 + 'to_supports_btrace' => 1, + 'to_detach' => 1 ); # The line we search for in target.h that marks where we should start diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index b4a35cb..1bfbde6 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -4,6 +4,13 @@ /* To regenerate this file, run:*/ /* make-target-delegates target.h > target-delegates.c */ static void +delegate_detach (struct target_ops *self, const char *arg1, int arg2) +{ + self = self->beneath; + self->to_detach (self, arg1, arg2); +} + +static void delegate_resume (struct target_ops *self, ptid_t arg1, int arg2, enum gdb_signal arg3) { self = self->beneath; @@ -90,6 +97,8 @@ delegate_supports_btrace (struct target_ops *self) static void install_delegators (struct target_ops *ops) { + if (ops->to_detach == NULL) + ops->to_detach = delegate_detach; if (ops->to_resume == NULL) ops->to_resume = delegate_resume; if (ops->to_wait == NULL) diff --git a/gdb/target.c b/gdb/target.c index c992cf3..dc14c60 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2597,19 +2597,10 @@ target_detach (const char *args, int from_tty) prepare_for_detach (); - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_detach != NULL) - { - t->to_detach (t, args, from_tty); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", - args, from_tty); - return; - } - } - - internal_error (__FILE__, __LINE__, _("could not find a target to detach")); + current_target.to_detach (¤t_target, args, from_tty); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n", + args, from_tty); } void -- 1.8.1.4 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0008-add-default-implementation-code.patch Content-Description: patch #3 Content-length: 18688 >From a0d428f0ac10c6acc8a41bd69912e4bf26b6066e Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 13 Dec 2013 14:14:29 -0700 Subject: [PATCH 08/11] add default implementation code --- gdb/make-target-delegates | 107 ++++++++++++++++++++++++++++++++-------------- gdb/target-delegates.c | 72 +++++++++++++++++++++++++++++++ gdb/target.c | 65 ++++------------------------ gdb/target.h | 50 ++++++++++++++++------ 4 files changed, 192 insertions(+), 102 deletions(-) diff --git a/gdb/make-target-delegates b/gdb/make-target-delegates index 89a0920..ed982c1 100755 --- a/gdb/make-target-delegates +++ b/gdb/make-target-delegates @@ -1,29 +1,12 @@ #!/usr/bin/perl -# For the time being we only allow certain methods. -%OK = ( - 'to_resume' => 1, - 'to_wait' => 1, - 'to_store_registers' => 1, - 'to_insert_breakpoint' => 1, - 'to_remove_breakpoint' => 1, - 'to_can_async_p' => 1, - 'to_is_async_p' => 1, - 'to_async' => 1, - 'to_stopped_by_watchpoint' => 1, - 'to_stopped_data_address' => 1, - 'to_xfer_partial' => 1, - 'to_supports_btrace' => 1, - 'to_detach' => 1 -); - # The line we search for in target.h that marks where we should start # looking for methods. $TRIGGER = qr,^struct target_ops$,; # The end of the methods part. $ENDER = qr,^\s*};$,; -$SYMBOL = qr,[a-zA-Z0-9_]+,; +$SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_]*,; $NAME_PART = qr,\(\*(?${SYMBOL}+)\)\s,; $ARGS_PART = qr,(?\(.*)$,; $INTRO_PART = qr,^\s*,; @@ -31,10 +14,14 @@ $INTRO_PART = qr,^\s*,; $SIMPLE_RETURN_PART = qr,[^\(]+,; $VEC_RETURN_PART = qr,VEC\s*\([^\)]+\)[^\(]*,; +$TARGET_DEFAULT_PART = qr,TARGET_DEFAULT\s*\((?.+)\),; + $METHOD = ($INTRO_PART . "(?" . $SIMPLE_RETURN_PART . "|" . $VEC_RETURN_PART . ")" . $NAME_PART . $ARGS_PART); +$METHOD_TRAILER = qr,(?\([^\)]+\))\s*${TARGET_DEFAULT_PART};$,; + sub trim($) { my ($result) = @_; $result =~ s,^\s*(\S*)\s*$,\1,; @@ -56,7 +43,7 @@ sub find_trigger() { sub parse_argtypes($) { my ($typestr) = @_; - $typestr =~ s/^\((.*)\);$/\1/; + $typestr =~ s/^\((.*)\)$/\1/; my (@typelist) = split (/,\s*/, $typestr); my (@result, $iter, $onetype); @@ -83,12 +70,13 @@ sub dname($) { return $name; } -# Write out a delegation function. -sub write_delegator($$@) { +# Write function header given name, return type, and argtypes. +# Returns a list of actual argument names. +sub write_function_header($$@) { my ($name, $return_type, @argtypes) = @_; print "static " . $return_type . "\n"; - print dname ($name) . ' ('; + print $name . ' ('; my $iter; my @argdecls; @@ -117,17 +105,56 @@ sub write_delegator($$@) { print join (', ', @argdecls) . ")\n"; print "{\n"; - print " self = self->beneath;\n"; + + return @actuals; +} + +# Write out a delegation function. +sub write_delegator($$@) { + my ($name, $return_type, @argtypes) = @_; + + my (@names) = write_function_header (dname ($name), $return_type, + @argtypes); + + print " $names[0] = $names[0]->beneath;\n"; print " "; if ($return_type ne 'void') { print "return "; } - print "self->" . $name . " ("; - print join (', ', @actuals); + print "$names[0]->" . $name . " ("; + print join (', ', @names); print ");\n"; print "}\n\n"; } +sub tdname ($) { + my ($name) = @_; + $name =~ s/to_/tdefault_/; + return $name; +} + +# Write out a default function. +sub write_tdefault($$$@) { + my ($content, $name, $return_type, @argtypes) = @_; + + if ($content =~ /^${SYMBOL}$/) { + return $content; + } + + write_function_header (tdname ($name), $return_type, @argtypes); + print " "; + + if ($content !~ /^${SYMBOL}/) { + print "return $content;\n"; + } else { + print "$content;\n"; + } + + print "}\n\n"; + + return tdname ($name); +} + print "/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */\n"; print "/* vi:set ro: */\n\n"; print "/* To regenerate this file, run:*/\n"; @@ -135,23 +162,27 @@ print "/* make-target-delegates target.h > target-delegates.c */\n"; find_trigger(); +%tdefault_names = (); @delegators = (); -$current_args = ''; +$current_line = ''; while (<>) { chomp; last if m/$ENDER/; - if ($current_args ne '') { + if ($current_line ne '') { s/^\s*//; - $current_args .= $_; + $current_line .= $_; } elsif (m/$METHOD/) { $name = $+{name}; - $current_args = $+{args}; + $current_line = $+{args}; $return_type = trim ($+{return_type}); } - if ($current_args =~ /\);\s*$/) { - if (defined $OK{$name}) { + if ($current_line =~ /\);\s*$/) { + if ($current_line =~ m,$METHOD_TRAILER,) { + $current_args = $+{args}; + $tdefault = $+{default_arg}; + @argtypes = parse_argtypes ($current_args); # The first argument must be "this" to be delegatable. @@ -159,10 +190,14 @@ while (<>) { write_delegator ($name, $return_type, @argtypes); push @delegators, $name; + + $tdefault_names{$name} = write_tdefault ($tdefault, + $name, $return_type, + @argtypes); } } - $current_args = ''; + $current_line = ''; } } @@ -173,4 +208,12 @@ for $iter (@delegators) { print " if (ops->" . $iter . " == NULL)\n"; print " ops->" . $iter . " = " . dname ($iter) . ";\n"; } +print "}\n\n"; + +# Now the default method code. +print "static void\ninstall_dummy_methods (struct target_ops *ops)\n{\n"; + +for $iter (@delegators) { + print " ops->" . $iter . " = " . $tdefault_names{$iter} . ";\n"; +} print "}\n"; diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index 1bfbde6..84429a4 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -11,12 +11,24 @@ delegate_detach (struct target_ops *self, const char *arg1, int arg2) } static void +tdefault_detach (struct target_ops *self, const char *arg1, int arg2) +{ + target_ignore (); +} + +static void delegate_resume (struct target_ops *self, ptid_t arg1, int arg2, enum gdb_signal arg3) { self = self->beneath; self->to_resume (self, arg1, arg2, arg3); } +static void +tdefault_resume (struct target_ops *self, ptid_t arg1, int arg2, enum gdb_signal arg3) +{ + noprocess (); +} + static ptid_t delegate_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) { @@ -24,6 +36,12 @@ delegate_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *a return self->to_wait (self, arg1, arg2, arg3); } +static ptid_t +tdefault_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) +{ + noprocess (); +} + static void delegate_store_registers (struct target_ops *self, struct regcache *arg1, int arg2) { @@ -31,6 +49,12 @@ delegate_store_registers (struct target_ops *self, struct regcache *arg1, int ar self->to_store_registers (self, arg1, arg2); } +static void +tdefault_store_registers (struct target_ops *self, struct regcache *arg1, int arg2) +{ + noprocess (); +} + static int delegate_insert_breakpoint (struct target_ops *self, struct gdbarch *arg1, struct bp_target_info *arg2) { @@ -53,6 +77,12 @@ delegate_stopped_by_watchpoint (struct target_ops *self) } static int +tdefault_stopped_by_watchpoint (struct target_ops *self) +{ + return 0; +} + +static int delegate_stopped_data_address (struct target_ops *self, CORE_ADDR *arg1) { self = self->beneath; @@ -60,6 +90,12 @@ delegate_stopped_data_address (struct target_ops *self, CORE_ADDR *arg1) } static int +tdefault_stopped_data_address (struct target_ops *self, CORE_ADDR *arg1) +{ + return 0; +} + +static int delegate_can_async_p (struct target_ops *self) { self = self->beneath; @@ -80,6 +116,12 @@ delegate_async (struct target_ops *self, async_callback_ftype *arg1, void *arg2) self->to_async (self, arg1, arg2); } +static void +tdefault_async (struct target_ops *self, async_callback_ftype *arg1, void *arg2) +{ + tcomplain (); +} + static LONGEST delegate_xfer_partial (struct target_ops *self, enum target_object arg1, const char *arg2, gdb_byte *arg3, const gdb_byte *arg4, ULONGEST arg5, LONGEST arg6) { @@ -87,6 +129,12 @@ delegate_xfer_partial (struct target_ops *self, enum target_object arg1, const return self->to_xfer_partial (self, arg1, arg2, arg3, arg4, arg5, arg6); } +static LONGEST +tdefault_xfer_partial (struct target_ops *self, enum target_object arg1, const char *arg2, gdb_byte *arg3, const gdb_byte *arg4, ULONGEST arg5, LONGEST arg6) +{ + return -1; +} + static int delegate_supports_btrace (struct target_ops *self) { @@ -94,6 +142,12 @@ delegate_supports_btrace (struct target_ops *self) return self->to_supports_btrace (self); } +static int +tdefault_supports_btrace (struct target_ops *self) +{ + return 0; +} + static void install_delegators (struct target_ops *ops) { @@ -124,3 +178,21 @@ install_delegators (struct target_ops *ops) if (ops->to_supports_btrace == NULL) ops->to_supports_btrace = delegate_supports_btrace; } + +static void +install_dummy_methods (struct target_ops *ops) +{ + ops->to_detach = tdefault_detach; + ops->to_resume = tdefault_resume; + ops->to_wait = tdefault_wait; + ops->to_store_registers = tdefault_store_registers; + ops->to_insert_breakpoint = memory_insert_breakpoint; + ops->to_remove_breakpoint = memory_remove_breakpoint; + ops->to_stopped_by_watchpoint = tdefault_stopped_by_watchpoint; + ops->to_stopped_data_address = tdefault_stopped_data_address; + ops->to_can_async_p = find_default_can_async_p; + ops->to_is_async_p = find_default_is_async_p; + ops->to_async = tdefault_async; + ops->to_xfer_partial = tdefault_xfer_partial; + ops->to_supports_btrace = tdefault_supports_btrace; +} diff --git a/gdb/target.c b/gdb/target.c index dc14c60..b6d8c85 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -45,8 +45,6 @@ #include "gdb/fileio.h" #include "agent.h" -#include "target-delegates.c" - static void target_info (char *, int); static void default_terminal_info (const char *, int); @@ -81,6 +79,12 @@ static LONGEST default_xfer_partial (struct target_ops *ops, static struct gdbarch *default_thread_architecture (struct target_ops *ops, ptid_t ptid); +static int find_default_can_async_p (struct target_ops *ignore); + +static int find_default_is_async_p (struct target_ops *ignore); + +#include "target-delegates.c" + static void init_dummy_target (void); static struct target_ops debug_target; @@ -3664,46 +3668,6 @@ dummy_pid_to_str (struct target_ops *ops, ptid_t ptid) return normal_pid_to_str (ptid); } -static void -dummy_resume (struct target_ops *self, ptid_t ptid, int step, - enum gdb_signal signal) -{ - noprocess (); -} - -static ptid_t -dummy_wait (struct target_ops *self, ptid_t ptid, - struct target_waitstatus *status, int options) -{ - noprocess (); -} - -static void -dummy_store_registers (struct target_ops *self, - struct regcache *regcache, - int regno) -{ - noprocess (); -} - -static LONGEST -dummy_xfer_partial (struct target_ops *ops, - enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) -{ - return -1; -} - -static void -dummy_async (struct target_ops *self, - void (*callback) (enum inferior_event_type, void *), - void *datum) -{ - tcomplain (); -} - /* Error-catcher for target_find_memory_regions. */ static int dummy_find_memory_regions (find_memory_region_ftype ignore1, void *ignore2) @@ -3745,14 +3709,7 @@ init_dummy_target (void) dummy_target.to_longname = "None"; dummy_target.to_doc = ""; dummy_target.to_attach = find_default_attach; - dummy_target.to_detach = - (void (*)(struct target_ops *, const char *, int))target_ignore; dummy_target.to_create_inferior = find_default_create_inferior; - dummy_target.to_resume = dummy_resume; - dummy_target.to_wait = dummy_wait; - dummy_target.to_can_async_p = find_default_can_async_p; - dummy_target.to_is_async_p = find_default_is_async_p; - dummy_target.to_async = dummy_async; dummy_target.to_supports_non_stop = find_default_supports_non_stop; dummy_target.to_supports_disable_randomization = find_default_supports_disable_randomization; @@ -3762,21 +3719,15 @@ init_dummy_target (void) dummy_target.to_make_corefile_notes = dummy_make_corefile_notes; dummy_target.to_get_bookmark = dummy_get_bookmark; dummy_target.to_goto_bookmark = dummy_goto_bookmark; - dummy_target.to_xfer_partial = dummy_xfer_partial; dummy_target.to_has_all_memory = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_memory = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_stack = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_registers = (int (*) (struct target_ops *)) return_zero; dummy_target.to_has_execution = (int (*) (struct target_ops *, ptid_t)) return_zero; - dummy_target.to_store_registers = dummy_store_registers; - dummy_target.to_stopped_by_watchpoint - = (int (*) (struct target_ops *)) return_zero; - dummy_target.to_stopped_data_address = - (int (*) (struct target_ops *, CORE_ADDR *)) return_zero; - dummy_target.to_supports_btrace - = (int (*) (struct target_ops *)) return_zero; dummy_target.to_magic = OPS_MAGIC; + + install_dummy_methods (&dummy_target); } static void diff --git a/gdb/target.h b/gdb/target.h index 4b364ef..20bb33a 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -343,6 +343,17 @@ struct thread_info; /* fwd decl for parameter list below: */ typedef void async_callback_ftype (enum inferior_event_type, void *); +/* This is used to indicate the default implementation for a target + method. It is handled by make-target-delegates. The argument can be: + . A simple constant, like "0", in which case the default method + returns the constant. + . A function call, like "tcomplain ()", in which case the default + method simply calls the function. Ordinarily such functions must + therefore be "noreturn". + . The name of a function, like "memory_insert_breakpoint", in which + case the named function is used as the default method. */ +#define TARGET_DEFAULT(ARG) + struct target_ops { struct target_ops *beneath; /* To the target under this one. */ @@ -365,13 +376,17 @@ struct target_ops void (*to_close) (void); void (*to_attach) (struct target_ops *ops, char *, int); void (*to_post_attach) (int); - void (*to_detach) (struct target_ops *ops, const char *, int); + void (*to_detach) (struct target_ops *ops, const char *, int) + TARGET_DEFAULT (target_ignore ()); void (*to_disconnect) (struct target_ops *, char *, int); - void (*to_resume) (struct target_ops *, ptid_t, int, enum gdb_signal); + void (*to_resume) (struct target_ops *, ptid_t, int, enum gdb_signal) + TARGET_DEFAULT (noprocess ()); ptid_t (*to_wait) (struct target_ops *, - ptid_t, struct target_waitstatus *, int); + ptid_t, struct target_waitstatus *, int) + TARGET_DEFAULT (noprocess ()); void (*to_fetch_registers) (struct target_ops *, struct regcache *, int); - void (*to_store_registers) (struct target_ops *, struct regcache *, int); + void (*to_store_registers) (struct target_ops *, struct regcache *, int) + TARGET_DEFAULT (noprocess ()); void (*to_prepare_to_store) (struct regcache *); /* Transfer LEN bytes of memory between GDB address MYADDR and @@ -402,9 +417,11 @@ struct target_ops void (*to_files_info) (struct target_ops *); int (*to_insert_breakpoint) (struct target_ops *, struct gdbarch *, - struct bp_target_info *); + struct bp_target_info *) + TARGET_DEFAULT (memory_insert_breakpoint); int (*to_remove_breakpoint) (struct target_ops *, struct gdbarch *, - struct bp_target_info *); + struct bp_target_info *) + TARGET_DEFAULT (memory_remove_breakpoint); int (*to_can_use_hw_breakpoint) (int, int, int); int (*to_ranged_break_num_registers) (struct target_ops *); int (*to_insert_hw_breakpoint) (struct gdbarch *, struct bp_target_info *); @@ -419,10 +436,12 @@ struct target_ops CORE_ADDR, CORE_ADDR, int); int (*to_remove_mask_watchpoint) (struct target_ops *, CORE_ADDR, CORE_ADDR, int); - int (*to_stopped_by_watchpoint) (struct target_ops *); + int (*to_stopped_by_watchpoint) (struct target_ops *) + TARGET_DEFAULT (0); int to_have_steppable_watchpoint; int to_have_continuable_watchpoint; - int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *); + int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *) + TARGET_DEFAULT (0); int (*to_watchpoint_addr_within_range) (struct target_ops *, CORE_ADDR, CORE_ADDR, int); @@ -484,9 +503,12 @@ struct target_ops int to_has_thread_control; /* control thread execution */ int to_attach_no_wait; /* ASYNC target controls */ - int (*to_can_async_p) (struct target_ops *); - int (*to_is_async_p) (struct target_ops *); - void (*to_async) (struct target_ops *, async_callback_ftype *, void *); + int (*to_can_async_p) (struct target_ops *) + TARGET_DEFAULT (find_default_can_async_p); + int (*to_is_async_p) (struct target_ops *) + TARGET_DEFAULT (find_default_is_async_p); + void (*to_async) (struct target_ops *, async_callback_ftype *, void *) + TARGET_DEFAULT (tcomplain ()); int (*to_supports_non_stop) (void); /* find_memory_regions support method for gcore */ int (*to_find_memory_regions) (find_memory_region_ftype func, void *data); @@ -537,7 +559,8 @@ struct target_ops LONGEST (*to_xfer_partial) (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len); + ULONGEST offset, LONGEST len) + TARGET_DEFAULT (-1); /* Returns the memory map for the target. A return value of NULL means that no memory map is available. If a memory address @@ -817,7 +840,8 @@ struct target_ops int (*to_can_use_agent) (void); /* Check whether the target supports branch tracing. */ - int (*to_supports_btrace) (struct target_ops *); + int (*to_supports_btrace) (struct target_ops *) + TARGET_DEFAULT (0); /* Enable branch tracing for PTID and allocate a branch trace target information struct for reading and for disabling branch trace. */ -- 1.8.1.4 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0009-update-to_attach.patch Content-Description: patch #4 Content-length: 3281 >From 35f46ca676e8e766fe7e384a7d1be89842a713bd Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 13 Dec 2013 14:16:57 -0700 Subject: [PATCH 09/11] update to_attach --- gdb/target-delegates.c | 10 ++++++++++ gdb/target.c | 21 ++++----------------- gdb/target.h | 3 ++- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index 84429a4..0847d09 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -4,6 +4,13 @@ /* To regenerate this file, run:*/ /* make-target-delegates target.h > target-delegates.c */ static void +delegate_attach (struct target_ops *self, char *arg1, int arg2) +{ + self = self->beneath; + self->to_attach (self, arg1, arg2); +} + +static void delegate_detach (struct target_ops *self, const char *arg1, int arg2) { self = self->beneath; @@ -151,6 +158,8 @@ tdefault_supports_btrace (struct target_ops *self) static void install_delegators (struct target_ops *ops) { + if (ops->to_attach == NULL) + ops->to_attach = delegate_attach; if (ops->to_detach == NULL) ops->to_detach = delegate_detach; if (ops->to_resume == NULL) @@ -182,6 +191,7 @@ install_delegators (struct target_ops *ops) static void install_dummy_methods (struct target_ops *ops) { + ops->to_attach = find_default_attach; ops->to_detach = tdefault_detach; ops->to_resume = tdefault_resume; ops->to_wait = tdefault_wait; diff --git a/gdb/target.c b/gdb/target.c index b6d8c85..a5c5505 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -3708,7 +3708,6 @@ init_dummy_target (void) dummy_target.to_shortname = "None"; dummy_target.to_longname = "None"; dummy_target.to_doc = ""; - dummy_target.to_attach = find_default_attach; dummy_target.to_create_inferior = find_default_create_inferior; dummy_target.to_supports_non_stop = find_default_supports_non_stop; dummy_target.to_supports_disable_randomization @@ -3755,22 +3754,10 @@ target_close (struct target_ops *targ) void target_attach (char *args, int from_tty) { - struct target_ops *t; - - for (t = current_target.beneath; t != NULL; t = t->beneath) - { - if (t->to_attach != NULL) - { - t->to_attach (t, args, from_tty); - if (targetdebug) - fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", - args, from_tty); - return; - } - } - - internal_error (__FILE__, __LINE__, - _("could not find a target to attach")); + current_target.to_attach (¤t_target, args, from_tty); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_attach (%s, %d)\n", + args, from_tty); } int diff --git a/gdb/target.h b/gdb/target.h index 20bb33a..fc53f56 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -374,7 +374,8 @@ struct target_ops to xfree everything (including the "struct target_ops"). */ void (*to_xclose) (struct target_ops *targ); void (*to_close) (void); - void (*to_attach) (struct target_ops *ops, char *, int); + void (*to_attach) (struct target_ops *ops, char *, int) + TARGET_DEFAULT (find_default_attach); void (*to_post_attach) (int); void (*to_detach) (struct target_ops *ops, const char *, int) TARGET_DEFAULT (target_ignore ()); -- 1.8.1.4 --=-=-=--