diff options
author | David Taylor <taylor@redhat.com> | 1998-12-28 23:06:13 +0000 |
---|---|---|
committer | David Taylor <taylor@redhat.com> | 1998-12-28 23:06:13 +0000 |
commit | 4ef1f4677390c085543fe80eec41b0fe5d58ddca (patch) | |
tree | d0e8320e4871a81733155e8ce653507dd3d64825 /gdb | |
parent | d6fdf61c78fbce1dad62cd1022e606fdaaad4202 (diff) | |
download | gdb-4ef1f4677390c085543fe80eec41b0fe5d58ddca.zip gdb-4ef1f4677390c085543fe80eec41b0fe5d58ddca.tar.gz gdb-4ef1f4677390c085543fe80eec41b0fe5d58ddca.tar.bz2 |
hp merge changes -- too numerous to mention here; see ChangeLog and
ChangeLog-gdbtk for details.
Diffstat (limited to 'gdb')
68 files changed, 7667 insertions, 859 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 806c61c..ae56d92 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,859 @@ +Mon Dec 28 17:43:36 1998 David Taylor <taylor@texas.cygnus.com> + + The following changes were made by Jim Blandy <jimb@cygnus.com>, + Edith Epstein <eepstein@cygnus.com>, Elena Zannoni + <ezannoni@cygnus.com> Stan Shebs <shebs@cygnus.com>, and David + Taylor <taylor@cygnus.com>, as part of the project to merge in + changes originally made by HP; HP did not create ChangeLog + entries. + + * c-lang.h(cp_print_value_fields): update prototype; fixed + prototype decl for c_val_print funct -- it needed an + embedded_offset param; fixed prototype of cp_print_value_fields. + include value.h. + (C_LANG_H): define. + + * c-valprint.c (c_val_print): added new parameter embedded_offset. + Add embedded_offset to valaddr in function calls. fix calls to + val_print, and cp_print_value_fields. Attempt to determine the + real type of the object to be printed. fixed call to + cp_print_value_fields. process TYPE_CODE_METHOD as well. moved + call to check_typedef out of conditional. added embedded offset + param to val_print call + + (c_value_print): add new parameter to call to val_print. handle + pointer to class case. ensure that const char *, const unsigned + char * come out without the type but the volatile variants and the + signed variants don't. + + * ch-lang.h: HP merge, 4/15/98 snapshot + Added a parameter to the chill_val_print funct decl + + * ch-valprint.c: HP merge, 4/15/98 snapshot + The various print routines have an additional + parameter. Currently, the new parameter is only + used when printing C++ expressions. So, in + ch-valprint.c, the new parameter is always 0. + Changes in calls to : val_print, chill_val_print, c_val_print + Affected functions : chill_val_print_array_elements, + chill_val_print, chill_print_value_fields, + chill_value_print + + * cp-valprint.c added vtable pointers names for aCC (HP) compiler. + (cp_print_class_method): print message for HP/aCC case. + (cp_print_class_member): add comments. + (cp_print_value): adjust address computations for virtual base + classes. added new parameter 'offset'. Find correct offset for + base class in HP/aCC case. Change call to cp_print_value_fields + to have extra par. + (cp_print_value_fields): do not print also if the only field is + the vtable pointer. Print out vtable ptr, for HP/aCC compiled + case. do not print leading '=' in case of anonymous union, or + struct. added new parameter 'offset'. Do not print the vtable + pointer as a member, in the HP aCC case. Changed calls to + val_print to have extra parameter. + (cp_print_hpacc_virtual_table_entries): new function. Print vtable + entries, in HP/aCC compiled case. + (cp_print_static_field): change call to cp_print_value_fields, and + val_print. + + * d30v-tdep.c: + (d30v_print_register) : added embedded_offset param to val_print + call + + * defs.h: additional include files included when TUI is defined. + (gdb_file_isatty): new function decl. + (GDB_FILE): if TUI is defined, define a structure rather + than making this an alias for FILE. + (gdb_stdout, gdb_stderr): if TUI is defined, then define these + as pointers to variables of type GDB_FILE rather than making them + be aliases for stdout and stderr. + (TUIDO): add definition conditionalized on definition + (or lack thereof) of TUI. + (command_class): add two additional values. + (precision_type): new enum. + (gdb_fclose): add declaration. + (store_address): change prototype to match function. + (tui_version, xdb_commands, dbx_commands): add decl's. + (gdb_file_deallocate): new function declaration + (pa_do_strcat_registers_info): new function declaration. + (streamtype): new enumerated type to distinguish between output to + a FILE and output to a buffer. + (tui_stream): new struct type, named GDB_FILE. Contains, + streamtype, FILE, buffer, and bufferlength fields. + (gdb_stdout): of type GDB_FILE, will pass this around gdb rather + than stdout. + (gdb_stderr): of type GDB_FILE, will pass this around gdb rather + than stderr. + (fputs_unfiltered_hook): change stream parameter from FILE to + GDB_FILE + (flush_hook): change stream parameter from FILE to GDB_FILE + (gdb_fclose): Fix declaration for gdb_fclose; parameter is now of + type GDB_FILE ** + (gdb_file_adjust_strbuf): new function declaration. function lives + in utils.c. + (gdb_file_init_astring): new function declaration. function lives + in utils.c + (gdb_file_get_strbuf): new function declaration. function lives in + utils.c + (source_full_path_of): declare. + + * exec.c (_initialize_exec): make definition of file command be + dependent upon dbx_commands not being set. + (exec_file_attach): new function. + (exec_file_command): call it. + (exec_ops): added new fields to_has_syscall_event, + to_enable_exception_callback, to_get_current_exception_event + to_post_wait, to_post_startup_inferior + to_acknowledge_created_inferior, to_clone_and_follow_inferior, + to_post_follow_inferior_by_clone, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file + + * f-lang.h (f_print_type): change FILE to GDB_FILE in decl. + (f_val_print): ditto. + (f_val_print): added parameter to the funct decl. + + * f-valprint.c (_initialize_f_valprint): if xdb_commands is set, + define lc command. + + (f77_create_arrayprint_offset_tbl): change FILE to GDB_FILE. + (f77_print_array): ditto. + (f77_print_array_1): ditto. + (f_val_print): ditto. + + (f_val_print): Added a parameter; this new parameter is currently + only non-zero when handling C++ expressions. In this file its + value is always 0. changed fflush to gdb_flush. + + * gnu-nat.c: + (init_gnu_ops): added and initialized new target ops vector fields + to_require_attach, to_require_detach, to_post_wait, + to_post_startup_inferior, to_acknowledge_created_inferior, + to_clone_and_follow_inferior, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file + (gnu_create_inferior): add param to fork_inferior call + + * hppa-tdep.c (after_prologue): if f is NULL, don't dereference + it. if no debug info, return zero telling caller that we need to + find the end of the prologue via the hard way (instruction + examination). + + (find_unwind_entry): avoid dereferencing a null + pointer. + + (hppa_pid_to_exec_file): deleted -- no longer used. + + (hppa_prepare_to_proceeed): add prototype. + (read_unwind_info): purecov comments, bug fixes. + (find_unwind_entry): purecov comments, bug fixes. + (find_stub_with_shl_get): purecov comments. + (frame_chain): additional parens. + (hppa_push_arguments): changes to commented out version of routine. + (hppa_fix_call_dummy): purecov comments, fix location of end.o. + (in_solib_call_trampoline): purecov comments. + (in_solib_return_trampoline): purecov comments. + (setup_d_pid_in_inferior): fix location of end.o. + (initialize_hp_cxx_exception_support): fix location of end.o. + (child_enable_exception_callback): purecov comments. + + (pa_do_strcat_registers_info): Has a new parameter, precision, + which is passed into the call to pa_strcat_fp_reg to indicate + whether to display the floating point registers using + single or double preceision. + (pa_strcat_registers): Introduce local variable, precision, and + pass it into call to pa_strcat_fp_reg. + (pa_strcat_fp_reg): Modified function. New parameter, precision, + used by function to decide whether to use single or double + precision. Also added the code to put a double precision value + into a buffer. + + (pa_do_strcat_registers_info): new routine. called by + tui/tuiRegs.c:_tuiRegisterFormat to place a register name + and value into a string buffer. Interface may change in + future. Checking this in so that we have something + functional for HP. + (pa_strcat_registers): new routine, called by + pa_do_strcat_registers_info. Does same thing as + pa_print_registers except it takes a stream parameter. + This routine should disappear in future. Checking in + so that we have something functional to give HP + (pa_strcat_fp_reg): new routine, called by + pa_do_strcat_registers_info and pa_strvat_registers + to place a floating point register name and value into + a buffer. This interface may change in future. + Checking in so that we have something functional to give HP. + + (pa_print_fp_reg): change prototype to match def'n. + (pa_register_look_aside): fix comment immediately before function. + + changes to better support stack unwinding, reading and writing + registers for HPUX. New includes : ptrace.h, bfd.h, dl.h. + (internalize_unwinds): initialize new fields in table. + (read_unwind_info): entries in the table are now more complex + structures. References of the form ...->table[index].stub_type are + now ...->table[index].stub_unwind.stub_type. + (find_proc_framesize) : added a check for pc == 0. + (rp_saved): entries in the table are now more complex + structures. References of the form ...->table[index].stub_type are + now ...->table[index].stub_unwind.stub_type. + (frameless_function_invocation): stub_type becomes + stub_unwind.stub_type + (saved_pc_after_call): stub_type becomes stub_unwind.stub_type + (hppa_frame_saved_pc): stub_type becomes stub_unwind.stub_type + (frame_chain_valid): stub_type becomes stub_unwind.stub_type + (hppa_call_dummy): stub_type becomes stub_unwind.stub_type + (pa_print_fp_reg): additional params to call val_print + (in_solib_call_trampoline): stub_type becomes + stub_unwind.stub_type + (in_solib_return_trampoline): stub_type becomes + stub_unwind.stub_typ + (skip_trampoline_code): additional code to handle external + dyncalls. Also stub_type becomes stub_unwind.stub_type + (hppa_pid_to_exec_file): new funct. FOr HPUX 10.0 and beyond there + is an explicit ptrace request for getting the pathname associated + with a process id (pid). + + (hppa_pid_to_exec_file): remove unwanted param from call to + call_ptrace. + + (args_for_find_stub): new structure. + (find_unwind_entry): deal with null input pc value. + (rp_saved): ditto. + For the import stub, return -24 always. + (hppa_frame_saved_pc): save old pc value, to detect we are in a loop. + (init_extra_frame_info): use TARGET_READ_FP. + (frame_chain): include thread support. + If the caller's pc is zero, we loose and return, just like stack bottom. + Disable warning about being unable to find unwind info. + (hppa_push_arguments): rewrite. + (hppa_value_returned_from_stack): new function. Handles returning a value + larger that 64 bits, stored on the stack. + (find_stub_with_shl_get): new function. To look up symbols in shlibs. + (cover_find_stub_with_shl_get): new function. Cover routine for + find_stub_with_shl_get to pass to catch_errors. + (hppa_fix_call_dummy): comment out old stub mechanism. Rewrite using dyncall. + (target_read_fp): new function. + (pa_do_registers_info): floating point registers start at FP4. + (pa_print_registers): use FP4_REGNUM instead of 72. + (skip_trampoline_code): do machine instruction matching for PA2.0. + (setup_d_pid_in_inferior): new function. Exception handling support. + (initialize_hp_cxx_exception_support): ditto. + (child_enable_exception_callback): ditto. + (child_get_current_exception_event): ditto. + + * hpux-thread.c + (hpux_thread_ops): initializing new target ops vector fields. + to_require_attach, to_require_detach, to_post_wait, + to_post_startup_inferior, to_acknowledge_created_inferior, + to_clone_and_follow_inferior, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file. + + * infcmd.c + Include objfiles.h + (attach_command): new local variable, exec_file, added code to + determine exec_file from pid if exec_file is not already known, + call new target operation, target_post_attach -- a no-op unless + on HPUXHPPA + (detach_command): after detaching, do a SOLIB_RESTART + + (objfiles.h): fix typo on include line. + + (run_command): only call SOLIB_RESTART if it's defined. + (detach_command): ditto. + + (run_command): If program has already been started, and decide + to restart it, the kill the target, fluch the caches, + call init_wait_for_inferior. Also purge old solib objfiles. + + (run_stack_dummy): add calls to + disable_watchpoints_before_interactive_call_start and + enable_watchpoints_after_interactive_call_stops + (finish_command): alter code handling the evaluation and printing + of the target function's return value. + (attach_command): when given a pid, but no exec file, try to + determine the exec file from the process. If the process does not + record a full path name, try to qualify the filename against the + source path. + (_initialize_infcmd): add some verbiage about how to use the + attach command + + (do_registers_info): changed calls to val_print + + made the symfile.h include preceed the + objfiles.h include. The other ordering caused a + compile problem (incompletely defined types). + + * inftarg.c (child_post_attach): Fix declaration, make static. + (proc_wait): Make globally visible. + (child_insert_fork_catchpoint, etc): Fix return type. + + (child_detach_from_process): declare. + (child_attach_to_process): declare. + (child_stop): make static to match declaration. + + (ptrace_him): change prototype back to return int. + + (ptrace_me): Remove debug output, pass NULL to fork_inferior if + not HPUX. + + (child_require_attach): new funct prototype and definition + (child_require_detach): new funct prototype and definition + (proc_wait): funct prototype and definition are enclosed by + proc_wait ifndef + (child_attach_to_process): new function, does most of the work + that child_attach used to do and some additional work to determine + whether gdb is already attached to the target how to react. + (child_attach): altered. It's now a wrapper for + child_attach_to_process. + (child_require_attach): new function, called if should attach even + when gdb is already attached to target. + (child_detach_from_process): new function, does most of the work + that child_detach used to do and some additional work to determine + whether gdb is currently attached to the target. + (child_detach): altered. It's now a wrapper for + child_detach_from_process. + (child_require_detach): new function, called if should try to + detach even when gdb is not attached to target. + (ptrace_him): calls a new function, + target_acknowledge_forked_child. Currently, + target_acknowledge_forked_child, is only defined to do something + for HPUX. + (child_create_inferior): changed call to fork_inferior. + (child_ops): added to_require_attach and to_require_detach fields + to the child_ops target ops vector. + + Some hacks for ttrace work + (child_wait): Additional local variables, additional code in + while loop to check for : process exited, process forked, + process vforked, process execd + (child_thread_alive): John B. seems to think that the kill + call is inapproapriate for HPUX. + (child_attach_to_process): using strtol rather than atoi. + no longer check for case where there is no known exec file. + (child_post_attach): new function, a default, a no-op + (child_insert_fork_catchpoint): new function, a default, a no-op + (child_remove_fork_catchpoint): new function, a default, a no-op + (child_insert_vfork_catchpoint): new function, a default, a no-op + (child_remove_vfork_catchpoint): new function, a default, a no-op + (child_can_follow_vfork_prior_to_exec ):new function, a default, + a no-op + (child_insert_exec_catchpoint): new function, a default, a no-op + (child_remove_exec_catchpoint): new function, a default, a no-op + (child_has_execd): new function, a default, returns 0 + (child_reported_exec_events_per_exec_call): new function, a + default, returns 1 + (child_has_exited): new function, a default. + (child_core_file_to_sym_file): new function, a default, returns NULL. + (child_ops): initialize new target_ops vector fields to the + child* functions. + + * jv-lang.h: + (java_val_print): added embedded_offset param to func decl. + + * jv-valprint.c: changing calls to val_print to accomodate new param. + (java_value_print): add embedded_offset param to val_print call + (java_print_value_fields): add embedded_offset param to val_print + call + (java_val_print): add embedded_offset param. alter call to + c_val_print to accomodate embedded_offset param. + + * language.c (lang_bool_type): return builtin_type_bool in c++ + case. + (unk_lang_val_print): Added embedded_offset param to + prototype declaration and definition. + + * language.h: + (LA_VAL_PRINT macro, la_val_print function decl): altered to + accomodate the new parameter to the various print functions. + + * m2-lang.h: + (m2_val_print): added a parameter to the func decl. + + * m2-valprint.c: + (m2_val_print): added a parameter. + This parameter is currently only used when + evaluating C++ expressions. So, it is + always 0 in this file. + + * m3-nat.c: + (m3_create_inferior): add param to fork_inferior call + (m3_pid_to_exec_file): new function + (m3_ops): adding and initializing new target ops vector fields. + + * mac-nat.c: + (init_child_ops): adding and initializing new target ops vector + fields to_require_attach, to_require_detach, to_post_wait, + to_post_startup_inferior, to_acknowledge_created_inferior, + to_clone_and_follow_inferior, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file + + * mips-tdep.c: chnages to accomodate additional parameter + to val_print. + (mips_print_register): alter calls to val_print + + * monitor.c (monitor_write): change stderr to gdb_stderr. + (monitor_remove_breakpoint): ditto. + + * monitor.c: + (init_base_monitor_ops): adding and initializing new target ops + vector fields to_require_attach, to_require_detach, + to_post_wait, to_post_startup_inferior, + to_acknowledge_created_inferior, to_clone_and_follow_inferior, + to_create_catch_fork_hook, to_create_catch_vfork_hook, + to_has_forked, to_has_vforked, to_post_follow_vfork, + to_pid_to_exec_file + + * ppc-bdm.c: + (init_bdm_ppc_ops): adding and initializing new target ops vector + fields to_require_attach, to_require_detach, to_post_wait, + to_post_startup_inferior, to_acknowledge_created_inferior, + to_clone_and_follow_inferior, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file + + * printcmd.c + (do_examine): when saving a value_ptr, remove it from + the list of value_ptr's to be freed automatically; when discarding + a previously saved value_ptr, free it. + + (print_formatted): update comments; add new comments. + (printf_command, print_insn): purecov comments. + (_initialize_printcmd): add assign as a command if dbx_commands is + set; create va as an alias for disassemble if xdb_commands is set. + (address_info): new cases LOC_INDIRECT and + LOC_THREAD_LOCAL_STATIC. + (display_command): if tui_version and exp starts with a '$', then + don't display it unless tui_vSetLayoutTo fails. + (disassemble_command): add tuiDo calls. + + (print_scalar_formatted): for integers that are long long, check + the print format and print out in binary octal, decimal, or + hex. Call the new print_*_chars functions in valprint.c + + (print_frame_args): Altered calls to val_print, to reflect + additional parameter to val_print (case LOC_BASEREG_ARG). + + * procfs.c: + (procfs_init_inferior): return value is now a void. + (procfs_ops): adding and initializing new target_ops vector fields. + (procfs_create_inferior): fix call to fork_inferior -- need another + parameter. + + * remote-adapt.c + (adapt_open): change stderr to gdb_stderr. + (adpat_insert_breakpoint): ditto. + (init_adapt_ops): adding and initializing new target_ops vector fields. + + * remote-array.c + (array_wait): change fflush to gdb_flush and stdout to gdb_stdout. + (init_array_ops): adding new and initializing target_ops vector fields. + + * remote-bug.c + (bug_load): change fflush to gdb_flush; stdout to gdb_stdout. + (bug_wait): change stderr to gdb_stderr. + (bug_insert_breakpoint): ditto. + (init_bug_ops): adding and initializing new target_ops vector fields. + + * remote-e7000.c + (init_e7000_ops): adding and initializing new target_ops vector fields. + * remote-eb.c (init_eb_ops): ditto. + * remote-es.c (init_es1800_ops): ditto. + (init_es1800_child_ops): ditto. + * remote-es.c (init_es1800_ops): ditto. + (init_es1800_child_ops): ditto. + * remote-hms.c (init_hms_ops): ditto. + * remote-hms.c (init_hms_ops): ditto. + * remote-nindy.c (init_nindy_ops): ditto. + * remote-nrom.c (init_nrom_ops): ditto. + * remote-os9k.c (init_rombug_ops): ditto. + * remote-rdp.c (init_remote_rdp_ops): ditto. + * remote-sds.c (init_sds_ops): ditto. + * remote-sim.c (init_gdbsim_ops): ditto. + * remote-st.c (init_st2000_ops): ditto. + * remote-udi.c (init_udi_ops): ditto. + * remote-vx.c (init_vx_ops): ditto. + (init_vx_run_ops): ditto. + * remote-vx.c: (init_vx_ops): ditto. + (init_vx_run_ops): ditto. + * remote.c (init_remote_ops): ditto. + (init_extended_remote_ops): ditto. + + * remote-mips.c (mips_getstring): change stderr to gdb_stderr. + (pmon_insert_breakpoint): ditto. + (pmon_remove_breakpoint): ditto. + (check_lsi_error): ditto. + (common_breakpoint): ditto. + (pmon_makeb64): ditto. + + * remote-mips.c (mips_xfer_memory): change fflush to gdb_flush; + change stdout to gdb_stdout. + + * remote-mm.c + (mm_open): change stderr to gdb_stderr. + + (init_mm_ops): adding and initializing new target_ops vector fields. + + (mm_load): fixed params in commented out call to symbol_file_add. + + * remote-nindy.c (instream): change declaration to FILE. + + * remote-udi.c: + (udi_load): fixed params in call to symbol_file_add + + * remote-vx.c: + (vx_add_symbols): fixed params in call to symbol_file_add + + * remote.c (init_remote_ops): cosmetic change to match expected + test output. + + * rs6000-nat.c: + (add_vmap): added params to call to allocate_objfile. + + * scm-lang.h : HP merge, 4/15/98 snapshot + Added parameter to the scm_val_print func decl + + * scm-valprint.c + + * scm-valprint.c (scm_scmval_print): cast svalue to (int); new + parameter. This parameter is currently only used when evaluating + C++ expressions. So, it is always 0 in this file. + (c_val_print): fixed prototype decl; it needed an embedded_offset + param. + + * sol-thread.c: + (sol_core_ops): added and initialized new target_ops vector fields. + (sol_thread_ops): ditto. + + * somsolib.c (DLD_FLAGS_MAPPRIVATE): new macro. + Define bit of __dld_flags in HP-UX a.out files. + (DLD_FLAGS_HOOKVALID): ditto. + (DLD_FLAGS_LISTVALID): ditto. + (DLD_FLAGS_BOR_ENABLE): ditto. + (som_solib_total_st_size): cumulative size in bytes of the + symbol tables of all shared objects on the so_list_head list. + (som_solib_st_size_threshhold_exceeded): threshold for adding symbols + for shlibs. + (som_solib_sizeof_symbol_table): new function. Computes size of + symbol table for a shlib. + (som_solib_load_symbols): new function. Load symbols from shlib. + (som_solib_add): detect if __dld_list is not valid. + Record main program's symbol table size. + Load symbols if called from command line. + Keep threshold into account when loading shlib symbols. + (som_solib_create_inferior_hook): use dld_flags macros. + (som_sharedlibrary_info_command): let user know if symbols were + not loaded. + (som_solib_restart): discard all the shlibs descriptors. + (_initialize_som_solib): chenge help message for auto-solib-add + command. + Set threshold for symbol table to 50 megabytes. + + * somsolib.c (_initialize_som_solib): added call to som_solib_restart. + (som_solib_restart): new function + (som_solib_in_dynamic_linker): new function + (som_solib_desire_dynamic_linker_symbols): new function + (som_solib_unloaded_library_pathname): new function + (som_solib_loaded_library_pathname): new function + (som_solib_library_pathname): new function + (som_solib_have_unload_event): new function + (som_solib_have_load_event): new function + (som_solib_create_catch_unload_hook): new function + (som_solib_create_catch_load_hook): new function + (som_solib_create_inferior_hook): rewritten + dld_cache: new struct + addr_and_unwind_t: new struct + (find_unwind_entry) added prototype + + * somsolib.c (som_solib_create_inferior_hook): introduce new local + msymbol2 and change some msymbol's to msymbol2's -- was clobbering + msymbol, passing a NULL to lookup_minimal_symbol_solib_trampoline, + and ultimately core dumping with a SEGV. + + * somsolib.c: + Include assert.h + (som_solib_mapped_entry): additional comments for text_addr, + text_link_addr, text_end, and tsd_start_addr fields. Commenting + out 2 tsd fields, __data_start and __data_end. + (som_solib_add_solib_objfile): add params to calls to symbol_file_add. + Add some code for distinguishing between a shared library and other + objfiles. This appears to be a prelude to thread local storage. + (som_solib_load_symbols): changes to printf statement + enclosed by SOLIB_DEBUG ifdef. + (som_solib_add): change comment to correctly specify path + to end.o -- /opt/langtools/lib/end.o. changes to printf statement + enclosed by SOLIB_DEBUG ifdef. + Removed several SOLIB_DEBUG ifdefs and the associated printfs. + Add code to find the start address for the object file's thread + local storage + (som_solib_create_inferior_hook): Fix warning messages use correct + path to end.o -- /opt/langtools/lib/end.o. Change control flow. + No longer user early returns from function is cases of error. + (reset_inferior_pid): new function + (som_solib_remove_inferior_hook): new function + (so_lib_thread_start_addr): new function. used for tsd. + + * somsolib.c: Removed references to ASSERT macro. + + * somsolib.c: add debugging macro. + (struct som_solib_mapped_entry): add new field tsd_start_addr. + (struct so_list): added new field solib_addr. + (som_solib_add_solib_objfile): new function. + (som_solib_load_symbols): rewritten. + (som_solib_add): make sure we don't load the symbols in if the + threshold was exceeded. + (som_solib_get_solib_by_pc): new function. Return the address of + handle of the shared library. + (som_solib_restart): disable breakpoints at restart. + (_initialize_som_solib): set threshold to 100 megabytes. + + * somsolib.c: add include of fcntl.h so that O_RDONLY is defined. + + * sparcl-tdep.c: + (init_sparclite_ops): added and initialized new target_ops vector fields. + + * target.c (cleanup_target): Changed casting of default functions + for to_has_forked, to_has_vforked, to_pid_to_exec_file to get rid + of warnings. Fixed PARAMS for to_has_syscall_event. Fixed the + return type on a few of the default function values. + + (cleanup_target): changes in the de_fault macro, both to + accomodate the new target_ops vector fields and to use + more accurate default functions. + + * target.c (debug_to_open): change stderr to gdb_stderr. + (debug_to_close): ditto. + (debug_to_attach): ditto. + (debug_to_post_attach): ditto. + (debug_to_require_attach): ditto. + (debug_to_detach): ditto. + (debug_to_require_detach): ditto. + (debug_to_resume): ditto. + (debug_to_wait): ditto. + (debug_to_post_wait): ditto. + (debug_to_fetch_registers): ditto. + (debug_to_store_registers): ditto. + (debug_to_prepare_to_store): ditto. + (debug_to_xfer_memory): ditto. + (debug_to_files_info): ditto. + (debug_to_insert_breakpoint): ditto. + (debug_to_remove_breakpoint): ditto. + (debug_to_terminal_init): ditto. + (debug_to_terminal_inferior): ditto. + (debug_to_terminal_ours_for_output): ditto. + (debug_to_terminal_ours): ditto. + (debug_to_terminal_info): ditto. + (debug_to_kill): ditto. + (debug_to_load): ditto. + (debug_to_lookup_symbol): ditto. + (debug_to_create_inferior): ditto. + (debug_to_post_startup_inferior): ditto. + (debug_to_acknowledge_created_inferior): ditto. + (debug_to_clone_and_follow_inferior): ditto. + (debug_to_post_follow_inferior_by_clone): ditto. + (debug_to_insert_fork_catchpoint): ditto. + (debug_to_remove_fork_catchpoint): ditto. + (debug_to_insert_vfork_catchpoint): ditto. + (debug_to_remove_vfork_catchpoint): ditto. + (debug_to_has_forked): ditto. + (debug_to_has_vforked): ditto. + (debug_to_can_follow_vfork_prior_to_exec): ditto. + (debug_to_post_follow_vfork): ditto. + (debug_to_insert_exec_catchpoint): ditto. + (debug_to_remove_exec_catchpoint): ditto. + (debug_to_has_execd): ditto. + (debug_to_reported_exec_events_per_exec_call): ditto. + (debug_to_has_syscall_event): ditto. + (debug_to_has_exited): ditto. + (debug_to_mourn_inferior): ditto. + (debug_to_can_run): ditto. + (debug_to_notice_signals): ditto. + (debug_to_thread_alive): ditto. + (debug_to_stop): ditto. + (debug_to_enable_exception_callback): ditto. + (debug_to_get_current_exception_event): ditto. + (debug_to_pid_to_exec_file): ditto. + (debug_to_core_file_to_sym_file): ditto. + + * target.c: + (default_clone_and_follow_inferior): new function prototype + declaration and function definition. + + (dummy_target): Add new target_ops vector fields and their + initializations. More target_ops vector changes for HPUX new + fields. New fields are to_post_wait, to_post_startup_inferior + to_acknowledge_created_inferior, to_clone_and_follow_inferior, + to_post_follow_inferior_by_clone, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file. + + (de_fault): add new HPUX specific target_ops operations to the + de_fault macro + + (INHERIT): added new HPUX specific target_ops operations. + + (debug_to_post_wait): new funct + (debug_to_post_startup_inferior): new funct + (debug_to_acknowledge_created_inferior): new funct + (debug_to_clone_and_follow_inferior): new funct + (debug_to_post_follow_inferior_by_clone): new funct + (debug_to_create_catch_fork_hook): new funct + (debug_to_create_catch_vfork_hook): new funct + (debug_to_has_forked): new funct + (debug_to_has_vforked): new funct + (debug_to_post_follow_vfork): new funct + (setup_target_debug): initialize new target_ops vector fields. + + * target.c: + (nosupport_runtime): new function, used in cleanup_target + + (update_current_target): Added new new target_ops vector fields to + the INHERIT macro definition. + + (generic_mourn_inferior): the call to breakpoint_init_inferior now takes a + parameter + + (normal_pid_to_str): Adding a \0 to the end of buf. + + (debug_to_has_syscall_event): new func + (debug_to_enable_exception_callback): new func + (debug_to_get_current_exception_event): new func + (setup_target_debug): initialize the 3 new target_ops vector fields + + * target.c: + (struct signals): fix message associated with SIGRETRACT. + + * target.c: + (return_one): new function, used by the de_fault macro + (debug_to_post_attach): new function + (debug_to_wait): added new cases : TARGET_WAITKIND_FORKED, + TARGET_WAITKIND_VFORKED, TARGET_WAITKIND_EXECD. + (debug_to_insert_fork_catchpoint): new function + (debug_to_remove_fork_catchpoint): new function + (debug_to_insert_vfork_catchpoint): new function + (debug_to_remove_vfork_catchpoint): new function + (debug_to_can_follow_vfork_prior_to_exec): new function + (debug_to_insert_exec_catchpoint): new function + (debug_to_remove_exec_catchpoint): new function + (debug_to_core_file_to_sym_file): new function + (setup_target_debug): give new fields in current_target target_ops + vector values. + + * target.h: + Include symtab.h + (target_waitkind): new enumerated values : + TARGET_WAITKIND_SYSCALL_ENTRY and TARGET_WAITKIND_SYSCALL_RETURN + (target_waitstatus): add a syscall_id field to structure + (child_has_syscall_event): new decl + (child_thread_alive): new decl + (target_ops): added 3 new fields: to_has_syscall_event, + to_enable_exception_callback, to_get_current_exception_event + (target_enable_exception_callback): new macro + (target_has_syscall_event): new macro + (target_get_current_exception_event): new macro + (TARGET_DISABLE_HW_WATCHPOINTS): new macro + (TARGET_ENABLE_HW_WATCHPOINTS): new macro + (PC_REQUIRES_RUN_BEFORE_USE): new macro + (target_tid_to_str): new macro + + * target.h: + (target_waitkind): new entries in enumerated type : + TARGET_WAITKIND_FORKED, TARGET_WAITKIND_VFORKED, + TARGET_WAITKIND_EXECD + (target_waitstatus): additional fields in struct to keep track + of child pid and pathname to execd file + (target_ops): add in the new target_ops function pointer fields. + New macros to go along with new target_ops fields. + New function decls : child_core_file_to_sym_file, + child_post_attach, child_insert_fork_catchpoint, + child_remove_fork_catchpoint, child_insert_vfork_catchpoint, + child_remove_vfork_catchpoint, child_can_follow_vfork_prior_to_exec, + child_insert_exec_catchpoint, child_remove_exec_catchpoint, + child_has_execd, child_has_exited + + * target.h: + In target_waitstatus.value, change name of child_pid field to + related_pid. + (target_pid_or_tid_to_str): define default macro + Added missing #endif after PC_REQUIRES_RUN_BEFORE_USE definition + (ENSURE_VFORKING_PARENT_REMAINS_STOPPED): define default macro + (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK): define default macro + + * target.h: HP merge, 4/15/98 snapshot + There are new function declarations for to_require_attach + and to_require_detach. There are also new macros, + target_require_attach and target_require_detach. There are + also new function declarations for find_default_require_detach + and find_default_require_attach. All these changes are ifdef'ed + for HPUX_SNAP1. + + * target.h: changes for HPUX specific target_ops vector fields + (target_ops): new fields + to_post_wait, to_post_startup_inferior + to_acknowledge_created_inferior, to_clone_and_follow_inferior, + to_post_follow_inferior_by_clone, to_create_catch_fork_hook, + to_create_catch_vfork_hook, to_has_forked, to_has_vforked, + to_post_follow_vfork, to_pid_to_exec_file + Function prototype definitions for new target_ops operations + New function definitions : child_pid_to_exec_file, child_post_wait, + child_post_startup_inferior, child_acknowledge_created_inferior, + child_clone_and_follow_inferior, + child_post_follow_inferior_by_clone, child_create_catch_fork_hook, + child_create_catch_vfork_hook, child_has_forked, child_has_vforked, + child_acknowledge_created_inferior, child_post_follow_vfork, + New macros : target_post_startup_inferior, + target_acknowledge_created_inferior, + target_clone_and_follow_inferior, + target_post_follow_inferior_by_clone, + target_create_catch_fork_hook, + target_create_catch_vfork_hook, + target_pid_to_exec_file + (find_default_clone_and_follow_inferior): new funct prototype + + * target.h: remove HPUX_SNAP1 and HPUX_SNAP2 ifdefs + + * txvu-tdep.c: + (txvu_print_register): added embedded_offset param to val_print + call. + + * v850ice.c: + (init_850ice_ops): adding and initializing new target_ops vector + fields : to_post_attach, to_post_follow_inferior_by_clone, + to_insert_fork_catchpoint, to_remove_fork_catchpoint, + to_insert_vfork_catchpoint, to_remove_vfork_catchpoint, + to_can_follow_vfork_prior_to_exec, to_insert_exec_catchpoint, + to_remove_exec_catchpoint, to_has_execd, + to_reported_exec_events_per_exec_call, to_has_exited, + to_core_file_to_sym_file + + * valprint.c (print_binary_chars): print out long long as + a binary number + (print_octal_chars): print out long long as an octal number + (print_decimal_chars): print out long long as a decimal number + + * valprint.c (strcat_longest): define it (from Stan Shebs). + + * valprint.c: HP merge, 4/15/98 snapshot + Added parameter to val_print. This is used for + evaluating C++ expressions. + + * value.h (VALUE_POINTED_TO_OFFSET): new macro. + Add field pointed_to_offset to value structure. + Add prototypes for new functions in valops.c. + + * value.h (write_register_pid): change prototype to match + function. + (val_print func decl): Additional parameter. + (VALUE_EMBEDDED_OFFSET): New macro. + (find_rt_vbase_offset): New func decl -- for C++ support. + + * win32-nat.c (child_ops): Remove unneeded settings. + (handle_load_dll): added params to call to symbol_file_add. + (init_child_ops): adding new target_ops vector fields and removing + a few. initializing new target ops vector fields. Wed Dec 23 15:03:42 1998 Per Bothner <bothner@cygnus.com> * Makefile.in (READLINE_CFLAGS): Search $(READLINE_SRC)/.. rather diff --git a/gdb/ChangeLog-gdbtk b/gdb/ChangeLog-gdbtk index 6f8e2df..9bf9121 100644 --- a/gdb/ChangeLog-gdbtk +++ b/gdb/ChangeLog-gdbtk @@ -1,3 +1,26 @@ +Mon Dec 28 17:44:36 1998 David Taylor <taylor@texas.cygnus.com> + + + The following changes were made by Jim Blandy <jimb@cygnus.com>, + Edith Epstein <eepstein@cygnus.com>, Elena Zannoni + <ezannoni@cygnus.com> Stan Shebs <shebs@cygnus.com>, and David + Taylor <taylor@cygnus.com>, as part of the project to merge in + changes originally made by HP; HP did not create ChangeLog + entries. + + * gdbtk.c (gdbtk_init): change stderr to gdb_stderr. + + * gdbtk-cmds.c + (get_pc_register): Use paddr_nz, not sprintf's %llx and + a cast to `long long'. Those aren't portable. + (gdb_eval): add embedded_offset param to val_print call + (get_register): add embedded_offset param to val_print call + + * gdbtk-hooks.c + (tk_command_loop): change instream to a FILE. + (gdbtk_flush): change both the declaration and definition to + use GDB_FILE rather than FILE. + Mon Dec 21 11:11:02 1998 Keith Seitz <keiths@cygnus.com> * gdbtk-cmds.c (get_register): Call get_saved_register instead of diff --git a/gdb/c-lang.h b/gdb/c-lang.h index b9536f5..28486fd 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -17,9 +17,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifdef __STDC__ /* Forward decls for prototypes */ -struct value; -#endif + +#if !defined (C_LANG_H) +#define C_LANG_H 1 + +#include "value.h" + extern int c_parse PARAMS ((void)); /* Defined in c-exp.y */ @@ -31,7 +34,7 @@ extern void /* Defined in c-typeprint.c */ c_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); extern int -c_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, +c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); extern int @@ -70,7 +73,7 @@ extern void cp_print_class_method PARAMS ((char *, struct type *, GDB_FILE *)); extern void -cp_print_value_fields PARAMS ((struct type *, char *, CORE_ADDR, +cp_print_value_fields PARAMS ((struct type *, struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, enum val_prettyprint, struct type**, int)); @@ -79,3 +82,6 @@ cp_is_vtbl_ptr_type PARAMS ((struct type *)); extern int cp_is_vtbl_member PARAMS ((struct type *)); + + +#endif /* !defined (C_LANG_H) */ diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 583b78a..a95f44d 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -43,10 +43,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ The PRETTY parameter controls prettyprinting. */ int -c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, +c_val_print (type, valaddr, embedded_offset, address, stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -65,9 +66,9 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: + elttype = check_typedef (TYPE_TARGET_TYPE (type)); if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) { - elttype = check_typedef (TYPE_TARGET_TYPE (type)); eltlen = TYPE_LENGTH (elttype); len = TYPE_LENGTH (type) / eltlen; if (prettyprint_arrays) @@ -89,13 +90,13 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, /* Look for a NULL char. */ for (temp_len = 0; - valaddr[temp_len] + (valaddr + embedded_offset)[temp_len] && temp_len < len && temp_len < print_max; temp_len++); len = temp_len; } - LA_PRINT_STRING (stream, valaddr, len, eltlen, 0); + LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 0); i = len; } else @@ -112,7 +113,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, { i = 0; } - val_print_array_elements (type, valaddr, address, stream, + val_print_array_elements (type, valaddr + embedded_offset, address, stream, format, deref_ref, recurse, pretty, i); fprintf_filtered (stream, "}"); } @@ -125,7 +126,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, case TYPE_CODE_PTR: if (format && format != 's') { - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); break; } if (vtblprint && cp_is_vtbl_ptr_type(type)) @@ -133,24 +134,24 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, /* Print the unmangled name if desired. */ /* Print vtable entry - we only get here if we ARE using -fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */ - print_address_demangle(extract_address (valaddr, TYPE_LENGTH (type)), + print_address_demangle(extract_address (valaddr + embedded_offset, TYPE_LENGTH (type)), stream, demangle); break; } elttype = check_typedef (TYPE_TARGET_TYPE (type)); if (TYPE_CODE (elttype) == TYPE_CODE_METHOD) { - cp_print_class_method (valaddr, type, stream); + cp_print_class_method (valaddr + embedded_offset, type, stream); } else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER) { - cp_print_class_member (valaddr, + cp_print_class_member (valaddr + embedded_offset, TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), stream, "&"); } else { - addr = unpack_pointer (type, valaddr); + addr = unpack_pointer (type, valaddr + embedded_offset); print_unpacked_pointer: elttype = check_typedef (TYPE_TARGET_TYPE (type)); @@ -181,7 +182,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, else if (cp_is_vtbl_member(type)) { /* print vtbl's nicely */ - CORE_ADDR vt_address = unpack_pointer (type, valaddr); + CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset); struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (vt_address); @@ -214,7 +215,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, wtype = TYPE_TARGET_TYPE(type); } vt_val = value_at (wtype, vt_address, NULL); - val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), + val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), 0, VALUE_ADDRESS (vt_val), stream, format, deref_ref, recurse + 1, pretty); if (pretty) @@ -240,7 +241,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, elttype = check_typedef (TYPE_TARGET_TYPE (type)); if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER) { - cp_print_class_member (valaddr, + cp_print_class_member (valaddr + embedded_offset, TYPE_DOMAIN_TYPE (elttype), stream, ""); break; @@ -249,7 +250,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, { fprintf_filtered (stream, "@"); print_address_numeric - (extract_address (valaddr, + (extract_address (valaddr + embedded_offset, TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream); if (deref_ref) fputs_filtered (": ", stream); @@ -263,12 +264,17 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, value_at (TYPE_TARGET_TYPE (type), unpack_pointer (lookup_pointer_type (builtin_type_void), - valaddr), + valaddr + embedded_offset), NULL); val_print (VALUE_TYPE (deref_val), - VALUE_CONTENTS (deref_val), - VALUE_ADDRESS (deref_val), stream, format, - deref_ref, recurse + 1, pretty); + VALUE_CONTENTS (deref_val), + 0, + VALUE_ADDRESS (deref_val), + stream, + format, + deref_ref, + recurse, + pretty); } else fputs_filtered ("???", stream); @@ -289,23 +295,24 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, /* Print vtable entry - we only get here if NOT using -fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */ print_address_demangle (extract_address ( - valaddr + TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8, + valaddr + embedded_offset + + TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8, TYPE_LENGTH (TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET))), stream, demangle); } else - cp_print_value_fields (type, valaddr, address, stream, format, + cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream, format, recurse, pretty, NULL, 0); break; case TYPE_CODE_ENUM: if (format) { - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); break; } len = TYPE_NFIELDS (type); - val = unpack_long (type, valaddr); + val = unpack_long (type, valaddr + embedded_offset); for (i = 0; i < len; i++) { QUIT; @@ -327,7 +334,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, case TYPE_CODE_FUNC: if (format) { - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); break; } /* FIXME, we should consider, at least for ANSI C language, eliminating @@ -342,10 +349,10 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, case TYPE_CODE_BOOL: format = format ? format : output_format; if (format) - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); else { - val = unpack_long (type, valaddr); + val = unpack_long (type, valaddr + embedded_offset); if (val == 0) fputs_filtered ("false", stream); else if (val == 1) @@ -369,11 +376,11 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, format = format ? format : output_format; if (format) { - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); } else { - val_print_type_code_int (type, valaddr, stream); + val_print_type_code_int (type, valaddr + embedded_offset, stream); /* C and C++ has no single byte int type, char is used instead. Since we don't know whether the value is really intended to be used as an integer or a character, print the character @@ -381,7 +388,7 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, if (TYPE_LENGTH (type) == 1) { fputs_filtered (" ", stream); - LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), stream); } } @@ -391,28 +398,32 @@ c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, format = format ? format : output_format; if (format) { - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); } else { fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d", - unpack_long (type, valaddr)); + unpack_long (type, valaddr + embedded_offset)); fputs_filtered (" ", stream); - LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), stream); + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), stream); } break; case TYPE_CODE_FLT: if (format) { - print_scalar_formatted (valaddr, type, format, 0, stream); + print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream); } else { - print_floating (valaddr, type, stream); + print_floating (valaddr + embedded_offset, type, stream); } break; + case TYPE_CODE_METHOD: + cp_print_class_method (valaddr + embedded_offset, lookup_pointer_type (type), stream); + break; + case TYPE_CODE_VOID: fprintf_filtered (stream, "void"); break; @@ -443,7 +454,9 @@ c_value_print (val, stream, format, pretty) enum val_prettyprint pretty; { struct type *type = VALUE_TYPE (val); - + struct type * real_type; + int full, top, using_enc; + /* If it is a pointer, indicate what it points to. Print type also if it is a reference. @@ -455,6 +468,9 @@ c_value_print (val, stream, format, pretty) { /* Hack: remove (char *) for char strings. Their type is indicated by the quoted string anyway. */ + /* Hack^2: ensure that const char *, const unsigned char * + come out without the type but the volatile variants + and the signed variants don't. */ if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_NAME (type) == NULL && TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL && @@ -462,14 +478,61 @@ c_value_print (val, stream, format, pretty) { /* Print nothing */ } + else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS)) + { + /* Pointer to class, check real type of object */ + fprintf_filtered (stream, "("); + type = value_rtti_target_type (val, &full, &top, &using_enc); + if (type) + { + /* RTTI entry found */ + type = lookup_pointer_type (type); + type_print (type, "", stream, -1); + } + else + { + /* No RTTI fields, do whatever we can */ + type = VALUE_ENCLOSING_TYPE (val); + type_print (type, "", stream, -1); + fprintf_filtered (stream, " ?"); + } + fprintf_filtered (stream, ") "); + } else { + /* normal case */ fprintf_filtered (stream, "("); type_print (type, "", stream, -1); fprintf_filtered (stream, ") "); } } - return val_print (type, VALUE_CONTENTS (val), - VALUE_ADDRESS (val) + VALUE_OFFSET (val), + if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS)) + { + /* Attempt to determine real type of object */ + real_type = value_rtti_type (val, &full, &top, &using_enc); + if (real_type) + { + /* We have RTTI information, so use it */ + val = value_full_object (val, real_type, full, top, using_enc); + fprintf_filtered (stream, "(%s%s) ", + TYPE_NAME (real_type), + full ? "" : " [incomplete object]"); + /* Print out object: enclosing type is same as real_type if full */ + return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0, + VALUE_ADDRESS (val), stream, format, 1, 0, pretty); + } + else if (type != VALUE_ENCLOSING_TYPE (val)) + { + /* No RTTI information, so let's do our best */ + fprintf_filtered (stream, "(%s ?) ", + TYPE_NAME (VALUE_ENCLOSING_TYPE (val))); + return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0, + VALUE_ADDRESS (val), stream, format, 1, 0, pretty); + } + /* Otherwise, we end up at the return outside this "if" */ + } + + return val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val), + VALUE_ADDRESS (val), stream, format, 1, 0, pretty); } diff --git a/gdb/ch-lang.h b/gdb/ch-lang.h index 699ab15..6525c30 100644 --- a/gdb/ch-lang.h +++ b/gdb/ch-lang.h @@ -31,7 +31,7 @@ extern void /* Defined in ch-typeprint.c */ chill_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); extern int -chill_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, +chill_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); extern int diff --git a/gdb/ch-valprint.c b/gdb/ch-valprint.c index 9c67d09..663ba64 100644 --- a/gdb/ch-valprint.c +++ b/gdb/ch-valprint.c @@ -161,7 +161,7 @@ chill_val_print_array_elements (type, valaddr, address, stream, chill_print_type_scalar (index_type, low_bound + i + reps - 1, stream); fputs_filtered ("): ", stream); - val_print (elttype, valaddr + i * eltlen, 0, stream, format, + val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format, deref_ref, recurse + 1, pretty); i = rep1 - 1; @@ -170,7 +170,7 @@ chill_val_print_array_elements (type, valaddr, address, stream, else { fputs_filtered ("): ", stream); - val_print (elttype, valaddr + i * eltlen, 0, stream, format, + val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format, deref_ref, recurse + 1, pretty); annotate_elt (); things_printed++; @@ -197,10 +197,11 @@ chill_val_print_array_elements (type, valaddr, address, stream, The PRETTY parameter controls prettyprinting. */ int -chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, - pretty) +chill_val_print (type, valaddr, embedded_offset, address, + stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -466,6 +467,7 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, NULL); val_print (VALUE_TYPE (deref_val), VALUE_CONTENTS (deref_val), + 0, VALUE_ADDRESS (deref_val), stream, format, deref_ref, recurse + 1, pretty); } @@ -475,13 +477,13 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, break; case TYPE_CODE_ENUM: - c_val_print (type, valaddr, address, stream, format, + c_val_print (type, valaddr, 0, address, stream, format, deref_ref, recurse, pretty); break; case TYPE_CODE_RANGE: if (TYPE_TARGET_TYPE (type)) - chill_val_print (TYPE_TARGET_TYPE (type), valaddr, address, stream, + chill_val_print (TYPE_TARGET_TYPE (type), valaddr, 0, address, stream, format, deref_ref, recurse, pretty); break; @@ -493,7 +495,7 @@ chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, default: /* Let's defer printing to the C printer, rather than print an error message. FIXME! */ - c_val_print (type, valaddr, address, stream, format, + c_val_print (type, valaddr, 0, address, stream, format, deref_ref, recurse, pretty); } gdb_flush (stream); @@ -562,13 +564,13 @@ chill_print_value_fields (type, valaddr, stream, format, recurse, pretty, v = value_from_longest (TYPE_FIELD_TYPE (type, i), unpack_field_as_long (type, valaddr, i)); - chill_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, + chill_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, 0, stream, format, 0, recurse + 1, pretty); } else { chill_val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, + valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0, 0, stream, format, 0, recurse + 1, pretty); } } @@ -615,13 +617,13 @@ chill_value_print (val, stream, format, pretty) fprintf_filtered (stream, ")"); } fprintf_filtered (stream, "("); - i = val_print (type, valaddr, VALUE_ADDRESS (val), + i = val_print (type, valaddr, 0, VALUE_ADDRESS (val), stream, format, 1, 0, pretty); fprintf_filtered (stream, ")"); return i; } } - return (val_print (type, VALUE_CONTENTS (val), + return (val_print (type, VALUE_CONTENTS (val), 0, VALUE_ADDRESS (val), stream, format, 1, 0, pretty)); } diff --git a/gdb/corefile.c b/gdb/corefile.c index 7f66ec1..8ffe49d 100644 --- a/gdb/corefile.c +++ b/gdb/corefile.c @@ -325,6 +325,37 @@ read_memory_unsigned_integer (memaddr, len) read_memory (memaddr, buf, len); return extract_unsigned_integer (buf, len); } + +void +read_memory_string (memaddr, buffer, max_len) + CORE_ADDR memaddr; + char * buffer; + int max_len; +{ + register char * cp; + register int i; + int cnt; + + cp = buffer; + while (1) + { + if (cp - buffer >= max_len) + { + buffer[max_len - 1] = '\0'; + break; + } + cnt = max_len - (cp - buffer); + if (cnt > 8) + cnt = 8; + read_memory (memaddr + (int) (cp - buffer), cp, cnt); + for (i = 0; i < cnt && *cp; i++, cp++) + ; /* null body */ + + if (i < cnt && !*cp) + break; + } +} + #if 0 /* Enable after 4.12. It is not tested. */ diff --git a/gdb/corelow.c b/gdb/corelow.c index 831b4b2..2ab0034 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <errno.h> #include <signal.h> #include <fcntl.h> +#include <unistd.h> #include "frame.h" /* required by inferior.h */ #include "inferior.h" #include "symtab.h" @@ -56,6 +57,8 @@ static void add_to_thread_list PARAMS ((bfd *, asection *, PTR)); static int ignore PARAMS ((CORE_ADDR, char *)); +static char * core_file_to_sym_file PARAMS ((char *)); + void _initialize_corelow PARAMS ((void)); /* Link a new core_fns into the global core_file_fns list. Called on gdb @@ -358,6 +361,69 @@ cant: registers_fetched (); } +static char * +core_file_to_sym_file (core) + char * core; +{ + CONST char * failing_command; + char * p; + char * temp; + bfd * temp_bfd; + int scratch_chan; + + if (! core) + error ("No core file specified."); + + core = tilde_expand (core); + if (core[0] != '/') + { + temp = concat (current_directory, "/", core, NULL); + core = temp; + } + + scratch_chan = open (core, write_files ? O_RDWR : O_RDONLY, 0); + if (scratch_chan < 0) + perror_with_name (core); + + temp_bfd = bfd_fdopenr (core, gnutarget, scratch_chan); + if (temp_bfd == NULL) + perror_with_name (core); + + if (!bfd_check_format (temp_bfd, bfd_core)) + { + /* Do it after the err msg */ + /* FIXME: should be checking for errors from bfd_close (for one thing, + on error it does not free all the storage associated with the + bfd). */ + make_cleanup (bfd_close, temp_bfd); + error ("\"%s\" is not a core dump: %s", + core, bfd_errmsg (bfd_get_error ())); + } + + /* Find the data section */ + if (build_section_table (temp_bfd, &core_ops.to_sections, + &core_ops.to_sections_end)) + error ("\"%s\": Can't find sections: %s", + bfd_get_filename (temp_bfd), bfd_errmsg (bfd_get_error ())); + + failing_command = bfd_core_file_failing_command (temp_bfd); + + bfd_close (temp_bfd); + + /* If we found a filename, remember that it is probably saved + relative to the executable that created it. If working directory + isn't there now, we may not be able to find the executable. Rather + than trying to be sauve about finding it, just check if the file + exists where we are now. If not, then punt and tell our client + we couldn't find the sym file. + */ + p = (char *) failing_command; + if ((p != NULL) && (access (p, F_OK) != 0)) + p = NULL; + + return p; +} + static void core_files_info (t) struct target_ops *t; @@ -376,6 +442,21 @@ ignore (addr, contents) return 0; } + +/* Okay, let's be honest: threads gleaned from a core file aren't + exactly lively, are they? On the other hand, if we don't claim + that each & every one is alive, then we don't get any of them + to appear in an "info thread" command, which is quite a useful + behaviour. + */ +static int +core_file_thread_alive (tid) + int tid; +{ + return 1; +} + + struct target_ops core_ops = { "core", /* to_shortname */ "Local core dump file", /* to_longname */ @@ -383,9 +464,13 @@ struct target_ops core_ops = { core_open, /* to_open */ core_close, /* to_close */ find_default_attach, /* to_attach */ + NULL, /* to_post_attach */ + find_default_require_attach, /* to_require_attach */ core_detach, /* to_detach */ + find_default_require_detach, /* to_require_detach */ 0, /* to_resume */ 0, /* to_wait */ + NULL, /* to_post_wait */ get_core_registers, /* to_fetch_registers */ 0, /* to_store_registers */ 0, /* to_prepare_to_store */ @@ -402,11 +487,33 @@ struct target_ops core_ops = { 0, /* to_load */ 0, /* to_lookup_symbol */ find_default_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + find_default_clone_and_follow_inferior, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ 0, /* to_mourn_inferior */ 0, /* to_can_run */ 0, /* to_notice_signals */ - 0, /* to_thread_alive */ + core_file_thread_alive, /* to_thread_alive */ 0, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + core_file_to_sym_file, /* to_core_file_to_sym_file */ core_stratum, /* to_stratum */ 0, /* to_next */ 0, /* to_has_all_memory */ diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index f4edef8..eeeb79e 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -32,6 +32,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "c-lang.h" #include "target.h" +/* Indication of presence of HP-compiled object files */ +extern int hp_som_som_object_present; /* defined in symtab.c */ + + int vtblprint; /* Controls printing of vtbl's */ int objectprint; /* Controls looking up an object's derived type using what we find in its vtables. */ @@ -45,9 +49,14 @@ cp_print_static_field PARAMS ((struct type *, value_ptr, GDB_FILE *, int, int, enum val_prettyprint)); static void -cp_print_value PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, +cp_print_value PARAMS ((struct type *, struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, enum val_prettyprint, struct type **)); +static void +cp_print_hpacc_virtual_table_entries PARAMS ((struct type *, int *, value_ptr, GDB_FILE *, + int, int, enum val_prettyprint)); + + void cp_print_class_method (valaddr, type, stream) char *valaddr; @@ -100,6 +109,12 @@ cp_print_class_method (valaddr, type, stream) sym = find_pc_function (addr); if (sym == 0) { + /* 1997-08-01 Currently unsupported with HP aCC */ + if (hp_som_som_object_present) + { + fputs_filtered ("?? <not supported with HP aCC>", stream); + return; + } error ("invalid pointer to member function"); } len = TYPE_NFN_FIELDS (domain); @@ -153,6 +168,13 @@ static const char vtbl_ptr_name_old[] = const char vtbl_ptr_name[] = { '_','_','v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; +/* HP aCC uses different names */ +const char hpacc_vtbl_ptr_name[] = + { '_', '_', 'v', 'f', 'p', 0 }; +const char hpacc_vtbl_ptr_type_name[] = + { '_', '_', 'v', 'f', 't', 'y', 'p', 0 }; + + /* Return truth value for assertion that TYPE is of the type "pointer to virtual function". */ @@ -198,14 +220,19 @@ cp_is_vtbl_member(type) TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and PRETTY have the same meanings as in cp_print_value and c_val_print. + 2nd argument REAL_TYPE is used to carry over the type of the derived + class across the recursion to base classes. + DONT_PRINT is an array of baseclass types that we should not print, or zero if called from top level. */ void -cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, +cp_print_value_fields (type, real_type, valaddr, offset, address, stream, format, recurse, pretty, dont_print_vb, dont_print_statmem) struct type *type; + struct type *real_type; char *valaddr; + int offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -217,6 +244,7 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, int i, len, n_baseclasses; struct obstack tmp_obstack; char *last_dont_print = obstack_next_free (&dont_print_statmem_obstack); + int fields_seen = 0; CHECK_TYPEDEF (type); @@ -224,18 +252,26 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, len = TYPE_NFIELDS (type); n_baseclasses = TYPE_N_BASECLASSES (type); - /* Print out baseclasses such that we don't print + /* First, print out baseclasses such that we don't print duplicates of virtual baseclasses. */ + if (n_baseclasses > 0) - cp_print_value (type, valaddr, address, stream, + cp_print_value (type, real_type, valaddr, offset, address, stream, format, recurse+1, pretty, dont_print_vb); - if (!len && n_baseclasses == 1) + /* Second, print out data fields */ + + /* If there are no data fields, or if the only field is the + * vtbl pointer, skip this part */ + if ((len == n_baseclasses) || + ((len - n_baseclasses == 1) && + TYPE_HAS_VTABLE(type) && + STREQN(TYPE_FIELD_NAME (type, n_baseclasses), hpacc_vtbl_ptr_name, 5)) || + !len) fprintf_filtered (stream, "<No data fields>"); else { extern int inspect_it; - int fields_seen = 0; if (dont_print_statmem == 0) { @@ -251,6 +287,11 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, /* If requested, skip printing of static fields. */ if (!static_field_print && TYPE_FIELD_STATIC (type, i)) continue; + + /* If a vtable pointer appears, we'll print it out later */ + if (TYPE_HAS_VTABLE(type) && STREQN(TYPE_FIELD_NAME (type, i), hpacc_vtbl_ptr_name, 5)) + continue; + if (fields_seen) fprintf_filtered (stream, ", "); else if (n_baseclasses > 0) @@ -302,7 +343,9 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, language_cplus, DMGL_PARAMS | DMGL_ANSI); annotate_field_name_end (); - fputs_filtered (" = ", stream); + /* do not print leading '=' in case of anonymous unions */ + if (strcmp (TYPE_FIELD_NAME (type, i), "")) + fputs_filtered (" = ", stream); annotate_field_value (); } @@ -319,9 +362,9 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, else { v = value_from_longest (TYPE_FIELD_TYPE (type, i), - unpack_field_as_long (type, valaddr, i)); + unpack_field_as_long (type, valaddr + offset, i)); - val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0, + val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0, 0, stream, format, 0, recurse + 1, pretty); } } @@ -344,7 +387,7 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, else { val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, + valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8, address + TYPE_FIELD_BITPOS (type, i) / 8, stream, format, 0, recurse + 1, pretty); } @@ -365,7 +408,81 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, fprintf_filtered (stream, "\n"); print_spaces_filtered (2 * recurse, stream); } - } + } /* if there are data fields */ + /* Now print out the virtual table pointer if there is one */ + if (TYPE_HAS_VTABLE(type) && STREQN(TYPE_FIELD_NAME (type, n_baseclasses), hpacc_vtbl_ptr_name, 5)) + { + value_ptr v; + /* First get the virtual table pointer and print it out*/ + +#if 0 + fputs_filtered ("__vfp = ", stream); +#endif + + fputs_filtered (", Virtual table at ", stream); + + /* pai: FIXME 32x64 problem? */ + /* Not sure what the best notation is in the case where there is no + baseclass name. */ + v = value_from_longest (lookup_pointer_type (builtin_type_unsigned_long), + * (unsigned long *) (valaddr + offset)); + + val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, 0, + stream, format, 0, recurse + 1, pretty); + fields_seen = 1; + + if (vtblprint) + { + /* Print out function pointers in vtable. */ + + /* FIXME: then-clause is for non-RRBC layout of virtual + * table. The RRBC case in the else-clause is yet to be + * implemented. The if (1) below should be changed to a + * test for whether the executable we have was compiled + * with a version of HP aCC that doesn't have RRBC + * support. */ + + if (1) + { + /* no RRBC support; function pointers embedded directly in vtable */ + + int vfuncs = count_virtual_fns (real_type); + + fputs_filtered (" {", stream); + + /* FIXME : doesn't work at present */ +#if 0 + fprintf_filtered (stream, "%d entr%s: ", vfuncs, vfuncs == 1 ? "y" : "ies"); +#else + fputs_filtered ("not implemented", stream); + + +#endif + + /* recursive function that prints all virtual function entries */ +#if 0 + cp_print_hpacc_virtual_table_entries (real_type, &vfuncs, v, stream, format, recurse, pretty); +#endif + fputs_filtered ("}", stream); + } /* non-RRBC case */ + else + { + /* FIXME -- seem comments above */ + /* RRBC support present; function pointers are found + * by indirection through the class segment entries. */ + + + } /* RRBC case */ + } /* if vtblprint */ + + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 * recurse, stream); + } + + } /* if vtable exists */ + fprintf_filtered (stream, "}"); } @@ -373,10 +490,12 @@ cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty, baseclasses. */ static void -cp_print_value (type, valaddr, address, stream, format, recurse, pretty, +cp_print_value (type, real_type, valaddr, offset, address, stream, format, recurse, pretty, dont_print_vb) struct type *type; + struct type *real_type; char *valaddr; + int offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -402,6 +521,7 @@ cp_print_value (type, valaddr, address, stream, format, recurse, pretty, for (i = 0; i < n_baseclasses; i++) { int boffset; + int skip; struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); char *basename = TYPE_NAME (baseclass); char *base_valaddr; @@ -421,8 +541,41 @@ cp_print_value (type, valaddr, address, stream, format, recurse, pretty, obstack_ptr_grow (&dont_print_vb_obstack, baseclass); } - boffset = baseclass_offset (type, i , valaddr, address); + if (TYPE_HAS_VTABLE (type) && BASETYPE_VIA_VIRTUAL (type, i)) + { + /* Assume HP/Taligent runtime convention */ + find_rt_vbase_offset (type, TYPE_BASECLASS (type, i), + valaddr, offset, &boffset, &skip); + if (skip >= 0) + error ("Virtual base class offset not found from vtable while printing"); + base_valaddr = valaddr; + } + else + { + boffset = baseclass_offset (type, i , valaddr + offset, address + offset); + skip = ((boffset == -1) || (boffset+offset) < 0 ) ? 1 : -1; + + if (BASETYPE_VIA_VIRTUAL (type, i)) + { + /* The virtual base class pointer might have been clobbered by the + user program. Make sure that it still points to a valid memory + location. */ + + if (boffset != -1 && ((boffset+offset) < 0 || (boffset+offset) >= TYPE_LENGTH (type))) + { + base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass)); + if (target_read_memory (address + boffset, base_valaddr, + TYPE_LENGTH (baseclass)) != 0) + skip = 1; + } + else + base_valaddr = valaddr; + } + else + base_valaddr = valaddr; + } + /* now do the printing */ if (pretty) { fprintf_filtered (stream, "\n"); @@ -434,24 +587,11 @@ cp_print_value (type, valaddr, address, stream, format, recurse, pretty, fputs_filtered (basename ? basename : "", stream); fputs_filtered ("> = ", stream); - /* The virtual base class pointer might have been clobbered by the - user program. Make sure that it still points to a valid memory - location. */ - if (boffset != -1 && (boffset < 0 || boffset >= TYPE_LENGTH (type))) - { - base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass)); - if (target_read_memory (address + boffset, base_valaddr, - TYPE_LENGTH (baseclass)) != 0) - boffset = -1; - } - else - base_valaddr = valaddr + boffset; - - if (boffset == -1) + if (skip >= 1) fprintf_filtered (stream, "<invalid address>"); else - cp_print_value_fields (baseclass, base_valaddr, address + boffset, + cp_print_value_fields (baseclass, real_type, base_valaddr, offset + boffset, address, stream, format, recurse, pretty, (struct type **) obstack_base (&dont_print_vb_obstack), 0); @@ -514,11 +654,11 @@ cp_print_static_field (type, val, stream, format, recurse, pretty) sizeof (CORE_ADDR)); CHECK_TYPEDEF (type); - cp_print_value_fields (type, VALUE_CONTENTS (val), VALUE_ADDRESS (val), + cp_print_value_fields (type, type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val), stream, format, recurse, pretty, NULL, 1); return; } - val_print (type, VALUE_CONTENTS (val), VALUE_ADDRESS (val), + val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val), VALUE_ADDRESS (val), stream, format, 0, recurse, pretty); } @@ -537,7 +677,16 @@ cp_print_class_member (valaddr, domain, stream, prefix) int bits = 0; register unsigned int i; unsigned len = TYPE_NFIELDS (domain); + /* @@ Make VAL into bit offset */ + + /* Note: HP aCC generates offsets that are the real byte offsets added + to a constant bias 0x20000000 (1 << 29). This constant bias gets + shifted out in the code below -- joyous happenstance! */ + + /* Note: HP cfront uses a constant bias of 1; if we support this + compiler ever, we will have to adjust the computation below */ + LONGEST val = unpack_long (builtin_type_int, valaddr) << 3; for (i = TYPE_N_BASECLASSES (domain); i < len; i++) { @@ -577,6 +726,72 @@ cp_print_class_member (valaddr, domain, stream, prefix) fprintf_filtered (stream, "%d", val >> 3); } + +/* This function prints out virtual table entries for a class; it + * recurses on the base classes to find all virtual functions + * available in a class. + * + * pai/1997-05-21 Note: As the name suggests, it's currently + * implemented for HP aCC runtime only. g++ objects are handled + * differently and I have made no attempt to fold that logic in + * here. The runtime layout is different for the two cases. Also, + * this currently has only the code for non-RRBC layouts generated by + * the HP aCC compiler; RRBC code is stubbed out and will have to be + * added later. */ + + +static void +cp_print_hpacc_virtual_table_entries (type, vfuncs, v, stream, format, recurse, pretty) + struct type * type; + int * vfuncs; + value_ptr v; + GDB_FILE *stream; + int format; + int recurse; + enum val_prettyprint pretty; +{ + int fn, oi; + + /* pai: FIXME this function doesn't work. It should handle a given + * virtual function only once (latest redefinition in class hierarchy) + */ + + /* Recursion on other classes that can share the same vtable */ + struct type * pbc = primary_base_class (type); + if (pbc) + cp_print_hpacc_virtual_table_entries (pbc, vfuncs, v, stream, format, recurse, pretty); + + /* Now deal with vfuncs declared in this class */ + for (fn = 0; fn < TYPE_NFN_FIELDS (type); fn++) + for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (type, fn); oi++) + if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (type, fn), oi)) + { + char * vf_name; + + /* virtual function offset */ + int vx = TYPE_FN_FIELD_VOFFSET (TYPE_FN_FIELDLIST1 (type, fn), oi) - 1; + + /* Get the address of the vfunction entry */ + value_ptr vf = value_copy (v); + if (VALUE_LAZY (vf)) + (void) value_fetch_lazy (vf); + vf->aligner.contents[0] += 4 * (HP_ACC_VFUNC_START + vx); /* adjust by offset */ + vf = value_ind (vf); /* get the entry */ + VALUE_TYPE (vf) = VALUE_TYPE (v); /* make it a pointer */ + + /* print out the entry */ + val_print (VALUE_TYPE (vf), VALUE_CONTENTS (vf), 0, 0, + stream, format, 0, recurse + 1, pretty); + vf_name = cplus_demangle (TYPE_FN_FIELD_PHYSNAME (TYPE_FN_FIELDLIST1 (type, fn), oi), + DMGL_ARM); /* pai: (temp) FIXME Maybe this should be DMGL_ANSI */ + fprintf_filtered (stream, " %s", vf_name); + if (--(*vfuncs) > 0) + fputs_filtered (", ", stream); + } +} + + + void _initialize_cp_valprint () { diff --git a/gdb/d30v-tdep.c b/gdb/d30v-tdep.c index 588e1de..ec46463 100644 --- a/gdb/d30v-tdep.c +++ b/gdb/d30v-tdep.c @@ -737,13 +737,13 @@ d30v_print_register (regnum, tabular) read_relative_register_raw_bytes (regnum, regbuf); - val_print (REGISTER_VIRTUAL_TYPE (regnum), regbuf, 0, + val_print (REGISTER_VIRTUAL_TYPE (regnum), regbuf, 0, 0, gdb_stdout, 'x', 1, 0, Val_pretty_default); if (!tabular) { printf_filtered (" "); - val_print (REGISTER_VIRTUAL_TYPE (regnum), regbuf, 0, + val_print (REGISTER_VIRTUAL_TYPE (regnum), regbuf, 0, 0, gdb_stdout, 'd', 1, 0, Val_pretty_default); } } @@ -94,6 +94,12 @@ typedef bfd_vma CORE_ADDR; /* Check if a character is one of the commonly used C++ marker characters. */ extern int is_cplus_marker PARAMS ((int)); +/* enable xdb commands if set */ +extern int xdb_commands; + +/* enable dbx commands if set */ +extern int dbx_commands; + extern int quit_flag; extern int immediate_quit; extern int sevenbit_strings; @@ -126,7 +132,7 @@ enum command_class no_class = -1, class_run = 0, class_vars, class_stack, class_files, class_support, class_info, class_breakpoint, class_trace, class_alias, class_obscure, class_user, class_maintenance, - class_pseudo + class_pseudo, class_tui, class_xdb }; /* Languages represented in the symbol table and elsewhere. @@ -1,5 +1,5 @@ /* Work with executable files, for GDB. - Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1997 + Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc. This file is part of GDB. @@ -76,10 +76,11 @@ int write_files = 0; /* Text start and end addresses (KLUDGE) if needed */ -#ifdef NEED_TEXT_START_END +#ifndef NEED_TEXT_START_END +#define NEED_TEXT_START_END (0) +#endif CORE_ADDR text_start = 0; CORE_ADDR text_end = 0; -#endif struct vmap *vmap; @@ -146,20 +147,29 @@ exec_close (quitting) /* Process the first arg in ARGS as the new exec file. - Note that we have to explicitly ignore additional args, since we can - be called from file_command(), which also calls symbol_file_command() - which can take multiple args. */ + This function is intended to be behave essentially the same + as exec_file_command, except that the latter will detect when + a target is being debugged, and will ask the user whether it + should be shut down first. (If the answer is "no", then the + new file is ignored.) + + This file is used by exec_file_command, to do the work of opening + and processing the exec file after any prompting has happened. + + And, it is used by child_attach, when the attach command was + given a pid but not a exec pathname, and the attach command could + figure out the pathname from the pid. (In this case, we shouldn't + ask the user whether the current target should be shut down -- + we're supplying the exec pathname late for good reason.) */ void -exec_file_command (args, from_tty) +exec_file_attach (args, from_tty) char *args; int from_tty; { char **argv; char *filename; - target_preopen (from_tty); - /* Remove any previous exec file. */ unpush_target (&exec_ops); @@ -177,7 +187,7 @@ exec_file_command (args, from_tty) if (argv == NULL) nomem (0); - make_cleanup (freeargv, (char *) argv); + make_cleanup ((make_cleanup_func) freeargv, (char *) argv); for (; (*argv != NULL) && (**argv == '-'); argv++) {;} if (*argv == NULL) @@ -248,38 +258,34 @@ exec_file_command (args, from_tty) scratch_pathname, bfd_errmsg (bfd_get_error ())); } -#ifdef NEED_TEXT_START_END - /* text_end is sometimes used for where to put call dummies. A few ports use these for other purposes too. */ - - { - struct section_table *p; - - /* Set text_start to the lowest address of the start of any - readonly code section and set text_end to the highest - address of the end of any readonly code section. */ - /* FIXME: The comment above does not match the code. The code - checks for sections with are either code *or* readonly. */ - - text_start = ~(CORE_ADDR)0; - text_end = (CORE_ADDR)0; - for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) - if (bfd_get_section_flags (p->bfd, p->the_bfd_section) - & (SEC_CODE | SEC_READONLY)) - { - if (text_start > p->addr) - text_start = p->addr; - if (text_end < p->endaddr) - text_end = p->endaddr; - } - } -#endif + if (NEED_TEXT_START_END) + { + struct section_table *p; + + /* Set text_start to the lowest address of the start of any + readonly code section and set text_end to the highest + address of the end of any readonly code section. */ + /* FIXME: The comment above does not match the code. The + code checks for sections with are either code *or* + readonly. */ + text_start = ~(CORE_ADDR)0; + text_end = (CORE_ADDR)0; + for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) + if (bfd_get_section_flags (p->bfd, p->the_bfd_section) + & (SEC_CODE | SEC_READONLY)) + { + if (text_start > p->addr) + text_start = p->addr; + if (text_end < p->endaddr) + text_end = p->endaddr; + } + } validate_files (); - set_endian_from_file (exec_bfd); - set_architecture_from_file (exec_bfd); + set_gdbarch_from_file (exec_bfd); push_target (&exec_ops); @@ -291,6 +297,25 @@ exec_file_command (args, from_tty) printf_unfiltered ("No executable file now.\n"); } +/* Process the first arg in ARGS as the new exec file. + + Note that we have to explicitly ignore additional args, since we can + be called from file_command(), which also calls symbol_file_command() + which can take multiple args. */ + +void +exec_file_command (args, from_tty) + char *args; + int from_tty; +{ + char **argv; + char *filename; + + target_preopen (from_tty); + + exec_file_attach (args, from_tty); +} + /* Set both the exec file and the symbol file, in one command. What a novelty. Why did GDB go through four major releases before this command was added? */ @@ -671,9 +696,13 @@ Specify the filename of the executable file.", /* to_doc */ exec_file_command, /* to_open */ exec_close, /* to_close */ find_default_attach, /* to_attach */ + NULL, /* to_post_attach */ + find_default_require_attach, /* to_require_attach */ 0, /* to_detach */ + find_default_require_detach, /* to_require_detach */ 0, /* to_resume */ 0, /* to_wait */ + NULL, /* to_post_wait */ 0, /* to_fetch_registers */ 0, /* to_store_registers */ 0, /* to_prepare_to_store */ @@ -690,11 +719,33 @@ Specify the filename of the executable file.", /* to_doc */ 0, /* to_load */ 0, /* to_lookup_symbol */ find_default_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + find_default_clone_and_follow_inferior, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ 0, /* to_mourn_inferior */ 0, /* to_can_run */ 0, /* to_notice_signals */ 0, /* to_thread_alive */ 0, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ file_stratum, /* to_stratum */ 0, /* to_next */ 0, /* to_has_all_memory */ @@ -712,14 +763,17 @@ _initialize_exec() { struct cmd_list_element *c; - c = add_cmd ("file", class_files, file_command, - "Use FILE as program to be debugged.\n\ + if (!dbx_commands) + { + c = add_cmd ("file", class_files, file_command, + "Use FILE as program to be debugged.\n\ It is read for its symbols, for getting the contents of pure memory,\n\ and it is the program executed when you use the `run' command.\n\ If FILE cannot be found as specified, your execution directory path\n\ ($PATH) is searched for a command of that name.\n\ No arg means to have no executable file and no symbols.", &cmdlist); - c->completer = filename_completer; + c->completer = filename_completer; + } c = add_cmd ("exec-file", class_files, exec_file_command, "Use FILE as program for getting contents of pure memory.\n\ diff --git a/gdb/f-lang.h b/gdb/f-lang.h index 226b399..c6b8f02 100644 --- a/gdb/f-lang.h +++ b/gdb/f-lang.h @@ -23,9 +23,11 @@ extern int f_parse PARAMS ((void)); extern void f_error PARAMS ((char *)); /* Defined in f-exp.y */ -extern void f_print_type PARAMS ((struct type *, char *, FILE *, int, int)); +extern void f_print_type PARAMS ((struct type *, char *, + GDB_FILE *, int, int)); -extern int f_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, +extern int f_val_print PARAMS ((struct type *, char *, int, + CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); /* Language-specific data structures */ diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c index d629d8b..23331b1 100644 --- a/gdb/f-valprint.c +++ b/gdb/f-valprint.c @@ -40,12 +40,13 @@ static int there_is_a_visible_common_named PARAMS ((char *)); static void info_common_command PARAMS ((char *, int)); static void list_all_visible_commons PARAMS ((char *)); static void f77_print_array PARAMS ((struct type *, char *, CORE_ADDR, - FILE *, int, int, int, + GDB_FILE *, int, int, int, enum val_prettyprint)); static void f77_print_array_1 PARAMS ((int, int, struct type *, char *, - CORE_ADDR, FILE *, int, int, int, + CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); -static void f77_create_arrayprint_offset_tbl PARAMS ((struct type *, FILE *)); +static void f77_create_arrayprint_offset_tbl PARAMS ((struct type *, + GDB_FILE *)); static void f77_get_dynamic_length_of_aggregate PARAMS ((struct type *)); int f77_array_offset_tbl[MAX_FORTRAN_DIMS+1][2]; @@ -231,7 +232,7 @@ f77_get_dynamic_length_of_aggregate (type) static void f77_create_arrayprint_offset_tbl (type, stream) struct type *type; - FILE *stream; + GDB_FILE *stream; { struct type *tmp_type; int eltlen; @@ -285,7 +286,7 @@ f77_print_array_1 (nss, ndimensions, type, valaddr, address, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -311,6 +312,7 @@ f77_print_array_1 (nss, ndimensions, type, valaddr, address, { val_print (TYPE_TARGET_TYPE (type), valaddr + i * F77_DIM_OFFSET (ndimensions), + 0, address + i * F77_DIM_OFFSET (ndimensions), stream, format, deref_ref, recurse, pretty); @@ -332,7 +334,7 @@ f77_print_array (type, valaddr, address, stream, format, deref_ref, recurse, struct type *type; char *valaddr; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -371,12 +373,13 @@ f77_print_array (type, valaddr, address, stream, format, deref_ref, recurse, The PRETTY parameter controls prettyprinting. */ int -f_val_print (type, valaddr, address, stream, format, deref_ref, recurse, +f_val_print (type, valaddr, embedded_offset, address, stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; - FILE *stream; + GDB_FILE *stream; int format; int deref_ref; int recurse; @@ -534,7 +537,7 @@ f_val_print (type, valaddr, address, stream, format, deref_ref, recurse, { /* Bash the type code temporarily. */ TYPE_CODE (type) = TYPE_CODE_INT; - f_val_print (type, valaddr, address, stream, format, + f_val_print (type, valaddr, 0, address, stream, format, deref_ref, recurse, pretty); /* Restore the type code so later uses work as intended. */ TYPE_CODE (type) = TYPE_CODE_BOOL; @@ -568,7 +571,7 @@ f_val_print (type, valaddr, address, stream, format, deref_ref, recurse, default: error ("Invalid F77 type code %d in symbol table.", TYPE_CODE (type)); } - fflush (stream); + gdb_flush (stream); return 0; } @@ -758,4 +761,7 @@ _initialize_f_valprint () { add_info ("common", info_common_command, "Print out the values contained in a Fortran COMMON block."); + if (xdb_commands) + add_com("lc", class_info, info_common_command, + "Print out the values contained in a Fortran COMMON block."); } diff --git a/gdb/gdbtk-cmds.c b/gdb/gdbtk-cmds.c index 5ce63b1..0019974 100644 --- a/gdb/gdbtk-cmds.c +++ b/gdb/gdbtk-cmds.c @@ -647,7 +647,8 @@ gdb_eval (clientData, interp, objc, objv) * the Tcl result. */ - val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), VALUE_ADDRESS (val), + val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), + VALUE_EMBEDDED_OFFSET(val), VALUE_ADDRESS (val), gdb_stdout, 0, 0, 0, 0); do_cleanups (old_chain); @@ -1694,7 +1695,7 @@ get_register (regnum, fp) } } else - val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, + val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0, 0, gdb_stdout, format, 1, 0, Val_pretty_default); } @@ -3394,7 +3395,7 @@ get_frame_name (interp, list, fi) print_address_numeric (fi->pc, 1, gdb_stdout); printf_filtered (" in "); } - printf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang, + fprintf_symbol_filtered (gdb_stdout, funname ? funname : "??", funlang, DMGL_ANSI); #endif objv[0] = Tcl_NewStringObj (funname != NULL ? funname : "??", -1); diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 8d3f320..c7cabba 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "value.h" #include "demangle.h" #include "complaints.h" +#include "gdbcmd.h" /* These variables point to the objects representing the predefined C data types. */ @@ -61,11 +62,15 @@ struct type *builtin_type_int32; struct type *builtin_type_uint32; struct type *builtin_type_int64; struct type *builtin_type_uint64; +struct type *builtin_type_bool; /* start-sanitize-r5900 */ struct type *builtin_type_int128; struct type *builtin_type_uint128; /* end-sanitize-r5900 */ +int opaque_type_resolution = 1; + + struct extra { char str[128]; int len; }; /* maximum extention is 128! FIXME */ static void add_name PARAMS ((struct extra *, char *)); @@ -107,6 +112,7 @@ alloc_type (objfile) TYPE_CODE (type) = TYPE_CODE_UNDEF; TYPE_OBJFILE (type) = objfile; TYPE_VPTR_FIELDNO (type) = -1; + TYPE_CV_TYPE (type) = type; /* chain back to itself */ return (type); } @@ -288,6 +294,89 @@ lookup_function_type (type) return make_function_type (type, (struct type **)0); } + +/* Make a "c-v" variant of a type -- a type that is identical to the + one supplied except that it may have const or volatile attributes + CNST is a flag for setting the const attribute + VOLTL is a flag for setting the volatile attribute + TYPE is the base type whose variant we are creating. + TYPEPTR, if nonzero, points + to a pointer to memory where the reference type should be stored. + If *TYPEPTR is zero, update it to point to the reference type we return. + We allocate new memory if needed. */ + +struct type * +make_cv_type (cnst, voltl, type, typeptr) + int cnst; + int voltl; + struct type *type; + struct type **typeptr; +{ + register struct type *ntype; /* New type */ + register struct type *tmp_type = type; /* tmp type */ + struct objfile *objfile; + + ntype = TYPE_CV_TYPE (type); + + while (ntype != type) + { + if ((TYPE_CONST (ntype) == cnst) && + (TYPE_VOLATILE (ntype) == voltl)) + { + if (typeptr == 0) + return ntype; + else if (*typeptr == 0) + { + *typeptr = ntype; /* Tracking alloc, and we have new type. */ + return ntype; + } + } + tmp_type = ntype; + ntype = TYPE_CV_TYPE (ntype); + } + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { + ntype = alloc_type (TYPE_OBJFILE (type)); + if (typeptr) + *typeptr = ntype; + } + else /* We have storage, but need to reset it. */ + { + ntype = *typeptr; + objfile = TYPE_OBJFILE (ntype); + /* memset ((char *) ntype, 0, sizeof (struct type)); */ + TYPE_OBJFILE (ntype) = objfile; + } + + /* Copy original type */ + memcpy ((char *) ntype, (char *) type, sizeof (struct type)); + /* But zero out fields that shouldn't be copied */ + TYPE_POINTER_TYPE (ntype) = (struct type *) 0; /* Need new pointer kind */ + TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0; /* Need new referene kind */ + /* Note: TYPE_TARGET_TYPE can be left as is */ + + /* Set flags appropriately */ + if (cnst) + TYPE_FLAGS (ntype) |= TYPE_FLAG_CONST; + else + TYPE_FLAGS (ntype) &= ~TYPE_FLAG_CONST; + + if (voltl) + TYPE_FLAGS (ntype) |= TYPE_FLAG_VOLATILE; + else + TYPE_FLAGS (ntype) &= ~TYPE_FLAG_VOLATILE; + + /* Fix the chain of cv variants */ + TYPE_CV_TYPE (ntype) = type; + TYPE_CV_TYPE (tmp_type) = ntype; + + return ntype; +} + + + + /* Implement direct support for MEMBER_TYPE in GNU C++. May need to construct such a type if this is the first use. The TYPE is the type of the member. The DOMAIN is the type @@ -719,21 +808,31 @@ lookup_union (name, block) struct block *block; { register struct symbol *sym; + struct type * t; sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0, (struct symtab **) NULL); if (sym == NULL) - { - error ("No union type named %s.", name); - } - if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION) - { - error ("This context has class, struct or enum %s, not a union.", name); - } - return (SYMBOL_TYPE (sym)); + error ("No union type named %s.", name); + + t = SYMBOL_TYPE(sym); + + if (TYPE_CODE (t) == TYPE_CODE_UNION) + return (t); + + /* C++ unions may come out with TYPE_CODE_CLASS, but we look at + * a further "declared_type" field to discover it is really a union. + */ + if (HAVE_CPLUS_STRUCT (t)) + if (TYPE_DECLARED_TYPE(t) == DECLARED_TYPE_UNION) + return (t); + + /* If we get here, it's not a union */ + error ("This context has class, struct or enum %s, not a union.", name); } + /* Lookup an enum type named "enum NAME", visible in lexical block BLOCK. */ @@ -990,7 +1089,28 @@ check_typedef (type) type = TYPE_TARGET_TYPE (type); } - if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab) + /* If this is a struct/class/union with no fields, then check whether a + full definition exists somewhere else. This is for systems where a + type definition with no fields is issued for such types, instead of + identifying them as stub types in the first place */ + + if (TYPE_IS_OPAQUE (type) && opaque_type_resolution && !currently_reading_symtab) + { + char * name = type_name_no_tag (type); + struct type * newtype; + if (name == NULL) + { + complain (&stub_noname_complaint); + return type; + } + newtype = lookup_transparent_type (name); + if (newtype) + { + memcpy ((char *) type, (char *) newtype, sizeof (struct type)); + } + } + /* Otherwise, rely on the stub flag being set for opaque/stubbed types */ + else if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab) { char* name = type_name_no_tag (type); /* FIXME: shouldn't we separately check the TYPE_NAME and the @@ -1003,13 +1123,10 @@ check_typedef (type) complain (&stub_noname_complaint); return type; } - sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, - (struct symtab **) NULL); + sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, (struct symtab **) NULL); if (sym) { - memcpy ((char *)type, - (char *)SYMBOL_TYPE(sym), - sizeof (struct type)); + memcpy ((char *)type, (char *)SYMBOL_TYPE(sym), sizeof (struct type)); } } @@ -1498,6 +1615,787 @@ chill_varying_type (type) return 1; } +/* Check whether BASE is an ancestor or base class or DCLASS + Return 1 if so, and 0 if not. + Note: callers may want to check for identity of the types before + calling this function -- identical types are considered to satisfy + the ancestor relationship even if they're identical */ + +int +is_ancestor (base, dclass) + struct type * base; + struct type * dclass; +{ + int i; + + CHECK_TYPEDEF (base); + CHECK_TYPEDEF (dclass); + + if (base == dclass) + return 1; + + for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++) + if (is_ancestor (base, TYPE_BASECLASS (dclass, i))) + return 1; + + return 0; +} + + + +/* See whether DCLASS has a virtual table. This routine is aimed at + the HP/Taligent ANSI C++ runtime model, and may not work with other + runtime models. Return 1 => Yes, 0 => No. */ + +int +has_vtable (dclass) + struct type * dclass; +{ + /* In the HP ANSI C++ runtime model, a class has a vtable only if it + has virtual functions or virtual bases. */ + + register int i; + + if (TYPE_CODE(dclass) != TYPE_CODE_CLASS) + return 0; + + /* First check for the presence of virtual bases */ + if (TYPE_FIELD_VIRTUAL_BITS(dclass)) + for (i=0; i < TYPE_N_BASECLASSES(dclass); i++) + if (B_TST(TYPE_FIELD_VIRTUAL_BITS(dclass), i)) + return 1; + + /* Next check for virtual functions */ + if (TYPE_FN_FIELDLISTS(dclass)) + for (i=0; i < TYPE_NFN_FIELDS(dclass); i++) + if (TYPE_FN_FIELD_VIRTUAL_P(TYPE_FN_FIELDLIST1(dclass, i), 0)) + return 1; + + /* Recurse on non-virtual bases to see if any of them needs a vtable */ + if (TYPE_FIELD_VIRTUAL_BITS(dclass)) + for (i=0; i < TYPE_N_BASECLASSES(dclass); i++) + if ((!B_TST (TYPE_FIELD_VIRTUAL_BITS(dclass), i)) && + (has_vtable (TYPE_FIELD_TYPE(dclass, i)))) + return 1; + + /* Well, maybe we don't need a virtual table */ + return 0; +} + +/* Return a pointer to the "primary base class" of DCLASS. + + A NULL return indicates that DCLASS has no primary base, or that it + couldn't be found (insufficient information). + + This routine is aimed at the HP/Taligent ANSI C++ runtime model, + and may not work with other runtime models. */ + +struct type * +primary_base_class (dclass) + struct type * dclass; +{ + /* In HP ANSI C++'s runtime model, a "primary base class" of a class + is the first directly inherited, non-virtual base class that + requires a virtual table */ + + register int i; + + if (TYPE_CODE(dclass) != TYPE_CODE_CLASS) + return NULL; + + for (i=0; i < TYPE_N_BASECLASSES(dclass); i++) + if (!TYPE_FIELD_VIRTUAL(dclass, i) && + has_vtable(TYPE_FIELD_TYPE(dclass, i))) + return TYPE_FIELD_TYPE(dclass, i); + + return NULL; +} + +/* Global manipulated by virtual_base_list[_aux]() */ + +static struct vbase * current_vbase_list = NULL; + +/* Return a pointer to a null-terminated list of struct vbase + items. The vbasetype pointer of each item in the list points to the + type information for a virtual base of the argument DCLASS. + + Helper function for virtual_base_list(). + Note: the list goes backward, right-to-left. virtual_base_list() + copies the items out in reverse order. */ + +struct vbase * +virtual_base_list_aux (dclass) + struct type * dclass; +{ + struct vbase * tmp_vbase; + register int i; + + if (TYPE_CODE(dclass) != TYPE_CODE_CLASS) + return NULL; + + for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++) + { + /* Recurse on this ancestor, first */ + virtual_base_list_aux(TYPE_FIELD_TYPE(dclass, i)); + + /* If this current base is itself virtual, add it to the list */ + if (BASETYPE_VIA_VIRTUAL(dclass, i)) + { + struct type * basetype = TYPE_FIELD_TYPE (dclass, i); + + /* Check if base already recorded */ + tmp_vbase = current_vbase_list; + while (tmp_vbase) + { + if (tmp_vbase->vbasetype == basetype) + break; /* found it */ + tmp_vbase = tmp_vbase->next; + } + + if (!tmp_vbase) /* normal exit from loop */ + { + /* Allocate new item for this virtual base */ + tmp_vbase = (struct vbase *) xmalloc (sizeof (struct vbase)); + + /* Stick it on at the end of the list */ + tmp_vbase->vbasetype = basetype; + tmp_vbase->next = current_vbase_list; + current_vbase_list = tmp_vbase; + } + } /* if virtual */ + } /* for loop over bases */ +} + + +/* Compute the list of virtual bases in the right order. Virtual + bases are laid out in the object's memory area in order of their + occurrence in a depth-first, left-to-right search through the + ancestors. + + Argument DCLASS is the type whose virtual bases are required. + Return value is the address of a null-terminated array of pointers + to struct type items. + + This routine is aimed at the HP/Taligent ANSI C++ runtime model, + and may not work with other runtime models. + + This routine merely hands off the argument to virtual_base_list_aux() + and then copies the result into an array to save space. */ + +struct type ** +virtual_base_list (dclass) + struct type * dclass; +{ + register struct vbase * tmp_vbase; + register struct vbase * tmp_vbase_2; + register int i; + int count; + struct type ** vbase_array; + + current_vbase_list = NULL; + virtual_base_list_aux(dclass); + + for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next) + /* no body */ ; + + count = i; + + vbase_array = (struct type **) xmalloc((count + 1) * sizeof (struct type *)); + + for (i=count -1, tmp_vbase = current_vbase_list; i >= 0; i--, tmp_vbase = tmp_vbase->next) + vbase_array[i] = tmp_vbase->vbasetype; + + /* Get rid of constructed chain */ + tmp_vbase_2 = tmp_vbase = current_vbase_list; + while (tmp_vbase) + { + tmp_vbase = tmp_vbase->next; + free(tmp_vbase_2); + tmp_vbase_2 = tmp_vbase; + } + + vbase_array[count] = NULL; + return vbase_array; +} + +/* Return the length of the virtual base list of the type DCLASS. */ + +int +virtual_base_list_length (dclass) + struct type * dclass; +{ + register int i; + register struct vbase * tmp_vbase; + + current_vbase_list = NULL; + virtual_base_list_aux(dclass); + + for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next) + /* no body */ ; + return i; +} + +/* Return the number of elements of the virtual base list of the type + DCLASS, ignoring those appearing in the primary base (and its + primary base, recursively). */ + +int +virtual_base_list_length_skip_primaries (dclass) + struct type * dclass; +{ + register int i; + register struct vbase * tmp_vbase; + struct type * primary; + + primary = TYPE_RUNTIME_PTR (dclass) ? TYPE_PRIMARY_BASE (dclass) : NULL; + + if (!primary) + return virtual_base_list_length (dclass); + + current_vbase_list = NULL; + virtual_base_list_aux(dclass); + + for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; tmp_vbase = tmp_vbase->next) + { + if (virtual_base_index (tmp_vbase->vbasetype, primary) >= 0) + continue; + i++; + } + return i; +} + + +/* Return the index (position) of type BASE, which is a virtual base + class of DCLASS, in the latter's virtual base list. A return of -1 + indicates "not found" or a problem. */ + +int +virtual_base_index(base, dclass) + struct type * base; + struct type * dclass; +{ + register struct type * vbase; + register int i; + + if ((TYPE_CODE(dclass) != TYPE_CODE_CLASS) || + (TYPE_CODE(base) != TYPE_CODE_CLASS)) + return -1; + + i = 0; + vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[0]; + while (vbase) + { + if (vbase == base) + break; + vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[++i]; + } + + return vbase ? i : -1; +} + + + +/* Return the index (position) of type BASE, which is a virtual base + class of DCLASS, in the latter's virtual base list. Skip over all + bases that may appear in the virtual base list of the primary base + class of DCLASS (recursively). A return of -1 indicates "not + found" or a problem. */ + +int +virtual_base_index_skip_primaries(base, dclass) + struct type * base; + struct type * dclass; +{ + register struct type * vbase; + register int i, j; + struct type * primary; + + if ((TYPE_CODE(dclass) != TYPE_CODE_CLASS) || + (TYPE_CODE(base) != TYPE_CODE_CLASS)) + return -1; + + primary = TYPE_RUNTIME_PTR(dclass) ? TYPE_PRIMARY_BASE(dclass) : NULL; + + j = -1; + i = 0; + vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[0]; + while (vbase) + { + if (!primary || (virtual_base_index_skip_primaries(vbase, primary) < 0)) + j++; + if (vbase == base) + break; + vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[++i]; + } + + return vbase ? j : -1; +} + +/* Return position of a derived class DCLASS in the list of + * primary bases starting with the remotest ancestor. + * Position returned is 0-based. */ + +int +class_index_in_primary_list (dclass) + struct type * dclass; +{ + struct type * pbc; /* primary base class */ + + /* Simply recurse on primary base */ + pbc = TYPE_PRIMARY_BASE (dclass); + if (pbc) + return 1 + class_index_in_primary_list (pbc); + else + return 0; +} + +/* Return a count of the number of virtual functions a type has. + * This includes all the virtual functions it inherits from its + * base classes too. + */ + +/* pai: FIXME This doesn't do the right thing: count redefined virtual + * functions only once (latest redefinition) + */ + +int +count_virtual_fns (dclass) + struct type * dclass; +{ + int base; /* index for base classes */ + int fn, oi; /* function and overloaded instance indices */ + + int vfuncs; /* count to return */ + + /* recurse on bases that can share virtual table */ + struct type * pbc = primary_base_class (dclass); + if (pbc) + vfuncs = count_virtual_fns (pbc); + + for (fn = 0; fn < TYPE_NFN_FIELDS (dclass); fn++) + for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (dclass, fn); oi++) + if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (dclass, fn), oi)) + vfuncs++; + + return vfuncs; +} + + + +/* Functions for overload resolution begin here */ + +/* Compare two badness vectors A and B and return the result. + * 0 => A and B are identical + * 1 => A and B are incomparable + * 2 => A is better than B + * 3 => A is worse than B */ + +int +compare_badness (a, b) + struct badness_vector * a; + struct badness_vector * b; +{ + int i; + int tmp; + short found_pos = 0; /* any positives in c? */ + short found_neg = 0; /* any negatives in c? */ + + /* differing lengths => incomparable */ + if (a->length != b->length) + return 1; + + /* Subtract b from a */ + for (i=0; i < a->length; i++) + { + tmp = a->rank[i] - b->rank[i]; + if (tmp > 0) + found_pos = 1; + else if (tmp < 0) + found_neg = 1; + } + + if (found_pos) + { + if (found_neg) + return 1; /* incomparable */ + else + return 3; /* A > B */ + } + else /* no positives */ + { + if (found_neg) + return 2; /* A < B */ + else + return 0; /* A == B */ + } +} + +/* Rank a function by comparing its parameter types (PARMS, length NPARMS), + * to the types of an argument list (ARGS, length NARGS). + * Return a pointer to a badness vector. This has NARGS + 1 entries. */ + +struct badness_vector * +rank_function (parms, nparms, args, nargs) + struct type ** parms; + int nparms; + struct type ** args; + int nargs; +{ + int i; + struct badness_vector * bv; + int min_len = nparms < nargs ? nparms : nargs; + + bv = xmalloc (sizeof (struct badness_vector)); + bv->length = nargs + 1; /* add 1 for the length-match rank */ + bv->rank = xmalloc ((nargs + 1) * sizeof (int)); + + /* First compare the lengths of the supplied lists. + * If there is a mismatch, set it to a high value. */ + + /* pai/1997-06-03 FIXME: when we have debug info about default + * arguments and ellipsis parameter lists, we should consider those + * and rank the length-match more finely. */ + + LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0; + + /* Now rank all the parameters of the candidate function */ + for (i=1; i <= min_len; i++) + bv->rank[i] = rank_one_type (parms[i-1], args[i-1]); + + /* If more arguments than parameters, add dummy entries */ + for (i = min_len +1; i <= nargs; i++) + bv->rank[i] = TOO_FEW_PARAMS_BADNESS; + + return bv; +} + +/* Compare one type (PARM) for compatibility with another (ARG). + * PARM is intended to be the parameter type of a function; and + * ARG is the supplied argument's type. This function tests if + * the latter can be converted to the former. + * + * Return 0 if they are identical types; + * Otherwise, return an integer which corresponds to how compatible + * PARM is to ARG. The higher the return value, the worse the match. + * Generally the "bad" conversions are all uniformly assigned a 100 */ + +int +rank_one_type (parm, arg) + struct type * parm; + struct type * arg; +{ + /* Identical type pointers */ + /* However, this still doesn't catch all cases of same type for arg + * and param. The reason is that builtin types are different from + * the same ones constructed from the object. */ + if (parm == arg) + return 0; + + /* Resolve typedefs */ + if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF) + parm = check_typedef (parm); + if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF) + arg = check_typedef (arg); + + /* Check if identical after resolving typedefs */ + if (parm == arg) + return 0; + +#if 0 + /* Debugging only */ + printf("------ Arg is %s [%d], parm is %s [%d]\n", + TYPE_NAME (arg), TYPE_CODE (arg), TYPE_NAME (parm), TYPE_CODE (parm)); +#endif + + /* x -> y means arg of type x being supplied for parameter of type y */ + + switch (TYPE_CODE (parm)) + { + case TYPE_CODE_PTR: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_PTR: + if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID) + return VOID_PTR_CONVERSION_BADNESS; + else + return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg)); + case TYPE_CODE_ARRAY: + return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg)); + case TYPE_CODE_FUNC: + return rank_one_type (TYPE_TARGET_TYPE (parm), arg); + case TYPE_CODE_INT: + case TYPE_CODE_ENUM: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + return POINTER_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + case TYPE_CODE_ARRAY: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_PTR: + case TYPE_CODE_ARRAY: + return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg)); + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + case TYPE_CODE_FUNC: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_PTR: /* funcptr -> func */ + return rank_one_type (parm, TYPE_TARGET_TYPE (arg)); + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + case TYPE_CODE_INT: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm)) + { + /* Deal with signed, unsigned, and plain chars and + signed and unsigned ints */ + if (TYPE_NOSIGN (parm)) + { + /* This case only for character types */ + if (TYPE_NOSIGN (arg)) /* plain char -> plain char */ + return 0; + else + return INTEGER_COERCION_BADNESS; /* signed/unsigned char -> plain char */ + } + else if (TYPE_UNSIGNED (parm)) + { + if (TYPE_UNSIGNED (arg)) + { + if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg))) + return 0; /* unsigned int -> unsigned int, or unsigned long -> unsigned long */ + else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long")) + return INTEGER_PROMOTION_BADNESS; /* unsigned int -> unsigned long */ + else + return INTEGER_COERCION_BADNESS; /* unsigned long -> unsigned int */ + } + else + { + if (!strcmp (TYPE_NAME (arg), "long") && !strcmp (TYPE_NAME (parm), "int")) + return INTEGER_COERCION_BADNESS; /* signed long -> unsigned int */ + else + return INTEGER_CONVERSION_BADNESS; /* signed int/long -> unsigned int/long */ + } + } + else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg)) + { + if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg))) + return 0; + else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long")) + return INTEGER_PROMOTION_BADNESS; + else + return INTEGER_COERCION_BADNESS; + } + else + return INTEGER_COERCION_BADNESS; + } + else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm)) + return INTEGER_PROMOTION_BADNESS; + else + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_ENUM: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + return INTEGER_PROMOTION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + case TYPE_CODE_PTR: + return NS_POINTER_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_ENUM: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_CHAR: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + case TYPE_CODE_INT: + if (TYPE_LENGTH (arg) > TYPE_LENGTH (parm)) + return INTEGER_COERCION_BADNESS; + else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm)) + return INTEGER_PROMOTION_BADNESS; + /* >>> !! else fall through !! <<< */ + case TYPE_CODE_CHAR: + /* Deal with signed, unsigned, and plain chars for C++ + and with int cases falling through from previous case */ + if (TYPE_NOSIGN (parm)) + { + if (TYPE_NOSIGN (arg)) + return 0; + else + return INTEGER_COERCION_BADNESS; + } + else if (TYPE_UNSIGNED (parm)) + { + if (TYPE_UNSIGNED (arg)) + return 0; + else + return INTEGER_PROMOTION_BADNESS; + } + else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg)) + return 0; + else + return INTEGER_COERCION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_RANGE: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_BOOL: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + case TYPE_CODE_FLT: + case TYPE_CODE_PTR: + return BOOLEAN_CONVERSION_BADNESS; + case TYPE_CODE_BOOL: + return 0; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_FLT: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_FLT: + if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm)) + return FLOAT_PROMOTION_BADNESS; + else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm)) + return 0; + else + return FLOAT_CONVERSION_BADNESS; + case TYPE_CODE_INT: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + case TYPE_CODE_CHAR: + return INT_FLOAT_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_COMPLEX: + switch (TYPE_CODE (arg)) + { /* Strictly not needed for C++, but... */ + case TYPE_CODE_FLT: + return FLOAT_PROMOTION_BADNESS; + case TYPE_CODE_COMPLEX: + return 0; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_STRUCT: + /* currently same as TYPE_CODE_CLASS */ + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_STRUCT: + /* Check for derivation */ + if (is_ancestor (parm, arg)) + return BASE_CONVERSION_BADNESS; + /* else fall through */ + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_UNION: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_UNION: + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_MEMBER: + switch (TYPE_CODE (arg)) + { + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_METHOD: + switch (TYPE_CODE (arg)) + { + + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_REF: + switch (TYPE_CODE (arg)) + { + + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + + break; + case TYPE_CODE_SET: + switch (TYPE_CODE (arg)) + { + /* Not in C++ */ + case TYPE_CODE_SET: + return rank_one_type (TYPE_FIELD_TYPE (parm, 0), TYPE_FIELD_TYPE (arg, 0)); + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_VOID: + default: + return INCOMPATIBLE_TYPE_BADNESS; + } /* switch (TYPE_CODE (arg)) */ +} + + +/* End of functions for overload resolution */ + + + #if MAINTENANCE_CMDS static void @@ -1887,6 +2785,8 @@ build_gdbtypes () init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 0, "char", (struct objfile *) NULL); + TYPE_FLAGS (builtin_type_char) |= TYPE_FLAG_NOSIGN; + builtin_type_signed_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 0, @@ -1985,6 +2885,19 @@ build_gdbtypes () init_type (TYPE_CODE_INT, 64 / 8, TYPE_FLAG_UNSIGNED, "uint64_t", (struct objfile *) NULL); + builtin_type_bool = + init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, + "bool", (struct objfile *) NULL); + + /* Add user knob for controlling resolution of opaque types */ + add_show_from_set + (add_set_cmd ("opaque-type-resolution", class_support, var_boolean, (char *)&opaque_type_resolution, + "Set resolution of opaque struct/class/union types (if set before loading symbols).", + &setlist), + &showlist); + opaque_type_resolution = 1; + /* start-sanitize-r5900 */ builtin_type_int128 = init_type (TYPE_CODE_INT, 128 / 8, diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 4c354fe..8e830d4 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -29,9 +29,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define FT_VOID 0 #define FT_BOOLEAN 1 -#define FT_CHAR 2 -#define FT_SIGNED_CHAR 3 -#define FT_UNSIGNED_CHAR 4 +#define FT_CHAR 2 /* we use this for not-unsigned C/C++ chars */ +#define FT_SIGNED_CHAR 3 /* we use this for C++ signed chars */ +#define FT_UNSIGNED_CHAR 4 /* we use this for C/C++ unsigned chars */ #define FT_SHORT 5 #define FT_SIGNED_SHORT 6 #define FT_UNSIGNED_SHORT 7 @@ -55,8 +55,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define FT_FLOAT_DECIMAL 25 #define FT_BYTE 26 #define FT_UNSIGNED_BYTE 27 +#define FT_TEMPLATE_ARG 28 -#define FT_NUM_MEMBERS 28 /* Highest FT_* above, plus one. */ +#define FT_NUM_MEMBERS 29 /* Highest FT_* above, plus one. */ /* Some macros for char-based bitfields. */ @@ -122,7 +123,10 @@ enum type_code /* Fortran */ TYPE_CODE_COMPLEX, /* Complex float */ - TYPE_CODE_TYPEDEF + TYPE_CODE_TYPEDEF, + TYPE_CODE_TEMPLATE, /* C++ template */ + TYPE_CODE_TEMPLATE_ARG /* C++ template arg */ + }; /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an @@ -136,10 +140,16 @@ enum type_code /* Some bits for the type's flags word. */ /* Unsigned integer type. If this is not set for a TYPE_CODE_INT, the - type is signed. */ + type is signed (unless TYPE_FLAG_NOSIGN (below) is set). */ #define TYPE_FLAG_UNSIGNED (1 << 0) +/* No sign for this type. In C++, "char", "signed char", and "unsigned + char" are distinct types; so we need an extra flag to indicate the + absence ofa sign! */ + +#define TYPE_FLAG_NOSIGN (1 << 1) + /* This appears in a type's flags word if it is a stub type (e.g., if someone referenced a type that wasn't defined in a source file via (struct sir_not_appearing_in_this_film *)). */ @@ -154,11 +164,43 @@ enum type_code #define TYPE_FLAG_TARGET_STUB (1 << 3) +/* Static type. If this is set, the corresponding type had + * a static modifier. + * Note: This may be unnecessary, since static data members + * are indicated by other means (bitpos == -1) + */ + +#define TYPE_FLAG_STATIC (1 << 4) + +/* Constant type. If this is set, the corresponding type has a + * const modifier. + */ + +#define TYPE_FLAG_CONST (1 << 5) + +/* Volatile type. If this is set, the corresponding type has a + * volatile modifier. + */ + +#define TYPE_FLAG_VOLATILE (1 << 6) + + /* This is a function type which appears to have a prototype. We need this for function calls in order to tell us if it's necessary to coerce the args, - or to just do the standard conversions. */ + or to just do the standard conversions. This is used with a short field. */ + +#define TYPE_FLAG_PROTOTYPED (1 << 7) + +/* This flag is used to indicate that processing for this type + is incomplete. + + (Mostly intended for HP platforms, where class methods, for + instance, can be encountered before their classes in the debug + info; the incomplete type has to be marked so that the class and + the method can be assigned correct types.) */ + +#define TYPE_FLAG_INCOMPLETE (1 << 8) -#define TYPE_FLAG_PROTOTYPED (1 << 4) struct type { @@ -245,9 +287,15 @@ struct type struct type *reference_type; + /* C-v variant chain. This points to a type that + differs from this one only in a const or volatile + attribute (or both). The various c-v variants + are chained together in a ring. */ + struct type *cv_type; + /* Flags about this type. */ - short flags; + int flags; /* Number of fields described for this type */ @@ -382,8 +430,22 @@ struct cplus_struct_type /* Number of methods described for this type, not including the methods that it derives from. */ - int nfn_fields_total; - + short nfn_fields_total; + + /* The "declared_type" field contains a code saying how the + user really declared this type, e.g., "class s", "union s", + "struct s". + The 3 above things come out from the C++ compiler looking like classes, + but we keep track of the real declaration so we can give + the correct information on "ptype". (Note: TEMPLATE may not + belong in this list...) */ + +#define DECLARED_TYPE_CLASS 0 +#define DECLARED_TYPE_UNION 1 +#define DECLARED_TYPE_STRUCT 2 +#define DECLARED_TYPE_TEMPLATE 3 + short declared_type; /* One of the above codes */ + /* For derived classes, the number of base classes is given by n_baseclasses and virtual_field_bits is a bit vector containing one bit per base class. If the base class is virtual, the corresponding bit will be set. @@ -453,10 +515,21 @@ struct cplus_struct_type char *physname; - /* The type of the method. */ + /* The function type for the method. + (This comment used to say "The return value of the method", + but that's wrong. The function type + is expected here, i.e. something with TYPE_CODE_FUNC, + and *not* the return-value type). */ struct type *type; + /* The argument list. Only valid if is_stub is clear. Contains + the type of each argument, including `this', and ending with + a NULL pointer after the last argument. Should not contain + a `this' pointer for static member functions. */ + + struct type **args; + /* For virtual functions. First baseclass that defines this virtual function. */ @@ -473,8 +546,11 @@ struct cplus_struct_type to reconstruct the rest of the fields). */ unsigned int is_stub : 1; + /* C++ method that is inlined */ + unsigned int is_inlined : 1; + /* Unused. */ - unsigned int dummy : 3; + unsigned int dummy : 2; /* Index into that baseclass's virtual function table, minus 2; else if static: VOFFSET_STATIC; else: 0. */ @@ -487,6 +563,72 @@ struct cplus_struct_type } *fn_fieldlists; + /* If this "struct type" describes a template, then it + * has arguments. "template_args" points to an array of + * template arg descriptors, of length "ntemplate_args". + * The only real information in each of these template arg descriptors + * is a name. "type" will typically just point to a "struct type" with + * the placeholder TYPE_CODE_TEMPLATE_ARG type. + */ + short ntemplate_args; + struct template_arg + { + char *name; + struct type *type; + } *template_args; + + /* If this "struct type" describes a template, it has a list + * of instantiations. "instantiations" is a pointer to an array + * of type's, one representing each instantiation. There + * are "ninstantiations" elements in this array. + */ + short ninstantiations; + struct type **instantiations; + + /* The following points to information relevant to the runtime model + * of the compiler. + * Currently being used only for HP's ANSI C++ compiler. + * (This type may have to be changed/enhanced for other compilers.) + * + * RUNTIME_PTR is NULL if there is no runtime information (currently + * this means the type was not compiled by HP aCC). + * + * Fields in structure pointed to: + * ->HAS_VTABLE : 0 => no virtual table, 1 => vtable present + * + * ->PRIMARY_BASE points to the first non-virtual base class that has + * a virtual table. + * + * ->VIRTUAL_BASE_LIST points to a list of struct type * pointers that + * point to the type information for all virtual bases among this type's + * ancestors. + */ + struct runtime_info { + short has_vtable; + struct type * primary_base; + struct type ** virtual_base_list; + } * runtime_ptr; + + /* Pointer to information about enclosing scope, if this is a + * local type. If it is not a local type, this is NULL + */ + struct local_type_info { + char * file; + int line; + } * localtype_ptr; +}; + +/* Struct used in computing virtual base list */ +struct vbase +{ + struct type * vbasetype; /* pointer to virtual base */ + struct vbase * next; /* next in chain */ +}; + +/* Struct used for ranking a function for overload resolution */ +struct badness_vector { + int length; + int * rank; }; /* The default value of TYPE_CPLUS_SPECIFIC(T) points to the @@ -508,6 +650,7 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_TARGET_TYPE(thistype) (thistype)->target_type #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type +#define TYPE_CV_TYPE(thistype) (thistype)->cv_type /* Note that if thistype is a TYPEDEF type, you have to call check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF type, so you only have to call check_typedef once. Since allocate_value @@ -516,11 +659,17 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_OBJFILE(thistype) (thistype)->objfile #define TYPE_FLAGS(thistype) (thistype)->flags #define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED) +#define TYPE_NOSIGN(thistype) ((thistype)->flags & TYPE_FLAG_NOSIGN) +#define TYPE_CONST(thistype) ((thistype)->flags & TYPE_FLAG_CONST) +#define TYPE_VOLATILE(thistype) ((thistype)->flags & TYPE_FLAG_VOLATILE) +#define TYPE_INCOMPLETE(thistype) ((thistype)->flags & TYPE_FLAG_INCOMPLETE) /* Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you wan the real type, you need to do TYPE_CODE (check_type (this_type)). */ #define TYPE_CODE(thistype) (thistype)->code #define TYPE_NFIELDS(thistype) (thistype)->nfields #define TYPE_FIELDS(thistype) (thistype)->fields +#define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args +#define TYPE_INSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->instantiations #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0) #define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0) @@ -545,6 +694,9 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_FN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->fn_fields #define TYPE_NFN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields #define TYPE_NFN_FIELDS_TOTAL(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields_total +#define TYPE_NTEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ntemplate_args +#define TYPE_NINSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ninstantiations +#define TYPE_DECLARED_TYPE(thistype) TYPE_CPLUS_SPECIFIC(thistype)->declared_type #define TYPE_TYPE_SPECIFIC(thistype) (thistype)->type_specific #define TYPE_ARG_TYPES(thistype) (thistype)->type_specific.arg_types #define TYPE_CPLUS_SPECIFIC(thistype) (thistype)->type_specific.cplus_stuff @@ -552,9 +704,12 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses #define TYPE_BASECLASS_NAME(thistype,index) (thistype)->fields[index].name #define TYPE_BASECLASS_BITPOS(thistype,index) TYPE_FIELD_BITPOS(thistype,index) -#define BASETYPE_VIA_PUBLIC(thistype, index) (!TYPE_FIELD_PRIVATE(thistype, index)) +#define BASETYPE_VIA_PUBLIC(thistype, index) \ + ((!TYPE_FIELD_PRIVATE(thistype, index)) && (!TYPE_FIELD_PROTECTED(thistype, index))) + #define BASETYPE_VIA_VIRTUAL(thistype, index) \ - B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (index)) + (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits == NULL ? 0 \ + : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (index))) #define FIELD_TYPE(thisfld) ((thisfld).type) #define FIELD_NAME(thisfld) ((thisfld).name) @@ -572,6 +727,8 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS(TYPE_FIELD(thistype,n)) #define TYPE_FIELD_BITSIZE(thistype, n) FIELD_BITSIZE(TYPE_FIELD(thistype,n)) #define TYPE_FIELD_PACKED(thistype, n) (FIELD_BITSIZE(TYPE_FIELD(thistype,n))!=0) +#define TYPE_TEMPLATE_ARG(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->template_args[n] +#define TYPE_INSTANTIATION(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->instantiations[n] #define TYPE_FIELD_PRIVATE_BITS(thistype) \ TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits @@ -599,7 +756,8 @@ allocate_cplus_struct_type PARAMS ((struct type *)); (TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits == NULL ? 0 \ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->ignore_field_bits, (n))) #define TYPE_FIELD_VIRTUAL(thistype, n) \ - B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n)) + (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits == NULL ? 0 \ + : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n))) #define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitsize < 0) #define TYPE_FIELD_STATIC_HAS_ADDR(thistype, n) ((thistype)->fields[n].bitsize == -2) @@ -621,11 +779,29 @@ allocate_cplus_struct_type PARAMS ((struct type *)); #define TYPE_FN_FIELD_PRIVATE(thisfn, n) ((thisfn)[n].is_private) #define TYPE_FN_FIELD_PROTECTED(thisfn, n) ((thisfn)[n].is_protected) #define TYPE_FN_FIELD_STUB(thisfn, n) ((thisfn)[n].is_stub) +#define TYPE_FN_FIELD_INLINED(thisfn, n) ((thisfn)[n].is_inlined) #define TYPE_FN_FIELD_FCONTEXT(thisfn, n) ((thisfn)[n].fcontext) #define TYPE_FN_FIELD_VOFFSET(thisfn, n) ((thisfn)[n].voffset-2) #define TYPE_FN_FIELD_VIRTUAL_P(thisfn, n) ((thisfn)[n].voffset > 1) #define TYPE_FN_FIELD_STATIC_P(thisfn, n) ((thisfn)[n].voffset == VOFFSET_STATIC) +#define TYPE_RUNTIME_PTR(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->runtime_ptr) +#define TYPE_VTABLE(thistype) (TYPE_RUNTIME_PTR(thistype)->has_vtable) +#define TYPE_HAS_VTABLE(thistype) (TYPE_RUNTIME_PTR(thistype) && TYPE_VTABLE(thistype)) +#define TYPE_PRIMARY_BASE(thistype) (TYPE_RUNTIME_PTR(thistype)->primary_base) +#define TYPE_VIRTUAL_BASE_LIST(thistype) (TYPE_RUNTIME_PTR(thistype)->virtual_base_list) + +#define TYPE_LOCALTYPE_PTR(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr) +#define TYPE_LOCALTYPE_FILE(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr->file) +#define TYPE_LOCALTYPE_LINE(thistype) (TYPE_CPLUS_SPECIFIC(thistype)->localtype_ptr->line) + +#define TYPE_IS_OPAQUE(thistype) (((TYPE_CODE (thistype) == TYPE_CODE_STRUCT) || \ + (TYPE_CODE (thistype) == TYPE_CODE_UNION)) && \ + (TYPE_NFIELDS (thistype) == 0) && \ + (TYPE_CPLUS_SPECIFIC (thistype) && (TYPE_NFN_FIELDS (thistype) == 0))) + + + /* Implicit sizes */ extern struct type *builtin_type_void; extern struct type *builtin_type_char; @@ -643,6 +819,7 @@ extern struct type *builtin_type_long_double; extern struct type *builtin_type_complex; extern struct type *builtin_type_double_complex; extern struct type *builtin_type_string; +extern struct type *builtin_type_bool; /* Explicit sizes - see <intypes.h> for naming schema */ extern struct type *builtin_type_int8; @@ -699,6 +876,9 @@ extern struct type *builtin_type_f_complex_s16; extern struct type *builtin_type_f_complex_s32; extern struct type *builtin_type_f_void; +/* RTTI for C++ */ +/* extern struct type *builtin_type_cxx_typeinfo; */ + /* Maximum and minimum values of built-in types */ #define MAX_OF_TYPE(t) \ @@ -736,6 +916,9 @@ extern struct type * make_reference_type PARAMS ((struct type *, struct type **)); extern struct type * +make_cv_type PARAMS ((int, int, struct type *, struct type **)); + +extern struct type * lookup_member_type PARAMS ((struct type *, struct type *)); extern void @@ -818,6 +1001,112 @@ extern int get_destructor_fn_field PARAMS ((struct type *, int *, int *)); extern int get_discrete_bounds PARAMS ((struct type*, LONGEST*, LONGEST*)); +extern int +get_discrete_bounds PARAMS ((struct type*, LONGEST*, LONGEST*)); + +extern int +is_ancestor PARAMS ((struct type *, struct type *)); + +extern int +has_vtable PARAMS ((struct type *)); + +extern struct type * +primary_base_class PARAMS ((struct type *)); + +extern struct type ** +virtual_base_list PARAMS ((struct type *)); + +extern int +virtual_base_list_length PARAMS ((struct type *)); +extern int +virtual_base_list_length_skip_primaries PARAMS ((struct type *)); + +extern int +virtual_base_index PARAMS ((struct type *, struct type *)); +extern int +virtual_base_index_skip_primaries PARAMS ((struct type *, struct type *)); + + +extern int +class_index_in_primary_list PARAMS ((struct type *)); + +extern int +count_virtual_fns PARAMS ((struct type*)); + +/* Constants for HP/Taligent ANSI C++ runtime model */ + +/* Where virtual function entries begin in the + * virtual table, in the non-RRBC vtable format. + * First 4 are the metavtable pointer, top offset, + * typeinfo pointer, and dup base info pointer */ +#define HP_ACC_VFUNC_START 4 + +/* (Negative) Offset where virtual base offset entries begin + * in the virtual table. Skips over metavtable pointer and + * the self-offset entry. + * NOTE: NEGATE THIS BEFORE USING! The virtual base offsets + * appear before the address point of the vtable (the slot + * pointed to by the object's vtable pointer), i.e. at lower + * addresses than the vtable pointer. */ +#define HP_ACC_VBASE_START 2 + +/* (Positive) Offset where the pointer to the typeinfo + * object is present in the virtual table */ +#define HP_ACC_TYPEINFO_OFFSET 2 + +/* (Positive) Offset where the ``top offset'' entry of + * the virtual table is */ +#define HP_ACC_TOP_OFFSET_OFFSET 1 + +/* Overload resolution */ + +#define LENGTH_MATCH(bv) ((bv)->rank[0]) + +/* Badness if parameter list length doesn't match arg list length */ +#define LENGTH_MISMATCH_BADNESS 100 +/* Dummy badness value for nonexistent parameter positions */ +#define TOO_FEW_PARAMS_BADNESS 100 +/* Badness if no conversion among types */ +#define INCOMPATIBLE_TYPE_BADNESS 100 +/* Badness of coercing large integer to smaller size */ +#define INTEGER_COERCION_BADNESS 100 +/* Badness of coercing large floating type to smaller size */ +#define FLOAT_COERCION_BADNESS 100 + +/* Badness of integral promotion */ +#define INTEGER_PROMOTION_BADNESS 1 +/* Badness of floating promotion */ +#define FLOAT_PROMOTION_BADNESS 1 +/* Badness of integral conversion */ +#define INTEGER_CONVERSION_BADNESS 2 +/* Badness of floating conversion */ +#define FLOAT_CONVERSION_BADNESS 2 +/* Badness of integer<->floating conversions */ +#define INT_FLOAT_CONVERSION_BADNESS 2 +/* Badness of converting to a boolean */ +#define BOOLEAN_CONVERSION_BADNESS 2 +/* Badness of pointer conversion */ +#define POINTER_CONVERSION_BADNESS 2 +/* Badness of conversion of pointer to void pointer */ +#define VOID_PTR_CONVERSION_BADNESS 2 +/* Badness of convering derived to base class */ +#define BASE_CONVERSION_BADNESS 2 + +/* Non-standard conversions allowed by the debugger */ +/* Converting a pointer to an int is usually OK */ +#define NS_POINTER_CONVERSION_BADNESS 10 + + +extern int +compare_badness PARAMS ((struct badness_vector *, struct badness_vector *)); + +extern struct badness_vector * +rank_function PARAMS ((struct type **, int, struct type **, int)); + +extern int +rank_one_type PARAMS ((struct type *, struct type *)); + + #if MAINTENANCE_CMDS extern void recursive_dump_type PARAMS ((struct type *, int)); #endif diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index cfd2a81..1cad0aa 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -2082,6 +2082,13 @@ gnu_stop () error ("to_stop target function not implemented"); } +static void +gnu_pid_to_exec_file () +{ + error ("to_pid_to_exec_file target function not implemented"); +} + + static int gnu_thread_alive (int tid) { @@ -2351,9 +2358,13 @@ init_gnu_ops(void) gnu_ops.to_open = gnu_open; /* to_open */ gnu_ops.to_close = 0; /* to_close */ gnu_ops.to_attach = gnu_attach; /* to_attach */ + gnu_ops.to_post_attach = NULL; + gnu_ops.to_require_attach = NULL; /* to_require_attach */ gnu_ops.to_detach = gnu_detach; /* to_detach */ + gnu_ops.to_require_detach = NULL; /* to_require_detach */ gnu_ops.to_resume = gnu_resume; /* to_resume */ gnu_ops.to_wait = gnu_wait; /* to_wait */ + gnu_ops.to_post_wait = NULL; /* to_post_wait */ gnu_ops.to_fetch_registers = gnu_fetch_registers; /* to_fetch_registers */ gnu_ops.to_store_registers = gnu_store_registers; /* to_store_registers */ gnu_ops.to_prepare_to_store = gnu_prepare_to_store; /* to_prepare_to_store */ @@ -2370,11 +2381,30 @@ init_gnu_ops(void) gnu_ops.to_load = 0; /* to_load */ gnu_ops.to_lookup_symbol = 0; /* to_lookup_symbol */ gnu_ops.to_create_inferior = gnu_create_inferior; /* to_create_inferior */ - gnu_ops.to_mourn_inferior = gnu_mourn_inferior; /* to_mourn_inferior */ + gnu_ops.to_post_startup_inferior = NULL; /* to_post_startup_inferior */ + gnu_ops.to_acknowledge_created_inferior = NULL; /* to_acknowledge_created_inferior */ + gnu_ops.to_clone_and_follow_inferior = NULL; /* to_clone_and_follow_inferior */ + gnu_ops.to_post_follow_inferior_by_clone = NULL; /* to_post_follow_inferior_by_clone */ + gnu_ops.to_insert_fork_catchpoint = NULL; + gnu_ops.to_remove_fork_catchpoint = NULL; + gnu_ops.to_insert_vfork_catchpoint = NULL; + gnu_ops.to_remove_vfork_catchpoint = NULL; + gnu_ops.to_has_forked = NULL; /* to_has_forked */ + gnu_ops.to_has_vforked = NULL; /* to_has_vforked */ + gnu_ops.to_can_follow_vfork_prior_to_exec = NULL; + gnu_ops.to_post_follow_vfork = NULL; /* to_post_follow_vfork */ + gnu_ops.to_insert_exec_catchpoint = NULL; + gnu_ops.to_remove_exec_catchpoint = NULL; + gnu_ops.to_has_execd = NULL; + gnu_ops.to_reported_exec_events_per_exec_call = NULL; + gnu_ops.to_has_exited = NULL; + gnu_ops.to_mourn_inferior = gnu_mourn_inferior; /* to_mourn_inferior */ gnu_ops.to_can_run = gnu_can_run; /* to_can_run */ gnu_ops.to_notice_signals = 0; /* to_notice_signals */ gnu_ops.to_thread_alive = gnu_thread_alive;/* to_thread_alive */ gnu_ops.to_stop = gnu_stop; /* to_stop */ + gnu_ops.to_pid_to_exec_file = gnu_pid_to_exec_file; /* to_pid_to_exec_file */ + gnu_ops.to_core_file_to_sym_file = NULL; gnu_ops.to_stratum = process_stratum; /* to_stratum */ gnu_ops.DONT_USE = 0; /* to_next */ gnu_ops.to_has_all_memory = 1; /* to_has_all_memory */ diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index e09c220..d0d5bf9 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1887,7 +1887,7 @@ pa_print_fp_reg (i) print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), gdb_stdout); fputs_filtered ("(single precision) ", gdb_stdout); - val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, gdb_stdout, 0, + val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered ("\n"); @@ -1907,7 +1907,7 @@ pa_print_fp_reg (i) print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), gdb_stdout); fputs_filtered ("(double precision) ", gdb_stdout); - val_print (builtin_type_double, virtual_buffer, 0, gdb_stdout, 0, + val_print (builtin_type_double, virtual_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered ("\n"); } diff --git a/gdb/hpux-thread.c b/gdb/hpux-thread.c index b8c227a..82d8ea4 100644 --- a/gdb/hpux-thread.c +++ b/gdb/hpux-thread.c @@ -593,9 +593,13 @@ struct target_ops hpux_thread_ops = { hpux_thread_open, /* to_open */ 0, /* to_close */ hpux_thread_attach, /* to_attach */ + NULL, /* to_post_attach */ + NULL, /* to_require_attach */ hpux_thread_detach, /* to_detach */ + NULL, /* to_require_detach */ hpux_thread_resume, /* to_resume */ hpux_thread_wait, /* to_wait */ + NULL, /* to_post_wait */ hpux_thread_fetch_registers, /* to_fetch_registers */ hpux_thread_store_registers, /* to_store_registers */ hpux_thread_prepare_to_store, /* to_prepare_to_store */ @@ -612,11 +616,33 @@ struct target_ops hpux_thread_ops = { 0, /* to_load */ 0, /* to_lookup_symbol */ hpux_thread_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + NULL, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_fork */ hpux_thread_mourn_inferior, /* to_mourn_inferior */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ hpux_thread_can_run, /* to_can_run */ hpux_thread_notice_signals, /* to_notice_signals */ hpux_thread_alive, /* to_thread_alive */ hpux_thread_stop, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ process_stratum, /* to_stratum */ 0, /* to_next */ 1, /* to_has_all_memory */ diff --git a/gdb/infcmd.c b/gdb/infcmd.c index eddd89a..4c18f6d 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1,5 +1,6 @@ /* Memory-access and commands for "inferior" process, for GDB. - Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1995, 1996 Free Software Foundation, Inc. + Copyright 1986, 87, 88, 89, 91, 92, 95, 96, 1998 + Free Software Foundation, Inc. This file is part of GDB. @@ -19,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include <signal.h> -#include <sys/param.h> #include "gdb_string.h" #include "symtab.h" #include "gdbtypes.h" @@ -31,8 +31,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdbcore.h" #include "target.h" #include "language.h" +#include "symfile.h" -static void continue_command PARAMS ((char *, int)); +/* Functions exported for general use: */ + +void nofp_registers_info PARAMS ((char *, int)); + +void all_registers_info PARAMS ((char *, int)); + +void registers_info PARAMS ((char *, int)); + +/* Local functions: */ + +void continue_command PARAMS ((char *, int)); static void until_next_command PARAMS ((int)); @@ -48,12 +59,6 @@ static void float_info PARAMS ((char *, int)); static void detach_command PARAMS ((char *, int)); -static void nofp_registers_info PARAMS ((char *, int)); - -static void all_registers_info PARAMS ((char *, int)); - -static void registers_info PARAMS ((char *, int)); - #if !defined (DO_REGISTERS_INFO) static void do_registers_info PARAMS ((int, int)); #endif @@ -74,9 +79,9 @@ static void jump_command PARAMS ((char *, int)); static void step_1 PARAMS ((int, int, char *)); -static void nexti_command PARAMS ((char *, int)); +void nexti_command PARAMS ((char *, int)); -static void stepi_command PARAMS ((char *, int)); +void stepi_command PARAMS ((char *, int)); static void next_command PARAMS ((char *, int)); @@ -84,6 +89,8 @@ static void step_command PARAMS ((char *, int)); static void run_command PARAMS ((char *, int)); +void _initialize_infcmd PARAMS ((void)); + #ifdef CALL_DUMMY_BREAKPOINT_OFFSET static void breakpoint_auto_delete_contents PARAMS ((PTR)); #endif @@ -206,6 +213,8 @@ Start it from the beginning? ")) exec_file = (char *) get_exec_file (0); + do_run_cleanups (NULL); + /* The exec file is re-read every time we do a generic_mourn_inferior, so we just have to worry about the symbol file. */ reread_symbols (); @@ -241,7 +250,7 @@ Start it from the beginning? ")) environ_vector (inferior_environ)); } -static void +void continue_command (proc_count_exp, from_tty) char *proc_count_exp; int from_tty; @@ -305,7 +314,7 @@ next_command (count_string, from_tty) /* Likewise, but step only one instruction. */ /* ARGSUSED */ -static void +void stepi_command (count_string, from_tty) char *count_string; int from_tty; @@ -314,7 +323,7 @@ stepi_command (count_string, from_tty) } /* ARGSUSED */ -static void +void nexti_command (count_string, from_tty) char *count_string; int from_tty; @@ -338,7 +347,8 @@ step_1 (skip_subroutines, single_inst, count_string) if (!single_inst || skip_subroutines) /* leave si command alone */ { enable_longjmp_breakpoint(); - cleanups = make_cleanup(disable_longjmp_breakpoint, 0); + cleanups = make_cleanup ((make_cleanup_func) disable_longjmp_breakpoint, + 0); } for (; count > 0; count--) @@ -443,6 +453,21 @@ jump_command (arg, from_tty) } } + if (sfn != NULL) + { + fixup_symbol_section (sfn, 0); + if (section_is_overlay (SYMBOL_BFD_SECTION (sfn)) && + !section_is_mapped (SYMBOL_BFD_SECTION (sfn))) + { + if (!query ("WARNING!!! Destination is in unmapped overlay! Jump anyway? ")) + { + error ("Not confirmed."); + /* NOTREACHED */ + } + } + } + + addr = sal.pc; if (from_tty) @@ -557,13 +582,13 @@ run_stack_dummy (addr, buffer) struct breakpoint *bpt; struct symtab_and_line sal; + INIT_SAL (&sal); /* initialize to zeroes */ #if CALL_DUMMY_LOCATION != AT_ENTRY_POINT sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET; #else sal.pc = CALL_DUMMY_ADDRESS (); #endif - sal.symtab = NULL; - sal.line = 0; + sal.section = find_pc_overlay (sal.pc); /* Set up a FRAME for the dummy frame so we can pass it to set_momentary_breakpoint. We need to give the breakpoint a @@ -705,7 +730,7 @@ finish_command (arg, from_tty) breakpoint = set_momentary_breakpoint (sal, frame, bp_finish); - old_chain = make_cleanup(delete_breakpoint, breakpoint); + old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); /* Find the function we will return from. */ @@ -947,10 +972,9 @@ path_command (dirname, from_tty) path_info ((char *)NULL, from_tty); } -/* The array of register names. */ - -char *reg_names[] = REGISTER_NAMES; - +#ifdef REGISTER_NAMES +char *gdb_register_names[] = REGISTER_NAMES; +#endif /* Print out the machine register regnum. If regnum is -1, print all registers (fpregs == 1) or all non-float registers (fpregs == 0). @@ -990,16 +1014,16 @@ do_registers_info (regnum, fpregs) /* If the register name is empty, it is undefined for this processor, so don't display anything. */ - if (reg_names[i] == NULL || *(reg_names[i]) == '\0') + if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0') continue; - fputs_filtered (reg_names[i], gdb_stdout); - print_spaces_filtered (15 - strlen (reg_names[i]), gdb_stdout); + fputs_filtered (REGISTER_NAME (i), gdb_stdout); + print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), gdb_stdout); /* Get the data in raw format. */ if (read_relative_register_raw_bytes (i, raw_buffer)) { - printf_filtered ("Invalid register contents\n"); + printf_filtered ("*value not available*\n"); continue; } @@ -1025,7 +1049,7 @@ do_registers_info (regnum, fpregs) printf_filtered ("<invalid float>"); else #endif - val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, + val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered ("\t(raw 0x"); @@ -1052,10 +1076,10 @@ do_registers_info (regnum, fpregs) /* Else print as integer in hex and in decimal. */ else { - val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0, + val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 'x', 1, 0, Val_pretty_default); printf_filtered ("\t"); - val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0, + val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); } @@ -1070,7 +1094,9 @@ do_registers_info (regnum, fpregs) } #endif /* no DO_REGISTERS_INFO. */ -static void +extern int target_map_name_to_register PARAMS ((char *, int)); + +void registers_info (addr_exp, fpregs) char *addr_exp; int fpregs; @@ -1097,10 +1123,13 @@ registers_info (addr_exp, fpregs) while (*end != '\0' && *end != ' ' && *end != '\t') ++end; numregs = ARCH_NUM_REGS; - for (regnum = 0; regnum < numregs; regnum++) - if (!strncmp (addr_exp, reg_names[regnum], end - addr_exp) - && strlen (reg_names[regnum]) == end - addr_exp) - goto found; + + regnum = target_map_name_to_register (addr_exp, end - addr_exp); + if (regnum >= 0) + goto found; + + regnum = numregs; + if (*addr_exp >= '0' && *addr_exp <= '9') regnum = atoi (addr_exp); /* Take a number */ if (regnum >= numregs) /* Bad name, or bad number */ @@ -1115,7 +1144,7 @@ found: } while (*addr_exp != '\0'); } -static void +void all_registers_info (addr_exp, from_tty) char *addr_exp; int from_tty; @@ -1123,13 +1152,14 @@ all_registers_info (addr_exp, from_tty) registers_info (addr_exp, 1); } -static void +void nofp_registers_info (addr_exp, from_tty) char *addr_exp; int from_tty; { registers_info (addr_exp, 0); } + /* * TODO: @@ -1253,7 +1283,7 @@ _initialize_infcmd () add_show_from_set (add_set_cmd ("args", class_run, var_string_noescape, (char *)&inferior_args, -"Set arguments to give program being debugged when it is started.\n\ +"Set argument list to give program being debugged when it is started.\n\ Follow this command with any number of args, to be passed to the program.", &setlist), &showlist); diff --git a/gdb/inftarg.c b/gdb/inftarg.c index eff9969..95f6c3a 100644 --- a/gdb/inftarg.c +++ b/gdb/inftarg.c @@ -1,5 +1,6 @@ /* Target-vector operations for controlling Unix child processes, for GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996 + Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. @@ -16,16 +17,28 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "frame.h" /* required by inferior.h */ #include "inferior.h" #include "target.h" -#include "wait.h" #include "gdbcore.h" #include "command.h" #include <signal.h> +#include <sys/types.h> +#include <fcntl.h> + +#ifdef HAVE_WAIT_H +# include <wait.h> +#else +# ifdef HAVE_SYS_WAIT_H +# include <sys/wait.h> +# endif +#endif + +/* "wait.h" fills in the gaps left by <wait.h> */ +#include "wait.h" static void child_prepare_to_store PARAMS ((void)); @@ -48,7 +61,7 @@ child_attach PARAMS ((char *, int)); static void ptrace_me PARAMS ((void)); -static void +static int ptrace_him PARAMS ((int)); static void child_create_inferior PARAMS ((char *, char *, char **)); @@ -59,11 +72,35 @@ child_mourn_inferior PARAMS ((void)); static int child_can_run PARAMS ((void)); +static int +proc_wait PARAMS ((int, int*)); + +static void +child_stop PARAMS ((void)); + +#ifndef CHILD_THREAD_ALIVE +static int child_thread_alive PARAMS ((int)); +#endif + extern char **environ; /* Forward declaration */ extern struct target_ops child_ops; +int child_suppress_run = 0; /* Non-zero if inftarg should pretend not to + be a runnable target. Used by targets + that can sit atop inftarg, such as HPUX + thread support. */ +static int +proc_wait (pid, status) + int pid; + int *status; +{ +#ifndef __GO32__ + return wait (status); +#endif +} + #ifndef CHILD_WAIT /* Wait for child to do something. Return pid of child, or -1 in case @@ -78,18 +115,16 @@ child_wait (pid, ourstatus) int status; do { - if (attach_flag) - set_sigint_trap(); /* Causes SIGINT to be passed on to the - attached process. */ + set_sigint_trap(); /* Causes SIGINT to be passed on to the + attached process. */ set_sigio_trap (); - pid = wait (&status); + pid = proc_wait (inferior_pid, &status); save_errno = errno; clear_sigio_trap (); - if (attach_flag) - clear_sigint_trap(); + clear_sigint_trap(); if (pid == -1) { @@ -108,6 +143,22 @@ child_wait (pid, ourstatus) } #endif /* CHILD_WAIT */ +#ifndef CHILD_THREAD_ALIVE + +/* Check to see if the given thread is alive. + + FIXME: Is kill() ever the right way to do this? I doubt it, but + for now we're going to try and be compatable with the old thread + code. */ +static int +child_thread_alive (pid) + int pid; +{ + return (kill (pid, 0) != -1); +} + +#endif + /* Attach to process PID, then initialize for debugging it. */ static void @@ -235,7 +286,7 @@ ptrace_me () /* Stub function which causes the GDB that runs it, to start ptrace-ing the child process. */ -static void +static int ptrace_him (pid) int pid; { @@ -247,6 +298,8 @@ ptrace_him (pid) /* One trap to exec the shell, one to exec the program being debugged. */ startup_inferior (2); #endif + + return pid; } /* Start an inferior Unix child process and sets inferior_pid to its pid. @@ -269,14 +322,36 @@ child_create_inferior (exec_file, allargs, env) static void child_mourn_inferior () { + /* FIXME: Should be in a header file */ + extern void proc_remove_foreign PARAMS ((int)); + unpush_target (&child_ops); + proc_remove_foreign (inferior_pid); generic_mourn_inferior (); } static int child_can_run () { - return(1); + /* This variable is controlled by modules that sit atop inftarg that may layer + their own process structure atop that provided here. hpux-thread.c does + this because of the Hpux user-mode level thread model. */ + + return !child_suppress_run; +} + +/* Send a SIGINT to the process group. This acts just like the user typed a + ^C on the controlling terminal. + + XXX - This may not be correct for all systems. Some may want to use + killpg() instead of kill (-pgrp). */ + +static void +child_stop () +{ + extern pid_t inferior_process_group; + + kill (-inferior_process_group, SIGINT); } struct target_ops child_ops = { @@ -286,9 +361,13 @@ struct target_ops child_ops = { child_open, /* to_open */ 0, /* to_close */ child_attach, /* to_attach */ + NULL, /* to_post_attach */ + NULL, /* to_require_attach */ child_detach, /* to_detach */ + NULL, /* to_require_detach */ child_resume, /* to_resume */ child_wait, /* to_wait */ + NULL, /* to_post_wait */ fetch_inferior_registers, /* to_fetch_registers */ store_inferior_registers, /* to_store_registers */ child_prepare_to_store, /* to_prepare_to_store */ @@ -305,9 +384,33 @@ struct target_ops child_ops = { 0, /* to_load */ 0, /* to_lookup_symbol */ child_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + NULL, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ child_mourn_inferior, /* to_mourn_inferior */ child_can_run, /* to_can_run */ 0, /* to_notice_signals */ + child_thread_alive, /* to_thread_alive */ + child_stop, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ process_stratum, /* to_stratum */ 0, /* to_next */ 1, /* to_has_all_memory */ @@ -315,13 +418,30 @@ struct target_ops child_ops = { 1, /* to_has_stack */ 1, /* to_has_registers */ 1, /* to_has_execution */ - 0, /* sections */ - 0, /* sections_end */ + 0, /* to_sections */ + 0, /* to_sections_end */ OPS_MAGIC /* to_magic */ }; void _initialize_inftarg () { +#ifdef HAVE_OPTIONAL_PROC_FS + char procname[32]; + int fd; + + /* If we have an optional /proc filesystem (e.g. under OSF/1), + don't add ptrace support if we can access the running GDB via /proc. */ +#ifndef PROC_NAME_FMT +#define PROC_NAME_FMT "/proc/%05d" +#endif + sprintf (procname, PROC_NAME_FMT, getpid ()); + if ((fd = open (procname, O_RDONLY)) >= 0) + { + close (fd); + return; + } +#endif + add_target (&child_ops); } diff --git a/gdb/jv-lang.h b/gdb/jv-lang.h index ba8aa4d..16b3f1a 100644 --- a/gdb/jv-lang.h +++ b/gdb/jv-lang.h @@ -41,7 +41,7 @@ extern struct type *java_void_type; extern struct objfile *dynamics_objfile; extern int -java_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, +java_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); extern int diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c index 0f3d639b..f8cb90b 100644 --- a/gdb/jv-valprint.c +++ b/gdb/jv-valprint.c @@ -136,8 +136,8 @@ java_value_print (val, stream, format, pretty) fprintf_filtered (stream, "%d: ", i); else fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1); - val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, - stream, format, 2, 1, pretty); + val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, 0, + stream, format, 2, 1, pretty); things_printed++; i += reps; } @@ -184,7 +184,7 @@ java_value_print (val, stream, format, pretty) return 0; } - return (val_print (type, VALUE_CONTENTS (val), address, + return (val_print (type, VALUE_CONTENTS (val), 0, address, stream, format, 1, 0, pretty)); } @@ -343,7 +343,8 @@ java_print_value_fields (type, valaddr, address, stream, v = value_from_longest (TYPE_FIELD_TYPE (type, i), unpack_field_as_long (type, valaddr, i)); - val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0, + val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), + 0, 0, stream, format, 0, recurse + 1, pretty); } } @@ -364,7 +365,7 @@ java_print_value_fields (type, valaddr, address, stream, if (TYPE_CODE (t) == TYPE_CODE_STRUCT) v = value_addr (v); val_print (VALUE_TYPE (v), - VALUE_CONTENTS (v), VALUE_ADDRESS (v), + VALUE_CONTENTS (v), 0, VALUE_ADDRESS (v), stream, format, 0, recurse+1, pretty); } } @@ -372,6 +373,7 @@ java_print_value_fields (type, valaddr, address, stream, { val_print (TYPE_FIELD_TYPE (type, i), valaddr + TYPE_FIELD_BITPOS (type, i) / 8, + 0, address + TYPE_FIELD_BITPOS (type, i) / 8, stream, format, 0, recurse + 1, pretty); } @@ -402,10 +404,11 @@ java_print_value_fields (type, valaddr, address, stream, The PRETTY parameter controls prettyprinting. */ int -java_val_print (type, valaddr, address, stream, format, deref_ref, recurse, - pretty) +java_val_print (type, valaddr, embedded_offset, address, stream, format, + deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -476,7 +479,7 @@ java_val_print (type, valaddr, address, stream, format, deref_ref, recurse, recurse, pretty); break; default: - return c_val_print (type, valaddr, address, stream, format, + return c_val_print (type, valaddr, 0, address, stream, format, deref_ref, recurse, pretty); } return 0; diff --git a/gdb/language.c b/gdb/language.c index db6d513..225d423 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -99,7 +99,7 @@ static void unk_lang_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); static int -unk_lang_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, +unk_lang_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); static int @@ -834,7 +834,7 @@ lang_bool_type () if (type && TYPE_CODE (type) == TYPE_CODE_BOOL) return type; } - /* ... else fall through ... */ + return builtin_type_bool; default: return builtin_type_int; } @@ -1278,10 +1278,11 @@ unk_lang_print_type (type, varstring, stream, show, level) } static int -unk_lang_val_print (type, valaddr, address, stream, format, deref_ref, +unk_lang_val_print (type, valaddr, embedded_offset, address, stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; GDB_FILE *stream; int format; diff --git a/gdb/language.h b/gdb/language.h index 1699804..e336869 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -153,7 +153,7 @@ struct language_defn /* Print a value using syntax appropriate for this language. */ - int (*la_val_print) PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, + int (*la_val_print) PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); /* Print a top-level value using syntax appropriate for this language. */ @@ -264,8 +264,8 @@ set_language PARAMS ((enum language)); #define LA_PRINT_TYPE(type,varstring,stream,show,level) \ (current_language->la_print_type(type,varstring,stream,show,level)) -#define LA_VAL_PRINT(type,valaddr,addr,stream,fmt,deref,recurse,pretty) \ - (current_language->la_val_print(type,valaddr,addr,stream,fmt,deref, \ +#define LA_VAL_PRINT(type,valaddr,offset,addr,stream,fmt,deref,recurse,pretty) \ + (current_language->la_val_print(type,valaddr,offset,addr,stream,fmt,deref, \ recurse,pretty)) #define LA_VALUE_PRINT(val,stream,fmt,pretty) \ (current_language->la_value_print(val,stream,fmt,pretty)) diff --git a/gdb/m2-lang.h b/gdb/m2-lang.h index 36bcfc3..dc627b7 100644 --- a/gdb/m2-lang.h +++ b/gdb/m2-lang.h @@ -27,5 +27,5 @@ extern void /* Defined in m2-typeprint.c */ m2_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int)); extern int -m2_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, +m2_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c index 91e24b7..12a2f27 100644 --- a/gdb/m2-valprint.c +++ b/gdb/m2-valprint.c @@ -27,10 +27,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* FIXME: For now, just explicitly declare c_val_print and use it instead */ int -m2_val_print (type, valaddr, address, stream, format, deref_ref, recurse, - pretty) +m2_val_print (type, valaddr, embedded_offset, address, + stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -39,8 +40,8 @@ m2_val_print (type, valaddr, address, stream, format, deref_ref, recurse, enum val_prettyprint pretty; { extern int - c_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, - int, enum val_prettyprint)); - return (c_val_print (type, valaddr, address, stream, format, deref_ref, + c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, + GDB_FILE *, int, int, int, enum val_prettyprint)); + return (c_val_print (type, valaddr, 0, address, stream, format, deref_ref, recurse, pretty)); } diff --git a/gdb/m3-nat.c b/gdb/m3-nat.c index c171945..d146bdf 100644 --- a/gdb/m3-nat.c +++ b/gdb/m3-nat.c @@ -4526,6 +4526,14 @@ m3_stop () error ("to_stop target function not implemented"); } +static char * +m3_pid_to_exec_file (pid) +int pid; +{ + error ("to_pid_to_exec_file target function not implemented"); + return NULL; /* To keep all compilers happy. */ +} + struct target_ops m3_ops = { "mach", /* to_shortname */ "Mach child process", /* to_longname */ @@ -4533,9 +4541,13 @@ struct target_ops m3_ops = { m3_open, /* to_open */ 0, /* to_close */ m3_attach, /* to_attach */ + NULL, /* to_post_attach */ + NULL, /* to_require_attach */ m3_detach, /* to_detach */ + NULL, /* to_require_detach */ m3_resume, /* to_resume */ mach_really_wait, /* to_wait */ + NULL, /* to_post_wait */ fetch_inferior_registers, /* to_fetch_registers */ store_inferior_registers, /* to_store_registers */ m3_prepare_to_store, /* to_prepare_to_store */ @@ -4551,13 +4563,31 @@ struct target_ops m3_ops = { m3_kill_inferior, /* to_kill */ 0, /* to_load */ 0, /* to_lookup_symbol */ - m3_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + NULL, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_exited */ m3_mourn_inferior, /* to_mourn_inferior */ m3_can_run, /* to_can_run */ 0, /* to_notice_signals */ 0, /* to_thread_alive */ m3_stop, /* to_stop */ + m3_pid_to_exec_file, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ process_stratum, /* to_stratum */ 0, /* to_next */ 1, /* to_has_all_memory */ diff --git a/gdb/mac-nat.c b/gdb/mac-nat.c index 178b215..15e3f69 100644 --- a/gdb/mac-nat.c +++ b/gdb/mac-nat.c @@ -341,9 +341,13 @@ static void init_child_ops(void) child_ops.to_open = child_open; child_ops.to_close = child_close; child_ops.to_attach = child_attach; + child_ops.to_post_attach = NULL; + child_ops.to_require_attach = NULL; /* to_require_attach */ child_ops.to_detach = child_detach; + child_ops.to_require_detach = NULL; /* to_require_detach */ child_ops.to_resume = child_resume; child_ops.to_wait = child_wait; + child_ops.to_post_wait = NULL; /* to_post_wait */ child_ops.to_fetch_registers = child_fetch_inferior_registers; child_ops.to_store_registers = child_store_inferior_registers; child_ops.to_prepare_to_store = child_prepare_to_store; @@ -360,11 +364,30 @@ static void init_child_ops(void) child_ops.to_load = 0; child_ops.to_lookup_symbol = 0; child_ops.to_create_inferior = child_create_inferior; + child_ops.to_post_startup_inferior = NULL; /* to_post_startup_inferior */ + child_ops.to_acknowledge_created_inferior = NULL; /* to_acknowledge_created_inferior */ + child_ops.to_clone_and_follow_inferior = NULL; /* to_clone_and_follow_inferior */ + child_ops.to_post_follow_inferior_by_clone = NULL; /* to_post_follow_inferior_by_clone */ + child_ops.to_insert_fork_catchpoint = NULL; + child_ops.to_remove_fork_catchpoint = NULL; + child_ops.to_insert_vfork_catchpoint = NULL; + child_ops.to_remove_vfork_catchpoint = NULL; + child_ops.to_has_forked = NULL; /* to_has_forked */ + child_ops.to_has_vforked = NULL; /* to_has_vforked */ + child_ops.to_can_follow_vfork_prior_to_exec = NULL; + child_ops.to_post_follow_vfork = NULL; /* to_post_follow_vfork */ + child_ops.to_insert_exec_catchpoint = NULL; + child_ops.to_remove_exec_catchpoint = NULL; + child_ops.to_has_execd = NULL; + child_ops.to_reported_exec_events_per_exec_call = NULL; + child_ops.to_has_exited = NULL; child_ops.to_mourn_inferior = child_mourn_inferior; child_ops.to_can_run = child_can_run; child_ops.to_notice_signals = 0; child_ops.to_thread_alive = 0; child_ops.to_stop = child_stop; + child_ops.to_pid_to_exec_file = NULL; /* to_pid_to_exec_file */ + child_ops.to_core_file_to_sym_file = NULL; child_ops.to_stratum = process_stratum; child_ops.DONT_USE = 0; child_ops.to_has_all_memory = 1; @@ -54,11 +54,17 @@ int display_time; int display_space; +/* Whether xdb commands will be handled */ +int xdb_commands = 0; + +/* Whether dbx commands will be handled */ +int dbx_commands = 0; + static void print_gdb_help PARAMS ((GDB_FILE *)); extern void gdb_init PARAMS ((char *)); #ifdef __CYGWIN__ #include <windows.h> /* for MAX_PATH */ -#include <sys/cygwin.h> /* for cygwin_conv_to_posix_path */ +#include <sys/cygwin.h> /* for cygwin32_conv_to_posix_path */ #endif int @@ -405,7 +411,7 @@ main (argc, argv) if (tmp != NULL) { homedir = (char *) alloca (MAX_PATH+1); - cygwin_conv_to_posix_path (tmp, homedir); + cygwin32_conv_to_posix_path (tmp, homedir); } else homedir = NULL; diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 01e6b04..0cd0063 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -51,12 +51,11 @@ enum mips_fpu_type MIPS_FPU_NONE /* No floating point. */ }; +#ifndef MIPS_DEFAULT_FPU_TYPE +#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_DOUBLE +#endif static int mips_fpu_type_auto = 1; -#ifdef MIPS_DEFAULT_FPU_TYPE static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE; -#else -static enum mips_fpu_type mips_fpu = MIPS_FPU_DOUBLE; -#endif #define MIPS_FPU_TYPE mips_fpu_type /* start-sanitize-carp start-sanitize-vr4xxx */ @@ -2214,7 +2213,7 @@ mips_print_register (regnum, all) REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer); printf_filtered ("(d%d: ", regnum-FP0_REGNUM); - val_print (builtin_type_double, dbuffer, 0, + val_print (builtin_type_double, dbuffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered ("); "); } @@ -2236,14 +2235,14 @@ mips_print_register (regnum, all) int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN); printf_filtered (" (float) "); - val_print (builtin_type_float, raw_buffer + offset, 0, + val_print (builtin_type_float, raw_buffer + offset, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); printf_filtered (", (double) "); - val_print (builtin_type_double, raw_buffer, 0, + val_print (builtin_type_double, raw_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); } else - val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0, + val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0, 0, gdb_stdout, 0, 1, 0, Val_pretty_default); /* Else print as integer in hex. */ else diff --git a/gdb/monitor.c b/gdb/monitor.c index 9dff7b1..9420fe6 100644 --- a/gdb/monitor.c +++ b/gdb/monitor.c @@ -327,14 +327,13 @@ monitor_printf_noecho (va_alist) if (remote_debug > 0) puts_debug ("sent -->", sndbuf, "<--"); #endif -#if EXTRA_RDEBUG - if (remote_debug) + if (EXTRA_RDEBUG + && remote_debug) { char *safe_string = (char *) alloca ((strlen (sndbuf) * 4) + 1); monitor_printable_string (safe_string, sndbuf); printf ("sent[%s]\n", safe_string); } -#endif monitor_write (sndbuf, len); } @@ -372,14 +371,13 @@ monitor_printf (va_alist) if (remote_debug > 0) puts_debug ("sent -->", sndbuf, "<--"); #endif -#if EXTRA_RDEBUG - if (remote_debug) + if (EXTRA_RDEBUG + && remote_debug) { char *safe_string = (char *) alloca ((len * 4) + 1); monitor_printable_string (safe_string, sndbuf); printf ("sent[%s]\n", safe_string); } -#endif monitor_write (sndbuf, len); @@ -400,7 +398,8 @@ monitor_write (buf, buflen) int buflen; { if (SERIAL_WRITE(monitor_desc, buf, buflen)) - fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "SERIAL_WRITE failed: %s\n", + safe_strerror (errno)); } @@ -525,14 +524,13 @@ monitor_expect (string, buf, buflen) int c; extern struct target_ops *targ_ops; -#if EXTRA_RDEBUG - if (remote_debug) + if (EXTRA_RDEBUG + && remote_debug) { char *safe_string = (char *) alloca ((strlen (string) * 4) + 1); monitor_printable_string (safe_string, string); printf ("MON Expecting '%s'\n", safe_string); } -#endif immediate_quit = 1; while (1) @@ -2048,7 +2046,8 @@ monitor_remove_breakpoint (addr, shadow) return 0; } } - fprintf_unfiltered (stderr, "Can't find breakpoint associated with 0x%x\n", addr); + fprintf_unfiltered (gdb_stderr, + "Can't find breakpoint associated with 0x%x\n", addr); return 1; } @@ -2203,10 +2202,14 @@ static void init_base_monitor_ops(void) monitor_ops.to_doc = NULL; monitor_ops.to_open = NULL; monitor_ops.to_close = monitor_close; - monitor_ops.to_attach = NULL; + monitor_ops.to_attach = NULL; + monitor_ops.to_post_attach = NULL; + monitor_ops.to_require_attach = NULL; monitor_ops.to_detach = monitor_detach; + monitor_ops.to_require_detach = NULL; monitor_ops.to_resume = monitor_resume; - monitor_ops.to_wait = monitor_wait; + monitor_ops.to_wait = monitor_wait; + monitor_ops.to_post_wait = NULL; monitor_ops.to_fetch_registers = monitor_fetch_registers; monitor_ops.to_store_registers = monitor_store_registers; monitor_ops.to_prepare_to_store = monitor_prepare_to_store; @@ -2223,11 +2226,30 @@ static void init_base_monitor_ops(void) monitor_ops.to_load = monitor_load; monitor_ops.to_lookup_symbol = 0; monitor_ops.to_create_inferior = monitor_create_inferior; + monitor_ops.to_post_startup_inferior = NULL; + monitor_ops.to_acknowledge_created_inferior = NULL; + monitor_ops.to_clone_and_follow_inferior = NULL; + monitor_ops.to_post_follow_inferior_by_clone = NULL; + monitor_ops.to_insert_fork_catchpoint = NULL; + monitor_ops.to_remove_fork_catchpoint = NULL; + monitor_ops.to_insert_vfork_catchpoint = NULL; + monitor_ops.to_remove_vfork_catchpoint = NULL; + monitor_ops.to_has_forked = NULL; + monitor_ops.to_has_vforked = NULL; + monitor_ops.to_can_follow_vfork_prior_to_exec = NULL; + monitor_ops.to_post_follow_vfork = NULL; + monitor_ops.to_insert_exec_catchpoint = NULL; + monitor_ops.to_remove_exec_catchpoint = NULL; + monitor_ops.to_has_execd = NULL; + monitor_ops.to_reported_exec_events_per_exec_call = NULL; + monitor_ops.to_has_exited = NULL; monitor_ops.to_mourn_inferior = monitor_mourn_inferior; monitor_ops.to_can_run = 0; monitor_ops.to_notice_signals = 0; monitor_ops.to_thread_alive = 0; - monitor_ops.to_stop = monitor_stop; + monitor_ops.to_stop = monitor_stop; + monitor_ops.to_pid_to_exec_file = NULL; + monitor_ops.to_core_file_to_sym_file = NULL; monitor_ops.to_stratum = process_stratum; monitor_ops.DONT_USE = 0; monitor_ops.to_has_all_memory = 1; @@ -2265,3 +2287,5 @@ When enabled, a hashmark \'#\' is displayed.", add_com ("monitor", class_obscure, monitor_command, "Send a command to the debug monitor."); } + + diff --git a/gdb/objfiles.h b/gdb/objfiles.h index d90095d..a124822 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -388,7 +388,12 @@ struct objfile To avoid this penalty for normal object files, we use this flag, whose setting is determined upon symbol table read in. */ -#define OBJF_REORDERED (2 << 1) /* Functions are reordered */ +#define OBJF_REORDERED (1 << 2) /* Functions are reordered */ + +/* Distinguish between an objfile for a shared library and a + "vanilla" objfile. */ + +#define OBJF_SHARED (1 << 3) /* From a shared library */ /* The object file that the main symbol table was loaded from (e.g. the argument to the "symbol-file" or "file" command). */ diff --git a/gdb/ppc-bdm.c b/gdb/ppc-bdm.c index 0dec6d2..f2f28f5 100644 --- a/gdb/ppc-bdm.c +++ b/gdb/ppc-bdm.c @@ -318,10 +318,14 @@ a wiggler, specify wiggler and then the port it is connected to\n\ (e.g. wiggler lpt1)." ; /* to_doc */ bdm_ppc_ops.to_open = bdm_ppc_open; bdm_ppc_ops.to_close = ocd_close; - bdm_ppc_ops.to_attach = NULL; - bdm_ppc_ops.to_detach = ocd_detach; + bdm_ppc_ops.to_attach = NULL; + bdm_ppc_ops.to_post_attach = NULL; + bdm_ppc_ops.to_require_attach = NULL; + bdm_ppc_ops.to_detach = ocd_detach; + bdm_ppc_ops.to_require_detach = NULL; bdm_ppc_ops.to_resume = ocd_resume; bdm_ppc_ops.to_wait = bdm_ppc_wait; + bdm_ppc_ops.to_post_wait = NULL; bdm_ppc_ops.to_fetch_registers = bdm_ppc_fetch_registers; bdm_ppc_ops.to_store_registers = bdm_ppc_store_registers; bdm_ppc_ops.to_prepare_to_store = ocd_prepare_to_store; @@ -338,11 +342,30 @@ a wiggler, specify wiggler and then the port it is connected to\n\ bdm_ppc_ops.to_load = ocd_load; bdm_ppc_ops.to_lookup_symbol = NULL; bdm_ppc_ops.to_create_inferior = ocd_create_inferior; + bdm_ppc_ops.to_post_startup_inferior = NULL; + bdm_ppc_ops.to_acknowledge_created_inferior = NULL; + bdm_ppc_ops.to_clone_and_follow_inferior = NULL; + bdm_ppc_ops.to_post_follow_inferior_by_clone = NULL; + bdm_ppc_ops.to_insert_fork_catchpoint = NULL; + bdm_ppc_ops.to_remove_fork_catchpoint = NULL; + bdm_ppc_ops.to_insert_vfork_catchpoint = NULL; + bdm_ppc_ops.to_remove_vfork_catchpoint = NULL; + bdm_ppc_ops.to_has_forked = NULL; + bdm_ppc_ops.to_has_vforked = NULL; + bdm_ppc_ops.to_can_follow_vfork_prior_to_exec = NULL; + bdm_ppc_ops.to_post_follow_vfork = NULL; + bdm_ppc_ops.to_insert_exec_catchpoint = NULL; + bdm_ppc_ops.to_remove_exec_catchpoint = NULL; + bdm_ppc_ops.to_has_execd = NULL; + bdm_ppc_ops.to_reported_exec_events_per_exec_call = NULL; + bdm_ppc_ops.to_has_exited = NULL; bdm_ppc_ops.to_mourn_inferior = ocd_mourn; bdm_ppc_ops.to_can_run = 0; bdm_ppc_ops.to_notice_signals = 0; bdm_ppc_ops.to_thread_alive = ocd_thread_alive; - bdm_ppc_ops.to_stop = ocd_stop; + bdm_ppc_ops.to_stop = ocd_stop; + bdm_ppc_ops.to_pid_to_exec_file = NULL; + bdm_ppc_ops.to_core_file_to_sym_file = NULL; bdm_ppc_ops.to_stratum = process_stratum; bdm_ppc_ops.DONT_USE = NULL; bdm_ppc_ops.to_has_all_memory = 1; diff --git a/gdb/procfs.c b/gdb/procfs.c index 56c1639..d1fb010 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -534,7 +534,7 @@ static void procfs_attach PARAMS ((char *, int)); static void proc_set_exec_trap PARAMS ((void)); -static int procfs_init_inferior PARAMS ((int)); +static int procfs_init_inferior PARAMS ((int)); static struct procinfo *create_procinfo PARAMS ((int)); @@ -2537,7 +2537,7 @@ NOTES */ -static int +static int procfs_init_inferior (pid) int pid; { @@ -2563,8 +2563,7 @@ procfs_init_inferior (pid) /* One trap to exec the shell, one to exec the program being debugged. */ startup_inferior (2); #endif - - return pid; + return (pid); } /* @@ -5760,10 +5759,14 @@ struct target_ops procfs_ops = { "Unix /proc child process (started by the \"run\" command).", /* to_doc */ procfs_open, /* to_open */ 0, /* to_close */ - procfs_attach, /* to_attach */ + procfs_attach, /* to_attach */ + NULL, /* to_post_attach */ + procfs_attach, /* to_require_attach */ procfs_detach, /* to_detach */ - procfs_resume, /* to_resume */ + procfs_detach, /* to_require_detach */ + procfs_resume, /* to_resume */ procfs_wait, /* to_wait */ + NULL, /* to_post_wait */ procfs_fetch_registers, /* to_fetch_registers */ procfs_store_registers, /* to_store_registers */ procfs_prepare_to_store, /* to_prepare_to_store */ @@ -5780,11 +5783,33 @@ struct target_ops procfs_ops = { 0, /* to_load */ 0, /* to_lookup_symbol */ procfs_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + NULL, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ procfs_mourn_inferior, /* to_mourn_inferior */ procfs_can_run, /* to_can_run */ procfs_notice_signals, /* to_notice_signals */ procfs_thread_alive, /* to_thread_alive */ procfs_stop, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ process_stratum, /* to_stratum */ 0, /* to_next */ 1, /* to_has_all_memory */ diff --git a/gdb/remote-adapt.c b/gdb/remote-adapt.c index 81d9a6e..6da344b 100644 --- a/gdb/remote-adapt.c +++ b/gdb/remote-adapt.c @@ -604,7 +604,7 @@ the baud rate, and the name of the program to run on the remote system."); printf_filtered("Remote debugging using virtual addresses works only\n"); printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n"); if (processor_type != a29k_freeze_mode) { - fprintf_filtered(stderr, + fprintf_filtered(gdb_stderr, "Freeze-mode debugging not available, and can only be done on an A29050.\n"); } } @@ -1238,7 +1238,7 @@ char *save; /* Throw away, let adapt save instructions */ expect_prompt (); return(0); /* Success */ } else { - fprintf_filtered(stderr, + fprintf_filtered(gdb_stderr, "Too many break points, break point not installed\n"); return(1); /* Failure */ } @@ -1372,9 +1372,13 @@ static void init_adapt_ops(void) adapt_ops.to_open = adapt_open; adapt_ops.to_close = adapt_close; adapt_ops.to_attach = adapt_attach; + adapt_ops.to_post_attach = NULL; + adapt_ops.to_require_attach = NULL; adapt_ops.to_detach = adapt_detach; + adapt_ops.to_require_detach = NULL; adapt_ops.to_resume = adapt_resume; adapt_ops.to_wait = adapt_wait; + adapt_ops.to_post_wait = NULL; adapt_ops.to_fetch_registers = adapt_fetch_register; adapt_ops.to_store_registers = adapt_store_register; adapt_ops.to_prepare_to_store = adapt_prepare_to_store; @@ -1390,12 +1394,31 @@ static void init_adapt_ops(void) adapt_ops.to_kill = adapt_kill; adapt_ops.to_load = adapt_load; adapt_ops.to_lookup_symbol = 0; - adapt_ops.to_create_inferior = adapt_create_inferior; + adapt_ops.to_create_inferior = adapt_create_inferior; + adapt_ops.to_post_startup_inferior = NULL; + adapt_ops.to_acknowledge_created_inferior = NULL; + adapt_ops.to_clone_and_follow_inferior = NULL; + adapt_ops.to_post_follow_inferior_by_clone = NULL; + adapt_ops.to_insert_fork_catchpoint = NULL; + adapt_ops.to_remove_fork_catchpoint = NULL; + adapt_ops.to_insert_vfork_catchpoint = NULL; + adapt_ops.to_remove_vfork_catchpoint = NULL; + adapt_ops.to_has_forked = NULL; + adapt_ops.to_has_vforked = NULL; + adapt_ops.to_can_follow_vfork_prior_to_exec = NULL; + adapt_ops.to_post_follow_vfork = NULL; + adapt_ops.to_insert_exec_catchpoint = NULL; + adapt_ops.to_remove_exec_catchpoint = NULL; + adapt_ops.to_has_execd = NULL; + adapt_ops.to_reported_exec_events_per_exec_call = NULL; + adapt_ops.to_has_exited = NULL; adapt_ops.to_mourn_inferior = adapt_mourn; adapt_ops.to_can_run = 0; adapt_ops.to_notice_signals = 0; adapt_ops.to_thread_alive = 0; adapt_ops.to_stop = 0 ; /* process_stratum; */ + adapt_ops.to_pid_to_exec_file = NULL; + adapt_ops.to_core_file_to_sym_file = NULL; adapt_ops.to_stratum = 0; adapt_ops.DONT_USE = 0 ; adapt_ops.to_has_all_memory = 1; diff --git a/gdb/remote-array.c b/gdb/remote-array.c index b250cc4..2b9531a 100644 --- a/gdb/remote-array.c +++ b/gdb/remote-array.c @@ -133,10 +133,14 @@ static void init_array_ops(void) Specify the serial device it is connected to (e.g. /dev/ttya)." ; array_ops.to_open = array_open; array_ops.to_close = array_close; - array_ops.to_attach = NULL; + array_ops.to_attach = NULL; + array_ops.to_post_attach = NULL; + array_ops.to_require_attach = NULL; array_ops.to_detach = array_detach; + array_ops.to_require_detach = NULL; array_ops.to_resume = array_resume; array_ops.to_wait = array_wait; + array_ops.to_post_wait = NULL; array_ops.to_fetch_registers = array_fetch_registers; array_ops.to_store_registers = array_store_registers; array_ops.to_prepare_to_store = array_prepare_to_store; @@ -153,11 +157,30 @@ Specify the serial device it is connected to (e.g. /dev/ttya)." ; array_ops.to_load = 0; array_ops.to_lookup_symbol = 0; array_ops.to_create_inferior = array_create_inferior; + array_ops.to_post_startup_inferior = NULL; + array_ops.to_acknowledge_created_inferior = NULL; + array_ops.to_clone_and_follow_inferior = NULL; + array_ops.to_post_follow_inferior_by_clone = NULL; + array_ops.to_insert_fork_catchpoint = NULL; + array_ops.to_remove_fork_catchpoint = NULL; + array_ops.to_insert_vfork_catchpoint = NULL; + array_ops.to_remove_vfork_catchpoint = NULL; + array_ops.to_has_forked = NULL; + array_ops.to_has_vforked = NULL; + array_ops.to_can_follow_vfork_prior_to_exec = NULL; + array_ops.to_post_follow_vfork = NULL; + array_ops.to_insert_exec_catchpoint = NULL; + array_ops.to_remove_exec_catchpoint = NULL; + array_ops.to_has_execd = NULL; + array_ops.to_reported_exec_events_per_exec_call = NULL; + array_ops.to_has_exited = NULL; array_ops.to_mourn_inferior = array_mourn_inferior; array_ops.to_can_run = 0; array_ops.to_notice_signals = 0; array_ops.to_thread_alive = 0; - array_ops.to_stop = 0; + array_ops.to_stop = 0; + array_ops.to_pid_to_exec_file = NULL; + array_ops.to_core_file_to_sym_file = NULL; array_ops.to_stratum = process_stratum; array_ops.DONT_USE = 0; array_ops.to_has_all_memory = 1; @@ -749,7 +772,7 @@ array_wait (pid, status) i = 0; } fputc_unfiltered (c, gdb_stdout); - fflush (stdout); + gdb_flush (gdb_stdout); } c = SERIAL_READCHAR(tty_desc, timeout); if (c > 0) { @@ -759,7 +782,7 @@ array_wait (pid, status) break; #if 0 fputc_unfiltered (c, gdb_stdout); - fflush (stdout); + gdb_flush (gdb_stdout); #endif } } diff --git a/gdb/remote-bug.c b/gdb/remote-bug.c index b8e664d..7a7244f 100644 --- a/gdb/remote-bug.c +++ b/gdb/remote-bug.c @@ -148,7 +148,7 @@ bug_load (args, fromtty) char *buffer = xmalloc (srec_frame); printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma, s->vma + s->_raw_size); - fflush (stdout); + gdb_flush (gdb_stdout); for (i = 0; i < s->_raw_size; i += srec_frame) { if (srec_frame > s->_raw_size - i) @@ -157,7 +157,7 @@ bug_load (args, fromtty) bfd_get_section_contents (abfd, s, buffer, i, srec_frame); bug_write_memory (s->vma + i, buffer, srec_frame); printf_filtered ("*"); - fflush (stdout); + gdb_flush (gdb_stdout); } printf_filtered ("\n"); free (buffer); @@ -335,7 +335,7 @@ bug_wait (pid, status) case -1: /* trouble */ default: - fprintf_filtered (stderr, + fprintf_filtered (gdb_stderr, "Trouble reading target during wait\n"); break; } @@ -922,7 +922,7 @@ bug_insert_breakpoint (addr, save) } else { - fprintf_filtered (stderr, + fprintf_filtered (gdb_stderr, "Too many break points, break point not installed\n"); return(1); } @@ -971,9 +971,13 @@ static void init_bug_ops(void) bug_ops.to_open = bug_open; bug_ops.to_close = gr_close; bug_ops.to_attach = 0; + bug_ops.to_post_attach = NULL; + bug_ops.to_require_attach = NULL; bug_ops.to_detach = gr_detach; + bug_ops.to_require_detach = NULL; bug_ops.to_resume = bug_resume; bug_ops.to_wait = bug_wait; + bug_ops.to_post_wait = NULL; bug_ops.to_fetch_registers = bug_fetch_register; bug_ops.to_store_registers = bug_store_register; bug_ops.to_prepare_to_store = gr_prepare_to_store; @@ -990,11 +994,30 @@ static void init_bug_ops(void) bug_ops.to_load = bug_load; bug_ops.to_lookup_symbol = 0; bug_ops.to_create_inferior = gr_create_inferior; + bug_ops.to_post_startup_inferior = NULL; + bug_ops.to_acknowledge_created_inferior = NULL; + bug_ops.to_clone_and_follow_inferior = NULL; + bug_ops.to_post_follow_inferior_by_clone = NULL; + bug_ops.to_insert_fork_catchpoint = NULL; + bug_ops.to_remove_fork_catchpoint = NULL; + bug_ops.to_insert_vfork_catchpoint = NULL; + bug_ops.to_remove_vfork_catchpoint = NULL; + bug_ops.to_has_forked = NULL; + bug_ops.to_has_vforked = NULL; + bug_ops.to_can_follow_vfork_prior_to_exec = NULL; + bug_ops.to_post_follow_vfork = NULL; + bug_ops.to_insert_exec_catchpoint = NULL; + bug_ops.to_remove_exec_catchpoint = NULL; + bug_ops.to_has_execd = NULL; + bug_ops.to_reported_exec_events_per_exec_call = NULL; + bug_ops.to_has_exited = NULL; bug_ops.to_mourn_inferior = gr_mourn; bug_ops.to_can_run = 0; bug_ops.to_notice_signals = 0; bug_ops.to_thread_alive = 0 ; bug_ops.to_stop = 0; + bug_ops.to_pid_to_exec_file = NULL; + bug_ops.to_core_file_to_sym_file = NULL; bug_ops.to_stratum = process_stratum ; bug_ops.DONT_USE = 0; bug_ops.to_has_all_memory = 1; diff --git a/gdb/remote-e7000.c b/gdb/remote-e7000.c index b252084..c8caf18 100644 --- a/gdb/remote-e7000.c +++ b/gdb/remote-e7000.c @@ -33,6 +33,7 @@ #include "defs.h" #include "gdbcore.h" +#include "gdbarch.h" #include "inferior.h" #include "target.h" #include "wait.h" @@ -2172,10 +2173,14 @@ target e7000 /dev/ttya 9600\n\ target e7000 foobar" ; e7000_ops.to_open = e7000_open; e7000_ops.to_close = e7000_close; - e7000_ops.to_attach = 0; - e7000_ops.to_detach = e7000_detach; + e7000_ops.to_attach = 0; + e7000_ops.to_post_attach = NULL; + e7000_ops.to_require_attach = NULL; + e7000_ops.to_detach = e7000_detach; + e7000_ops.to_require_detach = NULL; e7000_ops.to_resume = e7000_resume; - e7000_ops.to_wait = e7000_wait; + e7000_ops.to_wait = e7000_wait; + e7000_ops.to_post_wait = NULL; e7000_ops.to_fetch_registers = e7000_fetch_register; e7000_ops.to_store_registers = e7000_store_register; e7000_ops.to_prepare_to_store = e7000_prepare_to_store; @@ -2192,11 +2197,30 @@ target e7000 foobar" ; e7000_ops.to_load = e7000_load; e7000_ops.to_lookup_symbol = 0; e7000_ops.to_create_inferior = e7000_create_inferior; + e7000_ops.to_post_startup_inferior = NULL; + e7000_ops.to_acknowledge_created_inferior = NULL; + e7000_ops.to_clone_and_follow_inferior = NULL; + e7000_ops.to_post_follow_inferior_by_clone = NULL; + e7000_ops.to_insert_fork_catchpoint = NULL; + e7000_ops.to_remove_fork_catchpoint = NULL; + e7000_ops.to_insert_vfork_catchpoint = NULL; + e7000_ops.to_remove_vfork_catchpoint = NULL; + e7000_ops.to_has_forked = NULL; + e7000_ops.to_has_vforked = NULL; + e7000_ops.to_can_follow_vfork_prior_to_exec = NULL; + e7000_ops.to_post_follow_vfork = NULL; + e7000_ops.to_insert_exec_catchpoint = NULL; + e7000_ops.to_remove_exec_catchpoint = NULL; + e7000_ops.to_has_execd = NULL; + e7000_ops.to_reported_exec_events_per_exec_call = NULL; + e7000_ops.to_has_exited = NULL; e7000_ops.to_mourn_inferior = e7000_mourn_inferior; e7000_ops.to_can_run = 0; e7000_ops.to_notice_signals = 0; e7000_ops.to_thread_alive = 0; - e7000_ops.to_stop = e7000_stop; + e7000_ops.to_stop = e7000_stop; + e7000_ops.to_pid_to_exec_file = NULL; + e7000_ops.to_core_file_to_sym_file = NULL; e7000_ops.to_stratum = process_stratum; e7000_ops.DONT_USE = 0; e7000_ops.to_has_all_memory = 1; diff --git a/gdb/remote-eb.c b/gdb/remote-eb.c index 458750e..09c3911 100644 --- a/gdb/remote-eb.c +++ b/gdb/remote-eb.c @@ -987,9 +987,13 @@ target amd-eb /dev/ttya 9600 demo", eb_ops.to_open = eb_open; eb_ops.to_close = eb_close; eb_ops.to_attach = 0; + eb_ops.to_post_attach = NULL; + eb_ops.to_require_attach = NULL; eb_ops.to_detach = eb_detach; + eb_ops.to_require_detach = NULL; eb_ops.to_resume = eb_resume; eb_ops.to_wait = eb_wait; + eb_ops.to_post_wait = NULL; eb_ops.to_fetch_registers = eb_fetch_register; eb_ops.to_store_registers = eb_store_register; eb_ops.to_prepare_to_store = eb_prepare_to_store; @@ -1006,11 +1010,30 @@ target amd-eb /dev/ttya 9600 demo", eb_ops.to_load = generic_load; /* load */ eb_ops.to_lookup_symbol = 0; /* lookup_symbol */ eb_ops.to_create_inferior = eb_create_inferior; + eb_ops.to_post_startup_inferior = NULL; + eb_ops.to_acknowledge_created_inferior = NULL; + eb_ops.to_clone_and_follow_inferior = NULL; + eb_ops.to_post_follow_inferior_by_clone = NULL; + eb_ops.to_insert_fork_catchpoint = NULL; + eb_ops.to_remove_fork_catchpoint = NULL; + eb_ops.to_insert_vfork_catchpoint = NULL; + eb_ops.to_remove_vfork_catchpoint = NULL; + eb_ops.to_has_forked = NULL; + eb_ops.to_has_vforked = NULL; + eb_ops.to_can_follow_vfork_prior_to_exec = NULL; + eb_ops.to_post_follow_vfork = NULL; + eb_ops.to_insert_exec_catchpoint = NULL; + eb_ops.to_remove_exec_catchpoint = NULL; + eb_ops.to_has_execd = NULL; + eb_ops.to_reported_exec_events_per_exec_call = NULL; + eb_ops.to_has_exited = NULL; eb_ops.to_mourn_inferior = eb_mourn_inferior; eb_ops.to_can_run = 0; /* can_run */ eb_ops.to_notice_signals = 0; /* notice_signals */ eb_ops.to_thread_alive = 0; /* thread-alive */ eb_ops.to_stop = 0; /* to_stop */ + eb_ops.to_pid_to_exec_file = NULL; + eb_ops.to_core_file_to_sym_file = NULL; eb_ops.to_stratum = process_stratum; eb_ops.DONT_USE = 0; /* next */ eb_ops.to_has_all_memory = 1; diff --git a/gdb/remote-es.c b/gdb/remote-es.c index 3ea2e7b..7a63e41 100644 --- a/gdb/remote-es.c +++ b/gdb/remote-es.c @@ -2051,10 +2051,14 @@ static void init_es1800_ops(void) Specify the serial device it is connected to (e.g. /dev/ttya)." ; es1800_ops.to_open = es1800_open; es1800_ops.to_close = es1800_close; - es1800_ops.to_attach = es1800_attach; + es1800_ops.to_attach = es1800_attach; + es1800_ops.to_post_attach = NULL; + es1800_ops.to_require_attach = NULL; es1800_ops.to_detach = es1800_detach; + es1800_ops.to_require_detach = NULL; es1800_ops.to_resume = es1800_resume; - es1800_ops.to_wait = NULL; + es1800_ops.to_wait = NULL; + es1800_ops.to_post_wait = NULL; es1800_ops.to_fetch_registers = NULL; es1800_ops.to_store_registers = NULL; es1800_ops.to_prepare_to_store = es1800_prepare_to_store; @@ -2071,11 +2075,30 @@ Specify the serial device it is connected to (e.g. /dev/ttya)." ; es1800_ops.to_load = es1800_load; es1800_ops.to_lookup_symbol = NULL; es1800_ops.to_create_inferior = es1800_create_inferior; + es1800_ops.to_post_startup_inferior = NULL; + es1800_ops.to_acknowledge_created_inferior = NULL; + es1800_ops.to_clone_and_follow_inferior = NULL; + es1800_ops.to_post_follow_inferior_by_clone = NULL; + es1800_ops.to_insert_fork_catchpoint = NULL; + es1800_ops.to_remove_fork_catchpoint = NULL; + es1800_ops.to_insert_vfork_catchpoint = NULL; + es1800_ops.to_remove_vfork_catchpoint = NULL; + es1800_ops.to_has_forked = NULL; + es1800_ops.to_has_vforked = NULL; + es1800_ops.to_can_follow_vfork_prior_to_exec = NULL; + es1800_ops.to_post_follow_vfork = NULL; + es1800_ops.to_insert_exec_catchpoint = NULL; + es1800_ops.to_remove_exec_catchpoint = NULL; + es1800_ops.to_has_execd = NULL; + es1800_ops.to_reported_exec_events_per_exec_call = NULL; + es1800_ops.to_has_exited = NULL; es1800_ops.to_mourn_inferior = NULL; es1800_ops.to_can_run = 0; es1800_ops.to_notice_signals = 0; es1800_ops.to_thread_alive = 0; - es1800_ops.to_stop = 0; + es1800_ops.to_stop = 0; + es1800_ops.to_pid_to_exec_file = NULL; + es1800_ops.to_core_file_to_sym_file = NULL; es1800_ops.to_stratum = core_stratum; es1800_ops.DONT_USE = 0; es1800_ops.to_has_all_memory = 0; @@ -2093,47 +2116,70 @@ Specify the serial device it is connected to (e.g. /dev/ttya)." ; struct target_ops es1800_child_ops ; static void init_es1800_child_ops(void) { - es1800_ops.to_shortname = "es1800_process"; - es1800_ops.to_longname = "Remote serial target in ES1800-emulator protocol"; - es1800_ops.to_doc = "Remote debugging on the es1800 emulator via a serial line.\n\ + es1800_child_ops.to_shortname = "es1800_process"; + es1800_child_ops.to_longname = "Remote serial target in ES1800-emulator protocol"; + es1800_child_ops.to_doc = "Remote debugging on the es1800 emulator via a serial line.\n\ Specify the serial device it is connected to (e.g. /dev/ttya)."; - es1800_ops.to_open = es1800_child_open; - es1800_ops.to_close = NULL; - es1800_ops.to_attach = es1800_attach; - es1800_ops.to_detach = es1800_child_detach; - es1800_ops.to_resume = es1800_resume; - es1800_ops.to_wait = es1800_wait; - es1800_ops.to_fetch_registers = es1800_fetch_register; - es1800_ops.to_store_registers = es1800_store_register; - es1800_ops.to_prepare_to_store = es1800_prepare_to_store; - es1800_ops.to_xfer_memory = es1800_xfer_inferior_memory; - es1800_ops.to_files_info = es1800_files_info; - es1800_ops.to_insert_breakpoint = es1800_insert_breakpoint; - es1800_ops.to_remove_breakpoint = es1800_remove_breakpoint; - es1800_ops.to_terminal_init = NULL; - es1800_ops.to_terminal_inferior = NULL; - es1800_ops.to_terminal_ours_for_output = NULL; - es1800_ops.to_terminal_ours = NULL; - es1800_ops.to_terminal_info = NULL; - es1800_ops.to_kill = es1800_kill; - es1800_ops.to_load = es1800_load; - es1800_ops.to_lookup_symbol = NULL; - es1800_ops.to_create_inferior = es1800_create_inferior; - es1800_ops.to_mourn_inferior = es1800_mourn_inferior; - es1800_ops.to_can_run = 0; - es1800_ops.to_notice_signals = 0; - es1800_ops.to_thread_alive = 0; - es1800_ops.to_stop = 0; - es1800_ops.to_stratum = process_stratum; - es1800_ops.DONT_USE = 0; - es1800_ops.to_has_all_memory = 1; - es1800_ops.to_has_memory = 1; - es1800_ops.to_has_stack = 1; - es1800_ops.to_has_registers = 1; - es1800_ops.to_has_execution = 1; - es1800_ops.to_sections = NULL; - es1800_ops.to_sections_end = NULL; - es1800_ops.to_magic = OPS_MAGIC; + es1800_child_ops.to_open = es1800_child_open; + es1800_child_ops.to_close = NULL; + es1800_child_ops.to_attach = es1800_attach; + es1800_child_ops.to_post_attach = NULL; + es1800_child_ops.to_require_attach = NULL; + es1800_child_ops.to_detach = es1800_child_detach; + es1800_child_ops.to_require_detach = NULL; + es1800_child_ops.to_resume = es1800_resume; + es1800_child_ops.to_wait = es1800_wait; + es1800_child_ops.to_post_wait = NULL; + es1800_child_ops.to_fetch_registers = es1800_fetch_register; + es1800_child_ops.to_store_registers = es1800_store_register; + es1800_child_ops.to_prepare_to_store = es1800_prepare_to_store; + es1800_child_ops.to_xfer_memory = es1800_xfer_inferior_memory; + es1800_child_ops.to_files_info = es1800_files_info; + es1800_child_ops.to_insert_breakpoint = es1800_insert_breakpoint; + es1800_child_ops.to_remove_breakpoint = es1800_remove_breakpoint; + es1800_child_ops.to_terminal_init = NULL; + es1800_child_ops.to_terminal_inferior = NULL; + es1800_child_ops.to_terminal_ours_for_output = NULL; + es1800_child_ops.to_terminal_ours = NULL; + es1800_child_ops.to_terminal_info = NULL; + es1800_child_ops.to_kill = es1800_kill; + es1800_child_ops.to_load = es1800_load; + es1800_child_ops.to_lookup_symbol = NULL; + es1800_child_ops.to_create_inferior = es1800_create_inferior; + es1800_child_ops.to_post_startup_inferior = NULL; + es1800_child_ops.to_acknowledge_created_inferior = NULL; + es1800_child_ops.to_clone_and_follow_inferior = NULL; + es1800_child_ops.to_post_follow_inferior_by_clone = NULL; + es1800_child_ops.to_insert_fork_catchpoint = NULL; + es1800_child_ops.to_remove_fork_catchpoint = NULL; + es1800_child_ops.to_insert_vfork_catchpoint = NULL; + es1800_child_ops.to_remove_vfork_catchpoint = NULL; + es1800_child_ops.to_has_forked = NULL; + es1800_child_ops.to_has_vforked = NULL; + es1800_child_ops.to_can_follow_vfork_prior_to_exec = NULL; + es1800_child_ops.to_post_follow_vfork = NULL; + es1800_child_ops.to_insert_exec_catchpoint = NULL; + es1800_child_ops.to_remove_exec_catchpoint = NULL; + es1800_child_ops.to_has_execd = NULL; + es1800_child_ops.to_reported_exec_events_per_exec_call = NULL; + es1800_child_ops.to_has_exited = NULL; + es1800_child_ops.to_mourn_inferior = es1800_mourn_inferior; + es1800_child_ops.to_can_run = 0; + es1800_child_ops.to_notice_signals = 0; + es1800_child_ops.to_thread_alive = 0; + es1800_child_ops.to_stop = 0; + es1800_child_ops.to_pid_to_exec_file = NULL; + es1800_child_ops.to_core_file_to_sym_file = NULL; + es1800_child_ops.to_stratum = process_stratum; + es1800_child_ops.DONT_USE = 0; + es1800_child_ops.to_has_all_memory = 1; + es1800_child_ops.to_has_memory = 1; + es1800_child_ops.to_has_stack = 1; + es1800_child_ops.to_has_registers = 1; + es1800_child_ops.to_has_execution = 1; + es1800_child_ops.to_sections = NULL; + es1800_child_ops.to_sections_end = NULL; + es1800_child_ops.to_magic = OPS_MAGIC; } void diff --git a/gdb/remote-hms.c b/gdb/remote-hms.c index 63a985e..94e36f9 100644 --- a/gdb/remote-hms.c +++ b/gdb/remote-hms.c @@ -157,7 +157,6 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; add_target (&hms_ops); } - #if 0 /* This is kept here because we used to support the H8/500 in this module, and I haven't done the H8/500 yet */ @@ -1330,9 +1329,13 @@ by a serial line."; hms_ops.to_open = hms_open; hms_ops.to_close = hms_close; hms_ops.to_attach = 0; + hms_ops.to_post_attach = NULL; + hms_ops.to_require_attach = NULL; hms_ops.to_detach = hms_detach; + hms_ops.to_require_detach = NULL; hms_ops.to_resume = hms_resume; hms_ops.to_wait = hms_wait; + hms_ops.to_post_wait = NULL; hms_ops.to_fetch_registers = hms_fetch_register; hms_ops.to_store_registers = hms_store_register; hms_ops.to_prepare_to_store = hms_prepare_to_store; @@ -1349,11 +1352,30 @@ by a serial line."; hms_ops.to_load = generic_load; hms_ops.to_lookup_symbol = 0; hms_ops.to_create_inferior = hms_create_inferior; + hms_ops.to_post_startup_inferior = NULL; + hms_ops.to_acknowledge_created_inferior = NULL; + hms_ops.to_clone_and_follow_inferior = NULL; + hms_ops.to_post_follow_inferior_by_clone = NULL; + hms_ops.to_insert_fork_catchpoint = NULL; + hms_ops.to_remove_fork_catchpoint = NULL; + hms_ops.to_insert_vfork_catchpoint = NULL; + hms_ops.to_remove_vfork_catchpoint = NULL; + hms_ops.to_has_forked = NULL; + hms_ops.to_has_vforked = NULL; + hms_ops.to_can_follow_vfork_prior_to_exec = NULL; + hms_ops.to_post_follow_vfork = NULL; + hms_ops.to_insert_exec_catchpoint = NULL; + hms_ops.to_remove_exec_catchpoint = NULL; + hms_ops.to_has_execd = NULL; + hms_ops.to_reported_exec_events_per_exec_call = NULL; + hms_ops.to_has_exited = NULL; hms_ops.to_mourn_inferior = hms_mourn; hms_ops.to_can_run = 0; hms_ops.to_notice_signals = 0; hms_ops.to_thread_alive = 0; - hms_ops.to_stop = 0; + hms_ops.to_stop = 0; + hms_ops.to_pid_to_exec_file = NULL; + hms_ops.to_core_file_to_sym_file = NULL; hms_ops.to_stratum = process_stratum; hms_ops.DONT_USE = 0; hms_ops.to_has_all_memory = 1; diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c index 8b2299e..769834a 100644 --- a/gdb/remote-mips.c +++ b/gdb/remote-mips.c @@ -638,7 +638,8 @@ mips_getstring (string, n) c = SERIAL_READCHAR (mips_desc, 2); if (c == SERIAL_TIMEOUT) { - fprintf_unfiltered (stderr, "Failed to read %d characters from target (TIMEOUT)\n", n); + fprintf_unfiltered (gdb_stderr, + "Failed to read %d characters from target (TIMEOUT)\n", n); return 0; } @@ -2163,7 +2164,7 @@ mips_xfer_memory (memaddr, myaddr, len, write, ignore) if (i % 256 == 255) { printf_unfiltered ("*"); - fflush (stdout); + gdb_flush (gdb_stdout); } if (status) { @@ -2366,7 +2367,8 @@ pmon_insert_breakpoint (addr, contents_cache) tbuff[2] = '\0'; /* terminate the string */ if (sscanf (tbuff, "%d", &bpnum) != 1) { - fprintf_unfiltered (stderr, "Invalid decimal breakpoint number from target: %s\n", tbuff); + fprintf_unfiltered (gdb_stderr, + "Invalid decimal breakpoint number from target: %s\n", tbuff); return 1; } @@ -2384,19 +2386,21 @@ pmon_insert_breakpoint (addr, contents_cache) if (sscanf (tbuff, "0x%08x", &bpaddr) != 1) { - fprintf_unfiltered (stderr, "Invalid hex address from target: %s\n", tbuff); + fprintf_unfiltered (gdb_stderr, + "Invalid hex address from target: %s\n", tbuff); return 1; } if (bpnum >= PMON_MAX_BP) { - fprintf_unfiltered (stderr, "Error: Returned breakpoint number %d outside acceptable range (0..%d)\n", + fprintf_unfiltered (gdb_stderr, + "Error: Returned breakpoint number %d outside acceptable range (0..%d)\n", bpnum, PMON_MAX_BP - 1); return 1; } if (bpaddr != addr) - fprintf_unfiltered (stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr); + fprintf_unfiltered (gdb_stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr); mips_pmon_bp_info[bpnum] = bpaddr; @@ -2427,7 +2431,7 @@ pmon_remove_breakpoint (addr, contents_cache) if (bpnum >= PMON_MAX_BP) { - fprintf_unfiltered (stderr, + fprintf_unfiltered (gdb_stderr, "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n", paddr_nz (addr)); return 1; @@ -2606,14 +2610,14 @@ check_lsi_error (addr, rerrflg) if ((err->code & rerrflg) == err->code) { found = 1; - fprintf_unfiltered (stderr, + fprintf_unfiltered (gdb_stderr, "common_breakpoint (0x%s): Warning: %s\n", saddr, err->string); } } if (!found) - fprintf_unfiltered (stderr, + fprintf_unfiltered (gdb_stderr, "common_breakpoint (0x%s): Unknown warning: 0x%x\n", saddr, rerrflg); @@ -2626,14 +2630,14 @@ check_lsi_error (addr, rerrflg) { if ((err->code & rerrflg) == err->code) { - fprintf_unfiltered (stderr, + fprintf_unfiltered (gdb_stderr, "common_breakpoint (0x%s): Error: %s\n", saddr, err->string); return 1; } } - fprintf_unfiltered (stderr, + fprintf_unfiltered (gdb_stderr, "common_breakpoint (0x%s): Unknown error: 0x%x\n", saddr, rerrflg); @@ -2830,7 +2834,8 @@ common_breakpoint (set, addr, len, type) if (mips_monitor == MON_DDB) rresponse = rerrflg; if (rresponse != 22) /* invalid argument */ - fprintf_unfiltered (stderr, "common_breakpoint (0x%s): Got error: 0x%x\n", + fprintf_unfiltered (gdb_stderr, + "common_breakpoint (0x%s): Got error: 0x%x\n", paddr_nz (addr), rresponse); return 1; } @@ -3070,11 +3075,13 @@ pmon_makeb64 (v, p, n, chksum) int count = (n / 6); if ((n % 12) != 0) { - fprintf_unfiltered(stderr,"Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n",n,(n == 1)?"":"s"); + fprintf_unfiltered(gdb_stderr, + "Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n",n,(n == 1)?"":"s"); return(0); } if (n > 36) { - fprintf_unfiltered(stderr,"Fast encoding cannot process more than 36bits at the moment: %dbits\n",n); + fprintf_unfiltered(gdb_stderr, + "Fast encoding cannot process more than 36bits at the moment: %dbits\n",n); return(0); } diff --git a/gdb/remote-mm.c b/gdb/remote-mm.c index 2604279..c10f97e 100644 --- a/gdb/remote-mm.c +++ b/gdb/remote-mm.c @@ -345,7 +345,7 @@ erroid: printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n") ; if (processor_type != a29k_freeze_mode) { - fprintf_filtered(stderr, + fprintf_filtered(gdb_stderr, "Freeze-mode debugging not available, and can only be done on an A29050.\n"); } @@ -1015,7 +1015,7 @@ int from_tty; /* You may need to do an init_target_mm() */ /* init_target_mm(?,?,?,?,?,?,?,?); */ immediate_quit--; - /* symbol_file_add (arg_string, from_tty, text_addr, 0, 0); */ + /* symbol_file_add (arg_string, from_tty, text_addr, 0, 0, 0, 0); */ #endif } @@ -1597,9 +1597,13 @@ static void init_mm_ops(void) mm_ops.to_open = mm_open; mm_ops.to_close = mm_close; mm_ops.to_attach = mm_attach; + mm_ops.to_post_attach = NULL; + mm_ops.to_require_attach = NULL; mm_ops.to_detach = mm_detach; + mm_ops.to_require_detach = NULL; mm_ops.to_resume = mm_resume; mm_ops.to_wait = mm_wait; + mm_ops.to_post_wait = NULL; mm_ops.to_fetch_registers = mm_fetch_registers; mm_ops.to_store_registers = mm_store_registers; mm_ops.to_prepare_to_store = mm_prepare_to_store; @@ -1615,12 +1619,31 @@ static void init_mm_ops(void) mm_ops.to_kill = mm_kill; mm_ops.to_load = mm_load; mm_ops.to_lookup_symbol = 0; - mm_ops.to_create_inferior = mm_create_inferior; + mm_ops.to_create_inferior = mm_create_inferior; + mm_ops.to_post_startup_inferior = NULL; + mm_ops.to_acknowledge_created_inferior = NULL; + mm_ops.to_clone_and_follow_inferior = NULL; + mm_ops.to_post_follow_inferior_by_clone = NULL; + mm_ops.to_insert_fork_catchpoint = NULL; + mm_ops.to_remove_fork_catchpoint = NULL; + mm_ops.to_insert_vfork_catchpoint = NULL; + mm_ops.to_remove_vfork_catchpoint = NULL; + mm_ops.to_has_forked = NULL; + mm_ops.to_has_vforked = NULL; + mm_ops.to_can_follow_vfork_prior_to_exec = NULL; + mm_ops.to_post_follow_vfork = NULL; + mm_ops.to_insert_exec_catchpoint = NULL; + mm_ops.to_remove_exec_catchpoint = NULL; + mm_ops.to_has_execd = NULL; + mm_ops.to_reported_exec_events_per_exec_call = NULL; + mm_ops.to_has_exited = NULL; mm_ops.to_mourn_inferior = mm_mourn; mm_ops.to_can_run = 0; mm_ops.to_notice_signals = 0; mm_ops.to_thread_alive = 0; mm_ops.to_stop = 0; + mm_ops.to_pid_to_exec_file = NULL; + mm_ops.to_core_file_to_sym_file = NULL; mm_ops.to_stratum = process_stratum; mm_ops.DONT_USE = 0; mm_ops.to_has_all_memory = 1; diff --git a/gdb/remote-nindy.c b/gdb/remote-nindy.c index 17096f9..7853ae2 100644 --- a/gdb/remote-nindy.c +++ b/gdb/remote-nindy.c @@ -128,7 +128,7 @@ extern char *mktemp(); extern void generic_mourn_inferior (); extern struct target_ops nindy_ops; -extern GDB_FILE *instream; +extern FILE *instream; extern char ninStopWhy (); extern int ninMemGet (); @@ -779,9 +779,13 @@ specified when you started GDB." ; nindy_ops.to_open = nindy_open; nindy_ops.to_close = nindy_close; nindy_ops.to_attach = 0; + nindy_ops.to_post_attach = NULL; + nindy_ops.to_require_attach = NULL; nindy_ops.to_detach = nindy_detach; + nindy_ops.to_require_detach = NULL; nindy_ops.to_resume = nindy_resume; nindy_ops.to_wait = nindy_wait; + nindy_ops.to_post_wait = NULL; nindy_ops.to_fetch_registers = nindy_fetch_registers; nindy_ops.to_store_registers = nindy_store_registers; nindy_ops.to_prepare_to_store = nindy_prepare_to_store; @@ -798,11 +802,30 @@ specified when you started GDB." ; nindy_ops.to_load = nindy_load; nindy_ops.to_lookup_symbol = 0; /* lookup_symbol */ nindy_ops.to_create_inferior = nindy_create_inferior; + nindy_ops.to_post_startup_inferior = NULL; + nindy_ops.to_acknowledge_created_inferior = NULL; + nindy_ops.to_clone_and_follow_inferior = NULL; + nindy_ops.to_post_follow_inferior_by_clone = NULL; + nindy_ops.to_insert_fork_catchpoint = NULL; + nindy_ops.to_remove_fork_catchpoint = NULL; + nindy_ops.to_insert_vfork_catchpoint = NULL; + nindy_ops.to_remove_vfork_catchpoint = NULL; + nindy_ops.to_has_forked = NULL; + nindy_ops.to_has_vforked = NULL; + nindy_ops.to_can_follow_vfork_prior_to_exec = NULL; + nindy_ops.to_post_follow_vfork = NULL; + nindy_ops.to_insert_exec_catchpoint = NULL; + nindy_ops.to_remove_exec_catchpoint = NULL; + nindy_ops.to_has_execd = NULL; + nindy_ops.to_reported_exec_events_per_exec_call = NULL; + nindy_ops.to_has_exited = NULL; nindy_ops.to_mourn_inferior = nindy_mourn_inferior; nindy_ops.to_can_run = 0; /* can_run */ nindy_ops.to_notice_signals = 0; /* notice_signals */ nindy_ops.to_thread_alive = 0; /* to_thread_alive */ nindy_ops.to_stop = 0; /* to_stop */ + nindy_ops.to_pid_to_exec_file = NULL; + nindy_ops.to_core_file_to_sym_file = NULL; nindy_ops.to_stratum = process_stratum; nindy_ops.DONT_USE = 0; /* next */ nindy_ops.to_has_all_memory = 1; diff --git a/gdb/remote-nrom.c b/gdb/remote-nrom.c index d3b3d86..1410d36 100644 --- a/gdb/remote-nrom.c +++ b/gdb/remote-nrom.c @@ -276,10 +276,14 @@ static void init_nrom_ops(void) nrom_ops.to_doc = "Remote debug using a NetROM over Ethernet"; nrom_ops.to_open = nrom_open; nrom_ops.to_close = nrom_close; - nrom_ops.to_attach = NULL; - nrom_ops.to_detach = NULL; + nrom_ops.to_attach = NULL; + nrom_ops.to_post_attach = NULL; + nrom_ops.to_require_attach = NULL; + nrom_ops.to_detach = NULL; + nrom_ops.to_require_detach = NULL; nrom_ops.to_resume = NULL; - nrom_ops.to_wait = NULL; + nrom_ops.to_wait = NULL; + nrom_ops.to_post_wait = NULL; nrom_ops.to_fetch_registers = NULL; nrom_ops.to_store_registers = NULL; nrom_ops.to_prepare_to_store = NULL; @@ -295,12 +299,31 @@ static void init_nrom_ops(void) nrom_ops.to_kill = nrom_kill; nrom_ops.to_load = nrom_load; nrom_ops.to_lookup_symbol = NULL; - nrom_ops.to_create_inferior = NULL; + nrom_ops.to_create_inferior = NULL; + nrom_ops.to_post_startup_inferior = NULL; + nrom_ops.to_acknowledge_created_inferior = NULL; + nrom_ops.to_clone_and_follow_inferior = NULL; + nrom_ops.to_post_follow_inferior_by_clone = NULL; + nrom_ops.to_insert_fork_catchpoint = NULL; + nrom_ops.to_remove_fork_catchpoint = NULL; + nrom_ops.to_insert_vfork_catchpoint = NULL; + nrom_ops.to_remove_vfork_catchpoint = NULL; + nrom_ops.to_has_forked = NULL; + nrom_ops.to_has_vforked = NULL; + nrom_ops.to_can_follow_vfork_prior_to_exec = NULL; + nrom_ops.to_post_follow_vfork = NULL; + nrom_ops.to_insert_exec_catchpoint = NULL; + nrom_ops.to_remove_exec_catchpoint = NULL; + nrom_ops.to_has_execd = NULL; + nrom_ops.to_reported_exec_events_per_exec_call = NULL; + nrom_ops.to_has_exited = NULL; nrom_ops.to_mourn_inferior = nrom_mourn; nrom_ops.to_can_run = NULL; nrom_ops.to_notice_signals = 0; nrom_ops.to_thread_alive = 0; nrom_ops.to_stop = 0; + nrom_ops.to_pid_to_exec_file = NULL; + nrom_ops.to_core_file_to_sym_file = NULL; nrom_ops.to_stratum = download_stratum; nrom_ops.DONT_USE = NULL; nrom_ops.to_has_all_memory = 1; diff --git a/gdb/remote-os9k.c b/gdb/remote-os9k.c index acdc847..ca2f747 100644 --- a/gdb/remote-os9k.c +++ b/gdb/remote-os9k.c @@ -1155,9 +1155,13 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", rombug_ops.to_open = rombug_open; rombug_ops.to_close = rombug_close; rombug_ops.to_attach = 0; + rombug_ops.to_post_attach = NULL; + rombug_ops.to_require_attach = NULL; rombug_ops.to_detach = rombug_detach; + rombug_ops.to_require_detach = NULL; rombug_ops.to_resume = rombug_resume; rombug_ops.to_wait = rombug_wait; + rombug_ops.to_post_wait = NULL; rombug_ops.to_fetch_registers = rombug_fetch_register; rombug_ops.to_store_registers = rombug_store_register; rombug_ops.to_prepare_to_store = rombug_prepare_to_store; @@ -1174,11 +1178,30 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", rombug_ops.to_load = rombug_load; /* load */ rombug_ops.to_lookup_symbol = rombug_link; /* lookup_symbol */ rombug_ops.to_create_inferior = rombug_create_inferior; + rombug_ops.to_post_startup_inferior = NULL; + rombug_ops.to_acknowledge_created_inferior = NULL; + rombug_ops.to_clone_and_follow_inferior = NULL; + rombug_ops.to_post_follow_inferior_by_clone = NULL; + rombug_ops.to_insert_fork_catchpoint = NULL; + rombug_ops.to_remove_fork_catchpoint = NULL; + rombug_ops.to_insert_vfork_catchpoint = NULL; + rombug_ops.to_remove_vfork_catchpoint = NULL; + rombug_ops.to_has_forked = NULL; + rombug_ops.to_has_vforked = NULL; + rombug_ops.to_can_follow_vfork_prior_to_exec = NULL; + rombug_ops.to_post_follow_vfork = NULL; + rombug_ops.to_insert_exec_catchpoint = NULL; + rombug_ops.to_remove_exec_catchpoint = NULL; + rombug_ops.to_has_execd = NULL; + rombug_ops.to_reported_exec_events_per_exec_call = NULL; + rombug_ops.to_has_exited = NULL; rombug_ops.to_mourn_inferior = rombug_mourn_inferior; rombug_ops.to_can_run = 0; /* can_run */ rombug_ops.to_notice_signals = 0; /* notice_signals */ rombug_ops.to_thread_alive = 0; rombug_ops.to_stop = 0; /* to_stop */ + rombug_ops.to_pid_to_exec_file = NULL; + rombug_ops.to_core_file_to_sym_file = NULL; rombug_ops.to_stratum = process_stratum; rombug_ops.DONT_USE = 0; /* next */ rombug_ops.to_has_all_memory = 1; diff --git a/gdb/remote-rdp.c b/gdb/remote-rdp.c index 4b6d468..879a394 100644 --- a/gdb/remote-rdp.c +++ b/gdb/remote-rdp.c @@ -1444,9 +1444,13 @@ static void init_remote_rdp_ops(void) remote_rdp_ops.to_open = remote_rdp_open; remote_rdp_ops.to_close = remote_rdp_close; remote_rdp_ops.to_attach = remote_rdp_attach; - remote_rdp_ops.to_detach = NULL; + remote_rdp_ops.to_post_attach = NULL; + remote_rdp_ops.to_require_attach = NULL; + remote_rdp_ops.to_detach = NULL; + remote_rdp_ops.to_require_detach = NULL; remote_rdp_ops.to_resume = remote_rdp_resume; - remote_rdp_ops.to_wait = remote_rdp_wait; + remote_rdp_ops.to_wait = remote_rdp_wait; + remote_rdp_ops.to_post_wait = NULL; remote_rdp_ops.to_fetch_registers = remote_rdp_fetch_register; remote_rdp_ops.to_store_registers = remote_rdp_store_register; remote_rdp_ops.to_prepare_to_store = remote_rdp_prepare_to_store; @@ -1463,11 +1467,30 @@ static void init_remote_rdp_ops(void) remote_rdp_ops.to_load = generic_load; remote_rdp_ops.to_lookup_symbol = NULL; remote_rdp_ops.to_create_inferior = remote_rdp_create_inferior; + remote_rdp_ops.to_post_startup_inferior = NULL; + remote_rdp_ops.to_acknowledge_created_inferior = NULL; + remote_rdp_ops.to_clone_and_follow_inferior = NULL; + remote_rdp_ops.to_post_follow_inferior_by_clone = NULL; + remote_rdp_ops.to_insert_fork_catchpoint = NULL; + remote_rdp_ops.to_remove_fork_catchpoint = NULL; + remote_rdp_ops.to_insert_vfork_catchpoint = NULL; + remote_rdp_ops.to_remove_vfork_catchpoint = NULL; + remote_rdp_ops.to_has_forked = NULL; + remote_rdp_ops.to_has_vforked = NULL; + remote_rdp_ops.to_can_follow_vfork_prior_to_exec = NULL; + remote_rdp_ops.to_post_follow_vfork = NULL; + remote_rdp_ops.to_insert_exec_catchpoint = NULL; + remote_rdp_ops.to_remove_exec_catchpoint = NULL; + remote_rdp_ops.to_has_execd = NULL; + remote_rdp_ops.to_reported_exec_events_per_exec_call = NULL; + remote_rdp_ops.to_has_exited = NULL; remote_rdp_ops.to_mourn_inferior = generic_mourn_inferior; remote_rdp_ops.to_can_run = remote_rdp_can_run; remote_rdp_ops.to_notice_signals = 0; remote_rdp_ops.to_thread_alive = 0; - remote_rdp_ops.to_stop = 0; + remote_rdp_ops.to_stop = 0; + remote_rdp_ops.to_pid_to_exec_file = NULL; + remote_rdp_ops.to_core_file_to_sym_file = NULL; remote_rdp_ops.to_stratum = process_stratum; remote_rdp_ops.DONT_USE = NULL; remote_rdp_ops.to_has_all_memory = 1; diff --git a/gdb/remote-sds.c b/gdb/remote-sds.c index d3c6b70..05aa829 100644 --- a/gdb/remote-sds.c +++ b/gdb/remote-sds.c @@ -1132,10 +1132,14 @@ static void init_sds_ops(void) Specify the serial device it is connected to (e.g. /dev/ttya).", sds_ops.to_open = sds_open; sds_ops.to_close = sds_close; - sds_ops.to_attach = NULL; - sds_ops.to_detach = sds_detach; + sds_ops.to_attach = NULL; + sds_ops.to_post_attach = NULL; + sds_ops.to_require_attach = NULL; + sds_ops.to_detach = sds_detach; + sds_ops.to_require_detach = NULL; sds_ops.to_resume = sds_resume; - sds_ops.to_wait = sds_wait; + sds_ops.to_wait = sds_wait; + sds_ops.to_post_wait = NULL; sds_ops.to_fetch_registers = sds_fetch_registers; sds_ops.to_store_registers = sds_store_registers; sds_ops.to_prepare_to_store = sds_prepare_to_store; @@ -1152,11 +1156,30 @@ Specify the serial device it is connected to (e.g. /dev/ttya).", sds_ops.to_load = sds_load; sds_ops.to_lookup_symbol = NULL; sds_ops.to_create_inferior = sds_create_inferior; + sds_ops.to_post_startup_inferior = NULL; + sds_ops.to_acknowledge_created_inferior = NULL; + sds_ops.to_clone_and_follow_inferior = NULL; + sds_ops.to_post_follow_inferior_by_clone = NULL; + sds_ops.to_insert_fork_catchpoint = NULL; + sds_ops.to_remove_fork_catchpoint = NULL; + sds_ops.to_insert_vfork_catchpoint = NULL; + sds_ops.to_remove_vfork_catchpoint = NULL; + sds_ops.to_has_forked = NULL; + sds_ops.to_has_vforked = NULL; + sds_ops.to_can_follow_vfork_prior_to_exec = NULL; + sds_ops.to_post_follow_vfork = NULL; + sds_ops.to_insert_exec_catchpoint = NULL; + sds_ops.to_remove_exec_catchpoint = NULL; + sds_ops.to_has_execd = NULL; + sds_ops.to_reported_exec_events_per_exec_call = NULL; + sds_ops.to_has_exited = NULL; sds_ops.to_mourn_inferior = sds_mourn; sds_ops.to_can_run = 0; sds_ops.to_notice_signals = 0; sds_ops.to_thread_alive = 0; - sds_ops.to_stop = 0; + sds_ops.to_stop = 0; + sds_ops.to_pid_to_exec_file = NULL; + sds_ops.to_core_file_to_sym_file = NULL; sds_ops.to_stratum = process_stratum; sds_ops.DONT_USE = NULL; sds_ops.to_has_all_memory = 1; diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index 0c80544..132b1b3 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -926,10 +926,14 @@ static void init_gdbsim_ops(void) gdbsim_ops.to_doc = "Use the compiled-in simulator."; gdbsim_ops.to_open = gdbsim_open; gdbsim_ops.to_close = gdbsim_close; - gdbsim_ops.to_attach = NULL; - gdbsim_ops.to_detach = gdbsim_detach; + gdbsim_ops.to_attach = NULL; + gdbsim_ops.to_post_attach = NULL; + gdbsim_ops.to_require_attach = NULL; + gdbsim_ops.to_detach = gdbsim_detach; + gdbsim_ops.to_require_detach = NULL; gdbsim_ops.to_resume = gdbsim_resume; - gdbsim_ops.to_wait = gdbsim_wait; + gdbsim_ops.to_wait = gdbsim_wait; + gdbsim_ops.to_post_wait = NULL; gdbsim_ops.to_fetch_registers = gdbsim_fetch_register; gdbsim_ops.to_store_registers = gdbsim_store_register; gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store; @@ -946,11 +950,30 @@ static void init_gdbsim_ops(void) gdbsim_ops.to_load = gdbsim_load; gdbsim_ops.to_lookup_symbol = NULL; gdbsim_ops.to_create_inferior = gdbsim_create_inferior; + gdbsim_ops.to_post_startup_inferior = NULL; + gdbsim_ops.to_acknowledge_created_inferior = NULL; + gdbsim_ops.to_clone_and_follow_inferior = NULL; + gdbsim_ops.to_post_follow_inferior_by_clone = NULL; + gdbsim_ops.to_insert_fork_catchpoint = NULL; + gdbsim_ops.to_remove_fork_catchpoint = NULL; + gdbsim_ops.to_insert_vfork_catchpoint = NULL; + gdbsim_ops.to_remove_vfork_catchpoint = NULL; + gdbsim_ops.to_has_forked = NULL; + gdbsim_ops.to_has_vforked = NULL; + gdbsim_ops.to_can_follow_vfork_prior_to_exec = NULL; + gdbsim_ops.to_post_follow_vfork = NULL; + gdbsim_ops.to_insert_exec_catchpoint = NULL; + gdbsim_ops.to_remove_exec_catchpoint = NULL; + gdbsim_ops.to_has_execd = NULL; + gdbsim_ops.to_reported_exec_events_per_exec_call = NULL; + gdbsim_ops.to_has_exited = NULL; gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior; gdbsim_ops.to_can_run = 0; gdbsim_ops.to_notice_signals = 0; gdbsim_ops.to_thread_alive = 0; - gdbsim_ops.to_stop = gdbsim_stop; + gdbsim_ops.to_stop = gdbsim_stop; + gdbsim_ops.to_pid_to_exec_file = NULL; + gdbsim_ops.to_core_file_to_sym_file = NULL; gdbsim_ops.to_stratum = process_stratum; gdbsim_ops.DONT_USE = NULL; gdbsim_ops.to_has_all_memory = 1; @@ -971,7 +994,6 @@ void _initialize_remote_sim () { init_gdbsim_ops() ; - add_target (&gdbsim_ops); add_com ("sim <command>", class_obscure, simulator_command, diff --git a/gdb/remote-st.c b/gdb/remote-st.c index 18afd16..7255146 100644 --- a/gdb/remote-st.c +++ b/gdb/remote-st.c @@ -806,9 +806,13 @@ the speed to connect at in bits per second." ; st2000_ops.to_open = st2000_open; st2000_ops.to_close = st2000_close; st2000_ops.to_attach = 0; + st2000_run_ops.to_post_attach = NULL; + st2000_ops.to_require_attach = NULL; st2000_ops.to_detach = st2000_detach; + st2000_ops.to_require_detach = NULL; st2000_ops.to_resume = st2000_resume; st2000_ops.to_wait = st2000_wait; + st2000_ops.to_post_wait = NULL; st2000_ops.to_fetch_registers = st2000_fetch_register; st2000_ops.to_store_registers = st2000_store_register; st2000_ops.to_prepare_to_store = st2000_prepare_to_store; @@ -825,11 +829,30 @@ the speed to connect at in bits per second." ; st2000_ops.to_load = 0; /* load */ st2000_ops.to_lookup_symbol = 0; /* lookup_symbol */ st2000_ops.to_create_inferior = st2000_create_inferior; + st2000_ops.to_post_startup_inferior = NULL; + st2000_ops.to_acknowledge_created_inferior = NULL; + st2000_ops.to_clone_and_follow_inferior = NULL; + st2000_ops.to_post_follow_inferior_by_clone = NULL; + st2000_run_ops.to_insert_fork_catchpoint = NULL; + st2000_run_ops.to_remove_fork_catchpoint = NULL; + st2000_run_ops.to_insert_vfork_catchpoint = NULL; + st2000_run_ops.to_remove_vfork_catchpoint = NULL; + st2000_ops.to_has_forked = NULL; + st2000_ops.to_has_vforked = NULL; + st2000_run_ops.to_can_follow_vfork_prior_to_exec = NULL; + st2000_ops.to_post_follow_vfork = NULL; + st2000_run_ops.to_insert_exec_catchpoint = NULL; + st2000_run_ops.to_remove_exec_catchpoint = NULL; + st2000_run_ops.to_has_execd = NULL; + st2000_run_ops.to_reported_exec_events_per_exec_call = NULL; + st2000_run_ops.to_has_exited = NULL; st2000_ops.to_mourn_inferior = st2000_mourn_inferior; st2000_ops.to_can_run = 0; /* can_run */ st2000_ops.to_notice_signals = 0; /* notice_signals */ st2000_ops.to_thread_alive = 0; /* thread alive */ st2000_ops.to_stop = 0; /* to_stop */ + st2000_ops.to_pid_to_exec_file = NULL; + st2000_run_ops.to_core_file_to_sym_file = NULL; st2000_ops.to_stratum = process_stratum; st2000_ops.DONT_USE = 0; /* next */ st2000_ops.to_has_all_memory = 1; diff --git a/gdb/remote-udi.c b/gdb/remote-udi.c index 5b5ca5c..cdebf4c 100644 --- a/gdb/remote-udi.c +++ b/gdb/remote-udi.c @@ -1649,9 +1649,13 @@ To connect using a local connection to the \"tip.exe\" program which is\n\ udi_ops.to_open = udi_open; udi_ops.to_close = udi_close; udi_ops.to_attach = udi_attach; + udi_run_ops.to_post_attach = NULL; + udi_ops.to_require_attach = NULL; udi_ops.to_detach = udi_detach; + udi_ops.to_require_detach = NULL; udi_ops.to_resume = udi_resume; udi_ops.to_wait = udi_wait; + udi_ops.to_post_wait = NULL; udi_ops.to_fetch_registers = udi_fetch_registers; udi_ops.to_store_registers = udi_store_registers; udi_ops.to_prepare_to_store = udi_prepare_to_store; @@ -1668,11 +1672,30 @@ To connect using a local connection to the \"tip.exe\" program which is\n\ udi_ops.to_load = udi_load; udi_ops.to_lookup_symbol = 0; udi_ops.to_create_inferior = udi_create_inferior; + udi_ops.to_post_startup_inferior = NULL; + udi_ops.to_acknowledge_created_inferior = NULL; + udi_ops.to_clone_and_follow_inferior = NULL; + udi_ops.to_post_follow_inferior_by_clone = NULL; + udi_run_ops.to_insert_fork_catchpoint = NULL; + udi_run_ops.to_remove_fork_catchpoint = NULL; + udi_run_ops.to_insert_vfork_catchpoint = NULL; + udi_run_ops.to_remove_vfork_catchpoint = NULL; + udi_ops.to_has_forked = NULL; + udi_ops.to_has_vforked = NULL; + udi_run_ops.to_can_follow_vfork_prior_to_exec = NULL; + udi_ops.to_post_follow_vfork = NULL; + udi_run_ops.to_insert_exec_catchpoint = NULL; + udi_run_ops.to_remove_exec_catchpoint = NULL; + udi_run_ops.to_has_execd = NULL; + udi_run_ops.to_reported_exec_events_per_exec_call = NULL; + udi_run_ops.to_has_exited = NULL; udi_ops.to_mourn_inferior = udi_mourn; udi_ops.to_can_run = 0; udi_ops.to_notice_signals = 0; udi_ops.to_thread_alive = 0; - udi_ops.to_stop = 0; + udi_ops.to_stop = 0; + udi_ops.to_pid_to_exec_file = NULL; + udi_run_ops.to_core_file_to_sym_file = NULL; udi_ops.to_stratum = process_stratum; udi_ops.DONT_USE = 0; udi_ops.to_has_all_memory = 1; diff --git a/gdb/remote-vx.c b/gdb/remote-vx.c index b9fe630..4ac2a34 100644 --- a/gdb/remote-vx.c +++ b/gdb/remote-vx.c @@ -1405,9 +1405,13 @@ Specify the name of the machine to connect to.", vx_ops.to_open = vx_open; vx_ops.to_close = vx_close; vx_ops.to_attach = vx_attach; + vx_ops.to_post_attach = NULL; + vx_ops.to_require_attach = NULL; vx_ops.to_detach = 0; /* vx_detach, */ + vx_ops.to_require_detach = NULL; vx_ops.to_resume = 0; vx_ops.to_wait = 0; /* resume, wait */ + vx_ops.to_post_wait = NULL; vx_ops.to_fetch_registers = 0; vx_ops.to_store_registers = 0; /* read_reg, write_reg */ vx_ops.to_prepare_to_store = 0; /* prep_to_store, */ @@ -1424,11 +1428,30 @@ Specify the name of the machine to connect to.", vx_ops.to_load = vx_load_command; vx_ops.to_lookup_symbol = vx_lookup_symbol; vx_ops.to_create_inferior = vx_create_inferior; + vx_ops.to_post_startup_inferior = NULL; + vx_ops.to_acknowledge_created_inferior = NULL; + vx_ops.to_clone_and_follow_inferior = NULL; + vx_ops.to_post_follow_inferior_by_clone = NULL; + vx_ops.to_insert_fork_catchpoint = NULL; + vx_ops.to_remove_fork_catchpoint = NULL; + vx_ops.to_insert_vfork_catchpoint = NULL; + vx_ops.to_remove_vfork_catchpoint = NULL; + vx_ops.to_has_forked = NULL; + vx_ops.to_has_vforked = NULL; + vx_ops.to_can_follow_vfork_prior_to_exec = NULL; + vx_ops.to_post_follow_vfork = NULL; + vx_ops.to_insert_exec_catchpoint = NULL; + vx_ops.to_remove_exec_catchpoint = NULL; + vx_ops.to_has_execd = NULL; + vx_ops.to_reported_exec_events_per_exec_call = NULL; + vx_ops.to_has_exited = NULL; vx_ops.to_mourn_inferior = 0; /* mourn_inferior */ vx_ops.to_can_run = 0; /* can_run */ vx_ops.to_notice_signals = 0; /* notice_signals */ vx_ops.to_thread_alive = 0; /* thread_alive */ vx_ops.to_stop = 0; /* to_stop */ + vx_ops.to_pid_to_exec_file = NULL; + vx_ops.to_core_file_to_sym_file = NULL; vx_ops.to_stratum = core_stratum; vx_ops.DONT_USE = 0; /* next */ vx_ops.to_has_all_memory = 1; @@ -1453,9 +1476,13 @@ static void init_vx_run_ops(void) vx_run_ops.to_open = vx_proc_open; vx_run_ops.to_close = vx_proc_close; vx_run_ops.to_attach = 0; + vx_run_ops.to_post_attach = NULL; + vx_run_ops.to_require_attach = NULL; vx_run_ops.to_detach = vx_detach; + vx_run_ops.to_require_detach = NULL; vx_run_ops.to_resume = vx_resume; vx_run_ops.to_wait = vx_wait; + vx_run_ops.to_post_wait = NULL; vx_run_ops.to_fetch_registers = vx_read_register; vx_run_ops.to_store_registers = vx_write_register; vx_run_ops.to_prepare_to_store = vx_prepare_to_store; @@ -1472,11 +1499,30 @@ static void init_vx_run_ops(void) vx_run_ops.to_load = vx_load_command; vx_run_ops.to_lookup_symbol = vx_lookup_symbol; vx_run_ops.to_create_inferior = 0; + vx_run_ops.to_post_startup_inferior = NULL; + vx_run_ops.to_acknowledge_created_inferior = NULL; + vx_run_ops.to_clone_and_follow_inferior = NULL; + vx_run_ops.to_post_follow_inferior_by_clone = NULL; + vx_run_ops.to_insert_fork_catchpoint = NULL; + vx_run_ops.to_remove_fork_catchpoint = NULL; + vx_run_ops.to_insert_vfork_catchpoint = NULL; + vx_run_ops.to_remove_vfork_catchpoint = NULL; + vx_run_ops.to_has_forked = NULL; + vx_run_ops.to_has_vforked = NULL; + vx_run_ops.to_can_follow_vfork_prior_to_exec = NULL; + vx_run_ops.to_post_follow_fork = NULL; + vx_run_ops.to_insert_exec_catchpoint = NULL; + vx_run_ops.to_remove_exec_catchpoint = NULL; + vx_run_ops.to_has_execd = NULL; + vx_run_ops.to_reported_exec_events_per_exec_call = NULL; + vx_run_ops.to_has_exited = NULL; vx_run_ops.to_mourn_inferior = vx_mourn_inferior ; vx_run_ops.to_can_run = 0; vx_run_ops.to_notice_signals = 0; vx_run_ops.to_thread_alive = 0; - vx_run_ops.to_stop = 0; + vx_run_ops.to_stop = 0; + vx_run_ops.to_pid_to_exec_file = NULL; + vx_run_ops.to_core_file_to_sym_file = NULL; vx_run_ops.to_stratum = process_stratum; vx_run_ops.DONT_USE = 0; vx_run_ops.to_has_all_memory = 0; diff --git a/gdb/remote.c b/gdb/remote.c index d51c08a..ab0f470 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -209,11 +209,11 @@ static int remote_write_bytes PARAMS ((CORE_ADDR memaddr, static int remote_read_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len)); -static void remote_files_info PARAMS ((struct target_ops *ignore)); +static void remote_files_info PARAMS ((struct target_ops * ignore)); -static int remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, +static int remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char * myaddr, int len, int should_write, - struct target_ops *target)); + struct target_ops * target)); static void remote_prepare_to_store PARAMS ((void)); @@ -248,7 +248,7 @@ static void remote_send PARAMS ((char *buf)); static int readchar PARAMS ((int timeout)); -static int remote_wait PARAMS ((int pid, struct target_waitstatus *status)); +static int remote_wait PARAMS ((int pid, struct target_waitstatus * status)); static void remote_kill PARAMS ((void)); @@ -302,6 +302,8 @@ extern int putpkt PARAMS ((char *buf)); void remote_console_output PARAMS ((char *)); +/* Define the target subroutine names */ + void open_remote_target PARAMS ((char *, int, struct target_ops *, int)); void _initialize_remote PARAMS ((void)); @@ -358,6 +360,7 @@ static serial_t remote_desc = NULL; #define PBUFSIZ (REGISTER_BYTES * 2 + 32) #endif + /* This variable sets the number of bytes to be written to the target in a single packet. Normally PBUFSIZ is satisfactory, but some targets need smaller values (perhaps because the receiving end @@ -396,11 +399,174 @@ void (*target_resume_hook) PARAMS ((void)); void (*target_wait_loop_hook) PARAMS ((void)); +/* ------- REMOTE Thread (or) Process support ----------------------- */ + + + +static int +stub_unpack_int PARAMS ((char *buff, int fieldlength)); + +char * + unpack_varlen_hex PARAMS ((char *buff, int *result)); + + +static char * + unpack_nibble PARAMS ((char *buf, int *val)); + +static char * + unpack_nibble PARAMS ((char *buf, int *val)); + +static char * + pack_hex_byte PARAMS ((char *pkt, unsigned char byte)); + +static char * + unpack_byte PARAMS ((char *buf, int *value)); + +static char * + pack_int PARAMS ((char *buf, int value)); + +static char * + unpack_int PARAMS ((char *buf, int *value)); + +static char * + pack_string PARAMS ((char *pkt, char *string)); + +static char * + unpack_string PARAMS ((char *src, char *dest, int length)); + +static char * + pack_threadid PARAMS ((char *pkt, threadref * id)); + +static char * + unpack_threadid PARAMS ((char *inbuf, threadref * id)); + +void +int_to_threadref PARAMS ((threadref * id, int value)); + + +int +threadref_to_int PARAMS ((threadref * ref)); + +static void +copy_threadref PARAMS ((threadref * dest, threadref * src)); + +static int +threadmatch PARAMS ((threadref * dest, threadref * src)); + + +static char * + pack_threadinfo_request PARAMS ((char *pkt, + int mode, + threadref * id)); + +static int +remote_unpack_thread_info_response PARAMS (( + char *pkt, + threadref * expectedref, + struct gdb_ext_thread_info * info)); + + +int +remote_get_threadinfo PARAMS (( + threadref * threadid, + int fieldset, /* TAG mask */ + struct gdb_ext_thread_info * info)); + +int +adapt_remote_get_threadinfo PARAMS (( + gdb_threadref * ref, + int selection, + struct gdb_ext_thread_info * info)); +static char * + pack_threadlist_request PARAMS (( + char *pkt, + int startflag, + int threadcount, + threadref * nextthread)); + +static int +parse_threadlist_response PARAMS (( + char *pkt, + int result_limit, + threadref * original_echo, + threadref * resultlist, + int *doneflag)); +static int +remote_get_threadlist PARAMS (( + int startflag, + threadref * nextthread, + int result_limit, + int *done, + int *result_count, + threadref * threadlist)); + + + +static int +remote_newthread_step PARAMS (( + threadref * ref, + void *context)); + +int +remote_find_new_threads PARAMS ((void)) ; + +static void +threadalive_test PARAMS ((char *cmd, int tty)); + + +static void +threadset_test_cmd PARAMS ((char *cmd, int tty)); + +static void +threadlist_test_cmd PARAMS ((char *cmd, + int tty)); + +void +display_thread_info PARAMS ((struct gdb_ext_thread_info * info)); + + +int +get_and_display_threadinfo PARAMS ((threadref * ref)); + + +static void +threadinfo_test_cmd PARAMS ((char *cmd, + int tty)); + +static int +thread_display_step PARAMS (( + threadref * ref, + void *context)); + + +static void +threadlist_update_test_cmd PARAMS ((char *cmd, + int tty)); + + +static void +init_remote_threadtests PARAMS ((void)); + /* These are the threads which we last sent to the remote system. -1 for all or -2 for not sent yet. */ int general_thread; int cont_thread; +/* Call this function as a result of + 1) A halt indication (T packet) containing a thread id + 2) A direct query of currthread + 3) Successful execution of set thread + */ + +static void +record_currthread (currthread) + int currthread; +{ + inferior_pid = currthread; + general_thread = currthread; + cont_thread = currthread; +} + static void set_thread (th, gen) int th; @@ -439,14 +605,870 @@ remote_thread_alive (th) buf[0] = 'T'; if (th < 0) - sprintf (&buf[1], "-%x", -th); + sprintf (&buf[1], "-%08x", -th); else - sprintf (&buf[1], "%x", th); + sprintf (&buf[1], "%08x", th); putpkt (buf); getpkt (buf, 0); return (buf[0] == 'O' && buf[1] == 'K'); } +/* + About these extended threadlist and threadinfo packets. + They are variable length packets but, the fields within them + are often fixed length. + They are redundent enough to send over UDP as is the remote protocol + in general. + There is a matching unit test module in libstub. + */ + + +#define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES*2) +/* encode 64 bits in 16 chars of hex */ + + +static const char hexchars[] = "0123456789abcdef"; + +static int +ishex (ch, val) + char ch; + int *val; +{ + if ((ch >= 'a') && (ch <= 'f')) + { + *val = ch - 'a' + 10; + return 1; + } + if ((ch >= 'A') && (ch <= 'F')) + { + *val = ch - 'A' + 10; + return 1; + } + if ((ch >= '0') && (ch <= '9')) + { + *val = ch - '0'; + return 1; + } + return 0; +} + +static int +stubhex (ch) + unsigned char ch; +{ + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + if (ch >= '0' && ch <= '9') + return ch - '0'; + if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + return -1; +} + +static int +stub_unpack_int (buff, fieldlength) + char *buff; + int fieldlength; +{ + int retval = 0; + int nibble; + while (fieldlength) + { + nibble = stubhex (*buff++); + retval |= nibble; + fieldlength--; + if (fieldlength) + retval = retval << 4; + } + return retval; +} + +char * +unpack_varlen_hex (buff, result) + char *buff; /* packet to parse */ + int *result; +{ + int nibble; + int retval; + retval = 0; + + while (ishex (*buff, &nibble)) + { + buff++; + retval = retval << 4; + retval |= nibble & 0x0f; + } + *result = retval; + return buff; +} + +static char * +unpack_nibble (buf, val) + char *buf; + int *val; + +{ + ishex (*buf++, val); + return buf; +} + +static char * +pack_nibble (buf, nibble) + char *buf; + int nibble; + +{ + *buf++ = hexchars[(nibble & 0x0f)]; + return buf; +} + +static char * +pack_hex_byte (pkt, byte) + char *pkt; + unsigned char byte; +{ + *pkt++ = hexchars[(byte >> 4) & 0xf]; + *pkt++ = hexchars[(byte & 0xf)]; + return pkt; +} + +static char * +unpack_byte (buf, value) + char *buf; + int *value; +{ + *value = stub_unpack_int (buf, 2); + return buf + 2; +} + + +static char * +pack_int (buf, value) + char *buf; + int value; +{ + buf = pack_hex_byte (buf, (value >> 24) & 0xff); + buf = pack_hex_byte (buf, (value >> 16) & 0xff); + buf = pack_hex_byte (buf, (value >> 8) & 0x0ff); + buf = pack_hex_byte (buf, (value & 0xff)); + return buf; +} + + +static char * +unpack_int (buf, value) + char *buf; + int *value; +{ + *value = stub_unpack_int (buf, 8); + return buf + 8; +} + + +static char * +pack_string (pkt, string) + char *pkt; + char *string; +{ + char ch; + int len; + len = strlen (string); + if (len > 200) + len = 200; /* Bigger than most GDB packets, junk??? */ + pkt = pack_hex_byte (pkt, len); + while (len-- > 0) + { + ch = *string++; + if ((ch == '\0') || (ch == '#')) + ch = '*'; /* Protect encapsulation */ + *pkt++ = ch; + } + return pkt; +} + +static char * +unpack_string (src, dest, length) + char *src; + char *dest; + int length; +{ + while (length--) + *dest++ = *src++; + *dest = '\0'; + return src; +} + +static char * +pack_threadid (pkt, id) + char *pkt; + threadref *id; +{ + char *limit; + unsigned char *altid; + altid = (unsigned char *) id; + limit = pkt + BUF_THREAD_ID_SIZE; + while (pkt < limit) + pkt = pack_hex_byte (pkt, *altid++); + return pkt; +} + + +static char * +unpack_threadid (inbuf, id) + char *inbuf; + threadref *id; +{ + char *altref; + char *limit = inbuf + BUF_THREAD_ID_SIZE; + int x, y; + altref = (char *) id; + + while (inbuf < limit) + { + x = stubhex (*inbuf++); + y = stubhex (*inbuf++); + *altref++ = (x << 4) | y; + } + return inbuf; +} + +/* Externally, threadrefs are 64 bits but internally, they are still + ints. This is due to a mismatch of specifications. + We would like to use 64bit thread references internally. + This is an adapter function. + */ + +void +int_to_threadref (id, value) + threadref *id; + int value; +{ + unsigned char *scan; + scan = (unsigned char *) id; + { + int i = 4; + while (i--) + *scan++ = 0; + } + *scan++ = (value >> 24) & 0xff; + *scan++ = (value >> 16) & 0xff; + *scan++ = (value >> 8) & 0xff; + *scan++ = (value & 0xff); +} + +int +threadref_to_int (ref) + threadref *ref; +{ + int value = 0; + unsigned char *scan; + int i; + + scan = (char *) ref; + scan += 4; + i = 4; + while (i-- > 0) + value = (value << 8) | ((*scan++) & 0xff); + return value; +} + +static void +copy_threadref (dest, src) + threadref *dest; + threadref *src; +{ + int i; + unsigned char *csrc, *cdest; + csrc = (unsigned char *) src; + cdest = (unsigned char *) dest; + i = 8; + while (i--) + *cdest++ = *csrc++; +} + + + +static int +threadmatch (dest, src) + threadref *dest; + threadref *src; +{ + /* things are broken right now, so just assume we got a match */ +#if 0 + unsigned char *srcp, *destp; + int i, result; + srcp = (char *) src; + destp = (char *) dest; + + result = 1; + while (i-- > 0) + result &= (*srcp++ == *destp++) ? 1 : 0; + return result; +#endif + return 1; +} + +#if THREAD_PKT_TRACE +#define PKT_TRACE(title,packet) { printf_filtered("%s %s\n", title, packet);} +#else +#define PKT_TRACE(a,b) {} +#endif + + +/* ----- PACK_THREAD_INFO_REQUEST -------------------------------- */ + +/* + threadid:1, # always request threadid + context_exists:2, + display:4, + unique_name:8, + more_display:16 +*/ + +/* Encoding: 'Q':8,'P':8,mask:32,threadid:64 */ + +static char * + pack_threadinfo_request PARAMS ((char *pkt, + int mode, + threadref * id)); + +static char * +pack_threadinfo_request (pkt, mode, id) + char *pkt; + int mode; + threadref *id; +{ + char *base = pkt; + *pkt++ = 'q'; /* Info Query */ + *pkt++ = 'P'; /* process or thread info */ + pkt = pack_int (pkt, mode); /* mode */ + pkt = pack_threadid (pkt, id); /* threadid */ + *pkt = '\0'; /* terminate */ + PKT_TRACE ("threadinfo-req ", base); + return pkt; +} + + +/* These values tag the fields in a thread info response packet */ +/* Tagging the fields allows us to request specific fields and to + add more fields as time goes by */ +#define TAG_THREADID 1 /* Echo the thread identifier */ +#define TAG_EXISTS 2 /* It this process defined enough to + fetch registers and its stack */ +#define TAG_DISPLAY 4 /* A short thing maybe to put on a window */ +#define TAG_THREADNAME 8 /* string, maps 1-to-1 with a thread is */ +#define TAG_MOREDISPLAY 16 /* Whatever the kernel wants to say about the process*/ + + +static int +remote_unpack_thread_info_response (pkt, expectedref, info) + char *pkt; + threadref *expectedref; + struct gdb_ext_thread_info *info; +{ + int mask, length; + unsigned int tag; + threadref ref; + char *limit = pkt + PBUFSIZ; /* plausable parsing limit */ + int retval = 1; + + PKT_TRACE ("unpack-threadinfo ", pkt); + + /* info->threadid = 0; FIXME: implement zero_threadref */ + info->active = 0; + info->display[0] = '\0'; + info->shortname[0] = '\0'; + info->more_display[0] = '\0'; + + /* Assume the characters indicating the packet type have been stripped */ + pkt = unpack_int (pkt, &mask); /* arg mask */ + pkt = unpack_threadid (pkt, &ref); + + if (mask == 0) + warning("Incomplete response to threadinfo request\n"); + if (!threadmatch (&ref, expectedref)) + { /* This is an answer to a different request */ + warning("ERROR RMT Thread info mismatch\n"); + return 0; + } + copy_threadref (&info->threadid, &ref); + + /* Loop on tagged fields , try to bail if somthing goes wrong */ + + while ((pkt < limit) && mask && *pkt) /* packets are terminated with nulls */ + { + pkt = unpack_int (pkt, &tag); /* tag */ + pkt = unpack_byte (pkt, &length); /* length */ + if (!(tag & mask)) /* tags out of synch with mask */ + { + warning ("ERROR RMT: threadinfo tag mismatch\n"); + retval = 0; + break; + } + if (tag == TAG_THREADID) + { + if (length != 16) + { + warning ("ERROR RMT: length of threadid is not 16\n"); + retval = 0; + break; + } + pkt = unpack_threadid (pkt, &ref); + mask = mask & ~TAG_THREADID; + continue; + } + if (tag == TAG_EXISTS) + { + info->active = stub_unpack_int (pkt, length); + pkt += length; + mask = mask & ~(TAG_EXISTS); + if (length > 8) + { + warning ("ERROR RMT: 'exists' length too long\n"); + retval = 0; + break; + } + continue; + } + if (tag == TAG_THREADNAME) + { + pkt = unpack_string (pkt, &info->shortname[0], length); + mask = mask & ~TAG_THREADNAME; + continue; + } + if (tag == TAG_DISPLAY) + { + pkt = unpack_string (pkt, &info->display[0], length); + mask = mask & ~TAG_DISPLAY; + continue; + } + if (tag == TAG_MOREDISPLAY) + { + pkt = unpack_string (pkt, &info->more_display[0], length); + mask = mask & ~TAG_MOREDISPLAY; + continue; + } + warning ("ERROR RMT: unknown thread info tag\n"); + break; /* Not a tag we know about */ + } + return retval; +} + + +/* ------ REMOTE_GET_THREADINFO -------------------------------------- */ + +int +remote_get_threadinfo (threadid, fieldset, info) + threadref *threadid; + int fieldset; /* TAG mask */ + struct gdb_ext_thread_info *info; +{ + int result; + char threadinfo_pkt[PBUFSIZ]; + pack_threadinfo_request (threadinfo_pkt, fieldset, threadid); + putpkt (threadinfo_pkt); + getpkt (threadinfo_pkt, 0); + result = remote_unpack_thread_info_response (threadinfo_pkt + 2, threadid, info); + return result; +} + +/* ------- ADAPT_remote_GET_THREADINFO - */ +/* Unfortunatly, 61 but thread-ids are bugger than the internal + representation of a threadid. */ + + +int +adapt_remote_get_threadinfo (ref, selection, info) + gdb_threadref *ref; + int selection; + struct gdb_ext_thread_info *info; +{ + threadref lclref; + int_to_threadref (&lclref, *ref); + return remote_get_threadinfo (&lclref, selection, info); +} + + +/* -------- PACK_THREADLIST-REQUEST --------------------------------- */ +/* Format: i'Q':8,i"L":8,initflag:8,batchsize:16,lastthreadid:32 */ + +static char * +pack_threadlist_request (pkt, startflag, threadcount, nextthread) + char *pkt; + int startflag; + int threadcount; + threadref *nextthread; +{ + *pkt++ = 'q'; /* info query packet */ + *pkt++ = 'L'; /* Process LIST or threadLIST request */ + pkt = pack_nibble (pkt, startflag); /* initflag 1 bytes */ + pkt = pack_hex_byte (pkt, threadcount); /* threadcount 2 bytes */ + pkt = pack_threadid (pkt, nextthread); /* 64 bit thread identifier */ + *pkt = '\0'; + return pkt; +} + + +/* ---------- PARSE_THREADLIST_RESPONSE ------------------------------------ */ +/* Encoding: 'q':8,'M':8,count:16,done:8,argthreadid:64,(threadid:64)* */ + + +static int +parse_threadlist_response (pkt, result_limit, original_echo, + resultlist, doneflag) + char *pkt; + int result_limit; + threadref *original_echo; + threadref *resultlist; + int *doneflag; +{ + char *limit; + int count, resultcount, done; + resultcount = 0; + + /* assume the 'q' and 'M chars have been stripped */ + PKT_TRACE ("parse-threadlist-response ", pkt); + limit = pkt + (PBUFSIZ - BUF_THREAD_ID_SIZE); /* done parse past here */ + pkt = unpack_byte (pkt, &count); /* count field */ + pkt = unpack_nibble (pkt, &done); + /* The first threadid is the argument threadid */ + pkt = unpack_threadid (pkt, original_echo); /* should match query packet */ + while ((count-- > 0) && (pkt < limit)) + { + pkt = unpack_threadid (pkt, resultlist++); + if (resultcount++ >= result_limit) + break; + } + if (doneflag) + *doneflag = done; + return resultcount; /* successvalue */ +} + + + +static int +remote_get_threadlist (startflag, nextthread, result_limit, + done, result_count, threadlist) + int startflag; + threadref *nextthread; + int result_limit; + int *done; + int *result_count; + threadref *threadlist; + +{ + static threadref echo_nextthread; + char threadlist_packet[PBUFSIZ]; + char t_response[PBUFSIZ]; + int result = 1; + + /* Trancate result limit to be smaller than the packet size */ + if ((((result_limit + 1) * BUF_THREAD_ID_SIZE) + 10) >= PBUFSIZ) + result_limit = (PBUFSIZ / BUF_THREAD_ID_SIZE) - 2; + + pack_threadlist_request (threadlist_packet, + startflag, result_limit, nextthread); + putpkt (threadlist_packet); + getpkt (t_response, 0); + *result_count = parse_threadlist_response ( + t_response + 2, /* strip header */ + result_limit, + &echo_nextthread, + threadlist, + done); + if (!threadmatch (&echo_nextthread, nextthread)) + { + /* FIXME: This is a good reason to drop the packet */ + /* Possably, there is a duplicate response */ + /* Possabilities : + retransmit immediatly - race conditions + retransmit after timeout - yes + exit + wait for packet, then exit + */ + warning ("HMM: threadlist did not echo arg thread, dropping it\n"); + return 0; /* I choose simply exiting */ + } + if (*result_count <= 0) + { + if (*done != 1) + { + warning ("RMT ERROR : failed to get remote thread list\n"); + result = 0; + } + return result; /* break; */ + } + if (*result_count > result_limit) + { + *result_count = 0; + warning ("RMT ERROR: threadlist response longer than requested\n"); + return 0; + } + return result; +} + + + +/* This is the interface between remote and threads, remotes upper interface */ +/* remote_find_new_threads retreives the thread list and for each + thread in the list, looks up the thread in GDB's internal list, + ading the thread if it does not already exist. + This involves getting partial thread lists from the remote target so, + polling the quit_flag is required. +*/ + +typedef int (*rmt_thread_action) ( + threadref * ref, + void *context +); + +#define MAXTHREADLISTRESULTS 32 /* About this many threadisds fit in a packet */ + +static int +remote_threadlist_iterator PARAMS (( + rmt_thread_action stepfunction, + void *context, + int looplimit)); + +static int +remote_threadlist_iterator (stepfunction, context, looplimit) + rmt_thread_action stepfunction; + void *context; + int looplimit; +{ + int done, i, result_count; + int startflag = 1; + int result = 1; + int loopcount = 0; + static threadref nextthread; + static threadref echo_nextthread; + static threadref resultthreadlist[MAXTHREADLISTRESULTS]; + + done = 0; + while (!done) + { + if (loopcount++ > looplimit) + { + result = 0; + warning ("Remote fetch threadlist -infinite loop-\n"); + break; + } + if (!remote_get_threadlist (startflag, + &nextthread, + MAXTHREADLISTRESULTS, + &done, + &result_count, + resultthreadlist)) + { + result = 0; + break; + } + startflag = 0; /* clear for later iterations */ + /* Setup to resume next batch of thread references , set nestthread */ + if (result_count >= 1) + copy_threadref (&nextthread, &resultthreadlist[result_count - 1]); + /* output_threadid("last-of-batch",&nextthread); */ + i = 0; + while (result_count--) + if (!(result = (*stepfunction) (&resultthreadlist[i++], context))) + break; + } + return result; +} + + +static int +remote_newthread_step (ref, context) + threadref *ref; + void *context + ; + +{ + int pid; + pid = threadref_to_int (ref); + if (!in_thread_list (pid)) + add_thread (pid); + return 1; /* continue iterator */ +} + +#define CRAZY_MAX_THREADS 1000 + + +int +remote_find_new_threads (void) +{ + return remote_threadlist_iterator (remote_newthread_step, 0, CRAZY_MAX_THREADS); +} /* remote_find_new_threads */ + +int +remote_update_threads () +{ + /* Right now, this is empty. But it is one of the functions + defined for the thread target vector so it gets called. + If we were to allow the modification of the registers of + a suspended process, this would be implemented. */ + return 0; +} + +static struct target_thread_vector remote_thread_vec; + +/* Initialize the thread vector which is used by threads.c */ +/* The thread stubb is a package, it has an initializer */ +void init_remote_threads () +{ + remote_thread_vec.find_new_threads = remote_find_new_threads; + remote_thread_vec.get_thread_info = adapt_remote_get_threadinfo; +} + +/* --------- UNIT_TEST for THREAD oriented PACKETS -------------------------- */ + +#define SAMPLE_THREAD 0x05060708 /* Truncated 64 bit threadid */ + + +static void +threadset_test_cmd (cmd, tty) + char *cmd; + int tty; +{ + int sample_thread = SAMPLE_THREAD; + printf_filtered ("Remote threadset test\n"); + set_thread (sample_thread, 1); +} + + +static void +threadalive_test (cmd, tty) + char *cmd; + int tty; +{ + int sample_thread = SAMPLE_THREAD; + if (remote_thread_alive (sample_thread)) + printf_filtered ("PASS: Thread alive test\n"); + else + printf_filtered ("FAIL: Thread alive test\n"); +} + +void +output_threadid PARAMS ((char *title, threadref * ref)); + +void +output_threadid (title, ref) + char *title; + threadref *ref; +{ + char hexid[20]; + pack_threadid (&hexid[0], ref); /* Convert threead id into hex */ + hexid[16] = 0; + printf_filtered ("%s %s\n", title, (&hexid[0])); +} + + +static void +threadlist_test_cmd (cmd, tty) + char *cmd; + int tty; +{ + int startflag = 1; + threadref nextthread; + int done, result_count; + threadref threadlist[3]; + + printf_filtered ("Remote Threadlist test\n"); + if (!remote_get_threadlist (startflag, &nextthread, 3, &done, + &result_count, &threadlist[0])) + printf_filtered ("FAIL: threadlist test\n"); + else + { + threadref *scan = threadlist; + threadref *limit = scan + result_count; + while (scan < limit) + output_threadid (" thread ", scan++); + } +} + +void +display_thread_info (info) + struct gdb_ext_thread_info *info; +{ + + output_threadid ("Threadid: ", &info->threadid); + /* short name */ + printf_filtered ("Name: %s\n ", info->shortname); + /* format display state */ + printf_filtered ("State: %s\n", info->display); + /* additional data */ + printf_filtered ("other: %s\n\n", info->more_display); +} + +int +get_and_display_threadinfo (ref) + threadref *ref; +{ + int result; + int set; + struct gdb_ext_thread_info threadinfo; + + set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME + | TAG_MOREDISPLAY | TAG_DISPLAY; + if (0 != (result = remote_get_threadinfo (ref, set, &threadinfo))) + display_thread_info (&threadinfo); + return result; +} + +static void +threadinfo_test_cmd (cmd, tty) + char *cmd; + int tty; +{ + int athread = SAMPLE_THREAD; + threadref thread; + int set; + + int_to_threadref (&thread, athread); + printf_filtered ("Remote Threadinfo test\n"); + if (!get_and_display_threadinfo (&thread)) + printf_filtered ("FAIL cannot get thread info\n"); +} + + +static int +thread_display_step (ref, context) + threadref *ref; + void *context; +{ + /* output_threadid(" threadstep ",ref); *//* simple test */ + return get_and_display_threadinfo (ref); +} + + +static void +threadlist_update_test_cmd (cmd, tty) + char *cmd; + int tty; +{ + printf_filtered ("Remote Threadlist update test\n"); + remote_threadlist_iterator (thread_display_step, 0, CRAZY_MAX_THREADS); +} + +static void +init_remote_threadtests (void) +{ + add_com ("tlist", class_obscure, threadlist_test_cmd, + "Fetch and print the remote list of thread identifiers, one pkt only"); + add_com ("tinfo", class_obscure, threadinfo_test_cmd, + "Fetch and display info about one thread"); + add_com ("tset", class_obscure, threadset_test_cmd, + "Test setting to a different thread"); + add_com ("tupd", class_obscure, threadlist_update_test_cmd, + "Iterate through updating all remote thread info"); + add_com ("talive", class_obscure, threadalive_test, + " Remote thread alive test "); +} + +#define INIT_REMOTE_THREADTESTS { init_remote_threadtests();} +/* END OF REMOTE THREAD UNIT TESTS */ + + /* Restart the remote side; this is an extended protocol operation. */ static void @@ -655,7 +1677,10 @@ device is attached to the remote system (e.g. /dev/ttya)."); puts_filtered ("\n"); } push_target (target); /* Switch to using remote target now */ - + /* The target vector does not have the thread functions in it yet, + so we use this function to call back into the thread module and + register the thread vector and its contained functions. */ + bind_target_thread_vector(&remote_thread_vec); /* Start out by trying the 'P' request to set registers. We set this each time that we open a new target so that if the user switches from one stub to another, we can (if the target is closed and reopened) cope. */ @@ -916,16 +1941,17 @@ remote_wait (pid, status) regno = strtol ((const char *) p, &p_temp, 16); /* Read the register number */ p1 = (unsigned char *)p_temp; - if (p1 == p) + if (p1 == p) /* No register number present here */ { p1 = (unsigned char *) strchr ((const char *) p, ':'); if (p1 == NULL) - warning ("Malformed packet (missing colon): %s\n\ + warning ("Malformed packet(a) (missing colon): %s\n\ Packet: '%s'\n", p, buf); if (strncmp ((const char *) p, "thread", p1 - p) == 0) { - thread_num = strtol ((const char *) ++p1, &p_temp, 16); + p_temp = unpack_varlen_hex(++p1,&thread_num); + record_currthread(thread_num); p = (unsigned char *)p_temp; } } @@ -934,7 +1960,7 @@ Packet: '%s'\n", p = p1; if (*p++ != ':') - warning ("Malformed packet (missing colon): %s\n\ + warning ("Malformed packet(b) (missing colon): %s\n\ Packet: '%s'\n", p, buf); @@ -954,7 +1980,10 @@ Packet: '%s'\n", } if (*p++ != ';') - warning ("Remote register badly formatted: %s", buf); + { + warning ("Remote register badly formatted: %s", buf); + warning (" here: %s",p); + } } } /* fall through */ @@ -1778,6 +2807,8 @@ read_frame (buf) } } + + /* Read a packet from the remote machine, with error checking, and store it in BUF. BUF is expected to be of size PBUFSIZ. If FOREVER, wait forever rather than timing out; this is used @@ -2197,9 +3228,9 @@ init_remote_ops () Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_ops.to_open = remote_open; remote_ops.to_close = remote_close; - remote_ops.to_detach = remote_detach; + remote_ops.to_detach = remote_detach; remote_ops.to_resume = remote_resume; - remote_ops.to_wait = remote_wait; + remote_ops.to_wait = remote_wait; remote_ops.to_fetch_registers = remote_fetch_registers; remote_ops.to_store_registers = remote_store_registers; remote_ops.to_prepare_to_store = remote_prepare_to_store; @@ -2222,7 +3253,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; } static void -init_extended_remote_ops () +init_extended_remote_ops () { extended_remote_ops = remote_ops; @@ -2243,6 +3274,8 @@ _initialize_remote () init_extended_remote_ops (); add_target (&extended_remote_ops); + init_remote_threads(); + INIT_REMOTE_THREADTESTS /* conditional thread packet unit test */ add_cmd ("compare-sections", class_obscure, compare_sections_command, "Compare section data on target to the exec file.\n\ @@ -2260,22 +3293,29 @@ terminating `#' character and checksum.", add_show_from_set (add_set_cmd ("remotetimeout", no_class, var_integer, (char *)&remote_timeout, - "Set timeout value for remote read.\n", &setlist), + "Set timeout value for remote read.\n", + &setlist), &showlist); add_show_from_set (add_set_cmd ("remotebreak", no_class, var_integer, (char *)&remote_break, - "Set whether to send break if interrupted.\n", &setlist), + "Set whether to send break if interrupted.\n", + &setlist), &showlist); add_show_from_set (add_set_cmd ("remotewritesize", no_class, var_integer, (char *)&remote_write_size, - "Set the maximum number of bytes in each memory write packet.\n", &setlist), + "Set the maximum number of bytes in each memory write packet.\n", + &setlist), &showlist); + + remote_address_size = TARGET_PTR_BIT; add_show_from_set (add_set_cmd ("remoteaddresssize", class_obscure, var_integer, (char *)&remote_address_size, - "Set the maximum size of the address (in bits) in a memory packet.\n", &setlist), - &showlist); + "Set the maximum size of the address (in bits) in a memory packet.\n", + &setlist), + &showlist); } + diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c index 7e250ef..b61af3d 100644 --- a/gdb/rs6000-nat.c +++ b/gdb/rs6000-nat.c @@ -427,7 +427,7 @@ add_vmap (ldi) objname, bfd_errmsg (bfd_get_error ())); /*NOTREACHED*/ } - obj = allocate_objfile (vp->bfd, 0); + obj = allocate_objfile (vp->bfd, 0, 0, 0); vp->objfile = obj; #ifndef SOLIB_SYMBOLS_MANUAL diff --git a/gdb/scm-lang.h b/gdb/scm-lang.h index f122527..878a2ab 100644 --- a/gdb/scm-lang.h +++ b/gdb/scm-lang.h @@ -29,7 +29,7 @@ struct value; extern int scm_value_print PARAMS ((struct value *, GDB_FILE*, int, enum val_prettyprint)); -extern int scm_val_print PARAMS ((struct type*, char*, CORE_ADDR, GDB_FILE*, +extern int scm_val_print PARAMS ((struct type*, char*, int, CORE_ADDR, GDB_FILE*, int, int, int, enum val_prettyprint)); extern LONGEST scm_get_field PARAMS ((LONGEST, int)); diff --git a/gdb/scm-valprint.c b/gdb/scm-valprint.c index d05b7ee..71acc69 100644 --- a/gdb/scm-valprint.c +++ b/gdb/scm-valprint.c @@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* FIXME: Should be in a header file that we import. */ extern int -c_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int, +c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int, int, enum val_prettyprint)); static void scm_ipruk PARAMS ((char *, LONGEST, GDB_FILE *)); @@ -157,7 +157,7 @@ scm_scmval_print (svalue, stream, format, deref_ref, recurse, pretty) enum val_prettyprint pretty; { taloop: - switch (7 & svalue) + switch (7 & (int) svalue) { case 2: case 6: @@ -375,10 +375,11 @@ scm_scmval_print (svalue, stream, format, deref_ref, recurse, pretty) } int -scm_val_print (type, valaddr, address, stream, format, deref_ref, recurse, - pretty) +scm_val_print (type, valaddr, embedded_offset, address, + stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; + int embedded_offset; CORE_ADDR address; GDB_FILE *stream; int format; @@ -404,7 +405,7 @@ scm_val_print (type, valaddr, address, stream, format, deref_ref, recurse, } else { - return c_val_print (type, valaddr, address, stream, format, + return c_val_print (type, valaddr, 0, address, stream, format, deref_ref, recurse, pretty); } } @@ -416,6 +417,6 @@ scm_value_print (val, stream, format, pretty) int format; enum val_prettyprint pretty; { - return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), + return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), 0, VALUE_ADDRESS (val), stream, format, 1, 0, pretty)); } diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c index 9e571fe..ccaa6dc 100644 --- a/gdb/sol-thread.c +++ b/gdb/sol-thread.c @@ -1512,9 +1512,13 @@ struct target_ops sol_thread_ops = { sol_thread_open, /* to_open */ 0, /* to_close */ sol_thread_attach, /* to_attach */ + NULL, /* to_post_attach */ + NULL, /* to_require_attach */ sol_thread_detach, /* to_detach */ + NULL, /* to_require_detach */ sol_thread_resume, /* to_resume */ sol_thread_wait, /* to_wait */ + NULL, /* to_post_wait */ sol_thread_fetch_registers, /* to_fetch_registers */ sol_thread_store_registers, /* to_store_registers */ sol_thread_prepare_to_store, /* to_prepare_to_store */ @@ -1531,11 +1535,33 @@ struct target_ops sol_thread_ops = { 0, /* to_load */ 0, /* to_lookup_symbol */ sol_thread_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + NULL, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ sol_thread_mourn_inferior, /* to_mourn_inferior */ sol_thread_can_run, /* to_can_run */ sol_thread_notice_signals, /* to_notice_signals */ sol_thread_alive, /* to_thread_alive */ sol_thread_stop, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ process_stratum, /* to_stratum */ 0, /* to_next */ 1, /* to_has_all_memory */ @@ -1555,9 +1581,13 @@ struct target_ops sol_core_ops = { sol_core_open, /* to_open */ sol_core_close, /* to_close */ sol_thread_attach, /* XXX to_attach */ + NULL, /* to_post_attach */ + NULL, /* to_require_attach */ sol_core_detach, /* to_detach */ + NULL, /* to_require_detach */ 0, /* to_resume */ 0, /* to_wait */ + NULL, /* to_post_wait */ sol_thread_fetch_registers, /* to_fetch_registers */ 0, /* to_store_registers */ 0, /* to_prepare_to_store */ @@ -1574,11 +1604,33 @@ struct target_ops sol_core_ops = { 0, /* to_load */ 0, /* to_lookup_symbol */ sol_thread_create_inferior, /* XXX to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + NULL, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ 0, /* to_mourn_inferior */ 0, /* to_can_run */ 0, /* to_notice_signals */ 0, /* to_thread_alive */ 0, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ core_stratum, /* to_stratum */ 0, /* to_next */ 0, /* to_has_all_memory */ diff --git a/gdb/sparcl-tdep.c b/gdb/sparcl-tdep.c index 413901d..46cee7f 100644 --- a/gdb/sparcl-tdep.c +++ b/gdb/sparcl-tdep.c @@ -902,9 +902,13 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; sparclite_ops.to_open = sparclite_open; sparclite_ops.to_close = sparclite_close; sparclite_ops.to_attach = 0; - sparclite_ops.to_detach = 0; + sparclite_ops.to_post_attach = NULL; + sparclite_ops.to_require_attach = NULL; + sparclite_ops.to_detach = 0; + sparclite_ops.to_require_detach = NULL; sparclite_ops.to_resume = 0; - sparclite_ops.to_wait = 0; + sparclite_ops.to_wait = 0; + sparclite_ops.to_post_wait = NULL; sparclite_ops.to_fetch_registers = 0; sparclite_ops.to_store_registers = 0; sparclite_ops.to_prepare_to_store = 0; @@ -920,12 +924,31 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; sparclite_ops.to_kill = 0; sparclite_ops.to_load = sparclite_download; sparclite_ops.to_lookup_symbol = 0; - sparclite_ops.to_create_inferior = 0; + sparclite_ops.to_create_inferior = 0; + sparclite_ops.to_post_startup_inferior = NULL; + sparclite_ops.to_acknowledge_created_inferior = NULL; + sparclite_ops.to_clone_and_follow_inferior = NULL; + sparclite_ops.to_post_follow_inferior_by_clone = NULL; + sparclite_ops.to_insert_fork_catchpoint = NULL; + sparclite_ops.to_remove_fork_catchpoint = NULL; + sparclite_ops.to_insert_vfork_catchpoint = NULL; + sparclite_ops.to_remove_vfork_catchpoint = NULL; + sparclite_ops.to_has_forked = NULL; + sparclite_ops.to_has_vforked = NULL; + sparclite_ops.to_can_follow_vfork_prior_to_exec = NULL; + sparclite_ops.to_post_follow_vfork = NULL; + sparclite_ops.to_insert_exec_catchpoint = NULL; + sparclite_ops.to_remove_exec_catchpoint = NULL; + sparclite_ops.to_has_execd = NULL; + sparclite_ops.to_reported_exec_events_per_exec_call = NULL; + sparclite_ops.to_has_exited = NULL; sparclite_ops.to_mourn_inferior = 0; sparclite_ops.to_can_run = 0; sparclite_ops.to_notice_signals = 0; sparclite_ops.to_thread_alive = 0; - sparclite_ops.to_stop = 0; + sparclite_ops.to_stop = 0; + sparclite_ops.to_pid_to_exec_file = NULL; + sparclite_ops.to_core_file_to_sym_file = NULL; sparclite_ops.to_stratum = download_stratum; sparclite_ops.DONT_USE = 0; sparclite_ops.to_has_all_memory = 0; diff --git a/gdb/symtab.c b/gdb/symtab.c index a1a2c8e..b54c9f6 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1,5 +1,5 @@ /* Symbol table lookup for the GNU debugger, GDB. - Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 1997 + Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. This file is part of GDB. @@ -45,56 +45,65 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Prototypes for local functions */ -static int -find_methods PARAMS ((struct type *, char *, struct symbol **)); +static int find_methods PARAMS ((struct type *, char *, struct symbol **)); -static void -completion_list_add_name PARAMS ((char *, char *, int, char *, char *)); +static void completion_list_add_name PARAMS ((char *, char *, int, char *, + char *)); -static void -build_canonical_line_spec PARAMS ((struct symtab_and_line *, char *, char ***)); +static void build_canonical_line_spec PARAMS ((struct symtab_and_line *, + char *, char ***)); -static struct symtabs_and_lines -decode_line_2 PARAMS ((struct symbol *[], int, int, char ***)); +static struct symtabs_and_lines decode_line_2 PARAMS ((struct symbol *[], + int, int, char ***)); -static void -rbreak_command PARAMS ((char *, int)); +static void rbreak_command PARAMS ((char *, int)); -static void -types_info PARAMS ((char *, int)); +static void types_info PARAMS ((char *, int)); -static void -functions_info PARAMS ((char *, int)); +static void functions_info PARAMS ((char *, int)); -static void -variables_info PARAMS ((char *, int)); +static void variables_info PARAMS ((char *, int)); -static void -sources_info PARAMS ((char *, int)); +static void sources_info PARAMS ((char *, int)); -static void -output_source_filename PARAMS ((char *, int *)); +static void output_source_filename PARAMS ((char *, int *)); -char * -operator_chars PARAMS ((char *, char **)); +char *operator_chars PARAMS ((char *, char **)); static int find_line_common PARAMS ((struct linetable *, int, int *)); -static struct partial_symbol * -lookup_partial_symbol PARAMS ((struct partial_symtab *, const char *, - int, namespace_enum)); +static struct partial_symbol *lookup_partial_symbol PARAMS + ((struct partial_symtab *, const char *, + int, namespace_enum)); -static struct partial_symbol * -fixup_psymbol_section PARAMS ((struct partial_symbol *, struct objfile *)); +static struct partial_symbol *fixup_psymbol_section PARAMS ((struct + partial_symbol *, struct objfile *)); -static struct symtab * -lookup_symtab_1 PARAMS ((char *)); +static struct symtab *lookup_symtab_1 PARAMS ((char *)); -static void -cplusplus_hint PARAMS ((char *)); +static void cplusplus_hint PARAMS ((char *)); -static struct symbol * -find_active_alias PARAMS ((struct symbol *sym, CORE_ADDR addr)); +static struct symbol *find_active_alias PARAMS ((struct symbol *sym, + CORE_ADDR addr)); + +/* This flag is used in hppa-tdep.c, and set in hp-symtab-read.c */ +/* Signals the presence of objects compiled by HP compilers */ +int hp_som_som_object_present = 0; + +static void fixup_section PARAMS ((struct general_symbol_info *, + struct objfile *)); + +static int file_matches PARAMS ((char *, char **, int)); + +static void print_symbol_info PARAMS ((namespace_enum, + struct symtab *, struct symbol *, + int, char *)); + +static void print_msymbol_info PARAMS ((struct minimal_symbol *)); + +static void symtab_symbol_info PARAMS ((char *, namespace_enum, int)); + +void _initialize_symtab PARAMS ((void)); /* */ @@ -887,6 +896,120 @@ lookup_partial_symbol (pst, name, global, namespace) return (NULL); } +/* Look up a type named NAME in the struct_namespace. The type returned + must not be opaque -- i.e., must have at least one field defined + + This code was modelled on lookup_symbol -- the parts not relevant to looking + up types were just left out. In particular it's assumed here that types + are available in struct_namespace and only at file-static or global blocks. */ + + +struct type * +lookup_transparent_type (name) + const char *name; +{ + register struct symbol *sym; + register struct symtab *s = NULL; + register struct partial_symtab *ps; + struct blockvector *bv; + register struct objfile *objfile; + register struct block *block; + register struct minimal_symbol *msymbol; + + /* Now search all the global symbols. Do the symtab's first, then + check the psymtab's. If a psymtab indicates the existence + of the desired name as a global, then do psymtab-to-symtab + conversion on the fly and return the found symbol. */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE); + if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + { + return SYMBOL_TYPE (sym); + } + } + + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, 1, STRUCT_NAMESPACE)) + { + s = PSYMTAB_TO_SYMTAB(ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE); + if (!sym) + { + /* This shouldn't be necessary, but as a last resort + * try looking in the statics even though the psymtab + * claimed the symbol was global. It's possible that + * the psymtab gets it wrong in some cases. + */ + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE); + if (!sym) + error ("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s<type>).", + name, ps->filename, name, name); + } + if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + return SYMBOL_TYPE (sym); + } + } + + /* Now search the static file-level symbols. + Not strictly correct, but more useful than an error. + Do the symtab's first, then + check the psymtab's. If a psymtab indicates the existence + of the desired name as a file-level static, then do psymtab-to-symtab + conversion on the fly and return the found symbol. + */ + + ALL_SYMTABS (objfile, s) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE); + if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + { + return SYMBOL_TYPE (sym); + } + } + + ALL_PSYMTABS (objfile, ps) + { + if (!ps->readin && lookup_partial_symbol (ps, name, 0, STRUCT_NAMESPACE)) + { + s = PSYMTAB_TO_SYMTAB(ps); + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE); + if (!sym) + { + /* This shouldn't be necessary, but as a last resort + * try looking in the globals even though the psymtab + * claimed the symbol was static. It's possible that + * the psymtab gets it wrong in some cases. + */ + block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + sym = lookup_block_symbol (block, name, STRUCT_NAMESPACE); + if (!sym) + error ("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\ +%s may be an inlined function, or may be a template function\n\ +(if a template, try specifying an instantiation: %s<type>).", + name, ps->filename, name, name); + } + if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym))) + return SYMBOL_TYPE (sym); + } + } + return (struct type *) 0; +} + + /* Find the psymtab containing main(). */ /* FIXME: What about languages without main() or specially linked executables that have no main() ? */ @@ -1912,10 +2035,12 @@ find_methods (t, name, sym_arr) if (strncmp (method_name, "__", 2) == 0 || strncmp (method_name, "op", 2) == 0 || strncmp (method_name, "type", 4) == 0) - if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI)) - method_name = dem_opname; - else if (cplus_demangle_opname (method_name, dem_opname, 0)) - method_name = dem_opname; + { + if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI)) + method_name = dem_opname; + else if (cplus_demangle_opname (method_name, dem_opname, 0)) + method_name = dem_opname; + } if (STREQ (name, method_name)) /* Find all the overloaded methods with that name. */ @@ -2575,16 +2700,16 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line, canonical) msymbol = lookup_minimal_symbol (copy, NULL, NULL); if (msymbol != NULL) { - val.pc = SYMBOL_VALUE_ADDRESS (msymbol); - val.section = SYMBOL_BFD_SECTION (msymbol); + values.sals = (struct symtab_and_line *) + xmalloc (sizeof (struct symtab_and_line)); + values.sals[0] = find_pc_sect_line ( SYMBOL_VALUE_ADDRESS (msymbol), + (struct sec *)0,0 ); + values.sals[0].section = SYMBOL_BFD_SECTION (msymbol); if (funfirstline) { - val.pc += FUNCTION_START_OFFSET; - SKIP_PROLOGUE (val.pc); + values.sals[0].pc += FUNCTION_START_OFFSET; + SKIP_PROLOGUE (values.sals[0].pc); } - values.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - values.sals[0] = val; values.nelts = 1; return values; } @@ -2669,12 +2794,9 @@ decode_line_2 (sym_arr, nelts, funfirstline, canonical) if ((prompt = getenv ("PS2")) == NULL) { - prompt = ">"; + prompt = "> "; } - printf_unfiltered("%s ",prompt); - gdb_flush(gdb_stdout); - - args = command_line_input ((char *) NULL, 0, "overload-choice"); + args = command_line_input (prompt, 0, "overload-choice"); if (args == 0 || *args == 0) error_no_arg ("one or more choice numbers"); @@ -2904,7 +3026,8 @@ search_symbols (regexp, kind, nfiles, files, matches) register struct blockvector *bv; struct blockvector *prev_bv = 0; register struct block *b; - register int i, j; + register int i = 0; + register int j; register struct symbol *sym; struct partial_symbol **psym; struct objfile *objfile; @@ -3104,7 +3227,8 @@ search_symbols (regexp, kind, nfiles, files, matches) if (tail == NULL) { sr = psr; - old_chain = make_cleanup (free_search_symbols, sr); + old_chain = make_cleanup ((make_cleanup_func) + free_search_symbols, sr); } else tail->next = psr; @@ -3148,7 +3272,8 @@ search_symbols (regexp, kind, nfiles, files, matches) if (tail == NULL) { sr = psr; - old_chain = make_cleanup (free_search_symbols, &sr); + old_chain = make_cleanup ((make_cleanup_func) + free_search_symbols, &sr); } else tail->next = psr; @@ -3169,7 +3294,7 @@ search_symbols (regexp, kind, nfiles, files, matches) the data returned from search_symbols() to print information regarding the match to gdb_stdout. */ -static int +static void print_symbol_info (kind, s, sym, block, last) namespace_enum kind; struct symtab *s; @@ -3262,7 +3387,7 @@ symtab_symbol_info (regexp, kind, from_tty) /* must make sure that if we're interrupted, symbols gets freed */ search_symbols (regexp, kind, 0, (char **) NULL, &symbols); - old_chain = make_cleanup (free_search_symbols, symbols); + old_chain = make_cleanup ((make_cleanup_func) free_search_symbols, symbols); printf_filtered (regexp ? "All %ss matching regular expression \"%s\":\n" @@ -3341,7 +3466,7 @@ rbreak_command (regexp, from_tty) struct cleanup *old_chain; search_symbols (regexp, FUNCTIONS_NAMESPACE, 0, (char **) NULL, &ss); - old_chain = make_cleanup (free_search_symbols, ss); + old_chain = make_cleanup ((make_cleanup_func) free_search_symbols, ss); for (p = ss; p != NULL; p = p->next) { diff --git a/gdb/symtab.h b/gdb/symtab.h index 977a99d..bb58086 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -28,8 +28,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define obstack_chunk_free free #include "bcache.h" -#include "gnu-regex.h" - /* Don't do this; it means that if some .o's are compiled with GNU C and some are not (easy to do accidentally the way we configure things; also it is a pain to have to "make clean" every time you @@ -630,10 +628,26 @@ enum address_class LOC_UNRESOLVED, + /* Value is at a thread-specific location calculated by a + target-specific method. */ + + LOC_THREAD_LOCAL_STATIC, + /* The variable does not actually exist in the program. The value is ignored. */ - LOC_OPTIMIZED_OUT + LOC_OPTIMIZED_OUT, + + /* The variable is static, but actually lives at * (address). + * I.e. do an extra indirection to get to it. + * This is used on HP-UX to get at globals that are allocated + * in shared libraries, where references from images other + * than the one where the global was allocated are done + * with a level of indirection. + */ + + LOC_INDIRECT + }; /* Linked list of symbol's live ranges. */ @@ -1177,6 +1191,10 @@ contained_in PARAMS ((struct block *, struct block *)); extern void reread_symbols PARAMS ((void)); +extern struct type * +lookup_transparent_type PARAMS ((const char *)); + + /* Macro for name of symbol to indicate a file compiled with gcc. */ #ifndef GCC_COMPILED_FLAG_SYMBOL #define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." @@ -1270,6 +1288,41 @@ struct symtabs_and_lines int nelts; }; + + +/* Some types and macros needed for exception catchpoints. + Can't put these in target.h because symtab_and_line isn't + known there. This file will be included by breakpoint.c, + hppa-tdep.c, etc. */ + +/* Enums for exception-handling support */ +enum exception_event_kind { + EX_EVENT_THROW, + EX_EVENT_CATCH +}; + +/* Type for returning info about an exception */ +struct exception_event_record { + enum exception_event_kind kind; + struct symtab_and_line throw_sal; + struct symtab_and_line catch_sal; + /* This may need to be extended in the future, if + some platforms allow reporting more information, + such as point of rethrow, type of exception object, + type expected by catch clause, etc. */ +}; + +#define CURRENT_EXCEPTION_KIND (current_exception_event->kind) +#define CURRENT_EXCEPTION_CATCH_SAL (current_exception_event->catch_sal) +#define CURRENT_EXCEPTION_CATCH_LINE (current_exception_event->catch_sal.line) +#define CURRENT_EXCEPTION_CATCH_FILE (current_exception_event->catch_sal.symtab->filename) +#define CURRENT_EXCEPTION_CATCH_PC (current_exception_event->catch_sal.pc) +#define CURRENT_EXCEPTION_THROW_SAL (current_exception_event->throw_sal) +#define CURRENT_EXCEPTION_THROW_LINE (current_exception_event->throw_sal.line) +#define CURRENT_EXCEPTION_THROW_FILE (current_exception_event->throw_sal.symtab->filename) +#define CURRENT_EXCEPTION_THROW_PC (current_exception_event->throw_sal.pc) + + /* Given a pc value, return line number it is in. Second arg nonzero means if pc is on the boundary use the previous statement's line number. */ @@ -1368,7 +1421,8 @@ select_source_symtab PARAMS ((struct symtab *)); extern char **make_symbol_completion_list PARAMS ((char *, char *)); -extern void _initialize_source PARAMS ((void)); +extern struct symbol ** +make_symbol_overload_list PARAMS ((struct symbol *)); /* symtab.c */ diff --git a/gdb/target.c b/gdb/target.c index 44c90b7..736d200 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -44,6 +44,9 @@ static void maybe_kill_then_create_inferior PARAMS ((char *, char *, char **)); static void +default_clone_and_follow_inferior PARAMS ((int, int *)); + +static void maybe_kill_then_attach PARAMS ((char *, int)); static void @@ -64,8 +67,11 @@ nomemory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); static int return_zero PARAMS ((void)); -static void -ignore PARAMS ((void)); +static int +return_one PARAMS ((void)); + +void +target_ignore PARAMS ((void)); static void target_command PARAMS ((char *, int)); @@ -185,9 +191,13 @@ struct target_ops dummy_target = { 0, /* to_open */ 0, /* to_close */ find_default_attach, /* to_attach */ + NULL, /* to_post_attach */ + find_default_require_attach, /* to_require_attach */ 0, /* to_detach */ + find_default_require_detach, /* to_require_detach */ 0, /* to_resume */ 0, /* to_wait */ + NULL, /* to_post_wait */ 0, /* to_fetch_registers */ 0, /* to_store_registers */ 0, /* to_prepare_to_store */ @@ -204,11 +214,33 @@ struct target_ops dummy_target = { 0, /* to_load */ 0, /* to_lookup_symbol */ find_default_create_inferior, /* to_create_inferior */ + NULL, /* to_post_startup_inferior */ + NULL, /* to_acknowledge_created_inferior */ + find_default_clone_and_follow_inferior, /* to_clone_and_follow_inferior */ + NULL, /* to_post_follow_inferior_by_clone */ + NULL, /* to_insert_fork_catchpoint */ + NULL, /* to_remove_fork_catchpoint */ + NULL, /* to_insert_vfork_catchpoint */ + NULL, /* to_remove_vfork_catchpoint */ + NULL, /* to_has_forked */ + NULL, /* to_has_vforked */ + NULL, /* to_can_follow_vfork_prior_to_exec */ + NULL, /* to_post_follow_vfork */ + NULL, /* to_insert_exec_catchpoint */ + NULL, /* to_remove_exec_catchpoint */ + NULL, /* to_has_execd */ + NULL, /* to_reported_exec_events_per_exec_call */ + NULL, /* to_has_syscall_event */ + NULL, /* to_has_exited */ 0, /* to_mourn_inferior */ 0, /* to_can_run */ 0, /* to_notice_signals */ 0, /* to_thread_alive */ 0, /* to_stop */ + NULL, /* to_enable_exception_callback */ + NULL, /* to_get_current_exception_event */ + NULL, /* to_pid_to_exec_file */ + NULL, /* to_core_file_to_sym_file */ dummy_stratum, /* to_stratum */ 0, /* to_next */ 0, /* to_has_all_memory */ @@ -295,8 +327,8 @@ information on the arguments for a particular protocol, type\n\ /* Stub functions */ -static void -ignore () +void +target_ignore () { } @@ -336,6 +368,17 @@ nosymbol (name, addrp) } /* ARGSUSED */ +void +nosupport_runtime () +{ + if (!inferior_pid) + noprocess (); + else + error ("No run-time support for this"); +} + + +/* ARGSUSED */ static void default_terminal_info (args, from_tty) char *args; @@ -388,6 +431,14 @@ maybe_kill_then_create_inferior (exec, args, env) target_create_inferior (exec, args, env); } +static void +default_clone_and_follow_inferior (child_pid, followed_child) + int child_pid; + int *followed_child; +{ + target_clone_and_follow_inferior (child_pid, followed_child); +} + /* Clean up a target struct so it no longer has any zero pointers in it. We default entries, at least to stubs that print error messages. */ @@ -402,33 +453,59 @@ cleanup_target (t) /* FIELD DEFAULT VALUE */ de_fault (to_open, (void (*) PARAMS((char *, int))) tcomplain); - de_fault (to_close, (void (*) PARAMS((int))) ignore); + de_fault (to_close, (void (*) PARAMS((int))) target_ignore); de_fault (to_attach, maybe_kill_then_attach); - de_fault (to_detach, (void (*) PARAMS((char *, int))) ignore); + de_fault (to_post_attach, (void (*) PARAMS ((int))) target_ignore); + de_fault (to_require_attach, maybe_kill_then_attach); + de_fault (to_detach, (void (*) PARAMS((char *, int))) target_ignore); + de_fault (to_require_detach, (void (*) PARAMS((int, char *, int))) target_ignore); de_fault (to_resume, (void (*) PARAMS((int, int, enum target_signal))) noprocess); de_fault (to_wait, (int (*) PARAMS((int, struct target_waitstatus *))) noprocess); - de_fault (to_fetch_registers, (void (*) PARAMS((int))) ignore); + de_fault (to_post_wait, (void (*) PARAMS ((int, int))) target_ignore); + de_fault (to_fetch_registers, (void (*) PARAMS((int))) target_ignore); de_fault (to_store_registers, (void (*) PARAMS((int))) noprocess); de_fault (to_prepare_to_store, (void (*) PARAMS((void))) noprocess); de_fault (to_xfer_memory, (int (*) PARAMS((CORE_ADDR, char *, int, int, struct target_ops *))) nomemory); - de_fault (to_files_info, (void (*) PARAMS((struct target_ops *))) ignore); + de_fault (to_files_info, (void (*) PARAMS((struct target_ops *))) target_ignore); de_fault (to_insert_breakpoint, memory_insert_breakpoint); de_fault (to_remove_breakpoint, memory_remove_breakpoint); - de_fault (to_terminal_init, (void (*) PARAMS((void))) ignore); - de_fault (to_terminal_inferior, (void (*) PARAMS ((void))) ignore); - de_fault (to_terminal_ours_for_output,(void (*) PARAMS ((void))) ignore); - de_fault (to_terminal_ours, (void (*) PARAMS ((void))) ignore); + de_fault (to_terminal_init, (void (*) PARAMS((void))) target_ignore); + de_fault (to_terminal_inferior, (void (*) PARAMS ((void))) target_ignore); + de_fault (to_terminal_ours_for_output,(void (*) PARAMS ((void))) target_ignore); + de_fault (to_terminal_ours, (void (*) PARAMS ((void))) target_ignore); de_fault (to_terminal_info, default_terminal_info); de_fault (to_kill, (void (*) PARAMS((void))) noprocess); de_fault (to_load, (void (*) PARAMS((char *, int))) tcomplain); de_fault (to_lookup_symbol, (int (*) PARAMS ((char *, CORE_ADDR *))) nosymbol); de_fault (to_create_inferior, maybe_kill_then_create_inferior); - de_fault (to_mourn_inferior, (void (*) PARAMS((void))) noprocess); + de_fault (to_post_startup_inferior, (void (*) PARAMS ((int))) target_ignore); + de_fault (to_acknowledge_created_inferior, (void (*) PARAMS((int))) target_ignore); + de_fault (to_clone_and_follow_inferior, default_clone_and_follow_inferior); + de_fault (to_post_follow_inferior_by_clone, (void (*) PARAMS ((void))) target_ignore); + de_fault (to_insert_fork_catchpoint, (int (*) PARAMS ((int))) tcomplain); + de_fault (to_remove_fork_catchpoint, (int (*) PARAMS ((int))) tcomplain); + de_fault (to_insert_vfork_catchpoint, (int (*) PARAMS ((int))) tcomplain); + de_fault (to_remove_vfork_catchpoint, (int (*) PARAMS ((int))) tcomplain); + de_fault (to_has_forked, (int (*) PARAMS ((int, int *))) return_zero); + de_fault (to_has_vforked, (int (*) PARAMS ((int, int *))) return_zero); + de_fault (to_can_follow_vfork_prior_to_exec, (int (*) PARAMS ((void ))) return_zero); + de_fault (to_post_follow_vfork, (void (*) PARAMS ((int, int, int, int))) target_ignore); + de_fault (to_insert_exec_catchpoint, (int (*) PARAMS ((int))) tcomplain); + de_fault (to_remove_exec_catchpoint, (int (*) PARAMS ((int))) tcomplain); + de_fault (to_has_execd, (int (*) PARAMS ((int, char **))) return_zero); + de_fault (to_reported_exec_events_per_exec_call, (int (*) PARAMS ((void))) return_one); + de_fault (to_has_syscall_event, (int (*) PARAMS ((int, enum target_waitkind *, int *))) return_zero); + de_fault (to_has_exited, (int (*) PARAMS ((int, int, int *))) return_zero); + de_fault (to_mourn_inferior, (void (*) PARAMS ((void))) noprocess); de_fault (to_can_run, return_zero); - de_fault (to_notice_signals, (void (*) PARAMS((int))) ignore); - de_fault (to_thread_alive, (int (*) PARAMS((int))) ignore); - de_fault (to_stop, (void (*) PARAMS((void))) ignore); - + de_fault (to_notice_signals, (void (*) PARAMS((int))) target_ignore); + de_fault (to_thread_alive, (int (*) PARAMS((int))) target_ignore); + de_fault (to_stop, (void (*) PARAMS((void))) target_ignore); + de_fault (to_enable_exception_callback, (struct symtab_and_line * (*) PARAMS((enum exception_event_kind, int))) nosupport_runtime); + de_fault (to_get_current_exception_event, (struct exception_event_record * (*) PARAMS((void))) nosupport_runtime); + + de_fault (to_pid_to_exec_file, (char* (*) PARAMS((int))) return_zero); + de_fault (to_core_file_to_sym_file, (char* (*) PARAMS ((char *))) return_zero); #undef de_fault } @@ -459,9 +536,13 @@ update_current_target () INHERIT (to_open, t); INHERIT (to_close, t); INHERIT (to_attach, t); + INHERIT (to_post_attach, t); + INHERIT (to_require_attach, t); INHERIT (to_detach, t); + INHERIT (to_require_detach, t); INHERIT (to_resume, t); INHERIT (to_wait, t); + INHERIT (to_post_wait, t); INHERIT (to_fetch_registers, t); INHERIT (to_store_registers, t); INHERIT (to_prepare_to_store, t); @@ -478,11 +559,33 @@ update_current_target () INHERIT (to_load, t); INHERIT (to_lookup_symbol, t); INHERIT (to_create_inferior, t); + INHERIT (to_post_startup_inferior, t); + INHERIT (to_acknowledge_created_inferior, t); + INHERIT (to_clone_and_follow_inferior, t); + INHERIT (to_post_follow_inferior_by_clone, t); + INHERIT (to_insert_fork_catchpoint, t); + INHERIT (to_remove_fork_catchpoint, t); + INHERIT (to_insert_vfork_catchpoint, t); + INHERIT (to_remove_vfork_catchpoint, t); + INHERIT (to_has_forked, t); + INHERIT (to_has_vforked, t); + INHERIT (to_can_follow_vfork_prior_to_exec, t); + INHERIT (to_post_follow_vfork, t); + INHERIT (to_insert_exec_catchpoint, t); + INHERIT (to_remove_exec_catchpoint, t); + INHERIT (to_has_execd, t); + INHERIT (to_reported_exec_events_per_exec_call, t); + INHERIT (to_has_syscall_event, t); + INHERIT (to_has_exited, t); INHERIT (to_mourn_inferior, t); INHERIT (to_can_run, t); INHERIT (to_notice_signals, t); INHERIT (to_thread_alive, t); INHERIT (to_stop, t); + INHERIT (to_enable_exception_callback, t); + INHERIT (to_get_current_exception_event, t); + INHERIT (to_pid_to_exec_file, t); + INHERIT (to_core_file_to_sym_file, t); INHERIT (to_stratum, t); INHERIT (DONT_USE, t); INHERIT (to_has_all_memory, t); @@ -1001,6 +1104,31 @@ find_default_attach (args, from_tty) } void +find_default_require_attach (args, from_tty) + char *args; + int from_tty; +{ + struct target_ops *t; + + t = find_default_run_target("require_attach"); + (t->to_require_attach) (args, from_tty); + return; +} + +void +find_default_require_detach (pid, args, from_tty) + int pid; + char * args; + int from_tty; +{ + struct target_ops *t; + + t = find_default_run_target("require_detach"); + (t->to_require_detach) (pid, args, from_tty); + return; +} + +void find_default_create_inferior (exec_file, allargs, env) char *exec_file; char *allargs; @@ -1013,12 +1141,30 @@ find_default_create_inferior (exec_file, allargs, env) return; } +void +find_default_clone_and_follow_inferior (child_pid, followed_child) + int child_pid; + int *followed_child; +{ + struct target_ops *t; + + t = find_default_run_target("run"); + (t->to_clone_and_follow_inferior) (child_pid, followed_child); + return; +} + static int return_zero () { return 0; } +static int +return_one () +{ + return 1; +} + struct target_ops * find_core_target () { @@ -1116,7 +1262,7 @@ static struct { {"SIGLWP", "Signal LWP"}, {"SIGDANGER", "Swap space dangerously low"}, {"SIGGRANT", "Monitor mode granted"}, - {"SIGRETRACT", "Need to relinguish monitor mode"}, + {"SIGRETRACT", "Need to relinquish monitor mode"}, {"SIGMSG", "Monitor mode data available"}, {"SIGSOUND", "Sound completed"}, {"SIGSAK", "Secure attention"}, @@ -1637,12 +1783,32 @@ normal_pid_to_str (pid) static char buf[30]; if (STREQ (current_target.to_shortname, "remote")) - sprintf (buf, "thread %d", pid); + sprintf (buf, "thread %d\0", pid); else - sprintf (buf, "process %d", pid); + sprintf (buf, "process %d\0", pid); return buf; } + +/* Some targets (such as ttrace-based HPUX) don't allow us to request + notification of inferior events such as fork and vork immediately + after the inferior is created. (This because of how gdb gets an + inferior created via invoking a shell to do it. In such a scenario, + if the shell init file has commands in it, the shell will fork and + exec for each of those commands, and we will see each such fork + event. Very bad.) + + This function is used by all targets that allow us to request + notification of forks, etc at inferior creation time; e.g., in + target_acknowledge_forked_child. + */ +void +normal_target_post_startup_inferior (pid) + int pid; +{ + /* This space intentionally left blank. */ +} + #ifdef MAINTENANCE_CMDS static struct target_ops debug_target; @@ -1654,7 +1820,7 @@ debug_to_open (args, from_tty) { debug_target.to_open (args, from_tty); - fprintf_unfiltered (stderr, "target_open (%s, %d)\n", args, from_tty); + fprintf_unfiltered (gdb_stderr, "target_open (%s, %d)\n", args, from_tty); } static void @@ -1663,7 +1829,7 @@ debug_to_close (quitting) { debug_target.to_close (quitting); - fprintf_unfiltered (stderr, "target_close (%d)\n", quitting); + fprintf_unfiltered (gdb_stderr, "target_close (%d)\n", quitting); } static void @@ -1673,7 +1839,28 @@ debug_to_attach (args, from_tty) { debug_target.to_attach (args, from_tty); - fprintf_unfiltered (stderr, "target_attach (%s, %d)\n", args, from_tty); + fprintf_unfiltered (gdb_stderr, "target_attach (%s, %d)\n", args, from_tty); +} + + +static void +debug_to_post_attach (pid) + int pid; +{ + debug_target.to_post_attach (pid); + + fprintf_unfiltered (gdb_stderr, "target_post_attach (%d)\n", pid); +} + +static void +debug_to_require_attach (args, from_tty) + char *args; + int from_tty; +{ + debug_target.to_require_attach (args, from_tty); + + fprintf_unfiltered (gdb_stderr, + "target_require_attach (%s, %d)\n", args, from_tty); } static void @@ -1683,7 +1870,19 @@ debug_to_detach (args, from_tty) { debug_target.to_detach (args, from_tty); - fprintf_unfiltered (stderr, "target_detach (%s, %d)\n", args, from_tty); + fprintf_unfiltered (gdb_stderr, "target_detach (%s, %d)\n", args, from_tty); +} + +static void +debug_to_require_detach (pid, args, from_tty) + int pid; + char * args; + int from_tty; +{ + debug_target.to_require_detach (pid, args, from_tty); + + fprintf_unfiltered (gdb_stderr, + "target_require_detach (%d, %s, %d)\n", pid, args, from_tty); } static void @@ -1694,7 +1893,7 @@ debug_to_resume (pid, step, siggnal) { debug_target.to_resume (pid, step, siggnal); - fprintf_unfiltered (stderr, "target_resume (%d, %s, %s)\n", pid, + fprintf_unfiltered (gdb_stderr, "target_resume (%d, %s, %s)\n", pid, step ? "step" : "continue", target_signal_to_name (siggnal)); } @@ -1708,29 +1907,40 @@ debug_to_wait (pid, status) retval = debug_target.to_wait (pid, status); - fprintf_unfiltered (stderr, "target_wait (%d, status) = %d, ", pid, retval); - fprintf_unfiltered (stderr, "status->kind = "); + fprintf_unfiltered (gdb_stderr, + "target_wait (%d, status) = %d, ", pid, retval); + fprintf_unfiltered (gdb_stderr, "status->kind = "); switch (status->kind) { case TARGET_WAITKIND_EXITED: - fprintf_unfiltered (stderr, "exited, status = %d\n", status->value.integer); + fprintf_unfiltered (gdb_stderr, "exited, status = %d\n", + status->value.integer); break; case TARGET_WAITKIND_STOPPED: - fprintf_unfiltered (stderr, "stopped, signal = %s\n", + fprintf_unfiltered (gdb_stderr, "stopped, signal = %s\n", target_signal_to_name (status->value.sig)); break; case TARGET_WAITKIND_SIGNALLED: - fprintf_unfiltered (stderr, "signalled, signal = %s\n", + fprintf_unfiltered (gdb_stderr, "signalled, signal = %s\n", target_signal_to_name (status->value.sig)); break; case TARGET_WAITKIND_LOADED: - fprintf_unfiltered (stderr, "loaded\n"); + fprintf_unfiltered (gdb_stderr, "loaded\n"); + break; + case TARGET_WAITKIND_FORKED: + fprintf_unfiltered (gdb_stderr, "forked\n"); + break; + case TARGET_WAITKIND_VFORKED: + fprintf_unfiltered (gdb_stderr, "vforked\n"); + break; + case TARGET_WAITKIND_EXECD: + fprintf_unfiltered (gdb_stderr, "execd\n"); break; case TARGET_WAITKIND_SPURIOUS: - fprintf_unfiltered (stderr, "spurious\n"); + fprintf_unfiltered (gdb_stderr, "spurious\n"); break; default: - fprintf_unfiltered (stderr, "unknown???\n"); + fprintf_unfiltered (gdb_stderr, "unknown???\n"); break; } @@ -1738,18 +1948,29 @@ debug_to_wait (pid, status) } static void +debug_to_post_wait (pid, status) + int pid; + int status; +{ + debug_target.to_post_wait (pid, status); + + fprintf_unfiltered (gdb_stderr, "target_post_wait (%d, %d)\n", + pid, status); +} + +static void debug_to_fetch_registers (regno) int regno; { debug_target.to_fetch_registers (regno); - fprintf_unfiltered (stderr, "target_fetch_registers (%s)", - regno != -1 ? reg_names[regno] : "-1"); + fprintf_unfiltered (gdb_stderr, "target_fetch_registers (%s)", + regno != -1 ? REGISTER_NAME (regno) : "-1"); if (regno != -1) - fprintf_unfiltered (stderr, " = 0x%x %d", + fprintf_unfiltered (gdb_stderr, " = 0x%x %d", (unsigned long) read_register (regno), read_register (regno)); - fprintf_unfiltered (stderr, "\n"); + fprintf_unfiltered (gdb_stderr, "\n"); } static void @@ -1759,12 +1980,12 @@ debug_to_store_registers (regno) debug_target.to_store_registers (regno); if (regno >= 0 && regno < NUM_REGS) - fprintf_unfiltered (stderr, "target_store_registers (%s) = 0x%x %d\n", - reg_names[regno], + fprintf_unfiltered (gdb_stderr, "target_store_registers (%s) = 0x%x %d\n", + REGISTER_NAME (regno), (unsigned long) read_register (regno), (unsigned long) read_register (regno)); else - fprintf_unfiltered (stderr, "target_store_registers (%d)\n", regno); + fprintf_unfiltered (gdb_stderr, "target_store_registers (%d)\n", regno); } static void @@ -1772,7 +1993,7 @@ debug_to_prepare_to_store () { debug_target.to_prepare_to_store (); - fprintf_unfiltered (stderr, "target_prepare_to_store ()\n"); + fprintf_unfiltered (gdb_stderr, "target_prepare_to_store ()\n"); } static int @@ -1787,7 +2008,7 @@ debug_to_xfer_memory (memaddr, myaddr, len, write, target) retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target); - fprintf_unfiltered (stderr, + fprintf_unfiltered (gdb_stderr, "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d", (unsigned int) memaddr, /* possable truncate long long */ len, write ? "write" : "read", retval); @@ -1802,8 +2023,8 @@ debug_to_xfer_memory (memaddr, myaddr, len, write, target) for (i = 0; i < retval; i++) { if ((((long) &(myaddr[i])) & 0xf) == 0) - fprintf_unfiltered (stderr, "\n"); - fprintf_unfiltered (stderr, " %02x", myaddr[i] & 0xff); + fprintf_unfiltered (gdb_stderr, "\n"); + fprintf_unfiltered (gdb_stderr, " %02x", myaddr[i] & 0xff); } } @@ -1818,7 +2039,7 @@ debug_to_files_info (target) { debug_target.to_files_info (target); - fprintf_unfiltered (stderr, "target_files_info (xxx)\n"); + fprintf_unfiltered (gdb_stderr, "target_files_info (xxx)\n"); } static int @@ -1830,7 +2051,8 @@ debug_to_insert_breakpoint (addr, save) retval = debug_target.to_insert_breakpoint (addr, save); - fprintf_unfiltered (stderr, "target_insert_breakpoint (0x%x, xxx) = %d\n", + fprintf_unfiltered (gdb_stderr, + "target_insert_breakpoint (0x%x, xxx) = %d\n", (unsigned long) addr, retval); return retval; } @@ -1844,7 +2066,8 @@ debug_to_remove_breakpoint (addr, save) retval = debug_target.to_remove_breakpoint (addr, save); - fprintf_unfiltered (stderr, "target_remove_breakpoint (0x%x, xxx) = %d\n", + fprintf_unfiltered (gdb_stderr, + "target_remove_breakpoint (0x%x, xxx) = %d\n", (unsigned long)addr, retval); return retval; } @@ -1854,7 +2077,7 @@ debug_to_terminal_init () { debug_target.to_terminal_init (); - fprintf_unfiltered (stderr, "target_terminal_init ()\n"); + fprintf_unfiltered (gdb_stderr, "target_terminal_init ()\n"); } static void @@ -1862,7 +2085,7 @@ debug_to_terminal_inferior () { debug_target.to_terminal_inferior (); - fprintf_unfiltered (stderr, "target_terminal_inferior ()\n"); + fprintf_unfiltered (gdb_stderr, "target_terminal_inferior ()\n"); } static void @@ -1870,7 +2093,7 @@ debug_to_terminal_ours_for_output () { debug_target.to_terminal_ours_for_output (); - fprintf_unfiltered (stderr, "target_terminal_ours_for_output ()\n"); + fprintf_unfiltered (gdb_stderr, "target_terminal_ours_for_output ()\n"); } static void @@ -1878,7 +2101,7 @@ debug_to_terminal_ours () { debug_target.to_terminal_ours (); - fprintf_unfiltered (stderr, "target_terminal_ours ()\n"); + fprintf_unfiltered (gdb_stderr, "target_terminal_ours ()\n"); } static void @@ -1888,7 +2111,7 @@ debug_to_terminal_info (arg, from_tty) { debug_target.to_terminal_info (arg, from_tty); - fprintf_unfiltered (stderr, "target_terminal_info (%s, %d)\n", arg, + fprintf_unfiltered (gdb_stderr, "target_terminal_info (%s, %d)\n", arg, from_tty); } @@ -1897,7 +2120,7 @@ debug_to_kill () { debug_target.to_kill (); - fprintf_unfiltered (stderr, "target_kill ()\n"); + fprintf_unfiltered (gdb_stderr, "target_kill ()\n"); } static void @@ -1907,7 +2130,7 @@ debug_to_load (args, from_tty) { debug_target.to_load (args, from_tty); - fprintf_unfiltered (stderr, "target_load (%s, %d)\n", args, from_tty); + fprintf_unfiltered (gdb_stderr, "target_load (%s, %d)\n", args, from_tty); } static int @@ -1919,7 +2142,7 @@ debug_to_lookup_symbol (name, addrp) retval = debug_target.to_lookup_symbol (name, addrp); - fprintf_unfiltered (stderr, "target_lookup_symbol (%s, xxx)\n", name); + fprintf_unfiltered (gdb_stderr, "target_lookup_symbol (%s, xxx)\n", name); return retval; } @@ -1932,16 +2155,274 @@ debug_to_create_inferior (exec_file, args, env) { debug_target.to_create_inferior (exec_file, args, env); - fprintf_unfiltered (stderr, "target_create_inferior (%s, %s, xxx)\n", + fprintf_unfiltered (gdb_stderr, "target_create_inferior (%s, %s, xxx)\n", exec_file, args); } static void +debug_to_post_startup_inferior (pid) + int pid; +{ + debug_target.to_post_startup_inferior (pid); + + fprintf_unfiltered (gdb_stderr, "target_post_startup_inferior (%d)\n", + pid); +} + +static void +debug_to_acknowledge_created_inferior (pid) + int pid; +{ + debug_target.to_acknowledge_created_inferior (pid); + + fprintf_unfiltered (gdb_stderr, "target_acknowledge_created_inferior (%d)\n", + pid); +} + +static void +debug_to_clone_and_follow_inferior (child_pid, followed_child) + int child_pid; + int *followed_child; +{ + debug_target.to_clone_and_follow_inferior (child_pid, followed_child); + + fprintf_unfiltered (gdb_stderr, + "target_clone_and_follow_inferior (%d, %d)\n", + child_pid, *followed_child); +} + +static void +debug_to_post_follow_inferior_by_clone () +{ + debug_target.to_post_follow_inferior_by_clone (); + + fprintf_unfiltered (gdb_stderr, "target_post_follow_inferior_by_clone ()\n"); +} + +static int +debug_to_insert_fork_catchpoint (pid) + int pid; +{ + int retval; + + retval = debug_target.to_insert_fork_catchpoint (pid); + + fprintf_unfiltered (gdb_stderr, "target_insert_fork_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_remove_fork_catchpoint (pid) + int pid; +{ + int retval; + + retval = debug_target.to_remove_fork_catchpoint (pid); + + fprintf_unfiltered (gdb_stderr, "target_remove_fork_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_insert_vfork_catchpoint (pid) + int pid; +{ + int retval; + + retval = debug_target.to_insert_vfork_catchpoint (pid); + + fprintf_unfiltered (gdb_stderr, "target_insert_vfork_catchpoint (%d)= %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_remove_vfork_catchpoint (pid) + int pid; +{ + int retval; + + retval = debug_target.to_remove_vfork_catchpoint (pid); + + fprintf_unfiltered (gdb_stderr, "target_remove_vfork_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_has_forked (pid, child_pid) + int pid; + int * child_pid; +{ + int has_forked; + + has_forked = debug_target.to_has_forked (pid, child_pid); + + fprintf_unfiltered (gdb_stderr, "target_has_forked (%d, %d) = %d\n", + pid, *child_pid, has_forked); + + return has_forked; +} + +static int +debug_to_has_vforked (pid, child_pid) + int pid; + int * child_pid; +{ + int has_vforked; + + has_vforked = debug_target.to_has_vforked (pid, child_pid); + + fprintf_unfiltered (gdb_stderr, "target_has_vforked (%d, %d) = %d\n", + pid, *child_pid, has_vforked); + + return has_vforked; +} + +static int +debug_to_can_follow_vfork_prior_to_exec () +{ + int can_immediately_follow_vfork; + + can_immediately_follow_vfork = debug_target.to_can_follow_vfork_prior_to_exec (); + + fprintf_unfiltered (gdb_stderr, "target_can_follow_vfork_prior_to_exec () = %d\n", + can_immediately_follow_vfork); + + return can_immediately_follow_vfork; +} + +static void +debug_to_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child) + int parent_pid; + int followed_parent; + int child_pid; + int followed_child; +{ + debug_target.to_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child); + + fprintf_unfiltered (gdb_stderr, + "target_post_follow_vfork (%d, %d, %d, %d)\n", + parent_pid, followed_parent, child_pid, followed_child); +} + +static int +debug_to_insert_exec_catchpoint (pid) + int pid; +{ + int retval; + + retval = debug_target.to_insert_exec_catchpoint (pid); + + fprintf_unfiltered (gdb_stderr, "target_insert_exec_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_remove_exec_catchpoint (pid) + int pid; +{ + int retval; + + retval = debug_target.to_remove_exec_catchpoint (pid); + + fprintf_unfiltered (gdb_stderr, "target_remove_exec_catchpoint (%d) = %d\n", + pid, retval); + + return retval; +} + +static int +debug_to_has_execd (pid, execd_pathname) + int pid; + char ** execd_pathname; +{ + int has_execd; + + has_execd = debug_target.to_has_execd (pid, execd_pathname); + + fprintf_unfiltered (gdb_stderr, "target_has_execd (%d, %s) = %d\n", + pid, *execd_pathname, has_execd); + + return has_execd; +} + +static int +debug_to_reported_exec_events_per_exec_call () +{ + int reported_exec_events; + + reported_exec_events = debug_target.to_reported_exec_events_per_exec_call (); + + fprintf_unfiltered (gdb_stderr, + "target_reported_exec_events_per_exec_call () = %d\n", + reported_exec_events); + + return reported_exec_events; +} + +static int +debug_to_has_syscall_event (pid, kind, syscall_id) + int pid; + enum target_waitkind * kind; + int * syscall_id; +{ + int has_syscall_event; + char * kind_spelling = "??"; + + has_syscall_event = debug_target.to_has_syscall_event (pid, kind, syscall_id); + if (has_syscall_event) + { + switch (*kind) + { + case TARGET_WAITKIND_SYSCALL_ENTRY: + kind_spelling = "SYSCALL_ENTRY"; + break; + case TARGET_WAITKIND_SYSCALL_RETURN: + kind_spelling = "SYSCALL_RETURN"; + break; + default: + break; + } + } + + fprintf_unfiltered (gdb_stderr, + "target_has_syscall_event (%d, %s, %d) = %d\n", + pid, kind_spelling, *syscall_id, has_syscall_event); + + return has_syscall_event; +} + +static int +debug_to_has_exited (pid, wait_status, exit_status) + int pid; + int wait_status; + int * exit_status; +{ + int has_exited; + + has_exited = debug_target.to_has_exited (pid, wait_status, exit_status); + + fprintf_unfiltered (gdb_stderr, "target_has_exited (%d, %d, %d) = %d\n", + pid, wait_status, *exit_status, has_exited); + + return has_exited; +} + +static void debug_to_mourn_inferior () { debug_target.to_mourn_inferior (); - fprintf_unfiltered (stderr, "target_mourn_inferior ()\n"); + fprintf_unfiltered (gdb_stderr, "target_mourn_inferior ()\n"); } static int @@ -1951,7 +2432,7 @@ debug_to_can_run () retval = debug_target.to_can_run (); - fprintf_unfiltered (stderr, "target_can_run () = %d\n", retval); + fprintf_unfiltered (gdb_stderr, "target_can_run () = %d\n", retval); return retval; } @@ -1962,7 +2443,7 @@ debug_to_notice_signals (pid) { debug_target.to_notice_signals (pid); - fprintf_unfiltered (stderr, "target_notice_signals (%d)\n", pid); + fprintf_unfiltered (gdb_stderr, "target_notice_signals (%d)\n", pid); } static int @@ -1973,7 +2454,8 @@ debug_to_thread_alive (pid) retval = debug_target.to_thread_alive (pid); - fprintf_unfiltered (stderr, "target_thread_alive (%d) = %d\n", pid, retval); + fprintf_unfiltered (gdb_stderr, "target_thread_alive (%d) = %d\n", + pid, retval); return retval; } @@ -1983,7 +2465,55 @@ debug_to_stop () { debug_target.to_stop (); - fprintf_unfiltered (stderr, "target_stop ()\n"); + fprintf_unfiltered (gdb_stderr, "target_stop ()\n"); +} + +static struct symtab_and_line * +debug_to_enable_exception_callback (kind, enable) + enum exception_event_kind kind; + int enable; +{ + debug_target.to_enable_exception_callback (kind, enable); + + fprintf_unfiltered (gdb_stderr, + "target get_exception_callback_sal (%d, %d)\n", + kind, enable); +} + +static struct exception_event_record * +debug_to_get_current_exception_event () +{ + debug_target.to_get_current_exception_event(); + + fprintf_unfiltered (gdb_stderr, "target get_current_exception_event ()\n"); +} + +static char * +debug_to_pid_to_exec_file (pid) + int pid; +{ + char * exec_file; + + exec_file = debug_target.to_pid_to_exec_file (pid); + + fprintf_unfiltered (gdb_stderr, "target_pid_to_exec_file (%d) = %s\n", + pid, exec_file); + + return exec_file; +} + +static char * +debug_to_core_file_to_sym_file (core) + char * core; +{ + char * sym_file; + + sym_file = debug_target.to_core_file_to_sym_file (core); + + fprintf_unfiltered (gdb_stderr, "target_core_file_to_sym_file (%s) = %s\n", + core, sym_file); + + return sym_file; } static void @@ -1994,9 +2524,13 @@ setup_target_debug () current_target.to_open = debug_to_open; current_target.to_close = debug_to_close; current_target.to_attach = debug_to_attach; + current_target.to_post_attach = debug_to_post_attach; + current_target.to_require_attach = debug_to_require_attach; current_target.to_detach = debug_to_detach; + current_target.to_require_detach = debug_to_require_detach; current_target.to_resume = debug_to_resume; current_target.to_wait = debug_to_wait; + current_target.to_post_wait = debug_to_post_wait; current_target.to_fetch_registers = debug_to_fetch_registers; current_target.to_store_registers = debug_to_store_registers; current_target.to_prepare_to_store = debug_to_prepare_to_store; @@ -2013,11 +2547,34 @@ setup_target_debug () current_target.to_load = debug_to_load; current_target.to_lookup_symbol = debug_to_lookup_symbol; current_target.to_create_inferior = debug_to_create_inferior; + current_target.to_post_startup_inferior = debug_to_post_startup_inferior; + current_target.to_acknowledge_created_inferior = debug_to_acknowledge_created_inferior; + current_target.to_clone_and_follow_inferior = debug_to_clone_and_follow_inferior; + current_target.to_post_follow_inferior_by_clone = debug_to_post_follow_inferior_by_clone; + current_target.to_insert_fork_catchpoint = debug_to_insert_fork_catchpoint; + current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint; + current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint; + current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint; + current_target.to_has_forked = debug_to_has_forked; + current_target.to_has_vforked = debug_to_has_vforked; + current_target.to_can_follow_vfork_prior_to_exec = debug_to_can_follow_vfork_prior_to_exec; + current_target.to_post_follow_vfork = debug_to_post_follow_vfork; + current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint; + current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint; + current_target.to_has_execd = debug_to_has_execd; + current_target.to_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call; + current_target.to_has_syscall_event = debug_to_has_syscall_event; + current_target.to_has_exited = debug_to_has_exited; current_target.to_mourn_inferior = debug_to_mourn_inferior; current_target.to_can_run = debug_to_can_run; current_target.to_notice_signals = debug_to_notice_signals; current_target.to_thread_alive = debug_to_thread_alive; current_target.to_stop = debug_to_stop; + current_target.to_enable_exception_callback = debug_to_enable_exception_callback; + current_target.to_get_current_exception_event = debug_to_get_current_exception_event; + current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file; + current_target.to_core_file_to_sym_file = debug_to_core_file_to_sym_file; + } #endif /* MAINTENANCE_CMDS */ diff --git a/gdb/target.h b/gdb/target.h index a7e11e2..ccf047f 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -41,6 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ stratum. */ #include "bfd.h" +#include "symtab.h" enum strata { dummy_stratum, /* The lowest of the low */ @@ -68,6 +69,27 @@ enum target_waitkind { (e.g. it called load(2) on AIX). */ TARGET_WAITKIND_LOADED, + /* The program has forked. A "related" process' ID is in value.related_pid. + I.e., if the child forks, value.related_pid is the parent's ID. + */ + TARGET_WAITKIND_FORKED, + + /* The program has vforked. A "related" process's ID is in value.related_pid. + */ + TARGET_WAITKIND_VFORKED, + + /* The program has exec'ed a new executable file. The new file's pathname + is pointed to by value.execd_pathname. + */ + TARGET_WAITKIND_EXECD, + + /* The program has entered or returned from a system call. On HP-UX, this + is used in the hardware watchpoint implementation. The syscall's unique + integer ID number is in value.syscall_id; + */ + TARGET_WAITKIND_SYSCALL_ENTRY, + TARGET_WAITKIND_SYSCALL_RETURN, + /* Nothing happened, but we stopped anyway. This perhaps should be handled within target_wait, but I'm not sure target_wait should be resuming the inferior. */ @@ -200,10 +222,13 @@ enum target_signal { struct target_waitstatus { enum target_waitkind kind; - /* Exit status or signal number. */ + /* Forked child pid, execd pathname, exit status or signal number. */ union { int integer; enum target_signal sig; + int related_pid; + char * execd_pathname; + int syscall_id; } value; }; @@ -215,6 +240,7 @@ extern char *target_signal_to_name PARAMS ((enum target_signal)); /* Given a name (SIGHUP, etc.), return its signal. */ enum target_signal target_signal_from_name PARAMS ((char *)); + /* If certain kinds of activity happen, target_wait should perform callbacks. */ @@ -234,9 +260,13 @@ struct target_ops void (*to_open) PARAMS ((char *, int)); void (*to_close) PARAMS ((int)); void (*to_attach) PARAMS ((char *, int)); + void (*to_post_attach) PARAMS ((int)); + void (*to_require_attach) PARAMS ((char *, int)); void (*to_detach) PARAMS ((char *, int)); + void (*to_require_detach) PARAMS ((int, char *, int)); void (*to_resume) PARAMS ((int, int, enum target_signal)); int (*to_wait) PARAMS ((int, struct target_waitstatus *)); + void (*to_post_wait) PARAMS ((int, int)); void (*to_fetch_registers) PARAMS ((int)); void (*to_store_registers) PARAMS ((int)); void (*to_prepare_to_store) PARAMS ((void)); @@ -296,11 +326,33 @@ struct target_ops void (*to_load) PARAMS ((char *, int)); int (*to_lookup_symbol) PARAMS ((char *, CORE_ADDR *)); void (*to_create_inferior) PARAMS ((char *, char *, char **)); + void (*to_post_startup_inferior) PARAMS ((int)); + void (*to_acknowledge_created_inferior) PARAMS ((int)); + void (*to_clone_and_follow_inferior) PARAMS ((int, int *)); + void (*to_post_follow_inferior_by_clone) PARAMS ((void)); + int (*to_insert_fork_catchpoint) PARAMS ((int)); + int (*to_remove_fork_catchpoint) PARAMS ((int)); + int (*to_insert_vfork_catchpoint) PARAMS ((int)); + int (*to_remove_vfork_catchpoint) PARAMS ((int)); + int (*to_has_forked) PARAMS ((int, int *)); + int (*to_has_vforked) PARAMS ((int, int *)); + int (*to_can_follow_vfork_prior_to_exec) PARAMS ((void)); + void (*to_post_follow_vfork) PARAMS ((int, int, int, int)); + int (*to_insert_exec_catchpoint) PARAMS ((int)); + int (*to_remove_exec_catchpoint) PARAMS ((int)); + int (*to_has_execd) PARAMS ((int, char **)); + int (*to_reported_exec_events_per_exec_call) PARAMS ((void)); + int (*to_has_syscall_event) PARAMS ((int, enum target_waitkind *, int *)); + int (*to_has_exited) PARAMS ((int, int, int *)); void (*to_mourn_inferior) PARAMS ((void)); int (*to_can_run) PARAMS ((void)); void (*to_notice_signals) PARAMS ((int pid)); int (*to_thread_alive) PARAMS ((int pid)); void (*to_stop) PARAMS ((void)); + struct symtab_and_line * (*to_enable_exception_callback) PARAMS ((enum exception_event_kind, int)); + struct exception_event_record * (*to_get_current_exception_event) PARAMS ((void)); + char * (*to_pid_to_exec_file) PARAMS ((int pid)); + char * (*to_core_file_to_sym_file) PARAMS ((char *)); enum strata to_stratum; struct target_ops *DONT_USE; /* formerly to_next */ @@ -373,6 +425,26 @@ extern struct target_stack_item *target_stack; #define target_attach(args, from_tty) \ (*current_target.to_attach) (args, from_tty) +/* The target_attach operation places a process under debugger control, + and stops the process. + + This operation provides a target-specific hook that allows the + necessary bookkeeping to be performed after an attach completes. + */ +#define target_post_attach(pid) \ + (*current_target.to_post_attach) (pid) + +/* Attaches to a process on the target side, if not already attached. + (If already attached, takes no action.) + + This operation can be used to follow the child process of a fork. + On some targets, such child processes of an original inferior process + are automatically under debugger control, and thus do not require an + actual attach operation. */ + +#define target_require_attach(args, from_tty) \ + (*current_target.to_require_attach) (args, from_tty) + /* Takes a program previously attached to and detaches it. The program may resume execution (some targets do, some don't) and will no longer stop on signals, etc. We better not have left any breakpoints @@ -383,6 +455,21 @@ extern struct target_stack_item *target_stack; extern void target_detach PARAMS ((char *, int)); +/* Detaches from a process on the target side, if not already dettached. + (If already detached, takes no action.) + + This operation can be used to follow the parent process of a fork. + On some targets, such child processes of an original inferior process + are automatically under debugger control, and thus do require an actual + detach operation. + + PID is the process id of the child to detach from. + ARGS is arguments typed by the user (e.g. a signal to send the process). + FROM_TTY says whether to be verbose or not. */ + +#define target_require_detach(pid, args, from_tty) \ + (*current_target.to_require_detach) (pid, args, from_tty) + /* Resume execution of the target process PID. STEP says whether to single-step or to run free; SIGGNAL is the signal to be given to the target, or TARGET_SIGNAL_0 for no signal. The caller may not @@ -402,6 +489,20 @@ target_detach PARAMS ((char *, int)); #define target_wait(pid, status) \ (*current_target.to_wait) (pid, status) +/* The target_wait operation waits for a process event to occur, and + thereby stop the process. + + On some targets, certain events may happen in sequences. gdb's + correct response to any single event of such a sequence may require + knowledge of what earlier events in the sequence have been seen. + + This operation provides a target-specific hook that allows the + necessary bookkeeping to be performed to track such sequences. + */ + +#define target_post_wait(pid, status) \ + (*current_target.to_post_wait) (pid, status) + /* Fetch register REGNO, or all regs if regno == -1. No result. */ #define target_fetch_registers(regno) \ @@ -444,6 +545,78 @@ xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); extern int child_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); +extern char * +child_pid_to_exec_file PARAMS ((int)); + +extern char * +child_core_file_to_sym_file PARAMS ((char *)); + +extern void +child_post_attach PARAMS ((int)); + +extern void +child_post_wait PARAMS ((int, int)); + +extern void +child_post_startup_inferior PARAMS ((int)); + +extern void +child_acknowledge_created_inferior PARAMS ((int)); + +extern void +child_clone_and_follow_inferior PARAMS ((int, int *)); + +extern void +child_post_follow_inferior_by_clone PARAMS ((void)); + +extern int +child_insert_fork_catchpoint PARAMS ((int)); + +extern int +child_remove_fork_catchpoint PARAMS ((int)); + +extern int +child_insert_vfork_catchpoint PARAMS ((int)); + +extern int +child_remove_vfork_catchpoint PARAMS ((int)); + +extern int +child_has_forked PARAMS ((int, int *)); + +extern int +child_has_vforked PARAMS ((int, int *)); + +extern void +child_acknowledge_created_inferior PARAMS ((int)); + +extern int +child_can_follow_vfork_prior_to_exec PARAMS ((void)); + +extern void +child_post_follow_vfork PARAMS ((int, int, int, int)); + +extern int +child_insert_exec_catchpoint PARAMS ((int)); + +extern int +child_remove_exec_catchpoint PARAMS ((int)); + +extern int +child_has_execd PARAMS ((int, char **)); + +extern int +child_reported_exec_events_per_exec_call PARAMS ((void)); + +extern int +child_has_syscall_event PARAMS ((int, enum target_waitkind *, int *)); + +extern int +child_has_exited PARAMS ((int, int, int *)); + +extern int +child_thread_alive PARAMS ((int)); + /* From exec.c */ extern void @@ -539,6 +712,149 @@ print_section_info PARAMS ((struct target_ops *, bfd *)); #define target_create_inferior(exec_file, args, env) \ (*current_target.to_create_inferior) (exec_file, args, env) + +/* Some targets (such as ttrace-based HPUX) don't allow us to request + notification of inferior events such as fork and vork immediately + after the inferior is created. (This because of how gdb gets an + inferior created via invoking a shell to do it. In such a scenario, + if the shell init file has commands in it, the shell will fork and + exec for each of those commands, and we will see each such fork + event. Very bad.) + + Such targets will supply an appropriate definition for this function. + */ +#define target_post_startup_inferior(pid) \ + (*current_target.to_post_startup_inferior) (pid) + +/* On some targets, the sequence of starting up an inferior requires + some synchronization between gdb and the new inferior process, PID. + */ +#define target_acknowledge_created_inferior(pid) \ + (*current_target.to_acknowledge_created_inferior) (pid) + +/* An inferior process has been created via a fork() or similar + system call. This function will clone the debugger, then ensure + that CHILD_PID is attached to by that debugger. + + FOLLOWED_CHILD is set TRUE on return *for the clone debugger only*, + and FALSE otherwise. (The original and clone debuggers can use this + to determine which they are, if need be.) + + (This is not a terribly useful feature without a GUI to prevent + the two debuggers from competing for shell input.) + */ +#define target_clone_and_follow_inferior(child_pid,followed_child) \ + (*current_target.to_clone_and_follow_inferior) (child_pid, followed_child) + +/* This operation is intended to be used as the last in a sequence of + steps taken when following both parent and child of a fork. This + is used by a clone of the debugger, which will follow the child. + + The original debugger has detached from this process, and the + clone has attached to it. + + On some targets, this requires a bit of cleanup to make it work + correctly. + */ +#define target_post_follow_inferior_by_clone() \ + (*current_target.to_post_follow_inferior_by_clone) () + +/* On some targets, we can catch an inferior fork or vfork event when it + occurs. These functions insert/remove an already-created catchpoint for + such events. + */ +#define target_insert_fork_catchpoint(pid) \ + (*current_target.to_insert_fork_catchpoint) (pid) + +#define target_remove_fork_catchpoint(pid) \ + (*current_target.to_remove_fork_catchpoint) (pid) + +#define target_insert_vfork_catchpoint(pid) \ + (*current_target.to_insert_vfork_catchpoint) (pid) + +#define target_remove_vfork_catchpoint(pid) \ + (*current_target.to_remove_vfork_catchpoint) (pid) + +/* Returns TRUE if PID has invoked the fork() system call. And, + also sets CHILD_PID to the process id of the other ("child") + inferior process that was created by that call. + */ +#define target_has_forked(pid,child_pid) \ + (*current_target.to_has_forked) (pid,child_pid) + +/* Returns TRUE if PID has invoked the vfork() system call. And, + also sets CHILD_PID to the process id of the other ("child") + inferior process that was created by that call. + */ +#define target_has_vforked(pid,child_pid) \ + (*current_target.to_has_vforked) (pid,child_pid) + +/* Some platforms (such as pre-10.20 HP-UX) don't allow us to do + anything to a vforked child before it subsequently calls exec(). + On such platforms, we say that the debugger cannot "follow" the + child until it has vforked. + + This function should be defined to return 1 by those targets + which can allow the debugger to immediately follow a vforked + child, and 0 if they cannot. + */ +#define target_can_follow_vfork_prior_to_exec() \ + (*current_target.to_can_follow_vfork_prior_to_exec) () + +/* An inferior process has been created via a vfork() system call. + The debugger has followed the parent, the child, or both. The + process of setting up for that follow may have required some + target-specific trickery to track the sequence of reported events. + If so, this function should be defined by those targets that + require the debugger to perform cleanup or initialization after + the vfork follow. + */ +#define target_post_follow_vfork(parent_pid,followed_parent,child_pid,followed_child) \ + (*current_target.to_post_follow_vfork) (parent_pid,followed_parent,child_pid,followed_child) + +/* On some targets, we can catch an inferior exec event when it + occurs. These functions insert/remove an already-created catchpoint + for such events. + */ +#define target_insert_exec_catchpoint(pid) \ + (*current_target.to_insert_exec_catchpoint) (pid) + +#define target_remove_exec_catchpoint(pid) \ + (*current_target.to_remove_exec_catchpoint) (pid) + +/* Returns TRUE if PID has invoked a flavor of the exec() system call. + And, also sets EXECD_PATHNAME to the pathname of the executable file + that was passed to exec(), and is now being executed. + */ +#define target_has_execd(pid,execd_pathname) \ + (*current_target.to_has_execd) (pid,execd_pathname) + +/* Returns the number of exec events that are reported when a process + invokes a flavor of the exec() system call on this target, if exec + events are being reported. + */ +#define target_reported_exec_events_per_exec_call() \ + (*current_target.to_reported_exec_events_per_exec_call) () + +/* Returns TRUE if PID has reported a syscall event. And, also sets + KIND to the appropriate TARGET_WAITKIND_, and sets SYSCALL_ID to + the unique integer ID of the syscall. + */ +#define target_has_syscall_event(pid,kind,syscall_id) \ + (*current_target.to_has_syscall_event) (pid,kind,syscall_id) + +/* Returns TRUE if PID has exited. And, also sets EXIT_STATUS to the + exit code of PID, if any. + */ +#define target_has_exited(pid,wait_status,exit_status) \ + (*current_target.to_has_exited) (pid,wait_status,exit_status) + +/* The debugger has completed a blocking wait() call. There is now + some process event that must be processed. This function should + be defined by those targets that require the debugger to perform + cleanup or internal state changes in response to the process event. + */ + /* The inferior process has died. Do what is right. */ #define target_mourn_inferior() \ @@ -565,6 +881,21 @@ print_section_info PARAMS ((struct target_ops *, bfd *)); #define target_stop current_target.to_stop +/* Get the symbol information for a breakpointable routine called when + an exception event occurs. + Intended mainly for C++, and for those + platforms/implementations where such a callback mechanism is available, + e.g. HP-UX with ANSI C++ (aCC). Some compilers (e.g. g++) support + different mechanisms for debugging exceptions. */ + +#define target_enable_exception_callback(kind, enable) \ + (*current_target.to_enable_exception_callback) (kind, enable) + +/* Get the current exception event kind -- throw or catch, etc. */ + +#define target_get_current_exception_event() \ + (*current_target.to_get_current_exception_event) () + /* Pointer to next target in the chain, e.g. a core file and an exec file. */ #define target_next \ @@ -615,10 +946,38 @@ extern void target_link PARAMS ((char *, CORE_ADDR *)); extern char *normal_pid_to_str PARAMS ((int pid)); #endif +#ifndef target_tid_to_str +#define target_tid_to_str(PID) \ + normal_pid_to_str (PID) +extern char *normal_pid_to_str PARAMS ((int pid)); +#endif + + #ifndef target_new_objfile #define target_new_objfile(OBJFILE) #endif +#ifndef target_pid_or_tid_to_str +#define target_pid_or_tid_to_str(ID) \ + normal_pid_to_str (ID) +#endif + +/* Attempts to find the pathname of the executable file + that was run to create a specified process. + + The process PID must be stopped when this operation is used. + + If the executable file cannot be determined, NULL is returned. + + Else, a pointer to a character string containing the pathname + is returned. This string should be copied into a buffer by + the client if the string will not be immediately used, or if + it must persist. + */ + +#define target_pid_to_exec_file(pid) \ + (current_target.to_pid_to_exec_file) (pid) + /* Hook to call target-dependant code after reading in a new symbol table. */ #ifndef TARGET_SYMFILE_POSTREAD @@ -641,6 +1000,18 @@ extern char *normal_pid_to_str PARAMS ((int pid)); #define STOPPED_BY_WATCHPOINT(w) 0 #endif +/* HP-UX supplies these operations, which respectively disable and enable + the memory page-protections that are used to implement hardware watchpoints + on that platform. See wait_for_inferior's use of these. + */ +#if !defined(TARGET_DISABLE_HW_WATCHPOINTS) +#define TARGET_DISABLE_HW_WATCHPOINTS(pid) +#endif + +#if !defined(TARGET_ENABLE_HW_WATCHPOINTS) +#define TARGET_ENABLE_HW_WATCHPOINTS(pid) +#endif + /* Provide defaults for systems that don't support hardware watchpoints. */ #ifndef TARGET_HAS_HARDWARE_WATCHPOINTS @@ -652,6 +1023,23 @@ extern char *normal_pid_to_str PARAMS ((int pid)); #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(TYPE,CNT,OTHERTYPE) 0 +#if !defined(TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT) +#define TARGET_REGION_SIZE_OK_FOR_HW_WATCHPOINT(byte_count) \ + (LONGEST)(byte_count) <= REGISTER_SIZE +#endif + +/* However, some addresses may not be profitable to use hardware to watch, + or may be difficult to understand when the addressed object is out of + scope, and hence should be unwatched. On some targets, this may have + severe performance penalties, such that we might as well use regular + watchpoints, and save (possibly precious) hardware watchpoints for other + locations. + */ +#if !defined(TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT) +#define TARGET_RANGE_PROFITABLE_FOR_HW_WATCHPOINT(pid,start,len) 0 +#endif + + /* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes. TYPE is 0 for write, 1 for read, and 2 for read/write accesses. Returns 0 for success, non-zero for failure. */ @@ -677,6 +1065,38 @@ extern char *normal_pid_to_str PARAMS ((int pid)); #define DECR_PC_AFTER_HW_BREAK 0 #endif +/* Sometimes gdb may pick up what appears to be a valid target address + from a minimal symbol, but the value really means, essentially, + "This is an index into a table which is populated when the inferior + is run. Therefore, do not attempt to use this as a PC." + */ +#if !defined(PC_REQUIRES_RUN_BEFORE_USE) +#define PC_REQUIRES_RUN_BEFORE_USE(pc) (0) +#endif + +/* This will only be defined by a target that supports catching vfork events, + such as HP-UX. + + On some targets (such as HP-UX 10.20 and earlier), resuming a newly vforked + child process after it has exec'd, causes the parent process to resume as + well. To prevent the parent from running spontaneously, such targets should + define this to a function that prevents that from happening. + */ +#if !defined(ENSURE_VFORKING_PARENT_REMAINS_STOPPED) +#define ENSURE_VFORKING_PARENT_REMAINS_STOPPED(PID) (0) +#endif + +/* This will only be defined by a target that supports catching vfork events, + such as HP-UX. + + On some targets (such as HP-UX 10.20 and earlier), a newly vforked child + process must be resumed when it delivers its exec event, before the parent + vfork event will be delivered to us. + */ +#if !defined(RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK) +#define RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK() (0) +#endif + /* Routines for maintenance of the target structures... add_target: Add a target to the list of all possible targets. @@ -729,14 +1149,15 @@ build_section_table PARAMS ((bfd *, struct section_table **, /* From mem-break.c */ -extern int -memory_remove_breakpoint PARAMS ((CORE_ADDR, char *)); +extern int memory_remove_breakpoint PARAMS ((CORE_ADDR, char *)); -extern int -memory_insert_breakpoint PARAMS ((CORE_ADDR, char *)); +extern int memory_insert_breakpoint PARAMS ((CORE_ADDR, char *)); + +extern breakpoint_from_pc_fn memory_breakpoint_from_pc; +#ifndef BREAKPOINT_FROM_PC +#define BREAKPOINT_FROM_PC(pcptr, lenptr) memory_breakpoint_from_pc (pcptr, lenptr) +#endif -unsigned char * -memory_breakpoint_from_pc PARAMS ((CORE_ADDR *pcptr, int *lenptr)); /* From target.c */ @@ -749,9 +1170,18 @@ noprocess PARAMS ((void)); extern void find_default_attach PARAMS ((char *, int)); +void +find_default_require_attach PARAMS ((char *, int)); + +void +find_default_require_detach PARAMS ((int, char *, int)); + extern void find_default_create_inferior PARAMS ((char *, char *, char **)); +void +find_default_clone_and_follow_inferior PARAMS ((int, int *)); + extern struct target_ops * find_core_target PARAMS ((void)); @@ -782,16 +1212,23 @@ extern enum target_signal target_signal_from_command PARAMS ((int)); /* Any target can call this to switch to remote protocol (in remote.c). */ extern void push_remote_target PARAMS ((char *name, int from_tty)); - -/* Any target cah call this to open using the remote protocol */ -extern void open_remote_target PARAMS ((char *name, int from_tty, struct target_ops *target, int extended_p)); - /* Imported from machine dependent code */ -#ifdef NO_SINGLE_STEP -extern int one_stepped; -extern void single_step PARAMS ((enum target_signal)); -#endif /* NO_SINGLE_STEP */ +#ifndef SOFTWARE_SINGLE_STEP_P +#define SOFTWARE_SINGLE_STEP_P 0 +#define SOFTWARE_SINGLE_STEP(sig,bp_p) abort () +#endif /* SOFTWARE_SINGLE_STEP_P */ + +/* Blank target vector entries are initialized to target_ignore. */ +void target_ignore PARAMS ((void)); + +/* Macro for getting target's idea of a frame pointer. + FIXME: GDB's whole scheme for dealing with "frames" and + "frame pointers" needs a serious shakedown. */ +#ifndef TARGET_VIRTUAL_FRAME_POINTER +#define TARGET_VIRTUAL_FRAME_POINTER(ADDR, REGP, OFFP) \ + do { *(REGP) = FP_REGNUM; *(OFFP) = 0; } while (0) +#endif /* TARGET_VIRTUAL_FRAME_POINTER */ #endif /* !defined (TARGET_H) */ diff --git a/gdb/v850ice.c b/gdb/v850ice.c index f69966b..0135e58 100755 --- a/gdb/v850ice.c +++ b/gdb/v850ice.c @@ -4,7 +4,7 @@ This file is part of GDB. This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Pessublic License as published by +it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -921,10 +921,14 @@ static void init_850ice_ops(void) v850ice_ops.to_doc = "Debug a system controlled by a NEC 850 ICE."; v850ice_ops.to_open = v850ice_open; v850ice_ops.to_close = v850ice_close; - v850ice_ops.to_attach = NULL; - v850ice_ops.to_detach = v850ice_detach; + v850ice_ops.to_attach = NULL; + v850ice_ops.to_post_attach = NULL; + v850ice_ops.to_require_attach = NULL; + v850ice_ops.to_detach = v850ice_detach; + v850ice_ops.to_require_detach = NULL; v850ice_ops.to_resume = v850ice_resume; - v850ice_ops.to_wait = v850ice_wait; + v850ice_ops.to_wait = v850ice_wait; + v850ice_ops.to_post_wait = NULL; v850ice_ops.to_fetch_registers = v850ice_fetch_registers; v850ice_ops.to_store_registers = v850ice_store_registers; v850ice_ops.to_prepare_to_store = v850ice_prepare_to_store; @@ -940,12 +944,14 @@ static void init_850ice_ops(void) v850ice_ops.to_kill = v850ice_kill; v850ice_ops.to_load = v850ice_load; v850ice_ops.to_lookup_symbol = NULL; - v850ice_ops.to_create_inferior = NULL; + v850ice_ops.to_create_inferior = NULL; v850ice_ops.to_mourn_inferior = v850ice_mourn; v850ice_ops.to_can_run = 0; v850ice_ops.to_notice_signals = 0; v850ice_ops.to_thread_alive = NULL; v850ice_ops.to_stop = v850ice_stop; + v850ice_ops.to_pid_to_exec_file = NULL; + v850ice_ops.to_core_file_to_sym_file = NULL; v850ice_ops.to_stratum = process_stratum; v850ice_ops.DONT_USE = NULL; v850ice_ops.to_has_all_memory = 1; diff --git a/gdb/valops.c b/gdb/valops.c index f902304..076b3ea 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1,5 +1,5 @@ /* Perform non-arithmetic operations on values, for GDB. - Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996 + Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "target.h" #include "demangle.h" #include "language.h" +#include "gdbcmd.h" #include <errno.h> #include "gdb_string.h" @@ -41,13 +42,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define COERCE_FLOAT_TO_DOUBLE (param_type == NULL) #endif +/* Flag indicating HP compilers were used; needed to correctly handle some + value operations with HP aCC code/runtime. */ +extern int hp_som_som_object_present; + + /* Local functions. */ static int typecmp PARAMS ((int staticp, struct type *t1[], value_ptr t2[])); #ifdef CALL_DUMMY static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **)); -static value_ptr value_arg_coerce PARAMS ((value_ptr, struct type *)); +static value_ptr value_arg_coerce PARAMS ((value_ptr, struct type *, int)); #endif @@ -58,6 +64,10 @@ 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 *)); @@ -68,6 +78,8 @@ static CORE_ADDR allocate_space_in_inferior PARAMS ((int)); static value_ptr cast_into_complex PARAMS ((struct type *, value_ptr)); +void _initialize_valops PARAMS ((void)); + #define VALUE_SUBSTRING_START(VAL) VALUE_FRAME(VAL) /* Flag for whether we want to abandon failed expression evals by default. */ @@ -76,6 +88,9 @@ static value_ptr cast_into_complex PARAMS ((struct type *, value_ptr)); static int auto_abandon = 0; #endif +int overload_resolution = 0; + + /* Find the address of function name NAME in the inferior. */ @@ -109,7 +124,10 @@ find_function_in_inferior (name) } else { - error ("evaluation of this expression requires the program to have a function \"%s\".", name); + if (!target_has_execution) + error ("evaluation of this expression requires the target program to be active"); + else + error ("evaluation of this expression requires the program to have a function \"%s\".", name); } } } @@ -128,7 +146,10 @@ value_allocate_space_in_inferior (len) val = call_function_by_hand (val, 1, &blocklen); if (value_logical_not (val)) { - error ("No memory available to program."); + if (!target_has_execution) + error ("No memory available to program now: you need to start the target first"); + else + error ("No memory available to program: call to malloc failed"); } return val; } @@ -155,6 +176,8 @@ value_cast (type, arg2) register int scalar; struct type *type2; + int convert_to_boolean = 0; + if (VALUE_TYPE (arg2) == type) return arg2; @@ -206,8 +229,13 @@ value_cast (type, arg2) if (code1 == TYPE_CODE_COMPLEX) return cast_into_complex (type, arg2); - if (code1 == TYPE_CODE_BOOL || code1 == TYPE_CODE_CHAR) - code1 = TYPE_CODE_INT; + if (code1 == TYPE_CODE_BOOL) + { + code1 = TYPE_CODE_INT; + convert_to_boolean = 1; + } + if (code1 == TYPE_CODE_CHAR) + code1 = TYPE_CODE_INT; if (code2 == TYPE_CODE_BOOL || code2 == TYPE_CODE_CHAR) code2 = TYPE_CODE_INT; @@ -234,32 +262,86 @@ value_cast (type, arg2) else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM || code1 == TYPE_CODE_RANGE) && (scalar || code2 == TYPE_CODE_PTR)) - return value_from_longest (type, value_as_long (arg2)); + { + LONGEST longest; + + if (hp_som_som_object_present && /* if target compiled by HP aCC */ + (code2 == TYPE_CODE_PTR)) + { + unsigned int * ptr; + value_ptr retvalp; + + switch (TYPE_CODE (TYPE_TARGET_TYPE (type2))) + { + /* With HP aCC, pointers to data members have a bias */ + case TYPE_CODE_MEMBER: + retvalp = value_from_longest (type, value_as_long (arg2)); + ptr = (unsigned int *) VALUE_CONTENTS (retvalp); /* force evaluation */ + *ptr &= ~0x20000000; /* zap 29th bit to remove bias */ + return retvalp; + + /* While pointers to methods don't really point to a function */ + case TYPE_CODE_METHOD: + error ("Pointers to methods not supported with HP aCC"); + + default: + break; /* fall out and go to normal handling */ + } + } + longest = value_as_long (arg2); + return value_from_longest (type, convert_to_boolean ? (LONGEST) (longest ? 1 : 0) : longest); + } else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2)) { if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR) { - /* Look in the type of the source to see if it contains the - type of the target as a superclass. If so, we'll need to - offset the pointer rather than just change its type. */ struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type)); struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2)); if ( TYPE_CODE (t1) == TYPE_CODE_STRUCT && TYPE_CODE (t2) == TYPE_CODE_STRUCT - && TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */ + && !value_logical_not (arg2)) { - value_ptr v = search_struct_field (type_name_no_tag (t1), - value_ind (arg2), 0, t2, 1); - if (v) + value_ptr v; + + /* Look in the type of the source to see if it contains the + type of the target as a superclass. If so, we'll need to + offset the pointer rather than just change its type. */ + if (TYPE_NAME (t1) != NULL) + { + v = search_struct_field (type_name_no_tag (t1), + value_ind (arg2), 0, t2, 1); + if (v) + { + v = value_addr (v); + VALUE_TYPE (v) = type; + return v; + } + } + + /* Look in the type of the target to see if it contains the + type of the source as a superclass. If so, we'll need to + offset the pointer rather than just change its type. + FIXME: This fails silently with virtual inheritance. */ + if (TYPE_NAME (t2) != NULL) { - v = value_addr (v); - VALUE_TYPE (v) = type; - return v; + v = search_struct_field (type_name_no_tag (t2), + value_zero (t1, not_lval), 0, t1, 1); + if (v) + { + value_ptr v2 = value_ind (arg2); + VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v) + + VALUE_OFFSET (v); + v2 = value_addr (v2); + VALUE_TYPE (v2) = type; + return v2; + } } } /* No superclass found, just fall through to change ptr type. */ } VALUE_TYPE (arg2) = type; + VALUE_ENCLOSING_TYPE (arg2) = type; /* pai: chk_val */ + VALUE_POINTED_TO_OFFSET (arg2) = 0; /* pai: chk_val */ return arg2; } else if (chill_varying_type (type)) @@ -269,6 +351,8 @@ value_cast (type, arg2) int count1, count2; LONGEST low_bound, high_bound; char *valaddr, *valaddr_data; + /* For lint warning about eltype2 possibly uninitialized: */ + eltype2 = NULL; if (code2 == TYPE_CODE_BITSTRING) error ("not implemented: converting bitstring to varying type"); if ((code2 != TYPE_CODE_ARRAY && code2 != TYPE_CODE_STRING) @@ -341,7 +425,10 @@ value_zero (type, lv) value_at_lazy instead. value_at_lazy simply records the address of the data and sets the lazy-evaluation-required flag. The lazy flag is tested in the VALUE_CONTENTS macro, which is used if and when - the contents are actually required. */ + the contents are actually required. + + Note: value_at does *NOT* handle embedded offsets; perform such + adjustments before or after calling it. */ value_ptr value_at (type, addr, sect) @@ -357,18 +444,29 @@ value_at (type, addr, sect) val = allocate_value (type); #ifdef GDB_TARGET_IS_D10V - if (TYPE_TARGET_TYPE(type) && TYPE_CODE(TYPE_TARGET_TYPE(type)) == TYPE_CODE_FUNC) + if (TYPE_CODE (type) == TYPE_CODE_PTR + && TYPE_TARGET_TYPE (type) + && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)) { - int num; - short snum; - read_memory (addr, (char *)&snum, 2); + /* pointer to function */ + unsigned long num; + unsigned short snum; + snum = read_memory_unsigned_integer (addr, 2); num = D10V_MAKE_IADDR(snum); - memcpy( VALUE_CONTENTS_RAW (val), &num, 4); + store_address ( VALUE_CONTENTS_RAW (val), 4, num); + } + else if (TYPE_CODE(type) == TYPE_CODE_PTR) + { + /* pointer to data */ + unsigned long num; + unsigned short snum; + snum = read_memory_unsigned_integer (addr, 2); + num = D10V_MAKE_DADDR(snum); + store_address ( VALUE_CONTENTS_RAW (val), 4, num); } else #endif - - read_memory_section (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type), sect); + read_memory_section (addr, VALUE_CONTENTS_ALL_RAW (val), TYPE_LENGTH (type), sect); VALUE_LVAL (val) = lval_memory; VALUE_ADDRESS (val) = addr; @@ -400,10 +498,10 @@ value_at_lazy (type, addr, sect) return val; } -/* Called only from the VALUE_CONTENTS macro, if the current data for - a variable needs to be loaded into VALUE_CONTENTS(VAL). Fetches the - data from the user's process, and clears the lazy flag to indicate - that the data in the buffer is valid. +/* Called only from the VALUE_CONTENTS and VALUE_CONTENTS_ALL macros, + if the current data for a variable needs to be loaded into + VALUE_CONTENTS(VAL). Fetches the data from the user's process, and + clears the lazy flag to indicate that the data in the buffer is valid. If the value is zero-length, we avoid calling read_memory, which would abort. We mark the value as fetched anyway -- all 0 bytes of it. @@ -417,23 +515,35 @@ value_fetch_lazy (val) register value_ptr val; { CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val); - int length = TYPE_LENGTH (VALUE_TYPE (val)); + int length = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val)); #ifdef GDB_TARGET_IS_D10V struct type *type = VALUE_TYPE(val); - if (TYPE_TARGET_TYPE(type) && TYPE_CODE(TYPE_TARGET_TYPE(type)) == TYPE_CODE_FUNC) + if (TYPE_CODE (type) == TYPE_CODE_PTR + && TYPE_TARGET_TYPE (type) + && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)) { - int num; - short snum; - read_memory (addr, (char *)&snum, 2); + /* pointer to function */ + unsigned long num; + unsigned short snum; + snum = read_memory_unsigned_integer (addr, 2); num = D10V_MAKE_IADDR(snum); - memcpy( VALUE_CONTENTS_RAW (val), &num, 4); + store_address ( VALUE_CONTENTS_RAW (val), 4, num); + } + else if (TYPE_CODE(type) == TYPE_CODE_PTR) + { + /* pointer to data */ + unsigned long num; + unsigned short snum; + snum = read_memory_unsigned_integer (addr, 2); + num = D10V_MAKE_DADDR(snum); + store_address ( VALUE_CONTENTS_RAW (val), 4, num); } else #endif if (length) - read_memory_section (addr, VALUE_CONTENTS_RAW (val), length, + read_memory_section (addr, VALUE_CONTENTS_ALL_RAW (val), length, VALUE_BFD_SECTION (val)); VALUE_LAZY (val) = 0; return 0; @@ -488,7 +598,11 @@ value_assign (toval, fromval) { case lval_internalvar: set_internalvar (VALUE_INTERNALVAR (toval), fromval); - return value_copy (VALUE_INTERNALVAR (toval)->value); + val = value_copy (VALUE_INTERNALVAR (toval)->value); + VALUE_ENCLOSING_TYPE (val) = VALUE_ENCLOSING_TYPE (fromval); + VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (fromval); + VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (fromval); + return val; case lval_internalvar_component: set_internalvar_component (VALUE_INTERNALVAR (toval), @@ -679,6 +793,9 @@ Can't handle bitfield which doesn't fit in a single register."); memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval), TYPE_LENGTH (type)); VALUE_TYPE (val) = type; + VALUE_ENCLOSING_TYPE (val) = VALUE_ENCLOSING_TYPE (fromval); + VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (fromval); + VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (fromval); return val; } @@ -697,11 +814,11 @@ value_repeat (arg1, count) if (count < 1) error ("Invalid number %d of repetitions.", count); - val = allocate_repeat_value (VALUE_TYPE (arg1), count); + val = allocate_repeat_value (VALUE_ENCLOSING_TYPE (arg1), count); read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1), - VALUE_CONTENTS_RAW (val), - TYPE_LENGTH (VALUE_TYPE (val))); + VALUE_CONTENTS_ALL_RAW (val), + TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val))); VALUE_LVAL (val) = lval_memory; VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1); @@ -722,12 +839,14 @@ value_of_variable (var, b) { frame = block_innermost_frame (b); if (!frame) - if (BLOCK_FUNCTION (b) - && SYMBOL_NAME (BLOCK_FUNCTION (b))) - error ("No frame is currently executing in block %s.", - SYMBOL_NAME (BLOCK_FUNCTION (b))); - else - error ("No frame is currently executing in specified block"); + { + if (BLOCK_FUNCTION (b) + && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b))) + error ("No frame is currently executing in block %s.", + SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b))); + else + error ("No frame is currently executing in specified block"); + } } val = read_var_value (var, frame); @@ -797,7 +916,7 @@ value_ptr value_addr (arg1) value_ptr arg1; { - value_ptr retval; + value_ptr arg2; struct type *type = check_typedef (VALUE_TYPE (arg1)); if (TYPE_CODE (type) == TYPE_CODE_REF) @@ -805,7 +924,7 @@ value_addr (arg1) /* Copy the value, but change the type from (T&) to (T*). We keep the same location information, which is efficient, and allows &(&X) to get the location containing the reference. */ - value_ptr arg2 = value_copy (arg1); + arg2 = value_copy (arg1); VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type)); return arg2; } @@ -815,10 +934,19 @@ value_addr (arg1) if (VALUE_LVAL (arg1) != lval_memory) error ("Attempt to take address of value not located in memory."); - retval = value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)), - (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1))); - VALUE_BFD_SECTION (retval) = VALUE_BFD_SECTION (arg1); - return retval; + /* Get target memory address */ + arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)), + (LONGEST) (VALUE_ADDRESS (arg1) + + VALUE_OFFSET (arg1) + + VALUE_EMBEDDED_OFFSET (arg1))); + + /* This may be a pointer to a base subobject; so remember the + full derived object's type ... */ + VALUE_ENCLOSING_TYPE (arg2) = lookup_pointer_type (VALUE_ENCLOSING_TYPE (arg1)); + /* ... and also the relative position of the subobject in the full object */ + VALUE_POINTED_TO_OFFSET (arg2) = VALUE_EMBEDDED_OFFSET (arg1); + VALUE_BFD_SECTION (arg2) = VALUE_BFD_SECTION (arg1); + return arg2; } /* Given a value of a pointer type, apply the C unary * operator to it. */ @@ -827,24 +955,47 @@ value_ptr value_ind (arg1) value_ptr arg1; { - struct type *type1; + struct type *base_type; + value_ptr arg2; + value_ptr real_val; + COERCE_ARRAY (arg1); - type1 = check_typedef (VALUE_TYPE (arg1)); - if (TYPE_CODE (type1) == TYPE_CODE_MEMBER) + base_type = check_typedef (VALUE_TYPE (arg1)); + + if (TYPE_CODE (base_type) == TYPE_CODE_MEMBER) error ("not implemented: member types in value_ind"); /* Allow * on an integer so we can cast it to whatever we want. This returns an int, which seems like the most C-like thing to do. "long long" variables are rare enough that BUILTIN_TYPE_LONGEST would seem to be a mistake. */ - if (TYPE_CODE (type1) == TYPE_CODE_INT) + if (TYPE_CODE (base_type) == TYPE_CODE_INT) return value_at (builtin_type_int, (CORE_ADDR) value_as_long (arg1), VALUE_BFD_SECTION (arg1)); - else if (TYPE_CODE (type1) == TYPE_CODE_PTR) - return value_at_lazy (TYPE_TARGET_TYPE (type1), value_as_pointer (arg1), - VALUE_BFD_SECTION (arg1)); + else if (TYPE_CODE (base_type) == TYPE_CODE_PTR) + { + struct type *enc_type; + /* We may be pointing to something embedded in a larger object */ + /* Get the real type of the enclosing object */ + enc_type = check_typedef (VALUE_ENCLOSING_TYPE (arg1)); + enc_type = TYPE_TARGET_TYPE (enc_type); + /* Retrieve the enclosing object pointed to */ + arg2 = value_at_lazy (enc_type, + value_as_pointer (arg1) - VALUE_POINTED_TO_OFFSET (arg1), + VALUE_BFD_SECTION (arg1)); + /* Re-adjust type */ + VALUE_TYPE (arg2) = TYPE_TARGET_TYPE (base_type); + /* Add embedding info */ + VALUE_ENCLOSING_TYPE (arg2) = enc_type; + VALUE_EMBEDDED_OFFSET (arg2) = VALUE_POINTED_TO_OFFSET (arg1); + + /* We may be pointing to an object of some derived type */ + arg2 = value_full_object (arg2, NULL, 0, 0, 0); + return arg2; + } + error ("Attempt to take contents of a non-pointer value."); return 0; /* For lint -- never reached */ } @@ -862,13 +1013,18 @@ push_word (sp, word) char buffer[MAX_REGISTER_RAW_SIZE]; store_unsigned_integer (buffer, len, word); -#if 1 INNER_THAN 2 - sp -= len; - write_memory (sp, buffer, len); -#else /* stack grows upward */ - write_memory (sp, buffer, len); - sp += len; -#endif /* stack grows upward */ + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + sp -= len; + write_memory (sp, buffer, len); + } + else + { + /* stack grows upward */ + write_memory (sp, buffer, len); + sp += len; + } return sp; } @@ -881,13 +1037,18 @@ push_bytes (sp, buffer, len) char *buffer; int len; { -#if 1 INNER_THAN 2 - sp -= len; - write_memory (sp, buffer, len); -#else /* stack grows upward */ - write_memory (sp, buffer, len); - sp += len; -#endif /* stack grows upward */ + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + sp -= len; + write_memory (sp, buffer, len); + } + else + { + /* stack grows upward */ + write_memory (sp, buffer, len); + sp += len; + } return sp; } @@ -901,15 +1062,20 @@ value_push (sp, arg) register CORE_ADDR sp; value_ptr arg; { - register int len = TYPE_LENGTH (VALUE_TYPE (arg)); + register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg)); -#if 1 INNER_THAN 2 - sp -= len; - write_memory (sp, VALUE_CONTENTS (arg), len); -#else /* stack grows upward */ - write_memory (sp, VALUE_CONTENTS (arg), len); - sp += len; -#endif /* stack grows upward */ + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + sp -= len; + write_memory (sp, VALUE_CONTENTS_ALL (arg), len); + } + else + { + /* stack grows upward */ + write_memory (sp, VALUE_CONTENTS_ALL (arg), len); + sp += len; + } return sp; } @@ -920,12 +1086,14 @@ value_push (sp, arg) /* Perform the standard coercions that are specified for arguments to be passed to C functions. - If PARAM_TYPE is non-NULL, it is the expected parameter type. */ + If PARAM_TYPE is non-NULL, it is the expected parameter type. + IS_PROTOTYPED is non-zero if the function declaration is prototyped. */ static value_ptr -value_arg_coerce (arg, param_type) +value_arg_coerce (arg, param_type, is_prototyped) value_ptr arg; struct type *param_type; + int is_prototyped; { register struct type *arg_type = check_typedef (VALUE_TYPE (arg)); register struct type *type @@ -945,19 +1113,31 @@ value_arg_coerce (arg, param_type) case TYPE_CODE_CHAR: case TYPE_CODE_BOOL: case TYPE_CODE_ENUM: + /* If we don't have a prototype, coerce to integer type if necessary. */ + if (!is_prototyped) + { + if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int)) + type = builtin_type_int; + } + /* Currently all target ABIs require at least the width of an integer + type for an argument. We may have to conditionalize the following + type coercion for future targets. */ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int)) type = builtin_type_int; break; - case TYPE_CODE_FLT: - /* coerce float to double, unless the function prototype specifies float */ - if (COERCE_FLOAT_TO_DOUBLE) - { - if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double)) - type = builtin_type_double; - else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double)) - type = builtin_type_long_double; - } - break; + case TYPE_CODE_FLT: + /* FIXME: We should always convert floats to doubles in the + non-prototyped case. As many debugging formats include + no information about prototyping, we have to live with + COERCE_FLOAT_TO_DOUBLE for now. */ + if (!is_prototyped && COERCE_FLOAT_TO_DOUBLE) + { + if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double)) + type = builtin_type_double; + else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double)) + type = builtin_type_long_double; + } + break; case TYPE_CODE_FUNC: type = lookup_pointer_type (type); break; @@ -1074,7 +1254,14 @@ call_function_by_hand (function, nargs, args) /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word is in host byte order. Before calling FIX_CALL_DUMMY, we byteswap it and remove any extra bytes which might exist because ULONGEST is - bigger than REGISTER_SIZE. */ + bigger than REGISTER_SIZE. + + NOTE: This is pretty wierd, as the call dummy is actually a + sequence of instructions. But CISC machines will have + to pack the instructions into REGISTER_SIZE units (and + so will RISC machines for which INSTRUCTION_SIZE is not + REGISTER_SIZE). */ + static ULONGEST dummy[] = CALL_DUMMY; char dummy1[REGISTER_SIZE * sizeof dummy / sizeof (ULONGEST)]; CORE_ADDR old_sp; @@ -1086,13 +1273,15 @@ call_function_by_hand (function, nargs, args) CORE_ADDR funaddr; int using_gcc; /* Set to version of gcc in use, or zero if not gcc */ CORE_ADDR real_pc; + struct type *param_type = NULL; struct type *ftype = check_typedef (SYMBOL_TYPE (function)); if (!target_has_execution) noprocess(); save_inferior_status (&inf_status, 1); - old_chain = make_cleanup (restore_inferior_status, &inf_status); + old_chain = make_cleanup ((make_cleanup_func) restore_inferior_status, + &inf_status); /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers (and POP_FRAME for restoring them). (At least on most machines) @@ -1101,13 +1290,18 @@ call_function_by_hand (function, nargs, args) old_sp = sp = read_sp (); -#if 1 INNER_THAN 2 /* Stack grows down */ - sp -= sizeof dummy1; - start_sp = sp; -#else /* Stack grows up */ - start_sp = sp; - sp += sizeof dummy1; -#endif + if (INNER_THAN (1, 2)) + { + /* Stack grows down */ + sp -= sizeof dummy1; + start_sp = sp; + } + else + { + /* Stack grows up */ + start_sp = sp; + sp += sizeof dummy1; + } funaddr = find_function_addr (function, &value_type); CHECK_TYPEDEF (value_type); @@ -1186,12 +1380,50 @@ call_function_by_hand (function, nargs, args) for (i = nargs - 1; i >= 0; i--) { - struct type *param_type; - if (TYPE_NFIELDS (ftype) > i) - param_type = TYPE_FIELD_TYPE (ftype, i); - else - param_type = 0; - args[i] = value_arg_coerce (args[i], param_type); + /* If we're off the end of the known arguments, do the standard + promotions. FIXME: if we had a prototype, this should only + be allowed if ... were present. */ + if (i >= TYPE_NFIELDS (ftype)) + args[i] = value_arg_coerce (args[i], NULL, 0); + + else + { + int is_prototyped = TYPE_FLAGS (ftype) & TYPE_FLAG_PROTOTYPED; + param_type = TYPE_FIELD_TYPE (ftype, i); + + args[i] = value_arg_coerce (args[i], param_type, is_prototyped); + } + + /*elz: this code is to handle the case in which the function to be called + has a pointer to function as parameter and the corresponding actual argument + is the address of a function and not a pointer to function variable. + In aCC compiled code, the calls through pointers to functions (in the body + of the function called by hand) are made via $$dyncall_external which + requires some registers setting, this is taken care of if we call + via a function pointer variable, but not via a function address. + In cc this is not a problem. */ + + if (using_gcc == 0) + if (param_type) + /* if this parameter is a pointer to function*/ + if (TYPE_CODE (param_type) == TYPE_CODE_PTR) + if (TYPE_CODE (param_type->target_type) == TYPE_CODE_FUNC) + /* elz: FIXME here should go the test about the compiler used + to compile the target. We want to issue the error + message only if the compiler used was HP's aCC. + If we used HP's cc, then there is no problem and no need + to return at this point */ + if (using_gcc == 0) /* && compiler == aCC*/ + /* go see if the actual parameter is a variable of type + pointer to function or just a function */ + if (args[i]->lval == not_lval) + { + char *arg_name; + if (find_pc_partial_function((CORE_ADDR)args[i]->aligner.contents[0], &arg_name, NULL, NULL)) + error("\ +You cannot use function <%s> as argument. \n\ +You must use a pointer to function type variable. Command ignored.", arg_name); + } } #if defined (REG_STRUCT_HAS_ADDR) @@ -1213,34 +1445,48 @@ call_function_by_hand (function, nargs, args) && REG_STRUCT_HAS_ADDR (using_gcc, arg_type)) { CORE_ADDR addr; - int len = TYPE_LENGTH (arg_type); + int len; /* = TYPE_LENGTH (arg_type); */ + int aligned_len; + arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i])); + len = TYPE_LENGTH (arg_type); + #ifdef STACK_ALIGN /* MVS 11/22/96: I think at least some of this stack_align code is really broken. Better to let PUSH_ARGUMENTS adjust the stack in a target-defined manner. */ - int aligned_len = STACK_ALIGN (len); -#else - int aligned_len = len; -#endif -#if !(1 INNER_THAN 2) - /* The stack grows up, so the address of the thing we push - is the stack pointer before we push it. */ - addr = sp; + aligned_len = STACK_ALIGN (len); #else - sp -= aligned_len; + aligned_len = len; #endif + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + sp -= aligned_len; + } + else + { + /* The stack grows up, so the address of the thing we push + is the stack pointer before we push it. */ + addr = sp; + } /* Push the structure. */ - write_memory (sp, VALUE_CONTENTS (args[i]), len); -#if 1 INNER_THAN 2 - /* The stack grows down, so the address of the thing we push - is the stack pointer after we push it. */ - addr = sp; -#else - sp += aligned_len; -#endif + write_memory (sp, VALUE_CONTENTS_ALL (args[i]), len); + if (INNER_THAN (1, 2)) + { + /* The stack grows down, so the address of the thing we push + is the stack pointer after we push it. */ + addr = sp; + } + else + { + /* stack grows upward */ + sp += aligned_len; + } /* The value we're going to pass is the address of the thing we just pushed. */ - args[i] = value_from_longest (lookup_pointer_type (value_type), + /*args[i] = value_from_longest (lookup_pointer_type (value_type), + (LONGEST) addr);*/ + args[i] = value_from_longest (lookup_pointer_type (arg_type), (LONGEST) addr); } } @@ -1259,31 +1505,44 @@ call_function_by_hand (function, nargs, args) a target-defined manner. */ len = STACK_ALIGN (len); #endif -#if 1 INNER_THAN 2 - sp -= len; - struct_addr = sp; -#else - struct_addr = sp; - sp += len; -#endif + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + sp -= len; + struct_addr = sp; + } + else + { + /* stack grows upward */ + struct_addr = sp; + sp += len; + } } -#if defined(STACK_ALIGN) && (1 INNER_THAN 2) +/* elz: on HPPA no need for this extra alignment, maybe it is needed + on other architectures. This is because all the alignment is taken care + of in the above code (ifdef REG_STRUCT_HAS_ADDR) and in + hppa_push_arguments*/ +#ifndef NO_EXTRA_ALIGNMENT_NEEDED + +#if defined(STACK_ALIGN) /* MVS 11/22/96: I think at least some of this stack_align code is really broken. Better to let PUSH_ARGUMENTS adjust the stack in a target-defined manner. */ - { - /* If stack grows down, we must leave a hole at the top. */ - int len = 0; + if (INNER_THAN (1, 2)) + { + /* If stack grows down, we must leave a hole at the top. */ + int len = 0; - for (i = nargs - 1; i >= 0; i--) - len += TYPE_LENGTH (VALUE_TYPE (args[i])); + for (i = nargs - 1; i >= 0; i--) + len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i])); #ifdef CALL_DUMMY_STACK_ADJUST - len += CALL_DUMMY_STACK_ADJUST; + len += CALL_DUMMY_STACK_ADJUST; #endif - sp -= STACK_ALIGN (len) - len; - } + sp -= STACK_ALIGN (len) - len; + } #endif /* STACK_ALIGN */ +#endif /* NO_EXTRA_ALIGNMENT_NEEDED */ #ifdef PUSH_ARGUMENTS PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr); @@ -1305,15 +1564,16 @@ call_function_by_hand (function, nargs, args) sp = PUSH_RETURN_ADDRESS(real_pc, sp); #endif /* PUSH_RETURN_ADDRESS */ -#if defined(STACK_ALIGN) && !(1 INNER_THAN 2) - { - /* If stack grows up, we must leave a hole at the bottom, note - that sp already has been advanced for the arguments! */ +#if defined(STACK_ALIGN) + if (! INNER_THAN (1, 2)) + { + /* If stack grows up, we must leave a hole at the bottom, note + that sp already has been advanced for the arguments! */ #ifdef CALL_DUMMY_STACK_ADJUST - sp += CALL_DUMMY_STACK_ADJUST; + sp += CALL_DUMMY_STACK_ADJUST; #endif - sp = STACK_ALIGN (sp); - } + sp = STACK_ALIGN (sp); + } #endif /* STACK_ALIGN */ /* XXX This seems wrong. For stacks that grow down we shouldn't do @@ -1322,9 +1582,11 @@ call_function_by_hand (function, nargs, args) really broken. Better to let PUSH_ARGUMENTS adjust the stack in a target-defined manner. */ #ifdef CALL_DUMMY_STACK_ADJUST -#if 1 INNER_THAN 2 - sp -= CALL_DUMMY_STACK_ADJUST; -#endif + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + sp -= CALL_DUMMY_STACK_ADJUST; + } #endif /* CALL_DUMMY_STACK_ADJUST */ /* Store the address at which the structure is supposed to be @@ -1409,6 +1671,19 @@ the function call).", name); do_cleanups (old_chain); /* Figure out the value returned by the function. */ +/* elz: I defined this new macro for the hppa architecture only. + this gives us a way to get the value returned by the function from the stack, + at the same address we told the function to put it. + We cannot assume on the pa that r28 still contains the address of the returned + structure. Usually this will be overwritten by the callee. + I don't know about other architectures, so I defined this macro +*/ + +#ifdef VALUE_RETURNED_FROM_STACK + if (struct_return) + return (value_ptr) VALUE_RETURNED_FROM_STACK (value_type, struct_addr); +#endif + return value_being_returned (value_type, retbuf, struct_return); } } @@ -1456,10 +1731,10 @@ value_array (lowbound, highbound, elemvec) { error ("bad array bounds (%d, %d)", lowbound, highbound); } - typelength = TYPE_LENGTH (VALUE_TYPE (elemvec[0])); + typelength = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (elemvec[0])); for (idx = 1; idx < nelem; idx++) { - if (TYPE_LENGTH (VALUE_TYPE (elemvec[idx])) != typelength) + if (TYPE_LENGTH (VALUE_ENCLOSING_TYPE (elemvec[idx])) != typelength) { error ("array elements must all be the same size"); } @@ -1468,15 +1743,15 @@ value_array (lowbound, highbound, elemvec) rangetype = create_range_type ((struct type *) NULL, builtin_type_int, lowbound, highbound); arraytype = create_array_type ((struct type *) NULL, - VALUE_TYPE (elemvec[0]), rangetype); + VALUE_ENCLOSING_TYPE (elemvec[0]), rangetype); if (!current_language->c_style_arrays) { val = allocate_value (arraytype); for (idx = 0; idx < nelem; idx++) { - memcpy (VALUE_CONTENTS_RAW (val) + (idx * typelength), - VALUE_CONTENTS (elemvec[idx]), + memcpy (VALUE_CONTENTS_ALL_RAW (val) + (idx * typelength), + VALUE_CONTENTS_ALL (elemvec[idx]), typelength); } VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (elemvec[0]); @@ -1491,7 +1766,7 @@ value_array (lowbound, highbound, elemvec) addr = allocate_space_in_inferior (nelem * typelength); for (idx = 0; idx < nelem; idx++) { - write_memory (addr + (idx * typelength), VALUE_CONTENTS (elemvec[idx]), + write_memory (addr + (idx * typelength), VALUE_CONTENTS_ALL (elemvec[idx]), typelength); } @@ -1641,34 +1916,91 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) register struct type *type; int looking_for_baseclass; { + int found = 0; + char found_class[1024]; + value_ptr v; + struct type *vbase = NULL; + + found_class[0] = '\000'; + + v = search_struct_field_aux (name, arg1, offset, type, looking_for_baseclass, &found, found_class, &vbase); + if (found > 1) + warning ("%s ambiguous; using %s::%s. Use a cast to disambiguate.", + name, found_class, name); + + return v; +} + + +static value_ptr +search_struct_field_aux (name, arg1, offset, type, looking_for_baseclass, found, found_class_name, vbase) + char *name; + register value_ptr arg1; + int offset; + register struct type *type; + int looking_for_baseclass; + int * found; + char * found_class_name; + struct type ** vbase; +{ int i; + value_ptr retval = NULL; + char tmp_class_name[1024]; + int tmp_found = 0; + int assigned = 0; + int nbases = TYPE_N_BASECLASSES (type); + + tmp_class_name[0] = '\000'; CHECK_TYPEDEF (type); if (! looking_for_baseclass) - for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) + for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) { char *t_field_name = TYPE_FIELD_NAME (type, i); if (t_field_name && STREQ (t_field_name, name)) { - value_ptr v; + value_ptr v = NULL; if (TYPE_FIELD_STATIC (type, i)) + v = value_static_field (type, i); + if (v != NULL) { - char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i); - struct symbol *sym = - lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); - if (sym == NULL) - error ("Internal error: could not find physical static variable named %s", - phys_name); - v = value_at (TYPE_FIELD_TYPE (type, i), - SYMBOL_VALUE_ADDRESS (sym), SYMBOL_BFD_SECTION (sym)); + if (!*found) + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + char *class_name = TYPE_TAG_NAME (type); + retval = v; + if (class_name) + strcpy (found_class_name, class_name); + else + found_class_name = NULL; + } + (*found)++; } else - v = value_primitive_field (arg1, offset, i, type); + { + v = value_primitive_field (arg1, offset, i, type); + if (v != NULL) + { + if (!*found) + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + char *class_name = TYPE_TAG_NAME (type); + retval = v; + if (class_name) + strcpy (found_class_name, class_name); + else + found_class_name = NULL; + } + (*found)++; + } + } + if (v == 0) - error("there is no field named %s", name); - return v; + error("Couldn't retrieve field named %s", name); } if (t_field_name @@ -1702,15 +2034,29 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) && TYPE_FIELD_BITPOS (field_type, 0) == 0)) new_offset += TYPE_FIELD_BITPOS (type, i) / 8; - v = search_struct_field (name, arg1, new_offset, field_type, - looking_for_baseclass); - if (v) - return v; + v = search_struct_field_aux (name, arg1, new_offset, field_type, + looking_for_baseclass, &tmp_found, + tmp_class_name, vbase); + if (!*found && v) + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + retval = v; + /* TYPE_TAG_NAME can be null in case of an anonymous union */ + if (TYPE_TAG_NAME (type)) + strcpy (found_class_name, TYPE_TAG_NAME (type)); + else + strcpy (found_class_name, " "); + strcat (found_class_name, "::"); + strcat (found_class_name, tmp_class_name); + } + *found += tmp_found; + tmp_found = 0; } } } - for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) + for (i = 0; i < nbases; i++) { value_ptr v; struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); @@ -1723,41 +2069,262 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass) if (BASETYPE_VIA_VIRTUAL (type, i)) { - int boffset = VALUE_OFFSET (arg1) + offset; - boffset = baseclass_offset (type, i, - VALUE_CONTENTS (arg1) + boffset, - VALUE_ADDRESS (arg1) + boffset); - if (boffset == -1) - error ("virtual baseclass botch"); + int boffset; + value_ptr v2 = allocate_value (VALUE_ENCLOSING_TYPE (arg1)); + + if (TYPE_HAS_VTABLE (type)) + { + /* HP aCC compiled type, use Taligent/HP runtime model */ + int skip; + find_rt_vbase_offset (type, TYPE_BASECLASS (type, i), + VALUE_CONTENTS_ALL (arg1), + offset + VALUE_EMBEDDED_OFFSET (arg1), + &boffset, &skip); + if (skip >= 0) + error ("Virtual base class offset not found from vtable"); + } + + else + { + + boffset = baseclass_offset (type, i, + VALUE_CONTENTS_ALL (arg1) + offset, + VALUE_ADDRESS (arg1) + + VALUE_OFFSET (arg1) + offset); + if (boffset == -1) + error ("virtual baseclass botch"); + + /* The virtual base class pointer might have been clobbered by the + user program. Make sure that it still points to a valid memory + location. */ + + if ((boffset + offset) < 0 || + (boffset + offset) >= TYPE_LENGTH (type)) + { + CORE_ADDR base_addr; + + base_addr = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1) + + boffset + offset; + if (target_read_memory (base_addr, VALUE_CONTENTS_RAW (v2), + TYPE_LENGTH (basetype)) != 0) + error ("virtual baseclass botch"); + VALUE_LVAL (v2) = lval_memory; + VALUE_ADDRESS (v2) = base_addr; + assigned = 1; + } + } + + if (!assigned) + { + VALUE_LVAL (v2) = VALUE_LVAL (arg1); + VALUE_ADDRESS (v2) = VALUE_ADDRESS (arg1); + } + + /* Earlier, this code used to allocate a value of type + basetype and copy the contents of arg1 at the + appropriate offset into the new value. This doesn't + work because there is important stuff (virtual bases, + for example) that could be anywhere in the contents + of arg1, and not just within the length of a basetype + object. In particular the boffset below could be + negative, with the HP/Taligent C++ runtime system. + So, the only way to ensure that required information + is not lost is to always allocate a value of the same + type as arg1 and to fill it with the _entire_ + contents of arg1. It sounds wasteful, but there is + really no way around it if later member lookup, + casts, etc. have to work correctly with the returned + value. */ + + + VALUE_TYPE (v2) = basetype; + VALUE_OFFSET (v2) = VALUE_OFFSET (arg1); + VALUE_EMBEDDED_OFFSET(v2) + = VALUE_EMBEDDED_OFFSET(arg1) + offset + boffset; + if (VALUE_LAZY (arg1)) + VALUE_LAZY (v2) = 1; + else + memcpy ((char *) (v2)->aligner.contents, + (char *) (arg1)->aligner.contents, + TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg1))); + if (found_baseclass) - { - value_ptr v2 = allocate_value (basetype); - VALUE_LVAL (v2) = VALUE_LVAL (arg1); - VALUE_ADDRESS (v2) = VALUE_ADDRESS (arg1); - VALUE_OFFSET (v2) = VALUE_OFFSET (arg1) + offset + boffset; - if (VALUE_LAZY (arg1)) - VALUE_LAZY (v2) = 1; - else - memcpy (VALUE_CONTENTS_RAW (v2), - VALUE_CONTENTS_RAW (arg1) + offset + boffset, - TYPE_LENGTH (basetype)); - return v2; + { + /*return v2;*/ + + if (!*found) /* not yet found anything */ + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + retval = v2; + strcpy (found_class_name, TYPE_TAG_NAME (type)); + } + /* Don't count virtual bases twice when deciding ambiguity */ + if (*vbase != basetype) /* works for null *vbase */ + (*found)++; + /* Is this the first virtual base where we "found" something? */ + if (!*vbase) + *vbase = basetype; } - v = search_struct_field (name, arg1, offset + boffset, - TYPE_BASECLASS (type, i), - looking_for_baseclass); + else /* base not found, or looking for member */ + { + v = search_struct_field_aux (name, arg1, offset + boffset, + TYPE_BASECLASS (type, i), + looking_for_baseclass, &tmp_found, + tmp_class_name, vbase); + if (!*found && v) + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + retval = v; + /* TYPE_TAG_NAME can be null in case of an anonymous union */ + if (TYPE_TAG_NAME (type)) + strcpy (found_class_name, TYPE_TAG_NAME (type)); + else + strcpy (found_class_name, " "); + strcat (found_class_name, "::"); + strcat (found_class_name, tmp_class_name); + } + /* Don't count virtual bases twice when deciding ambiguity */ + if (*vbase != basetype) /* works for null *vbase */ + *found += tmp_found; + /* Is this the first virtual base where we "found" something? */ + if (!*vbase) + *vbase = basetype; + tmp_found = 0; + } } else if (found_baseclass) - v = value_primitive_field (arg1, offset, i, type); + { + v = value_primitive_field (arg1, offset, i, type); + if (!*found) + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + retval = v; + strcpy (found_class_name, TYPE_TAG_NAME (type)); + } + (*found)++; + } else - v = search_struct_field (name, arg1, - offset + TYPE_BASECLASS_BITPOS (type, i) / 8, - basetype, looking_for_baseclass); - if (v) return v; + { + v = search_struct_field_aux (name, arg1, + offset + TYPE_BASECLASS_BITPOS (type, i) / 8, + basetype, looking_for_baseclass, &tmp_found, + tmp_class_name, vbase); + if (!*found && v) + { + /* Record return value and class name, and continue + looking for possible ambiguous members */ + retval = v; + /* TYPE_TAG_NAME can be null in case of an anonymous union */ + if (TYPE_TAG_NAME (type)) + strcpy (found_class_name, TYPE_TAG_NAME (type)); + else + strcpy (found_class_name, " "); + strcat (found_class_name, "::"); + strcat (found_class_name, tmp_class_name); + } + *found += tmp_found; + tmp_found = 0; + } } - return NULL; + return retval; } + +/* Return the offset (in bytes) of the virtual base of type BASETYPE + * in an object pointed to by VALADDR (on the host), assumed to be of + * type TYPE. OFFSET is number of bytes beyond start of ARG to start + * looking (in case VALADDR is the contents of an enclosing object). + * + * This routine recurses on the primary base of the derived class because + * the virtual base entries of the primary base appear before the other + * virtual base entries. + * + * If the virtual base is not found, a negative integer is returned. + * The magnitude of the negative integer is the number of entries in + * the virtual table to skip over (entries corresponding to various + * ancestral classes in the chain of primary bases). + * + * Important: This assumes the HP / Taligent C++ runtime + * conventions. Use baseclass_offset() instead to deal with g++ + * conventions. */ + +void +find_rt_vbase_offset(type, basetype, valaddr, offset, boffset_p, skip_p) + struct type * type; + struct type * basetype; + char * valaddr; + int offset; + int * boffset_p; + int * skip_p; +{ + int boffset; /* offset of virtual base */ + int index; /* displacement to use in virtual table */ + int skip; + + value_ptr vp; + CORE_ADDR vtbl; /* the virtual table pointer */ + struct type * pbc; /* the primary base class */ + + /* Look for the virtual base recursively in the primary base, first. + * This is because the derived class object and its primary base + * subobject share the primary virtual table. */ + + boffset = 0; + pbc = TYPE_PRIMARY_BASE(type); + if (pbc) + { + find_rt_vbase_offset (pbc, basetype, valaddr, offset, &boffset, &skip); + if (skip < 0) + { + *boffset_p = boffset; + *skip_p = -1; + return; + } + } + else + skip = 0; + + + /* Find the index of the virtual base according to HP/Taligent + runtime spec. (Depth-first, left-to-right.) */ + index = virtual_base_index_skip_primaries (basetype, type); + + if (index < 0) { + *skip_p = skip + virtual_base_list_length_skip_primaries (type); + *boffset_p = 0; + return; + } + + /* pai: FIXME -- 32x64 possible problem */ + /* First word (4 bytes) in object layout is the vtable pointer */ + vtbl = * (CORE_ADDR *) (valaddr + offset); + + /* Before the constructor is invoked, things are usually zero'd out. */ + if (vtbl == 0) + error ("Couldn't find virtual table -- object may not be constructed yet."); + + + /* Find virtual base's offset -- jump over entries for primary base + * ancestors, then use the index computed above. But also adjust by + * HP_ACC_VBASE_START for the vtable slots before the start of the + * virtual base entries. Offset is negative -- virtual base entries + * appear _before_ the address point of the virtual table. */ + + /* pai: FIXME -- 32x64 problem, if word = 8 bytes, change multiplier + & use long type */ + + /* epstein : FIXME -- added param for overlay section. May not be correct */ + vp = value_at (builtin_type_int, vtbl + 4 * (- skip - index - HP_ACC_VBASE_START), NULL); + boffset = value_as_long (vp); + *skip_p = -1; + *boffset_p = boffset; + return; +} + + /* Helper function used by value_struct_elt to recurse through baseclasses. Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes, and search in it assuming it has (class) type TYPE. @@ -1797,7 +2364,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) name_matched = 1; if (j > 0 && args == 0) - error ("cannot resolve overloaded method `%s'", name); + error ("cannot resolve overloaded method `%s': no arguments supplied", name); while (j >= 0) { if (TYPE_FN_FIELD_STUB (f, j)) @@ -1823,14 +2390,47 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) if (BASETYPE_VIA_VIRTUAL (type, i)) { - base_offset = VALUE_OFFSET (*arg1p) + offset; - base_offset = - baseclass_offset (type, i, - VALUE_CONTENTS (*arg1p) + base_offset, - VALUE_ADDRESS (*arg1p) + base_offset); - if (base_offset == -1) - error ("virtual baseclass botch"); - } + if (TYPE_HAS_VTABLE (type)) + { + /* HP aCC compiled type, search for virtual base offset + according to HP/Taligent runtime spec. */ + int skip; + find_rt_vbase_offset (type, TYPE_BASECLASS (type, i), + VALUE_CONTENTS_ALL (*arg1p), + offset + VALUE_EMBEDDED_OFFSET (*arg1p), + &base_offset, &skip); + if (skip >= 0) + error ("Virtual base class offset not found in vtable"); + } + else + { + struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i)); + char *base_valaddr; + + /* The virtual base class pointer might have been clobbered by the + user program. Make sure that it still points to a valid memory + location. */ + + if (offset < 0 || offset >= TYPE_LENGTH (type)) + { + base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass)); + if (target_read_memory (VALUE_ADDRESS (*arg1p) + + VALUE_OFFSET (*arg1p) + offset, + base_valaddr, + TYPE_LENGTH (baseclass)) != 0) + error ("virtual baseclass botch"); + } + else + base_valaddr = VALUE_CONTENTS (*arg1p) + offset; + + base_offset = + baseclass_offset (type, i, base_valaddr, + VALUE_ADDRESS (*arg1p) + + VALUE_OFFSET (*arg1p) + offset); + if (base_offset == -1) + error ("virtual baseclass botch"); + } + } else { base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8; @@ -1975,6 +2575,142 @@ value_struct_elt (argp, args, name, static_memfuncp, err) return v; } + +/* Search through the methods of an object (and its bases) + * to find a specified method. Return the pointer to the + * fn_field list of overloaded instances. + * Helper function for value_find_oload_list. + * ARGP is a pointer to a pointer to a value (the object) + * METHOD is a string containing the method name + * OFFSET is the offset within the value + * STATIC_MEMFUNCP is set if the method is static + * TYPE is the assumed type of the object + * NUM_FNS is the number of overloaded instances + * BASETYPE is set to the actual type of the subobject where the method is found + * BOFFSET is the offset of the base subobject where the method is found */ + +struct fn_field * +find_method_list (argp, method, offset, static_memfuncp, type, num_fns, basetype, boffset) + value_ptr *argp; + char * method; + int offset; + int * static_memfuncp; + struct type * type; + int * num_fns; + struct type ** basetype; + int * boffset; +{ + int i; + struct fn_field * f; + CHECK_TYPEDEF (type); + + *num_fns = 0; + + /* First check in object itself */ + for (i = TYPE_NFN_FIELDS (type) -1; i >= 0; i--) + { + /* pai: FIXME What about operators and type conversions? */ + char * fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i); + if (fn_field_name && STREQ (fn_field_name, method)) + { + *num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i); + *basetype = type; + *boffset = offset; + return TYPE_FN_FIELDLIST1 (type, i); + } + } + + /* Not found in object, check in base subobjects */ + for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) + { + int base_offset; + if (BASETYPE_VIA_VIRTUAL (type, i)) + { + if (TYPE_HAS_VTABLE (type)) + { + /* HP aCC compiled type, search for virtual base offset + * according to HP/Taligent runtime spec. */ + int skip; + find_rt_vbase_offset (type, TYPE_BASECLASS (type, i), + VALUE_CONTENTS_ALL (*argp), + offset + VALUE_EMBEDDED_OFFSET (*argp), + &base_offset, &skip); + if (skip >= 0) + error ("Virtual base class offset not found in vtable"); + } + else + { + /* probably g++ runtime model */ + base_offset = VALUE_OFFSET (*argp) + offset; + base_offset = + baseclass_offset (type, i, + VALUE_CONTENTS (*argp) + base_offset, + VALUE_ADDRESS (*argp) + base_offset); + if (base_offset == -1) + error ("virtual baseclass botch"); + } + } + else /* non-virtual base, simply use bit position from debug info */ + { + base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8; + } + f = find_method_list (argp, method, base_offset + offset, + static_memfuncp, TYPE_BASECLASS (type, i), num_fns, basetype, boffset); + if (f) + return f; + } + return NULL; +} + +/* Return the list of overloaded methods of a specified name. + * ARGP is a pointer to a pointer to a value (the object) + * METHOD is the method name + * OFFSET is the offset within the value contents + * STATIC_MEMFUNCP is set if the method is static + * NUM_FNS is the number of overloaded instances + * BASETYPE is set to the type of the base subobject that defines the method + * BOFFSET is the offset of the base subobject which defines the method */ + +struct fn_field * +value_find_oload_method_list (argp, method, offset, static_memfuncp, num_fns, basetype, boffset) + value_ptr *argp; + char * method; + int offset; + int * static_memfuncp; + int * num_fns; + struct type ** basetype; + int * boffset; +{ + struct type * t; + value_ptr v; + + t = check_typedef (VALUE_TYPE (*argp)); + + /* code snarfed from value_struct_elt */ + while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF) + { + *argp = value_ind (*argp); + /* Don't coerce fn pointer to fn and then back again! */ + if (TYPE_CODE (VALUE_TYPE (*argp)) != TYPE_CODE_FUNC) + COERCE_ARRAY (*argp); + t = check_typedef (VALUE_TYPE (*argp)); + } + + if (TYPE_CODE (t) == TYPE_CODE_MEMBER) + error ("Not implemented: member type in value_find_oload_lis"); + + if ( TYPE_CODE (t) != TYPE_CODE_STRUCT + && TYPE_CODE (t) != TYPE_CODE_UNION) + error ("Attempt to extract a component of a value that is not a struct or union"); + + /* Assume it's not static, unless we see that it is. */ + if (static_memfuncp) + *static_memfuncp =0; + + return find_method_list (argp, method, 0, static_memfuncp, t, num_fns, basetype, boffset); + +} + /* C++: return 1 is NAME is a legitimate name for the destructor of type TYPE. If TYPE does not have a destructor, or if NAME is inappropriate for TYPE, an error is signaled. */ @@ -2111,15 +2847,11 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) { if (TYPE_FIELD_STATIC (t, i)) { - char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i); - struct symbol *sym = - lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); - if (sym == NULL) - error ("Internal error: could not find physical static variable named %s", - phys_name); - return value_at (SYMBOL_TYPE (sym), - SYMBOL_VALUE_ADDRESS (sym), - SYMBOL_BFD_SECTION (sym)); + v = value_static_field (t, i); + if (v == NULL) + error ("Internal error: could not find static variable %s", + name); + return v; } if (TYPE_FIELD_PACKED (t, i)) error ("pointers to bitfield members not allowed"); @@ -2227,6 +2959,226 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) return 0; } + +/* Find the real run-time type of a value using RTTI. + * V is a pointer to the value. + * A pointer to the struct type entry of the run-time type + * is returneed. + * FULL is a flag that is set only if the value V includes + * the entire contents of an object of the RTTI type. + * TOP is the offset to the top of the enclosing object of + * the real run-time type. This offset may be for the embedded + * object, or for the enclosing object of V. + * USING_ENC is the flag that distinguishes the two cases. + * If it is 1, then the offset is for the enclosing object, + * otherwise for the embedded object. + * + * This currently works only for RTTI information generated + * by the HP ANSI C++ compiler (aCC). g++ today (1997-06-10) + * does not appear to support RTTI. This function returns a + * NULL value for objects in the g++ runtime model. */ + +struct type * +value_rtti_type (v, full, top, using_enc) + value_ptr v; + int * full; + int * top; + int * using_enc; +{ + struct type * known_type; + struct type * rtti_type; + CORE_ADDR coreptr; + value_ptr vp; + int using_enclosing = 0; + long top_offset = 0; + char rtti_type_name[256]; + + if (full) + *full = 0; + if (top) + *top = -1; + if (using_enc) + *using_enc = 0; + + /* Get declared type */ + known_type = VALUE_TYPE (v); + CHECK_TYPEDEF (known_type); + /* RTTI works only or class objects */ + if (TYPE_CODE (known_type) != TYPE_CODE_CLASS) + return NULL; + + /* If neither the declared type nor the enclosing type of the + * value structure has a HP ANSI C++ style virtual table, + * we can't do anything. */ + if (!TYPE_HAS_VTABLE (known_type)) + { + known_type = VALUE_ENCLOSING_TYPE (v); + CHECK_TYPEDEF (known_type); + if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) || + !TYPE_HAS_VTABLE (known_type)) + return NULL; /* No RTTI, or not HP-compiled types */ + CHECK_TYPEDEF (known_type); + using_enclosing = 1; + } + + if (using_enclosing && using_enc) + *using_enc = 1; + + /* First get the virtual table address */ + coreptr = * (CORE_ADDR *) ((VALUE_CONTENTS_ALL (v)) + + VALUE_OFFSET (v) + + (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v))); + if (coreptr == 0) + return NULL; /* return silently -- maybe called on gdb-generated value */ + + /* Fetch the top offset of the object */ + /* FIXME possible 32x64 problem with pointer size & arithmetic */ + vp = value_at (builtin_type_int, + coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET, + VALUE_BFD_SECTION (v)); + top_offset = value_as_long (vp); + if (top) + *top = top_offset; + + /* Fetch the typeinfo pointer */ + /* FIXME possible 32x64 problem with pointer size & arithmetic */ + vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v)); + /* Indirect through the typeinfo pointer and retrieve the pointer + * to the string name */ + coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp)); + if (!coreptr) + error ("Retrieved null typeinfo pointer in trying to determine run-time type"); + vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v)); /* 4 -> offset of name field */ + /* FIXME possible 32x64 problem */ + + coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp)); + + read_memory_string (coreptr, rtti_type_name, 256); + + if (strlen (rtti_type_name) == 0) + error ("Retrieved null type name from typeinfo"); + + /* search for type */ + rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1); + + if (!rtti_type) + error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name); + CHECK_TYPEDEF (rtti_type); + +#if 0 /* debugging*/ + printf("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1); +#endif + + /* Check whether we have the entire object */ + if (full /* Non-null pointer passed */ + + && + /* Either we checked on the whole object in hand and found the + top offset to be zero */ + (((top_offset == 0) && + using_enclosing && + TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type)) + || + /* Or we checked on the embedded object and top offset was the + same as the embedded offset */ + ((top_offset == VALUE_EMBEDDED_OFFSET (v)) && + !using_enclosing && + TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type)))) + + *full = 1; + + return rtti_type; +} + +/* Given a pointer value V, find the real (RTTI) type + of the object it points to. + Other parameters FULL, TOP, USING_ENC as with value_rtti_type() + and refer to the values computed for the object pointed to. */ + +struct type * +value_rtti_target_type (v, full, top, using_enc) + value_ptr v; + int * full; + int * top; + int * using_enc; +{ + value_ptr target; + + target = value_ind (v); + + return value_rtti_type (target, full, top, using_enc); +} + +/* Given a value pointed to by ARGP, check its real run-time type, and + if that is different from the enclosing type, create a new value + using the real run-time type as the enclosing type (and of the same + type as ARGP) and return it, with the embedded offset adjusted to + be the correct offset to the enclosed object + RTYPE is the type, and XFULL, XTOP, and XUSING_ENC are the other + parameters, computed by value_rtti_type(). If these are available, + they can be supplied and a second call to value_rtti_type() is avoided. + (Pass RTYPE == NULL if they're not available */ + +value_ptr +value_full_object (argp, rtype, xfull, xtop, xusing_enc) + value_ptr argp; + struct type * rtype; + int xfull; + int xtop; + int xusing_enc; + +{ + struct type * real_type; + int full = 0; + int top = -1; + int using_enc = 0; + value_ptr new_val; + + if (rtype) + { + real_type = rtype; + full = xfull; + top = xtop; + using_enc = xusing_enc; + } + else + real_type = value_rtti_type (argp, &full, &top, &using_enc); + + /* If no RTTI data, or if object is already complete, do nothing */ + if (!real_type || real_type == VALUE_ENCLOSING_TYPE (argp)) + return argp; + + /* If we have the full object, but for some reason the enclosing + type is wrong, set it */ /* pai: FIXME -- sounds iffy */ + if (full) + { + VALUE_ENCLOSING_TYPE (argp) = real_type; + return argp; + } + + /* Check if object is in memory */ + if (VALUE_LVAL (argp) != lval_memory) + { + warning ("Couldn't retrieve complete object of RTTI type %s; object may be in register(s).", TYPE_NAME (real_type)); + + return argp; + } + + /* All other cases -- retrieve the complete object */ + /* Go back by the computed top_offset from the beginning of the object, + adjusting for the embedded offset of argp if that's what value_rtti_type + used for its computation. */ + new_val = value_at_lazy (real_type, VALUE_ADDRESS (argp) - top + + (using_enc ? 0 : VALUE_EMBEDDED_OFFSET (argp)), + VALUE_BFD_SECTION (argp)); + VALUE_TYPE (new_val) = VALUE_TYPE (argp); + VALUE_EMBEDDED_OFFSET (new_val) = using_enc ? top + VALUE_EMBEDDED_OFFSET (argp) : top; + return new_val; +} + + + + /* C++: return the value of the class instance variable, if one exists. Flag COMPLAIN signals an error if the request is made in an inappropriate context. */ @@ -2242,9 +3194,11 @@ value_of_this (complain) value_ptr this; if (selected_frame == 0) - if (complain) - error ("no frame selected"); - else return 0; + { + if (complain) + error ("no frame selected"); + else return 0; + } func = get_frame_function (selected_frame); if (!func) @@ -2257,9 +3211,11 @@ value_of_this (complain) b = SYMBOL_BLOCK_VALUE (func); i = BLOCK_NSYMS (b); if (i <= 0) - if (complain) - error ("no args, no `this'"); - else return 0; + { + if (complain) + error ("no args, no `this'"); + else return 0; + } /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER symbol instead of the LOC_ARG one (if both exist). */ @@ -2439,4 +3395,12 @@ _initialize_valops () &setlist), &showlist); #endif + + add_show_from_set + (add_set_cmd ("overload-resolution", class_support, var_boolean, (char *)&overload_resolution, + "Set overload resolution in evaluating C++ functions.", + &setlist), + &showlist); + overload_resolution = 1; + } diff --git a/gdb/value.h b/gdb/value.h index ae2545a..f2c4da7 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -61,7 +61,9 @@ struct value lval_reg_frame_relative. */ int regnum; } location; - /* Describes offset of a value within lval a structure in bytes. */ + /* Describes offset of a value within lval of a structure in bytes. + This is used in retrieving contents from target memory. [Note also + the member embedded_offset below.] */ int offset; /* Only used for bitfields; number of bits contained in them. */ int bitsize; @@ -77,6 +79,14 @@ struct value CORE_ADDR frame_addr; /* Type of the value. */ struct type *type; + /* Type of the enclosing object if this is an embedded subobject. + The member embedded_offset gives the real position of the subobject + if type is not the same as enclosing_type. + + If the type field is a pointer type, then enclosing_type is + a pointer type pointing to the real (enclosing) type of the target + object. */ + struct type *enclosing_type; /* Values are stored in a chain, so that they can be deleted easily over calls to the inferior. Values assigned to internal variables or put into the value history are taken off this @@ -101,23 +111,41 @@ struct value /* If nonzero, this is the value of a variable which does not actually exist in the program. */ char optimized_out; + /* If this value represents an object that is embedded inside a + larger object (e.g., a base subobject in C++), this gives the + offset (in bytes) from the start of the contents buffer where + the embedded object begins. This is required because some C++ + runtime implementations lay out objects (especially virtual bases + with possibly negative offsets to ancestors). + Note: This may be positive or negative! Also note that this offset + is not used when retrieving contents from target memory; the entire + enclosing object has to be retrieved always, and the offset for + that is given by the member offset above. */ + int embedded_offset; + /* If this value represents a pointer to an object that is embedded + in another object, this gives the embedded_offset of the object + that is pointed to. */ + int pointed_to_offset; /* The BFD section associated with this value. */ asection *bfd_section; /* Actual contents of the value. For use of this value; setting it uses the stuff above. Not valid if lazy is nonzero. Target byte-order. We force it to be aligned properly for any - possible value. */ + possible value. Note that a value therefore extends beyond + what is declared here. */ union { long contents[1]; double force_double_align; LONGEST force_longlong_align; char *literal_data; } aligner; + /* Do not add any new members here -- contents above will trash them */ }; typedef struct value *value_ptr; #define VALUE_TYPE(val) (val)->type +#define VALUE_ENCLOSING_TYPE(val) (val)->enclosing_type #define VALUE_LAZY(val) (val)->lazy /* VALUE_CONTENTS and VALUE_CONTENTS_RAW both return the address of the gdb buffer used to hold a copy of the contents of the lval. @@ -125,10 +153,23 @@ typedef struct value *value_ptr; it uses value_fetch_lazy() to load the buffer from the process being debugged if it hasn't already been loaded. VALUE_CONTENTS_RAW is used when data is being stored into the buffer, or when it is - certain that the contents of the buffer are valid. */ -#define VALUE_CONTENTS_RAW(val) ((char *) (val)->aligner.contents) + certain that the contents of the buffer are valid. + Note: The contents pointer is adjusted by the offset required to + get to the real subobject, if the value happens to represent + something embedded in a larger run-time object. */ + +#define VALUE_CONTENTS_RAW(val) ((char *) (val)->aligner.contents + (val)->embedded_offset) #define VALUE_CONTENTS(val) ((void)(VALUE_LAZY(val) && value_fetch_lazy(val)),\ VALUE_CONTENTS_RAW(val)) + +/* The ALL variants of the above two macros do not adjust the returned + pointer by the embedded_offset value. */ + +#define VALUE_CONTENTS_ALL_RAW(val) ((char *) (val)->aligner.contents) +#define VALUE_CONTENTS_ALL(val) ((void) (VALUE_LAZY(val) && value_fetch_lazy(val)),\ + VALUE_CONTENTS_ALL_RAW(val)) + + extern int value_fetch_lazy PARAMS ((value_ptr val)); #define VALUE_LVAL(val) (val)->lval @@ -142,6 +183,8 @@ extern int value_fetch_lazy PARAMS ((value_ptr val)); #define VALUE_NEXT(val) (val)->next #define VALUE_REGNO(val) (val)->regno #define VALUE_OPTIMIZED_OUT(val) ((val)->optimized_out) +#define VALUE_EMBEDDED_OFFSET(val) ((val)->embedded_offset) +#define VALUE_POINTED_TO_OFFSET(val) ((val)->pointed_to_offset) #define VALUE_BFD_SECTION(val) ((val)->bfd_section) /* Convert a REF to the object referenced. */ @@ -302,12 +345,24 @@ extern value_ptr value_struct_elt_for_reference PARAMS ((struct type *domain, extern value_ptr value_static_field PARAMS ((struct type *type, int fieldno)); +extern struct fn_field * +value_find_oload_method_list PARAMS ((value_ptr *, char *, int, int *, int *, struct type **, int *)); + extern value_ptr value_field PARAMS ((value_ptr arg1, int fieldno)); extern value_ptr value_primitive_field PARAMS ((value_ptr arg1, int offset, int fieldno, struct type *arg_type)); +extern struct type * +value_rtti_type PARAMS ((value_ptr, int *, int *, int *)); + +extern struct type * +value_rtti_target_type PARAMS ((value_ptr, int *, int *, int *)); + +extern value_ptr +value_full_object PARAMS ((value_ptr, struct type *, int, int, int)); + extern value_ptr value_cast PARAMS ((struct type *type, value_ptr arg2)); extern value_ptr value_zero PARAMS ((struct type *type, enum lval_type lv)); @@ -463,7 +518,7 @@ extern value_ptr value_release_to_mark PARAMS ((value_ptr mark)); extern int -val_print PARAMS ((struct type *type, char *valaddr, CORE_ADDR address, +val_print PARAMS ((struct type *type, char *valaddr, int embedded_offset, CORE_ADDR address, GDB_FILE *stream, int format, int deref_ref, int recurse, enum val_prettyprint pretty)); @@ -504,10 +559,10 @@ extern value_ptr call_function_by_hand PARAMS ((value_ptr, int, value_ptr *)); extern value_ptr value_literal_complex PARAMS ((value_ptr, value_ptr, struct type*)); +extern void find_rt_vbase_offset PARAMS ((struct type *, struct type *, char *, int, int *, int *)); + extern value_ptr find_function_in_inferior PARAMS ((char *)); extern value_ptr value_allocate_space_in_inferior PARAMS ((int)); -extern void _initialize_values PARAMS ((void)); - #endif /* !defined (VALUE_H) */ diff --git a/gdb/values.c b/gdb/values.c index db6f204..ecc11fe 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -86,6 +86,7 @@ allocate_value (type) VALUE_NEXT (val) = all_values; all_values = val; VALUE_TYPE (val) = type; + VALUE_ENCLOSING_TYPE (val) = type; VALUE_LVAL (val) = not_lval; VALUE_ADDRESS (val) = 0; VALUE_FRAME (val) = 0; @@ -96,6 +97,8 @@ allocate_value (type) VALUE_LAZY (val) = 0; VALUE_OPTIMIZED_OUT (val) = 0; VALUE_BFD_SECTION (val) = NULL; + VALUE_EMBEDDED_OFFSET (val) = 0; + VALUE_POINTED_TO_OFFSET (val) = 0; val->modifiable = 1; return val; } @@ -213,8 +216,9 @@ value_ptr value_copy (arg) value_ptr arg; { - register struct type *type = VALUE_TYPE (arg); - register value_ptr val = allocate_value (type); + register struct type *encl_type = VALUE_ENCLOSING_TYPE (arg); + register value_ptr val = allocate_value (encl_type); + VALUE_TYPE (val) = VALUE_TYPE (arg); VALUE_LVAL (val) = VALUE_LVAL (arg); VALUE_ADDRESS (val) = VALUE_ADDRESS (arg); VALUE_OFFSET (val) = VALUE_OFFSET (arg); @@ -224,12 +228,15 @@ value_copy (arg) VALUE_REGNO (val) = VALUE_REGNO (arg); VALUE_LAZY (val) = VALUE_LAZY (arg); VALUE_OPTIMIZED_OUT (val) = VALUE_OPTIMIZED_OUT (arg); + VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (arg); + VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (arg); VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (arg); val->modifiable = arg->modifiable; if (!VALUE_LAZY (val)) { - memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg), - TYPE_LENGTH (VALUE_TYPE (arg))); + memcpy (VALUE_CONTENTS_ALL_RAW (val), VALUE_CONTENTS_ALL_RAW (arg), + TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg))); + } return val; } @@ -744,9 +751,23 @@ value_static_field (type, fieldno) char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); struct symbol *sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL); if (sym == NULL) - return NULL; - addr = SYMBOL_VALUE_ADDRESS (sym); - sect = SYMBOL_BFD_SECTION (sym); + { + /* With some compilers, e.g. HP aCC, static data members are reported + as non-debuggable symbols */ + struct minimal_symbol * msym = lookup_minimal_symbol (phys_name, NULL, NULL); + if (!msym) + return NULL; + else + { + addr = SYMBOL_VALUE_ADDRESS (msym); + sect = SYMBOL_BFD_SECTION (msym); + } + } + else + { + addr = SYMBOL_VALUE_ADDRESS (sym); + sect = SYMBOL_BFD_SECTION (sym); + } SET_FIELD_PHYSADDR (TYPE_FIELD (type, fieldno), addr); } return value_at (TYPE_FIELD_TYPE (type, fieldno), addr, sect); @@ -782,23 +803,43 @@ value_primitive_field (arg1, offset, fieldno, arg_type) VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8; VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno); } + else if (fieldno < TYPE_N_BASECLASSES (arg_type)) + { + /* This field is actually a base subobject, so preserve the + entire object's contents for later references to virtual + bases, etc. */ + v = allocate_value (VALUE_ENCLOSING_TYPE (arg1)); + VALUE_TYPE (v) = arg_type; + if (VALUE_LAZY (arg1)) + VALUE_LAZY (v) = 1; + else + memcpy (VALUE_CONTENTS_ALL_RAW (v), VALUE_CONTENTS_ALL_RAW (arg1), + TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg1))); + VALUE_OFFSET (v) = VALUE_OFFSET (arg1); + VALUE_EMBEDDED_OFFSET (v) + = offset + + VALUE_EMBEDDED_OFFSET (arg1) + + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; + } else { + /* Plain old data member */ + offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; v = allocate_value (type); if (VALUE_LAZY (arg1)) VALUE_LAZY (v) = 1; else memcpy (VALUE_CONTENTS_RAW (v), - VALUE_CONTENTS_RAW (arg1) + offset - + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8, + VALUE_CONTENTS_RAW (arg1) + offset, TYPE_LENGTH (type)); + VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset; } VALUE_LVAL (v) = VALUE_LVAL (arg1); if (VALUE_LVAL (arg1) == lval_internalvar) VALUE_LVAL (v) = lval_internalvar_component; VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1); - VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset - + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; +/* VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset + + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; */ return v; } @@ -875,74 +916,164 @@ value_virtual_fn_field (arg1p, f, j, type, offset) { value_ptr arg1 = *arg1p; struct type *type1 = check_typedef (VALUE_TYPE (arg1)); - struct type *entry_type; - /* First, get the virtual function table pointer. That comes - with a strange type, so cast it to type `pointer to long' (which - should serve just fine as a function type). Then, index into - the table, and convert final value to appropriate function type. */ - value_ptr entry, vfn, vtbl; - value_ptr vi = value_from_longest (builtin_type_int, - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); - struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j); - struct type *context; - if (fcontext == NULL) - /* We don't have an fcontext (e.g. the program was compiled with - g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE. - This won't work right for multiple inheritance, but at least we - should do as well as GDB 3.x did. */ - fcontext = TYPE_VPTR_BASETYPE (type); - context = lookup_pointer_type (fcontext); - /* Now context is a pointer to the basetype containing the vtbl. */ - if (TYPE_TARGET_TYPE (context) != type1) - { - arg1 = value_ind (value_cast (context, value_addr (arg1))); - type1 = check_typedef (VALUE_TYPE (arg1)); - } - context = type1; - /* Now context is the basetype containing the vtbl. */ - - /* This type may have been defined before its virtual function table - was. If so, fill in the virtual function table entry for the - type now. */ - if (TYPE_VPTR_FIELDNO (context) < 0) - fill_in_vptr_fieldno (context); - - /* The virtual function table is now an array of structures - which have the form { int16 offset, delta; void *pfn; }. */ - vtbl = value_ind (value_primitive_field (arg1, 0, - TYPE_VPTR_FIELDNO (context), - TYPE_VPTR_BASETYPE (context))); - - /* Index into the virtual function table. This is hard-coded because - looking up a field is not cheap, and it may be important to save - time, e.g. if the user has set a conditional breakpoint calling - a virtual function. */ - entry = value_subscript (vtbl, vi); - entry_type = check_typedef (VALUE_TYPE (entry)); - - if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT) + if (TYPE_HAS_VTABLE (type)) { - /* Move the `this' pointer according to the virtual function table. */ - VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)); + /* Deal with HP/Taligent runtime model for virtual functions */ + value_ptr vp; + value_ptr argp; /* arg1 cast to base */ + CORE_ADDR vfunc_addr; /* address of virtual method */ + CORE_ADDR coreptr; /* pointer to target address */ + int class_index; /* which class segment pointer to use */ + struct type * ftype = TYPE_FN_FIELD_TYPE (f, j); /* method type */ + + argp = value_cast (type, *arg1p); + + if (VALUE_ADDRESS (argp) == 0) + error ("Address of object is null; object may not have been created."); - if (! VALUE_LAZY (arg1)) - { - VALUE_LAZY (arg1) = 1; - value_fetch_lazy (arg1); - } + /* pai: FIXME -- 32x64 possible problem? */ + /* First word (4 bytes) in object layout is the vtable pointer */ + coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (argp)); /* pai: (temp) */ + /* + offset + VALUE_EMBEDDED_OFFSET (argp)); */ - vfn = value_field (entry, 2); + if (!coreptr) + error ("Virtual table pointer is null for object; object may not have been created."); + + /* pai/1997-05-09 + * FIXME: The code here currently handles only + * the non-RRBC case of the Taligent/HP runtime spec; when RRBC + * is introduced, the condition for the "if" below will have to + * be changed to be a test for the RRBC case. */ + + if (1) + { + /* Non-RRBC case; the virtual function pointers are stored at fixed + * offsets in the virtual table. */ + + /* Retrieve the offset in the virtual table from the debug + * info. The offset of the vfunc's entry is in words from + * the beginning of the vtable; but first we have to adjust + * by HP_ACC_VFUNC_START to account for other entries */ + + /* pai: FIXME: 32x64 problem here, a word may be 8 bytes in + * which case the multiplier should be 8 and values should be long */ + vp = value_at (builtin_type_int, + coreptr + 4 * (TYPE_FN_FIELD_VOFFSET (f, j) + HP_ACC_VFUNC_START), NULL); + + coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp)); + /* coreptr now contains the address of the virtual function */ + /* (Actually, it contains the pointer to the plabel for the function. */ + } + else + { + /* RRBC case; the virtual function pointers are found by double + * indirection through the class segment tables. */ + + /* Choose class segment depending on type we were passed */ + class_index = class_index_in_primary_list (type); + + /* Find class segment pointer. These are in the vtable slots after + * some other entries, so adjust by HP_ACC_VFUNC_START for that. */ + /* pai: FIXME 32x64 problem here, if words are 8 bytes long + * the multiplier below has to be 8 and value should be long. */ + vp = value_at (builtin_type_int, + coreptr + 4 * (HP_ACC_VFUNC_START + class_index), NULL); + /* Indirect once more, offset by function index */ + /* pai: FIXME 32x64 problem here, again multiplier could be 8 and value long */ + coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp) + 4 * TYPE_FN_FIELD_VOFFSET (f, j)); + vp = value_at (builtin_type_int, coreptr, NULL); + coreptr = * (CORE_ADDR *) (VALUE_CONTENTS (vp)); + + /* coreptr now contains the address of the virtual function */ + /* (Actually, it contains the pointer to the plabel for the function.) */ + + } + + if (!coreptr) + error ("Address of virtual function is null; error in virtual table?"); + + /* Wrap this addr in a value and return pointer */ + vp = allocate_value (ftype); + VALUE_TYPE (vp) = ftype; + VALUE_ADDRESS (vp) = coreptr; + + /* pai: (temp) do we need the value_ind stuff in value_fn_field? */ + return vp; } - else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR) - vfn = entry; - else - error ("I'm confused: virtual function table has bad type"); - /* Reinstantiate the function pointer with the correct type. */ - VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); + else + { /* Not using HP/Taligent runtime conventions; so try to + * use g++ conventions for virtual table */ + + struct type *entry_type; + /* First, get the virtual function table pointer. That comes + with a strange type, so cast it to type `pointer to long' (which + should serve just fine as a function type). Then, index into + the table, and convert final value to appropriate function type. */ + value_ptr entry, vfn, vtbl; + value_ptr vi = value_from_longest (builtin_type_int, + (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); + struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j); + struct type *context; + if (fcontext == NULL) + /* We don't have an fcontext (e.g. the program was compiled with + g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE. + This won't work right for multiple inheritance, but at least we + should do as well as GDB 3.x did. */ + fcontext = TYPE_VPTR_BASETYPE (type); + context = lookup_pointer_type (fcontext); + /* Now context is a pointer to the basetype containing the vtbl. */ + if (TYPE_TARGET_TYPE (context) != type1) + { + arg1 = value_ind (value_cast (context, value_addr (arg1))); + type1 = check_typedef (VALUE_TYPE (arg1)); + } + + context = type1; + /* Now context is the basetype containing the vtbl. */ + + /* This type may have been defined before its virtual function table + was. If so, fill in the virtual function table entry for the + type now. */ + if (TYPE_VPTR_FIELDNO (context) < 0) + fill_in_vptr_fieldno (context); + + /* The virtual function table is now an array of structures + which have the form { int16 offset, delta; void *pfn; }. */ + vtbl = value_ind (value_primitive_field (arg1, 0, + TYPE_VPTR_FIELDNO (context), + TYPE_VPTR_BASETYPE (context))); + + /* Index into the virtual function table. This is hard-coded because + looking up a field is not cheap, and it may be important to save + time, e.g. if the user has set a conditional breakpoint calling + a virtual function. */ + entry = value_subscript (vtbl, vi); + entry_type = check_typedef (VALUE_TYPE (entry)); + + if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT) + { + /* Move the `this' pointer according to the virtual function table. */ + VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)); + + if (! VALUE_LAZY (arg1)) + { + VALUE_LAZY (arg1) = 1; + value_fetch_lazy (arg1); + } + + vfn = value_field (entry, 2); + } + else if (TYPE_CODE (entry_type) == TYPE_CODE_PTR) + vfn = entry; + else + error ("I'm confused: virtual function table has bad type"); + /* Reinstantiate the function pointer with the correct type. */ + VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); - *arg1p = arg1; - return vfn; + *arg1p = arg1; + return vfn; + } } /* ARG is a pointer to an object we know to be at least |