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