diff options
author | Jason Molenda <jsm@bugshack.cygnus.com> | 1999-09-22 03:28:34 +0000 |
---|---|---|
committer | Jason Molenda <jsm@bugshack.cygnus.com> | 1999-09-22 03:28:34 +0000 |
commit | 3f58899ae80421eb6d2ed3d0d2329986f6e77c66 (patch) | |
tree | ef3cd06b12eee7b8d002704a5cf4fecea06a643d | |
parent | ff49b98273f2bad8ff6ec338eee32c6d90113d05 (diff) | |
download | gdb-3f58899ae80421eb6d2ed3d0d2329986f6e77c66.tar.gz |
import gdb-1999-09-21
74 files changed, 2896 insertions, 1908 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4e5e353cd3f..278bdf07940 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,527 @@ +Tue Sep 21 14:55:29 1999 Andrew Cagney <cagney@b1.cygnus.com> + + From 1999-08-20 J.T. Conklin <jtc@redback.com>: + * remote.c (read_frame): expand cisco run-length encoding variant + inline as is done for the standard encoding. + (remote_cisco_expand): Removed. + +1999-09-20 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-loop.c: Include <sys/time.h>. + +1999-09-20 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * ser-ocd.c: (ser_ocd_open, ser_ocd_raw, ser_ocd_readchar, + ser_ocd_setbaudrate, ser_ocd_write, ser_ocd_close, + ser_ocd_get_tty_state, ser_ocd_set_tty_state): Remove unused + prototypes. + (ocd_readremote): Remove. + (ocd_write): Remove unused var 'c'. + +1999-09-20 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-top.c (change_line_handler): Cleanup dead code. Add comments. + * event-loop.c: Cleanup #if 0 code. + + * event-loop.h (timer_handler_func): New function type. + (create_timer): Export function. + (delete_timer): Export function. + + * event-loop.c: Add timeout and timeout_valid fields to + gdb_notifier. New structures gdb_timer and timer_list. + (gdb_do_one_event): Check whether there are any timers tht are + ready, before going to wait. + (gdb_wait_for_event): If the timeout structure is meaningful, pass + that to select()/poll(). + (create_timer): New function. Creates a timer. + (delete_timer): New function. Deletes a timer. + (handle_timer_event): New function. Deals with timers that are ready. + (poll_timers): New Function. Chack whether timers have expired. + +Mon Sep 20 17:00:06 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.c (getpkt, putpkt, remote_console_output): Move + declaration from here. + * remote.h: To here. New file. + * tracepoint.c(putpkt, getpkt, remote_console_output): Delete + declarations. Moved to "remote.h". + * Makefile.in (remote_h): Define. + * remote.c, tracepoint.c: Include "remote.h". + * Makefile.in (tracepoint.o, remote.o): Add dependency on + "remote.h". + + * remote.h (remote_cisco_objfile_relocate, + cleanup_sigint_signal_handler): Add declaration. Include FIXME. + * infrun.c: Include "remote.h". + (complete_execution): Delete local extern declaration + of ``cleanup_sigint_signal_handler''. + * Makefile.in (infrun.o): Add dependency on remote.h. + +Mon Sep 20 13:41:04 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * kod.c (ecos_kod_open, ecos_kod_request, ecos_kod_close, + cisco_kod_open, cisco_kod_request, cisco_kod_close): Move + declarations from here. + * kod.h: To here. New file. + * kod-cisco.c, kod.c: Include "kod.h". + * Makefile.in (kod-cisco.o, kod.o): Add dependency on "kod.h". + + * kod.h (kod_display_callback_ftype, kod_query_callback_ftype): + New function types. + * kod.h (kod_cisco_open): Use in declaration. + * kod.c (gdb_kod_open): Update definition. + * kod-cisco.c (cisco_kod_open): Update definition. + +Mon Sep 20 12:13:27 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * mn10300-tdep.c (_initialize_mn10300_tdep): Add declaration. + + * breakpoint.c (until_break_command_continuation): Add + declaration. Make static. + * event-top.c (rl_callback_read_char_wrapper): Ditto. + +Fri Sep 17 19:28:17 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * source.c: Include "source.h". + (open_source_file, find_source_lines): Move declaration from here. + * source.h: New file. To here. + * Makefile.in (source.o): Add dependency on source.h. + + * breakpoints.c (delete_command): Move declaration from here. + * breakpoints.h (delete_command): To here. + +1999-09-18 Jim Blandy <jimb@cris.red-bean.com> + + * hppa-tdep.c (in_solib_call_trampoline): If we can't recognize + the instruction we're at, we're not in a stub. + +Sat Sep 18 07:13:03 1999 Jeffrey A Law (law@cygnus.com) + + * dwarf2read.c (dwarf_decode_lines): Correctly handle + DW_LNS_const_add_pc. + +1999-09-18 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * remote.c (remote_async_open_1): Use inferior_event_handler to + handle inferior events. + (extended_remote_async_create_inferior): Ditto. + + * serial.h (serial_event_ftype): Add two pars. + + * ser-unix.c (ser_unix_event): Add two parameters, error and fd. + Pass those into the call to the actual inferior event handler. + + * infrun.c (complete_execution): Stdin handler is stdin_event_handler. + + * event-top.h (stdin_event_handler): Export new function. + + * event-top.c (stdin_event_handler): New function. Smarter handler + for events on stdin. + (change_line_handler): Don't need to update the handler for stdin + here anymore. + (_initialize_event_loop): Stdin handler is now stdin_event_handler. + + * event-loop.h: (handler_func): Change signature, adding two new + args. + (sig_handler_func): New function type. It is the old handler_func. + (create_async_signal_handler): Update to use sig_handler_func. + (delete_async_signal_handler): Prototype for new function. + + * event-loop.c: Include "inferior.h". + (struct file_handler): Add field error, to indicate error + condition on fd. + (struct async_signal_handler): Rename type of proc field. + (add_file_handler): Add exception condition as something select() + should report. + (handle_file_event): In case of error on the fd, record this in + the file_handler structure. Update call to (*proc)() to match new + signature. + (gdb_wait_for_event): If select() or poll() return error, report + this to user. + (create_async_signal_handler): Change first param type to + sig_handler_func*. + (inferior_event_handler): New function. Smarter inferior event + handling. + +1999-09-18 Jim Blandy <jimb@cris.red-bean.com> + + * pa64solib.c (pa64_solib_create_inferior_hook): Remove code which + tries to set __d_pid; it's not relevant to PA64 shared libraries. + + A psymtab's texthigh element, and a block's endaddr element, are + the address past the end of the address range, never the address + of the last byte. These data structures mean the same thing on + forty different architectures; there's no reason they should be + different on HP/UX. + * symtab.c (find_pc_sect_psymtab): Remove special case for HP/UX. + (find_pc_sect_symtab): Same. + * objfiles.c (find_pc_sect_section): Same. + +Sat Sep 18 07:13:03 1999 Jeffrey A Law (law@cygnus.com) + + * hppa-tdep.c (internalize_unwinds): Handle PA64 shared libraries + correctly + + * hppa-tdep.c (in_solib_call_trampoline): Handle PA64 shared library + trampolines. + +1999-09-17 Jim Blandy <jimb@zwingli.cygnus.com> + + * breakpoint.c (permanent_breakpoint_here_p): Delete. + Accidentally left over from previous changes. + +1999-09-17 Jim Blandy <jimb@cris.red-bean.com> + + * config/pa/tm-hppa64.h (ARGS_GROW_DOWNWARD): Deleted. There are + many more differences between the 32- and 64-bit ABI's than the + direction the arguments grow, so this name is misleading. + (PA20W_CALLING_CONVENTIONS): Define this instead. + * config/pa/tm-hppa.h (ARGS_GROW_DOWNWARD): Delete. + * hppa-tdep.c (hppa_push_arguments): Split into two separate + functions, depending on whether PA20W_CALLING_CONVENTIONS is + #defined. These implement completely separate specifications, + they don't really share that much code anyway, and this is much + more readable. Specifically: leave a 16-byte, not 32-byte, frame + marker; correctly align objects larger than eight bytes; promote + all integral scalar arguments smaller than eight bytes to a full + register width; pad aggregates smaller than eight bytes on the + right. + +Thu Sep 16 17:33:35 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.c (remote_async_open_1): Use SERIAL_ASYNC to + enable/disable async event callback on serial port. Use + SERIAL_CAN_ASYNC_P / SERIAL_IS_ASYNC_P to determine if / when + async mode. + (remote_async_resume, remote_async_detach, remote_async_kill, + extended_remote_async_create_inferior, remote_async_wait): Ditto. + + * ser-unix.c (hardwire_readchar): When ASYNC, only read a single + character. + (ser_unix_readchar): Ditto. Problems occure with back-to-back + data from a target. The ASYNC code can loose the second data + chunk. + + * serial.c (serial_fdopen): Initialize async_handler and + async_context. + +1999-09-16 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * utils.c (discard_all_continuations): New function. + * defs.h: (discard_all_continuations): Add prototype. + +1999-09-16 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * valops.c: Remove prototype for search_struct_field_aux(). THe + function was nowhere in the file. + (value_ind): Remove unused var real_val. + (value_find_oload_method_list): Remove unused var v. + (find_overload_match): Remove extra declaration of var jj. + + * Makefile.in (event_top_h): Define. Add dependency on this for + every file that includes event-top.h. + +Thu Sep 16 17:33:35 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * serial.c (serial_open): Delete ``&'' device. + * ser-unix.c (_initialize_ser_hardwire): Make the "hardwire" + device async. Delete temporary "async-hardwire" device. + +Thu Sep 16 16:27:13 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * serial.h (SERIAL_IS_ASYNC_P): Define. Non-zero when serial + device is in async mode. + (SERIAL_CAN_ASYNC_P): Rename SERIAL_ASYNC_P. + * serial.c (serial_is_async_p): Implement. + (serial_can_async_p): Rename serial_async_p. + (serial_open): Initialize ASYNC_HANDLER and ASYNC_CONTEXT. Save + the original name in SCB instead of the stripped name. + +Thu Sep 16 12:20:11 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * serial.h (struct serial_ops): Add field ASYNC. + (SERIAL_ASYNC, SERIAL_ASYNC_P): New macros. + (struct _serial_t): Add fields async_context and async_handler. + * serial.c (serial_async, serial_async_p): Implement. + + * ser-unix.c: Include "event-loop.h". + (ser_unix_async), ser-unix.c: New function. Implement async mode. + (async_event): Handle async events. + * ser-unix.c (_initialize_ser_hardwire), ser-tcp.c + (_initialize_ser_tcp), ser-pipe.c (_initialize_ser_pipe): Enable + ASYNC. + + * serial.c (serial_open): Discard leading ``|'' before opening a + pipe device. + * ser-pipe.c (pipe_open): Adjust. + * serial.c (serial_open): Add ``&'' prefix so that + "async-hardwire" device can be explicitly selected. Work in + progress. + * ser-unix.c: Register "async-hardwire" device. + +Thu Sep 16 09:04:53 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * ser-unix.h: New file. Declare generic ser_unix functions. + * ser-unix.c (ser_unix_nop_get_tty_state, + ser_unix_nop_set_tty_state, ser_unix_nop_raw, ser_unix_wait_for, + ser_unix_readchar, ser_unix_nop_noflush_set_tty_state, + ser_unix_nop_print_tty_state, ser_unix_nop_setbaudrate, + ser_unix_nop_setstopbits, ser_unix_write, + ser_unix_nop_flush_output, ser_unix_nop_flush_input, + ser_unix_nop_send_break, ser_unix_nop_drain_output): New + functions. + * ser-unix.c: Include <sys/wait.h>, <sys/socket.h>, + "gdb_string.h". + + * ser-tcp.c (_initialize_ser_tcp), ser-unix.c + (_initialize_ser_hardwire), ser-pipe.c (_initialize_ser_tcp): + Initialize ops vector using assignment. + + * ser-pipe.c, ser-tcp.c, ser-unix.c: Include ser-unix.h. + + * ser-pipe.c (pipe_get_tty_state, pipe_set_tty_state, + pipe_return_0, pipe_raw, wait_for, pipe_readchar, + pipe_noflush_set_tty_state, pipe_print_tty_state, + pipe_setbaudrate, pipe_setstopbits, pipe_write), ser-tcp.c + (tcp_get_tty_state, tcp_set_tty_state, tcp_return_0, tcp_raw, + wait_for, tcp_readchar, tcp_noflush_set_tty_state, + tcp_print_tty_state, tcp_setbaudrate, tcp_setstopbits, tcp_write): + Delete functions. + +1999-09-15 Stan Shebs <shebs@andros.cygnus.com> + + * d10v-tdep.c (remote_d10v_translate_xfer_address): Move to here + from remote-d10v.c, also change the memory translation to its + previous version. + * remote-d10v.c: Remove. + * config/d10v/d10v.mt (TDEPFILES): Remove remote-d10v.o. + +1999-09-15 Jim Blandy <jimb@cris.red-bean.com> + + * breakpoint.c (remove_breakpoint): Return zero, not nothing. + +1999-09-14 Jim Blandy <jimb@cris.red-bean.com> + + * hppa-tdep.c (frame_chain): If the unwind info says we've saved + r3, don't trust it. Call get_frame_saved_regs and see if we can + actually find an address for r3 there. + + * pa64solib.c (pa64_sharedlibrary_info_command): Text fix. + +Tue Sep 14 14:34:28 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * serial.h (DEPRECATED_SERIAL_FD): Define. + * serial.c (deprecated_serial_fd): New function. + + * remote.c (remote_async_open_1, remote_async_open_1, + remote_async_detach, remote_async_kill, + extended_remote_async_create_inferior, minitelnet): Update. + * remote-es.c (es1800_open, es1800_close, es1800_transparent): Update. + + * remote-st.c (connect_command), remote-os9k.c (connect_command): + Fix. Call FD_SET et.al. with FD instead of serial_t. + +1999-09-14 Jim Blandy <jimb@cris.red-bean.com> + + * hppa-tdep.c (hppa_frame_find_saved_regs): The two possible + instructions for saving the return pointer (32- and 64-bit) save + it at different offsets. + + * config/pa/tm-hppa64.h: Doc fix. + + * defs.h (continuation): Make this a typedef. + + * Makefile.in (gdbtk.o, gdbtk-cmds.o): Depend on $(top_h). + + * Makefile.in (i386-linux-nat.o): Depend on symfile.h, not + $(symfile_h); the latter has no definition. + + * breakpoint.c (breakpoint_here_p): Remove meaningless code, + testing b->enable against shlib_disabled and call_disabled after + we know it is enabled. + + Implement "permanent breakpoints" --- breakpoints that are + hardwired into the inferior's code. GDB knows they're there, but + doesn't try to insert or remove them, etc. + * breakpoint.h (enum enable): Add `permanent' enablement state. + * breakpoint.c (make_breakpoint_permanent): New function. + * breakpoint.h (make_breakpoint_permanent): Add declaration. + * breakpoint.c (insert_breakpoints): Don't bother to insert + permanent breakpoints... + (remove_breakpoint): ... or remove them. + (breakpoint_here_p): Handle `permanent' like `enabled'. Change + return value to indicate whether it's a permanent breakpoint here, + or an ordinary breakpoint. + * breakpoint.h (enum breakpoint_here): New enum. + (breakpoint_here_p): Change declaration. + * breakpoint.h (breakpoint_1): Extend bpenables to cover all the + enablement states. + (describe_other_breakpoints): Describe permanent breakpoints. + (check_duplicates): If one of the breakpoints at ADDRESS is a + permanent breakpoint, treat all the others as the duplicates, so + we don't try to insert or remove any of them. Verify that only + the permanent breakpoint is actually inserted. + (delete_breakpoint): Complain if we discover that another + breakpoint was inserted at the same place as a permanent + breakpoint. + (disable_breakpoint): Fail silently if asked to disable a + permanent breakpoint. + (do_enable_breakpoint): Don't change a permanent breakpoint's + enablement to ordinary `enabled'. Leave it alone. + (create_solib_event_breakpoint): Return the + breakpoint object created. + * breakpoint.h (create_solib_event_breakpoint): Fix declaration. + * pa64solib.c (pa64_solib_create_inferior_hook): Do turn on the + DT_HP_DEBUG_CALLBACK flag in the dynamic linker, so it will call + __dld_break, which contains the permanent breakpoint, when interesting + things happen. Tell GDB that the breakpoint in __dld_break is + permanent. + * gdbtk-cmds.c (gdb_get_breakpoint_info): Report a permanent + breakpoint as enabled. + * infrun.c (SKIP_PERMANENT_BREAKPOINT): Provide default definition. + (default_skip_permanent_breakpoint): New function. + (resume): If we're trying to resume at a permanent breakpoint, use + SKIP_PERMANENT_BREAKPOINT to step over it. + * hppa-tdep.c (hppa_skip_permanent_breakpoint): New function. + * config/pa/tm-hppa.h (hppa_skip_permanent_breakpoint): Declare. + (SKIP_PERMANENT_BREAKPOINT): Define. + +1999-09-14 Kevin Buettner <kevinb@cygnus.com> + + * symtab.h, minsyms.c (find_stab_function_addr): Changed + type of second parameter from partial_symtab * to char *. + Fixed all callers. + * minsyms.c (find_stab_function_addr): Look for minimal + symbol without filename if filename based search fails. + * dbxread.c (process_one_symbol): Call find_stab_function_addr() + in place of inline code with identical functionality. + * partial-stab.h (case N_FUN, descriptors 'F' and 'f'): Look + up symbol's address from minimal symbol table when N_FUN + address is missing. Also, make sure this value is used for + calculating the value of the texthigh field. + +1999-09-14 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-loop.c (create_file_handler): Increment the total number + of file descriptors for the poll case, only if this is a new file + desc. + +1999-09-14 Eli Zaretskii <eliz@is.elta.co.il> + + * go32-nat.c: misc minor cleanups and fixes missed in last patch. + +Tue Sep 14 12:37:33 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * serial.h (SERIAL_PRINT_TTY_STATE): Add STREAM parameter. + (union serial_ops): Update. + + * ser-unix.c (hardwire_print_tty_state, ser-tcp.c + (tcp_print_tty_state), ser-pipe.c (pipe_print_tty_state, + ser-go32.c (dos_print_tty_state, ser-mac.c (mac_print_tty_state, + ser-ocd.c (ocd_print_tty_state, ser-e7kpc.c + (e7000pc_print_tty_state): Update. + * inflow.c (child_terminal_info): Update. + * serial.c (serial_print_tty_state): Update. + +Tue Sep 14 11:41:37 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * serial.c, serial.h, ser-tcp.c, ser-unix.c, ser-pipe.c: Convert + all functions to ISO-C. + * serial.h, serial.c: Move all indirect macro function calls from + serial.h into serial.c. + (serial_drain_output, serial_flush_output, serial_flush_input, + serial_raw, serial_get_tty_state, serial_set_tty_state, + serial_print_tty_state, serial_noflush_set_tty_state, + serial_setbaudrate, serial_setstopbits): New functions. + (do_serial_close): Rename serial_close. + (serial_close, serial_un_fdopen): New functions. Call + do_serial_close. + +1999-09-13 James Ingham <jingham@leda.cygnus.com> + + * symtab.c (decode_line_1): Find the rightmost parenthesis in the + expression, not the leftmost. This allows us to parse function + declarations with embedded function prototypes. + +Mon Sep 13 18:39:31 1999 Jeffrey A Law (law@cygnus.com) + + * pa64solib.c (pa64_sharedlibrary_info_command): Fix typos. + +1999-09-13 Kevin Buettner <kevinb@cygnus.com> + + * i386-tdep.c (i386_extract_return_value): ifdef'd so that + non-linux targets will work again. + (i386_do_registers_info, i386_print_register): Revert changes + of 1999-09-03; these functions have been removed because they + are Linux specific and break non-Linux builds. This functionality + will be restored after FP support unification has been achieved. + * i387-tdep.c (i387_print_register, void i387_float_info): + Likewise. + * config/i386/tm-linux.h (i387_float_info, FLOAT_INFO, + DO_REGISTERS_INFO, i386_do_registers_info, + i387_print_register): Likewise. + +1999-09-13 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-top.c (call_readline): Change to accept gdb_client_data as + param. + (rl_callback_read_char_wrapper): New function to match what the + event loop expects and what readline expects. + (change_line_handler): Make call_readline point to + rl_callback_read_char_wrapper, instead of rl_callback_read_char. + (_initialize_event_loop): Ditto. + (gdb_readline2): Change parameter to gdb_client_data. + * event-top.h (call_readline, gdb_readline2): Change accordingly. + + * event-loop.c (add_file_handler): Change 2nd par to + handler_func*. No more need for casting. + * event-loop.h (create_async_signal_handler): Change accordingly. + + * inferior.h (fetch_inferior_event): Change parameter to void*. + * infrun.c (fetch_inferior_event): Ditto. + +1999-09-13 Stan Shebs <shebs@andros.cygnus.com> + + * infrun.c (step_into_function): New function, broken out from the + step_into_function label in handle_inferior_event. + (handle_inferior_event): Change a goto into a function call. + +1999-09-13 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * event-top.h: New file. All the exported vars and functions from + event-top.c. + + * event-loop.h (struct gdb_event, event_handler_func, + file_handler, async_signal_handler, SELECT_MASK, fd_mask, NBBY, + FD_SETSIZE, howmany, NFDBITS, MASK_SIZE): Move to event-loop.c. + (struct prompts, PROMPT, PREFIX, SUFFIX, display_gdb_prompt, + async_init_signals, set_async_editing_command, + set_async_annotation_level, set_async_prompt, handle_stop_sig, + handle_sigint, pop_prompt, push_prompt, gdb_readline2, + mark_async_signal_handler_wrapper, async_request_quit, + async_command_editing_p, exec_done_display_p, + async_annotation_suffix, new_async_prompt, the_prompts, + call_readline, input_handler, input_fd): Move to event-top.h. + (All function prototypes): Don't use PARAMS anymore. + + * event-loop.c: (struct gdb_event, event_handler_func, + file_handler, async_signal_handler, SELECT_MASK, fd_mask, NBBY, + FD_SETSIZE, howmany, NFDBITS, MASK_SIZE): Move to here from + event-loop.h. + Include event-top.h. Remove use of PARAMS. ANSIfy functions headers. + + * event-top.c: Include event-top.h. Include "signals.h", not + <signals.h>. + Remove use of PARAMS. ANSIfy functions headers. + (handle_stop_sig): move prototype to event-top.h. + + * remote.c: Include event-top.h. Make it understand + async_signal_handler type. + * infrun.c: Include event-top.h. + * mi-main.c: Ditto. + * top.c Ditto. + * utils.c: Ditto. + Mon Sep 13 18:54:05 1999 Andrew Cagney <cagney@b1.cygnus.com> * gdbarch.sh: Describe each of the fields. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index b1cd01e364f..a83add62778 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 = 19990913 +VERSION = 19990921 DIST=gdb LINT=/usr/5bin/lint @@ -454,8 +454,10 @@ top_h = top.h inferior_h = inferior.h $(breakpoint_h) tracepoint_h = tracepoint.h ax_h = ax.h -event_loop_h = event-loop.h -version_h = version.h +event_loop_h = event-loop.h +event_top_h = event-top.h +remote_h = remote.h +version_h = version.h # Header files that need to have srcdir added. Note that in the cases # where we use a macro like $(gdbcmd_h), things are carefully arranged @@ -1122,10 +1124,10 @@ eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \ $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \ gdb_string.h -event-loop.o: event-loop.c $(defs_h) $(top_h) $(event_loop_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) 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 @@ -1143,7 +1145,7 @@ fork-child.o: fork-child.c $(wait_h) $(defs_h) $(gdbcore_h) \ # to fix breakpoint.c's compiler warnings. tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(tracepoint_h) \ $(gdbtypes_h) $(expression_h) $(gdbcmd_h) $(value_h) target.h \ - language.h gdb_string.h $(readline_headers) + language.h gdb_string.h $(readline_headers) $(remote_h) $(CC) -c $(INTERNAL_WARN_CFLAGS) $(NO_WERROR_CFLAGS) $< gdbarch.o: gdbarch.c $(defs_h) $(bfd_h) $(gdbcmd_h) @@ -1217,7 +1219,8 @@ infptrace.o: infptrace.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \ gdb_string.h $(wait_h) $(command_h) infrun.o: infrun.c $(wait_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ - $(inferior_h) target.h gdbthread.h gdb_string.h $(event_loop_h) + $(inferior_h) target.h gdbthread.h gdb_string.h $(event_loop_h) \ + $(event_top_h) target.h inftarg.o: inftarg.c $(wait_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ target.h terminal.h $(command_h) @@ -1241,9 +1244,9 @@ jv-valprint.o: jv-valprint.c $(bfd_h) $(defs_h) $(symtab_h) $(gdbtypes_h) \ $(expression_h) $(value_h) $(INCLUDE_DIR)/demangle.h valprint.h \ language.h jv-lang.h c-lang.h gdbcore.h annotate.h -kod.o: kod.c $(defs_h) $(command_h) $(gdbcmd_h) target.h gdb_string.h +kod.o: kod.c $(defs_h) $(command_h) $(gdbcmd_h) target.h gdb_string.h kod.h -kod-cisco.o: kod-cisco.c $(defs_h) gdb_string.h +kod-cisco.o: kod-cisco.c $(defs_h) gdb_string.h kod.h language.o: language.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \ $(gdbcmd_h) $(gdbtypes_h) language.h parser-defs.h $(symtab_h) \ @@ -1504,7 +1507,7 @@ remote-utils.o: remote-utils.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ remote.o: remote.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \ $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h \ - $(event_loop_h) + $(event_loop_h) $(event_top_h) $(remote_h) remote-nrom.o: remote-nrom.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \ $(inferior_h) $(remote_utils_h) symfile.h terminal.h @@ -1533,11 +1536,11 @@ ser-mac.o: ser-mac.c $(defs_h) serial.h signals.h ser-ocd.o: ser-ocd.c $(defs_h) serial.h signals.h gdb_string.h -ser-pipe.o: ser-pipe.c $(defs_h) serial.h signals.h gdb_string.h +ser-pipe.o: ser-pipe.c $(defs_h) serial.h signals.h gdb_string.h ser-unix.h -ser-tcp.o: ser-tcp.c $(defs_h) serial.h signals.h gdb_string.h +ser-tcp.o: ser-tcp.c $(defs_h) serial.h signals.h gdb_string.h ser-unix.h -ser-unix.o: ser-unix.c $(defs_h) serial.h +ser-unix.o: ser-unix.c $(defs_h) serial.h ser-unix.h serial.o: serial.c $(defs_h) serial.h gdb_string.h @@ -1556,7 +1559,7 @@ solib.o: solib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ source.o: source.c $(defs_h) $(expression_h) $(frame_h) $(gdbcmd_h) \ $(gdbcore_h) language.h objfiles.h gnu-regex.h symfile.h $(symtab_h) \ - gdb_string.h + gdb_string.h source.h sparc-nat.o: sparc-nat.c $(bfd_h) $(defs_h) $(inferior_h) $(gdbcore_h) \ target.h @@ -1614,7 +1617,7 @@ thread.o: thread.c $(defs_h) gdbthread.h $(gdbcmd_h) target.h top.o: top.c top.h $(bfd_h) $(getopt_h) $(readline_headers) call-cmds.h \ $(defs_h) $(gdbcmd_h) $(inferior_h) language.h signals.h \ - $(remote_utils_h) gdb_string.h $(event_loop_h) $(version_h) + $(remote_utils_h) gdb_string.h $(event_loop_h) $(event_top_h) $(version_h) typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \ $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \ @@ -1628,7 +1631,7 @@ umax-xdep.o: umax-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h) utils.o: utils.c $(bfd_h) $(defs_h) $(expression_h) $(gdbcmd_h) \ language.h signals.h target.h terminal.h $(readline_headers) \ - gdb_string.h $(event_loop_h) + gdb_string.h $(event_loop_h) $(event_top_h) valarith.o: valarith.c $(bfd_h) $(defs_h) $(expression_h) \ $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \ diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index e61fab383e9..bccdeeef45e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -44,6 +44,8 @@ /* Prototypes for local functions. */ +static void until_break_command_continuation (struct continuation_arg *arg); + static void catch_command_1 PARAMS ((char *, int, int)); @@ -252,8 +254,6 @@ do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp)); if such is available. */ static int can_use_hw_watchpoints; -void delete_command PARAMS ((char *, int)); - void _initialize_breakpoint PARAMS ((void)); void set_breakpoint_count PARAMS ((int)); @@ -671,7 +671,10 @@ insert_breakpoints () ALL_BREAKPOINTS_SAFE (b, temp) { - if (b->type != bp_watchpoint + if (b->enable == permanent) + /* Permanent breakpoints cannot be inserted or removed. */ + continue; + else if (b->type != bp_watchpoint && b->type != bp_hardware_watchpoint && b->type != bp_read_watchpoint && b->type != bp_access_watchpoint @@ -1131,6 +1134,10 @@ remove_breakpoint (b, is) { int val; + if (b->enable == permanent) + /* Permanent breakpoints cannot be inserted or removed. */ + return 0; + if (b->type == bp_none) warning ("attempted to remove apparently deleted breakpoint #%d?", b->number); @@ -1144,7 +1151,6 @@ remove_breakpoint (b, is) && b->type != bp_catch_exec && b->type != bp_catch_catch && b->type != bp_catch_throw) - { if (b->type == bp_hardware_breakpoint) val = target_remove_hw_breakpoint (b->address, b->shadow_contents); @@ -1357,33 +1363,42 @@ breakpoint_init_inferior (context) } } -/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at - PC. When continuing from a location with a breakpoint, we actually - single step once before calling insert_breakpoints. */ +/* breakpoint_here_p (PC) returns non-zero if an enabled breakpoint + exists at PC. It returns ordinary_breakpoint_here if it's an + ordinary breakpoint, or permanent_breakpoint_here if it's a + permanent breakpoint. + - When continuing from a location with an ordinary breakpoint, we + actually single step once before calling insert_breakpoints. + - When continuing from a localion with a permanent breakpoint, we + need to use the `SKIP_PERMANENT_BREAKPOINT' macro, provided by + the target, to advance the PC past the breakpoint. */ -int +enum breakpoint_here breakpoint_here_p (pc) CORE_ADDR pc; { register struct breakpoint *b; + int any_breakpoint_here = 0; ALL_BREAKPOINTS (b) - if (b->enable == enabled - && b->enable != shlib_disabled - && b->enable != call_disabled + if ((b->enable == enabled + || b->enable == permanent) && b->address == pc) /* bp is enabled and matches pc */ - { - if (overlay_debugging && - section_is_overlay (b->section) && - !section_is_mapped (b->section)) - continue; /* unmapped overlay -- can't be a match */ - else - return 1; - } + { + if (overlay_debugging && + section_is_overlay (b->section) && + !section_is_mapped (b->section)) + continue; /* unmapped overlay -- can't be a match */ + else if (b->enable == permanent) + return permanent_breakpoint_here; + else + any_breakpoint_here = 1; + } - return 0; + return any_breakpoint_here ? ordinary_breakpoint_here : 0; } + /* breakpoint_inserted_here_p (PC) is just like breakpoint_here_p(), but it only returns true if there is actually a breakpoint inserted at PC. */ @@ -2842,7 +2857,7 @@ breakpoint_1 (bnum, allflag) static char *bpdisps[] = {"del", "dstp", "dis", "keep"}; - static char bpenables[] = "nyn"; + static char bpenables[] = "nynny"; char wrap_indent[80]; @@ -3141,8 +3156,9 @@ describe_other_breakpoints (pc, section) b->number, ((b->enable == disabled || b->enable == shlib_disabled || - b->enable == call_disabled) - ? " (disabled)" : ""), + b->enable == call_disabled) ? " (disabled)" + : b->enable == permanent ? " (permanent)" + : ""), (others > 1) ? "," : ((others == 1) ? " and" : "")); } printf_filtered ("also set at pc "); @@ -3169,7 +3185,9 @@ set_default_breakpoint (valid, addr, symtab, line) /* Rescan breakpoints at address ADDRESS, marking the first one as "first" and any others as "duplicates". - This is so that the bpt instruction is only inserted once. */ + This is so that the bpt instruction is only inserted once. + If we have a permanent breakpoint at ADDRESS, make that one + the official one, and the rest as duplicates. */ static void check_duplicates (address, section) @@ -3178,6 +3196,7 @@ check_duplicates (address, section) { register struct breakpoint *b; register int count = 0; + struct breakpoint *perm_bp = 0; if (address == 0) /* Watchpoints are uninteresting */ return; @@ -3189,9 +3208,44 @@ check_duplicates (address, section) && b->address == address && (overlay_debugging == 0 || b->section == section)) { + /* Have we found a permanent breakpoint? */ + if (b->enable == permanent) + { + perm_bp = b; + break; + } + count++; b->duplicate = count > 1; } + + /* If we found a permanent breakpoint at this address, go over the + list again and declare all the other breakpoints there to be the + duplicates. */ + if (perm_bp) + { + perm_bp->duplicate = 0; + + /* Permanent breakpoint should always be inserted. */ + if (! perm_bp->inserted) + internal_error ("allegedly permanent breakpoint is not " + "actually inserted"); + + ALL_BREAKPOINTS (b) + if (b != perm_bp) + { + if (b->inserted) + internal_error ("another breakpoint was inserted on top of " + "a permanent breakpoint"); + + if (b->enable != disabled + && b->enable != shlib_disabled + && b->enable != call_disabled + && b->address == address + && (overlay_debugging == 0 || b->section == section)) + b->duplicate = 1; + } + } } /* Low level routine to set a breakpoint. @@ -3254,6 +3308,18 @@ set_raw_breakpoint (sal) return b; } + +/* Note that the breakpoint object B describes a permanent breakpoint + instruction, hard-wired into the inferior's code. */ +void +make_breakpoint_permanent (struct breakpoint *b) +{ + b->enable = permanent; + + /* By definition, permanent breakpoints are already present in the code. */ + b->inserted = 1; +} + #ifdef GET_LONGJMP_TARGET static void @@ -3333,7 +3399,7 @@ remove_solib_event_breakpoints () delete_breakpoint (b); } -void +struct breakpoint * create_solib_event_breakpoint (address) CORE_ADDR address; { @@ -3347,6 +3413,8 @@ create_solib_event_breakpoint (address) b->number = internal_breakpoint_number--; b->disposition = donttouch; b->type = bp_shlib_event; + + return b; } /* Disable any breakpoints that are on code in shared libraries. Only @@ -4643,9 +4711,8 @@ awatch_command (arg, from_tty) cmd_continuation pointer, to complete the until command. It takes care of cleaning up the temporary breakpoints set up by the until command. */ -void -until_break_command_continuation (arg) - struct continuation_arg *arg; +static void +until_break_command_continuation (struct continuation_arg *arg) { /* Do all the exec cleanups, which at this point should only be the one set up in the first part of the until_break_command @@ -5929,6 +5996,14 @@ delete_breakpoint (bpt) { int val; + /* We should never reach this point if there is a permanent + breakpoint at the same address as the one being deleted. + If there is a permanent breakpoint somewhere, it should + always be the only one inserted. */ + if (b->enable == permanent) + internal_error ("another breakpoint was inserted on top of " + "a permanent breakpoint"); + if (b->type == bp_hardware_breakpoint) val = target_insert_hw_breakpoint (b->address, b->shadow_contents); else @@ -6377,6 +6452,10 @@ disable_breakpoint (bpt) if (bpt->type == bp_watchpoint_scope) return; + /* You can't disable permanent breakpoints. */ + if (bpt->enable == permanent) + return; + bpt->enable = disabled; check_duplicates (bpt->address, bpt->section); @@ -6445,7 +6524,8 @@ do_enable_breakpoint (bpt, disposition) error ("Hardware breakpoints used exceeds limit."); } - bpt->enable = enabled; + if (bpt->enable != permanent) + bpt->enable = enabled; bpt->disposition = disposition; check_duplicates (bpt->address, bpt->section); breakpoints_changed (); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index ee03af7d09a..fb29c84301d 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -129,13 +129,18 @@ enum enable shlib_disabled, /* The eventpoint's address is in an unloaded solib. The eventpoint will be automatically enabled and reset when that solib is loaded. */ - call_disabled /* The eventpoint has been disabled while a call + call_disabled, /* The eventpoint has been disabled while a call into the inferior is "in flight", because some eventpoints interfere with the implementation of a call on some targets. The eventpoint will be automatically enabled and reset when the call "lands" (either completes, or stops at another eventpoint). */ + permanent /* There is a breakpoint instruction hard-wired into + the target's code. Don't try to write another + breakpoint instruction on top of it, or restore + its value. Step over it using the architecture's + SKIP_INSN macro. */ }; @@ -459,6 +464,15 @@ enum inf_context inf_running, inf_exited }; + +/* The possible return values for breakpoint_here_p. + We guarantee that zero always means "no breakpoint here". */ +enum breakpoint_here + { + no_breakpoint_here = 0, + ordinary_breakpoint_here, + permanent_breakpoint_here + }; /* Prototypes for breakpoint-related functions. */ @@ -466,7 +480,7 @@ enum inf_context /* Forward declarations for prototypes */ struct frame_info; -extern int breakpoint_here_p PARAMS ((CORE_ADDR)); +extern enum breakpoint_here breakpoint_here_p PARAMS ((CORE_ADDR)); extern int breakpoint_inserted_here_p PARAMS ((CORE_ADDR)); @@ -594,7 +608,9 @@ extern void disable_breakpoint PARAMS ((struct breakpoint *)); extern void enable_breakpoint PARAMS ((struct breakpoint *)); -extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR)); +extern void make_breakpoint_permanent PARAMS ((struct breakpoint *)); + +extern struct breakpoint *create_solib_event_breakpoint PARAMS ((CORE_ADDR)); extern void remove_solib_event_breakpoints PARAMS ((void)); @@ -624,4 +640,8 @@ extern int ep_is_shlib_catchpoint PARAMS ((struct breakpoint *)); extern struct breakpoint *set_breakpoint_sal PARAMS ((struct symtab_and_line)); +/* Enable breakpoints and delete when hit. Called with ARG == NULL + deletes all breakpoints. */ +extern void delete_command (char *arg, int from_tty); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/config/d10v/d10v.mt b/gdb/config/d10v/d10v.mt index eddb1b3f3e2..c65e47f71df 100644 --- a/gdb/config/d10v/d10v.mt +++ b/gdb/config/d10v/d10v.mt @@ -1,5 +1,6 @@ # Target: Mitsubishi D10V processor -TDEPFILES= d10v-tdep.o remote-d10v.o +TDEPFILES= d10v-tdep.o TM_FILE= tm-d10v.h + SIM_OBS= remote-sim.o SIM= ../sim/d10v/libsim.a diff --git a/gdb/config/i386/tm-linux.h b/gdb/config/i386/tm-linux.h index e4f70a2078d..9f5ac78436f 100644 --- a/gdb/config/i386/tm-linux.h +++ b/gdb/config/i386/tm-linux.h @@ -214,20 +214,9 @@ double_to_i387 PARAMS ((char *, char *)); /* end of copy */ -extern void i387_float_info(void); -#define FLOAT_INFO { i387_float_info (); } - /* The following works around a problem with /usr/include/sys/procfs.h */ #define sys_quotactl 1 -/* Define DO_REGISTERS_INFO() to do machine-specific formatting - of register dumps. */ - -#define DO_REGISTERS_INFO(_regnum, fp) i386_do_registers_info(_regnum, fp) -extern void i386_do_registers_info PARAMS ((int, int)); - -extern void i387_print_register PARAMS ((char *, int)); - /* When the i386 Linux kernel calls a signal handler, the return address points to a bit of code on the stack. These definitions are used to identify this bit of code as a signal trampoline in diff --git a/gdb/config/pa/tm-hppa.h b/gdb/config/pa/tm-hppa.h index 60ec0378c68..d5359818ad1 100644 --- a/gdb/config/pa/tm-hppa.h +++ b/gdb/config/pa/tm-hppa.h @@ -563,7 +563,6 @@ extern void hppa_pop_frame PARAMS ((void)); #define CALL_DUMMY_LENGTH (INSTRUCTION_SIZE * 28) #define REG_PARM_STACK_SPACE 16 -#define ARGS_GROW_DOWNWARD #else /* defined PA_LEVEL_0 */ @@ -796,3 +795,7 @@ PARAMS ((CORE_ADDR, int)) probably much more common. (FIXME). */ #define COERCE_FLOAT_TO_DOUBLE (current_language -> la_language == language_c) + +/* Here's how to step off a permanent breakpoint. */ +#define SKIP_PERMANENT_BREAKPOINT (hppa_skip_permanent_breakpoint) +extern void hppa_skip_permanent_breakpoint (void); diff --git a/gdb/config/pa/tm-hppa64.h b/gdb/config/pa/tm-hppa64.h index 99049fed27a..7f30c664f32 100644 --- a/gdb/config/pa/tm-hppa64.h +++ b/gdb/config/pa/tm-hppa64.h @@ -210,8 +210,8 @@ call_dummy #undef REG_PARM_STACK_SPACE #define REG_PARM_STACK_SPACE 64 -/* Arguments grow in the normal direction for the PA64 port. */ -#undef ARGS_GROW_DOWNWARD +/* Use the 64-bit calling conventions designed for the PA2.0 in wide mode. */ +#define PA20W_CALLING_CONVENTIONS #undef FUNC_LDIL_OFFSET #undef FUNC_LDO_OFFSET diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 3c93ea97ebd..fa8b080e84d 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -1030,6 +1030,165 @@ d10v_extract_return_value (type, regbuf, valbuf) } } +/* Translate a GDB virtual ADDR/LEN into a format the remote target + understands. Returns number of bytes that can be transfered + starting at taddr, ZERO if no bytes can be transfered. */ + +void +remote_d10v_translate_xfer_address (CORE_ADDR memaddr, int nr_bytes, + CORE_ADDR *targ_addr, int *targ_len) +{ + CORE_ADDR phys; + CORE_ADDR seg; + CORE_ADDR off; + char *from = "unknown"; + char *to = "unknown"; + + /* GDB interprets addresses as: + + 0x00xxxxxx: Physical unified memory segment (Unified memory) + 0x01xxxxxx: Physical instruction memory segment (On-chip insn memory) + 0x02xxxxxx: Physical data memory segment (On-chip data memory) + 0x10xxxxxx: Logical data address segment (DMAP translated memory) + 0x11xxxxxx: Logical instruction address segment (IMAP translated memory) + + The remote d10v board interprets addresses as: + + 0x00xxxxxx: Physical unified memory segment (Unified memory) + 0x01xxxxxx: Physical instruction memory segment (On-chip insn memory) + 0x02xxxxxx: Physical data memory segment (On-chip data memory) + + Translate according to current IMAP/dmap registers */ + + enum + { + targ_unified = 0x00000000, + targ_insn = 0x01000000, + targ_data = 0x02000000, + }; + + seg = (memaddr >> 24); + off = (memaddr & 0xffffffL); + + switch (seg) + { + case 0x00: /* Physical unified memory */ + from = "phys-unified"; + phys = targ_unified | off; + to = "unified"; + break; + + case 0x01: /* Physical instruction memory */ + from = "phys-insn"; + phys = targ_insn | off; + to = "chip-insn"; + break; + + case 0x02: /* Physical data memory segment */ + from = "phys-data"; + phys = targ_data | off; + to = "chip-data"; + break; + + case 0x10: /* in logical data address segment */ + { + from = "logical-data"; + if (off <= 0x7fffL) + { + /* On chip data */ + phys = targ_data + off; + if (off + nr_bytes > 0x7fffL) + /* don't cross VM boundary */ + nr_bytes = 0x7fffL - off + 1; + to = "chip-data"; + } + else if (off <= 0xbfffL) + { + unsigned short dmap = read_register (DMAP_REGNUM); + short map = dmap; + + if (map & 0x1000) + { + /* Instruction memory */ + phys = targ_insn | ((map & 0xf) << 14) | (off & 0x3fff); + to = "chip-insn"; + } + else + { + /* Unified memory */ + phys = targ_unified | ((map & 0x3ff) << 14) | (off & 0x3fff); + to = "unified"; + } + if (off + nr_bytes > 0xbfffL) + /* don't cross VM boundary */ + nr_bytes = (0xbfffL - off + 1); + } + else + { + /* Logical address out side of data segments, not supported */ + *targ_len = 0; + return; + } + break; + } + + case 0x11: /* in logical instruction address segment */ + { + short map; + unsigned short imap0 = read_register (IMAP0_REGNUM); + unsigned short imap1 = read_register (IMAP1_REGNUM); + + from = "logical-insn"; + if (off <= 0x1ffffL) + { + map = imap0; + } + else if (off <= 0x3ffffL) + { + map = imap1; + } + else + { + /* Logical address outside of IMAP[01] segment, not + supported */ + *targ_len = 0; + return; + } + if ((off & 0x1ffff) + nr_bytes > 0x1ffffL) + { + /* don't cross VM boundary */ + nr_bytes = 0x1ffffL - (off & 0x1ffffL) + 1; + } + if (map & 0x1000) + /* Instruction memory */ + { + phys = targ_insn | off; + to = "chip-insn"; + } + else + { + phys = ((map & 0x7fL) << 17) + (off & 0x1ffffL); + if (phys > 0xffffffL) + { + /* Address outside of unified address segment */ + *targ_len = 0; + return; + } + phys |= targ_unified; + to = "unified"; + } + break; + } + + default: + *targ_len = 0; + return; + } + + *targ_addr = phys; + *targ_len = nr_bytes; +} + /* The following code implements access to, and display of, the D10V's instruction trace buffer. The buffer consists of 64K or more 4-byte words of data, of which each words includes an 8-bit count, diff --git a/gdb/dbxread.c b/gdb/dbxread.c index d9ad0405275..368880d59f6 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -2314,34 +2314,8 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile) from N_FUN symbols. */ if (type == N_FUN && valu == ANOFFSET (section_offsets, SECT_OFF_TEXT)) - { - struct minimal_symbol *msym; - char *p; - int n; - - p = strchr (name, ':'); - if (p == NULL) - p = name; - n = p - name; - p = alloca (n + 2); - strncpy (p, name, n); - p[n] = 0; - - msym = lookup_minimal_symbol (p, last_source_file, - objfile); - if (msym == NULL) - { - /* Sun Fortran appends an underscore to the minimal - symbol name, try again with an appended underscore - if the minimal symbol was not found. */ - p[n] = '_'; - p[n + 1] = 0; - msym = lookup_minimal_symbol (p, last_source_file, - objfile); - } - if (msym) - valu = SYMBOL_VALUE_ADDRESS (msym); - } + valu = + find_stab_function_addr (name, last_source_file, objfile); #endif #ifdef SUN_FIXED_LBRAC_BUG diff --git a/gdb/defs.h b/gdb/defs.h index 6f1d96a720b..3c8161b5559 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -691,9 +691,10 @@ continuation; extern struct continuation *cmd_continuation; /* From utils.c */ -void add_continuation PARAMS ((void (*) PARAMS ((struct continuation_arg *)), +extern void add_continuation PARAMS ((void (*) PARAMS ((struct continuation_arg *)), struct continuation_arg *)); -void do_all_continuations PARAMS ((void)); +extern void do_all_continuations PARAMS ((void)); +extern void discard_all_continuations PARAMS ((void)); /* String containing the current directory (what getwd would return). */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 090f58ca771..e195e54deed 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,12 @@ +1999-09-14 Michael Snyder <msnyder@cleaver.cygnus.com> + + * gdbint.texinfo: Fix typo, add the word "have". + +1999-09-14 Jim Blandy <jimb@cris.red-bean.com> + + * gdbint.texinfo (Target Architecture Definition): Document the + SKIP_PERMANENT_BREAKPOINT macro. + 1999-09-07 Stan Shebs <shebs@andros.cygnus.com> * gdb.texinfo: Fiks speling errers. diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 3fc14bae7dc..765c446607a 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -46,7 +46,7 @@ regarded as a program in the language TeX). @page @tex \def\$#1${{#1}} % Kluge: collect RCS revision info without $...$ -\xdef\manvers{\$Revision: 1.1.1.16 $} % For use in headers, footers too +\xdef\manvers{\$Revision: 1.1.1.17 $} % For use in headers, footers too {\parskip=0pt \hfill Cygnus Solutions\par \hfill \manvers\par @@ -1596,6 +1596,16 @@ defined, no conversion will be done. @item SHIFT_INST_REGS (Only used for m88k targets.) +@item SKIP_PERMANENT_BREAKPOINT +Advance the inferior's PC past a permanent breakpoint. GDB normally +steps over a breakpoint by removing it, stepping one instruction, and +re-inserting the breakpoint. However, permanent breakpoints are +hardwired into the inferior, and can't be removed, so this strategy +doesn't work. Calling SKIP_PERMANENT_BREAKPOINT adjusts the processor's +state so that execution will resume just after the breakpoint. This +macro does the right thing even when the breakpoint is in the delay slot +of a branch or jump. + @item SKIP_PROLOGUE (pc) A C expression that returns the address of the ``real'' code beyond the function entry prologue found at @var{pc}. @@ -2759,7 +2769,7 @@ also documents all the available macros. @c Conditionals}, @pxref{Native Conditionals}, and @pxref{Obsolete @c Conditionals}) -Start with the header files. Once you some idea of how GDB's internal +Start with the header files. Once you have some idea of how GDB's internal symbol tables are stored (see @file{symtab.h}, @file{gdbtypes.h}), you will find it much easier to understand the code which uses and creates those symbol tables. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 9db63c22714..85dd111207b 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -4016,8 +4016,14 @@ dwarf_decode_lines (offset, comp_dir, abfd) case DW_LNS_set_basic_block: basic_block = 1; break; + /* Add to the address register of the state machine the + address increment value corresponding to special opcode + 255. Ie, this value is scaled by the minimum instruction + length since special opcode 255 would have scaled the + the increment. */ case DW_LNS_const_add_pc: - address += (255 - lh.opcode_base) / lh.line_range; + address += (lh.minimum_instruction_length + * ((255 - lh.opcode_base) / lh.line_range)); break; case DW_LNS_fixed_advance_pc: address += read_2_bytes (abfd, line_ptr); diff --git a/gdb/event-loop.c b/gdb/event-loop.c index 261c8383163..8815e04234b 100644 --- a/gdb/event-loop.c +++ b/gdb/event-loop.c @@ -22,6 +22,8 @@ #include "defs.h" #include "top.h" #include "event-loop.h" +#include "event-top.h" +#include "inferior.h" /* For fetch_inferior_event. */ #ifdef HAVE_POLL #include <poll.h> #else @@ -29,6 +31,103 @@ #endif #include <errno.h> #include <setjmp.h> +#include <sys/time.h> + +/* Type of the mask arguments to select. */ + +#ifndef NO_FD_SET +#define SELECT_MASK fd_set +#else +#ifndef _AIX +typedef long fd_mask; +#endif +#if defined(_IBMR2) +#define SELECT_MASK void +#else +#define SELECT_MASK int +#endif +#endif + +/* Define "NBBY" (number of bits per byte) if it's not already defined. */ + +#ifndef NBBY +#define NBBY 8 +#endif + + +/* Define the number of fd_masks in an fd_set */ + +#ifndef FD_SETSIZE +#ifdef OPEN_MAX +#define FD_SETSIZE OPEN_MAX +#else +#define FD_SETSIZE 256 +#endif +#endif +#if !defined(howmany) +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef NFDBITS +#define NFDBITS NBBY*sizeof(fd_mask) +#endif +#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) + + +typedef struct gdb_event gdb_event; +typedef void (event_handler_func) (int); + +/* Event for the GDB event system. Events are queued by calling + async_queue_event and serviced later on by gdb_do_one_event. An + event can be, for instance, a file descriptor becoming ready to be + read. Servicing an event simply means that the procedure PROC will + be called. We have 2 queues, one for file handlers that we listen + to in the event loop, and one for the file handlers+events that are + ready. The procedure PROC associated with each event is always the + same (handle_file_event). Its duty is to invoke the handler + associated with the file descriptor whose state change generated + the event, plus doing other cleanups adn such. */ + +struct gdb_event + { + event_handler_func *proc; /* Procedure to call to service this event. */ + int fd; /* File descriptor that is ready. */ + struct gdb_event *next_event; /* Next in list of events or NULL. */ + }; + +/* Information about each file descriptor we register with the event + loop. */ + +typedef struct file_handler + { + int fd; /* File descriptor. */ + 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. */ + gdb_client_data client_data; /* Argument to pass to proc. */ + int error; /* Was an error detected on this fd? */ + struct file_handler *next_file; /* Next registered file descriptor. */ + } +file_handler; + +/* PROC is a function to be invoked when the READY flag is set. This + happens when there has been a signal and the corresponding signal + handler has 'triggered' this async_signal_handler for + execution. The actual work to be done in response to a signal will + be carried out by PROC at a later time, within process_event. This + provides a deferred execution of signal handlers. + Async_init_signals takes care of setting up such an + asyn_signal_handler for each interesting signal. */ +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 */ + gdb_client_data client_data; /* Argument to async_handler_func */ + } +async_signal_handler; + /* Event queue: - the first event in the queue is the head of the queue. @@ -75,6 +174,11 @@ static struct /* Number of file descriptors to monitor. */ int num_fds; + /* Timeout in milliseconds for calls to poll(). */ + int timeout; + + /* Flag to tell whether the timeout value shuld be used. */ + int timeout_valid; } gdb_notifier; @@ -97,11 +201,40 @@ static struct /* Number of valid bits (highest fd value + 1). */ int num_fds; - } + /* Time structure for calls to select(). */ + struct timeval timeout; + + /* Flag to tell whether the timeout struct should be used. */ + int timeout_valid; + } gdb_notifier; #endif /* HAVE_POLL */ +/* Structure associated with a timer. PROC will be executed at the + first occasion after WHEN. */ +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 */ + } +gdb_timer; + +/* List of currently active timers. It is sorted in order of + increasing timers.*/ +static struct + { + /* Pointer to first in timer list. */ + struct gdb_timer *first_timer; + + /* Length of timer list. */ + int num_timers; + } +timer_list; + /* All the async_signal_handlers gdb is interested in are kept onto this list. */ static struct @@ -120,12 +253,17 @@ sighandler_list; function. */ static int async_handler_ready = 0; -static void create_file_handler PARAMS ((int, int, handler_func *, gdb_client_data)); -static void invoke_async_signal_handler PARAMS ((void)); -static void handle_file_event PARAMS ((int)); -static int gdb_wait_for_event PARAMS ((void)); -static int gdb_do_one_event PARAMS ((void)); -static int check_async_ready PARAMS ((void)); +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 int process_event (void); +static void handle_timer_event (int dummy); +static void poll_timers (void); /* Insert an event object into the gdb event queue at @@ -139,9 +277,7 @@ static int check_async_ready PARAMS ((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 (event_ptr, position) - gdb_event *event_ptr; - queue_position position; +async_queue_event (gdb_event *event_ptr, queue_position position) { if (position == TAIL) { @@ -169,9 +305,8 @@ async_queue_event (event_ptr, position) processing. The procedure associated to this event is always handle_file_event, which will in turn invoke the one that was associated to FD when it was registered with the event loop. */ -gdb_event * -create_file_event (fd) - int fd; +static gdb_event * +create_file_event (int fd) { gdb_event *file_event_ptr; @@ -191,7 +326,7 @@ create_file_event (fd) priority events first, by invoking the associated event handler procedure. */ static int -process_event () +process_event (void) { gdb_event *event_ptr, *prev_ptr; event_handler_func *proc; @@ -257,7 +392,7 @@ process_event () it. Returns 1 if something was done otherwise returns 0 (this can happen if there are no event sources to wait for). */ static int -gdb_do_one_event () +gdb_do_one_event (void) { int result = 0; @@ -272,6 +407,9 @@ gdb_do_one_event () break; } + /* 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, we should get out because this means that there are no event sources left. This will make the event loop stop, @@ -313,7 +451,7 @@ gdb_do_one_event () /* Start up the event loop. This is the entry point to the event loop from the command loop. */ void -start_event_loop () +start_event_loop (void) { /* Loop until there is something to do. This is the entry point to the event loop engine. gdb_do_one_event will process one event @@ -328,20 +466,16 @@ start_event_loop () } - /* Wrapper function for create_file_handler, so that the caller doesn't have to know implementation details about the use of poll vs. select. */ void -add_file_handler (fd, proc, client_data) - int fd; - void (*proc) (void); - 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, (handler_func *) proc, client_data); + create_file_handler (fd, POLLIN, proc, client_data); #else - create_file_handler (fd, GDB_READABLE, (handler_func *) proc, client_data); + create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data); #endif } @@ -356,11 +490,7 @@ add_file_handler (fd, proc, 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 (fd, mask, proc, client_data) - 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; @@ -377,7 +507,8 @@ create_file_handler (fd, mask, proc, client_data) break; } - /* It is a new file descriptor. */ + /* It is a new file descriptor. Add it to the list. Otherwise, just + change the data associated with it.*/ if (file_ptr == NULL) { file_ptr = (file_handler *) xmalloc (sizeof (file_handler)); @@ -385,6 +516,9 @@ create_file_handler (fd, mask, proc, client_data) file_ptr->ready_mask = 0; file_ptr->next_file = gdb_notifier.first_file_handler; gdb_notifier.first_file_handler = file_ptr; +#ifdef HAVE_POLL + gdb_notifier.num_fds++; +#endif } file_ptr->proc = proc; file_ptr->client_data = client_data; @@ -392,7 +526,6 @@ create_file_handler (fd, mask, proc, client_data) #ifdef HAVE_POLL - gdb_notifier.num_fds++; if (gdb_notifier.poll_fds) gdb_notifier.poll_fds = (struct pollfd *) realloc (gdb_notifier.poll_fds, @@ -433,8 +566,7 @@ create_file_handler (fd, mask, proc, client_data) /* Remove the file descriptor FD from the list of monitored fd's: i.e. we don't care anymore about events on the FD. */ void -delete_file_handler (fd) - int fd; +delete_file_handler (int fd) { file_handler *file_ptr, *prev_ptr = NULL; int i, j; @@ -536,11 +668,14 @@ delete_file_handler (fd) through event_ptr->proc. EVENT_FILE_DESC is file descriptor of the event in the front of the event queue. */ static void -handle_file_event (event_file_desc) - int event_file_desc; +handle_file_event (int event_file_desc) { file_handler *file_ptr; - int mask, error_mask; + int mask; +#ifdef HAVE_POLL + int error_mask; + int error_mask_returned; +#endif /* Search the file handler list to find one that matches the fd in the event. */ @@ -563,8 +698,30 @@ handle_file_event (event_file_desc) error_mask = POLLHUP | POLLERR | POLLNVAL; mask = (file_ptr->ready_mask & file_ptr->mask) | (file_ptr->ready_mask & error_mask); + error_mask_returned = mask & error_mask; + if (error_mask_returned != 0) + { + /* Work in progress. We may need to tell somebody what + 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);*/ + file_ptr->error = 1; + } + else + file_ptr->error = 0; #else /* ! HAVE_POLL */ + if (file_ptr->ready_mask & GDB_EXCEPTION) + { + printf_unfiltered ("Exception condition detected on fd %d\n", file_ptr->fd); + file_ptr->error = 1; + } + else + file_ptr->error = 0; mask = file_ptr->ready_mask & file_ptr->mask; #endif /* HAVE_POLL */ @@ -573,7 +730,7 @@ handle_file_event (event_file_desc) /* If there was a match, then call the handler. */ if (mask != 0) - (*file_ptr->proc) (file_ptr->client_data); + (*file_ptr->proc) (file_ptr->error, file_ptr->fd, file_ptr->client_data); break; } } @@ -587,7 +744,7 @@ handle_file_event (event_file_desc) Return -1 if there are no files descriptors to monitor, otherwise return 0. */ static int -gdb_wait_for_event () +gdb_wait_for_event (void) { file_handler *file_ptr; gdb_event *file_event_ptr; @@ -607,7 +764,14 @@ gdb_wait_for_event () #ifdef HAVE_POLL num_found = - poll (gdb_notifier.poll_fds, (unsigned long) gdb_notifier.num_fds, -1); + 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.*/ + if (num_found == -1 && errno != EINTR) + perror_with_name ("Poll"); #else /* ! HAVE_POLL */ memcpy (gdb_notifier.ready_masks, @@ -616,14 +780,18 @@ gdb_wait_for_event () 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], - 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) - memset (gdb_notifier.ready_masks, - 0, 3 * MASK_SIZE * sizeof (fd_mask)); - + { + memset (gdb_notifier.ready_masks, + 0, 3 * MASK_SIZE * sizeof (fd_mask)); + /* Dont print anything is we got a signal, let gdb handle it. */ + if (errno != EINTR) + perror_with_name ("Select"); + } #endif /* HAVE_POLL */ /* Enqueue all detected file events. */ @@ -703,9 +871,7 @@ gdb_wait_for_event () PROC is the function to call with CLIENT_DATA argument whenever the handler is invoked. */ async_signal_handler * -create_async_signal_handler (proc, client_data) - 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; @@ -728,8 +894,7 @@ create_async_signal_handler (proc, client_data) some event. The caller of this function is the interrupt handler associated with a signal. */ void -mark_async_signal_handler (async_handler_ptr) - 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; @@ -737,7 +902,7 @@ mark_async_signal_handler (async_handler_ptr) /* Call all the handlers that are ready. */ static void -invoke_async_signal_handler () +invoke_async_signal_handler (void) { async_signal_handler *async_handler_ptr; @@ -768,8 +933,7 @@ invoke_async_signal_handler () /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). Free the space allocated for it. */ void -delete_async_signal_handler (async_handler_ptr) - async_signal_handler **async_handler_ptr; +delete_async_signal_handler (async_signal_handler **async_handler_ptr) { async_signal_handler *prev_ptr; @@ -794,7 +958,212 @@ delete_async_signal_handler (async_handler_ptr) /* Is it necessary to call invoke_async_signal_handler? */ static int -check_async_ready () +check_async_ready (void) { return async_handler_ready; } + +/* FIXME: where does this function belong? */ +/* General function to handle events in the inferior. So far it just + takes care of detecting errors reported by select() or poll(), + otherwise it assumes that all is OK, and goes on reading data from + the fd. This however may not always be what we want to do. */ +void +inferior_event_handler (int error, gdb_client_data client_data, int fd) +{ + if (error == 1) + { + printf_unfiltered ("error detected on fd %d\n", fd); + delete_file_handler (fd); + discard_all_continuations (); + } + else + fetch_inferior_event (client_data); +} + +/* 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.*/ +int +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; + + /* compute seconds */ + delta.tv_sec = milliseconds / 1000; + /* compute microseconds */ + 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 ) + { + 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_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; + 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) || + ((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; + timer_list.first_timer = timer_ptr; + + } + else + { + 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; + } + + gdb_notifier.timeout_valid = 0; + return timer_ptr->timer_id; +} + +/* There is a chance that the creator of the timer wants to get rid of + it before it expires. */ +void +delete_timer (int id) +{ + struct gdb_timer *timer_ptr, *prev_timer = NULL; + + /* Find the entry for the given timer. */ + + for (timer_ptr = timer_list.first_timer; timer_ptr != NULL; + timer_ptr = timer_ptr->next) + { + if (timer_ptr->timer_id == id) + break; + } + + if (timer_ptr == NULL) + return; + /* Get rid of the timer in the timer list. */ + if (timer_ptr == timer_list.first_timer) + timer_list.first_timer = timer_ptr->next; + else + { + for (prev_timer = timer_list.first_timer; + prev_timer->next != timer_ptr; + prev_timer = prev_timer->next) + ; + prev_timer->next = timer_ptr->next; + } + free ((char *) timer_ptr); + + gdb_notifier.timeout_valid = 0; +} + +/* 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.*/ +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) && + (timer_ptr->when.tv_usec > time_now.tv_usec))) + break; + + /* Get rid of the timer from the beginning of the list. */ + timer_list.first_timer = timer_ptr->next; + saved_timer = timer_ptr; + timer_ptr = timer_ptr->next; + /* Call the procedure associated with that timer. */ + (*saved_timer->proc) (timer_ptr->client_data); + free (saved_timer); + } + + 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.*/ +static void +poll_timers (void) +{ + struct timeval time_now, delta; + gdb_event *event_ptr; + + if (timer_list.num_timers) + { + gettimeofday (&time_now, NULL); + delta.tv_sec = timer_list.first_timer->when.tv_sec - time_now.tv_sec; + delta.tv_usec = timer_list.first_timer->when.tv_usec - time_now.tv_usec; + /* borrow? */ + if (delta.tv_usec < 0) + { + delta.tv_sec -= 1; + delta.tv_usec += 1000000; + } + + /* Oops it expired already. Tell select / poll to return + immediately. */ + if (delta.tv_sec < 0) + { + delta.tv_sec = 0; + delta.tv_usec = 0; + } + + if (delta.tv_sec == 0 && delta.tv_usec == 0) + { + event_ptr = (gdb_event *) xmalloc (sizeof (gdb_event)); + event_ptr->proc = handle_timer_event; + event_ptr->fd = timer_list.first_timer->timer_id; + async_queue_event (event_ptr, TAIL); + } + + /* Now we need to update the timeout for select/ poll, because we + don't want to sit there while this timer is expiring. */ +#ifdef HAVE_POLL + gdb_notifier.timeout = delta.tv_sec * 1000; +#else + gdb_notifier.timeout.sec = delta.tv_sec; + gdb_notifier.timeout.usec = delta.tv_usec; +#endif + gdb_notifier.timeout_valid = 1; + } + else + gdb_notifier.timeout_valid = 0; +} diff --git a/gdb/event-loop.h b/gdb/event-loop.h index baebccd3b85..ffb01233267 100644 --- a/gdb/event-loop.h +++ b/gdb/event-loop.h @@ -58,62 +58,10 @@ Corollary tasks are the creation and deletion of event sources. */ typedef PTR gdb_client_data; -typedef struct gdb_event gdb_event; - -typedef void (handler_func) PARAMS ((gdb_client_data)); -typedef void (event_handler_func) PARAMS ((int)); - -/* Event for the GDB event system. Events are queued by calling - async_queue_event and serviced later on by gdb_do_one_event. An - event can be, for instance, a file descriptor becoming ready to be - read. Servicing an event simply means that the procedure PROC will - be called. We have 2 queues, one for file handlers that we listen - to in the event loop, and one for the file handlers+events that are - ready. The procedure PROC associated with each event is always the - same (handle_file_event). Its duty is to invoke the handler - associated with the file descriptor whose state change generated - the event, plus doing other cleanups adn such. */ - -struct gdb_event - { - event_handler_func *proc; /* Procedure to call to service this event. */ - int fd; /* File descriptor that is ready. */ - struct gdb_event *next_event; /* Next in list of events or NULL. */ - }; - -/* Information about each file descriptor we register with the event - loop. */ - -typedef struct file_handler - { - int fd; /* File descriptor. */ - 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. */ - gdb_client_data client_data; /* Argument to pass to proc. */ - struct file_handler *next_file; /* Next registered file descriptor. */ - } -file_handler; - -/* PROC is a function to be invoked when the READY flag is set. This - happens when there has been a signal and the corresponding signal - handler has 'triggered' this async_signal_handler for - execution. The actual work to be done in response to a signal will - be carried out by PROC at a later time, within process_event. This - provides a deferred execution of signal handlers. - Async_init_signals takes care of setting up such an - asyn_signal_handler for each interesting signal. */ - -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 */ - handler_func *proc; /* Function to call to do the work */ - gdb_client_data client_data; /* Argument to async_handler_func */ - } -async_signal_handler; +struct async_signal_handler; +typedef void (handler_func) (int, int, gdb_client_data); +typedef void (sig_handler_func) (gdb_client_data); +typedef void (timer_handler_func) (gdb_client_data); /* Where to add an event onto the event queue, by queue_event. */ typedef enum @@ -134,129 +82,19 @@ queue_position; #define GDB_WRITABLE (1<<2) #define GDB_EXCEPTION (1<<3) -/* Type of the mask arguments to select. */ - -#ifndef NO_FD_SET -#define SELECT_MASK fd_set -#else -#ifndef _AIX -typedef long fd_mask; -#endif -#if defined(_IBMR2) -#define SELECT_MASK void -#else -#define SELECT_MASK int -#endif -#endif - -/* Define "NBBY" (number of bits per byte) if it's not already defined. */ - -#ifndef NBBY -#define NBBY 8 -#endif - - -/* Define the number of fd_masks in an fd_set */ - -#ifndef FD_SETSIZE -#ifdef OPEN_MAX -#define FD_SETSIZE OPEN_MAX -#else -#define FD_SETSIZE 256 -#endif -#endif -#if !defined(howmany) -#define howmany(x, y) (((x)+((y)-1))/(y)) -#endif -#ifndef NFDBITS -#define NFDBITS NBBY*sizeof(fd_mask) -#endif -#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) - - -/* Stack for prompts. Each prompt is composed as a prefix, a prompt - and a suffix. The prompt to be displayed at any given time is the - one on top of the stack. A stack is necessary because of cases in - which the execution of a gdb command requires further input from - the user, like for instance 'commands' for breakpoints and - 'actions' for tracepoints. In these cases, the prompt is '>' and - gdb should process input using the asynchronous readline interface - and the event loop. In order to achieve this, we need to save - somewhere the state of GDB, i.e. that it is processing user input - as part of a command and not as part of the top level command loop. - The prompt stack represents part of the saved state. Another part - would be the function that readline would invoke after a whole line - of input has ben entered. This second piece would be something - like, for instance, where to return within the code for the actions - commands after a line has been read. This latter portion has not - beeen implemented yet. The need for a 3-part prompt arises from - the annotation level. When this is set to 2, the prompt is actually - composed of a prefix, the prompt itself and a suffix. */ - -/* At any particular time there will be always at least one prompt on - the stack, the one being currently displayed by gdb. If gdb is - using annotation level equal 2, there will be 2 prompts on the - stack: the usual one, w/o prefix and suffix (at top - 1), and the - 'composite' one with prefix and suffix added (at top). At this - time, this is the only use of the prompt stack. Resetting annotate - to 0 or 1, pops the top of the stack, resetting its size to one - element. The MAXPROMPTS limit is safe, for now. Once other cases - are dealt with (like the different prompts used for 'commands' or - 'actions') this array implementation of the prompt stack may have - to change. */ - -#define MAXPROMPTS 10 -struct prompts - { - struct - { - char *prefix; - char *prompt; - char *suffix; - } - prompt_stack[MAXPROMPTS]; - int top; - }; - -#define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt -#define PREFIX(X) the_prompts.prompt_stack[the_prompts.top + X].prefix -#define SUFFIX(X) the_prompts.prompt_stack[the_prompts.top + X].suffix - /* Exported functions from event-loop.c */ -extern void start_event_loop PARAMS ((void)); -extern void delete_file_handler PARAMS ((int)); -extern void add_file_handler PARAMS ((int, void (*) (void), gdb_client_data)); -extern void mark_async_signal_handler PARAMS ((async_signal_handler *)); -extern async_signal_handler * - create_async_signal_handler PARAMS ((handler_func *, gdb_client_data)); -extern void delete_async_signal_handler PARAMS ((async_signal_handler ** async_handler_ptr)); -extern gdb_event *create_file_event PARAMS ((int)); +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 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 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 void delete_timer (int id); -/* Exported functions from event-top.c. - FIXME: these should really go into top.h. */ -extern void display_gdb_prompt PARAMS ((char *)); -extern void async_init_signals PARAMS ((void)); -extern void set_async_editing_command PARAMS ((char *, int, struct cmd_list_element *)); -extern void set_async_annotation_level PARAMS ((char *, int, struct cmd_list_element *)); -extern void set_async_prompt PARAMS ((char *, int, struct cmd_list_element *)); -extern void handle_stop_sig PARAMS ((int)); -extern void handle_sigint PARAMS ((int)); -extern void pop_prompt PARAMS ((void)); -extern void push_prompt PARAMS ((char *, char *, char *)); -extern void gdb_readline2 PARAMS ((void)); -extern void mark_async_signal_handler_wrapper (void *); -extern void async_request_quit (gdb_client_data); -/* Exported variables from event-top.c. - FIXME: these should really go into top.h. */ -extern int async_command_editing_p; -extern int exec_done_display_p; -extern char *async_annotation_suffix; -extern char *new_async_prompt; -extern struct prompts the_prompts; -extern void (*call_readline) PARAMS ((void)); -extern void (*input_handler) PARAMS ((char *)); -extern int input_fd; diff --git a/gdb/event-top.c b/gdb/event-top.c index 330f9034ef8..622396f1e69 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -23,8 +23,9 @@ #include "top.h" #include "inferior.h" #include "terminal.h" /* for job_control */ -#include <signal.h> +#include "signals.h" #include "event-loop.h" +#include "event-top.h" /* For dont_repeat() */ #include "gdbcmd.h" @@ -36,39 +37,34 @@ /* readline defines this. */ #undef savestring -extern void _initialize_event_loop PARAMS ((void)); +extern void _initialize_event_loop (void); -static void command_line_handler PARAMS ((char *)); -static void command_line_handler_continuation PARAMS ((struct continuation_arg *)); -void gdb_readline2 PARAMS ((void)); -void pop_prompt PARAMS ((void)); -void push_prompt PARAMS ((char *, char *, char *)); -static void change_line_handler PARAMS ((void)); -static void change_annotation_level PARAMS ((void)); -static void command_handler PARAMS ((char *)); +static void rl_callback_read_char_wrapper (gdb_client_data client_data); +static void command_line_handler (char *rl); +static void command_line_handler_continuation (struct continuation_arg *arg); +static void change_line_handler (void); +static void change_annotation_level (void); +static void command_handler (char *command); +void cli_command_loop (void); +static void async_do_nothing (gdb_client_data arg); +static void async_disconnect (gdb_client_data arg); +static void async_stop_sig (gdb_client_data arg); +static void async_float_handler (gdb_client_data arg); /* Signal handlers. */ -void handle_sigint PARAMS ((int)); -static void handle_sigquit PARAMS ((int)); -static void handle_sighup PARAMS ((int)); -static void handle_sigfpe PARAMS ((int)); +static void handle_sigquit (int sig); +static void handle_sighup (int sig); +static void handle_sigfpe (int sig); #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) -static void handle_sigwinch PARAMS ((int)); -#endif -/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */ -#ifndef STOP_SIGNAL -#ifdef SIGTSTP -#define STOP_SIGNAL SIGTSTP -void handle_stop_sig PARAMS ((int)); -#endif +static void handle_sigwinch (int sig); #endif /* Functions to be invoked by the event loop in response to signals. */ -static void async_do_nothing PARAMS ((gdb_client_data)); -static void async_disconnect PARAMS ((gdb_client_data)); -static void async_float_handler PARAMS ((gdb_client_data)); -static void async_stop_sig PARAMS ((gdb_client_data)); +static void async_do_nothing (gdb_client_data); +static void async_disconnect (gdb_client_data); +static void async_float_handler (gdb_client_data); +static void async_stop_sig (gdb_client_data); /* Readline offers an alternate interface, via callback functions. These are all included in the file callback.c in the @@ -90,8 +86,8 @@ static void async_stop_sig PARAMS ((gdb_client_data)); line of input is ready. CALL_READLINE is to be set to the function that readline offers as callback to the event_loop. */ -void (*input_handler) PARAMS ((char *)); -void (*call_readline) PARAMS ((void)); +void (*input_handler) (char *); +void (*call_readline) (gdb_client_data); /* Important variables for the event loop. */ @@ -158,10 +154,19 @@ struct readline_input_state readline_input_state; +/* Wrapper function foe calling into the readline library. The event + loop expects the callback function to have a paramter, while readline + expects none. */ +static void +rl_callback_read_char_wrapper (gdb_client_data client_data) +{ + rl_callback_read_char (); +} + /* Initialize all the necessary variables, start the event loop, register readline, and stdin, start the loop. */ void -cli_command_loop () +cli_command_loop (void) { int length; char *a_prompt; @@ -195,12 +200,18 @@ cli_command_loop () which the user sets editing on again, by restoring readline handling of the input. */ static void -change_line_handler () +change_line_handler (void) { + /* NOTE: this operates on input_fd, not instream. If we are reading + commands from a file, instream will point to the file. However in + async mode, we always read commands from a file with editing + off. This means that the 'set editing on/off' will have effect + only on the interactive session. */ + if (async_command_editing_p) { /* Turn on editing by using readline. */ - call_readline = rl_callback_read_char; + call_readline = rl_callback_read_char_wrapper; input_handler = command_line_handler; } else @@ -213,18 +224,6 @@ change_line_handler () first thing from .gdbinit. */ input_handler = command_line_handler; } - - /* To tell the event loop to change the handler associated with the - input file descriptor, we need to create a new event source, - corresponding to the same fd, but with a new event handler - function. */ - /* NOTE: this operates on input_fd, not instream. If we are reading - commands from a file, instream will point to the file. However in - async mode, we always read commands from a file with editing - off. This means that the 'set editing on/off' will have effect - only on the interactive session. */ - delete_file_handler (input_fd); - add_file_handler (input_fd, call_readline, 0); } /* Displays the prompt. The prompt that is displayed is the current @@ -239,8 +238,7 @@ change_line_handler () 3. Other???? FIXME: 2. & 3. not implemented yet for async. */ void -display_gdb_prompt (new_prompt) - char *new_prompt; +display_gdb_prompt (char *new_prompt) { int prompt_length = 0; char *gdb_prompt = get_prompt (); @@ -312,7 +310,7 @@ display_gdb_prompt (new_prompt) it pops the top of the prompt stack when we want the annotation level to be the normal ones (1 or 0). */ static void -change_annotation_level () +change_annotation_level (void) { char *prefix, *suffix; @@ -357,10 +355,7 @@ change_annotation_level () strings, except when the annotation level is 2. Memory is allocated within savestring for the new prompt. */ void -push_prompt (prefix, prompt, suffix) - char *prefix; - char *prompt; - char *suffix; +push_prompt (char *prefix, char *prompt, char *suffix) { the_prompts.top++; PREFIX (0) = savestring (prefix, strlen (prefix)); @@ -378,7 +373,7 @@ push_prompt (prefix, prompt, suffix) /* Pops the top of the prompt stack, and frees the memory allocated for it. */ void -pop_prompt () +pop_prompt (void) { /* If we are not during a 'synchronous' execution command, in which case, the top prompt would be empty. */ @@ -398,6 +393,26 @@ pop_prompt () free (SUFFIX (0)); the_prompts.top--; } + +/* When there is an event ready on the stdin file desriptor, instead + of calling readline directly throught the callback function, or + instead of calling gdb_readline2, give gdb a chance to detect + errors and do something. */ +void +stdin_event_handler (int error, int fd, gdb_client_data client_data) +{ + if (error) + { + printf_unfiltered ("error detected on stdin, fd %d\n", fd); + delete_file_handler (fd); + discard_all_continuations (); + /* If stdin died, we may as well kill gdb. */ + exit (1); + } + else + (*call_readline) (client_data); +} + /* Handles a gdb command. This function is called by command_line_handler, which has processed one or more input lines @@ -406,8 +421,7 @@ pop_prompt () function. The command_loop function will be obsolete when we switch to use the event loop at every execution of gdb. */ static void -command_handler (command) - char *command; +command_handler (char *command) { struct cleanup *old_chain; int stdin_is_tty = ISATTY (stdin); @@ -507,8 +521,7 @@ command_handler (command) are always running synchronously. Or if we have just executed a command that doesn't start the target. */ void -command_line_handler_continuation (arg) - struct continuation_arg *arg; +command_line_handler_continuation (struct continuation_arg *arg) { extern int display_time; extern int display_space; @@ -551,8 +564,7 @@ command_line_handler_continuation (arg) obsolete once we use the event loop as the default mechanism in GDB. */ static void -command_line_handler (rl) - char *rl; +command_line_handler (char *rl) { static char *linebuffer = 0; static unsigned linelength = 0; @@ -768,7 +780,7 @@ command_line_handler (rl) will become obsolete when the event loop is made the default execution for gdb. */ void -gdb_readline2 () +gdb_readline2 (gdb_client_data client_data) { int c; char *result; @@ -851,7 +863,7 @@ gdb_readline2 () init_signals will become obsolete as we move to have to event loop as the default for gdb. */ void -async_init_signals () +async_init_signals (void) { signal (SIGINT, handle_sigint); sigint_token = @@ -899,17 +911,15 @@ async_init_signals () } void -mark_async_signal_handler_wrapper (token) - void *token; +mark_async_signal_handler_wrapper (PTR token) { - mark_async_signal_handler ((async_signal_handler *) token); + mark_async_signal_handler ((struct async_signal_handler *) token); } /* Tell the event loop what to do if SIGINT is received. See event-signal.c. */ void -handle_sigint (sig) - int sig; +handle_sigint (int sig) { signal (sig, handle_sigint); @@ -930,8 +940,7 @@ handle_sigint (sig) /* Do the quit. All the checks have been done by the caller. */ void -async_request_quit (arg) - gdb_client_data arg; +async_request_quit (gdb_client_data arg) { quit_flag = 1; #ifdef REQUEST_QUIT @@ -944,8 +953,7 @@ async_request_quit (arg) /* Tell the event loop what to do if SIGQUIT is received. See event-signal.c. */ static void -handle_sigquit (sig) - int sig; +handle_sigquit (int sig) { mark_async_signal_handler_wrapper (sigquit_token); signal (sig, handle_sigquit); @@ -953,8 +961,7 @@ handle_sigquit (sig) /* Called by the event loop in response to a SIGQUIT. */ static void -async_do_nothing (arg) - gdb_client_data arg; +async_do_nothing (gdb_client_data arg) { /* Empty function body. */ } @@ -972,8 +979,7 @@ handle_sighup (sig) /* Called by the event loop to process a SIGHUP */ static void -async_disconnect (arg) - gdb_client_data arg; +async_disconnect (gdb_client_data arg) { catch_errors (quit_cover, NULL, "Could not kill the program being debugged", @@ -985,16 +991,14 @@ async_disconnect (arg) #ifdef STOP_SIGNAL void -handle_stop_sig (sig) - int sig; +handle_stop_sig (int sig) { mark_async_signal_handler_wrapper (sigtstp_token); signal (sig, handle_stop_sig); } static void -async_stop_sig (arg) - gdb_client_data arg; +async_stop_sig (gdb_client_data arg) { char *prompt = get_prompt (); #if STOP_SIGNAL == SIGTSTP @@ -1016,8 +1020,7 @@ async_stop_sig (arg) /* Tell the event loop what to do if SIGFPE is received. See event-signal.c. */ static void -handle_sigfpe (sig) - int sig; +handle_sigfpe (int sig) { mark_async_signal_handler_wrapper (sigfpe_token); signal (sig, handle_sigfpe); @@ -1025,8 +1028,7 @@ handle_sigfpe (sig) /* Event loop will call this functin to process a SIGFPE. */ static void -async_float_handler (arg) - gdb_client_data arg; +async_float_handler (gdb_client_data arg) { /* This message is based on ANSI C, section 4.7. Note that integer divide by zero causes this, so "float" is a misnomer. */ @@ -1037,8 +1039,7 @@ async_float_handler (arg) See event-signal.c. */ #if defined(SIGWINCH) && defined(SIGWINCH_HANDLER) static void -handle_sigwinch (sig) - int sig; +handle_sigwinch (int sig) { mark_async_signal_handler_wrapper (sigwinch_token); signal (sig, handle_sigwinch); @@ -1049,10 +1050,7 @@ handle_sigwinch (sig) /* Called by do_setshow_command. */ /* ARGSUSED */ void -set_async_editing_command (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; +set_async_editing_command (char *args, int from_tty, struct cmd_list_element *c) { change_line_handler (); } @@ -1060,10 +1058,7 @@ set_async_editing_command (args, from_tty, c) /* Called by do_setshow_command. */ /* ARGSUSED */ void -set_async_annotation_level (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; +set_async_annotation_level (char *args, int from_tty, struct cmd_list_element *c) { change_annotation_level (); } @@ -1071,10 +1066,7 @@ set_async_annotation_level (args, from_tty, c) /* Called by do_setshow_command. */ /* ARGSUSED */ void -set_async_prompt (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; +set_async_prompt (char *args, int from_tty, struct cmd_list_element *c) { PROMPT (0) = savestring (new_async_prompt, strlen (new_async_prompt)); } @@ -1083,13 +1075,13 @@ set_async_prompt (args, from_tty, c) interface, i.e. via a callback function (rl_callback_read_char), and hook up instream to the event loop. */ void -_initialize_event_loop () +_initialize_event_loop (void) { if (async_p) { /* When a character is detected on instream by select or poll, readline will be invoked via this callback function. */ - call_readline = rl_callback_read_char; + call_readline = rl_callback_read_char_wrapper; /* When readline has read an end-of-line character, it passes the complete line to gdb for processing. command_line_handler @@ -1113,7 +1105,7 @@ _initialize_event_loop () the target program (inferior), but that must be registered only when it actually exists (I.e. after we say 'run' or after we connect to a remote target. */ - add_file_handler (input_fd, call_readline, 0); + add_file_handler (input_fd, stdin_event_handler, 0); /* Tell gdb that we will be using the readline library. This could be overwritten by a command in .gdbinit like 'set diff --git a/gdb/frame.h b/gdb/frame.h index d154b9408ce..b7ab53031cc 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -27,13 +27,13 @@ /* XXXX - deprecated */ struct frame_saved_regs { + /* For each register R (except the SP), regs[R] is the address at + which it was saved on entry to the frame, or zero if it was not + saved on entry to this frame. This includes special registers + such as pc and fp saved in special ways in the stack frame. - /* For each register, address of where it was saved on entry to - the frame, or zero if it was not saved on entry to this frame. - This includes special registers such as pc and fp saved in - special ways in the stack frame. The SP_REGNUM is even more - special, the address here is the sp for the next frame, not the - address where the sp was saved. */ + regs[SP_REGNUM] is different. It holds the actual SP, not the + address at which it was saved. */ CORE_ADDR regs[NUM_REGS]; }; diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c index 0601a0d7d62..f16b522b5eb 100644 --- a/gdb/go32-nat.c +++ b/gdb/go32-nat.c @@ -34,6 +34,7 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <unistd.h> #include <io.h> #include <dpmi.h> #include <debug/v2load.h> @@ -797,6 +798,7 @@ ignore (void) do {\ CONTROL &= ~(DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (index)));\ D_REGS[index] = address;\ + dr_ref_count[index]++;\ } while(0) #define SET_WATCH(index,address,rw,len) \ @@ -808,11 +810,7 @@ ignore (void) #define IS_WATCH(index) \ (CONTROL & (DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE*(index)))) -#define WATCH_HIT(index) \ - (\ - (STATUS & (1 << index)) && \ - (CONTROL & (DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index)))\ - ) +#define WATCH_HIT(index) ((STATUS & (1 << (index))) && IS_WATCH(index)) #define DR_DEF(index) \ ((CONTROL >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (index))) & 0x0f) @@ -1142,10 +1140,6 @@ go32_insert_hw_breakpoint (CORE_ADDR addr, CORE_ADDR shadow) return i < 4 ? 0 : -1; } -static int inf_flags_valid = 0; -static int inf_in_flag; -static int inf_out_flag; - /* Put the device open on handle FD into either raw or cooked mode, return 1 if it was in raw mode, zero otherwise. */ diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 5751b45e1dd..ffcbf32b6b4 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -341,8 +341,12 @@ internalize_unwinds (objfile, table, section, entries, size, text_offset) low_text_segment_address = -1; /* If addresses are 64 bits wide, then unwinds are supposed to - be segment relative offsets instead of absolute addresses. */ - if (TARGET_PTR_BIT == 64) + be segment relative offsets instead of absolute addresses. + + Note that when loading a shared library (text_offset != 0) the + unwinds are already relative to the text_offset that will be + passed in. */ + if (TARGET_PTR_BIT == 64 && text_offset == 0) { bfd_map_over_sections (objfile->obfd, record_text_segment_lowaddr, (PTR) NULL); @@ -1102,6 +1106,12 @@ frame_chain (frame) CORE_ADDR frame_base; struct frame_info *tmp_frame; + /* A frame in the current frame list, or zero. */ + struct frame_info *saved_regs_frame = 0; + /* Where the registers were saved in saved_regs_frame. + If saved_regs_frame is zero, this is garbage. */ + struct frame_saved_regs saved_regs; + CORE_ADDR caller_pc; struct minimal_symbol *min_frame_symbol; @@ -1195,8 +1205,7 @@ frame_chain (frame) We use information from unwind descriptors to determine if %r3 is saved into the stack (Entry_GR field has this information). */ - tmp_frame = frame; - while (tmp_frame) + for (tmp_frame = frame; tmp_frame; tmp_frame = tmp_frame->next) { u = find_unwind_entry (tmp_frame->pc); @@ -1216,14 +1225,25 @@ frame_chain (frame) return (CORE_ADDR) 0; } - /* Entry_GR specifies the number of callee-saved general registers - saved in the stack. It starts at %r3, so %r3 would be 1. */ - if (u->Entry_GR >= 1 || u->Save_SP + if (u->Save_SP || tmp_frame->signal_handler_caller || pc_in_interrupt_handler (tmp_frame->pc)) break; - else - tmp_frame = tmp_frame->next; + + /* Entry_GR specifies the number of callee-saved general registers + saved in the stack. It starts at %r3, so %r3 would be 1. */ + if (u->Entry_GR >= 1) + { + /* The unwind entry claims that r3 is saved here. However, + in optimized code, GCC often doesn't actually save r3. + We'll discover this if we look at the prologue. */ + get_frame_saved_regs (tmp_frame, &saved_regs); + saved_regs_frame = tmp_frame; + + /* If we have an address for r3, that's good. */ + if (saved_regs.regs[FP_REGNUM]) + break; + } } if (tmp_frame) @@ -1239,8 +1259,6 @@ frame_chain (frame) /* %r3 was saved somewhere in the stack. Dig it out. */ else { - struct frame_saved_regs saved_regs; - /* Sick. For optimization purposes many kernels don't have the @@ -1267,7 +1285,8 @@ frame_chain (frame) fail miserably if the function which performs the system call has a variable sized stack frame. */ - get_frame_saved_regs (tmp_frame, &saved_regs); + if (tmp_frame != saved_regs_frame) + get_frame_saved_regs (tmp_frame, &saved_regs); /* Abominable hack. */ if (current_target.to_has_execution == 0 @@ -1296,14 +1315,14 @@ frame_chain (frame) } else { - struct frame_saved_regs saved_regs; - /* Get the innermost frame. */ tmp_frame = frame; while (tmp_frame->next != NULL) tmp_frame = tmp_frame->next; - get_frame_saved_regs (tmp_frame, &saved_regs); + if (tmp_frame != saved_regs_frame) + get_frame_saved_regs (tmp_frame, &saved_regs); + /* Abominable hack. See above. */ if (current_target.to_has_execution == 0 && ((saved_regs.regs[FLAGS_REGNUM] @@ -1670,19 +1689,22 @@ restore_pc_queue (fsr) return 1; } + +#ifdef PA20W_CALLING_CONVENTIONS + /* This function pushes a stack frame with arguments as part of the inferior function calling mechanism. - For PAs the stack always grows to higher addresses. However the arguments - may grow to either higher or lower addresses depending on which ABI is - currently in use. + This is the version for the PA64, in which later arguments appear + at higher addresses. (The stack always grows towards higher + addresses.) We simply allocate the appropriate amount of stack space and put arguments into their proper slots. The call dummy code will copy arguments into registers as needed by the ABI. - Note for the PA64 ABI we load up the argument pointer since the caller - must provide the argument pointer to the callee. */ + This ABI also requires that the caller provide an argument pointer + to the callee, so we do that too. */ CORE_ADDR hppa_push_arguments (nargs, args, sp, struct_return, struct_addr) @@ -1716,30 +1738,137 @@ hppa_push_arguments (nargs, args, sp, struct_return, struct_addr) /* Iterate over each argument provided by the user. */ for (i = 0; i < nargs; i++) { - lengths[i] = TYPE_LENGTH (VALUE_TYPE (args[i])); + struct type *arg_type = VALUE_TYPE (args[i]); + + /* Integral scalar values smaller than a register are padded on + the left. We do this by promoting them to full-width, + although the ABI says to pad them with garbage. */ + if (is_integral_type (arg_type) + && TYPE_LENGTH (arg_type) < REGISTER_SIZE) + { + args[i] = value_cast ((TYPE_UNSIGNED (arg_type) + ? builtin_type_unsigned_long + : builtin_type_long), + args[i]); + arg_type = VALUE_TYPE (args[i]); + } + + lengths[i] = TYPE_LENGTH (arg_type); /* Align the size of the argument to the word size for this target. */ bytes_reserved = (lengths[i] + REGISTER_SIZE - 1) & -REGISTER_SIZE; -#ifdef ARGS_GROW_DOWNWARD - offset[i] = cum_bytes_reserved + lengths[i]; -#else - /* If the arguments grow towards lower addresses, then we want - offset[i] to point to the start of the argument rather than - the end of the argument. */ offset[i] = cum_bytes_reserved; - offset[i] += (lengths[i] < REGISTER_SIZE - ? REGISTER_SIZE - lengths[i] : 0); -#endif + /* Aggregates larger than eight bytes (the only types larger + than eight bytes we have) are aligned on a 16-byte boundary, + possibly padded on the right with garbage. This may leave an + empty word on the stack, and thus an unused register, as per + the ABI. */ + if (bytes_reserved > 8) + { + /* Round up the offset to a multiple of two slots. */ + int new_offset = ((offset[i] + 2*REGISTER_SIZE-1) + & -(2*REGISTER_SIZE)); - /* If the argument is a double word argument, then it needs to be - double word aligned. + /* Note the space we've wasted, if any. */ + bytes_reserved += new_offset - offset[i]; + offset[i] = new_offset; + } - ?!? I do not think this code is correct when !ARGS_GROW_DOWNWAR. */ + cum_bytes_reserved += bytes_reserved; + } + + /* CUM_BYTES_RESERVED already accounts for all the arguments + passed by the user. However, the ABIs mandate minimum stack space + allocations for outgoing arguments. + + The ABIs also mandate minimum stack alignments which we must + preserve. */ + cum_bytes_aligned = STACK_ALIGN (cum_bytes_reserved); + sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE); + + /* Now write each of the args at the proper offset down the stack. */ + for (i = 0; i < nargs; i++) + write_memory (orig_sp + offset[i], VALUE_CONTENTS (args[i]), lengths[i]); + + /* If a structure has to be returned, set up register 28 to hold its + address */ + if (struct_return) + write_register (28, struct_addr); + + /* For the PA64 we must pass a pointer to the outgoing argument list. + The ABI mandates that the pointer should point to the first byte of + storage beyond the register flushback area. + + However, the call dummy expects the outgoing argument pointer to + be passed in register %r4. */ + write_register (4, orig_sp + REG_PARM_STACK_SPACE); + + /* ?!? This needs further work. We need to set up the global data + pointer for this procedure. This assumes the same global pointer + for every procedure. The call dummy expects the dp value to + be passed in register %r6. */ + write_register (6, read_register (27)); + + /* The stack will have 64 bytes of additional space for a frame marker. */ + return sp + 64; +} + +#else + +/* This function pushes a stack frame with arguments as part of the + inferior function calling mechanism. + + This is the version of the function for the 32-bit PA machines, in + which later arguments appear at lower addresses. (The stack always + grows towards higher addresses.) + + We simply allocate the appropriate amount of stack space and put + arguments into their proper slots. The call dummy code will copy + arguments into registers as needed by the ABI. */ + +CORE_ADDR +hppa_push_arguments (nargs, args, sp, struct_return, struct_addr) + int nargs; + value_ptr *args; + CORE_ADDR sp; + int struct_return; + CORE_ADDR struct_addr; +{ + /* array of arguments' offsets */ + int *offset = (int *) alloca (nargs * sizeof (int)); + + /* array of arguments' lengths: real lengths in bytes, not aligned to + word size */ + int *lengths = (int *) alloca (nargs * sizeof (int)); + + /* The number of stack bytes occupied by the current argument. */ + int bytes_reserved; + + /* The total number of bytes reserved for the arguments. */ + int cum_bytes_reserved = 0; + + /* Similarly, but aligned. */ + int cum_bytes_aligned = 0; + int i; + + /* Iterate over each argument provided by the user. */ + for (i = 0; i < nargs; i++) + { + lengths[i] = TYPE_LENGTH (VALUE_TYPE (args[i])); + + /* Align the size of the argument to the word size for this + target. */ + bytes_reserved = (lengths[i] + REGISTER_SIZE - 1) & -REGISTER_SIZE; + + offset[i] = cum_bytes_reserved + lengths[i]; + + /* If the argument is a double word argument, then it needs to be + double word aligned. */ if ((bytes_reserved == 2 * REGISTER_SIZE) - && (offset[i] % 2 * REGISTER_SIZE)) + && (offset[i] % 2 * REGISTER_SIZE)) { int new_offset = 0; /* BYTES_RESERVED is already aligned to the word, so we put @@ -1761,55 +1890,31 @@ hppa_push_arguments (nargs, args, sp, struct_return, struct_addr) } - /* CUM_BYTES_RESERVED already accounts for all the arguments - passed by the user. However, the ABIs mandate minimum stack space + /* CUM_BYTES_RESERVED already accounts for all the arguments passed + by the user. However, the ABI mandates minimum stack space allocations for outgoing arguments. - The ABIs also mandate minimum stack alignments which we must + The ABI also mandates minimum stack alignments which we must preserve. */ cum_bytes_aligned = STACK_ALIGN (cum_bytes_reserved); sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE); /* Now write each of the args at the proper offset down the stack. - - The two ABIs write arguments in different directions using different - starting points. What fun. - ?!? We need to promote values to a full register instead of skipping words in the stack. */ -#ifndef ARGS_GROW_DOWNWARD - for (i = 0; i < nargs; i++) - write_memory (orig_sp + offset[i], VALUE_CONTENTS (args[i]), lengths[i]); -#else for (i = 0; i < nargs; i++) write_memory (sp - offset[i], VALUE_CONTENTS (args[i]), lengths[i]); -#endif /* If a structure has to be returned, set up register 28 to hold its address */ if (struct_return) write_register (28, struct_addr); -#ifndef ARGS_GROW_DOWNWARD - /* For the PA64 we must pass a pointer to the outgoing argument list. - The ABI mandates that the pointer should point to the first byte of - storage beyond the register flushback area. - - However, the call dummy expects the outgoing argument pointer to - be passed in register %r4. */ - write_register (4, orig_sp + REG_PARM_STACK_SPACE); - - /* ?!? This needs further work. We need to set up the global data - pointer for this procedure. This assumes the same global pointer - for every procedure. The call dummy expects the dp value to - be passed in register %r6. */ - write_register (6, read_register (27)); -#endif - /* The stack will have 32 bytes of additional space for a frame marker. */ return sp + 32; } +#endif /* elz: this function returns a value which is built looking at the given address. It is called from call_function_by_hand, in case we need to return a @@ -1973,8 +2078,8 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) CORE_ADDR solib_handle = 0; /* Nonzero if we will use GCC's PLT call routine. This routine must be - passed an import stub, not a PLABEL. It is also necessary to set %r19 - (the PIC register) before performing the call. + passed an import stub, not a PLABEL. It is also necessary to set %r19 + (the PIC register) before performing the call. If zero, then we are using __d_plt_call (HP's PLT call routine) or we are calling the target directly. When using __d_plt_call we want to @@ -2045,7 +2150,7 @@ hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) write_register (5, fun); /* We need to see if this objfile has a different DP value than our - own (it could be a shared library for example. */ + own (it could be a shared library for example). */ ALL_OBJFILES (objfile) { struct obj_section *s; @@ -2822,8 +2927,73 @@ in_solib_call_trampoline (pc, name) static CORE_ADDR dyncall = 0; static CORE_ADDR sr4export = 0; -/* FIXME XXX - dyncall and sr4export must be initialized whenever we get a - new exec file */ +#ifdef GDB_TARGET_IS_HPPA_20W + /* PA64 has a completely different stub/trampoline scheme. Is it + better? Maybe. It's certainly harder to determine with any + certainty that we are in a stub because we can not refer to the + unwinders to help. + + The heuristic is simple. Try to lookup the current PC value in th + minimal symbol table. If that fails, then assume we are not in a + stub and return. + + Then see if the PC value falls within the section bounds for the + section containing the minimal symbol we found in the first + step. If it does, then assume we are not in a stub and return. + + Finally peek at the instructions to see if they look like a stub. */ + { + struct minimal_symbol *minsym; + asection *sec; + CORE_ADDR addr; + int insn, i; + + minsym = lookup_minimal_symbol_by_pc (pc); + if (! minsym) + return 0; + + sec = SYMBOL_BFD_SECTION (minsym); + + if (sec->vma <= pc + && sec->vma + sec->_cooked_size < pc) + return 0; + + /* We might be in a stub. Peek at the instructions. Stubs are 3 + instructions long. */ + insn = read_memory_integer (pc, 4); + + /* Find out where we we think we are within the stub. */ + if ((insn & 0xffffc00e) == 0x53610000) + addr = pc; + else if ((insn & 0xffffffff) == 0xe820d000) + addr = pc - 4; + else if ((insn & 0xffffc00e) == 0x537b0000) + addr = pc - 8; + else + return 0; + + /* Now verify each insn in the range looks like a stub instruction. */ + insn = read_memory_integer (addr, 4); + if ((insn & 0xffffc00e) != 0x53610000) + return 0; + + /* Now verify each insn in the range looks like a stub instruction. */ + insn = read_memory_integer (addr + 4, 4); + if ((insn & 0xffffffff) != 0xe820d000) + return 0; + + /* Now verify each insn in the range looks like a stub instruction. */ + insn = read_memory_integer (addr + 8, 4); + if ((insn & 0xffffc00e) != 0x537b0000) + return 0; + + /* Looks like a stub. */ + return 1; + } +#endif + + /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a + new exec file */ /* First see if PC is in one of the two C-library trampolines. */ if (!dyncall) @@ -2997,9 +3167,8 @@ skip_trampoline_code (pc, name) struct minimal_symbol *msym; struct unwind_table_entry *u; - -/* FIXME XXX - dyncall and sr4export must be initialized whenever we get a - new exec file */ + /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a + new exec file */ if (!dyncall) { @@ -3829,16 +3998,21 @@ hppa_frame_find_saved_regs (frame_info, frame_saved_regs) /* There are limited ways to store the return pointer into the stack. */ - if (inst == 0x6bc23fd9 || inst == 0x0fc212c1) + if (inst == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */ { save_rp = 0; frame_saved_regs->regs[RP_REGNUM] = frame_info->frame - 20; } + else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */ + { + save_rp = 0; + frame_saved_regs->regs[RP_REGNUM] = frame_info->frame - 16; + } /* Note if we saved SP into the stack. This also happens to indicate the location of the saved frame pointer. */ - if ((inst & 0xffffc000) == 0x6fc10000 - || (inst & 0xffffc00c) == 0x73c10008) + if ( (inst & 0xffffc000) == 0x6fc10000 /* stw,ma r1,N(sr0,sp) */ + || (inst & 0xffffc00c) == 0x73c10008) /* std,ma r1,N(sr0,sp) */ { frame_saved_regs->regs[FP_REGNUM] = frame_info->frame; save_sp = 0; @@ -4542,6 +4716,30 @@ hppa_prepare_to_proceed () #endif /* PREPARE_TO_PROCEED */ void +hppa_skip_permanent_breakpoint () +{ + /* To step over a breakpoint instruction on the PA takes some + fiddling with the instruction address queue. + + When we stop at a breakpoint, the IA queue front (the instruction + we're executing now) points at the breakpoint instruction, and + the IA queue back (the next instruction to execute) points to + whatever instruction we would execute after the breakpoint, if it + were an ordinary instruction. This is the case even if the + breakpoint is in the delay slot of a branch instruction. + + Clearly, to step past the breakpoint, we need to set the queue + front to the back. But what do we put in the back? What + instruction comes after that one? Because of the branch delay + slot, the next insn is always at the back + 4. */ + write_register (PCOQ_HEAD_REGNUM, read_register (PCOQ_TAIL_REGNUM)); + write_register (PCSQ_HEAD_REGNUM, read_register (PCSQ_TAIL_REGNUM)); + + write_register (PCOQ_TAIL_REGNUM, read_register (PCOQ_TAIL_REGNUM) + 4); + /* We can leave the tail's space the same, since there's no jump. */ +} + +void _initialize_hppa_tdep () { tm_print_insn = print_insn_hppa; diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 6aef61b31c3..20294087904 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -684,13 +684,19 @@ i386_extract_return_value (type, regbuf, valbuf) double d; /* 387 %st(0), gcc uses this */ floatformat_to_double (&floatformat_i387_ext, - ®buf[REGISTER_BYTE(FPDATA_REGNUM)], +#if defined(FPDATA_REGNUM) + ®buf[REGISTER_BYTE (FPDATA_REGNUM)], +#else /* !FPDATA_REGNUM */ + ®buf[REGISTER_BYTE (FP0_REGNUM)], +#endif /* FPDATA_REGNUM */ + &d); store_floating (valbuf, TYPE_LENGTH (type), d); } else #endif /* I386_AIX_TARGET || I386_GNULINUX_TARGET*/ { +#if defined(LOW_RETURN_REGNUM) int len = TYPE_LENGTH (type); int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM); int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM); @@ -708,6 +714,9 @@ i386_extract_return_value (type, regbuf, valbuf) } else error ("GDB bug: i386-tdep.c (i386_extract_return_value): Don't know how to find a return value %d bytes long", len); +#else /* !LOW_RETURN_REGNUM */ + memcpy (valbuf, regbuf, TYPE_LENGTH (type)); +#endif /* LOW_RETURN_REGNUM */ } } @@ -961,51 +970,6 @@ set_disassembly_flavor () set_architecture_from_arch_mach (bfd_arch_i386, bfd_mach_i386_i386_intel_syntax); } -/* Print the register regnum, or all registers if regnum is -1 */ - -void -i386_do_registers_info (regnum, fpregs) - int regnum; - int fpregs; -{ - char raw_regs [REGISTER_BYTES]; - int i; - - for (i = 0; i < NUM_REGS; i++) - read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i)); - - if (regnum < FPSTART_REGNUM) - i386_print_register (raw_regs, regnum, fpregs); - else - i387_print_register (raw_regs, regnum); -} - -static void -i386_print_register (raw_regs, regnum, fpregs) - char *raw_regs; - int regnum; - int fpregs; -{ - int i; - long val; - char string[12]; - - for (i = 0; i < FPSTART_REGNUM; i++) - { - if ((regnum != -1) && (i != regnum)) - continue; - - val = extract_signed_integer (raw_regs + REGISTER_BYTE (i), 4); - - sprintf(string, "0x%x", val); - printf_filtered ("%8.8s: %10.10s %11d\n", REGISTER_NAME(i), string, val); - } - - if ((regnum == -1) && fpregs) - for (i = FPSTART_REGNUM; i < FPEND_REGNUM; i++) - i387_print_register (raw_regs, i); -} - void _initialize_i386_tdep () { diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index a8fdba7ebed..aac013c79a4 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -149,145 +149,6 @@ print_387_status_word (status) puts_unfiltered ("\n"); } -void -i387_print_register (raw_regs, regnum) - char *raw_regs; - int regnum; -{ - unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; - unsigned long val; - int j, sign, special; - unsigned swd, tags, expon, top, norm, ls, ms; - char string[12]; - -#if (FPREG_RAW_SIZE != 10) -#error "Bad FPREG_RAW_SIZE" -#endif - - printf_filtered ("%8.8s: ", REGISTER_NAME (regnum)); - if (regnum < FPDATA_REGNUM) - { - val = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum), 4); - if ( (regnum < FPSTART_REGNUM + 3) || - (regnum == FPSTART_REGNUM + 6) ) - /* Don't print the un-modifiable bytes. */ - sprintf(string, "0x%04x", val & 0xffff); - else - sprintf(string, "0x%08x", val); - - printf_unfiltered ("%10.10s", string); - - if (regnum == FPCONTROL_REGNUM) - print_387_control_bits (val); - else if (regnum == FPSTATUS_REGNUM) - print_387_status_bits (val); - } - else - { - /* An FPU stack register. */ - if ( REGISTER_RAW_SIZE (regnum) != FPREG_RAW_SIZE ) - error ("GDB bug: i387-tdep.c (i387_print_register): wrong size for FPU stack register"); - - /* Put the data in the buffer. No conversions are ever necessary. */ - memcpy (virtual_buffer, raw_regs + REGISTER_BYTE (regnum), - FPREG_RAW_SIZE); - - swd = extract_signed_integer (raw_regs + REGISTER_BYTE (FPSTATUS_REGNUM), - 4); - top = (swd >> 11) & 7; - tags = extract_signed_integer (raw_regs + REGISTER_BYTE (FPTAG_REGNUM), - 4); - - puts_unfiltered ("0x"); - for (j = 0; j < FPREG_RAW_SIZE; j++) - printf_unfiltered ("%02x", - (unsigned char)raw_regs[REGISTER_BYTE (regnum) - + FPREG_RAW_SIZE - 1 - j]); - - puts_unfiltered (" "); - special = 0; - switch ((tags >> (((regnum - FPDATA_REGNUM + top) & 7) * 2)) & 3) - { - case 0: puts_unfiltered ("Valid "); break; - case 1: puts_unfiltered ("Zero "); break; - case 2: puts_unfiltered ("Spec "); - special = 1; - break; - case 3: puts_unfiltered ("Empty "); break; - } - - expon = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) - + FPREG_RAW_SIZE - 2, 2); - sign = expon & 0x8000; - expon &= 0x7fff; - ms = extract_unsigned_integer (raw_regs + REGISTER_BYTE (regnum) + 4, 4); - ls = extract_signed_integer (raw_regs + REGISTER_BYTE (regnum), 4); - norm = ms & 0x80000000; - - if ( expon == 0 ) - { - if ( ms | ls ) - { - /* Denormal or Pseudodenormal. */ - if ( norm ) - puts_unfiltered ("Pseudo "); - else - puts_unfiltered ("Denorm "); - } - else - { - /* Zero. */ - puts_unfiltered ("Zero "); - } - } - else if ( expon == 0x7fff ) - { - /* Infinity, NaN or unsupported. */ - if ( (ms == 0x80000000) && - (ls == 0) ) - { - puts_unfiltered ("Infty "); - } - else if ( norm ) - { - if ( ms & 0x40000000 ) - puts_unfiltered ("QNaN "); - else - puts_unfiltered ("SNaN "); - } - else - { - puts_unfiltered ("Unsupp "); - } - } - else - { - /* Normal or unsupported. */ - if ( norm ) - puts_unfiltered ("Normal "); - else - puts_unfiltered ("Unsupp "); - } - - val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0, - gdb_stdout, 0, - 1, 0, Val_pretty_default); - } - puts_filtered ("\n"); -} - -void i387_float_info(void) -{ - char raw_regs [REGISTER_BYTES]; - int i; - - for (i = FPSTART_REGNUM; i <= FPEND_REGNUM; i++) - read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i)); - - for (i = FPSTART_REGNUM; i <= FPEND_REGNUM; i++) - i387_print_register (raw_regs, i); -} - #ifdef LD_I387 int i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr) diff --git a/gdb/inferior.h b/gdb/inferior.h index 8f2f43502d3..b0a6fa62c02 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -158,7 +158,7 @@ extern void generic_target_write_fp PARAMS ((CORE_ADDR)); extern void wait_for_inferior PARAMS ((void)); -extern void fetch_inferior_event PARAMS ((void)); +extern void fetch_inferior_event PARAMS ((void *)); extern void init_wait_for_inferior PARAMS ((void)); diff --git a/gdb/inflow.c b/gdb/inflow.c index 02b5be20266..bbd92b9e9a3 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -492,7 +492,7 @@ child_terminal_info (args, from_tty) printf_filtered ("Process group = %d\n", inferior_process_group); #endif - SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate); + SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate, gdb_stdout); } /* NEW_TTY_PREFORK is called before forking a new child process, diff --git a/gdb/infrun.c b/gdb/infrun.c index a46587ecb24..dd569c3dd05 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -35,6 +35,8 @@ #include "top.h" #include <signal.h> #include "event-loop.h" +#include "event-top.h" +#include "remote.h" /* For cleanup_sigint_signal_handler. */ /* Prototypes for local functions */ @@ -268,6 +270,26 @@ static int use_thread_step_needed = USE_THREAD_STEP_NEEDED; #define INSTRUCTION_NULLIFIED 0 #endif +/* We can't step off a permanent breakpoint in the ordinary way, because we + can't remove it. Instead, we have to advance the PC to the next + instruction. This macro should expand to a pointer to a function that + does that, or zero if we have no such function. If we don't have a + definition for it, we have to report an error. */ +#ifndef SKIP_PERMANENT_BREAKPOINT +#define SKIP_PERMANENT_BREAKPOINT (default_skip_permanent_breakpoint) +static void +default_skip_permanent_breakpoint () +{ + error_begin (); + fprintf_filtered (gdb_stderr, "\ +The program is stopped at a permanent breakpoint, but GDB does not know\n\ +how to step past a permanent breakpoint on this architecture. Try using\n\ +a command like `return' or `jump' to continue execution.\n"); + return_to_top_level (RETURN_ERROR); +} +#endif + + /* Convert the #defines into values. This is temporary until wfi control flow is completely sorted out. */ @@ -766,6 +788,8 @@ set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c) } + + /* Resume the inferior, but allow a QUIT. This is useful if the user wants to interrupt some lengthy single-stepping operation (for child processes, the SIGINT goes to the inferior, and so @@ -790,6 +814,13 @@ resume (int step, enum target_signal sig) step = 0; #endif + /* Normally, by the time we reach `resume', the breakpoints are either + removed or inserted, as appropriate. The exception is if we're sitting + at a permanent breakpoint; we need to step over it, but permanent + breakpoints can't be removed. So we have to test for it here. */ + if (breakpoint_here_p (read_pc ()) == permanent_breakpoint_here) + SKIP_PERMANENT_BREAKPOINT (); + if (SOFTWARE_SINGLE_STEP_P && step) { /* Do it the hard way, w/temp breakpoints */ @@ -1175,6 +1206,7 @@ void init_execution_control_state (struct execution_control_state * ecs); void handle_inferior_event (struct execution_control_state * ecs); static void check_sigtramp2 (struct execution_control_state *ecs); +static void step_into_function (struct execution_control_state *ecs); static void step_over_function (struct execution_control_state *ecs); static void stop_stepping (struct execution_control_state *ecs); static void prepare_to_wait (struct execution_control_state *ecs); @@ -1250,7 +1282,8 @@ struct execution_control_state async_ecss; struct execution_control_state *async_ecs; void -fetch_inferior_event (void) +fetch_inferior_event (client_data) + gdb_client_data client_data; { static struct cleanup *old_cleanups; @@ -2761,66 +2794,15 @@ handle_inferior_event (struct execution_control_state *ecs) tmp_sal = find_pc_line (ecs->stop_func_start, 0); if (tmp_sal.line != 0) - goto step_into_function; + { + step_into_function (ecs); + return; + } } step_over_function (ecs); keep_going (ecs); return; - step_into_function: - /* Subroutine call with source code we should not step over. - Do step to the first line of code in it. */ - { - struct symtab *s; - - s = find_pc_symtab (stop_pc); - if (s && s->language != language_asm) - ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start); - } - ecs->sal = find_pc_line (ecs->stop_func_start, 0); - /* Use the step_resume_break to step until - the end of the prologue, even if that involves jumps - (as it seems to on the vax under 4.2). */ - /* If the prologue ends in the middle of a source line, - continue to the end of that source line (if it is still - within the function). Otherwise, just go to end of prologue. */ -#ifdef PROLOGUE_FIRSTLINE_OVERLAP - /* no, don't either. It skips any code that's - legitimately on the first line. */ -#else - if (ecs->sal.end && ecs->sal.pc != ecs->stop_func_start && ecs->sal.end < ecs->stop_func_end) - ecs->stop_func_start = ecs->sal.end; -#endif - - if (ecs->stop_func_start == stop_pc) - { - /* We are already there: stop now. */ - stop_step = 1; - stop_stepping (ecs); - return; - } - else - /* Put the step-breakpoint there and go until there. */ - { - struct symtab_and_line sr_sal; - - INIT_SAL (&sr_sal); /* initialize to zeroes */ - sr_sal.pc = ecs->stop_func_start; - sr_sal.section = find_pc_overlay (ecs->stop_func_start); - /* Do not specify what the fp should be when we stop - since on some machines the prologue - is where the new fp value is established. */ - check_for_old_step_resume_breakpoint (); - step_resume_breakpoint = - set_momentary_breakpoint (sr_sal, NULL, bp_step_resume); - if (breakpoints_inserted) - insert_breakpoints (); - - /* And make sure stepping stops right away then. */ - step_range_end = step_range_start; - } - keep_going (ecs); - return; } /* We've wandered out of the step range. */ @@ -2980,6 +2962,63 @@ check_sigtramp2 (struct execution_control_state *ecs) } } +/* Subroutine call with source code we should not step over. Do step + to the first line of code in it. */ + +static void +step_into_function (struct execution_control_state *ecs) +{ + struct symtab *s; + struct symtab_and_line sr_sal; + + s = find_pc_symtab (stop_pc); + if (s && s->language != language_asm) + ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start); + + ecs->sal = find_pc_line (ecs->stop_func_start, 0); + /* Use the step_resume_break to step until the end of the prologue, + even if that involves jumps (as it seems to on the vax under + 4.2). */ + /* If the prologue ends in the middle of a source line, continue to + the end of that source line (if it is still within the function). + Otherwise, just go to end of prologue. */ +#ifdef PROLOGUE_FIRSTLINE_OVERLAP + /* no, don't either. It skips any code that's legitimately on the + first line. */ +#else + if (ecs->sal.end + && ecs->sal.pc != ecs->stop_func_start + && ecs->sal.end < ecs->stop_func_end) + ecs->stop_func_start = ecs->sal.end; +#endif + + if (ecs->stop_func_start == stop_pc) + { + /* We are already there: stop now. */ + stop_step = 1; + stop_stepping (ecs); + return; + } + else + { + /* Put the step-breakpoint there and go until there. */ + INIT_SAL (&sr_sal); /* initialize to zeroes */ + sr_sal.pc = ecs->stop_func_start; + sr_sal.section = find_pc_overlay (ecs->stop_func_start); + /* Do not specify what the fp should be when we stop since on + some machines the prologue is where the new fp value is + established. */ + check_for_old_step_resume_breakpoint (); + step_resume_breakpoint = + set_momentary_breakpoint (sr_sal, NULL, bp_step_resume); + if (breakpoints_inserted) + insert_breakpoints (); + + /* And make sure stepping stops right away then. */ + step_range_end = step_range_start; + } + keep_going (ecs); +} /* We've just entered a callee, and we wish to resume until it returns to the caller. Setting a step_resume breakpoint on the return @@ -3234,12 +3273,10 @@ stopped_for_internal_shlib_event (bpstat bs) static void complete_execution (void) { - extern int cleanup_sigint_signal_handler (void); - target_executing = 0; if (sync_execution) { - add_file_handler (input_fd, call_readline, 0); + add_file_handler (input_fd, stdin_event_handler, 0); pop_prompt (); sync_execution = 0; cleanup_sigint_signal_handler (); diff --git a/gdb/kod-cisco.c b/gdb/kod-cisco.c index c5be81ade93..ac82635d723 100644 --- a/gdb/kod-cisco.c +++ b/gdb/kod-cisco.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "gdb_string.h" +#include "kod.h" #ifdef HAVE_STDLIB_H #include <stdlib.h> @@ -43,8 +44,8 @@ static void (*gdb_kod_query) (char *, char *, int *); displaying output (presumably to the user) and the other for querying the target. */ char * -cisco_kod_open (void (*display_func) (char *), - void (*query_func) (char *, char *, int *)) +cisco_kod_open (kod_display_callback_ftype *display_func, + kod_query_callback_ftype *query_func) { char buffer[PBUFSIZ]; int bufsiz = PBUFSIZ; diff --git a/gdb/kod.c b/gdb/kod.c index a0969109cf8..cbe093fd419 100644 --- a/gdb/kod.c +++ b/gdb/kod.c @@ -25,6 +25,7 @@ #include "gdbcmd.h" #include "target.h" #include "gdb_string.h" +#include "kod.h" /* Prototypes for exported functions. */ void _initialize_kod (void); @@ -61,7 +62,8 @@ static void gdb_kod_query (char *, char *, int *); gdb_kod_close - This is called when the KOD connection to the remote should be terminated. */ -static char *(*gdb_kod_open) (void *, void *); +static char *(*gdb_kod_open) (kod_display_callback_ftype *display, + kod_query_callback_ftype *query); static void (*gdb_kod_request) (char *, int); static void (*gdb_kod_close) (); @@ -73,17 +75,6 @@ char *operating_system; switching OS's. */ static char *old_operating_system; -/* Functions imported from the library for all supported OSes. - FIXME: we really should do something better, such as dynamically - loading the KOD modules. */ -extern char *ecos_kod_open (void *, void *); -extern void ecos_kod_request (char *, int); -extern void ecos_kod_close (); -extern char *cisco_kod_open (void *, void *); -extern void cisco_kod_request (char *, int); -extern void cisco_kod_close (); - - /* Print a line of data generated by the module. */ static void diff --git a/gdb/minsyms.c b/gdb/minsyms.c index e878b916563..30e0e77185c 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -440,9 +440,9 @@ lookup_minimal_symbol_by_pc (pc) #ifdef SOFUN_ADDRESS_MAYBE_MISSING CORE_ADDR -find_stab_function_addr (namestring, pst, objfile) +find_stab_function_addr (namestring, filename, objfile) char *namestring; - struct partial_symtab *pst; + char *filename; struct objfile *objfile; { struct minimal_symbol *msym; @@ -457,7 +457,7 @@ find_stab_function_addr (namestring, pst, objfile) strncpy (p, namestring, n); p[n] = 0; - msym = lookup_minimal_symbol (p, pst->filename, objfile); + msym = lookup_minimal_symbol (p, filename, objfile); if (msym == NULL) { /* Sun Fortran appends an underscore to the minimal symbol name, @@ -465,8 +465,23 @@ find_stab_function_addr (namestring, pst, objfile) was not found. */ p[n] = '_'; p[n + 1] = 0; - msym = lookup_minimal_symbol (p, pst->filename, objfile); + msym = lookup_minimal_symbol (p, filename, objfile); } + + if (msym == NULL && filename != NULL) + { + /* Try again without the filename. */ + p[n] = 0; + msym = lookup_minimal_symbol (p, 0, objfile); + } + if (msym == NULL && filename != NULL) + { + /* And try again for Sun Fortran, but without the filename. */ + p[n] = '_'; + p[n + 1] = 0; + msym = lookup_minimal_symbol (p, 0, objfile); + } + return msym == NULL ? 0 : SYMBOL_VALUE_ADDRESS (msym); } #endif /* SOFUN_ADDRESS_MAYBE_MISSING */ diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index 9f54e0de158..f884f054652 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -29,6 +29,7 @@ #include "gdbcore.h" #include "symfile.h" +extern void _initialize_mn10300_tdep (void); static CORE_ADDR mn10300_analyze_prologue PARAMS ((struct frame_info * fi, CORE_ADDR pc)); diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 7e57562e53a..253739c1e85 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -960,13 +960,8 @@ find_pc_sect_section (pc, section) struct objfile *objfile; ALL_OBJSECTIONS (objfile, s) -#if defined(HPUXHPPA) - if ((section == 0 || section == s->the_bfd_section) && - s->addr <= pc && pc <= s->endaddr) -#else if ((section == 0 || section == s->the_bfd_section) && s->addr <= pc && pc < s->endaddr) -#endif return (s); return (NULL); diff --git a/gdb/pa64solib.c b/gdb/pa64solib.c index aa11f2497c6..b0b4645d29f 100644 --- a/gdb/pa64solib.c +++ b/gdb/pa64solib.c @@ -530,40 +530,13 @@ pa64_solib_create_inferior_hook () if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) return; - /* Slam the pid of the process into __d_pid; failing is only a warning! */ - msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile); - if (msymbol == NULL) - { - warning ("Unable to find __d_pid symbol in object file."); - warning ("Suggest linking with /opt/langtools/lib/end.o."); - warning ("GDB will be unable to track explicit library load/unload calls"); - goto keep_going; - } - - anaddr = SYMBOL_VALUE_ADDRESS (msymbol); - store_unsigned_integer (buf, 4, inferior_pid); - status = target_write_memory (anaddr, buf, 4); - if (status != 0) - { - warning ("Unable to write __d_pid"); - warning ("Suggest linking with /opt/langtools/lib/end.o."); - warning ("GDB will be unable to track explicit library load/unload calls"); - goto keep_going; - } - -keep_going: - /* Read in the .dynamic section. */ if (! read_dynamic_info (shlib_info, &dld_cache)) error ("Unable to read the .dynamic section."); /* Turn on the flags we care about. */ dld_cache.dld_flags |= DT_HP_DEBUG_PRIVATE; - /* ?!? Right now GDB is not recognizing hitting the callback breakpoint - as a shared library event. Fix that and remove the #if0 code. */ -#if 0 dld_cache.dld_flags |= DT_HP_DEBUG_CALLBACK; -#endif status = target_write_memory (dld_cache.dld_flags_addr, (char *) &dld_cache.dld_flags, sizeof (dld_cache.dld_flags)); @@ -621,7 +594,17 @@ keep_going: sym_addr = load_addr + sym_addr + 4; /* Create the shared library breakpoint. */ - create_solib_event_breakpoint (sym_addr); + { + struct breakpoint *b + = create_solib_event_breakpoint (sym_addr); + + /* The breakpoint is actually hard-coded into the dynamic linker, + so we don't need to actually insert a breakpoint instruction + there. In fact, the dynamic linker's code is immutable, even to + ttrace, so we shouldn't even try to do that. For cases like + this, we have "permanent" breakpoints. */ + make_breakpoint_permanent (b); + } /* We're done with the temporary bfd. */ bfd_close (tmp_bfd); @@ -856,9 +839,9 @@ pa64_sharedlibrary_info_command (ignore, from_tty) } printf_unfiltered ("Shared Object Libraries\n"); - printf_unfiltered (" %-19s%-19s%-19s%-19s\n", - " tstart", " tend", - " dstart", " dend"); + printf_unfiltered (" %-19s%-19s%-19s%-19s\n", + " text start", " text end", + " data start", " data end"); while (so_list) { unsigned int flags; @@ -876,14 +859,14 @@ pa64_sharedlibrary_info_command (ignore, from_tty) local_hex_string_custom (so_list->pa64_solib_desc.text_base, "016l")); printf_unfiltered (" %-18s", - local_hex_string_custom ((so_list->pa64_solib_desc.text_base, + local_hex_string_custom ((so_list->pa64_solib_desc.text_base + so_list->pa64_solib_desc.text_size), "016l")); printf_unfiltered (" %-18s", local_hex_string_custom (so_list->pa64_solib_desc.data_base, "016l")); printf_unfiltered (" %-18s\n", - local_hex_string_custom ((so_list->pa64_solib_desc.data_base, + local_hex_string_custom ((so_list->pa64_solib_desc.data_base + so_list->pa64_solib_desc.data_size), "016l")); so_list = so_list->next; diff --git a/gdb/partial-stab.h b/gdb/partial-stab.h index b4ba251fb93..87ab12ac304 100644 --- a/gdb/partial-stab.h +++ b/gdb/partial-stab.h @@ -577,9 +577,6 @@ switch (CUR_SYMBOL_TYPE) case 'f': CUR_SYMBOL_VALUE += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT); #ifdef DBXREAD_ONLY - /* Keep track of the start of the last function so we - can handle end of function symbols. */ - last_function_start = CUR_SYMBOL_VALUE; /* Kludges for ELF/STABS with Sun ACC */ last_function_name = namestring; #ifdef SOFUN_ADDRESS_MAYBE_MISSING @@ -588,12 +585,16 @@ switch (CUR_SYMBOL_TYPE) if (pst && textlow_not_set) { pst->textlow = - find_stab_function_addr (namestring, pst, objfile); + find_stab_function_addr (namestring, pst->filename, objfile); textlow_not_set = 0; } #endif /* End kludge. */ + /* Keep track of the start of the last function so we + can handle end of function symbols. */ + last_function_start = CUR_SYMBOL_VALUE; + /* In reordered executables this function may lie outside the bounds created by N_SO symbols. If that's the case use the address of this function as the low bound for @@ -620,22 +621,27 @@ switch (CUR_SYMBOL_TYPE) case 'F': CUR_SYMBOL_VALUE += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT); #ifdef DBXREAD_ONLY - /* Keep track of the start of the last function so we - can handle end of function symbols. */ - last_function_start = CUR_SYMBOL_VALUE; /* Kludges for ELF/STABS with Sun ACC */ last_function_name = namestring; #ifdef SOFUN_ADDRESS_MAYBE_MISSING /* Do not fix textlow==0 for .o or NLM files, as 0 is a legit value for the bottom of the text seg in those cases. */ + if (CUR_SYMBOL_VALUE == ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT)) + CUR_SYMBOL_VALUE = + find_stab_function_addr (namestring, pst->filename, objfile); if (pst && textlow_not_set) { - pst->textlow = - find_stab_function_addr (namestring, pst, objfile); + pst->textlow = CUR_SYMBOL_VALUE; textlow_not_set = 0; } #endif /* End kludge. */ + + /* Keep track of the start of the last function so we + can handle end of function symbols. */ + last_function_start = CUR_SYMBOL_VALUE; + /* In reordered executables this function may lie outside the bounds created by N_SO symbols. If that's the case use the address of this function as the low bound for diff --git a/gdb/remote-es.c b/gdb/remote-es.c index b433fe8e808..95d42363f8a 100644 --- a/gdb/remote-es.c +++ b/gdb/remote-es.c @@ -360,14 +360,14 @@ es1800_open (name, from_tty) es1800_saved_ttystate = SERIAL_GET_TTY_STATE (es1800_desc); - if ((fcflag = fcntl (es1800_desc->fd, F_GETFL, 0)) == -1) + if ((fcflag = fcntl (DEPRECATED_SERIAL_FD (es1800_desc), F_GETFL, 0)) == -1) { perror_with_name ("fcntl serial"); } es1800_fc_save = fcflag; fcflag = (fcflag & (FREAD | FWRITE)); /* mask out any funny stuff */ - if (fcntl (es1800_desc->fd, F_SETFL, fcflag) == -1) + if (fcntl (DEPRECATED_SERIAL_FD (es1800_desc), F_SETFL, fcflag) == -1) { perror_with_name ("fcntl serial"); } @@ -470,7 +470,7 @@ es1800_close (quitting) printf ("\nClosing connection to emulator...\n"); if (SERIAL_SET_TTY_STATE (es1800_desc, es1800_saved_ttystate) < 0) print_sys_errmsg ("warning: unable to restore tty state", errno); - fcntl (es1800_desc->fd, F_SETFL, es1800_fc_save); + fcntl (DEPRECATED_SERIAL_FD (es1800_desc), F_SETFL, es1800_fc_save); SERIAL_CLOSE (es1800_desc); es1800_desc = NULL; } @@ -1876,7 +1876,7 @@ es1800_transparent (args, from_tty) perror_with_name ("ioctl console"); } - if ((fcflag = fcntl (es1800_desc->fd, F_GETFL, 0)) == -1) + if ((fcflag = fcntl (DEPRECATED_SERIAL_FD (es1800_desc), F_GETFL, 0)) == -1) { perror_with_name ("fcntl serial"); } @@ -1884,7 +1884,7 @@ es1800_transparent (args, from_tty) es1800_fc_save = fcflag; fcflag = fcflag | FNDELAY; - if (fcntl (es1800_desc->fd, F_SETFL, fcflag) == -1) + if (fcntl (DEPRECATED_SERIAL_FD (es1800_desc), F_SETFL, fcflag) == -1) { perror_with_name ("fcntl serial"); } @@ -1920,7 +1920,7 @@ es1800_transparent (args, from_tty) perror_with_name ("FEL! read:"); } - cc = read (es1800_desc->fd, inputbuf, inputcnt); + cc = read (DEPRECATED_SERIAL_FD (es1800_desc), inputbuf, inputcnt); if (cc != -1) { for (i = 0; i < cc;) @@ -1959,7 +1959,7 @@ es1800_transparent (args, from_tty) close (console); - if (fcntl (es1800_desc->fd, F_SETFL, es1800_fc_save) == -1) + if (fcntl (DEPRECATED_SERIAL_FD (es1800_desc), F_SETFL, es1800_fc_save) == -1) { perror_with_name ("FEL! fcntl"); } diff --git a/gdb/remote-os9k.c b/gdb/remote-os9k.c index a523c3c636b..a9d92b57505 100644 --- a/gdb/remote-os9k.c +++ b/gdb/remote-os9k.c @@ -1074,7 +1074,7 @@ connect_command (args, fromtty) do { FD_SET (0, &readfds); - FD_SET (monitor_desc, &readfds); + FD_SET (DEPRECATED_SERIAL_FD (monitor_desc), &readfds); numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0); } while (numfds == 0); @@ -1109,7 +1109,7 @@ connect_command (args, fromtty) } } - if (FD_ISSET (monitor_desc, &readfds)) + if (FD_ISSET (DEPRECATED_SERIAL_FD (monitor_desc), &readfds)) { while (1) { diff --git a/gdb/remote-st.c b/gdb/remote-st.c index 3400903503f..1d270a44a24 100644 --- a/gdb/remote-st.c +++ b/gdb/remote-st.c @@ -729,7 +729,7 @@ connect_command (args, fromtty) do { FD_SET (0, &readfds); - FD_SET (st2000_desc, &readfds); + FD_SET (DEPRECATED_SERIAL_FD (st2000_desc), &readfds); numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0); } while (numfds == 0); @@ -764,7 +764,7 @@ connect_command (args, fromtty) } } - if (FD_ISSET (st2000_desc, &readfds)) + if (FD_ISSET (DEPRECATED_SERIAL_FD (st2000_desc), &readfds)) { while (1) { diff --git a/gdb/remote.c b/gdb/remote.c index 56ce7795a66..645ef223104 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -36,6 +36,7 @@ #include "objfiles.h" #include "gdb-stabs.h" #include "gdbthread.h" +#include "remote.h" #include "dcache.h" @@ -46,6 +47,7 @@ #endif #include "event-loop.h" +#include "event-top.h" #include <signal.h> #include "serial.h" @@ -186,14 +188,8 @@ static void record_currthread PARAMS ((int currthread)); extern int fromhex PARAMS ((int a)); -extern void getpkt PARAMS ((char *buf, int forever)); - -extern int putpkt PARAMS ((char *buf)); - static int putpkt_binary PARAMS ((char *buf, int cnt)); -void remote_console_output PARAMS ((char *)); - static void check_binary_download PARAMS ((CORE_ADDR addr)); struct packet_config; @@ -1840,8 +1836,10 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); 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) - add_file_handler (remote_desc->fd, fetch_inferior_event, 0); + 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 */ @@ -1858,7 +1856,7 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); /* 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 && async_p) + 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 @@ -1877,13 +1875,13 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); RETURN_MASK_ALL)) { /* Unregister the file descriptor from the event loop. */ - if (async_p) - delete_file_handler (remote_desc->fd); + if (SERIAL_IS_ASYNC_P (remote_desc)) + SERIAL_ASYNC (remote_desc, NULL, 0); pop_target (); return; } - if (!async_p) + if (!SERIAL_IS_ASYNC_P (remote_desc)) { if (extended_p) { @@ -1948,8 +1946,8 @@ remote_async_detach (args, from_tty) remote_send (buf); /* Unregister the file descriptor from the event loop. */ - if (async_p) - delete_file_handler (remote_desc->fd); + if (SERIAL_IS_ASYNC_P (remote_desc)) + SERIAL_ASYNC (remote_desc, NULL, 0); pop_target (); if (from_tty) @@ -2053,7 +2051,7 @@ remote_async_resume (pid, step, siggnal) 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 (async_p && !target_executing) + if (SERIAL_IS_ASYNC_P (remote_desc) && !target_executing) { target_executing = 1; @@ -2145,9 +2143,9 @@ cleanup_sigint_signal_handler () { signal (SIGINT, handle_sigint); if (sigint_remote_twice_token) - delete_async_signal_handler ((async_signal_handler **) & sigint_remote_twice_token); + delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_twice_token); if (sigint_remote_token) - delete_async_signal_handler ((async_signal_handler **) & sigint_remote_token); + delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_token); } /* Send ^C to target to halt it. Target will respond, and send us a @@ -2473,10 +2471,10 @@ remote_async_wait (pid, status) { unsigned char *p; - if (!async_p) + if (!SERIAL_IS_ASYNC_P (remote_desc)) ofunc = signal (SIGINT, remote_interrupt); getpkt ((char *) buf, 1); - if (!async_p) + if (!SERIAL_IS_ASYNC_P (remote_desc)) signal (SIGINT, ofunc); /* This is a hook for when we need to do something (perhaps the @@ -3519,33 +3517,6 @@ putpkt_binary (buf, cnt) static int remote_cisco_mode; -static void -remote_cisco_expand (src, dest) - char *src; - char *dest; -{ - int i; - int repeat; - - do - { - if (*src == '*') - { - repeat = (fromhex (src[1]) << 4) + fromhex (src[2]); - for (i = 0; i < repeat; i++) - { - *dest++ = *(src - 1); - } - src += 2; - } - else - { - *dest++ = *src; - } - } - while (*src++); -} - /* Come here after finding the start of the frame. Collect the rest into BUF, verifying the checksum, length, and handling run-length compression. Returns 0 on any error, 1 on success. */ @@ -3586,16 +3557,7 @@ read_frame (buf) pktcsum |= fromhex (readchar (remote_timeout)); if (csum == pktcsum) - { - if (remote_cisco_mode) /* variant run-length-encoding */ - { - char *tmp_buf = alloca (PBUFSIZ); - - remote_cisco_expand (buf, tmp_buf); - strcpy (buf, tmp_buf); - } - return 1; - } + return 1; if (remote_debug) { @@ -3608,27 +3570,43 @@ read_frame (buf) return 0; } case '*': /* Run length encoding */ - if (remote_cisco_mode == 0) /* variant run-length-encoding */ - { - csum += c; - c = readchar (remote_timeout); - csum += c; - c = c - ' ' + 3; /* Compute repeat count */ + { + int repeat; + csum += c; - if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1) - { - memset (bp, *(bp - 1), c); - bp += c; - continue; - } + if (remote_cisco_mode == 0) + { + c = readchar (remote_timeout); + csum += c; + repeat = c - ' ' + 3; /* Compute repeat count */ + } + else + { + /* Cisco's run-length encoding variant uses two + hex chars to represent the repeat count. */ + + c = readchar (remote_timeout); + csum += c; + repeat = fromhex (c) << 4; + c = readchar (remote_timeout); + csum += c; + repeat += fromhex (c); + } - *bp = '\0'; - printf_filtered ("Repeat count %d too large for buffer: ", c); - puts_filtered (buf); - puts_filtered ("\n"); - return 0; - } - /* else fall thru to treat like default */ + if (repeat > 0 && repeat <= 255 + && bp + repeat - 1 < buf + PBUFSIZ - 1) + { + memset (bp, *(bp - 1), repeat); + bp += c; + continue; + } + + *bp = '\0'; + printf_filtered ("Repeat count %d too large for buffer: ", repeat); + puts_filtered (buf); + puts_filtered ("\n"); + return 0; + } default: if (bp < buf + PBUFSIZ - 1) { @@ -3755,8 +3733,8 @@ static void remote_async_kill () { /* Unregister the file descriptor from the event loop. */ - if (async_p) - delete_file_handler (remote_desc->fd); + if (SERIAL_IS_ASYNC_P (remote_desc)) + SERIAL_ASYNC (remote_desc, NULL, 0); /* For some mysterious reason, wait_for_inferior calls kill instead of mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */ @@ -3854,8 +3832,8 @@ extended_remote_async_create_inferior (exec_file, args, env) /* If running asynchronously, register the target file descriptor with the event loop. */ - if (async_p) - add_file_handler (remote_desc->fd, fetch_inferior_event, 0); + if (async_p && SERIAL_CAN_ASYNC_P (remote_desc)) + SERIAL_ASYNC (remote_desc, inferior_event_handler, 0); /* Now restart the remote server. */ extended_remote_restart (); @@ -4939,7 +4917,7 @@ minitelnet () FD_ZERO (&input); FD_SET (fileno (stdin), &input); - FD_SET (remote_desc->fd, &input); + FD_SET (DEPRECATED_SERIAL_FD (remote_desc), &input); status = select (tablesize, &input, 0, 0, 0); if ((status == -1) && (errno != EINTR)) diff --git a/gdb/ser-e7kpc.c b/gdb/ser-e7kpc.c index 5f35baedf0e..6a39cc1cc1e 100644 --- a/gdb/ser-e7kpc.c +++ b/gdb/ser-e7kpc.c @@ -420,9 +420,9 @@ e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate) } static void -e7000pc_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +e7000pc_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) { /* Nothing to print. */ return; diff --git a/gdb/ser-go32.c b/gdb/ser-go32.c index 89db6f85c05..c1bf22778a3 100644 --- a/gdb/ser-go32.c +++ b/gdb/ser-go32.c @@ -696,9 +696,9 @@ dos_flush_input (scb) } static void -dos_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +dos_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) { /* Nothing to print */ return; diff --git a/gdb/ser-mac.c b/gdb/ser-mac.c index 7bab8ad76fd..4e8a20ae62f 100644 --- a/gdb/ser-mac.c +++ b/gdb/ser-mac.c @@ -232,9 +232,9 @@ mac_noflush_set_tty_state (scb, new_ttystate, old_ttystate) } static void -mac_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +mac_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) { /* Nothing to print. */ return; diff --git a/gdb/ser-ocd.c b/gdb/ser-ocd.c index 646985ff78c..a56c2c6a482 100644 --- a/gdb/ser-ocd.c +++ b/gdb/ser-ocd.c @@ -1,7 +1,7 @@ /* Remote serial interface for Macraigor Systems implementation of On-Chip Debugging using serial target box or serial wiggler - Copyright 1994, 1997 Free Software Foundation, Inc. + Copyright 1994, 1997, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -27,15 +27,6 @@ #include <windows.h> #endif -static int ser_ocd_open PARAMS ((serial_t scb, const char *name)); -static void ser_ocd_raw PARAMS ((serial_t scb)); -static int ser_ocd_readchar PARAMS ((serial_t scb, int timeout)); -static int ser_ocd_setbaudrate PARAMS ((serial_t scb, int rate)); -static int ser_ocd_write PARAMS ((serial_t scb, const char *str, int len)); -static void ser_ocd_close PARAMS ((serial_t scb)); -static serial_ttystate ser_ocd_get_tty_state PARAMS ((serial_t scb)); -static int ser_ocd_set_tty_state PARAMS ((serial_t scb, serial_ttystate state)); - #ifdef _WIN32 /* On Windows, this function pointer is initialized to a function in the wiggler DLL. */ @@ -84,11 +75,6 @@ ocd_raw (scb) /* Always in raw mode */ } -static void -ocd_readremote () -{ -} - /* We need a buffer to store responses from the Wigglers.dll */ #define WIGGLER_BUFF_SIZE 512 unsigned char from_wiggler_buffer[WIGGLER_BUFF_SIZE]; @@ -144,9 +130,9 @@ ocd_noflush_set_tty_state (scb, new_ttystate, old_ttystate) } static void -ocd_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +ocd_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) { /* Nothing to print. */ return; @@ -166,8 +152,6 @@ ocd_write (scb, str, len) const char *str; int len; { - char c; - #ifdef _WIN32 /* send packet to Wigglers.dll and store response so we can give it to remote-wiggler.c when get_packet is run */ diff --git a/gdb/ser-pipe.c b/gdb/ser-pipe.c index 0c36a31e07a..efbc24185d1 100644 --- a/gdb/ser-pipe.c +++ b/gdb/ser-pipe.c @@ -22,6 +22,8 @@ #include "defs.h" #include "serial.h" +#include "ser-unix.h" + #include <sys/types.h> #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> @@ -31,31 +33,11 @@ #include <fcntl.h> #include "signals.h" -#include "gdb_string.h" - -extern int (*ui_loop_hook) PARAMS ((int)); - -static int pipe_open PARAMS ((serial_t scb, const char *name)); -static void pipe_raw PARAMS ((serial_t scb)); -static int wait_for PARAMS ((serial_t scb, int timeout)); -static int pipe_readchar PARAMS ((serial_t scb, int timeout)); -static int pipe_setbaudrate PARAMS ((serial_t scb, int rate)); -static int pipe_setstopbits PARAMS ((serial_t scb, int num)); -static int pipe_write PARAMS ((serial_t scb, const char *str, int len)); -/* FIXME: static void pipe_restore PARAMS ((serial_t scb)); */ -static void pipe_close PARAMS ((serial_t scb)); -static serial_ttystate pipe_get_tty_state PARAMS ((serial_t scb)); -static int pipe_set_tty_state PARAMS ((serial_t scb, serial_ttystate state)); -static int pipe_return_0 PARAMS ((serial_t)); -static int pipe_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate, - serial_ttystate)); -static void pipe_print_tty_state PARAMS ((serial_t, serial_ttystate)); -extern void _initialize_ser_pipe PARAMS ((void)); - -#undef XMALLOC -#define XMALLOC(T) ((T*) xmalloc (sizeof (T))) +static int pipe_open (serial_t scb, const char *name); +static void pipe_close (serial_t scb); +extern void _initialize_ser_pipe (void); struct pipe_state { @@ -65,9 +47,7 @@ struct pipe_state /* Open up a raw pipe */ static int -pipe_open (scb, name) - serial_t scb; - const char *name; +pipe_open (serial_t scb, const char *name) { #if !defined(O_NONBLOCK) || !defined(F_GETFL) || !defined(F_SETFL) || !HAVE_SOCKETPAIR return -1; @@ -114,7 +94,7 @@ pipe_open (scb, name) for (old = pidlist; old; old = old->next) close (fileno (old->fp)); /* don't allow a flush */ #endif - execl ("/bin/sh", "sh", "-c", name + 1, NULL); + execl ("/bin/sh", "sh", "-c", name, NULL); _exit (127); } @@ -143,224 +123,8 @@ pipe_open (scb, name) #endif } -static serial_ttystate -pipe_get_tty_state (scb) - serial_t scb; -{ - /* return garbage */ - return xmalloc (sizeof (int)); -} - -static int -pipe_set_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; -{ - return 0; -} - -static int -pipe_return_0 (scb) - serial_t scb; -{ - return 0; -} - -static void -pipe_raw (scb) - serial_t scb; -{ - return; /* Always in raw mode */ -} - -/* Wait for input on scb, with timeout seconds. Returns 0 on success, - otherwise SERIAL_TIMEOUT or SERIAL_ERROR. - - For termio{s}, we actually just setup VTIME if necessary, and let the - timeout occur in the read() in pipe_read(). - */ - -static int -wait_for (scb, timeout) - serial_t scb; - int timeout; -{ - int numfds; - struct timeval tv; - fd_set readfds, exceptfds; - - FD_ZERO (&readfds); - FD_ZERO (&exceptfds); - - tv.tv_sec = timeout; - tv.tv_usec = 0; - - FD_SET (scb->fd, &readfds); - FD_SET (scb->fd, &exceptfds); - - while (1) - { - if (timeout >= 0) - numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv); - else - numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0); - - if (numfds <= 0) - { - if (numfds == 0) - return SERIAL_TIMEOUT; - else if (errno == EINTR) - continue; - else - return SERIAL_ERROR; /* Got an error from select or poll */ - } - - return 0; - } -} - -/* Read a character with user-specified timeout. TIMEOUT is number of seconds - to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns - char if successful. Returns -2 if timeout expired, EOF if line dropped - dead, or -3 for any other error (see errno in that case). */ - -static int -pipe_readchar (scb, timeout) - serial_t scb; - int timeout; -{ - int status; - int delta; - - if (scb->bufcnt-- > 0) - return *scb->bufp++; - - /* We have to be able to keep the GUI alive here, so we break the original - timeout into steps of 1 second, running the "keep the GUI alive" hook - each time through the loop. - - Also, timeout = 0 means to poll, so we just set the delta to 0, so we - will only go through the loop once. */ - - delta = (timeout == 0 ? 0 : 1); - while (1) - { - - /* N.B. The UI may destroy our world (for instance by calling - remote_stop,) in which case we want to get out of here as - quickly as possible. It is not safe to touch scb, since - someone else might have freed it. The ui_loop_hook signals that - we should exit by returning 1. */ - - if (ui_loop_hook) - { - if (ui_loop_hook (0)) - return SERIAL_TIMEOUT; - } - - status = wait_for (scb, delta); - timeout -= delta; - - /* If we got a character or an error back from wait_for, then we can - break from the loop before the timeout is completed. */ - - if (status != SERIAL_TIMEOUT) - { - break; - } - - /* If we have exhausted the original timeout, then generate - a SERIAL_TIMEOUT, and pass it out of the loop. */ - - else if (timeout == 0) - { - status = SERIAL_TIMEOUT; - break; - } - } - - if (status < 0) - return status; - - while (1) - { - scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ); - if (scb->bufcnt != -1 || errno != EINTR) - break; - } - - if (scb->bufcnt <= 0) - { - if (scb->bufcnt == 0) - return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to - distinguish between EOF & timeouts - someday] */ - else - return SERIAL_ERROR; /* Got an error from read */ - } - - scb->bufcnt--; - scb->bufp = scb->buf; - return *scb->bufp++; -} - -static int -pipe_noflush_set_tty_state (scb, new_ttystate, old_ttystate) - serial_t scb; - serial_ttystate new_ttystate; - serial_ttystate old_ttystate; -{ - return 0; -} - -static void -pipe_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; -{ - /* Nothing to print. */ - return; -} - -static int -pipe_setbaudrate (scb, rate) - serial_t scb; - int rate; -{ - return 0; /* Never fails! */ -} - -static int -pipe_setstopbits (scb, num) - serial_t scb; - int num; -{ - return 0; /* Never fails! */ -} - -static int -pipe_write (scb, str, len) - serial_t scb; - const char *str; - int len; -{ - int cc; - - while (len > 0) - { - cc = write (scb->fd, str, len); - - if (cc < 0) - return 1; - len -= cc; - str += cc; - } - return 0; -} - static void -pipe_close (scb) - serial_t scb; +pipe_close (serial_t scb) { struct pipe_state *state = scb->state; if (state != NULL) @@ -375,29 +139,30 @@ pipe_close (scb) } } -static struct serial_ops pipe_ops = -{ - "pipe", - 0, - pipe_open, - pipe_close, - pipe_readchar, - pipe_write, - pipe_return_0, /* flush output */ - pipe_return_0, /* flush input */ - pipe_return_0, /* send break */ - pipe_raw, - pipe_get_tty_state, - pipe_set_tty_state, - pipe_print_tty_state, - pipe_noflush_set_tty_state, - pipe_setbaudrate, - pipe_setstopbits, - pipe_return_0, /* wait for output to drain */ -}; +static struct serial_ops pipe_ops; void -_initialize_ser_pipe () +_initialize_ser_pipe (void) { - serial_add_interface (&pipe_ops); + struct serial_ops *ops = XMALLOC (struct serial_ops); + memset (ops, sizeof (struct serial_ops), 0); + ops->name = "pipe"; + ops->next = 0; + ops->open = pipe_open; + ops->close = pipe_close; + ops->readchar = ser_unix_readchar; + ops->write = ser_unix_write; + ops->flush_output = ser_unix_nop_flush_output; + ops->flush_input = ser_unix_nop_flush_input; + ops->send_break = ser_unix_nop_send_break; + ops->go_raw = ser_unix_nop_raw; + ops->get_tty_state = ser_unix_nop_get_tty_state; + ops->set_tty_state = ser_unix_nop_set_tty_state; + ops->print_tty_state = ser_unix_nop_print_tty_state; + ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state; + ops->setbaudrate = ser_unix_nop_setbaudrate; + ops->setstopbits = ser_unix_nop_setstopbits; + ops->drain_output = ser_unix_nop_drain_output; + ops->async = ser_unix_async; + serial_add_interface (ops); } diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c index f565328f09b..01e8ca03326 100644 --- a/gdb/ser-tcp.c +++ b/gdb/ser-tcp.c @@ -1,5 +1,5 @@ /* Serial interface for raw TCP connections on Un*x like systems - Copyright 1992, 1993, 1998 Free Software Foundation, Inc. + Copyright 1992, 1993, 1998-1999 Free Software Foundation, Inc. This file is part of GDB. @@ -20,13 +20,14 @@ #include "defs.h" #include "serial.h" +#include "ser-unix.h" + #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <sys/socket.h> - #ifndef __CYGWIN32__ #include <netinet/tcp.h> #endif @@ -34,37 +35,15 @@ #include "signals.h" #include "gdb_string.h" -extern int (*ui_loop_hook) PARAMS ((int)); - -struct tcp_ttystate - { - int bogus; - }; - -static int tcp_open PARAMS ((serial_t scb, const char *name)); -static void tcp_raw PARAMS ((serial_t scb)); -static int wait_for PARAMS ((serial_t scb, int timeout)); -static int tcp_readchar PARAMS ((serial_t scb, int timeout)); -static int tcp_setbaudrate PARAMS ((serial_t scb, int rate)); -static int tcp_setstopbits PARAMS ((serial_t scb, int num)); -static int tcp_write PARAMS ((serial_t scb, const char *str, int len)); -/* FIXME: static void tcp_restore PARAMS ((serial_t scb)); */ -static void tcp_close PARAMS ((serial_t scb)); -static serial_ttystate tcp_get_tty_state PARAMS ((serial_t scb)); -static int tcp_set_tty_state PARAMS ((serial_t scb, serial_ttystate state)); -static int tcp_return_0 PARAMS ((serial_t)); -static int tcp_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate, - serial_ttystate)); -static void tcp_print_tty_state PARAMS ((serial_t, serial_ttystate)); - -void _initialize_ser_tcp PARAMS ((void)); +static int tcp_open (serial_t scb, const char *name); +static void tcp_close (serial_t scb); + +void _initialize_ser_tcp (void); /* Open up a raw tcp socket */ static int -tcp_open (scb, name) - serial_t scb; - const char *name; +tcp_open (serial_t scb, const char *name) { char *port_str; int port; @@ -143,231 +122,8 @@ tcp_open (scb, name) return 0; } -static serial_ttystate -tcp_get_tty_state (scb) - serial_t scb; -{ - struct tcp_ttystate *state; - - state = (struct tcp_ttystate *) xmalloc (sizeof *state); - - return (serial_ttystate) state; -} - -static int -tcp_set_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; -{ - struct tcp_ttystate *state; - - state = (struct tcp_ttystate *) ttystate; - - return 0; -} - -static int -tcp_return_0 (scb) - serial_t scb; -{ - return 0; -} - static void -tcp_raw (scb) - serial_t scb; -{ - return; /* Always in raw mode */ -} - -/* Wait for input on scb, with timeout seconds. Returns 0 on success, - otherwise SERIAL_TIMEOUT or SERIAL_ERROR. - - For termio{s}, we actually just setup VTIME if necessary, and let the - timeout occur in the read() in tcp_read(). - */ - -static int -wait_for (scb, timeout) - serial_t scb; - int timeout; -{ - int numfds; - struct timeval tv; - fd_set readfds, exceptfds; - - FD_ZERO (&readfds); - FD_ZERO (&exceptfds); - - tv.tv_sec = timeout; - tv.tv_usec = 0; - - FD_SET (scb->fd, &readfds); - FD_SET (scb->fd, &exceptfds); - - while (1) - { - if (timeout >= 0) - numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv); - else - numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0); - - if (numfds <= 0) - { - if (numfds == 0) - return SERIAL_TIMEOUT; - else if (errno == EINTR) - continue; - else - return SERIAL_ERROR; /* Got an error from select or poll */ - } - - return 0; - } -} - -/* Read a character with user-specified timeout. TIMEOUT is number of seconds - to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns - char if successful. Returns -2 if timeout expired, EOF if line dropped - dead, or -3 for any other error (see errno in that case). */ - -static int -tcp_readchar (scb, timeout) - serial_t scb; - int timeout; -{ - int status; - int delta; - - if (scb->bufcnt-- > 0) - return *scb->bufp++; - - /* We have to be able to keep the GUI alive here, so we break the original - timeout into steps of 1 second, running the "keep the GUI alive" hook - each time through the loop. - - Also, timeout = 0 means to poll, so we just set the delta to 0, so we - will only go through the loop once. */ - - delta = (timeout == 0 ? 0 : 1); - while (1) - { - - /* N.B. The UI may destroy our world (for instance by calling - remote_stop,) in which case we want to get out of here as - quickly as possible. It is not safe to touch scb, since - someone else might have freed it. The ui_loop_hook signals that - we should exit by returning 1. */ - - if (ui_loop_hook) - { - if (ui_loop_hook (0)) - return SERIAL_TIMEOUT; - } - - status = wait_for (scb, delta); - timeout -= delta; - - /* If we got a character or an error back from wait_for, then we can - break from the loop before the timeout is completed. */ - - if (status != SERIAL_TIMEOUT) - { - break; - } - - /* If we have exhausted the original timeout, then generate - a SERIAL_TIMEOUT, and pass it out of the loop. */ - - else if (timeout == 0) - { - status = SERIAL_TIMEOUT; - break; - } - } - - if (status < 0) - return status; - - while (1) - { - scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ); - if (scb->bufcnt != -1 || errno != EINTR) - break; - } - - if (scb->bufcnt <= 0) - { - if (scb->bufcnt == 0) - return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to - distinguish between EOF & timeouts - someday] */ - else - return SERIAL_ERROR; /* Got an error from read */ - } - - scb->bufcnt--; - scb->bufp = scb->buf; - return *scb->bufp++; -} - -static int -tcp_noflush_set_tty_state (scb, new_ttystate, old_ttystate) - serial_t scb; - serial_ttystate new_ttystate; - serial_ttystate old_ttystate; -{ - return 0; -} - -static void -tcp_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; -{ - /* Nothing to print. */ - return; -} - -static int -tcp_setbaudrate (scb, rate) - serial_t scb; - int rate; -{ - return 0; /* Never fails! */ -} - -static int -tcp_setstopbits (scb, num) - serial_t scb; - int num; -{ - return 0; /* Never fails! */ -} - -static int -tcp_write (scb, str, len) - serial_t scb; - const char *str; - int len; -{ - int cc; - - while (len > 0) - { - cc = write (scb->fd, str, len); - - if (cc < 0) - return 1; - len -= cc; - str += cc; - } - return 0; -} - -static void -tcp_close (scb) - serial_t scb; +tcp_close (serial_t scb) { if (scb->fd < 0) return; @@ -376,29 +132,28 @@ tcp_close (scb) scb->fd = -1; } -static struct serial_ops tcp_ops = -{ - "tcp", - 0, - tcp_open, - tcp_close, - tcp_readchar, - tcp_write, - tcp_return_0, /* flush output */ - tcp_return_0, /* flush input */ - tcp_return_0, /* send break */ - tcp_raw, - tcp_get_tty_state, - tcp_set_tty_state, - tcp_print_tty_state, - tcp_noflush_set_tty_state, - tcp_setbaudrate, - tcp_setstopbits, - tcp_return_0, /* wait for output to drain */ -}; - void -_initialize_ser_tcp () +_initialize_ser_tcp (void) { - serial_add_interface (&tcp_ops); + struct serial_ops *ops = XMALLOC (struct serial_ops); + memset (ops, sizeof (struct serial_ops), 0); + ops->name = "tcp"; + ops->next = 0; + ops->open = tcp_open; + ops->close = tcp_close; + ops->readchar = ser_unix_readchar; + ops->write = ser_unix_write; + ops->flush_output = ser_unix_nop_flush_output; + ops->flush_input = ser_unix_nop_flush_input; + ops->send_break = ser_unix_nop_send_break; + ops->go_raw = ser_unix_nop_raw; + ops->get_tty_state = ser_unix_nop_get_tty_state; + ops->set_tty_state = ser_unix_nop_set_tty_state; + ops->print_tty_state = ser_unix_nop_print_tty_state; + ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state; + ops->setbaudrate = ser_unix_nop_setbaudrate; + ops->setstopbits = ser_unix_nop_setstopbits; + ops->drain_output = ser_unix_nop_drain_output; + ops->async = ser_unix_async; + serial_add_interface (ops); } diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index e477cd10915..7c268a9f57e 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -1,5 +1,5 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems - Copyright 1992, 1993, 1994, 1998 Free Software Foundation, Inc. + Copyright 1992, 1993, 1994, 1998-1999 Free Software Foundation, Inc. This file is part of GDB. @@ -20,9 +20,20 @@ #include "defs.h" #include "serial.h" +#include "ser-unix.h" + #include <fcntl.h> #include <sys/types.h> #include "terminal.h" +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#include <sys/socket.h> +#include <sys/time.h> + +#include "gdb_string.h" +#include "event-loop.h" + #ifdef HAVE_TERMIOS @@ -46,10 +57,6 @@ struct hardwire_ttystate #endif /* termio */ #ifdef HAVE_SGTTY -/* Needed for the code which uses select(). We would include <sys/select.h> - too if it existed on all systems. */ -#include <sys/time.h> - struct hardwire_ttystate { struct sgttyb sgttyb; @@ -60,37 +67,35 @@ struct hardwire_ttystate }; #endif /* sgtty */ -static int hardwire_open PARAMS ((serial_t scb, const char *name)); -static void hardwire_raw PARAMS ((serial_t scb)); -static int wait_for PARAMS ((serial_t scb, int timeout)); -static int hardwire_readchar PARAMS ((serial_t scb, int timeout)); -static int rate_to_code PARAMS ((int rate)); -static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate)); -static int hardwire_write PARAMS ((serial_t scb, const char *str, int len)); -static void hardwire_close PARAMS ((serial_t scb)); -static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate * state)); -static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate * state)); -static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb)); -static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state)); -static int hardwire_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate, - serial_ttystate)); -static void hardwire_print_tty_state PARAMS ((serial_t, serial_ttystate)); -static int hardwire_drain_output PARAMS ((serial_t)); -static int hardwire_flush_output PARAMS ((serial_t)); -static int hardwire_flush_input PARAMS ((serial_t)); -static int hardwire_send_break PARAMS ((serial_t)); -static int hardwire_setstopbits PARAMS ((serial_t, int)); - -void _initialize_ser_hardwire PARAMS ((void)); - -extern int (*ui_loop_hook) PARAMS ((int)); +static int hardwire_open (serial_t scb, const char *name); +static void hardwire_raw (serial_t scb); +static int wait_for (serial_t scb, int timeout); +static int hardwire_readchar (serial_t scb, int timeout); +static int rate_to_code (int rate); +static int hardwire_setbaudrate (serial_t scb, int rate); +static int hardwire_write (serial_t scb, const char *str, int len); +static void hardwire_close (serial_t scb); +static int get_tty_state (serial_t scb, struct hardwire_ttystate * state); +static int set_tty_state (serial_t scb, struct hardwire_ttystate * state); +static serial_ttystate hardwire_get_tty_state (serial_t scb); +static int hardwire_set_tty_state (serial_t scb, serial_ttystate state); +static int hardwire_noflush_set_tty_state (serial_t, serial_ttystate, + serial_ttystate); +static void hardwire_print_tty_state (serial_t, serial_ttystate, struct gdb_file *); +static int hardwire_drain_output (serial_t); +static int hardwire_flush_output (serial_t); +static int hardwire_flush_input (serial_t); +static int hardwire_send_break (serial_t); +static int hardwire_setstopbits (serial_t, int); + +void _initialize_ser_hardwire (void); + +extern int (*ui_loop_hook) (int); /* Open up a real live device for serial I/O */ static int -hardwire_open (scb, name) - serial_t scb; - const char *name; +hardwire_open (serial_t scb, const char *name) { scb->fd = open (name, O_RDWR); if (scb->fd < 0) @@ -100,9 +105,7 @@ hardwire_open (scb, name) } static int -get_tty_state (scb, state) - serial_t scb; - struct hardwire_ttystate *state; +get_tty_state (serial_t scb, struct hardwire_ttystate *state) { #ifdef HAVE_TERMIOS if (tcgetattr (scb->fd, &state->termios) < 0) @@ -132,9 +135,7 @@ get_tty_state (scb, state) } static int -set_tty_state (scb, state) - serial_t scb; - struct hardwire_ttystate *state; +set_tty_state (serial_t scb, struct hardwire_ttystate *state) { #ifdef HAVE_TERMIOS if (tcsetattr (scb->fd, TCSANOW, &state->termios) < 0) @@ -164,8 +165,7 @@ set_tty_state (scb, state) } static serial_ttystate -hardwire_get_tty_state (scb) - serial_t scb; +hardwire_get_tty_state (serial_t scb) { struct hardwire_ttystate *state; @@ -178,9 +178,7 @@ hardwire_get_tty_state (scb) } static int -hardwire_set_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +hardwire_set_tty_state (serial_t scb, serial_ttystate ttystate) { struct hardwire_ttystate *state; @@ -190,10 +188,9 @@ hardwire_set_tty_state (scb, ttystate) } static int -hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate) - serial_t scb; - serial_ttystate new_ttystate; - serial_ttystate old_ttystate; +hardwire_noflush_set_tty_state (serial_t scb, + serial_ttystate new_ttystate, + serial_ttystate old_ttystate) { struct hardwire_ttystate new_state; #ifdef HAVE_SGTTY @@ -224,63 +221,63 @@ hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate) } static void -hardwire_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +hardwire_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) { struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate; int i; #ifdef HAVE_TERMIOS - printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n", - state->termios.c_iflag, state->termios.c_oflag); - printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n", - state->termios.c_cflag, state->termios.c_lflag); + fprintf_filtered (stream, "c_iflag = 0x%x, c_oflag = 0x%x,\n", + state->termios.c_iflag, state->termios.c_oflag); + fprintf_filtered (stream, "c_cflag = 0x%x, c_lflag = 0x%x\n", + state->termios.c_cflag, state->termios.c_lflag); #if 0 /* This not in POSIX, and is not really documented by those systems which have it (at least not Sun). */ - printf_filtered ("c_line = 0x%x.\n", state->termios.c_line); + fprintf_filtered (stream, "c_line = 0x%x.\n", state->termios.c_line); #endif - printf_filtered ("c_cc: "); + fprintf_filtered (stream, "c_cc: "); for (i = 0; i < NCCS; i += 1) - printf_filtered ("0x%x ", state->termios.c_cc[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", state->termios.c_cc[i]); + fprintf_filtered (stream, "\n"); #endif #ifdef HAVE_TERMIO - printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n", - state->termio.c_iflag, state->termio.c_oflag); - printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", - state->termio.c_cflag, state->termio.c_lflag, - state->termio.c_line); - printf_filtered ("c_cc: "); + fprintf_filtered (stream, "c_iflag = 0x%x, c_oflag = 0x%x,\n", + state->termio.c_iflag, state->termio.c_oflag); + fprintf_filtered (stream, "c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", + state->termio.c_cflag, state->termio.c_lflag, + state->termio.c_line); + fprintf_filtered (stream, "c_cc: "); for (i = 0; i < NCC; i += 1) - printf_filtered ("0x%x ", state->termio.c_cc[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", state->termio.c_cc[i]); + fprintf_filtered (stream, "\n"); #endif #ifdef HAVE_SGTTY - printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags); + fprintf_filtered (stream, "sgttyb.sg_flags = 0x%x.\n", + state->sgttyb.sg_flags); - printf_filtered ("tchars: "); + fprintf_filtered (stream, "tchars: "); for (i = 0; i < (int) sizeof (struct tchars); i++) - printf_filtered ("0x%x ", ((unsigned char *) &state->tc)[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", ((unsigned char *) &state->tc)[i]); + fprintf_filtered ("\n"); - printf_filtered ("ltchars: "); + fprintf_filtered (stream, "ltchars: "); for (i = 0; i < (int) sizeof (struct ltchars); i++) - printf_filtered ("0x%x ", ((unsigned char *) &state->ltc)[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", ((unsigned char *) &state->ltc)[i]); + fprintf_filtered (stream, "\n"); - printf_filtered ("lmode: 0x%x\n", state->lmode); + fprintf_filtered (stream, "lmode: 0x%x\n", state->lmode); #endif } /* Wait for the output to drain away, as opposed to flushing (discarding) it */ static int -hardwire_drain_output (scb) - serial_t scb; +hardwire_drain_output (serial_t scb) { #ifdef HAVE_TERMIOS return tcdrain (scb->fd); @@ -309,8 +306,7 @@ hardwire_drain_output (scb) } static int -hardwire_flush_output (scb) - serial_t scb; +hardwire_flush_output (serial_t scb) { #ifdef HAVE_TERMIOS return tcflush (scb->fd, TCOFLUSH); @@ -327,8 +323,7 @@ hardwire_flush_output (scb) } static int -hardwire_flush_input (scb) - serial_t scb; +hardwire_flush_input (serial_t scb) { scb->bufcnt = 0; scb->bufp = scb->buf; @@ -348,8 +343,7 @@ hardwire_flush_input (scb) } static int -hardwire_send_break (scb) - serial_t scb; +hardwire_send_break (serial_t scb) { #ifdef HAVE_TERMIOS return tcsendbreak (scb->fd, 0); @@ -379,8 +373,7 @@ hardwire_send_break (scb) } static void -hardwire_raw (scb) - serial_t scb; +hardwire_raw (serial_t scb) { struct hardwire_ttystate state; @@ -425,10 +418,12 @@ hardwire_raw (scb) timeout occur in the read() in hardwire_read(). */ +/* FIXME: Don't replace this with the equivalent ser_unix*() until the + old TERMIOS/SGTTY/... timer code has been flushed. cagney + 1999-09-16. */ + static int -wait_for (scb, timeout) - serial_t scb; - int timeout; +wait_for (serial_t scb, int timeout) { #ifdef HAVE_SGTTY { @@ -537,10 +532,19 @@ wait_for (scb, timeout) to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */ + +/* FIXME: cagney/1999-09-16: Don't replace this with the equivalent + ser_unix*() until the old TERMIOS/SGTTY/... timer code has been + flushed. */ + +/* NOTE: cagney/1999-09-16: This function is not identical to + ser_unix_readchar() as part of replacing it with ser_unix*() + merging will be required - this code handles the case where read() + times out due to no data while ser_unix_readchar() doesn't expect + that. */ + static int -hardwire_readchar (scb, timeout) - serial_t scb; - int timeout; +hardwire_readchar (serial_t scb, int timeout) { int status, delta; int detach = 0; @@ -579,7 +583,11 @@ hardwire_readchar (scb, timeout) if (status < 0) return status; - scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ); + /* NOTE: cagney/1999-09-17: See ser_unix_readchar() for reason + why ASYNC reads are character by character. */ + + scb->bufcnt = read (scb->fd, scb->buf, + (SERIAL_IS_ASYNC_P (scb) ? 1 : BUFSIZ)); if (scb->bufcnt <= 0) { @@ -718,8 +726,7 @@ baudtab[] = }; static int -rate_to_code (rate) - int rate; +rate_to_code (int rate) { int i; @@ -731,9 +738,7 @@ rate_to_code (rate) } static int -hardwire_setbaudrate (scb, rate) - serial_t scb; - int rate; +hardwire_setbaudrate (serial_t scb, int rate) { struct hardwire_ttystate state; @@ -807,11 +812,12 @@ hardwire_setstopbits (scb, num) return set_tty_state (scb, &state); } +/* FIXME: Don't replace this with the equivalent ser_unix*() until the + old TERMIOS/SGTTY/... timer code has been flushed. cagney + 1999-09-16. */ + static int -hardwire_write (scb, str, len) - serial_t scb; - const char *str; - int len; +hardwire_write (serial_t scb, const char *str, int len) { int cc; @@ -820,16 +826,16 @@ hardwire_write (scb, str, len) cc = write (scb->fd, str, len); if (cc < 0) - return 1; + return 1; len -= cc; str += cc; } return 0; } + static void -hardwire_close (scb) - serial_t scb; +hardwire_close (serial_t scb) { if (scb->fd < 0) return; @@ -838,29 +844,276 @@ hardwire_close (scb) scb->fd = -1; } -static struct serial_ops hardwire_ops = -{ - "hardwire", - 0, - hardwire_open, - hardwire_close, - hardwire_readchar, - hardwire_write, - hardwire_flush_output, - hardwire_flush_input, - hardwire_send_break, - hardwire_raw, - hardwire_get_tty_state, - hardwire_set_tty_state, - hardwire_print_tty_state, - hardwire_noflush_set_tty_state, - hardwire_setbaudrate, - hardwire_setstopbits, - hardwire_drain_output, /* wait for output to drain */ -}; + +/* Generic operations used by all UNIX/FD based serial interfaces. */ + +serial_ttystate +ser_unix_nop_get_tty_state (serial_t scb) +{ + /* allocate a dummy */ + return (serial_ttystate) XMALLOC (int); +} + +int +ser_unix_nop_set_tty_state (serial_t scb, serial_ttystate ttystate) +{ + return 0; +} + +void +ser_unix_nop_raw (serial_t scb) +{ + return; /* Always in raw mode */ +} + +/* Wait for input on scb, with timeout seconds. Returns 0 on success, + otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */ + +int +ser_unix_wait_for (serial_t scb, int timeout) +{ + int numfds; + struct timeval tv; + fd_set readfds, exceptfds; + + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + FD_SET (scb->fd, &readfds); + FD_SET (scb->fd, &exceptfds); + + while (1) + { + if (timeout >= 0) + numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv); + else + numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0); + + if (numfds <= 0) + { + if (numfds == 0) + return SERIAL_TIMEOUT; + else if (errno == EINTR) + continue; + else + return SERIAL_ERROR; /* Got an error from select or poll */ + } + + return 0; + } +} + +/* Read a character with user-specified timeout. TIMEOUT is number of seconds + to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns + char if successful. Returns -2 if timeout expired, EOF if line dropped + dead, or -3 for any other error (see errno in that case). */ + +int +ser_unix_readchar (serial_t scb, int timeout) +{ + int status; + int delta; + + if (scb->bufcnt-- > 0) + return *scb->bufp++; + + /* We have to be able to keep the GUI alive here, so we break the original + timeout into steps of 1 second, running the "keep the GUI alive" hook + each time through the loop. + + Also, timeout = 0 means to poll, so we just set the delta to 0, so we + will only go through the loop once. */ + + delta = (timeout == 0 ? 0 : 1); + while (1) + { + + /* N.B. The UI may destroy our world (for instance by calling + remote_stop,) in which case we want to get out of here as + quickly as possible. It is not safe to touch scb, since + someone else might have freed it. The ui_loop_hook signals that + we should exit by returning 1. */ + + if (ui_loop_hook) + { + if (ui_loop_hook (0)) + return SERIAL_TIMEOUT; + } + + status = ser_unix_wait_for (scb, delta); + timeout -= delta; + + /* If we got a character or an error back from wait_for, then we can + break from the loop before the timeout is completed. */ + + if (status != SERIAL_TIMEOUT) + { + break; + } + + /* If we have exhausted the original timeout, then generate + a SERIAL_TIMEOUT, and pass it out of the loop. */ + + else if (timeout == 0) + { + status = SERIAL_TIMEOUT; + break; + } + } + + if (status < 0) + return status; + + while (1) + { + /* FIXME: cagney/1999-09-17: ASYNC: The ASYNC serial code needs + to be modified so that it agressivly tries to drain its local + input buffer. Until this is done, the read() below can only + take in single characters. This is to ensure that + unprocessed data doesn't end up sitting in the input fifo. */ + scb->bufcnt = read (scb->fd, scb->buf, + (SERIAL_IS_ASYNC_P (scb) ? 1 : BUFSIZ)); + if (scb->bufcnt != -1 || errno != EINTR) + break; + } + + if (scb->bufcnt <= 0) + { + if (scb->bufcnt == 0) + return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to + distinguish between EOF & timeouts + someday] */ + else + return SERIAL_ERROR; /* Got an error from read */ + } + + scb->bufcnt--; + scb->bufp = scb->buf; + return *scb->bufp++; +} + +int +ser_unix_nop_noflush_set_tty_state (serial_t scb, + serial_ttystate new_ttystate, + serial_ttystate old_ttystate) +{ + return 0; +} + +void +ser_unix_nop_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) +{ + /* Nothing to print. */ + return; +} + +int +ser_unix_nop_setbaudrate (serial_t scb, int rate) +{ + return 0; /* Never fails! */ +} + +int +ser_unix_nop_setstopbits (serial_t scb, int num) +{ + return 0; /* Never fails! */ +} + +int +ser_unix_write (serial_t scb, const char *str, int len) +{ + int cc; + + while (len > 0) + { + cc = write (scb->fd, str, len); + + if (cc < 0) + return 1; + len -= cc; + str += cc; + } + return 0; +} + +int +ser_unix_nop_flush_output (serial_t scb) +{ + return 0; +} + +int +ser_unix_nop_flush_input (serial_t scb) +{ + return 0; +} + +int +ser_unix_nop_send_break (serial_t scb) +{ + return 0; +} + +int +ser_unix_nop_drain_output (serial_t scb) +{ + return 0; +} + +static void +ser_unix_event (int error, int fd, gdb_client_data context) +{ + serial_t scb = context; + scb->async_handler (error, scb->async_context, fd); +} + +void +ser_unix_async (serial_t scb, + int async_p) +{ + if (async_p) + { + add_file_handler (scb->fd, ser_unix_event, scb); + } + else + { + delete_file_handler (scb->fd); + } +} void -_initialize_ser_hardwire () +_initialize_ser_hardwire (void) { - serial_add_interface (&hardwire_ops); + struct serial_ops *ops = XMALLOC (struct serial_ops); + memset (ops, sizeof (struct serial_ops), 0); + ops->name = "hardwire"; + ops->next = 0; + ops->open = hardwire_open; + ops->close = hardwire_close; + /* FIXME: Don't replace this with the equivalent ser_unix*() until + the old TERMIOS/SGTTY/... timer code has been flushed. cagney + 1999-09-16. */ + ops->readchar = hardwire_readchar; + /* FIXME: Don't replace this with the equivalent ser_unix*() until + the old TERMIOS/SGTTY/... timer code has been flushed. cagney + 1999-09-16. */ + ops->write = hardwire_write; + ops->flush_output = hardwire_flush_output; + ops->flush_input = hardwire_flush_input; + ops->send_break = hardwire_send_break; + ops->go_raw = hardwire_raw; + ops->get_tty_state = hardwire_get_tty_state; + ops->set_tty_state = hardwire_set_tty_state; + ops->print_tty_state = hardwire_print_tty_state; + ops->noflush_set_tty_state = hardwire_noflush_set_tty_state; + ops->setbaudrate = hardwire_setbaudrate; + ops->setstopbits = hardwire_setstopbits; + ops->drain_output = hardwire_drain_output; + ops->async = ser_unix_async; + serial_add_interface (ops); } diff --git a/gdb/serial.c b/gdb/serial.c index 9dd316f1dbe..3853014ef97 100644 --- a/gdb/serial.c +++ b/gdb/serial.c @@ -1,5 +1,5 @@ /* Generic serial interface routines - Copyright 1992, 1993, 1996, 1997 Free Software Foundation, Inc. + Copyright 1992, 1993, 1996, 1997, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -24,7 +24,7 @@ #include "gdb_string.h" #include "gdbcmd.h" -extern void _initialize_serial PARAMS ((void)); +extern void _initialize_serial (void); /* Linked list of serial I/O handlers */ @@ -44,8 +44,8 @@ static serial_t scb_base; static char *serial_logfile = NULL; static GDB_FILE *serial_logfp = NULL; -static struct serial_ops *serial_interface_lookup PARAMS ((char *)); -static void serial_logchar PARAMS ((int, int, int)); +static struct serial_ops *serial_interface_lookup (char *); +static void serial_logchar (int, int, int); static char logbase_hex[] = "hex"; static char logbase_octal[] = "octal"; static char logbase_ascii[] = "ascii"; @@ -54,6 +54,7 @@ static char *logbase_enums[] = static char *serial_logbase = logbase_ascii; + static int serial_current_type = 0; /* Log char CH of type CHTYPE, with TIMEOUT */ @@ -63,10 +64,7 @@ static int serial_current_type = 0; #define SERIAL_BREAK 1235 static void -serial_logchar (ch_type, ch, timeout) - int ch_type; - int ch; - int timeout; +serial_logchar (int ch_type, int ch, int timeout) { if (ch_type != serial_current_type) { @@ -128,8 +126,7 @@ serial_logchar (ch_type, ch, timeout) } void -serial_log_command (cmd) - const char *cmd; +serial_log_command (const char *cmd) { if (!serial_logfp) return; @@ -144,60 +141,9 @@ serial_log_command (cmd) gdb_flush (serial_logfp); } -int -serial_write (scb, str, len) - serial_t scb; - const char *str; - int len; -{ - if (serial_logfp != NULL) - { - int count; - - for (count = 0; count < len; count++) - serial_logchar ('w', str[count] & 0xff, 0); - - /* Make sure that the log file is as up-to-date as possible, - in case we are getting ready to dump core or something. */ - gdb_flush (serial_logfp); - } - - return (scb->ops->write (scb, str, len)); -} - -int -serial_readchar (scb, timeout) - serial_t scb; - int timeout; -{ - int ch; - - ch = scb->ops->readchar (scb, timeout); - if (serial_logfp != NULL) - { - serial_logchar ('r', ch, timeout); - - /* Make sure that the log file is as up-to-date as possible, - in case we are getting ready to dump core or something. */ - gdb_flush (serial_logfp); - } - - return (ch); -} - -int -serial_send_break (scb) - serial_t scb; -{ - if (serial_logfp != NULL) - serial_logchar ('w', SERIAL_BREAK, 0); - - return (scb->ops->send_break (scb)); -} - + static struct serial_ops * -serial_interface_lookup (name) - char *name; +serial_interface_lookup (char *name) { struct serial_ops *ops; @@ -209,8 +155,7 @@ serial_interface_lookup (name) } void -serial_add_interface (optable) - struct serial_ops *optable; +serial_add_interface (struct serial_ops *optable) { optable->next = serial_ops_list; serial_ops_list = optable; @@ -219,11 +164,11 @@ serial_add_interface (optable) /* Open up a device or a network socket, depending upon the syntax of NAME. */ serial_t -serial_open (name) - const char *name; +serial_open (const char *name) { serial_t scb; struct serial_ops *ops; + const char *open_name = name; for (scb = scb_base; scb; scb = scb->next) if (scb->name && strcmp (scb->name, name) == 0) @@ -241,7 +186,10 @@ serial_open (name) else if (strncmp (name, "lpt", 3) == 0) ops = serial_interface_lookup ("parallel"); else if (strncmp (name, "|", 1) == 0) - ops = serial_interface_lookup ("pipe"); + { + ops = serial_interface_lookup ("pipe"); + open_name = name + 1; /* discard ``|'' */ + } else ops = serial_interface_lookup ("hardwire"); @@ -255,7 +203,7 @@ serial_open (name) scb->bufcnt = 0; scb->bufp = scb->buf; - if (scb->ops->open (scb, name)) + if (scb->ops->open (scb, open_name)) { free (scb); return NULL; @@ -264,6 +212,8 @@ serial_open (name) scb->name = strsave (name); scb->next = scb_base; scb->refcnt = 1; + scb->async_handler = NULL; + scb->async_context = NULL; scb_base = scb; last_serial_opened = scb; @@ -279,8 +229,7 @@ serial_open (name) } serial_t -serial_fdopen (fd) - const int fd; +serial_fdopen (const int fd) { serial_t scb; struct serial_ops *ops; @@ -309,6 +258,8 @@ serial_fdopen (fd) scb->name = NULL; scb->next = scb_base; scb->refcnt = 1; + scb->async_handler = NULL; + scb->async_context = NULL; scb_base = scb; last_serial_opened = scb; @@ -316,10 +267,8 @@ serial_fdopen (fd) return scb; } -void -serial_close (scb, really_close) - serial_t scb; - int really_close; +static void +do_serial_close (serial_t scb, int really_close) { serial_t tmp_scb; @@ -345,6 +294,10 @@ serial_close (scb, really_close) if (scb->refcnt > 0) return; + /* ensure that the FD has been taken out of async mode */ + if (scb->async_handler != NULL) + serial_async (scb, NULL, NULL); + if (really_close) scb->ops->close (scb); @@ -366,6 +319,178 @@ serial_close (scb, really_close) free (scb); } +void +serial_close (serial_t scb) +{ + do_serial_close (scb, 1); +} + +void +serial_un_fdopen (serial_t scb) +{ + do_serial_close (scb, 0); +} + +int +serial_readchar (serial_t scb, int timeout) +{ + int ch; + + ch = scb->ops->readchar (scb, timeout); + if (serial_logfp != NULL) + { + serial_logchar ('r', ch, timeout); + + /* Make sure that the log file is as up-to-date as possible, + in case we are getting ready to dump core or something. */ + gdb_flush (serial_logfp); + } + + return (ch); +} + +int +serial_write (serial_t scb, const char *str, int len) +{ + if (serial_logfp != NULL) + { + int count; + + for (count = 0; count < len; count++) + serial_logchar ('w', str[count] & 0xff, 0); + + /* Make sure that the log file is as up-to-date as possible, + in case we are getting ready to dump core or something. */ + gdb_flush (serial_logfp); + } + + return (scb->ops->write (scb, str, len)); +} + +void +serial_printf (serial_t desc, const char *format,...) +{ + va_list args; + char *buf; + va_start (args, format); + + vasprintf (&buf, format, args); + SERIAL_WRITE (desc, buf, strlen (buf)); + + free (buf); + va_end (args); +} + +int +serial_drain_output (serial_t scb) +{ + return scb->ops->drain_output (scb); +} + +int +serial_flush_output (serial_t scb) +{ + return scb->ops->flush_output (scb); +} + +int +serial_flush_input (serial_t scb) +{ + return scb->ops->flush_input (scb); +} + +int +serial_send_break (serial_t scb) +{ + if (serial_logfp != NULL) + serial_logchar ('w', SERIAL_BREAK, 0); + + return (scb->ops->send_break (scb)); +} + +void +serial_raw (serial_t scb) +{ + scb->ops->go_raw (scb); +} + +serial_ttystate +serial_get_tty_state (serial_t scb) +{ + return scb->ops->get_tty_state (scb); +} + +int +serial_set_tty_state (serial_t scb, serial_ttystate ttystate) +{ + return scb->ops->set_tty_state (scb, ttystate); +} + +void +serial_print_tty_state (serial_t scb, + serial_ttystate ttystate, + struct gdb_file *stream) +{ + scb->ops->print_tty_state (scb, ttystate, stream); +} + +int +serial_noflush_set_tty_state (serial_t scb, + serial_ttystate new_ttystate, + serial_ttystate old_ttystate) +{ + return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate); +} + +int +serial_setbaudrate (serial_t scb, int rate) +{ + return scb->ops->setbaudrate (scb, rate); +} + +int +serial_setstopbits (serial_t scb, int num) +{ + return scb->ops->setstopbits (scb, num); +} + +int +serial_can_async_p (serial_t scb) +{ + return (scb->ops->async != NULL); +} + +int +serial_is_async_p (serial_t scb) +{ + return (scb->ops->async != NULL) && (scb->async_handler != NULL); +} + +void +serial_async (serial_t scb, + serial_event_ftype *handler, + void *context) +{ + /* Only change mode if there is a need. */ + if ((scb->async_handler == NULL) + != (handler == NULL)) + scb->ops->async (scb, handler != NULL); + scb->async_handler = handler; + scb->async_context = context; +} + +int +deprecated_serial_fd (serial_t scb) +{ + /* FIXME: should this output a warning that deprecated code is being + called? */ + if (scb->fd < 0) + { + internal_error ("serial: FD not valid"); + } + return scb->fd; /* sigh */ +} + #if 0 /* The connect command is #if 0 because I hadn't thought of an elegant @@ -389,8 +514,7 @@ serial_close (scb, really_close) static serial_t tty_desc; /* Controlling terminal */ static void -cleanup_tty (ttystate) - serial_ttystate ttystate; +cleanup_tty (serial_ttystate ttystate) { printf_unfiltered ("\r\n[Exiting connect mode]\r\n"); SERIAL_SET_TTY_STATE (tty_desc, ttystate); @@ -399,9 +523,7 @@ cleanup_tty (ttystate) } static void -connect_command (args, fromtty) - char *args; - int fromtty; +connect_command (char *args, int fromtty) { int c; char cur_esc = 0; @@ -493,21 +615,7 @@ connect_command (args, fromtty) #endif /* 0 */ void -serial_printf (serial_t desc, const char *format,...) -{ - va_list args; - char *buf; - va_start (args, format); - - vasprintf (&buf, format, args); - SERIAL_WRITE (desc, buf, strlen (buf)); - - free (buf); - va_end (args); -} - -void -_initialize_serial () +_initialize_serial (void) { #if 0 add_com ("connect", class_obscure, connect_command, diff --git a/gdb/serial.h b/gdb/serial.h index 09916fe8387..e3a1bf271f3 100644 --- a/gdb/serial.h +++ b/gdb/serial.h @@ -1,5 +1,5 @@ /* Remote serial support interface definitions for GDB, the GNU Debugger. - Copyright 1992, 1993 Free Software Foundation, Inc. + Copyright 1992, 1993, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -21,175 +21,219 @@ #ifndef SERIAL_H #define SERIAL_H -/* Terminal state pointer. This is specific to each type of interface. */ - -typedef PTR serial_ttystate; +/* For most routines, if a failure is indicated, then errno should be + examined. */ -struct _serial_t - { - int fd; /* File descriptor */ - struct serial_ops *ops; /* Function vector */ - void *state; /* Local context info for open FD */ - serial_ttystate ttystate; /* Not used (yet) */ - int bufcnt; /* Amount of data in receive buffer */ - unsigned char *bufp; /* Current byte */ - unsigned char buf[BUFSIZ]; /* Da buffer itself */ - int current_timeout; /* (termio{s} only), last value of VTIME */ - /* ser-unix.c termio{,s} only, we still need to wait for this many more - seconds. */ - int timeout_remaining; - char *name; /* The name of the device or host */ - struct _serial_t *next; /* Pointer to the next serial_t */ - int refcnt; /* Number of pointers to this block */ - }; +/* Terminal state pointer. This is specific to each type of + interface. */ +typedef void *serial_ttystate; +struct _serial_t; typedef struct _serial_t *serial_t; -struct serial_ops - { - char *name; - struct serial_ops *next; - int (*open) PARAMS ((serial_t, const char *name)); - void (*close) PARAMS ((serial_t)); - int (*readchar) PARAMS ((serial_t, int timeout)); - int (*write) PARAMS ((serial_t, const char *str, int len)); - /* Discard pending output */ - int (*flush_output) PARAMS ((serial_t)); - /* Discard pending input */ - int (*flush_input) PARAMS ((serial_t)); - int (*send_break) PARAMS ((serial_t)); - void (*go_raw) PARAMS ((serial_t)); - serial_ttystate (*get_tty_state) PARAMS ((serial_t)); - int (*set_tty_state) PARAMS ((serial_t, serial_ttystate)); - void (*print_tty_state) PARAMS ((serial_t, serial_ttystate)); - int (*noflush_set_tty_state) - PARAMS ((serial_t, serial_ttystate, serial_ttystate)); - int (*setbaudrate) PARAMS ((serial_t, int rate)); - int (*setstopbits) PARAMS ((serial_t, int num)); - /* Wait for output to drain */ - int (*drain_output) PARAMS ((serial_t)); - }; +/* Try to open NAME. Returns a new serial_t on success, NULL on + failure. */ -/* Add a new serial interface to the interface list */ +extern serial_t serial_open (const char *name); +#define SERIAL_OPEN(NAME) serial_open(NAME) -void serial_add_interface PARAMS ((struct serial_ops * optable)); +/* Open a new serial stream using a file handle. */ -serial_t serial_open PARAMS ((const char *name)); +extern serial_t serial_fdopen (const int fd); +#define SERIAL_FDOPEN(FD) serial_fdopen(FD) -serial_t serial_fdopen PARAMS ((const int fd)); +/* Push out all buffers, close the device and destroy SERIAL_T. */ -/* For most routines, if a failure is indicated, then errno should be - examined. */ +extern void serial_close (serial_t); +#define SERIAL_CLOSE(SERIAL_T) serial_close ((SERIAL_T)) -/* Try to open NAME. Returns a new serial_t on success, NULL on failure. - */ +/* Push out all buffers and destroy SERIAL_T without closing the + device. */ -#define SERIAL_OPEN(NAME) serial_open(NAME) +extern void serial_un_fdopen (serial_t scb); +#define SERIAL_UN_FDOPEN(SERIAL_T) serial_un_fdopen ((SERIAL_T)) -/* Open a new serial stream using a file handle. */ +/* Read one char from the serial device with TIMEOUT seconds to wait + or -1 to wait forever. Use timeout of 0 to effect a poll. Returns + char if ok, else one of the following codes. Note that all error + codes are guaranteed to be < 0. */ -#define SERIAL_FDOPEN(FD) serial_fdopen(FD) +#define SERIAL_ERROR -1 /* General error, see errno for details */ +#define SERIAL_TIMEOUT -2 +#define SERIAL_EOF -3 + +extern int serial_readchar (serial_t scb, int timeout); +#define SERIAL_READCHAR(SERIAL_T, TIMEOUT) serial_readchar ((SERIAL_T), (TIMEOUT)) + +/* Write LEN chars from STRING to the port SERIAL_T. Returns 0 for + success, non-zero for failure. */ + +extern int serial_write (serial_t scb, const char *str, int len); +#define SERIAL_WRITE(SERIAL_T, STRING,LEN) serial_write (SERIAL_T, STRING, LEN) + +/* Write a printf style string onto the serial port. */ + +extern void serial_printf (serial_t desc, const char *,...) ATTR_FORMAT (printf, 2, 3); /* Allow pending output to drain. */ -#define SERIAL_DRAIN_OUTPUT(SERIAL_T) \ - ((SERIAL_T)->ops->drain_output((SERIAL_T))) +extern int serial_drain_output (serial_t); +#define SERIAL_DRAIN_OUTPUT(SERIAL_T) serial_drain_output ((SERIAL_T)) -/* Flush (discard) pending output. Might also flush input (if this system can't flush - only output). */ +/* Flush (discard) pending output. Might also flush input (if this + system can't flush only output). */ -#define SERIAL_FLUSH_OUTPUT(SERIAL_T) \ - ((SERIAL_T)->ops->flush_output((SERIAL_T))) +extern int serial_flush_output (serial_t); +#define SERIAL_FLUSH_OUTPUT(SERIAL_T) serial_flush_output ((SERIAL_T)) -/* Flush pending input. Might also flush output (if this system can't flush - only input). */ +/* Flush pending input. Might also flush output (if this system can't + flush only input). */ -#define SERIAL_FLUSH_INPUT(SERIAL_T)\ - ((*(SERIAL_T)->ops->flush_input) ((SERIAL_T))) +extern int serial_flush_input (serial_t); +#define SERIAL_FLUSH_INPUT(SERIAL_T) serial_flush_input ((SERIAL_T)) /* Send a break between 0.25 and 0.5 seconds long. */ -extern int serial_send_break PARAMS ((serial_t scb)); - +extern int serial_send_break (serial_t scb); #define SERIAL_SEND_BREAK(SERIAL_T) serial_send_break (SERIAL_T) /* Turn the port into raw mode. */ -#define SERIAL_RAW(SERIAL_T) (SERIAL_T)->ops->go_raw((SERIAL_T)) +extern void serial_raw (serial_t scb); +#define SERIAL_RAW(SERIAL_T) serial_raw ((SERIAL_T)) /* Return a pointer to a newly malloc'd ttystate containing the state of the tty. */ -#define SERIAL_GET_TTY_STATE(SERIAL_T) (SERIAL_T)->ops->get_tty_state((SERIAL_T)) + +extern serial_ttystate serial_get_tty_state (serial_t scb); +#define SERIAL_GET_TTY_STATE(SERIAL_T) serial_get_tty_state ((SERIAL_T)) /* Set the state of the tty to TTYSTATE. The change is immediate. When changing to or from raw mode, input might be discarded. - Returns 0 for success, negative value for error (in which case errno - contains the error). */ -#define SERIAL_SET_TTY_STATE(SERIAL_T, TTYSTATE) (SERIAL_T)->ops->set_tty_state((SERIAL_T), (TTYSTATE)) + Returns 0 for success, negative value for error (in which case + errno contains the error). */ + +extern int serial_set_tty_state (serial_t scb, serial_ttystate ttystate); +#define SERIAL_SET_TTY_STATE(SERIAL_T, TTYSTATE) serial_set_tty_state ((SERIAL_T), (TTYSTATE)) -/* printf_filtered a user-comprehensible description of ttystate. */ -#define SERIAL_PRINT_TTY_STATE(SERIAL_T, TTYSTATE) \ - ((*((SERIAL_T)->ops->print_tty_state)) ((SERIAL_T), (TTYSTATE))) +/* printf_filtered a user-comprehensible description of ttystate on + the specified STREAM. FIXME: At present this sends output to the + default stream - GDB_STDOUT. */ + +extern void serial_print_tty_state (serial_t scb, serial_ttystate ttystate, struct gdb_file *); +#define SERIAL_PRINT_TTY_STATE(SERIAL_T, TTYSTATE, STREAM) serial_print_tty_state ((SERIAL_T), (TTYSTATE), (STREAM)) /* Set the tty state to NEW_TTYSTATE, where OLD_TTYSTATE is the current state (generally obtained from a recent call to SERIAL_GET_TTY_STATE), but be careful not to discard any input. - This means that we never switch in or out of raw mode, even - if NEW_TTYSTATE specifies a switch. */ + This means that we never switch in or out of raw mode, even if + NEW_TTYSTATE specifies a switch. */ + +extern int serial_noflush_set_tty_state (serial_t scb, serial_ttystate new_ttystate, serial_ttystate old_ttystate); #define SERIAL_NOFLUSH_SET_TTY_STATE(SERIAL_T, NEW_TTYSTATE, OLD_TTYSTATE) \ - ((*((SERIAL_T)->ops->noflush_set_tty_state)) \ - ((SERIAL_T), (NEW_TTYSTATE), (OLD_TTYSTATE))) +serial_noflush_set_tty_state ((SERIAL_T), (NEW_TTYSTATE), (OLD_TTYSTATE)) -/* Read one char from the serial device with TIMEOUT seconds to wait - or -1 to wait forever. Use timeout of 0 to effect a poll. Returns - char if ok, else one of the following codes. Note that all error - codes are guaranteed to be < 0. */ +/* Set the baudrate to the decimal value supplied. Returns 0 for + success, -1 for failure. */ -#define SERIAL_ERROR -1 /* General error, see errno for details */ -#define SERIAL_TIMEOUT -2 -#define SERIAL_EOF -3 +extern int serial_setbaudrate (serial_t scb, int rate); +#define SERIAL_SETBAUDRATE(SERIAL_T, RATE) serial_setbaudrate ((SERIAL_T), (RATE)) -extern int serial_readchar PARAMS ((serial_t scb, int timeout)); +/* Set the number of stop bits to the value specified. Returns 0 for + success, -1 for failure. */ -#define SERIAL_READCHAR(SERIAL_T, TIMEOUT) serial_readchar (SERIAL_T, TIMEOUT) +#define SERIAL_1_STOPBITS 1 +#define SERIAL_1_AND_A_HALF_STOPBITS 2 /* 1.5 bits, snicker... */ +#define SERIAL_2_STOPBITS 3 -/* Set the baudrate to the decimal value supplied. Returns 0 for success, - -1 for failure. */ +extern int serial_setstopbits (serial_t scb, int num); +#define SERIAL_SETSTOPBITS(SERIAL_T, NUM) serial_setstopbits ((SERIAL_T), (NUM)) -#define SERIAL_SETBAUDRATE(SERIAL_T, RATE) ((SERIAL_T)->ops->setbaudrate((SERIAL_T), RATE)) +/* Asynchronous serial interface: */ -/* Set the number of stop bits to the value specified. Returns 0 for success, - -1 for failure. */ +/* Can the serial device support asynchronous mode? */ -#define SERIAL_1_STOPBITS 1 -#define SERIAL_1_AND_A_HALF_STOPBITS 2 /* 1.5 bits, snicker... */ -#define SERIAL_2_STOPBITS 3 +extern int serial_can_async_p (serial_t scb); +#define SERIAL_CAN_ASYNC_P(SERIAL_T) serial_can_async_p ((SERIAL_T)) -#define SERIAL_SETSTOPBITS(SERIAL_T, NUM) ((SERIAL_T)->ops->setstopbits((SERIAL_T), NUM)) +/* Has the serial device been put in asynchronous mode? */ -/* Write LEN chars from STRING to the port SERIAL_T. Returns 0 for - success, non-zero for failure. */ +extern int serial_is_async_p (serial_t scb); +#define SERIAL_IS_ASYNC_P(SERIAL_T) serial_is_async_p ((SERIAL_T)) -extern int serial_write PARAMS ((serial_t scb, const char *str, int len)); +/* For ASYNC enabled devices, register a callback and enable + asynchronous mode. To disable asynchronous mode, register a NULL + callback. */ -#define SERIAL_WRITE(SERIAL_T, STRING,LEN) serial_write (SERIAL_T, STRING, LEN) +typedef void (serial_event_ftype) (int error, void *context, int fd); +extern void serial_async (serial_t scb, serial_event_ftype *handler, void *context); +#define SERIAL_ASYNC(SERIAL_T, HANDLER, CONTEXT) serial_async ((SERIAL_T), (HANDLER), (CONTEXT)) -/* Push out all buffers, close the device and destroy SERIAL_T. */ +/* Provide direct access to the underlying FD (if any) used to + implement the serial device. This interface is clearly + deprecated. Will call internal_error() if the operation isn't + applicable to the current serial device. */ -extern void serial_close PARAMS ((serial_t, int)); +extern int deprecated_serial_fd (serial_t scb); +#define DEPRECATED_SERIAL_FD(SERIAL_T) deprecated_serial_fd ((SERIAL_T)) -#define SERIAL_CLOSE(SERIAL_T) serial_close(SERIAL_T, 1) -/* Push out all buffers and destroy SERIAL_T without closing the device. */ +/* Details of an instance of a serial object */ -#define SERIAL_UN_FDOPEN(SERIAL_T) serial_close(SERIAL_T, 0) +struct _serial_t + { + int fd; /* File descriptor */ + struct serial_ops *ops; /* Function vector */ + void *state; /* Local context info for open FD */ + serial_ttystate ttystate; /* Not used (yet) */ + int bufcnt; /* Amount of data in receive buffer */ + unsigned char *bufp; /* Current byte */ + unsigned char buf[BUFSIZ]; /* Da buffer itself */ + int current_timeout; /* (termio{s} only), last value of VTIME */ + /* ser-unix.c termio{,s} only, we still need to wait for this many more + seconds. */ + int timeout_remaining; + char *name; /* The name of the device or host */ + struct _serial_t *next; /* Pointer to the next serial_t */ + int refcnt; /* Number of pointers to this block */ + void *async_context; /* Async event thread's context */ + serial_event_ftype *async_handler;/* Async event handler */ + }; + +struct serial_ops + { + char *name; + struct serial_ops *next; + int (*open) (serial_t, const char *name); + void (*close) (serial_t); + int (*readchar) (serial_t, int timeout); + int (*write) (serial_t, const char *str, int len); + /* Discard pending output */ + int (*flush_output) (serial_t); + /* Discard pending input */ + int (*flush_input) (serial_t); + int (*send_break) (serial_t); + void (*go_raw) (serial_t); + serial_ttystate (*get_tty_state) (serial_t); + int (*set_tty_state) (serial_t, serial_ttystate); + void (*print_tty_state) (serial_t, serial_ttystate, struct gdb_file *); + int (*noflush_set_tty_state) (serial_t, serial_ttystate, serial_ttystate); + int (*setbaudrate) (serial_t, int rate); + int (*setstopbits) (serial_t, int num); + /* Wait for output to drain */ + int (*drain_output) (serial_t); + /* Change the serial device into/out of asynchronous mode, call + the specified function when ever there is something + interesting. */ + void (*async) (serial_t scb, int async_p); + }; + +/* Add a new serial interface to the interface list */ -extern void serial_printf -PARAMS ((serial_t desc, const char *,...)) -ATTR_FORMAT (printf, 2, 3); +extern void serial_add_interface (struct serial_ops * optable); /* File in which to record the remote debugging session */ - extern void serial_log_command PARAMS ((const char *)); +extern void serial_log_command (const char *); #endif /* SERIAL_H */ diff --git a/gdb/source.c b/gdb/source.c index 4293e59bc14..358cac9e496 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -23,6 +23,7 @@ #include "expression.h" #include "language.h" #include "command.h" +#include "source.h" #include "gdbcmd.h" #include "frame.h" #include "value.h" @@ -58,12 +59,6 @@ #endif /* ! defined (CRLF_SOURCE_FILES) */ -/* Forward declarations */ - -int open_source_file PARAMS ((struct symtab *)); - -void find_source_lines PARAMS ((struct symtab *, int)); - /* Prototypes for exported functions. */ void _initialize_source PARAMS ((void)); diff --git a/gdb/symtab.c b/gdb/symtab.c index e6a67b0151f..36a40519416 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -396,11 +396,7 @@ find_pc_sect_psymtab (pc, section) ALL_PSYMTABS (objfile, pst) { -#if defined(HPUXHPPA) - if (pc >= pst->textlow && pc <= pst->texthigh) -#else if (pc >= pst->textlow && pc < pst->texthigh) -#endif { struct minimal_symbol *msymbol; struct partial_symtab *tpst; @@ -419,11 +415,7 @@ find_pc_sect_psymtab (pc, section) for (tpst = pst; tpst != NULL; tpst = tpst->next) { -#if defined(HPUXHPPA) - if (pc >= tpst->textlow && pc <= tpst->texthigh) -#else if (pc >= tpst->textlow && pc < tpst->texthigh) -#endif { struct partial_symbol *p; @@ -1437,11 +1429,7 @@ find_pc_sect_symtab (pc, section) b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); if (BLOCK_START (b) <= pc -#if defined(HPUXHPPA) - && BLOCK_END (b) >= pc -#else && BLOCK_END (b) > pc -#endif && (distance == 0 || BLOCK_END (b) - BLOCK_START (b) < distance)) { @@ -2578,7 +2566,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) && strchr (gdb_completer_quote_characters, **argptr) != NULL); has_parens = ((pp = strchr (*argptr, '(')) != NULL - && (pp = strchr (pp, ')')) != NULL); + && (pp = strrchr (pp, ')')) != NULL); /* Now that we're safely past the has_parens check, * put back " if (condition)" so outer layers can see it diff --git a/gdb/symtab.h b/gdb/symtab.h index 0d9903b2aef..d651209ecdb 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1219,7 +1219,7 @@ extern struct minimal_symbol *prim_record_minimal_symbol_and_info #ifdef SOFUN_ADDRESS_MAYBE_MISSING extern CORE_ADDR find_stab_function_addr PARAMS ((char *, - struct partial_symtab *, + char *, struct objfile *)); #endif diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 7198d6e9f01..5d162aeb99b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,24 @@ +1999-09-18 Jim Blandy <jimb@cris.red-bean.com> + + * gdb.base/break.exp: Code locations are in hex, don't forget! + (For HP-UX.) + +1999-09-17 Stan Shebs <shebs@andros.cygnus.com> + + * condbreak.exp: Use break.c as test program. + * condbreak.c: Remove, redundant with break.c. + +1999-09-15 Stan Shebs <shebs@andros.cygnus.com> + + * config/monitor.exp (gdb_target_monitor): Disable X- and + Z-packets if the target needs it. + +1999-09-13 James Ingham <jingham@leda.cygnus.com> + + * gdb.c++/overload.exp: Added tests for listing overloaded + functions with function pointers in the arg, explicitly calling + out the version you want. + 1999-09-09 Stan Shebs <shebs@andros.cygnus.com> * long_long.exp: Add variations of test cases that work for diff --git a/gdb/testsuite/config/monitor.exp b/gdb/testsuite/config/monitor.exp index 727ef5386b5..b4824807ef0 100644 --- a/gdb/testsuite/config/monitor.exp +++ b/gdb/testsuite/config/monitor.exp @@ -38,6 +38,12 @@ proc gdb_target_monitor { exec_file } { if [target_info exists binarydownload] { gdb_test "set remotebinarydownload [target_info binarydownload]" "" "" } + if { [ target_info exists disable_x_packet ] } { + gdb_test "set remote X-packet disable" "" + } + if { [ target_info exists disable_z_packet ] } { + gdb_test "set remote Z-packet disable" "" + } if [target_info exists gdb_serial] { set serialport "[target_info gdb_serial]"; } elseif [target_info exists netport] { diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp index 454d08b95d1..bfd3c41ed3e 100644 --- a/gdb/testsuite/gdb.base/break.exp +++ b/gdb/testsuite/gdb.base/break.exp @@ -556,12 +556,13 @@ gdb_expect { # As long as we're stopped (breakpointed) in a called function, # verify that we can successfully backtrace & such from here. # + if [istarget "hppa*-*-hpux*"] then { send_gdb "bt\n" gdb_expect { - -re "#0\[ \t\]*0x\[0-9\]* in marker2.*:4\[49\]\r\n#1.*_sr4export.*$gdb_prompt $"\ + -re "#0\[ \t\]*$hex in marker2.*:4\[49\]\r\n#1.*_sr4export.*$gdb_prompt $"\ {pass "backtrace while in called function"} - -re "#0\[ \t\]*0x\[0-9\]* in marker2.*:4\[49\]\r\n#1.*function called from gdb.*$gdb_prompt $"\ + -re "#0\[ \t\]*$hex in marker2.*:4\[49\]\r\n#1.*function called from gdb.*$gdb_prompt $"\ {pass "backtrace while in called function"} -re "$gdb_prompt $"\ diff --git a/gdb/testsuite/gdb.base/condbreak.exp b/gdb/testsuite/gdb.base/condbreak.exp index 8ec8536cad9..ae0858bf52b 100644 --- a/gdb/testsuite/gdb.base/condbreak.exp +++ b/gdb/testsuite/gdb.base/condbreak.exp @@ -1,4 +1,4 @@ -# Copyright (C) 1997, 1998 Free Software Foundation, Inc. +# Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,8 +21,6 @@ # Purpose is to test conditional breakpoints. # Modeled after "break.exp". - - if $tracelevel then { strace $tracelevel } @@ -35,7 +33,7 @@ global usestubs set prms_id 0 set bug_id 0 -set testfile "condbreak" +set testfile "break" set srcfile ${testfile}.c set binfile ${objdir}/${subdir}/${testfile} diff --git a/gdb/testsuite/gdb.c++/overload.cc b/gdb/testsuite/gdb.c++/overload.cc index 58d07de930e..97083c5640c 100644 --- a/gdb/testsuite/gdb.c++/overload.cc +++ b/gdb/testsuite/gdb.c++/overload.cc @@ -24,6 +24,10 @@ int overload1arg (unsigned long); int overload1arg (float); int overload1arg (double); +int overloadfnarg (void); +int overloadfnarg (int); +int overloadfnarg (int, int (*) (int)); + int overloadargs (int a1); int overloadargs (int a1, int a2); int overloadargs (int a1, int a2, int a3); @@ -94,6 +98,12 @@ int foo::overload1arg (unsigned long arg) { arg = 0; return 10;} int foo::overload1arg (float arg) { arg = 0; return 11;} int foo::overload1arg (double arg) { arg = 0; return 12;} +/* Test to see that we can explicitly request overloaded functions + with function pointers in the prototype. */ + +int foo::overloadfnarg (void) { return ifoo * 20; } +int foo::overloadfnarg (int arg) { arg = 0; return 13;} +int foo::overloadfnarg (int arg, int (*foo) (int)) { return foo(arg); } /* Some functions to test overloading by varying argument count. */ diff --git a/gdb/testsuite/gdb.c++/overload.exp b/gdb/testsuite/gdb.c++/overload.exp index fa12bff2515..e889273d7b4 100644 --- a/gdb/testsuite/gdb.c++/overload.exp +++ b/gdb/testsuite/gdb.c++/overload.exp @@ -397,3 +397,25 @@ gdb_expect { -re ".*$gdb_prompt $" { fail "print call overloaded func double arg" } timeout { fail "(timeout) print call overloaded func double arg" } } + +# Now some tests to see if we can list overloaded functions properly: + +send_gdb "set listsize 1\n" +gdb_expect -re ".*$gdb_prompt $" + +gdb_test "list foo::overloadfnarg(void)"\ + ".*int foo::overloadfnarg.*\\(void\\).*" \ + "print overloaded function with no args" + +gdb_test "list foo::overloadfnarg(int)"\ + "int foo::overloadfnarg.*\\(int arg\\).*" \ + "print overloaded function with int arg" + +gdb_test "list foo::overloadfnarg(int, int (*)(int))" \ + "int foo::overloadfnarg.*\\(int arg, int \\(\\*foo\\) \\(int\\)\\).*" \ + "print overloaded function with function ptr args" + +# This one crashes GDB. Don't know why yet. +gdb_test "list \"foo::overloadfnarg(int, int (*)(int))\"" \ + "int foo::overloadfnarg.*\\(int arg, int \\(\\*foo\\) \\(int\\)\\).*" \ + "print overloaded function with function ptr args - quotes around argument" diff --git a/gdb/top.c b/gdb/top.c index 2271d2a0496..3ffc241942b 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -46,6 +46,7 @@ #include <sys/types.h> #include "event-loop.h" +#include "event-top.h" #include "gdb_string.h" #include "gdb_stat.h" #include <ctype.h> diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 988cb122318..0317e210450 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -30,6 +30,7 @@ #include "gdb_string.h" #include "inferior.h" #include "tracepoint.h" +#include "remote.h" #include "ax.h" #include "ax-gdb.h" @@ -193,13 +194,6 @@ trace_error (buf) } } -/* Entry points into remote.c (FIXME: move this interface down to tgt vector) - */ - -extern int putpkt PARAMS ((char *)); -extern void getpkt PARAMS ((char *, int)); -extern void remote_console_output PARAMS ((char *)); - /* Utility: wait for reply from stub, while accepting "O" packets */ static char * remote_get_noisy_reply (buf) diff --git a/gdb/tui/ChangeLog b/gdb/tui/ChangeLog index 7dc1bf60460..c2a7b58383d 100644 --- a/gdb/tui/ChangeLog +++ b/gdb/tui/ChangeLog @@ -1,3 +1,8 @@ +Fri Sep 17 19:34:38 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * tuiSource.c: Include "source.h". + (open_source_file, find_source_lines): Delete declarations. + 1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com) * tui.h: Include stdarg.h instead of varargs.h if we're on an ISO Cish diff --git a/gdb/tui/tuiSource.c b/gdb/tui/tuiSource.c index 36c1e7cd9a2..356b0140a3b 100644 --- a/gdb/tui/tuiSource.c +++ b/gdb/tui/tuiSource.c @@ -8,6 +8,7 @@ #include "symtab.h" #include "frame.h" #include "breakpoint.h" +#include "source.h" #include "tui.h" #include "tuiData.h" @@ -17,13 +18,6 @@ /***************************************** -** EXTERNAL FUNCTION DECLS ** -******************************************/ - -extern int open_source_file PARAMS ((struct symtab *)); -extern void find_source_lines PARAMS ((struct symtab *, int)); - -/***************************************** ** EXTERNAL DATA DECLS ** ******************************************/ extern int current_source_line; diff --git a/gdb/utils.c b/gdb/utils.c index bd42ee2cd3e..feba7647701 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -22,6 +22,7 @@ #include <ctype.h> #include "gdb_string.h" #include "event-loop.h" +#include "event-top.h" #ifdef HAVE_CURSES_H #include <curses.h> @@ -393,6 +394,22 @@ do_all_continuations () free (continuation_ptr); } } + +/* Walk down the cmd_continuation list, and get rid of all the + continuations. */ +void +discard_all_continuations () +{ + struct continuation *continuation_ptr; + + while (cmd_continuation) + { + continuation_ptr = cmd_continuation; + cmd_continuation = continuation_ptr->next; + free (continuation_ptr); + } +} + /* Print a warning message. Way to use this is to call warning_begin, diff --git a/gdb/valops.c b/gdb/valops.c index 3c30d8ff9be..ea61789876f 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -61,10 +61,6 @@ static CORE_ADDR value_push PARAMS ((CORE_ADDR, value_ptr)); static value_ptr search_struct_field PARAMS ((char *, value_ptr, int, struct type *, int)); -static value_ptr search_struct_field_aux PARAMS ((char *, value_ptr, int, - struct type *, int, int *, char *, - struct type **)); - static value_ptr search_struct_method PARAMS ((char *, value_ptr *, value_ptr *, int, int *, struct type *)); @@ -970,7 +966,6 @@ value_ind (arg1) { struct type *base_type; value_ptr arg2; - value_ptr real_val; COERCE_ARRAY (arg1); @@ -2544,7 +2539,6 @@ value_find_oload_method_list (argp, method, offset, static_memfuncp, num_fns, ba int *boffset; { struct type *t; - value_ptr v; t = check_typedef (VALUE_TYPE (*argp)); @@ -2677,8 +2671,6 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp, /* Consider each candidate in turn */ for (ix = 0; ix < num_fns; ix++) { - int jj; - /* Number of parameters for current candidate */ nparms = method ? TYPE_NFIELDS (fns_ptr[ix].type) : TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[ix])); diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 4f9d2704977..e0274569ad0 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,20 @@ +Mon Sep 20 21:44:06 1999 Geoffrey Keating <geoffk@cygnus.com> + + * sim-fpu.c (i2fpu): Keep the guard bits sticky when converting + large values. + +Wed Sep 15 14:12:37 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * hw-tree.c, hw-properties.c, hw-instances.c: Include "sim-io.h". + +Tue Sep 14 14:15:47 1999 Dave Brolley <brolley@cygnus.com> + + * cgen-par.h (CGEN_BI_WRITE): New enumerator. + (bi_write): New union element. + (sim_queue_bi_write): New function. + * cgen-par.c (sim_queue_bi_write): New function. + (cgen_write_queue_element_execute): Handle CGEN_BI_WRITE. + Thu Sep 2 18:15:53 1999 Andrew Cagney <cagney@b1.cygnus.com> * configure: Regenerated to track ../common/aclocal.m4 changes. diff --git a/sim/common/Make-common.in b/sim/common/Make-common.in index 9b9ea4e5ef2..7c25d6c125f 100644 --- a/sim/common/Make-common.in +++ b/sim/common/Make-common.in @@ -399,7 +399,6 @@ sim-fpu.o: $(srccom)/sim-fpu.c $(sim-fpu_h) \ $(SIM_EXTRA_DEPS) $(CC) -c $(srccom)/sim-fpu.c $(ALL_CFLAGS) - sim-hload.o: $(srccom)/sim-hload.c $(sim-assert_h) \ $(srcroot)/include/remote-sim.h \ $(SIM_EXTRA_DEPS) diff --git a/sim/common/cgen-par.c b/sim/common/cgen-par.c index 8b983fbe4c0..51147adad7d 100644 --- a/sim/common/cgen-par.c +++ b/sim/common/cgen-par.c @@ -24,6 +24,15 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Functions required by the cgen interface. These functions add various kinds of writes to the write queue. */ +void sim_queue_bi_write (SIM_CPU *cpu, BI *target, BI value) +{ + CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu); + CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q); + element->kind = CGEN_BI_WRITE; + element->kinds.bi_write.target = target; + element->kinds.bi_write.value = value; +} + void sim_queue_qi_write (SIM_CPU *cpu, UQI *target, UQI value) { CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu); @@ -138,6 +147,9 @@ cgen_write_queue_element_execute (SIM_CPU *cpu, CGEN_WRITE_QUEUE_ELEMENT *item) IADDR pc; switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item)) { + case CGEN_BI_WRITE: + *item->kinds.bi_write.target = item->kinds.bi_write.value; + break; case CGEN_QI_WRITE: *item->kinds.qi_write.target = item->kinds.qi_write.value; break; diff --git a/sim/common/cgen-par.h b/sim/common/cgen-par.h index ce4efd59307..25272a3c5e7 100644 --- a/sim/common/cgen-par.h +++ b/sim/common/cgen-par.h @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Kinds of writes stored on the write queue. */ enum cgen_write_queue_kind { - CGEN_QI_WRITE, CGEN_SI_WRITE, CGEN_SF_WRITE, + CGEN_BI_WRITE, CGEN_QI_WRITE, CGEN_SI_WRITE, CGEN_SF_WRITE, CGEN_PC_WRITE, CGEN_FN_SI_WRITE, CGEN_FN_DI_WRITE, CGEN_FN_DF_WRITE, CGEN_MEM_QI_WRITE, CGEN_MEM_HI_WRITE, CGEN_MEM_SI_WRITE, @@ -35,6 +35,10 @@ typedef struct { enum cgen_write_queue_kind kind; /* Used to select union member below. */ union { struct { + BI *target; + BI value; + } bi_write; + struct { UQI *target; QI value; } qi_write; @@ -107,6 +111,7 @@ typedef struct { extern CGEN_WRITE_QUEUE_ELEMENT *cgen_write_queue_overflow (CGEN_WRITE_QUEUE *); /* Functions for queuing writes. Used by semantic code. */ +extern void sim_queue_bi_write (SIM_CPU *, BI *, BI); extern void sim_queue_qi_write (SIM_CPU *, UQI *, UQI); extern void sim_queue_si_write (SIM_CPU *, SI *, SI); extern void sim_queue_sf_write (SIM_CPU *, SI *, SF); diff --git a/sim/common/hw-instances.c b/sim/common/hw-instances.c index 613f8198e54..22c1cd9e9a9 100644 --- a/sim/common/hw-instances.c +++ b/sim/common/hw-instances.c @@ -22,6 +22,7 @@ #include "hw-main.h" #include "hw-base.h" +#include "sim-io.h" #include "sim-assert.h" struct hw_instance_data { diff --git a/sim/common/hw-properties.c b/sim/common/hw-properties.c index a1e9291269c..5a4d76dbf1d 100644 --- a/sim/common/hw-properties.c +++ b/sim/common/hw-properties.c @@ -21,6 +21,7 @@ #include "hw-main.h" #include "hw-base.h" +#include "sim-io.h" #include "sim-assert.h" #ifdef HAVE_STRING_H diff --git a/sim/common/hw-tree.c b/sim/common/hw-tree.c index 1a558351b25..3f31b3b4394 100644 --- a/sim/common/hw-tree.c +++ b/sim/common/hw-tree.c @@ -22,6 +22,7 @@ #include "hw-base.h" #include "hw-tree.h" +#include "sim-io.h" #include "sim-assert.h" #ifdef HAVE_STDLIB_H diff --git a/sim/common/sim-base.h b/sim/common/sim-base.h index f3af30553a2..420b137b6b2 100644 --- a/sim/common/sim-base.h +++ b/sim/common/sim-base.h @@ -236,7 +236,6 @@ typedef struct { #define STATE_HW(sd) ((sd)->base.hw) #endif - /* Should image loads be performed using the LMA or VMA? Older simulators use the VMA while newer simulators prefer the LMA. */ int load_at_lma_p; diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c index abf746a9b68..99381e06b17 100644 --- a/sim/common/sim-fpu.c +++ b/sim/common/sim-fpu.c @@ -541,7 +541,7 @@ i2fpu (sim_fpu *f, signed64 i, int is_64bit) { do { - f->fraction >>= 1; + f->fraction = (f->fraction >> 1) | (f->fraction & 1); f->normal_exp += 1; } while (f->fraction >= IMPLICIT_2); diff --git a/sim/configure b/sim/configure index 4d0232e5411..82caaacf491 100755 --- a/sim/configure +++ b/sim/configure @@ -13,8 +13,6 @@ ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --enable-sim " -ac_help="$ac_help -" # Initialize some variables set by options. # The variables have the same names as the options, with @@ -529,7 +527,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:533: checking for $ac_word" >&5 +echo "configure:531: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -559,7 +557,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:563: checking for $ac_word" >&5 +echo "configure:561: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -610,7 +608,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:614: checking for $ac_word" >&5 +echo "configure:612: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -642,7 +640,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:646: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:644: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -653,12 +651,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 657 "configure" +#line 655 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -684,12 +682,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:688: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:686: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:693: checking whether we are using GNU C" >&5 +echo "configure:691: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -698,7 +696,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:702: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -717,7 +715,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:721: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:719: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -779,7 +777,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:783: checking for a BSD compatible install" >&5 +echo "configure:781: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -838,7 +836,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:842: checking host system type" >&5 +echo "configure:840: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -859,7 +857,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:863: checking build system type" >&5 +echo "configure:861: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -885,7 +883,7 @@ fi # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:889: checking for $ac_word" >&5 +echo "configure:887: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -917,7 +915,7 @@ fi # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:921: checking for $ac_word" >&5 +echo "configure:919: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -949,7 +947,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:953: checking for $ac_word" >&5 +echo "configure:951: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1029,7 +1027,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:1033: checking host system type" >&5 +echo "configure:1031: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -1050,7 +1048,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:1054: checking target system type" >&5 +echo "configure:1052: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -1068,7 +1066,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1072: checking build system type" >&5 +echo "configure:1070: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1112,7 +1110,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x," # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1116: checking for $ac_word" >&5 +echo "configure:1114: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1142,7 +1140,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1146: checking for $ac_word" >&5 +echo "configure:1144: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1193,7 +1191,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1197: checking for $ac_word" >&5 +echo "configure:1195: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1225,7 +1223,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1229: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1227: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1236,12 +1234,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1240 "configure" +#line 1238 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1245: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1243: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1267,12 +1265,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1271: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1269: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1276: checking whether we are using GNU C" >&5 +echo "configure:1274: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1281,7 +1279,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1283: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1300,7 +1298,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1304: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1302: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1338,7 +1336,7 @@ AR=${AR-ar} # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1342: checking for $ac_word" >&5 +echo "configure:1340: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1483,8 +1481,6 @@ case "${target}" in esac - - # Is there a testsuite directory for the target? testdir=`echo ${target} | sed -e 's/-.*-/-/'` if test -r ${srcdir}/testsuite/${testdir}/configure ; then diff --git a/sim/configure.in b/sim/configure.in index c37304990f0..ccff05e7cb2 100644 --- a/sim/configure.in +++ b/sim/configure.in @@ -131,8 +131,6 @@ case "${target}" in esac - - # Is there a testsuite directory for the target? testdir=`echo ${target} | sed -e 's/-.*-/-/'` if test -r ${srcdir}/testsuite/${testdir}/configure ; then diff --git a/sim/d10v/ChangeLog b/sim/d10v/ChangeLog index 0695db23b27..6fa21b1de4f 100644 --- a/sim/d10v/ChangeLog +++ b/sim/d10v/ChangeLog @@ -1,3 +1,7 @@ +1999-09-14 Nick Clifton <nickc@cygnus.com> + + * simops.c: Disable setting of DM bit in PSW. + Wed Sep 8 19:34:55 MDT 1999 Diego Novillo <dnovillo@cygnus.com> * simops.c (op_types): Added new memory indirect type OP_MEMREF3. diff --git a/sim/d10v/simops.c b/sim/d10v/simops.c index 22bdd91e104..9d779438b9e 100644 --- a/sim/d10v/simops.c +++ b/sim/d10v/simops.c @@ -48,7 +48,6 @@ enum { PSW_MASK = (PSW_SM_BIT | PSW_EA_BIT | PSW_DB_BIT - | PSW_DM_BIT | PSW_IE_BIT | PSW_RP_BIT | PSW_MD_BIT @@ -1097,7 +1096,7 @@ OP_5F20 () trace_input ("dbt", OP_VOID, OP_VOID, OP_VOID); SET_DPC (PC + 1); SET_DPSW (PSW); - SET_PSW (PSW_DM_BIT | (PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + SET_PSW (PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)); JMP (DBT_VECTOR_START); trace_output_void (); } @@ -2242,7 +2241,6 @@ OP_5F40 () trace_output_void (); } - /* sac */ void OP_5209 () { @@ -2275,7 +2273,6 @@ void OP_5209 () trace_output_40 (tmp); } - /* sachi */ void OP_4209 () @@ -2309,7 +2306,6 @@ OP_4209 () trace_output_16 (OP[0]); } - /* sadd */ void OP_1223 () @@ -2407,7 +2403,6 @@ OP_3220 () trace_output_40(tmp); } - /* sleep */ void OP_5FC0 () @@ -3428,4 +3423,3 @@ OP_5000000 () SET_GPR (OP[0], tmp); trace_output_16 (tmp); } - diff --git a/sim/testsuite/ChangeLog b/sim/testsuite/ChangeLog index e876e1f8f67..5c537dc6175 100644 --- a/sim/testsuite/ChangeLog +++ b/sim/testsuite/ChangeLog @@ -1,3 +1,9 @@ +1999-09-15 Doug Evans <devans@casey.cygnus.com> + + * sim/arm/b.cgs: New testcase. + * sim/arm/bic.cgs: New testcase. + * sim/arm/bl.cgs: New testcase. + Thu Sep 2 18:15:53 1999 Andrew Cagney <cagney@b1.cygnus.com> * configure: Regenerated to track ../common/aclocal.m4 changes. |