diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 242 | ||||
-rw-r--r-- | gdb/Makefile.in | 31 | ||||
-rw-r--r-- | gdb/ax-gdb.c | 37 | ||||
-rw-r--r-- | gdb/breakpoint.c | 18 | ||||
-rw-r--r-- | gdb/command.h | 17 | ||||
-rw-r--r-- | gdb/complaints.c | 18 | ||||
-rw-r--r-- | gdb/defs.h | 26 | ||||
-rw-r--r-- | gdb/elfread.c | 2 | ||||
-rw-r--r-- | gdb/event-loop.c | 139 | ||||
-rw-r--r-- | gdb/event-loop.h | 14 | ||||
-rw-r--r-- | gdb/event-top.c | 70 | ||||
-rw-r--r-- | gdb/event-top.h | 2 | ||||
-rw-r--r-- | gdb/hppa-tdep.c | 45 | ||||
-rw-r--r-- | gdb/infcmd.c | 55 | ||||
-rw-r--r-- | gdb/infrun.c | 87 | ||||
-rw-r--r-- | gdb/irix5-nat.c | 33 | ||||
-rw-r--r-- | gdb/m32r-stub.c | 2 | ||||
-rw-r--r-- | gdb/main.c | 6 | ||||
-rw-r--r-- | gdb/osfsolib.c | 34 | ||||
-rw-r--r-- | gdb/pa64solib.c | 45 | ||||
-rw-r--r-- | gdb/procfs.c | 24 | ||||
-rw-r--r-- | gdb/remote.c | 218 | ||||
-rw-r--r-- | gdb/remote.h | 5 | ||||
-rw-r--r-- | gdb/rs6000-nat.c | 23 | ||||
-rw-r--r-- | gdb/solib.c | 35 | ||||
-rw-r--r-- | gdb/somsolib.c | 44 | ||||
-rw-r--r-- | gdb/target.c | 57 | ||||
-rw-r--r-- | gdb/target.h | 19 | ||||
-rw-r--r-- | gdb/top.c | 34 | ||||
-rw-r--r-- | gdb/tracepoint.c | 2 | ||||
-rw-r--r-- | gdb/utils.c | 26 |
31 files changed, 863 insertions, 547 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 278bdf0..0802506 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,245 @@ +Tue Sep 28 11:08:34 1999 Jeffrey A Law (law@cygnus.com) + + * hppa-tdep.c (hppa_fix_call_dummy): Ignore IMPORT_SHLIB stubs + except for hpux11 native. Break out of the loop to find a + stub as soon as we find an IMPORT stub. + (skip_prologue_hard_way): Also recognize copy %ret1,target and + all PA64 argument stores as prologue instructions. + +1999-09-28 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * breakpoint.c, defs.h, event-top.c, infcmd.c, infrun.c, main.c, + remote.c, top.c, tracepoint.c, utils.c (async_p): Change var name + to event_loop_p. + +1999-09-28 Jim Blandy <jimb@cris.red-bean.com> + + * hppa-tdep.c (skip_prologue_hard_way): Recognize ldo insns + which generate pointers into the argument list. + +Tue Sep 28 13:56:49 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.h (cleanup_sigint_signal_handler, + initialize_sigint_signal_handler): Delete extern declarations. + * event-top.c, infrun.c: No longer need to include "remote.h". + * remote.c (cleanup_sigint_signal_handler, + initialize_sigint_signal_handler): Make static. + * Makefile.in (event-top.o): Delete dependency on "remote.h". + + * remote.c (remote_async_terminal_ours_p): New static global. Keep + track of who currently owns the terminal. + (remote_async_open_1): Initialize. + (remote_async_terminal_inferior): Test + remote_async_terminal_ours_p. Claim CNTRL-C handler as part of + transfering the terminal to the target. + (remote_async_terminal_ours): Similar. + +Mon Sep 27 12:33:45 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.c (async_interrupt_query): Delete function. Merged into + interrupt_query. Async cases handled by target_terminal_ours, + target_terminal_inferior and SERIAL_CLOSE. + (async_remote_interrupt_twice): Update. + (remote_async_terminal_ours, remote_async_terminal_inferior): New + functions. Steal STDIN from GDB's CLI. + (init_remote_async_ops): Initialize to_terminal_ours and + to_terminal_inferior. + + * event-top.c (async_disable_stdin, async_disable_stdin): Use + target_terminal_ours / target_terminal_inferior to transfer + ownership of the terminal between GDB and the target. + +1999-09-27 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * infcmd.c (run_command): Call async_disable_stdin() only if + dealing with an asynchronous target. + +Mon Sep 27 11:48:38 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * target.h (struct target_ops): Add to_can_async_p, to_is_async_p, + to_async. Delete to_has_async. These correspond well with + SERIAL* async methods. + (target_can_async_p, target_is_async_p, target_async): Define. + * target.c (update_current_target, cleanup_target): Update. + + * remote.c (remote_async_open_1): Change target to async using + target_async. + (remote_can_async_p, remote_is_async_p, remote_async): New + functions. + (remote_async_wait, remote_async_open_1): Add FIXME about how + wait_forever_enabled_p can almost be deleted once the client can + enable/disable target_async. + + * breakpoint.c (until_break_command), infrun.c (proceed), infcmd.c + (run_command, continue_command, step_1, jump_command, + until_command, finish_command, interrupt_target_command), top.c + (return_to_top_level, execute_command), event-top.c + (command_handler): Replace target_has_async with + target_can_async_p. + +Sun Sep 26 02:10:47 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.c (remote_async_open_1): If we go into async mode, never + wait for ever. + + * infcmd.c: Include "event-top.h". + (run_command, continue_command, jump_command, until_command, + finish_command): Use async_disable_stdin to disable the console + for synchronous commands. + + * remote.c (async_interrupt_query): Only disconnect the console + from the terminal when sync_execution. + + * remote.c (initialize_sigint_signal_handler): Move declaration + from here. + * remote.h: To here. Make non-static. + + * remote.c (remote_async_resume, async_interrupt_query): Move + prompt code from here. + * event-top.c (async_disable_stdin, async_enable_stdin): To + here. New function. + + * infrun.c (start_remote): Delete commented out code. + +Fri Sep 24 12:38:31 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.c (remote_async_open_1): Perform the initial async_open + using only synchronous calls. Only after the target is fully + connected, switch to async mode. Include FIXME about now it + currently works VS how it should be working. + (remote_async_open_1, set_extended_protocol): Delete function + set_extended_protocol. All open communication is now done + synchronously. + (forever_enabled_p): New variable. Determine if remote_async_wait + should block FOREVER when fetching target information. + (remote_cisco_open, remote_open_1): Set forever_enabled_p. + + * infrun.c (start_remote): During the initial connect, always use + a synchronous wait. + +Sat Sep 25 18:13:38 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (event-top.o): Add dependency. + * event-top.c: Include "remote.h". + * remote.c (async_interrupt_query), event-top.c: + (async_enable_stdin): Pass dummy parameter to + cleanup_sigint_signal_handler. + * remote.c (cleanup_sigint_signal_handler), remote.h + (cleanup_sigint_signal_handler), event-top.c (async_enable_stdin), + event-top.h (async_enable_stdin): Change signature to match + make_exec_error_cleanup handler pararameter. + +Thu Sep 23 20:48:22 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * defs.h (enum command_class): Move from here. + * command.h (command_class): To here. + +1999-09-24 Kevin Buettner <kevinb@cygnus.com> + * breakpoint.c (bpstat_stop_status): Use not_a_breakpoint to + help properly set bp_addr. + * infrun.c (handle_inferior_event): Simplify calls to + bp_stop_status. + +1999-09-24 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * top.c (return_to_top_level): Do exec_error cleanups if are + interrupting a simulated synchronous execution command. + + * infrun.c (start_remote): Create a cleanup to enable stdin in + case of error from this command. + (complete_execution): Do the enabling of stdin via the exec_error + cleanups, when needed. + + * remote.c (remote_async_resume): Make sure we re-enable stdin in + case of error from the target. + (handle_remote_sigint_twice): The handler to be set is + async_remote_interrupt_twice, not async_remote_interrupt. + (async_remote_interrupt_twice): Don't do anything if the target + has been killed already. Call async_interrupt_query, instead of + interrupt_query. + (async_interrupt_query): New function. Async case of + interrupt_query(). + + * event-top.c (async_enable_stdin): New function. Reinstate stdin + with the event loop. + * event-top.h (async_enable_stdin): Export. + + * utils.c (exec_error_cleanup_chain): New cleanup chain. + (make_exec_error_cleanup, do_exec_error_cleanups, + discard_exec_error_cleanups): New functions. + * defs.h (make_exec_error_cleanup, do_exec_error_cleanups, + discard_exec_error_cleanups): Export. + +1999-09-24 Jim Blandy <jimb@zwingli.cygnus.com> + + * ax-gdb.c (expr_to_agent): Don't forget to pass argument to + new_agent_expr. + +1999-09-24 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-loop.c (fetch_inferior_event_wrapper): New + function. Wrapper to pass to catch_errors. + (inferior_event_handler): Pop the target if things go bad with it. + Call fetch_inferior_event() from within catch_errors(). + +1999-09-24 Jim Blandy <jimb@zwingli.cygnus.com> + + * ax-gdb.c: Use internal_error instead of error, where + appropriate. + +1999-09-23 James Ingham <jingham@leda.cygnus.com> + + * target.c (target_resize_to_sections): New function. Gather the + resizing code for the to_sections field into one place, and make + sure you update the other targets that are sharing the to_sections + structure. + * target.h: Declare the target_resize_to_sections function. + * solib.c (solib_add): use target_resize_to_sections. + * somsolib.c (som_solib_load_symbols): ditto + * rs6000-nat.c (xcoff_relocate_core): ditto + * pa64solib.c (pa64_solib_load_symbols): ditto + * irix5-nat.c (solib_add):ditto + + * top.c: Define the attach & detach hooks + * defs.h: Declare the attach & detach hooks. + * infcmd.c (attach_command): call the attach hook if it exists. + (detach_command): call the detach hook if it exists. + + * complaints.c (complain): Send the complaints to stderr rather + than stdout, so they don't get mixed into the result stream from + commands. + +1999-09-23 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-loop.c (poll_timers): Use correct timeval field names, + when setting the notifier timeouts, in case of select() used. + (gdb_wait_for_event): Pass a pointer to the timeout structure to + select(), not the structure. + +Wed Sep 22 10:35:32 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (init.c): Change generated file to include "defs.h" + and "call-cmds.h". Use initialize_file_ftype when declaring + each initialize functions. + (call_cmds_h): Add definition. + (init.o): Add target and dependencies. + (init.c): Don't grep for _initialize* in init.c. + + * defs.h (initialize_file_ftype): Add function typedef. + +1999-09-22 Michael Snyder <msnyder@cleaver.cygnus.com> + + * procfs.c (init_procinfo): move fltset initialization to caller. + (do_attach, create_procinfo): initialize fltset. + +1999-09-22 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-loop.c, event-top.c, event-loop.h: Rerun indent. + +1999-09-21 Doug Evans <devans@casey.cygnus.com> + + * m32r-stub.c (handle_exception): Fix typo in patch of 1999-08-26. + Tue Sep 21 14:55:29 1999 Andrew Cagney <cagney@b1.cygnus.com> From 1999-08-20 J.T. Conklin <jtc@redback.com>: diff --git a/gdb/Makefile.in b/gdb/Makefile.in index a83add6..913939f 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -229,7 +229,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \ ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) -VERSION = 19990921 +VERSION = 19990928 DIST=gdb LINT=/usr/5bin/lint @@ -448,6 +448,7 @@ breakpoint_h = breakpoint.h $(frame_h) $(value_h) command_h = command.h gdbcmd_h = gdbcmd.h $(command_h) +call_cmds_h = call-cmds.h defs_h = defs.h xm.h tm.h nm.h config.status config.h gdbarch.h top_h = top.h @@ -622,15 +623,11 @@ uninstall: force init.c: $(OBS) $(TSOBS) @echo Making init.c - @rm -f init.c-tmp - @echo '/* Do not modify this file. */' >init.c-tmp - @echo '/* It is created automatically by the Makefile. */'>>init.c-tmp - @echo '#include "ansidecl.h"' >>init.c-tmp - @echo 'extern void initialize_all_files PARAMS ((void));' >>init.c-tmp - @echo 'void initialize_all_files PARAMS ((void)) {' >>init.c-tmp + @rm -f init.c-tmp init.l-tmp @-echo $(OBS) $(TSOBS) | \ tr ' ' '\012' | \ sed -e '/^Onindy.o/d' \ + -e '/^init.o/d' \ -e '/^nindy.o/d' \ -e '/ttyflush.o/d' \ -e '/xdr_ld.o/d' \ @@ -645,12 +642,24 @@ init.c: $(OBS) $(TSOBS) -e 's/\.o/.c/' \ -e 's|\([^ ][^ ]*\)|$(srcdir)/\1|g' | \ while read f; do grep '^_initialize_[a-z_0-9A-Z]* *(' $$f 2>/dev/null; done | \ - sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 PARAMS ((void)); \1 ();}/' >>init.c-tmp + sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/\1/' > init.l-tmp + @echo '/* Do not modify this file. */' >>init.c-tmp + @echo '/* It is created automatically by the Makefile. */'>>init.c-tmp + @echo '#include "defs.h"' >>init.c-tmp + @echo '#include "call-cmds.h"' >>init.c-tmp + @sed -e 's/\(.*\)/extern initialize_file_ftype \1;/' <init.l-tmp >>init.c-tmp + @echo 'void' >>init.c-tmp + @echo 'initialize_all_files (void)' >>init.c-tmp + @echo '{' >>init.c-tmp + @sed -e 's/\(.*\)/ \1 ();/' <init.l-tmp >>init.c-tmp @echo '}' >>init.c-tmp + @rm init.l-tmp @mv init.c-tmp init.c .PRECIOUS: init.c +init.o: init.c $(defs_h) $(call_cmds_h) + # Removing the old gdb first works better if it is running, at least on SunOS. gdb$(EXEEXT): main.o libgdb.a $(ADD_DEPS) $(CDEPS) $(TDEPLIBS) rm -f gdb$(EXEEXT) @@ -755,7 +764,7 @@ tags: TAGS clean mostlyclean: @$(MAKE) $(FLAGS_TO_PASS) DO=clean "DODIRS=$(SUBDIRS)" subdir_do - rm -f *.o *.a $(ADD_FILES) *~ init.c-tmp + rm -f *.o *.a $(ADD_FILES) *~ init.c-tmp init.l-tmp rm -f init.c version.c rm -f gdb$(EXEEXT) core make.log rm -f gdb[0-9]$(EXEEXT) @@ -1127,7 +1136,8 @@ eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \ event-loop.o: event-loop.c $(defs_h) $(top_h) $(event_loop_h) $(event_top_h) event-top.o: event-top.c top.h $(readline_headers) \ - $(defs_h) $(inferior_h) $(event_loop_h) $(event_top_h) terminal.h $(gdbcmd_h) + $(defs_h) $(inferior_h) $(event_loop_h) $(event_top_h) terminal.h \ + $(gdbcmd_h) exec.o: exec.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \ target.h language.h gdb_string.h @@ -1699,5 +1709,4 @@ m2-exp.tab.o: m2-exp.tab.c $(defs_h) $(expression_h) $(gdbtypes_h) \ gdb-events.o: gdb-events.c gdb-events.h $(defs_h) $(gdbcmd_h) - ### end of the gdb Makefile.in. diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 8b3d133..218dd6e 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -31,10 +31,11 @@ #include "ax.h" #include "ax-gdb.h" -/* Probably the best way to read this file is to start with the types - and enums in ax-gdb.h, and then look at gen_expr, towards the - bottom; that's the main function that looks at the GDB expressions - and calls everything else to generate code. +/* To make sense of this file, you should read doc/agentexpr.texi. + Then look at the types and enums in ax-gdb.h. For the code itself, + look at gen_expr, towards the bottom; that's the main function that + looks at the GDB expressions and calls everything else to generate + code. I'm beginning to wonder whether it wouldn't be nicer to internally generate trees, with types, and then spit out the bytecode in @@ -439,7 +440,7 @@ gen_fetch (ax, type) implementing something we should be (this code's fault). In any case, it's a bug the user shouldn't see. */ default: - error ("GDB bug: ax-gdb.c (gen_fetch): strange size"); + internal_error ("ax-gdb.c (gen_fetch): strange size"); } gen_sign_extend (ax, type); @@ -450,7 +451,7 @@ gen_fetch (ax, type) pointer (other code's fault), or we're not implementing something we should be (this code's fault). In any case, it's a bug the user shouldn't see. */ - error ("GDB bug: ax-gdb.c (gen_fetch): bad type code"); + internal_error ("ax-gdb.c (gen_fetch): bad type code"); } } @@ -571,7 +572,7 @@ gen_var_ref (ax, value, var) break; case LOC_CONST_BYTES: - error ("GDB bug: ax-gdb.c (gen_var_ref): LOC_CONST_BYTES symbols are not supported"); + internal_error ("ax-gdb.c (gen_var_ref): LOC_CONST_BYTES symbols are not supported"); /* Variable at a fixed location in memory. Easy. */ case LOC_STATIC: @@ -1162,7 +1163,7 @@ gen_deref (ax, value) /* The caller should check the type, because several operators use this, and we don't know what error message to generate. */ if (value->type->code != TYPE_CODE_PTR) - error ("GDB bug: ax-gdb.c (gen_deref): expected a pointer"); + internal_error ("ax-gdb.c (gen_deref): expected a pointer"); /* We've got an rvalue now, which is a pointer. We want to yield an lvalue, whose address is exactly that pointer. So we don't @@ -1221,7 +1222,7 @@ find_field (type, name) /* Make sure this isn't C++. */ if (TYPE_N_BASECLASSES (type) != 0) - error ("GDB bug: ax-gdb.c (find_field): derived classes supported"); + internal_error ("ax-gdb.c (find_field): derived classes supported"); for (i = 0; i < TYPE_NFIELDS (type); i++) { @@ -1231,7 +1232,7 @@ find_field (type, name) return i; if (this_name[0] == '\0') - error ("GDB bug: ax-gdb.c (find_field): anonymous unions not supported"); + internal_error ("ax-gdb.c (find_field): anonymous unions not supported"); } error ("Couldn't find member named `%s' in struct/union `%s'", @@ -1306,7 +1307,7 @@ gen_bitfield_ref (ax, value, type, start, end) /* Can we fetch the number of bits requested at all? */ if ((end - start) > ((1 << num_ops) * 8)) - error ("GDB bug: ax-gdb.c (gen_bitfield_ref): bitfield too wide"); + internal_error ("ax-gdb.c (gen_bitfield_ref): bitfield too wide"); /* Note that we know here that we only need to try each opcode once. That may not be true on machines with weird byte sizes. */ @@ -1626,7 +1627,7 @@ gen_expr (pc, ax, value) default: /* We should only list operators in the outer case statement that we actually handle in the inner case statement. */ - error ("GDB bug: ax-gdb.c (gen_expr): op case sets don't match"); + internal_error ("ax-gdb.c (gen_expr): op case sets don't match"); } break; @@ -1701,7 +1702,7 @@ gen_expr (pc, ax, value) the given type, and dereference it. */ if (value->kind != axs_rvalue) /* This would be weird. */ - error ("GDB bug: ax-gdb.c (gen_expr): OP_MEMVAL operand isn't an rvalue???"); + internal_error ("ax-gdb.c (gen_expr): OP_MEMVAL operand isn't an rvalue???"); value->type = type; value->kind = axs_lvalue_memory; } @@ -1769,7 +1770,7 @@ gen_expr (pc, ax, value) else /* If this `if' chain doesn't handle it, then the case list shouldn't mention it, and we shouldn't be here. */ - error ("GDB bug: ax-gdb.c (gen_expr): unhandled struct case"); + internal_error ("ax-gdb.c (gen_expr): unhandled struct case"); } break; @@ -1783,7 +1784,6 @@ gen_expr (pc, ax, value) -#if 0 /* not used */ /* Generating bytecode from GDB expressions: driver */ /* Given a GDB expression EXPR, produce a string of agent bytecode @@ -1795,7 +1795,7 @@ expr_to_agent (expr, value) struct axs_value *value; { struct cleanup *old_chain = 0; - struct agent_expr *ax = new_agent_expr (); + struct agent_expr *ax = new_agent_expr (0); union exp_element *pc; old_chain = make_cleanup ((make_cleanup_func) free_agent_expr, ax); @@ -1812,6 +1812,7 @@ expr_to_agent (expr, value) } +#if 0 /* not used */ /* Given a GDB expression EXPR denoting an lvalue in memory, produce a string of agent bytecode which will leave its address and size on the top of stack. Return the agent expression. @@ -1836,7 +1837,7 @@ expr_to_address_and_size (expr) return ax; } -#endif /* 0 */ +#endif /* Given a GDB expression EXPR, return bytecode to trace its value. The result will use the `trace' and `trace_quick' bytecodes to @@ -1909,7 +1910,7 @@ agent_command (exp, from_tty) struct cleanup *old_chain = 0; struct expression *expr; struct agent_expr *agent; - struct frame_info *fi = get_current_frame (); /* need current scope */ + struct frame_info *fi = get_current_frame (); /* need current scope */ /* We don't deal with overlay debugging at the moment. We need to think more carefully about this. If you copy this code into diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index bccdeee..a6a5f4f 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2155,7 +2155,8 @@ bpstat_stop_status (pc, not_a_breakpoint) char message[sizeof (message1) + 30 /* slop */ ]; /* Get the address where the breakpoint would have been. */ - bp_addr = *pc - DECR_PC_AFTER_BREAK; + bp_addr = *pc - (not_a_breakpoint && !SOFTWARE_SINGLE_STEP_P ? + 0 : DECR_PC_AFTER_BREAK); ALL_BREAKPOINTS_SAFE (b, temp) { @@ -2184,13 +2185,6 @@ bpstat_stop_status (pc, not_a_breakpoint) && b->address != (*pc - DECR_PC_AFTER_HW_BREAK)) continue; - if (b->type != bp_watchpoint - && b->type != bp_hardware_watchpoint - && b->type != bp_read_watchpoint - && b->type != bp_access_watchpoint - && not_a_breakpoint) - continue; - /* Is this a catchpoint of a load or unload? If so, did we get a load or unload of the specified library? If not, ignore it. */ @@ -4757,7 +4751,7 @@ until_break_command (arg, from_tty) breakpoint = set_momentary_breakpoint (sal, selected_frame, bp_until); - if (!async_p || !target_has_async) + if (!event_loop_p || !target_can_async_p ()) old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); else @@ -4770,7 +4764,7 @@ until_break_command (arg, from_tty) where we get a chance to do that is in fetch_inferior_event, so we must set things up for that. */ - if (async_p && target_has_async) + if (event_loop_p && target_can_async_p ()) { /* In this case we don't need args for the continuation, because all it needs to do is do the cleanups in the @@ -4786,7 +4780,7 @@ until_break_command (arg, from_tty) sal = find_pc_line (prev_frame->pc, 0); sal.pc = prev_frame->pc; breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until); - if (!async_p || !target_has_async) + if (!event_loop_p || !target_can_async_p ()) make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); else make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); @@ -4795,7 +4789,7 @@ until_break_command (arg, from_tty) proceed (-1, TARGET_SIGNAL_DEFAULT, 0); /* Do the cleanups now, anly if we are not running asynchronously, of if we are, but the target is still synchronous. */ - if (!async_p || !target_has_async) + if (!event_loop_p || !target_can_async_p ()) do_cleanups (old_chain); } diff --git a/gdb/command.h b/gdb/command.h index c7b8e5e..29484a5 100644 --- a/gdb/command.h +++ b/gdb/command.h @@ -19,6 +19,23 @@ #if !defined (COMMAND_H) #define COMMAND_H 1 +/* Command classes are top-level categories into which commands are broken + down for "help" purposes. + Notes on classes: class_alias is for alias commands which are not + abbreviations of the original command. class-pseudo is for + commands which are not really commands nor help topics ("stop"). */ + +enum command_class +{ + /* Special args to help_list */ + class_deprecated, all_classes = -2, all_commands = -1, + /* Classes of commands */ + no_class = -1, class_run = 0, class_vars, class_stack, + class_files, class_support, class_info, class_breakpoint, class_trace, + class_alias, class_obscure, class_user, class_maintenance, + class_pseudo, class_tui, class_xdb, +}; + /* Not a set/show command. Note that some commands which begin with "set" or "show" might be in this category, if their syntax does not fall into one of the following categories. */ diff --git a/gdb/complaints.c b/gdb/complaints.c index 5903a4e..c22d213 100644 --- a/gdb/complaints.c +++ b/gdb/complaints.c @@ -84,18 +84,18 @@ complain (struct complaint *complaint,...) /* Isolated messages, must be self-explanatory. */ case 0: begin_line (); - puts_filtered ("During symbol reading, "); + fputs_filtered ("During symbol reading, ", gdb_stderr); wrap_here (""); - vprintf_filtered (complaint->message, args); - puts_filtered (".\n"); + vfprintf_filtered (gdb_stderr, complaint->message, args); + fputs_filtered (".\n", gdb_stderr); break; /* First of a series, without `set verbose'. */ case 1: begin_line (); - puts_filtered ("During symbol reading..."); - vprintf_filtered (complaint->message, args); - puts_filtered ("..."); + fputs_filtered ("During symbol reading...", gdb_stderr); + vfprintf_filtered (gdb_stderr, complaint->message, args); + fputs_filtered ("...", gdb_stderr); wrap_here (""); complaint_series++; break; @@ -104,14 +104,14 @@ complain (struct complaint *complaint,...) (We'll already have produced a "Reading in symbols for XXX..." message and will clean up at the end with a newline.) */ default: - vprintf_filtered (complaint->message, args); - puts_filtered ("..."); + vfprintf_filtered (gdb_stderr, complaint->message, args); + fputs_filtered ("...", gdb_stderr); wrap_here (""); } /* If GDB dumps core, we'd like to see the complaints first. Presumably GDB will not be sending so many complaints that this becomes a performance hog. */ - gdb_flush (gdb_stdout); + gdb_flush (gdb_stderr); va_end (args); } @@ -165,23 +165,6 @@ extern void quit PARAMS ((void)); } #endif -/* Command classes are top-level categories into which commands are broken - down for "help" purposes. - Notes on classes: class_alias is for alias commands which are not - abbreviations of the original command. class-pseudo is for commands - which are not really commands nor help topics ("stop"). */ - -enum command_class -{ - /* Special args to help_list */ - all_classes = -2, all_commands = -1, - /* Classes of commands */ - no_class = -1, class_run = 0, class_vars, class_stack, - class_files, class_support, class_info, class_breakpoint, class_trace, - class_alias, class_obscure, class_user, class_maintenance, - class_pseudo, class_tui, class_xdb -}; - /* Languages represented in the symbol table and elsewhere. This should probably be in language.h, but since enum's can't be forward declared to satisfy opaque references before their @@ -303,9 +286,11 @@ extern void do_final_cleanups PARAMS ((struct cleanup *)); extern void do_my_cleanups PARAMS ((struct cleanup **, struct cleanup *)); extern void do_run_cleanups PARAMS ((struct cleanup *)); extern void do_exec_cleanups PARAMS ((struct cleanup *)); +extern void do_exec_error_cleanups PARAMS ((struct cleanup *)); extern void discard_cleanups PARAMS ((struct cleanup *)); extern void discard_final_cleanups PARAMS ((struct cleanup *)); +extern void discard_exec_error_cleanups PARAMS ((struct cleanup *)); extern void discard_my_cleanups PARAMS ((struct cleanup **, struct cleanup *)); typedef void (*make_cleanup_func) PARAMS ((void *)); @@ -322,6 +307,7 @@ extern struct cleanup *make_my_cleanup PARAMS ((struct cleanup **, extern struct cleanup *make_run_cleanup PARAMS ((make_cleanup_func, void *)); extern struct cleanup *make_exec_cleanup PARAMS ((make_cleanup_func, void *)); +extern struct cleanup *make_exec_error_cleanup PARAMS ((make_cleanup_func, void *)); extern struct cleanup *save_cleanups PARAMS ((void)); extern struct cleanup *save_final_cleanups PARAMS ((void)); @@ -552,6 +538,8 @@ extern void symbol_file_command PARAMS ((char *, int)); /* From top.c */ +typedef void initialize_file_ftype (void); + extern char *skip_quoted PARAMS ((char *)); extern char *gdb_readline PARAMS ((char *)); @@ -1146,7 +1134,7 @@ struct cmd_list_element; /* Should the asynchronous variant of the interpreter (using the event-loop) be enabled? */ -extern int async_p; +extern int event_loop_p; extern void (*init_ui_hook) PARAMS ((char *argv0)); extern void (*command_loop_hook) PARAMS ((void)); @@ -1173,6 +1161,8 @@ extern void (*context_hook) PARAMS ((int)); extern int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status)); +extern void (*attach_hook) PARAMS ((void)); +extern void (*detach_hook) PARAMS ((void)); extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd, int from_tty)); diff --git a/gdb/elfread.c b/gdb/elfread.c index e33ed82..afb043d 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -36,7 +36,7 @@ extern void _initialize_elfread PARAMS ((void)); /* The struct elfinfo is available only during ELF symbol table and - psymtab reading. It is destroyed at the complation of psymtab-reading. + psymtab reading. It is destroyed at the completion of psymtab-reading. It's local to elf_symfile_read. */ struct elfinfo diff --git a/gdb/event-loop.c b/gdb/event-loop.c index 8815e04..8668fcc 100644 --- a/gdb/event-loop.c +++ b/gdb/event-loop.c @@ -23,7 +23,7 @@ #include "top.h" #include "event-loop.h" #include "event-top.h" -#include "inferior.h" /* For fetch_inferior_event. */ +#include "inferior.h" /* For fetch_inferior_event. */ #ifdef HAVE_POLL #include <poll.h> #else @@ -103,9 +103,9 @@ typedef struct file_handler int mask; /* Events we want to monitor: POLLIN, etc. */ int ready_mask; /* Events that have been seen since the last time. */ - handler_func *proc; /* Procedure to call when fd is ready. */ + handler_func *proc; /* Procedure to call when fd is ready. */ gdb_client_data client_data; /* Argument to pass to proc. */ - int error; /* Was an error detected on this fd? */ + int error; /* Was an error detected on this fd? */ struct file_handler *next_file; /* Next registered file descriptor. */ } file_handler; @@ -123,7 +123,7 @@ typedef struct async_signal_handler int ready; /* If ready, call this handler from the main event loop, using invoke_async_handler. */ struct async_signal_handler *next_handler; /* Ptr to next handler */ - sig_handler_func *proc; /* Function to call to do the work */ + sig_handler_func *proc; /* Function to call to do the work */ gdb_client_data client_data; /* Argument to async_handler_func */ } async_signal_handler; @@ -206,7 +206,7 @@ static struct /* Flag to tell whether the timeout struct should be used. */ int timeout_valid; - } + } gdb_notifier; #endif /* HAVE_POLL */ @@ -218,13 +218,13 @@ struct gdb_timer struct timeval when; int timer_id; struct gdb_timer *next; - timer_handler_func *proc; /* Function to call to do the work */ - gdb_client_data client_data; /* Argument to async_handler_func */ + timer_handler_func *proc; /* Function to call to do the work */ + gdb_client_data client_data; /* Argument to async_handler_func */ } gdb_timer; /* List of currently active timers. It is sorted in order of - increasing timers.*/ + increasing timers. */ static struct { /* Pointer to first in timer list. */ @@ -253,17 +253,18 @@ sighandler_list; function. */ static int async_handler_ready = 0; -static void create_file_handler (int fd, int mask, handler_func *proc, gdb_client_data client_data); +static void create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data); static void invoke_async_signal_handler (void); static void handle_file_event (int event_file_desc); static int gdb_wait_for_event (void); static int gdb_do_one_event (void); static int check_async_ready (void); -static void async_queue_event (gdb_event *event_ptr, queue_position position); -static gdb_event * create_file_event (int fd); +static void async_queue_event (gdb_event * event_ptr, queue_position position); +static gdb_event *create_file_event (int fd); static int process_event (void); static void handle_timer_event (int dummy); static void poll_timers (void); +static int fetch_inferior_event_wrapper (gdb_client_data client_data); /* Insert an event object into the gdb event queue at @@ -277,7 +278,7 @@ static void poll_timers (void); as last in first out. Event appended at the tail of the queue will be processed first in first out. */ static void -async_queue_event (gdb_event *event_ptr, queue_position position) +async_queue_event (gdb_event * event_ptr, queue_position position) { if (position == TAIL) { @@ -407,7 +408,7 @@ gdb_do_one_event (void) break; } - /* Are any timers that are ready? If so, put an event on the queue.*/ + /* Are any timers that are ready? If so, put an event on the queue. */ poll_timers (); /* Wait for a new event. If gdb_wait_for_event returns -1, @@ -470,7 +471,7 @@ start_event_loop (void) doesn't have to know implementation details about the use of poll vs. select. */ void -add_file_handler (int fd, handler_func *proc, gdb_client_data client_data) +add_file_handler (int fd, handler_func * proc, gdb_client_data client_data) { #ifdef HAVE_POLL create_file_handler (fd, POLLIN, proc, client_data); @@ -490,7 +491,7 @@ add_file_handler (int fd, handler_func *proc, gdb_client_data client_data) PROC is the procedure that will be called when an event occurs for FD. CLIENT_DATA is the argument to pass to PROC. */ static void -create_file_handler (int fd, int mask, handler_func *proc, gdb_client_data client_data) +create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data) { file_handler *file_ptr; @@ -508,7 +509,7 @@ create_file_handler (int fd, int mask, handler_func *proc, gdb_client_data clien } /* It is a new file descriptor. Add it to the list. Otherwise, just - change the data associated with it.*/ + change the data associated with it. */ if (file_ptr == NULL) { file_ptr = (file_handler *) xmalloc (sizeof (file_handler)); @@ -703,16 +704,16 @@ handle_file_event (int event_file_desc) if (error_mask_returned != 0) { /* Work in progress. We may need to tell somebody what - kind of error we had. */ + kind of error we had. */ /*if (error_mask_returned & POLLHUP) - printf_unfiltered ("Hangup detected on fd %d\n", file_ptr->fd); - if (error_mask_returned & POLLERR) - printf_unfiltered ("Error detected on fd %d\n", file_ptr->fd); - if (error_mask_returned & POLLNVAL) - printf_unfiltered ("Invalid fd %d\n", file_ptr->fd);*/ + printf_unfiltered ("Hangup detected on fd %d\n", file_ptr->fd); + if (error_mask_returned & POLLERR) + printf_unfiltered ("Error detected on fd %d\n", file_ptr->fd); + if (error_mask_returned & POLLNVAL) + printf_unfiltered ("Invalid fd %d\n", file_ptr->fd); */ file_ptr->error = 1; - } - else + } + else file_ptr->error = 0; #else /* ! HAVE_POLL */ if (file_ptr->ready_mask & GDB_EXCEPTION) @@ -764,12 +765,12 @@ gdb_wait_for_event (void) #ifdef HAVE_POLL num_found = - poll (gdb_notifier.poll_fds, - (unsigned long) gdb_notifier.num_fds, + poll (gdb_notifier.poll_fds, + (unsigned long) gdb_notifier.num_fds, gdb_notifier.timeout_valid ? gdb_notifier.timeout : -1); /* Don't print anything if we get out of poll because of a - signal.*/ + signal. */ if (num_found == -1 && errno != EINTR) perror_with_name ("Poll"); @@ -780,8 +781,8 @@ gdb_wait_for_event (void) num_found = select (gdb_notifier.num_fds, (SELECT_MASK *) & gdb_notifier.ready_masks[0], (SELECT_MASK *) & gdb_notifier.ready_masks[MASK_SIZE], - (SELECT_MASK *) & gdb_notifier.ready_masks[2 * MASK_SIZE], - gdb_notifier.timeout_valid ? gdb_notifier.timeout : NULL); + (SELECT_MASK *) & gdb_notifier.ready_masks[2 * MASK_SIZE], + gdb_notifier.timeout_valid ? &gdb_notifier.timeout : NULL); /* Clear the masks after an error from select. */ if (num_found == -1) @@ -871,7 +872,7 @@ gdb_wait_for_event (void) PROC is the function to call with CLIENT_DATA argument whenever the handler is invoked. */ async_signal_handler * -create_async_signal_handler (sig_handler_func *proc, gdb_client_data client_data) +create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data) { async_signal_handler *async_handler_ptr; @@ -894,7 +895,7 @@ create_async_signal_handler (sig_handler_func *proc, gdb_client_data client_data some event. The caller of this function is the interrupt handler associated with a signal. */ void -mark_async_signal_handler (async_signal_handler *async_handler_ptr) +mark_async_signal_handler (async_signal_handler * async_handler_ptr) { ((async_signal_handler *) async_handler_ptr)->ready = 1; async_handler_ready = 1; @@ -933,7 +934,7 @@ invoke_async_signal_handler (void) /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). Free the space allocated for it. */ void -delete_async_signal_handler (async_signal_handler **async_handler_ptr) +delete_async_signal_handler (async_signal_handler ** async_handler_ptr) { async_signal_handler *prev_ptr; @@ -975,18 +976,36 @@ inferior_event_handler (int error, gdb_client_data client_data, int fd) { printf_unfiltered ("error detected on fd %d\n", fd); delete_file_handler (fd); + pop_target (); discard_all_continuations (); } else - fetch_inferior_event (client_data); + /* Use catch errors for now, until the inner layers of + fetch_inferior_event (i.e. readchar) can return meaningful + error status. If an error occurs while getting an event from + the target, just get rid of the target. */ + if (!catch_errors (fetch_inferior_event_wrapper, client_data, "", RETURN_MASK_ALL)) + { + delete_file_handler (fd); + discard_all_continuations (); + pop_target (); + display_gdb_prompt (0); + } +} + +static int +fetch_inferior_event_wrapper (gdb_client_data client_data) +{ + fetch_inferior_event (client_data); + return 1; } /* Create a timer that will expire in MILLISECONDS from now. When the timer is ready, PROC will be executed. At creation, the timer is aded to the timers queue. This queue is kept sorted in order of - increasing timers. Return a handle to the timer struct.*/ + increasing timers. Return a handle to the timer struct. */ int -create_timer (int milliseconds, timer_handler_func *proc, gdb_client_data client_data) +create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data client_data) { struct gdb_timer *timer_ptr, *timer_index, *prev_timer; struct timeval time_now, delta; @@ -994,39 +1013,39 @@ create_timer (int milliseconds, timer_handler_func *proc, gdb_client_data client /* compute seconds */ delta.tv_sec = milliseconds / 1000; /* compute microseconds */ - delta.tv_usec = (milliseconds % 1000) * 1000; - + delta.tv_usec = (milliseconds % 1000) * 1000; + gettimeofday (&time_now, NULL); timer_ptr = (struct gdb_timer *) xmalloc (sizeof (gdb_timer)); timer_ptr->when.tv_sec = time_now.tv_sec + delta.tv_sec; timer_ptr->when.tv_usec = time_now.tv_usec + delta.tv_usec; /* carry? */ - if (timer_ptr->when.tv_usec >= 1000000 ) + if (timer_ptr->when.tv_usec >= 1000000) { timer_ptr->when.tv_sec += 1; timer_ptr->when.tv_usec -= 1000000; } timer_ptr->proc = proc; timer_ptr->client_data = client_data; - timer_list.num_timers ++; + timer_list.num_timers++; timer_ptr->timer_id = timer_list.num_timers; /* Now add the timer to the timer queue, making sure it is sorted in increasing order of expiration. */ - for (timer_index = timer_list.first_timer; - timer_index != NULL; + for (timer_index = timer_list.first_timer; + timer_index != NULL; timer_index = timer_index->next) { /* If the seconds field is greater or if it is the same, but the microsecond field is greater. */ - if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec) || + if ((timer_index->when.tv_sec > timer_ptr->when.tv_sec) || ((timer_index->when.tv_sec == timer_ptr->when.tv_sec) && (timer_index->when.tv_usec > timer_ptr->when.tv_usec))) break; } - + if (timer_index == timer_list.first_timer) { timer_ptr->next = timer_list.first_timer; @@ -1035,11 +1054,11 @@ create_timer (int milliseconds, timer_handler_func *proc, gdb_client_data client } else { - for (prev_timer = timer_list.first_timer; - prev_timer->next != timer_index; + for (prev_timer = timer_list.first_timer; + prev_timer->next != timer_index; prev_timer = prev_timer->next) ; - + prev_timer->next = timer_ptr; timer_ptr->next = timer_index; } @@ -1085,20 +1104,20 @@ delete_timer (int id) /* When a timer event is put on the event queue, it will be handled by this function. Just call the assiciated procedure and delete the timer event from the event queue. Repeat this for each timer that - has expired.*/ + has expired. */ static void handle_timer_event (int dummy) { struct timeval time_now; struct gdb_timer *timer_ptr, *saved_timer; - + gettimeofday (&time_now, NULL); timer_ptr = timer_list.first_timer; while (timer_ptr != NULL) { - if ((timer_ptr->when.tv_sec > time_now.tv_sec) || - ((timer_ptr->when.tv_sec == time_now.tv_sec) && + if ((timer_ptr->when.tv_sec > time_now.tv_sec) || + ((timer_ptr->when.tv_sec == time_now.tv_sec) && (timer_ptr->when.tv_usec > time_now.tv_usec))) break; @@ -1113,19 +1132,19 @@ handle_timer_event (int dummy) gdb_notifier.timeout_valid = 0; } - + /* Check whether any timers in the timers queue are ready. If at least one timer is ready, stick an event onto the event queue. Even in case more than one timer is ready, one event is enough, because the handle_timer_event() will go through the timers list and call the procedures associated with all that have expired. Update the - timeout for the select() or poll() as well.*/ + timeout for the select() or poll() as well. */ static void poll_timers (void) { struct timeval time_now, delta; gdb_event *event_ptr; - + if (timer_list.num_timers) { gettimeofday (&time_now, NULL); @@ -1137,9 +1156,9 @@ poll_timers (void) delta.tv_sec -= 1; delta.tv_usec += 1000000; } - + /* Oops it expired already. Tell select / poll to return - immediately. */ + immediately. */ if (delta.tv_sec < 0) { delta.tv_sec = 0; @@ -1155,15 +1174,15 @@ poll_timers (void) } /* Now we need to update the timeout for select/ poll, because we - don't want to sit there while this timer is expiring. */ + don't want to sit there while this timer is expiring. */ #ifdef HAVE_POLL - gdb_notifier.timeout = delta.tv_sec * 1000; + gdb_notifier.timeout = delta.tv_sec * 1000; #else - gdb_notifier.timeout.sec = delta.tv_sec; - gdb_notifier.timeout.usec = delta.tv_usec; + gdb_notifier.timeout.tv_sec = delta.tv_sec; + gdb_notifier.timeout.tv_usec = delta.tv_usec; #endif gdb_notifier.timeout_valid = 1; } - else + else gdb_notifier.timeout_valid = 0; } diff --git a/gdb/event-loop.h b/gdb/event-loop.h index ffb0123..e559464 100644 --- a/gdb/event-loop.h +++ b/gdb/event-loop.h @@ -86,15 +86,11 @@ queue_position; extern void start_event_loop (void); extern void delete_file_handler (int fd); -extern void add_file_handler (int fd, handler_func *proc, gdb_client_data client_data); +extern void add_file_handler (int fd, handler_func * proc, gdb_client_data client_data); extern void mark_async_signal_handler (struct async_signal_handler *async_handler_ptr); -extern struct async_signal_handler * - create_async_signal_handler (sig_handler_func *proc, gdb_client_data client_data); -extern void delete_async_signal_handler (struct async_signal_handler ** async_handler_ptr); +extern struct async_signal_handler * + create_async_signal_handler (sig_handler_func * proc, gdb_client_data client_data); +extern void delete_async_signal_handler (struct async_signal_handler **async_handler_ptr); extern void inferior_event_handler (int error, gdb_client_data client_data, int fd); -extern int create_timer (int milliseconds, timer_handler_func *proc, gdb_client_data client_data); +extern int create_timer (int milliseconds, timer_handler_func * proc, gdb_client_data client_data); extern void delete_timer (int id); - - - - diff --git a/gdb/event-top.c b/gdb/event-top.c index 622396f..b1b625d 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -244,22 +244,22 @@ display_gdb_prompt (char *new_prompt) char *gdb_prompt = get_prompt (); - if (target_executing && sync_execution) + if (target_executing && sync_execution) { /* This is to trick readline into not trying to display the - prompt. Even though we display the prompt using this - function, readline still tries to do its own display if we - don't call rl_callback_handler_install and - rl_callback_handler_remove (which readline detects because a - global variable is not set). If readline did that, it could - mess up gdb signal handlers for SIGINT. Readline assumes - that between calls to rl_set_signals and rl_clear_signals gdb - doesn't do anything with the signal handlers. Well, that's - not the case, because when the target executes we change the - SIGINT signal handler. If we allowed readline to display the - prompt, the signal handler change would happen exactly - between the calls to the above two functions. - Calling rl_callback_handler_remove(), does the job. */ + prompt. Even though we display the prompt using this + function, readline still tries to do its own display if we + don't call rl_callback_handler_install and + rl_callback_handler_remove (which readline detects because a + global variable is not set). If readline did that, it could + mess up gdb signal handlers for SIGINT. Readline assumes + that between calls to rl_set_signals and rl_clear_signals gdb + doesn't do anything with the signal handlers. Well, that's + not the case, because when the target executes we change the + SIGINT signal handler. If we allowed readline to display the + prompt, the signal handler change would happen exactly + between the calls to the above two functions. + Calling rl_callback_handler_remove(), does the job. */ rl_callback_handler_remove (); return; @@ -410,10 +410,44 @@ stdin_event_handler (int error, int fd, gdb_client_data client_data) exit (1); } else - (*call_readline) (client_data); + (*call_readline) (client_data); } +/* Re-enable stdin after the end of an execution command in + synchronous mode, or after an error from the target, and we aborted + the exec operation. */ + +void +async_enable_stdin (void *dummy) +{ + /* See NOTE in async_disable_stdin() */ + /* FIXME: cagney/1999-09-27: Call this before clearing + sync_execution. Current target_terminal_ours() implementations + check for sync_execution before switching the terminal. */ + target_terminal_ours (); + pop_prompt (); + sync_execution = 0; +} + +/* Disable reads from stdin (the console) marking the command as + synchronous. */ + +void +async_disable_stdin (void) +{ + sync_execution = 1; + push_prompt ("", "", ""); + /* FIXME: cagney/1999-09-27: At present this call is technically + redundant since infcmd.c and infrun.c both already call + target_terminal_inferior(). As the terminal handling (in + sync/async mode) is refined, the duplicate calls can be + eliminated (Here or in infcmd.c/infrun.c). */ + target_terminal_inferior (); + make_exec_cleanup (async_enable_stdin, NULL); + make_exec_error_cleanup (async_enable_stdin, NULL); +} + /* Handles a gdb command. This function is called by command_line_handler, which has processed one or more input lines into COMMAND. */ @@ -471,7 +505,7 @@ command_handler (char *command) /* Set things up for this function to be compete later, once the executin has completed, if we are doing an execution command, otherwise, just go ahead and finish. */ - if (target_has_async && target_executing) + if (target_can_async_p () && target_executing) { arg1 = (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); @@ -487,7 +521,7 @@ command_handler (char *command) /* Do any commands attached to breakpoint we stopped at. Only if we are always running synchronously. Or if we have just executed a command that doesn't start the target. */ - if (!target_has_async || !target_executing) + if (!target_can_async_p () || !target_executing) { bpstat_do_actions (&stop_bpstat); do_cleanups (old_chain); @@ -1077,7 +1111,7 @@ set_async_prompt (char *args, int from_tty, struct cmd_list_element *c) void _initialize_event_loop (void) { - if (async_p) + if (event_loop_p) { /* When a character is detected on instream by select or poll, readline will be invoked via this callback function. */ diff --git a/gdb/event-top.h b/gdb/event-top.h index 24184a4..baacd1b 100644 --- a/gdb/event-top.h +++ b/gdb/event-top.h @@ -90,6 +90,8 @@ extern void gdb_readline2 (gdb_client_data client_data); extern void mark_async_signal_handler_wrapper (PTR token); extern void async_request_quit (gdb_client_data arg); extern void stdin_event_handler (int error, int fd, gdb_client_data client_data); +extern void async_disable_stdin (void); +extern void async_enable_stdin (void *dummy); /* Exported variables from event-top.c. FIXME: these should really go into top.h. */ diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index ffcbf32..793f89b 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -2254,14 +2254,34 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) /* It must also be an import stub. */ u = find_unwind_entry (SYMBOL_VALUE (stub_symbol)); - if (!u - || (u->stub_unwind.stub_type != IMPORT) - && u->stub_unwind.stub_type != IMPORT_SHLIB) + if (u == NULL + || (u->stub_unwind.stub_type != IMPORT +#ifdef GDB_NATIVE_HPUX_11 + /* Sigh. The hpux 10.20 dynamic linker will blow + chunks if we perform a call to an unbound function + via the IMPORT_SHLIB stub. The hpux 11.00 dynamic + linker will blow chunks if we do not call the + unbound function via the IMPORT_SHLIB stub. + + We currently have no way to select bevahior on just + the target. However, we only support HPUX/SOM in + native mode. So we conditinalize on a native + #ifdef. Ugly. Ugly. Ugly */ + && u->stub_unwind.stub_type != IMPORT_SHLIB +#endif + )) continue; /* OK. Looks like the correct import stub. */ newfun = SYMBOL_VALUE (stub_symbol); fun = newfun; + + /* If we found an IMPORT stub, then we want to stop + searching now. If we found an IMPORT_SHLIB, we want + to continue the search in the hopes that we will find + an IMPORT stub. */ + if (u->stub_unwind.stub_type == IMPORT) + break; } } @@ -3671,6 +3691,15 @@ restart: || (inst & 0xffffc00c) == 0x73c10008) save_sp = 0; + /* Are we loading some register with an offset from the argument + pointer? */ + if ((inst & 0xffe00000) == 0x37a00000 + || (inst & 0xffffffe0) == 0x081d0240) + { + pc += 4; + continue; + } + /* Account for general and floating-point register saves. */ reg_num = inst_saves_gr (inst); save_gr &= ~(1 << reg_num); @@ -3685,9 +3714,9 @@ restart: FIXME. Can still die if we have a mix of GR and FR argument stores! */ - if (reg_num >= 23 && reg_num <= 26) + if (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26) { - while (reg_num >= 23 && reg_num <= 26) + while (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26) { pc += 4; status = target_read_memory (pc, buf, 4); @@ -3714,7 +3743,7 @@ restart: save. */ if ((inst & 0xfc000000) == 0x34000000 && inst_saves_fr (next_inst) >= 4 - && inst_saves_fr (next_inst) <= 7) + && inst_saves_fr (next_inst) <= (TARGET_PTR_BIT == 64 ? 11 : 7)) { /* So we drop into the code below in a reasonable state. */ reg_num = inst_saves_fr (next_inst); @@ -3725,9 +3754,9 @@ restart: This is a kludge as on the HP compiler sets this bit and it never does prologue scheduling. So once we see one, skip past all of them. */ - if (reg_num >= 4 && reg_num <= 7) + if (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7)) { - while (reg_num >= 4 && reg_num <= 7) + while (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7)) { pc += 8; status = target_read_memory (pc, buf, 4); diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 3a41f6a..4fbee95 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -35,6 +35,7 @@ #include "symfile.h" #include "objfiles.h" #include "event-loop.h" +#include "event-top.h" #include "parser-defs.h" /* Functions exported for general use: */ @@ -280,7 +281,10 @@ Start it from the beginning? ")) want them to go away (PR 2207). This is probably reasonable. */ if (!args) - sync_execution = 1; + { + if (event_loop_p && target_can_async_p ()) + async_disable_stdin (); + } else { char *cmd; @@ -288,15 +292,15 @@ Start it from the beginning? ")) /* If we get a request for running in the bg but the target doesn't support it, error out. */ - if (async_p && async_exec && !target_has_async) + if (event_loop_p && async_exec && !target_can_async_p ()) error ("Asynchronous execution not supported on this target."); /* If we don't get a request of running in the bg, then we need to simulate synchronous (fg) execution. */ - if (async_p && !async_exec && target_has_async) + if (event_loop_p && !async_exec && target_can_async_p ()) { /* Simulate synchronous execution */ - sync_execution = 1; + async_disable_stdin (); } /* If there were other args, beside '&', process them. */ @@ -348,15 +352,15 @@ continue_command (proc_count_exp, from_tty) /* If we must run in the background, but the target can't do it, error out. */ - if (async_p && async_exec && !target_has_async) + if (event_loop_p && async_exec && !target_can_async_p ()) error ("Asynchronous execution not supported on this target."); /* If we are not asked to run in the bg, then prepare to run in the foreground, synchronously. */ - if (async_p && !async_exec && target_has_async) + if (event_loop_p && !async_exec && target_can_async_p ()) { /* Simulate synchronous execution */ - sync_execution = 1; + async_disable_stdin (); } /* If have argument (besides '&'), set proceed count of breakpoint @@ -451,15 +455,15 @@ step_1 (skip_subroutines, single_inst, count_string) /* If we get a request for running in the bg but the target doesn't support it, error out. */ - if (async_p && async_exec && !target_has_async) + if (event_loop_p && async_exec && !target_can_async_p ()) error ("Asynchronous execution not supported on this target."); /* If we don't get a request of running in the bg, then we need to simulate synchronous (fg) execution. */ - if (async_p && !async_exec && target_has_async) + if (event_loop_p && !async_exec && target_can_async_p ()) { /* Simulate synchronous execution */ - sync_execution = 1; + async_disable_stdin (); } count = count_string ? parse_and_eval_address (count_string) : 1; @@ -550,15 +554,15 @@ jump_command (arg, from_tty) /* If we must run in the background, but the target can't do it, error out. */ - if (async_p && async_exec && !target_has_async) + if (event_loop_p && async_exec && !target_can_async_p ()) error ("Asynchronous execution not supported on this target."); /* If we are not asked to run in the bg, then prepare to run in the foreground, synchronously. */ - if (async_p && !async_exec && target_has_async) + if (event_loop_p && !async_exec && target_can_async_p ()) { /* Simulate synchronous execution */ - sync_execution = 1; + async_disable_stdin (); } if (!arg) @@ -848,15 +852,15 @@ until_command (arg, from_tty) /* If we must run in the background, but the target can't do it, error out. */ - if (async_p && async_exec && !target_has_async) + if (event_loop_p && async_exec && !target_can_async_p ()) error ("Asynchronous execution not supported on this target."); /* If we are not asked to run in the bg, then prepare to run in the foreground, synchronously. */ - if (async_p && !async_exec && target_has_async) + if (event_loop_p && !async_exec && target_can_async_p ()) { /* Simulate synchronous execution */ - sync_execution = 1; + async_disable_stdin (); } if (arg) @@ -964,15 +968,15 @@ finish_command (arg, from_tty) /* If we must run in the background, but the target can't do it, error out. */ - if (async_p && async_exec && !target_has_async) + if (event_loop_p && async_exec && !target_can_async_p ()) error ("Asynchronous execution not supported on this target."); /* If we are not asked to run in the bg, then prepare to run in the foreground, synchronously. */ - if (async_p && !async_exec && target_has_async) + if (event_loop_p && !async_exec && target_can_async_p ()) { /* Simulate synchronous execution */ - sync_execution = 1; + async_disable_stdin (); } if (arg) @@ -993,7 +997,7 @@ finish_command (arg, from_tty) breakpoint = set_momentary_breakpoint (sal, frame, bp_finish); - if (!async_p || !target_has_async) + if (!event_loop_p || !target_can_async_p ()) old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); else make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); @@ -1014,7 +1018,7 @@ finish_command (arg, from_tty) execution, set things up for the rest of the finish command to be completed later on, when gdb has detected that the target has stopped, in fetch_inferior_event. */ - if (async_p && target_has_async) + if (event_loop_p && target_can_async_p ()) { arg1 = (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); @@ -1033,7 +1037,7 @@ finish_command (arg, from_tty) /* Do this only if not running asynchronously or if the target cannot do async execution. Otherwise, complete this command when the target actually stops, in fetch_inferior_event. */ - if (!async_p || !target_has_async) + if (!event_loop_p || !target_can_async_p ()) { /* Did we stop at our breakpoint? */ @@ -1589,6 +1593,9 @@ attach_command (args, from_tty) target_post_attach (inferior_pid); normal_stop (); + + if (attach_hook) + attach_hook (); } /* @@ -1612,6 +1619,8 @@ detach_command (args, from_tty) #if defined(SOLIB_RESTART) SOLIB_RESTART (); #endif + if (detach_hook) + detach_hook (); } /* Stop the execution of the target while running in async mode, in @@ -1621,7 +1630,7 @@ interrupt_target_command (args, from_tty) char *args; int from_tty; { - if (async_p && target_has_async) + if (event_loop_p && target_can_async_p ()) { dont_repeat (); /* Not for the faint of heart */ target_stop (); diff --git a/gdb/infrun.c b/gdb/infrun.c index dd569c3..48fe874 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -36,7 +36,6 @@ #include <signal.h> #include "event-loop.h" #include "event-top.h" -#include "remote.h" /* For cleanup_sigint_signal_handler. */ /* Prototypes for local functions */ @@ -1070,7 +1069,7 @@ The same program may be running in another process."); and in any case decode why it stopped, and act accordingly. */ /* Do this only if we are not using the event loop, or if the target does not support asynchronous execution. */ - if (!async_p || !target_has_async) + if (!event_loop_p || !target_can_async_p ()) { wait_for_inferior (); normal_stop (); @@ -1096,23 +1095,22 @@ start_remote (void) stop_soon_quietly = 1; trap_expected = 0; - /* Go on waiting only in case gdb is not started in async mode, or - in case the target doesn't support async execution. */ - if (!async_p || !target_has_async) - { - wait_for_inferior (); - normal_stop (); - } - else - { - /* The 'tar rem' command should always look synchronous, - i.e. display the prompt only once it has connected and - started the target. */ - sync_execution = 1; - push_prompt ("", "", ""); - delete_file_handler (input_fd); - target_executing = 1; - } + /* Always go on waiting for the target, regardless of the mode. */ + /* FIXME: cagney/1999-09-23: At present it isn't possible to + indicate th wait_for_inferior that a target should timeout if + nothing is returned (instead of just blocking). Because of this, + targets expecting an immediate response need to, internally, set + things up so that the target_wait() is forced to eventually + timeout. */ + /* FIXME: cagney/1999-09-24: It isn't possible for target_open() to + differentiate to its caller what the state of the target is after + the initial open has been performed. Here we're assuming that + the target has stopped. It should be possible to eventually have + target_open() return to the caller an indication that the target + is currently running and GDB state should be set to the same as + for an async run. */ + wait_for_inferior (); + normal_stop (); } /* Initialize static vars when a new inferior begins. */ @@ -1588,13 +1586,7 @@ handle_inferior_event (struct execution_control_state *ecs) stop_pc = read_pc_pid (ecs->pid); ecs->saved_inferior_pid = inferior_pid; inferior_pid = ecs->pid; - stop_bpstat = bpstat_stop_status - (&stop_pc, - (DECR_PC_AFTER_BREAK ? - (prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && currently_stepping (ecs)) - : 0) - ); + stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs)); ecs->random_signal = !bpstat_explains_signal (stop_bpstat); inferior_pid = ecs->saved_inferior_pid; goto process_event_stop_test; @@ -1642,13 +1634,7 @@ handle_inferior_event (struct execution_control_state *ecs) } stop_pc = read_pc (); - stop_bpstat = bpstat_stop_status - (&stop_pc, - (DECR_PC_AFTER_BREAK ? - (prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && currently_stepping (ecs)) - : 0) - ); + stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs)); ecs->random_signal = !bpstat_explains_signal (stop_bpstat); goto process_event_stop_test; @@ -1713,13 +1699,7 @@ handle_inferior_event (struct execution_control_state *ecs) stop_pc = read_pc_pid (ecs->pid); ecs->saved_inferior_pid = inferior_pid; inferior_pid = ecs->pid; - stop_bpstat = bpstat_stop_status - (&stop_pc, - (DECR_PC_AFTER_BREAK ? - (prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && currently_stepping (ecs)) - : 0) - ); + stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs)); ecs->random_signal = !bpstat_explains_signal (stop_bpstat); inferior_pid = ecs->saved_inferior_pid; goto process_event_stop_test; @@ -2105,22 +2085,15 @@ handle_inferior_event (struct execution_control_state *ecs) /* See if there is a breakpoint at the current PC. */ stop_bpstat = bpstat_stop_status (&stop_pc, - (DECR_PC_AFTER_BREAK ? - /* Notice the case of stepping through a jump - that lands just after a breakpoint. - Don't confuse that with hitting the breakpoint. - What we check for is that 1) stepping is going on - and 2) the pc before the last insn does not match - the address of the breakpoint before the current pc - and 3) we didn't hit a breakpoint in a signal handler - without an intervening stop in sigtramp, which is - detected by a new stack pointer value below - any usual function calling stack adjustments. */ + /* Pass TRUE if our reason for stopping is something other + than hitting a breakpoint. We do this by checking that + 1) stepping is going on and 2) we didn't hit a breakpoint + in a signal handler without an intervening stop in + sigtramp, which is detected by a new stack pointer value + below any usual function calling stack adjustments. */ (currently_stepping (ecs) - && prev_pc != stop_pc - DECR_PC_AFTER_BREAK && !(step_range_end - && INNER_THAN (read_sp (), (step_sp - 16)))) : - 0) + && INNER_THAN (read_sp (), (step_sp - 16)))) ); /* Following in case break condition called a function. */ @@ -3274,12 +3247,10 @@ static void complete_execution (void) { target_executing = 0; + if (sync_execution) { - add_file_handler (input_fd, stdin_event_handler, 0); - pop_prompt (); - sync_execution = 0; - cleanup_sigint_signal_handler (); + do_exec_error_cleanups (ALL_CLEANUPS); display_gdb_prompt (0); } else diff --git a/gdb/irix5-nat.c b/gdb/irix5-nat.c index dc9abe0..50bae76 100644 --- a/gdb/irix5-nat.c +++ b/gdb/irix5-nat.c @@ -908,37 +908,8 @@ solib_add (arg_string, from_tty, target) if (count) { - int update_coreops; - - /* We must update the to_sections field in the core_ops structure - here, otherwise we dereference a potential dangling pointer - for each call to target_read/write_memory within this routine. */ - update_coreops = core_ops.to_sections == target->to_sections; - - /* Reallocate the target's section table including the new size. */ - if (target->to_sections) - { - old = target->to_sections_end - target->to_sections; - target->to_sections = (struct section_table *) - xrealloc ((char *) target->to_sections, - (sizeof (struct section_table)) * (count + old)); - } - else - { - old = 0; - target->to_sections = (struct section_table *) - xmalloc ((sizeof (struct section_table)) * count); - } - target->to_sections_end = target->to_sections + (count + old); - - /* Update the to_sections field in the core_ops structure - if needed. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } - + old = target_resize_to_sections (target, count); + /* Add these section table entries to the target's table. */ while ((so = find_solib (so)) != NULL) { diff --git a/gdb/m32r-stub.c b/gdb/m32r-stub.c index bc5e599..dcbdbbb 100644 --- a/gdb/m32r-stub.c +++ b/gdb/m32r-stub.c @@ -429,7 +429,7 @@ handle_exception(int exceptionVector) break; } case 'G': /* set the value of the CPU registers - return OK */ - hex2mem(&ptr, (unsigned char*) registers, NUMREGBYTES, 0); + hex2mem(ptr, (unsigned char*) registers, NUMREGBYTES, 0); strcpy(remcomOutBuffer,"OK"); break; case 's': /* sAA..AA Step one instruction from AA..AA(optional) */ @@ -46,7 +46,7 @@ int display_space; invoked on the command line with the -nw --async options. In this version, the usual command_loop is substituted by and event loop which processes UI events asynchronously. */ -int async_p = 1; +int event_loop_p = 1; /* Whether this is the command line version or not */ int tui_version = 0; @@ -177,8 +177,8 @@ main (argc, argv) with no equivalent). */ static struct option long_options[] = { - {"async", no_argument, &async_p, 1}, - {"noasync", no_argument, &async_p, 0}, + {"async", no_argument, &event_loop_p, 1}, + {"noasync", no_argument, &event_loop_p, 0}, #if defined(TUI) {"tui", no_argument, &tui_version, 1}, #endif diff --git a/gdb/osfsolib.c b/gdb/osfsolib.c index 831fc75..6b05613 100644 --- a/gdb/osfsolib.c +++ b/gdb/osfsolib.c @@ -655,38 +655,10 @@ solib_add (arg_string, from_tty, target) if (count) { - int update_coreops; - - /* We must update the to_sections field in the core_ops structure - here, otherwise we dereference a potential dangling pointer - for each call to target_read/write_memory within this routine. */ - update_coreops = core_ops.to_sections == target->to_sections; - - /* Reallocate the target's section table including the new size. */ - if (target->to_sections) - { - old = target->to_sections_end - target->to_sections; - target->to_sections = (struct section_table *) - xrealloc ((char *) target->to_sections, - (sizeof (struct section_table)) * (count + old)); - } - else - { - old = 0; - target->to_sections = (struct section_table *) - xmalloc ((sizeof (struct section_table)) * count); - } - target->to_sections_end = target->to_sections + (count + old); - - /* Update the to_sections field in the core_ops structure - if needed. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } - /* Add these section table entries to the target's table. */ + + old = target_resize_to_sections (target, count); + while ((so = find_solib (so)) != NULL) { if (so->so_name[0]) diff --git a/gdb/pa64solib.c b/gdb/pa64solib.c index b0b4645..414e5b8 100644 --- a/gdb/pa64solib.c +++ b/gdb/pa64solib.c @@ -357,49 +357,12 @@ pa64_solib_load_symbols (so, name, from_tty, text_addr, target) status = target_read_memory (text_addr, buf, 4); if (status != 0) { - int old, new; - int update_coreops; - int update_execops; - - /* We must update the to_sections field in the core_ops structure - here, otherwise we dereference a potential dangling pointer - for each call to target_read/write_memory within this routine. */ - update_coreops = core_ops.to_sections == target->to_sections; - - /* Ditto exec_ops (this was a bug). */ - update_execops = exec_ops.to_sections == target->to_sections; - + int new, old; + new = so->sections_end - so->sections; - /* Add sections from the shared library to the core target. */ - if (target->to_sections) - { - old = target->to_sections_end - target->to_sections; - target->to_sections = (struct section_table *) - xrealloc ((char *) target->to_sections, - ((sizeof (struct section_table)) * (old + new))); - } - else - { - old = 0; - target->to_sections = (struct section_table *) - xmalloc ((sizeof (struct section_table)) * new); - } - target->to_sections_end = (target->to_sections + old + new); - - /* Update the to_sections field in the core_ops structure - if needed, ditto exec_ops. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } - - if (update_execops) - { - exec_ops.to_sections = target->to_sections; - exec_ops.to_sections_end = target->to_sections_end; - } + old = target_resize_to_sections (target, new); + /* Copy over the old data before it gets clobbered. */ memcpy ((char *) (target->to_sections + old), so->sections, diff --git a/gdb/procfs.c b/gdb/procfs.c index 9abda2e..4bd8fe9 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -2265,9 +2265,6 @@ init_procinfo (pid, kill) prfillset (&sctl.sigset); notice_signals (pi, &sctl); - prfillset (&fctl.fltset); - prdelset (&fctl.fltset, FLTPAGE); - #else /* ! UNIXWARE */ ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset); ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset); @@ -2280,11 +2277,6 @@ init_procinfo (pid, kill) memset ((char *) &pi->prrun, 0, sizeof (pi->prrun)); prfillset (&pi->prrun.pr_trace); procfs_notice_signals (pid); - prfillset (&pi->prrun.pr_fault); - prdelset (&pi->prrun.pr_fault, FLTPAGE); -#ifdef PROCFS_DONT_TRACE_FAULTS - premptyset (&pi->prrun.pr_fault); -#endif #endif /* UNIXWARE */ if (!procfs_read_status (pi)) @@ -2340,9 +2332,17 @@ create_procinfo (pid) #ifdef PROCFS_USE_READ_WRITE fctl.cmd = PCSFAULT; + prfillset (&fctl.fltset); + prdelset (&fctl.fltset, FLTPAGE); + if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0) proc_init_failed (pi, "PCSFAULT failed", 1); #else + prfillset (&pi->prrun.pr_fault); + prdelset (&pi->prrun.pr_fault, FLTPAGE); +#ifdef PROCFS_DONT_TRACE_FAULTS + premptyset (&pi->prrun.pr_fault); +#endif if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0) proc_init_failed (pi, "PIOCSFAULT failed", 1); #endif @@ -3318,9 +3318,17 @@ do_attach (pid) #ifdef PROCFS_USE_READ_WRITE fctl.cmd = PCSFAULT; + prfillset (&fctl.fltset); + prdelset (&fctl.fltset, FLTPAGE); + if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0) print_sys_errmsg ("PCSFAULT failed", errno); #else /* PROCFS_USE_READ_WRITE */ + prfillset (&pi->prrun.pr_fault); + prdelset (&pi->prrun.pr_fault, FLTPAGE); +#ifdef PROCFS_DONT_TRACE_FAULTS + premptyset (&pi->prrun.pr_fault); +#endif if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault)) { print_sys_errmsg ("PIOCSFAULT failed", errno); diff --git a/gdb/remote.c b/gdb/remote.c index 645ef22..aa36ec7 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -53,7 +53,9 @@ #include "serial.h" /* Prototypes for local functions */ -static void initialize_sigint_signal_handler PARAMS ((void)); +static void cleanup_sigint_signal_handler (void *dummy); +static void initialize_sigint_signal_handler (void); + static void handle_remote_sigint PARAMS ((int)); static void handle_remote_sigint_twice PARAMS ((int)); static void async_remote_interrupt PARAMS ((gdb_client_data)); @@ -83,7 +85,6 @@ static void remote_resume PARAMS ((int pid, int step, enum target_signal siggnal)); static void remote_async_resume PARAMS ((int pid, int step, enum target_signal siggnal)); - static int remote_start_remote PARAMS ((PTR)); static void remote_open PARAMS ((char *name, int from_tty)); @@ -253,6 +254,16 @@ static struct target_ops extended_async_remote_ops; was static int remote_timeout = 2; */ extern int remote_timeout; +/* FIXME: cagney/1999-09-23: Even though getpkt was called with + ``forever'' still use the normal timeout mechanism. This is + currently used by the ASYNC code to guarentee that target reads + during the initial connect always time-out. Once getpkt has been + modified to return a timeout indication and, in turn + remote_wait()/wait_for_inferior() have gained a timeout parameter + this can go away. */ +static int wait_forever_enabled_p = 1; + + /* This variable chooses whether to send a ^C or a break when the user requests program interruption. Although ^C is usually what remote systems expect, and that is the default here, sometimes a break is @@ -311,6 +322,11 @@ static int remote_address_size; static int remote_register_buf_size = 0; +/* Tempoary to track who currently owns the terminal. See + target_async_terminal_* for more details. */ + +static int remote_async_terminal_ours_p; + /* Generic configuration support for packets the stub optionally supports. Allows the user to specify the use of the packet as well as allowing GDB to auto-detect support in the remote stub. */ @@ -1717,6 +1733,9 @@ remote_open_1 (name, from_tty, target, extended_p) error ("To open a remote debug connection, you need to specify what\n\ serial device is attached to the remote system (e.g. /dev/ttya)."); + /* See FIXME above */ + wait_forever_enabled_p = 1; + target_preopen (from_tty); unpush_target (target); @@ -1832,15 +1851,6 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); puts_filtered ("\n"); } - /* If running in asynchronous mode, register the target with the - event loop. Set things up so that when there is an event on the - file descriptor, the event loop will call fetch_inferior_event, - which will do the proper analysis to determine what happened. */ - if (async_p && SERIAL_CAN_ASYNC_P (remote_desc)) - SERIAL_ASYNC (remote_desc, inferior_event_handler, 0); - if (remote_debug && SERIAL_IS_ASYNC_P (remote_desc)) - fputs_unfiltered ("Async mode.\n", gdb_stdlog); - push_target (target); /* Switch to using remote target now */ init_packet_config (&remote_protocol_P); @@ -1853,20 +1863,26 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); binary downloading. */ init_packet_config (&remote_protocol_binary_download); - /* If running asynchronously, set things up for telling the target - to use the extended protocol. This will happen only after the - target has been connected to, in fetch_inferior_event. */ - if (extended_p && SERIAL_IS_ASYNC_P (remote_desc)) - add_continuation (set_extended_protocol, NULL); - /* Without this, some commands which require an active target (such as kill) won't work. This variable serves (at least) double duty as both the pid of the target process (if it has such), and as a flag indicating that a target is active. These functions should be split out into seperate variables, especially since GDB will someday have a notion of debugging several processes. */ - inferior_pid = MAGIC_NULL_PID; + + /* With this target we start out by owning the terminal. */ + remote_async_terminal_ours_p = 1; + + /* FIXME: cagney/1999-09-23: During the initial connection it is + assumed that the target is already ready and able to respond to + requests. Unfortunatly remote_start_remote() eventually calls + wait_for_inferior() with no timeout. wait_forever_enabled_p gets + around this. Eventually a mechanism that allows + wait_for_inferior() to expect/get timeouts will be + implemented. */ + wait_forever_enabled_p = 0; + /* Start the remote connection; if error (0), discard this target. In particular, if the user quits, be sure to discard it (we'd be in an inconsistent state otherwise). */ @@ -1874,35 +1890,32 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); "Couldn't establish connection to remote target\n", RETURN_MASK_ALL)) { - /* Unregister the file descriptor from the event loop. */ - if (SERIAL_IS_ASYNC_P (remote_desc)) - SERIAL_ASYNC (remote_desc, NULL, 0); pop_target (); + wait_forever_enabled_p = 1; return; } - if (!SERIAL_IS_ASYNC_P (remote_desc)) + wait_forever_enabled_p = 1; + + if (extended_p) { - if (extended_p) - { - /* tell the remote that we're using the extended protocol. */ - char *buf = alloca (PBUFSIZ); - putpkt ("!"); - getpkt (buf, 0); - } + /* tell the remote that we're using the extended protocol. */ + char *buf = alloca (PBUFSIZ); + putpkt ("!"); + getpkt (buf, 0); } -} -/* This will be called by fetch_inferior_event, via the - cmd_continuation pointer, only after the target has stopped. */ -static void -set_extended_protocol (arg) - struct continuation_arg *arg; -{ - /* tell the remote that we're using the extended protocol. */ - char *buf = alloca (PBUFSIZ); - putpkt ("!"); - getpkt (buf, 0); + /* If running in asynchronous mode, register the target with the + event loop. Set things up so that when there is an event on the + file descriptor, the event loop will call fetch_inferior_event, + which will do the proper analysis to determine what happened. */ + /* FIXME: cagney/1999-09-26: We shouldn't just put the target into + async mode. Instead we should leave the target synchronous and + then leave it to the client to flip modes. */ + if (event_loop_p && target_can_async_p ()) + target_async (inferior_event_handler, 0); + if (remote_debug && SERIAL_IS_ASYNC_P (remote_desc)) + fputs_unfiltered ("Serial put into async mode.\n", gdb_stdlog); } /* This takes a program previously attached to and detaches it. After @@ -2046,25 +2059,13 @@ remote_async_resume (pid, step, siggnal) if (target_resume_hook) (*target_resume_hook) (); - /* Set things up before execution starts for async commands. */ - /* This function can be entered more than once for the same execution - command, because it is also called by handle_inferior_event. So - we make sure that we don't do the initialization for sync - execution more than once. */ - if (SERIAL_IS_ASYNC_P (remote_desc) && !target_executing) - { - target_executing = 1; - - /* If the command must look synchronous, fake it, by making gdb - display an empty prompt after the command has completed. Also - disable input. */ - if (sync_execution) - { - push_prompt ("", "", ""); - delete_file_handler (input_fd); - initialize_sigint_signal_handler (); - } - } + /* Tell the world that the target is now executing. */ + /* FIXME: cagney/1999-09-23: Is it the targets responsibility to set + this? Instead, should the client of target just assume (for + async targets) that the target is going to start executing? Is + this information already found in the continuation block? */ + if (SERIAL_IS_ASYNC_P (remote_desc)) + target_executing = 1; if (siggnal != TARGET_SIGNAL_0) { @@ -2110,11 +2111,11 @@ handle_remote_sigint_twice (sig) { signal (sig, handle_sigint); sigint_remote_twice_token = - create_async_signal_handler (async_remote_interrupt, NULL); + create_async_signal_handler (async_remote_interrupt_twice, NULL); mark_async_signal_handler_wrapper (sigint_remote_twice_token); } -/* Perform the real interruption of hte target execution, in response +/* Perform the real interruption of the target execution, in response to a ^C. */ static void async_remote_interrupt (arg) @@ -2132,14 +2133,19 @@ static void async_remote_interrupt_twice (arg) gdb_client_data arg; { - interrupt_query (); - signal (SIGINT, handle_remote_sigint); + /* Do something only if the target was not killed by the previous + cntl-C. */ + if (target_executing) + { + interrupt_query (); + signal (SIGINT, handle_remote_sigint); + } } /* Reinstall the usual SIGINT handlers, after the target has stopped. */ -void -cleanup_sigint_signal_handler () +static void +cleanup_sigint_signal_handler (void *dummy) { signal (SIGINT, handle_sigint); if (sigint_remote_twice_token) @@ -2214,6 +2220,51 @@ Give up (and stop debugging it)? ")) target_terminal_inferior (); } +/* Enable/disable target terminal ownership. Most targets can use + terminal groups to control terminal ownership. Remote targets are + different in that explicit transfer of ownership to/from GDB/target + is required. */ + +static void +remote_async_terminal_inferior (void) +{ + /* FIXME: cagney/1999-09-27: Shouldn't need to test for + sync_execution here. This function should only be called when + GDB is resuming the inferior in the forground. A background + resume (``run&'') should leave GDB in control of the terminal and + consequently should not call this code. */ + if (!sync_execution) + return; + /* FIXME: cagney/1999-09-27: Closely related to the above. Make + calls target_terminal_*() idenpotent. The event-loop GDB talking + to an asynchronous target with a synchronous command calls this + function from both event-top.c and infrun.c/infcmd.c. Once GDB + stops trying to transfer the terminal to the target when it + shouldn't this guard can go away. */ + if (!remote_async_terminal_ours_p) + return; + delete_file_handler (input_fd); + remote_async_terminal_ours_p = 0; + initialize_sigint_signal_handler (); + /* NOTE: At this point we could also register our selves as the + recipient of all input. Any characters typed could then be + passed on down to the target. */ +} + +static void +remote_async_terminal_ours (void) +{ + /* See FIXME in remote_async_terminal_inferior. */ + if (!sync_execution) + return; + /* See FIXME in remote_async_terminal_inferior. */ + if (remote_async_terminal_ours_p) + return; + cleanup_sigint_signal_handler (NULL); + add_file_handler (input_fd, stdin_event_handler, 0); + remote_async_terminal_ours_p = 1; +} + /* If nonzero, ignore the next kill. */ int kill_kludge; @@ -2473,7 +2524,11 @@ remote_async_wait (pid, status) if (!SERIAL_IS_ASYNC_P (remote_desc)) ofunc = signal (SIGINT, remote_interrupt); - getpkt ((char *) buf, 1); + /* FIXME: cagney/1999-09-27: If we're in async mode we should + _never_ wait for ever -> test on target_is_async_p(). + However, before we do that we need to ensure that the caller + knows how to take the target into/out of async mode. */ + getpkt ((char *) buf, wait_forever_enabled_p); if (!SERIAL_IS_ASYNC_P (remote_desc)) signal (SIGINT, ofunc); @@ -3832,7 +3887,7 @@ extended_remote_async_create_inferior (exec_file, args, env) /* If running asynchronously, register the target file descriptor with the event loop. */ - if (async_p && SERIAL_CAN_ASYNC_P (remote_desc)) + if (event_loop_p && SERIAL_CAN_ASYNC_P (remote_desc)) SERIAL_ASYNC (remote_desc, inferior_event_handler, 0); /* Now restart the remote server. */ @@ -4673,6 +4728,9 @@ remote_cisco_open (name, from_tty) "To open a remote debug connection, you need to specify what \n\ device is attached to the remote system (e.g. host:port)."); + /* See FIXME above */ + wait_forever_enabled_p = 1; + target_preopen (from_tty); unpush_target (&remote_cisco_ops); @@ -5010,6 +5068,26 @@ Specify the serial device it is connected to (e.g. host:2020)."; remote_cisco_ops.to_magic = OPS_MAGIC; } +static int +remote_can_async_p (void) +{ + /* We're async whenever the serial device is. */ + return SERIAL_CAN_ASYNC_P (remote_desc); +} + +static int +remote_is_async_p (void) +{ + /* We're async whenever the serial device is. */ + return SERIAL_IS_ASYNC_P (remote_desc); +} + +static void +remote_async (void (*callback) (int error, void *context, int fd), void *context) +{ + SERIAL_ASYNC (remote_desc, callback, context); +} + /* Target async and target extended-async. This are temporary targets, until it is all tested. Eventually @@ -5036,6 +5114,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_files_info = remote_files_info; remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint; remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior; + remote_async_ops.to_terminal_ours = remote_async_terminal_ours; remote_async_ops.to_kill = remote_async_kill; remote_async_ops.to_load = generic_load; remote_async_ops.to_mourn_inferior = remote_async_mourn; @@ -5051,7 +5131,9 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_has_registers = 1; remote_async_ops.to_has_execution = 1; remote_async_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */ - remote_async_ops.to_has_async_exec = 1; + remote_async_ops.to_can_async_p = remote_can_async_p; + remote_async_ops.to_is_async_p = remote_is_async_p; + remote_async_ops.to_async = remote_async; remote_async_ops.to_magic = OPS_MAGIC; } diff --git a/gdb/remote.h b/gdb/remote.h index d67f7a5..3530e89 100644 --- a/gdb/remote.h +++ b/gdb/remote.h @@ -43,11 +43,6 @@ extern int putpkt (char *buf); extern void remote_console_output PARAMS ((char *)); -/* FIXME: cagney/1999-09-20: This function is going to be replaced - with a more generic (non remote specific) mechanism. */ - -extern void cleanup_sigint_signal_handler (void); - /* FIXME: cagney/1999-09-20: The remote cisco stuff in remote.c needs to be broken out into a separate file (remote-cisco.[hc]?). Before that can happen, a remote protocol stack framework needs to be diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c index abd5362..6554f69 100644 --- a/gdb/rs6000-nat.c +++ b/gdb/rs6000-nat.c @@ -755,28 +755,9 @@ xcoff_relocate_core (target) add our sections to the section table for the core target. */ if (vp != vmap) { - int count; struct section_table *stp; - int update_coreops; - - /* We must update the to_sections field in the core_ops structure - now to avoid dangling pointer dereferences. */ - update_coreops = core_ops.to_sections == target->to_sections; - - count = target->to_sections_end - target->to_sections; - count += 2; - target->to_sections = (struct section_table *) - xrealloc (target->to_sections, - sizeof (struct section_table) * count); - target->to_sections_end = target->to_sections + count; - - /* Update the to_sections field in the core_ops structure - if needed. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } + + target_resize_to_sections (target, 2); stp = target->to_sections_end - 2; stp->bfd = vp->bfd; diff --git a/gdb/solib.c b/gdb/solib.c index 7f2f8ca..d719837 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -1174,7 +1174,7 @@ solib_add (arg_string, from_tty, target) #endif SVR4_SHARED_LIBS - if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL) + if ((re_err = re_comp (arg_string? arg_string : ".")) != NULL) { error ("Invalid regexp: %s", re_err); } @@ -1196,38 +1196,9 @@ solib_add (arg_string, from_tty, target) if (count) { - int update_coreops; - - /* We must update the to_sections field in the core_ops structure - here, otherwise we dereference a potential dangling pointer - for each call to target_read/write_memory within this routine. */ - update_coreops = core_ops.to_sections == target->to_sections; - - /* Reallocate the target's section table including the new size. */ - if (target->to_sections) - { - old = target->to_sections_end - target->to_sections; - target->to_sections = (struct section_table *) - xrealloc ((char *) target->to_sections, - (sizeof (struct section_table)) * (count + old)); - } - else - { - old = 0; - target->to_sections = (struct section_table *) - xmalloc ((sizeof (struct section_table)) * count); - } - target->to_sections_end = target->to_sections + (count + old); - - /* Update the to_sections field in the core_ops structure - if needed. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } - + /* Add these section table entries to the target's table. */ + old = target_resize_to_sections (target, count); while ((so = find_solib (so)) != NULL) { if (so->so_name[0]) diff --git a/gdb/somsolib.c b/gdb/somsolib.c index 924fa52..65793bd 100644 --- a/gdb/somsolib.c +++ b/gdb/somsolib.c @@ -375,49 +375,11 @@ som_solib_load_symbols (so, name, from_tty, text_addr, target) if (status != 0) { int old, new; - int update_coreops; - int update_execops; - - /* We must update the to_sections field in the core_ops structure - here, otherwise we dereference a potential dangling pointer - for each call to target_read/write_memory within this routine. */ - update_coreops = core_ops.to_sections == target->to_sections; - - /* Ditto exec_ops (this was a bug). - */ - update_execops = exec_ops.to_sections == target->to_sections; new = so->sections_end - so->sections; - /* Add sections from the shared library to the core target. */ - if (target->to_sections) - { - old = target->to_sections_end - target->to_sections; - target->to_sections = (struct section_table *) - xrealloc ((char *) target->to_sections, - ((sizeof (struct section_table)) * (old + new))); - } - else - { - old = 0; - target->to_sections = (struct section_table *) - xmalloc ((sizeof (struct section_table)) * new); - } - target->to_sections_end = (target->to_sections + old + new); - - /* Update the to_sections field in the core_ops structure - if needed, ditto exec_ops. */ - if (update_coreops) - { - core_ops.to_sections = target->to_sections; - core_ops.to_sections_end = target->to_sections_end; - } - - if (update_execops) - { - exec_ops.to_sections = target->to_sections; - exec_ops.to_sections_end = target->to_sections_end; - } - + + old = target_resize_to_sections (target, new); + /* Copy over the old data before it gets clobbered. */ memcpy ((char *) (target->to_sections + old), so->sections, diff --git a/gdb/target.c b/gdb/target.c index fc1f64b..01e01c2 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -450,6 +450,9 @@ cleanup_target (t) de_fault (to_pid_to_exec_file, (char *(*)PARAMS ((int))) return_zero); de_fault (to_core_file_to_sym_file, (char *(*)PARAMS ((char *))) return_zero); + de_fault (to_can_async_p, (int (*) (void)) return_zero); + de_fault (to_is_async_p, (int (*) (void)) return_zero); + de_fault (to_async, (void (*) (void (*) (int, void*, int), void*)) tcomplain); #undef de_fault } @@ -541,9 +544,11 @@ update_current_target () INHERIT (to_has_registers, t); INHERIT (to_has_execution, t); INHERIT (to_has_thread_control, t); - INHERIT (to_has_async_exec, t); INHERIT (to_sections, t); INHERIT (to_sections_end, t); + INHERIT (to_can_async_p, t); + INHERIT (to_is_async_p, t); + INHERIT (to_async, t); INHERIT (to_magic, t); #undef INHERIT @@ -1113,6 +1118,56 @@ return_one () return 1; } +/* + * Resize the to_sections pointer. Also make sure that anyone that + * was holding on to an old value of it gets updated. + * Returns the old size. + */ + +int +target_resize_to_sections (struct target_ops *target, int num_added) +{ + struct target_ops **t; + struct section_table *old_value; + int old_count; + + old_value = target->to_sections; + + if (target->to_sections) + { + old_count = target->to_sections_end - target->to_sections; + target->to_sections = (struct section_table *) + xrealloc ((char *) target->to_sections, + (sizeof (struct section_table)) * (num_added + old_count)); + } + else + { + old_count = 0; + target->to_sections = (struct section_table *) + xmalloc ((sizeof (struct section_table)) * num_added); + } + target->to_sections_end = target->to_sections + (num_added + old_count); + + /* Check to see if anyone else was pointing to this structure. + If old_value was null, then no one was. */ + + if (old_value) + { + for (t = target_structs; t < target_structs + target_struct_size; + ++t) + { + if ((*t)->to_sections == old_value) + { + (*t)->to_sections = target->to_sections; + (*t)->to_sections_end = target->to_sections_end; + } + } + } + + return old_count; + +} + /* Find a single runnable target in the stack and return it. If for some reason there is more than one, return NULL. */ diff --git a/gdb/target.h b/gdb/target.h index e038802..5439fac 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -397,11 +397,14 @@ struct target_ops int to_has_registers; int to_has_execution; int to_has_thread_control; /* control thread execution */ - int to_has_async_exec; struct section_table *to_sections; struct section_table *to_sections_end; + /* ASYNC target controls */ + int (*to_can_async_p) (void); + int (*to_is_async_p) (void); + void (*to_async) (void (*cb) (int error, void *context, int fd), void *context); int to_magic; /* Need sub-structure for target machine related rather than comm related? */ }; @@ -1009,9 +1012,14 @@ print_section_info PARAMS ((struct target_ops *, bfd *)); #define target_can_switch_threads \ (current_target.to_has_thread_control & tc_switch) -/* Does the target support asynchronous execution? */ -#define target_has_async \ - (current_target.to_has_async_exec) +/* Can the target support asynchronous execution? */ +#define target_can_async_p() (current_target.to_can_async_p ()) + +/* Is the target in asynchronous execution mode? */ +#define target_is_async_p() (current_target.to_is_async_p()) + +/* Put the target in async mode with the specified callback function. */ +#define target_async(CALLBACK,CONTEXT) (current_target.to_async((CALLBACK), (CONTEXT))) extern void target_link PARAMS ((char *, CORE_ADDR *)); @@ -1266,6 +1274,9 @@ extern struct target_ops *find_run_target PARAMS ((void)); extern struct target_ops * find_core_target PARAMS ((void)); + +int +target_resize_to_sections PARAMS ((struct target_ops *target, int num_added)); /* Stuff that should be shared among the various remote targets. */ @@ -417,6 +417,12 @@ void (*create_breakpoint_hook) PARAMS ((struct breakpoint * bpt)); void (*delete_breakpoint_hook) PARAMS ((struct breakpoint * bpt)); void (*modify_breakpoint_hook) PARAMS ((struct breakpoint * bpt)); +/* Called as appropriate to notify the interface that we have attached + to or detached from an already running process. */ + +void (*attach_hook) PARAMS ((void)); +void (*detach_hook) PARAMS ((void)); + /* Called during long calculations to allow GUI to repair window damage, and to check for stop buttons, etc... */ @@ -471,7 +477,7 @@ PARAMS ((void)) ATTR_NORETURN; loop, but can be caught via catch_errors. */ NORETURN void - return_to_top_level (reason) +return_to_top_level (reason) enum return_reason reason; { quit_flag = 0; @@ -483,8 +489,10 @@ PARAMS ((void)) ATTR_NORETURN; disable_current_display (); do_cleanups (ALL_CLEANUPS); - if (async_p && target_has_async) + if (event_loop_p && target_can_async_p ()) do_exec_cleanups (ALL_CLEANUPS); + if (event_loop_p && sync_execution) + do_exec_error_cleanups (ALL_CLEANUPS); if (annotation_level > 1) switch (reason) @@ -688,7 +696,7 @@ gdb_init (argv0) not the async version is run. NOTE: in the future we plan to make the event loop be the default engine of gdb, and this difference will disappear. */ - if (async_p) + if (event_loop_p) async_init_signals (); else init_signals (); @@ -1275,7 +1283,7 @@ execute_command (p, from_tty) /* If the target is running, we allow only a limited set of commands. */ - if (async_p && target_has_async && target_executing) + if (event_loop_p && target_can_async_p () && target_executing) if (!strcmp (c->name, "help") && !strcmp (c->name, "pwd") && !strcmp (c->name, "show") @@ -2100,7 +2108,7 @@ command_line_input (prompt_arg, repeat, annotation_suffix) #ifdef STOP_SIGNAL if (job_control) { - if (async_p) + if (event_loop_p) signal (STOP_SIGNAL, handle_stop_sig); else signal (STOP_SIGNAL, stop_sig); @@ -2965,7 +2973,7 @@ get_prompt_1 (formatted_prompt) { char *local_prompt; - if (async_p) + if (event_loop_p) local_prompt = PROMPT (0); else local_prompt = gdb_prompt_string; @@ -3201,7 +3209,7 @@ get_prompt () else { /* Prompt could not be formatted. */ - if (async_p) + if (event_loop_p) return PROMPT (0); else return gdb_prompt_string; @@ -3217,7 +3225,7 @@ set_prompt (s) if (prompt != NULL) free (prompt); */ - if (async_p) + if (event_loop_p) PROMPT (0) = savestring (s, strlen (s)); else gdb_prompt_string = savestring (s, strlen (s)); @@ -3789,7 +3797,7 @@ init_main () /* If we are running the asynchronous version, we initialize the prompts differently. */ - if (!async_p) + if (!event_loop_p) { gdb_prompt_string = savestring (DEFAULT_PROMPT, strlen (DEFAULT_PROMPT)); } @@ -3862,7 +3870,7 @@ until the next time it is started.", &cmdlist); async version is run. NOTE: this difference is going to disappear as we make the event loop be the default engine of gdb. */ - if (!async_p) + if (!event_loop_p) { add_show_from_set (add_set_cmd ("prompt", class_support, var_string, @@ -3938,7 +3946,7 @@ hitting return."); /* The set editing command is different depending whether or not the async version is run. NOTE: this difference is going to disappear as we make the event loop be the default engine of gdb. */ - if (!async_p) + if (!event_loop_p) { add_show_from_set (add_set_cmd ("editing", class_support, var_boolean, (char *) &command_editing_p, @@ -4062,7 +4070,7 @@ from the target.", &setlist), the async version is run. NOTE: this difference is going to disappear as we make the event loop be the default engine of gdb. */ - if (!async_p) + if (!event_loop_p) { c = add_set_cmd ("annotate", class_obscure, var_zinteger, (char *) &annotation_level, "Set annotation_level.\n\ @@ -4081,7 +4089,7 @@ from the target.", &setlist), add_show_from_set (c, &showlist); c->function.sfunc = set_async_annotation_level; } - if (async_p) + if (event_loop_p) { add_show_from_set (add_set_cmd ("exec-done-display", class_support, var_boolean, (char *) &exec_done_display_p, diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 0317e21..6b0be60 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -842,7 +842,7 @@ read_actions (t) #ifdef STOP_SIGNAL if (job_control) { - if (async_p) + if (event_loop_p) signal (STOP_SIGNAL, handle_stop_sig); else signal (STOP_SIGNAL, stop_sig); diff --git a/gdb/utils.c b/gdb/utils.c index feba764..6001501 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -84,6 +84,8 @@ static struct cleanup *cleanup_chain; /* cleaned up after a failed command */ static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */ static struct cleanup *run_cleanup_chain; /* cleaned up on each 'run' */ static struct cleanup *exec_cleanup_chain; /* cleaned up on each execution command */ +/* cleaned up on each error from within an execution command */ +static struct cleanup *exec_error_cleanup_chain; /* Pointer to what is left to do for an execution command after the target stops. Used only in asynchronous mode, by targets that @@ -181,6 +183,14 @@ make_exec_cleanup (function, arg) return make_my_cleanup (&exec_cleanup_chain, function, arg); } +struct cleanup * +make_exec_error_cleanup (function, arg) + void (*function) PARAMS ((PTR)); + PTR arg; +{ + return make_my_cleanup (&exec_error_cleanup_chain, function, arg); +} + static void do_freeargv (arg) void *arg; @@ -245,6 +255,13 @@ do_exec_cleanups (old_chain) } void +do_exec_error_cleanups (old_chain) + register struct cleanup *old_chain; +{ + do_my_cleanups (&exec_error_cleanup_chain, old_chain); +} + +void do_my_cleanups (pmy_chain, old_chain) register struct cleanup **pmy_chain; register struct cleanup *old_chain; @@ -276,6 +293,13 @@ discard_final_cleanups (old_chain) } void +discard_exec_error_cleanups (old_chain) + register struct cleanup *old_chain; +{ + discard_my_cleanups (&exec_error_cleanup_chain, old_chain); +} + +void discard_my_cleanups (pmy_chain, old_chain) register struct cleanup **pmy_chain; register struct cleanup *old_chain; @@ -1487,7 +1511,7 @@ prompt_for_continue () ++p; if (p[0] == 'q') { - if (!async_p) + if (!event_loop_p) request_quit (SIGINT); else async_request_quit (0); |