]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2008-11-20 Stan Shebs <stan@codesourcery.com>
authorStan Shebs <shebs@codesourcery.com>
Fri, 21 Nov 2008 02:31:59 +0000 (02:31 +0000)
committerStan Shebs <shebs@codesourcery.com>
Fri, 21 Nov 2008 02:31:59 +0000 (02:31 +0000)
Multi-process (primarily multi-exec) support.

2008-10-14  Stan Shebs  <stan@codesourcery.com>

* blockframe.c (get_frame_block): Get inferior from frame.
* block.c (block_for_pc_inf): New function.
* block.h (block_for_pc_inf): Declare.
* symfile.c (find_pc_inf_sect): New function.
* symfile.h (find_pc_inf_sect): Declare.
* symtab.c (find_pc_inf_line): New function.
* symtab.h (find_pc_inf_line): Declare.
* frame.c (struct frame_info) New field inferior.
(fprint_frame_id): Display inferior.
(get_frame_id): Set inferior_num from inferior.
(frame_id_eq): Compare inferiors.
(create_sentinel_frame): Set inferior.
(create_new_frame): Copy inferior from sentinel.
(get_prev_frame_raw): Copy inferior from next frame.
(find_frame_sal): Use find_pc_inf_line.
(get_frame_inferior): New function.
* frame.h (struct frame_id): New field inferior_num.

* breakpoint.c (expand_sals_by_inferiors): Copy section from input
sal to expanded sals.
* symtab.c (expand_line_sal): Ditto.

2008-10-10  Stan Shebs  <stan@codesourcery.com>

* remote.c (discard_pending_stop_replies): Initialize prev.
* infrun.c (infrun_thread_stop_requested): Ditto.

2008-10-08  Stan Shebs  <stan@codesourcery.com>

* inferior.h (struct inferior): Rename environ field to inf_environ.
* inferior.c (print_inferior): Ditto.

2008-10-01  Stan Shebs  <stan@codesourcery.com>

* inferior.h (detach_fork): Declare here...
* linux-fork.h (detach_fork): ...instead of here.
* linux-fork.c (detach_fork): Move to...
* infrun.c (detach_fork): ...here.
* remote.c (detach_fork): Remove decl.

2008-09-30  Stan Shebs  <stan@codesourcery.com>

* linespec.c (decode_line_1): Better default for one-exec case.
* remote (remote_start_remote): Use the exec in the one-exec case.

2008-09-29  Stan Shebs  <stan@codesourcery.com>

* infcmd.c (attach_command): If only one exec, assume it is the
attached inferior's exec.
(attach_command_post_wait): Set inferior's exec from
the one that was found.
* inf-ptrace.c (inf_ptrace_attach): Only report exec file if
if there is just one present.
(inf_ptrace_detach): Use inferior to get correct exec name.

2008-09-29  Stan Shebs  <stan@codesourcery.com>

* inferior.c (print_inferior): Use exec short names, and drop
unused address space display.

2008-09-26  Stan Shebs  <stan@codesourcery.com>

* breakpoint.c (should_be_inserted): Test for no inferior.
(clone_breakpoint_location): New function, broken out from...
(update_breakpoint_inferiors): ...here, also tweak conditions
for adding a location.
(insert_breakpoint_location): Don't count non-running inferiors.
(remove_breakpoint): Set tmp_inf.
(print_one_breakpoint_location): Add allflag arg, use to always
show inf.
(print_one_breakpoint): Add allflag arg.
(do_captured_breakpoint_query): Fix caller.
(breakpoint_1): Ditto.
* exec.c (create_exec): Save full pathname as exec name.
(find_exec_by_name): Use find_exec_by_substr.
* fork-child.c (fork_inferior): Warn if exec not found for new
inferior.

2008-09-25  Stan Shebs  <stan@codesourcery.com>

* breakpoint.c (should_be_inserted): Don't insert in inferiors
that are not running.
(update_breakpoint_inferiors): New function.
(insert_breakpoints): Call it.
(insert_breakpoint_locations): Don't insert in inferiors that are
not running.
(set_raw_breakpoint_without_location): Set trigger set from
current itset here...
(set_raw_breakpoint): Instead of here. Also add default fillins
for the location's inferior.
(add_location_to_breakpoint): Similarly.
(expand_sals_by_inferiors): New function.
(breakpoint_re_set_one): Call it.
(resolve_sal_pc): Don't set sal inferior.
* breakpoint.h (struct breakpoint): Remove exec field, never used.
* inferior.h (inferior_list): Declare.
* inferior.c (inferior_list): Make public.
(add_inferior_to_itset): Auto-add inferiors after exec's inferior.
(first_inferior_in_set): Check for zero-length vector.
* exec.c (xfer_memory): Use tmp_inf as inferior if set.
* infcmd.c (focus_command): Improve user feedback.
* linespec.c (build_canonical_line_spec): Record exec name as part
of canonical spec.
(symbol_found): Canonicalize specs more.
(decode_indirect): Revert rewrite from 2008-09-14.
(decode_sharp): Use find_exec_by_substr, better error messages.
* minsyms.c (lookup_minimal_symbol_in_exec): New function.
(lookup_minimal_symbol_in_exec_1): New function, body of
lookup_minimal_symbol.
* symtab.h (lookup_minimal_symbol_in_exec): Declare.
* symtab.c (find_function_start_sal): Set inferior to use.
(append_expanded_sal): Return pointer to the new sal.
* remote.c (remote_xfer_memory): Better parms to ptid_build, remove
debug print.
(remote_xfer_partial): Ditto.

2008-09-22  Pedro Alves  <pedro@codesourcery.com>

* inferior.c (itset_member): Fix typo.

2008-09-22  Stan Shebs  <stan@codesourcery.com>

* inferior.h (current_inf): Remove declaration.
(tmp_inf): Declare.
* inferior.c (current_inf): Remove.
(tmp_inf): New global, hack to bypass passing inferior throughout
target stack.
(print_inferior): Don't report current_inf.
(add_inferior_command): Don't use current_inf.
(name_inferior_command): Use first inferior of current_itset.
(update_itset): Handle NULL case.
(add_inferior_itset): Recursively add all inferiors derived from
an exec if the exec's own inferior is present.
(first_inferior_in_set): New function.
(free_inferior): Comment out until references cleared reliably.
* infcmd.c (focus_command): Don't set current_inf.
(get_inferior_args): Use first_inferior_in_set instead of
current_inf.
(set_inferior_args): Ditto.
(set_inferior_args_vector): Ditto.
(notice_args_set): Ditto.
* breakpoint.c (insert_breakpoint_locations): Remove insertion test
using current_inf, set tmp_inf.
(reattach_breakpoints): Set tmp_inf.
(bpstat_check_breakpoint_conditions): Test trigger set here...
(bpstat_stop_status): ... instead of here.
(bpstat_check_trigger_set): Add special case for exec's own
inferior.
(print_one_breakpoint_location): Also test for multiple inferiors
before displaying location's inferior, flag trigger set with "i/t"
instead of "focus".
(check_duplicates): Pass location's inferior to...
(check_duplicates_for): Add inferior arg and use.
(set_raw_breakpoint): Override sal inferior with one from the
trigger set.
(add_location_to_breakpoint): Ditto.
* remote.c (remote_xfer_memory): Switch inferiors if tmp_inf is
set to something different from inferior_ptid.
(remote_xfer_partial): Ditto.
* top.c (execute_command): Always update the current itset.

2008-09-19  Stan Shebs  <stan@codesourcery.com>

* inferior.c (set_inferior_exec): New function.
(set_inferior_exec_command): New command.
* inferior.h: Declare set_inferior_exec.
* fork-child.c (fork_inferior): Set the inferior's exec.
* remote.c (extended_remote_create_inferior_1): Ditto.
gdb/doc/
* gdb.texinfo (Debugging Multiple Programs): Describe set-exec.

2008-09-18  Stan Shebs  <stan@codesourcery.com>

* target.c (target_resize_to_sections): Adjust execs' section
tables too.

2008-09-17  Stan Shebs  <stan@codesourcery.com>

gdb/doc/
* gdb.texinfo (Invoking GDB): Describe multiple program args.
(File Options): Describe multi-program effects.
(Multiple Programs): New section, multi-program debugging.
(Forks): Rename section from "Processes".
(Specify Location): Describe the #-syntax.
(Variables): Describe the #-syntax.
(Files): Describe add-file and add-exec-file.
(Maintenance Commands): Describe maint print execs.

2008-09-15  Stan Shebs  <stan@codesourcery.com>

* exec.c (addr_space_info_command): Don't try to display host address.

2008-09-14  Stan Shebs  <stan@codesourcery.com>

* c-exp.y: (yylex): Accept '#' in identifiers.
* linespec.c (decode_sharp): New function.
(decode_line_1): Use it for #-syntax.
(decode_indirect): Rewrite to accept exec arg and iterate over
inferiors.
(struct d_i_data): New struct for inferior iteration.
(decode_indirect_callback): New function.
(decode_variable): Pass in exec, use in symbol lookup.

2008-09-14  Stan Shebs  <stan@codesourcery.com>

* breakpoint.h (struct bp_location): Add inferior field instead
of address space field.
* breakpoint.c (insert_breakpoint_locations): Only insert in
appropriate inferior.
(bpstat_check_trigger_set): New function.
(bpstat_stop_status): Call it, check location's inferior also.
(print_one_breakpoint_location): Report location's inferior.
(set_raw_breakpoint): Set location inferior, clear an experiment.
(add_location_to_breakpoint): Ditto.
(expand_line_sal_maybe): Check for non-NULL original function.
(resolve_sal_pc): Set sal inferior.
(clear_command): Be careful to not clear anything twice.
* symtab.h: Update declarations of symbol lookups.
(struct symtab_and_line): Change address space to inferior field.
* symtab.c (init_sal): Clear inferior field.
(append_expanded_sal): Set inferior.
(lookup_symbol_in_language_1): New function.
(lookup_symbol_in_language): Call it.
(lookup_symbol_in_exec_in_language): New function.
(lookup_symbol): Detect #-syntax and find exec to use.
(lookup_symbol_aux): Add exec argument and use it.
(lookup_symbol_aux_symtabs): Ditto.
(lookup_symbol_aux_psymtabs): Ditto.
(basic_lookup_symbol_nonlocal): Ditto.
(lookup_symbol_static): Ditto.
(lookup_symbol_global): Ditto.
* ada-lang.c (cp_lookup_symbol_nonlocal): Ditto.
* cp-support.h (cp_lookup_symbol_nonlocal): Ditto.
* cp-namespace.c (cp_lookup_symbol_nonlocal): Ditto.
* language.h (struct language_defn): Ditto.
* scm-valprint.c (scm_inferior_print): Add exec arg to
lookup_symbol_global.
* source.c (select_source_symtab): Use current_exec.
* addrspace.h (struct addr_space): New field num.
* exec.h (struct exec): New fields sections and sections_end.
* exec.c (exec_file_attach_1): Set them from exec_ops, set
inferior's address space name from exec.
(find_exec_by_substr): New function.
(build_section_table): Don't free old table.
(print_section_info): Use exec's section table.
(next_address_space_num): New global, numbering for address spaces.
(new_address_space): Use it.
(addr_space_info_command): Display it.
* infcmd.c (set_current_exec): Set exec_ops section table.
* inferior.h (update_itset): Declare.
* inferior.c (add_inferior_silent): Set address space.
(print_inferior): Display it.
(number_of_inferiors): New function.
(itset_member): New function.

2008-09-04  Stan Shebs  <stan@codesourcery.com>

* corefile.c (close_exec_file): Remove #if 0 block.
(validate_files): Use first_exec instead of exec_bfd.
(get_exec_file): Ditto.
* corelow.c (core_open): Ditto.
* utils.c (string_to_core_addr): Ditto.
* arch-utils.c (gdbarch_update_p): Ditto.
* linux-thread-db.c (enable_thread_event): Ditto.
(thread_db_get_thread_local_address ): Ditto.
* exec.c (find_exec_by_name): Test short name also.
(file_command): Set current exec.

2008-09-03  Stan Shebs  <stan@codesourcery.com>

* inferior.c (add_threads_to_itset): Default to including all
of an inferior's threads.

2008-08-31  Stan Shebs  <stan@codesourcery.com>

Parsing for i/t sets.
* inferior.h (struct itset_entry): New struct.
(struct itset): Make thread lists be per-inferior, add parse state
variables.
* inferior.c: (add_inferior_command): Add error checking and
confirmation.
(remove_inferior_command): Update for itset restructuring.
(new_itset): Don't pass in dynamic-ness, call parse_itset_spec.
(update_itset): Similarly.
(parse_itset_spec): New, parsing of itset spec.
(parse_itset_list, parse_itset_range, etc): New.
(make_itset_from_spec): Rewrite.
(dump_itset): Rewrite to reflect itset structure.
* infcmd.c (focus_command): Similarly.

2008-08-25  Stan Shebs  <stan@codesourcery.com>

First part of multiprocess support.
* Makefile.in (COMMON_OBS): Add inferior.o.
* addrspace.h: New file.
* breakpoints.h (struct bp_location): Add address space field.
(struct breakpoint): Add trigger set and exec fields.
* breakpoints.c (print_one_breakpoint_location): Display trigger
set.
(set_raw_breakpoint): Set trigger set from current itset.
* corefile.c (reopen_exec_file): Rewrite for multiple execs.
(get_exec_file): Add case for current_exec.
* corelow.c (is_core_file): New function.
(core_files_info): Pass additional arg to print_section_info.
* exec.h (struct exec): New struct.
* exec.c (execs): New global.
(exec_bfd_mtime): Remove.
(last_exec_created, current_exec, first_exec): New globals.
(exec_close): Clear all exec objects.
(exec_file_clear): Tweak user message.
(exec_file_add): New function.
(exec_file_attach_1): New function, body of exec_file_attach,
plus new code to handle multiple execs.
(exec_file_attach): Call it.
(exec_file_update): New function.
(create_exec, find_exec_by_name, number_of_execs): New functions.
(exec_file_command): Rephrase query, set current exec.
(add_exec_file_command): New command.
(add_file_command): New command.
(print_section_info): Add exec argument.
(exec_files_info): Rewrite for multiple execs.
(maintenance_print_execs): New function.
(new_address_space): New function.
(addr_space_info_command): New command.
* gdbcore.h (exec_bfd_mtime): Remove decl.
(exec_file_add): Declare.
* infcmd.c: Include exec.h.
(current_itset): New global.
(set_current_exec): New function.
(focus_command): New command.
(get_inferior_args): Maybe get from the current inferior.
(set_inferior_args): Also set in current inferior.
(set_inferior_args_vector): Similarly.
(notice_args_set): Similarly.
(attach_command): Rephrase query.
* inferior.h (struct inferior): New struct.
(struct itset): New struct.
* inferior.c: New file, management of multiple inferiors.
* main.c (captured_main): Rewrite to allow multiple executables,
pids, and corefiles on the command line.
* maint.c (maintenance_info_sections): Rewrite for multiple execs.
* objfiles.h (struct objfile): New field for exec.
(ALL_OBJFILES_FOR_EXEC, ALL_PRIMARY_SYMTABS_FOR_EXEC,
ALL_PSYMTABS_FOR_EXEC): New macros.
* objfiles.c (allocate_objfile): Clear exec field.
* solib.c (clear_solib): Use first_exec instead of exec_bfd.
* source.c (select_source_symtab): Use ALL_OBJFILES_FOR_EXEC.
(find_source_lines): Use mtime from exec.
* symfile.c (syms_from_objfile): Don't clear objfile if multiple
execs.
(new_symfile_objfile): Get objfile's exec from last_exec_created.
(symbol_file_clear): Rephrase messages.
(reread_symbols): Update objfile's exec if necessary.
* symmisc.c (dump_objfile): Dump objfile's exec also.
(maintenance_print_objfiles): Report symfile_objfile.
* symtab.h (struct symtab_and_line): Add address space field.
* symtab.c (find_pc_sect_psymtab): Look for a plausible exec, and
then use it.
(lookup_symbol_aux_symtabs): Use current exec.
(lookup_symbol_aux_symtabs): Ditto.
(basic_lookup_transparent_type): Ditto.
(find_pc_sect_symtab): Ditto.
* target.h (print_section_info): Add arg to decl.
* tui/tui-win.c: Rename "focus" command to "ffocus".

gdb/testsuite:

2008-11-20  Stan Shebs  <stan@codesourcery.com>

2008-09-14  Stan Shebs  <stan@codesourcery.com>

* gdb.gdb/selftest.exp: Update to reflect current sources.
* Makefile.in (ALL_SUBDIRS): Add gdb.multi.
* configure.ac (AC_OUTPUT): Add gdb.multi/Makefile.
* configure: Regenerate.

* gdb.multi/Makefile.in: New.
* gdb.multi/hello.c, hangout.c, goodbye.c: New source files.
* gdb.multi/base.exp: New file, basic multiprocess tests.

2008-08-25  Stan Shebs  <stan@codesourcery.com>

* config/monitor.exp: Match on rephrased message.
* gdb.base/attach.exp: Ditto.
* gdb.base/default.exp: Ditto.
* lib/gdb.exp: Ditto.

60 files changed:
gdb/ChangeLog
gdb/ada-lang.c
gdb/arch-utils.c
gdb/block.c
gdb/block.h
gdb/blockframe.c
gdb/breakpoint.c
gdb/breakpoint.h
gdb/c-exp.y
gdb/corefile.c
gdb/corelow.c
gdb/cp-namespace.c
gdb/cp-support.h
gdb/doc/gdb.texinfo
gdb/exec.c
gdb/exec.h
gdb/fork-child.c
gdb/frame.c
gdb/frame.h
gdb/gdbcore.h
gdb/inf-ptrace.c
gdb/infcmd.c
gdb/inferior.c
gdb/inferior.h
gdb/infrun.c
gdb/language.h
gdb/linespec.c
gdb/linux-fork.c
gdb/linux-fork.h
gdb/linux-nat.c
gdb/linux-thread-db.c
gdb/main.c
gdb/maint.c
gdb/minsyms.c
gdb/objfiles.c
gdb/objfiles.h
gdb/remote.c
gdb/scm-valprint.c
gdb/solib.c
gdb/source.c
gdb/symfile.c
gdb/symfile.h
gdb/symmisc.c
gdb/symtab.c
gdb/symtab.h
gdb/target.c
gdb/target.h
gdb/testsuite/ChangeLog
gdb/testsuite/Makefile.in
gdb/testsuite/config/monitor.exp
gdb/testsuite/configure
gdb/testsuite/configure.ac
gdb/testsuite/gdb.base/attach.exp
gdb/testsuite/gdb.base/checkpoint.exp
gdb/testsuite/gdb.base/default.exp
gdb/testsuite/gdb.gdb/selftest.exp
gdb/testsuite/lib/gdb.exp
gdb/top.c
gdb/tui/tui-win.c
gdb/utils.c

index 4eabe76f4470331787b5a5a2e041295315f6414f..35d6390f5e6fff5dd1bbc4b8aa65bdbc170eb9d7 100644 (file)
@@ -1,3 +1,374 @@
+2008-11-20  Stan Shebs  <stan@codesourcery.com>
+
+       Multi-process (primarily multi-exec) support.
+
+       2008-10-14  Stan Shebs  <stan@codesourcery.com>
+
+       * blockframe.c (get_frame_block): Get inferior from frame.
+       * block.c (block_for_pc_inf): New function.
+       * block.h (block_for_pc_inf): Declare.
+       * symfile.c (find_pc_inf_sect): New function.
+       * symfile.h (find_pc_inf_sect): Declare.
+       * symtab.c (find_pc_inf_line): New function.
+       * symtab.h (find_pc_inf_line): Declare.
+       * frame.c (struct frame_info) New field inferior.
+       (fprint_frame_id): Display inferior.
+       (get_frame_id): Set inferior_num from inferior.
+       (frame_id_eq): Compare inferiors.
+       (create_sentinel_frame): Set inferior.
+       (create_new_frame): Copy inferior from sentinel.
+       (get_prev_frame_raw): Copy inferior from next frame.
+       (find_frame_sal): Use find_pc_inf_line.
+       (get_frame_inferior): New function.
+       * frame.h (struct frame_id): New field inferior_num.
+
+       * breakpoint.c (expand_sals_by_inferiors): Copy section from input
+       sal to expanded sals.
+       * symtab.c (expand_line_sal): Ditto.
+
+       2008-10-10  Stan Shebs  <stan@codesourcery.com>
+
+       * remote.c (discard_pending_stop_replies): Initialize prev.
+       * infrun.c (infrun_thread_stop_requested): Ditto.
+
+       2008-10-08  Stan Shebs  <stan@codesourcery.com>
+
+       * inferior.h (struct inferior): Rename environ field to inf_environ.
+       * inferior.c (print_inferior): Ditto.
+
+       2008-10-01  Stan Shebs  <stan@codesourcery.com>
+
+       * inferior.h (detach_fork): Declare here...
+       * linux-fork.h (detach_fork): ...instead of here.
+       * linux-fork.c (detach_fork): Move to...
+       * infrun.c (detach_fork): ...here.
+       * remote.c (detach_fork): Remove decl.
+
+       2008-09-30  Stan Shebs  <stan@codesourcery.com>
+
+       * linespec.c (decode_line_1): Better default for one-exec case.
+       * remote (remote_start_remote): Use the exec in the one-exec case.
+
+       2008-09-29  Stan Shebs  <stan@codesourcery.com>
+
+       * infcmd.c (attach_command): If only one exec, assume it is the
+       attached inferior's exec.
+       (attach_command_post_wait): Set inferior's exec from
+       the one that was found.
+       * inf-ptrace.c (inf_ptrace_attach): Only report exec file if
+       if there is just one present.
+       (inf_ptrace_detach): Use inferior to get correct exec name.
+
+       2008-09-29  Stan Shebs  <stan@codesourcery.com>
+
+       * inferior.c (print_inferior): Use exec short names, and drop
+       unused address space display.
+
+       2008-09-26  Stan Shebs  <stan@codesourcery.com>
+
+       * breakpoint.c (should_be_inserted): Test for no inferior.
+       (clone_breakpoint_location): New function, broken out from...
+       (update_breakpoint_inferiors): ...here, also tweak conditions
+       for adding a location.
+       (insert_breakpoint_location): Don't count non-running inferiors.
+       (remove_breakpoint): Set tmp_inf.
+       (print_one_breakpoint_location): Add allflag arg, use to always
+       show inf.
+       (print_one_breakpoint): Add allflag arg.
+       (do_captured_breakpoint_query): Fix caller.
+       (breakpoint_1): Ditto.
+       * exec.c (create_exec): Save full pathname as exec name.
+       (find_exec_by_name): Use find_exec_by_substr.
+       * fork-child.c (fork_inferior): Warn if exec not found for new
+       inferior.
+
+       2008-09-25  Stan Shebs  <stan@codesourcery.com>
+
+       * breakpoint.c (should_be_inserted): Don't insert in inferiors
+       that are not running.
+       (update_breakpoint_inferiors): New function.
+       (insert_breakpoints): Call it.
+       (insert_breakpoint_locations): Don't insert in inferiors that are
+       not running.
+       (set_raw_breakpoint_without_location): Set trigger set from
+       current itset here...
+       (set_raw_breakpoint): Instead of here. Also add default fillins
+       for the location's inferior.
+       (add_location_to_breakpoint): Similarly.
+       (expand_sals_by_inferiors): New function.
+       (breakpoint_re_set_one): Call it.
+       (resolve_sal_pc): Don't set sal inferior.
+       * breakpoint.h (struct breakpoint): Remove exec field, never used.
+       * inferior.h (inferior_list): Declare.
+       * inferior.c (inferior_list): Make public.
+       (add_inferior_to_itset): Auto-add inferiors after exec's inferior.
+       (first_inferior_in_set): Check for zero-length vector.
+       * exec.c (xfer_memory): Use tmp_inf as inferior if set.
+       * infcmd.c (focus_command): Improve user feedback.
+       * linespec.c (build_canonical_line_spec): Record exec name as part
+       of canonical spec.
+       (symbol_found): Canonicalize specs more.
+       (decode_indirect): Revert rewrite from 2008-09-14.
+       (decode_sharp): Use find_exec_by_substr, better error messages.
+       * minsyms.c (lookup_minimal_symbol_in_exec): New function.
+       (lookup_minimal_symbol_in_exec_1): New function, body of
+       lookup_minimal_symbol.
+       * symtab.h (lookup_minimal_symbol_in_exec): Declare.
+       * symtab.c (find_function_start_sal): Set inferior to use.
+       (append_expanded_sal): Return pointer to the new sal.
+       * remote.c (remote_xfer_memory): Better parms to ptid_build, remove
+       debug print.
+       (remote_xfer_partial): Ditto.
+       
+       2008-09-22  Pedro Alves  <pedro@codesourcery.com>
+
+       * inferior.c (itset_member): Fix typo.
+
+       2008-09-22  Stan Shebs  <stan@codesourcery.com>
+
+       * inferior.h (current_inf): Remove declaration.
+       (tmp_inf): Declare.
+       * inferior.c (current_inf): Remove.
+       (tmp_inf): New global, hack to bypass passing inferior throughout
+       target stack.
+       (print_inferior): Don't report current_inf.
+       (add_inferior_command): Don't use current_inf.
+       (name_inferior_command): Use first inferior of current_itset.
+       (update_itset): Handle NULL case.
+       (add_inferior_itset): Recursively add all inferiors derived from
+       an exec if the exec's own inferior is present.
+       (first_inferior_in_set): New function.
+       (free_inferior): Comment out until references cleared reliably.
+       * infcmd.c (focus_command): Don't set current_inf.
+       (get_inferior_args): Use first_inferior_in_set instead of
+       current_inf.
+       (set_inferior_args): Ditto.
+       (set_inferior_args_vector): Ditto.
+       (notice_args_set): Ditto.
+       * breakpoint.c (insert_breakpoint_locations): Remove insertion test
+       using current_inf, set tmp_inf.
+       (reattach_breakpoints): Set tmp_inf.
+       (bpstat_check_breakpoint_conditions): Test trigger set here...
+       (bpstat_stop_status): ... instead of here.
+       (bpstat_check_trigger_set): Add special case for exec's own
+       inferior.
+       (print_one_breakpoint_location): Also test for multiple inferiors
+       before displaying location's inferior, flag trigger set with "i/t"
+       instead of "focus".
+       (check_duplicates): Pass location's inferior to...
+       (check_duplicates_for): Add inferior arg and use.
+       (set_raw_breakpoint): Override sal inferior with one from the
+       trigger set.
+       (add_location_to_breakpoint): Ditto.
+       * remote.c (remote_xfer_memory): Switch inferiors if tmp_inf is
+       set to something different from inferior_ptid.
+       (remote_xfer_partial): Ditto.
+       * top.c (execute_command): Always update the current itset.
+
+       2008-09-19  Stan Shebs  <stan@codesourcery.com>
+
+       * inferior.c (set_inferior_exec): New function.
+       (set_inferior_exec_command): New command.
+       * inferior.h: Declare set_inferior_exec.
+       * fork-child.c (fork_inferior): Set the inferior's exec.
+       * remote.c (extended_remote_create_inferior_1): Ditto.
+       gdb/doc/
+       * gdb.texinfo (Debugging Multiple Programs): Describe set-exec.
+
+       2008-09-18  Stan Shebs  <stan@codesourcery.com>
+
+       * target.c (target_resize_to_sections): Adjust execs' section
+       tables too.
+       
+       2008-09-17  Stan Shebs  <stan@codesourcery.com>
+
+       gdb/doc/
+       * gdb.texinfo (Invoking GDB): Describe multiple program args.
+       (File Options): Describe multi-program effects.
+       (Multiple Programs): New section, multi-program debugging.
+       (Forks): Rename section from "Processes".
+       (Specify Location): Describe the #-syntax.
+       (Variables): Describe the #-syntax.
+       (Files): Describe add-file and add-exec-file.
+       (Maintenance Commands): Describe maint print execs.
+
+       2008-09-15  Stan Shebs  <stan@codesourcery.com>
+
+       * exec.c (addr_space_info_command): Don't try to display host address.
+
+       2008-09-14  Stan Shebs  <stan@codesourcery.com>
+
+       * c-exp.y: (yylex): Accept '#' in identifiers.
+       * linespec.c (decode_sharp): New function.
+       (decode_line_1): Use it for #-syntax.
+       (decode_indirect): Rewrite to accept exec arg and iterate over
+       inferiors.
+       (struct d_i_data): New struct for inferior iteration.
+       (decode_indirect_callback): New function.
+       (decode_variable): Pass in exec, use in symbol lookup.
+
+       2008-09-14  Stan Shebs  <stan@codesourcery.com>
+
+       * breakpoint.h (struct bp_location): Add inferior field instead
+       of address space field.
+       * breakpoint.c (insert_breakpoint_locations): Only insert in
+       appropriate inferior.
+       (bpstat_check_trigger_set): New function.
+       (bpstat_stop_status): Call it, check location's inferior also.
+       (print_one_breakpoint_location): Report location's inferior.
+       (set_raw_breakpoint): Set location inferior, clear an experiment.
+       (add_location_to_breakpoint): Ditto.
+       (expand_line_sal_maybe): Check for non-NULL original function.
+       (resolve_sal_pc): Set sal inferior.
+       (clear_command): Be careful to not clear anything twice.
+       * symtab.h: Update declarations of symbol lookups.
+       (struct symtab_and_line): Change address space to inferior field.
+       * symtab.c (init_sal): Clear inferior field.
+       (append_expanded_sal): Set inferior.
+       (lookup_symbol_in_language_1): New function.
+       (lookup_symbol_in_language): Call it.
+       (lookup_symbol_in_exec_in_language): New function.
+       (lookup_symbol): Detect #-syntax and find exec to use.
+       (lookup_symbol_aux): Add exec argument and use it.
+       (lookup_symbol_aux_symtabs): Ditto.
+       (lookup_symbol_aux_psymtabs): Ditto.
+       (basic_lookup_symbol_nonlocal): Ditto.
+       (lookup_symbol_static): Ditto.
+       (lookup_symbol_global): Ditto.
+       * ada-lang.c (cp_lookup_symbol_nonlocal): Ditto.
+       * cp-support.h (cp_lookup_symbol_nonlocal): Ditto.
+       * cp-namespace.c (cp_lookup_symbol_nonlocal): Ditto.
+       * language.h (struct language_defn): Ditto.
+       * scm-valprint.c (scm_inferior_print): Add exec arg to
+       lookup_symbol_global.
+       * source.c (select_source_symtab): Use current_exec.
+       * addrspace.h (struct addr_space): New field num.
+       * exec.h (struct exec): New fields sections and sections_end.
+       * exec.c (exec_file_attach_1): Set them from exec_ops, set
+       inferior's address space name from exec.
+       (find_exec_by_substr): New function.
+       (build_section_table): Don't free old table.
+       (print_section_info): Use exec's section table.
+       (next_address_space_num): New global, numbering for address spaces.
+       (new_address_space): Use it.
+       (addr_space_info_command): Display it.
+       * infcmd.c (set_current_exec): Set exec_ops section table.
+       * inferior.h (update_itset): Declare.
+       * inferior.c (add_inferior_silent): Set address space.
+       (print_inferior): Display it.
+       (number_of_inferiors): New function.
+       (itset_member): New function.
+
+       2008-09-04  Stan Shebs  <stan@codesourcery.com>
+
+       * corefile.c (close_exec_file): Remove #if 0 block.
+       (validate_files): Use first_exec instead of exec_bfd.
+       (get_exec_file): Ditto.
+       * corelow.c (core_open): Ditto.
+       * utils.c (string_to_core_addr): Ditto.
+       * arch-utils.c (gdbarch_update_p): Ditto.
+       * linux-thread-db.c (enable_thread_event): Ditto.
+       (thread_db_get_thread_local_address ): Ditto.
+       * exec.c (find_exec_by_name): Test short name also.
+       (file_command): Set current exec.
+
+       2008-09-03  Stan Shebs  <stan@codesourcery.com>
+
+       * inferior.c (add_threads_to_itset): Default to including all
+       of an inferior's threads.
+
+       2008-08-31  Stan Shebs  <stan@codesourcery.com>
+
+       Parsing for i/t sets.
+       * inferior.h (struct itset_entry): New struct.
+       (struct itset): Make thread lists be per-inferior, add parse state
+       variables.
+       * inferior.c: (add_inferior_command): Add error checking and
+       confirmation.
+       (remove_inferior_command): Update for itset restructuring.
+       (new_itset): Don't pass in dynamic-ness, call parse_itset_spec.
+       (update_itset): Similarly.
+       (parse_itset_spec): New, parsing of itset spec.
+       (parse_itset_list, parse_itset_range, etc): New.
+       (make_itset_from_spec): Rewrite.
+       (dump_itset): Rewrite to reflect itset structure.
+       * infcmd.c (focus_command): Similarly.
+
+       2008-08-25  Stan Shebs  <stan@codesourcery.com>
+
+       First part of multiprocess support.
+       * Makefile.in (COMMON_OBS): Add inferior.o.
+       * addrspace.h: New file.
+       * breakpoints.h (struct bp_location): Add address space field.
+       (struct breakpoint): Add trigger set and exec fields.
+       * breakpoints.c (print_one_breakpoint_location): Display trigger
+       set.
+       (set_raw_breakpoint): Set trigger set from current itset.
+       * corefile.c (reopen_exec_file): Rewrite for multiple execs.
+       (get_exec_file): Add case for current_exec.
+       * corelow.c (is_core_file): New function.
+       (core_files_info): Pass additional arg to print_section_info.
+       * exec.h (struct exec): New struct.
+       * exec.c (execs): New global.
+       (exec_bfd_mtime): Remove.
+       (last_exec_created, current_exec, first_exec): New globals.
+       (exec_close): Clear all exec objects.
+       (exec_file_clear): Tweak user message.
+       (exec_file_add): New function.
+       (exec_file_attach_1): New function, body of exec_file_attach,
+       plus new code to handle multiple execs.
+       (exec_file_attach): Call it.
+       (exec_file_update): New function.
+       (create_exec, find_exec_by_name, number_of_execs): New functions.
+       (exec_file_command): Rephrase query, set current exec.
+       (add_exec_file_command): New command.
+       (add_file_command): New command.
+       (print_section_info): Add exec argument.
+       (exec_files_info): Rewrite for multiple execs.
+       (maintenance_print_execs): New function.
+       (new_address_space): New function.
+       (addr_space_info_command): New command.
+       * gdbcore.h (exec_bfd_mtime): Remove decl.
+       (exec_file_add): Declare.
+       * infcmd.c: Include exec.h.
+       (current_itset): New global.
+       (set_current_exec): New function.
+       (focus_command): New command.
+       (get_inferior_args): Maybe get from the current inferior.
+       (set_inferior_args): Also set in current inferior.
+       (set_inferior_args_vector): Similarly.
+       (notice_args_set): Similarly.
+       (attach_command): Rephrase query.
+       * inferior.h (struct inferior): New struct.
+       (struct itset): New struct.
+       * inferior.c: New file, management of multiple inferiors.
+       * main.c (captured_main): Rewrite to allow multiple executables,
+       pids, and corefiles on the command line.
+       * maint.c (maintenance_info_sections): Rewrite for multiple execs.
+       * objfiles.h (struct objfile): New field for exec.
+       (ALL_OBJFILES_FOR_EXEC, ALL_PRIMARY_SYMTABS_FOR_EXEC,
+       ALL_PSYMTABS_FOR_EXEC): New macros.
+       * objfiles.c (allocate_objfile): Clear exec field.
+       * solib.c (clear_solib): Use first_exec instead of exec_bfd.
+       * source.c (select_source_symtab): Use ALL_OBJFILES_FOR_EXEC.
+       (find_source_lines): Use mtime from exec.
+       * symfile.c (syms_from_objfile): Don't clear objfile if multiple
+       execs.
+       (new_symfile_objfile): Get objfile's exec from last_exec_created.
+       (symbol_file_clear): Rephrase messages.
+       (reread_symbols): Update objfile's exec if necessary.
+       * symmisc.c (dump_objfile): Dump objfile's exec also.
+       (maintenance_print_objfiles): Report symfile_objfile.
+       * symtab.h (struct symtab_and_line): Add address space field.
+       * symtab.c (find_pc_sect_psymtab): Look for a plausible exec, and
+       then use it.
+       (lookup_symbol_aux_symtabs): Use current exec.
+       (lookup_symbol_aux_symtabs): Ditto.
+       (basic_lookup_transparent_type): Ditto.
+       (find_pc_sect_symtab): Ditto.
+       * target.h (print_section_info): Add arg to decl.
+       * tui/tui-win.c: Rename "focus" command to "ffocus".
+
 2008-11-19  Doug Evans  <dje@google.com>
 
        * inferior.h (proceed_to_finish): Delete, unused.
index 2ccba785e06c9591027824c4ce80d6bc24d9ceae..f92d23b935953f5d296a3e17a4e80d8a9e142526 100644 (file)
@@ -4871,6 +4871,7 @@ static struct symbol *
 ada_lookup_symbol_nonlocal (const char *name,
                             const char *linkage_name,
                             const struct block *block,
+                           const struct exec *exec,
                             const domain_enum domain)
 {
   if (linkage_name == NULL)
index 3014558e0313e72c74dc7f97152249da26ebedee..439c48b6d9d12fc0a887c72d8dd708943ce51ce7 100644 (file)
@@ -23,6 +23,7 @@
 #include "arch-utils.h"
 #include "buildsym.h"
 #include "gdbcmd.h"
+#include "exec.h"
 #include "inferior.h"          /* enum CALL_DUMMY_LOCATION et.al. */
 #include "gdb_string.h"
 #include "regcache.h"
@@ -469,8 +470,8 @@ gdbarch_update_p (struct gdbarch_info info)
   struct gdbarch *new_gdbarch;
 
   /* Check for the current file.  */
-  if (info.abfd == NULL)
-    info.abfd = exec_bfd;
+  if (info.abfd == NULL && first_exec && first_exec->ebfd)
+    info.abfd = first_exec->ebfd;
   if (info.abfd == NULL)
     info.abfd = core_bfd;
 
index 58dcf72f0662eadc3881c3723e8fc68bc9b6fef9..640beb61b0d79dcc8af59d2aa312c80f64f922b6 100644 (file)
@@ -149,6 +149,22 @@ blockvector_for_pc (CORE_ADDR pc, struct block **pblock)
                                  pblock, NULL);
 }
 
+/* Given a pc and an inferior, find the block.  */
+
+struct block *
+block_for_pc_inf (CORE_ADDR pc, struct inferior *inf)
+{
+  struct blockvector *bl;
+  struct block *b;
+  struct obj_section *section;
+
+  section = find_pc_inf_sect (pc, inf);
+  bl = blockvector_for_pc_sect (pc, section, &b, NULL);
+  if (bl)
+    return b;
+  return 0;
+}
+
 /* Return the innermost lexical block containing the specified pc value
    in the specified section, or 0 if there is none.  */
 
index af4d056b50a67367a558486167fc549da178ab96..9f81477670546526a3e2494d3366d950bea9fada 100644 (file)
@@ -29,6 +29,7 @@ struct using_direct;
 struct obstack;
 struct dictionary;
 struct addrmap;
+struct inferior;
 
 /* All of the name-scope contours of the program
    are represented by `struct block' objects.
@@ -147,6 +148,8 @@ extern struct block *block_for_pc (CORE_ADDR);
 
 extern struct block *block_for_pc_sect (CORE_ADDR, struct obj_section *);
 
+extern struct block *block_for_pc_inf (CORE_ADDR, struct inferior *);
+
 extern const char *block_scope (const struct block *block);
 
 extern void block_set_scope (struct block *block, const char *scope,
index 5e2020d4a0bd934e7d26ff390290955c55ae4257..ec98233b934237a1810f3de3bcc47e5aa525f286 100644 (file)
@@ -60,12 +60,13 @@ void _initialize_blockframe (void);
 struct block *
 get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
 {
+  struct inferior *inf = get_frame_inferior (frame);
   const CORE_ADDR pc = get_frame_address_in_block (frame);
 
   if (addr_in_block)
     *addr_in_block = pc;
 
-  return block_for_pc (pc);
+  return block_for_pc_inf (pc, inf);
 }
 
 CORE_ADDR
index 847dbdd7aca292bb74cb105b6b428b5e0bad377f..24fa293e312d70bfcf2317f8f5832f90bf3b61aa 100644 (file)
@@ -38,6 +38,7 @@
 #include "gdb_string.h"
 #include "demangle.h"
 #include "annotate.h"
+#include "exec.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "source.h"
 
 #include "mi/mi-common.h"
 
+static int
+bpstat_check_trigger_set (const struct bp_location *bl, struct inferior *inf,
+                         int thread_id);
+
 /* Arguments to pass as context to some catch command handlers.  */
 #define CATCH_PERMANENT ((void *) (uintptr_t) 0)
 #define CATCH_TEMPORARY ((void *) (uintptr_t) 1)
@@ -823,6 +828,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
   struct frame_id saved_frame_id;
   struct bp_location *loc;
   bpstat bs;
+  struct inferior *inf;
 
   /* We don't free locations.  They are stored in
      bp_location_chain and update_global_locations will
@@ -852,6 +858,8 @@ update_watchpoint (struct breakpoint *b, int reparse)
        select_frame (fi);
     }
 
+  inf = get_frame_inferior (get_selected_frame (NULL));
+
   if (within_current_scope && reparse)
     {
       char *s;
@@ -928,6 +936,7 @@ update_watchpoint (struct breakpoint *b, int reparse)
                  for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
                    ;
                  *tmp = loc;
+                 loc->inferior = inf;
                  loc->address = addr;
                  loc->length = len;
                  loc->watchpoint_type = type;
@@ -979,6 +988,9 @@ should_be_inserted (struct bp_location *bpt)
   if (!bpt->enabled || bpt->shlib_disabled || bpt->duplicate)
     return 0;
 
+  if (!bpt->inferior || (bpt->inferior && bpt->inferior->pid == 0))
+    return 0;
+
   return 1;
 }
 
@@ -1195,6 +1207,83 @@ Note: automatically using hardware breakpoints for read-only addresses.\n"));
   return 0;
 }
 
+/* Given a location, create and add another location differing only in
+   the inferior.  */
+
+void
+clone_breakpoint_location (struct breakpoint *b, struct bp_location *loc,
+                          struct inferior *inf)
+{
+  struct bp_location *new_loc, **tmp;
+  struct gdb_exception e;
+
+  new_loc = allocate_bp_location (b, b->type);
+  for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
+    ;
+  *tmp = new_loc;
+  new_loc->requested_address = loc->requested_address;
+  new_loc->address = loc->address;
+  new_loc->length = loc->length;
+  new_loc->inferior = inf;
+  if (b->cond_string)
+    {
+      char *s = b->cond_string;
+      TRY_CATCH (e, RETURN_MASK_ERROR)
+       {
+         new_loc->cond = parse_exp_1 (&s, block_for_pc_inf (new_loc->address,
+                                                            inf), 0);
+       }
+      if (e.reason < 0)
+       {
+       }
+    }
+  /* Permanent breakpoints will be inserted in every inferior created
+     from the same exec.  */
+  if (b->enable_state == bp_permanent)
+    new_loc->inserted = loc->inserted;
+}
+
+/* For the given breakpoint, look for any inferiors that might have
+   appeared and need a breakpoint location to be inserted.  */
+
+void
+update_breakpoint_inferiors (struct breakpoint *b)
+{
+  struct bp_location *loc, *loc2;
+  struct inferior *inf;
+
+  update_itset (b->trigger_set);
+
+  for (loc = b->loc; loc; loc = loc->next)
+    {
+      if (loc->inferior == NULL
+         || (loc->inferior
+             && loc->inferior->exec
+             && loc->inferior->exec->inferior == loc->inferior))
+       {
+         for (inf = inferior_list; inf; inf = inf->next)
+           {
+             if ((loc->inferior == NULL
+                  || inf->exec == loc->inferior->exec)
+                 && inf->pid != 0)
+               {
+                 int found = 0;
+                 for (loc2 = b->loc; loc2; loc2 = loc2->next)
+                   {
+                     if (inf == loc2->inferior)
+                       {
+                         found = 1;
+                         break;
+                       }
+                   }
+                 if (!found)
+                   clone_breakpoint_location (b, loc, inf);
+               }
+           }
+       }
+    }
+}
+
 /* Make sure all breakpoints are inserted in inferior.
    Throws exception on any error.
    A breakpoint that is already inserted won't be inserted
@@ -1205,8 +1294,12 @@ insert_breakpoints (void)
   struct breakpoint *bpt;
 
   ALL_BREAKPOINTS (bpt)
+  {
+    update_breakpoint_inferiors (bpt);
+
     if (is_hardware_watchpoint (bpt))
       update_watchpoint (bpt, 0 /* don't reparse. */);
+  }
 
   update_global_location_list (1);
 
@@ -1254,9 +1347,17 @@ insert_breakpoint_locations (void)
          && !valid_thread_id (b->owner->thread))
        continue;
 
+      /* Only insert into running inferiors.  */
+      if (!b->inferior || b->inferior->pid == 0)
+       continue;
+
+      /* Nasty hack to smuggle the location's inferior down to target bits.  */
+      tmp_inf = b->inferior;
       val = insert_bp_location (b, tmp_error_stream,
                                    &disabled_breaks, &process_warning,
                                    &hw_breakpoint_error);
+      tmp_inf = NULL;
+
       if (val)
        error = val;
     }
@@ -1278,7 +1379,9 @@ insert_breakpoint_locations (void)
        continue;
       
       for (loc = bpt->loc; loc; loc = loc->next)
-       if (!loc->inserted)
+       if (!loc->inserted
+           && !(loc->inferior == NULL
+                || (loc->inferior && loc->inferior->pid == 0)))
          {
            some_failed = 1;
            break;
@@ -1370,8 +1473,12 @@ reattach_breakpoints (int pid)
     if (b->inserted)
       {
        b->inserted = 0;
+       /* Nasty hack to smuggle the location's inferior down to
+          target bits.  */
+       tmp_inf = b->inferior;
        val = insert_bp_location (b, tmp_error_stream,
                                  &dummy1, &dummy2, &dummy3);
+       tmp_inf = NULL;
        if (val != 0)
          {
            do_cleanups (old_chain);
@@ -1527,6 +1634,9 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
      This should not ever happen.  */
   gdb_assert (b->owner->type != bp_none);
 
+  /* Nasty hack to smuggle the location's inferior down to target.  */
+  tmp_inf = b->inferior;
+
   if (b->loc_type == bp_loc_software_breakpoint
       || b->loc_type == bp_loc_hardware_breakpoint)
     {
@@ -1624,6 +1734,7 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
       b->inserted = (is == mark_inserted);
     }
 
+  tmp_inf = NULL;
   return 0;
 }
 
@@ -2814,9 +2925,9 @@ bpstat_check_watchpoint (bpstat bs)
 }
 
 
-/* Check conditions (condition proper, frame, thread and ignore count)
-   of breakpoint referred to by BS.  If we should not stop for this
-   breakpoint, set BS->stop to 0.  */
+/* Check conditions (condition proper, frame, thread, ignore count,
+   and trigger set) of breakpoint referred to by BS.  If we should not
+   stop for this breakpoint, set BS->stop to 0.  */
 static void
 bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
 {
@@ -2858,6 +2969,13 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
        {
          bs->stop = 0;
        }
+      else if (b->trigger_set
+              && !bpstat_check_trigger_set (bl, 
+                                            find_inferior_pid (ptid_get_pid (ptid)),
+                                            pid_to_thread_id (ptid)))
+       {
+         bs->stop = 0;
+       }
       else if (b->ignore_count > 0)
        {
          b->ignore_count--;
@@ -2870,6 +2988,33 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
     }
 }
 
+/* Test whether this stopping inferior and thread are in the i/t set
+   for this breakpoint.  */
+
+static int
+bpstat_check_trigger_set (const struct bp_location *bl, struct inferior *inf,
+                         int thread_id)
+{
+  struct breakpoint *b = bl->owner;
+
+  if (!b->trigger_set)
+    return 1;
+
+  update_itset (b->trigger_set);
+
+  if (itset_member (b->trigger_set, inf, thread_id))
+    return 1;
+
+  /* Stop if the location points to the exec's own inferior, and the inferior
+     here was launched from that exec.  */
+  if (bl->inferior
+      && bl->inferior->exec
+      && bl->inferior->exec->inferior == bl->inferior
+      && inf->exec == bl->inferior->exec)
+    return 1;
+
+  return 0;
+}
 
 /* Get a bpstat associated with having just stopped at address
    BP_ADDR in thread PTID.
@@ -2908,6 +3053,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
     if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
       continue;
 
+    /* Any location that is somehow not connected with a running
+       inferior cannot possibly cause a stop.  */
+    if (!bl->inferior || bl->inferior->pid == 0)
+      continue;
+
     /* For hardware watchpoints, we look only at the first location.
        The watchpoint_check function will work on entire expression,
        not the individual locations.  For read watchopints, the
@@ -3317,7 +3467,7 @@ static void
 print_one_breakpoint_location (struct breakpoint *b,
                               struct bp_location *loc,
                               int loc_number,
-                              CORE_ADDR *last_addr)
+                              CORE_ADDR *last_addr, int allflag)
 {
   struct command_line *l;
   struct symbol *sym;
@@ -3432,11 +3582,7 @@ print_one_breakpoint_location (struct breakpoint *b,
 
   if (b->ops != NULL && b->ops->print_one != NULL)
     {
-      /* Although the print_one can possibly print
-        all locations,  calling it here is not likely
-        to get any nice result.  So, make sure there's
-        just one location.  */
-      gdb_assert (b->loc == NULL || b->loc->next == NULL);
+      /* FIXME make this work right for multiple inferiors etc */
       b->ops->print_one (b, last_addr);
     }
   else
@@ -3491,6 +3637,15 @@ print_one_breakpoint_location (struct breakpoint *b,
        break;
       }
 
+  /* For backward compatibility, don't display inferiors unless there
+     are several.  */
+  if (number_of_execs () > 1 || number_of_inferiors () > 2 || allflag)
+    {
+      ui_out_text (uiout, " inf ");
+      ui_out_field_int (uiout, "inf",
+                       ((loc && loc->inferior) ? loc->inferior->num : 0));
+    }
+  
   if (!part_of_multiple && b->thread != -1)
     {
       /* FIXME: This seems to be redundant and lost here; see the
@@ -3499,6 +3654,13 @@ print_one_breakpoint_location (struct breakpoint *b,
       ui_out_field_int (uiout, "thread", b->thread);
     }
   
+  if (!part_of_multiple && b->trigger_set)
+    {
+      ui_out_text (uiout, " i/t [");
+      ui_out_field_string (uiout, "i/t", b->trigger_set->spec);
+      ui_out_text (uiout, "]");
+    }
+  
   ui_out_text (uiout, "\n");
   
   if (part_of_multiple && frame_id_p (b->frame_id))
@@ -3583,9 +3745,9 @@ print_one_breakpoint_location (struct breakpoint *b,
 
 static void
 print_one_breakpoint (struct breakpoint *b,
-                     CORE_ADDR *last_addr)
+                     CORE_ADDR *last_addr, int allflag)
 {
-  print_one_breakpoint_location (b, NULL, 0, last_addr);
+  print_one_breakpoint_location (b, NULL, 0, last_addr, allflag);
 
   /* If this breakpoint has custom print function,
      it's already printed.  Otherwise, print individual
@@ -3608,7 +3770,7 @@ print_one_breakpoint (struct breakpoint *b,
          struct bp_location *loc;
          int n = 1;
          for (loc = b->loc; loc; loc = loc->next, ++n)
-           print_one_breakpoint_location (b, loc, n, last_addr);
+           print_one_breakpoint_location (b, loc, n, last_addr, allflag);
        }
     }
 }
@@ -3629,7 +3791,7 @@ do_captured_breakpoint_query (struct ui_out *uiout, void *data)
     {
       if (args->bnum == b->number)
        {
-         print_one_breakpoint (b, &dummy_addr);
+         print_one_breakpoint (b, &dummy_addr, 0);
          return GDB_RC_OK;
        }
     }
@@ -3736,7 +3898,7 @@ breakpoint_1 (int bnum, int allflag)
        /* We only print out user settable breakpoints unless the
           allflag is set. */
        if (allflag || user_settable_breakpoint (b))
-         print_one_breakpoint (b, &last_addr);
+         print_one_breakpoint (b, &last_addr, allflag);
       }
   
   do_cleanups (bkpttbl_chain);
@@ -3888,7 +4050,7 @@ breakpoint_address_is_meaningful (struct breakpoint *bpt)
    that one the official one, and the rest as duplicates.  */
 
 static void
-check_duplicates_for (CORE_ADDR address, struct obj_section *section)
+check_duplicates_for (CORE_ADDR address, struct inferior *inf, struct obj_section *section)
 {
   struct bp_location *b;
   int count = 0;
@@ -3900,6 +4062,7 @@ check_duplicates_for (CORE_ADDR address, struct obj_section *section)
        && b->enabled
        && !b->shlib_disabled
        && b->address == address        /* address / overlay match */
+       && b->inferior == inf
        && (!overlay_debugging || b->section == section)
        && breakpoint_address_is_meaningful (b->owner))
     {
@@ -3934,6 +4097,7 @@ check_duplicates_for (CORE_ADDR address, struct obj_section *section)
                && b->owner->enable_state != bp_call_disabled
                && b->enabled && !b->shlib_disabled             
                && b->address == address        /* address / overlay match */
+               && b->inferior == inf
                && (!overlay_debugging || b->section == section)
                && breakpoint_address_is_meaningful (b->owner))
              {
@@ -3957,7 +4121,7 @@ check_duplicates (struct breakpoint *bpt)
     return;
 
   for (; bl; bl = bl->next)
-    check_duplicates_for (bl->address, bl->section);    
+    check_duplicates_for (bl->address, bl->inferior, bl->section);    
 }
 
 static void
@@ -4093,6 +4257,7 @@ set_raw_breakpoint_without_location (enum bptype bptype)
   b->language = current_language->la_language;
   b->input_radix = input_radix;
   b->thread = -1;
+  b->trigger_set = current_itset;
   b->enable_state = bp_enabled;
   b->next = 0;
   b->silent = 0;
@@ -4154,6 +4319,7 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
 {
   struct breakpoint *b = set_raw_breakpoint_without_location (bptype);
   CORE_ADDR adjusted_address;
+  struct inferior *inf;
 
   /* Adjust the breakpoint's address prior to allocating a location.
      Once we call allocate_bp_location(), that mostly uninitialized
@@ -4166,6 +4332,18 @@ set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
   b->loc = allocate_bp_location (b, bptype);
   b->loc->requested_address = sal.pc;
   b->loc->address = adjusted_address;
+  b->loc->inferior = sal.inferior;
+
+  /* Find an inferior in the trigger set.  */
+  if (!b->loc->inferior)
+    b->loc->inferior = first_inferior_in_set (b->trigger_set);
+
+  /* Find an inferior from the sal's symtab.  */
+  if (!b->loc->inferior
+      && sal.symtab
+      && sal.symtab->objfile
+      && sal.symtab->objfile->exec)
+    b->loc->inferior = sal.symtab->objfile->exec->inferior;
 
   if (sal.symtab == NULL)
     b->source_file = NULL;
@@ -4993,6 +5171,7 @@ add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
                            const struct symtab_and_line *sal)
 {
   struct bp_location *loc, **tmp;
+  struct inferior *inf;
 
   loc = allocate_bp_location (b, bptype);
   for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
@@ -5001,6 +5180,19 @@ add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
   loc->requested_address = sal->pc;
   loc->address = adjust_breakpoint_address (loc->requested_address,
                                            bptype);
+  loc->inferior = sal->inferior;
+
+  /* Find an inferior in the trigger set.  */
+  if (!loc->inferior)
+    loc->inferior = first_inferior_in_set (b->trigger_set);
+
+  /* Find an inferior from the sal's symtab.  */
+  if (!loc->inferior
+      && sal->symtab
+      && sal->symtab->objfile
+      && sal->symtab->objfile->exec)
+    loc->inferior = sal->symtab->objfile->exec->inferior;
+
   loc->section = sal->section;
 
   set_breakpoint_location_function (loc);
@@ -5183,8 +5375,9 @@ expand_line_sal_maybe (struct symtab_and_line sal)
          if (find_pc_partial_function (pc, &this_function, 
                                        &func_addr, &func_end))
            {
-             if (this_function && 
-                 strcmp (this_function, original_function) != 0)
+             if (this_function
+                 && original_function
+                 && strcmp (this_function, original_function) != 0)
                {
                  remove_sal (&expanded, i);
                  --i;
@@ -5233,6 +5426,50 @@ expand_line_sal_maybe (struct symtab_and_line sal)
   return expanded;
 }
 
+extern /*static*/ struct symtab_and_line *
+append_expanded_sal (struct symtabs_and_lines *sal,
+                    struct symtab *symtab,
+                    int lineno, CORE_ADDR pc);
+
+struct symtabs_and_lines
+expand_sals_by_inferiors (struct symtabs_and_lines sals)
+{
+  struct symtabs_and_lines expanded;
+  struct symtab_and_line sal, *new_sal;
+  struct inferior *sal_inf, *inf;
+  int i;
+
+  expanded.nelts = 0;
+  expanded.sals = NULL;
+
+  for (i = 0; i < sals.nelts; ++i)
+    {
+      sal = sals.sals[i];
+      append_expanded_sal (&expanded, sal.symtab, sal.line, sal.pc);
+      expanded.sals[expanded.nelts-1].section = sal.section;
+      sal_inf = sal.inferior;
+      if (!sal_inf
+         && sal.symtab
+         && sal.symtab->objfile
+         && sal.symtab->objfile->exec)
+       sal_inf = sal.symtab->objfile->exec->inferior;
+      if (sal_inf)
+       {
+         for (inf = inferior_list; inf; inf = inf->next)
+           {
+             if (inf->exec == sal_inf->exec && inf->pid != 0)
+               {
+                 new_sal = append_expanded_sal (&expanded, sal.symtab, sal.line, sal.pc);
+                 new_sal->section = sal.section;
+                 new_sal->inferior = inf;
+               }
+           }
+       }
+    }
+
+  return expanded;
+}
+
 /* Add SALS.nelts breakpoints to the breakpoint table.  For each
    SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
    value.  COND_STRING, if not NULL, specified the condition to be
@@ -6750,7 +6987,20 @@ clear_command (char *arg, int from_tty)
            }
 
          if (match)
-           VEC_safe_push(breakpoint_p, found, b);
+           {
+             struct breakpoint *b2;
+             int already_there = 0;
+             for (ix = 0; VEC_iterate(breakpoint_p, found, ix, b2); ix++)
+               {
+                 if (b2 == b)
+                   {
+                     already_there = 1;
+                     break;
+                   }
+               }
+             if (!already_there)
+               VEC_safe_push(breakpoint_p, found, b);
+           }
        }
     }
   /* Now go thru the 'found' chain and delete them.  */
@@ -7390,6 +7640,7 @@ breakpoint_re_set_one (void *bint)
          b->condition_not_parsed = 0;
        }
       expanded = expand_line_sal_maybe (sals.sals[0]);
+      expanded = expand_sals_by_inferiors (expanded);
       update_breakpoint_locations (b, expanded);
 
       xfree (sals.sals);
index cff6c3f927e427a74f22585aa04ecf689c86fedf..800260ed602a0dbf536fa46530cb4e7bbafdcfe3 100644 (file)
@@ -26,6 +26,8 @@
 
 struct value;
 struct block;
+struct exec;
+struct itset;
 
 /* This is the maximum number of bytes a breakpoint instruction can take.
    Feel free to increase it.  It's just used in a few places to size
@@ -221,6 +223,9 @@ struct bp_location
      than reference counting.  */
   struct breakpoint *owner;
 
+  /* The inferior (process etc) of this location.  */
+  struct inferior *inferior;
+
   /* Conditional.  Break only if this expression's value is nonzero.  
      Unlike string form of condition, which is associated with breakpoint,
      this is associated with location, since if breakpoint has several
@@ -426,6 +431,9 @@ struct breakpoint
     /* Thread number for thread-specific breakpoint, or -1 if don't care */
     int thread;
 
+    /* Inferior/thread set controlling where this breakpoint will stop.  */
+    struct itset *trigger_set;
+
     /* Count of the number of times this breakpoint was taken, dumped
        with the info, but not used for anything else.  Useful for
        seeing how many times you hit a break prior to the program
index 153e2be3cf8a188549d81c65452d8e2270209c66..44a189612dc4008b2d2a85944b2ec80fa7e0b0e4 100644 (file)
@@ -1714,7 +1714,7 @@ yylex ()
       return (STRING);
     }
 
-  if (!(c == '_' || c == '$'
+  if (!(c == '_' || c == '$' || c == '#'
        || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
     /* We must have come across a bad character (e.g. ';').  */
     error ("Invalid character '%c' in expression.", c);
@@ -1722,7 +1722,7 @@ yylex ()
   /* It's a name.  See how long it is.  */
   namelen = 0;
   for (c = tokstart[namelen];
-       (c == '_' || c == '$' || (c >= '0' && c <= '9')
+       (c == '_' || c == '$' || c == '#' || (c >= '0' && c <= '9')
        || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
     {
       /* Template parameter lists are part of the name.
index af2d1a3633b9e14be46aecd2039d775d2514c351..1d60087c3110510c08e82f6ca14a1b3f5a85a260 100644 (file)
@@ -29,6 +29,7 @@
 #include "gdbcmd.h"
 #include "bfd.h"
 #include "target.h"
+#include "exec.h"
 #include "gdbcore.h"
 #include "dis-asm.h"
 #include "gdb_stat.h"
@@ -135,41 +136,35 @@ specify_exec_file_hook (void (*hook) (char *))
 void
 close_exec_file (void)
 {
-#if 0                          /* FIXME */
-  if (exec_bfd)
-    bfd_tempclose (exec_bfd);
-#endif
 }
 
 void
 reopen_exec_file (void)
 {
-#if 0                          /* FIXME */
-  if (exec_bfd)
-    bfd_reopen (exec_bfd);
-#else
   char *filename;
   int res;
   struct stat st;
-  long mtime;
+  int ix;
+  struct exec *exec;
 
-  /* Don't do anything if there isn't an exec file. */
-  if (exec_bfd == NULL)
+  if (!execs)
     return;
 
-  /* If the timestamp of the exec file has changed, reopen it. */
-  filename = xstrdup (bfd_get_filename (exec_bfd));
-  make_cleanup (xfree, filename);
-  res = stat (filename, &st);
-
-  if (exec_bfd_mtime && exec_bfd_mtime != st.st_mtime)
-    exec_file_attach (filename, 0);
-  else
-    /* If we accessed the file since last opening it, close it now;
-       this stops GDB from holding the executable open after it
-       exits.  */
-    bfd_cache_close_all ();
-#endif
+  for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+    {
+      /* If the timestamp of the exec file has changed, reopen it.  */
+      filename = xstrdup (exec->name);
+      make_cleanup (xfree, filename);
+      res = stat (filename, &st);
+
+      if (exec->ebfd_mtime && exec->ebfd_mtime != st.st_mtime)
+       exec_file_update (exec);
+      else
+       /* If we accessed the file since last opening it, close it now;
+          this stops GDB from holding the executable open after it
+          exits.  */
+       bfd_cache_close_all ();
+    }
 }
 \f
 /* If we have both a core file and an exec file,
@@ -178,11 +173,11 @@ reopen_exec_file (void)
 void
 validate_files (void)
 {
-  if (exec_bfd && core_bfd)
+  if (first_exec && first_exec->ebfd && core_bfd)
     {
-      if (!core_file_matches_executable_p (core_bfd, exec_bfd))
+      if (!core_file_matches_executable_p (core_bfd, first_exec->ebfd))
        warning (_("core file may not match specified executable file."));
-      else if (bfd_get_mtime (exec_bfd) > bfd_get_mtime (core_bfd))
+      else if (bfd_get_mtime (first_exec->ebfd) > bfd_get_mtime (core_bfd))
        warning (_("exec file is newer than core file."));
     }
 }
@@ -194,8 +189,13 @@ validate_files (void)
 char *
 get_exec_file (int err)
 {
-  if (exec_bfd)
-    return bfd_get_filename (exec_bfd);
+  /* This function needs to go away, or return a list of execs, but in
+     the meantime, returning the filename from the current exec is a
+     minimal approximation.  */
+  if (current_exec)
+    return bfd_get_filename (current_exec->ebfd);
+  if (first_exec && first_exec->ebfd)
+    return bfd_get_filename (first_exec->ebfd);
   if (!err)
     return NULL;
 
index 35c998cae04bafa7b417f9e2ab4bdcece0626423..b5d8a4c6a81478f69fcf35e09aa1f4246a95e22d 100644 (file)
@@ -108,6 +108,60 @@ deprecated_add_core_fns (struct core_fns *cf)
   core_file_fns = cf;
 }
 
+int
+is_core_file (char *filename)
+{
+  const char *p;
+  int siggy;
+  struct cleanup *old_chain;
+  char *temp;
+  bfd *temp_bfd;
+  int scratch_chan;
+  int flags;
+
+  if (!filename)
+    return 0;
+
+  filename = tilde_expand (filename);
+  if (!IS_ABSOLUTE_PATH(filename))
+    {
+      temp = concat (current_directory, "/", filename, (char *)NULL);
+      xfree (filename);
+      filename = temp;
+    }
+
+  old_chain = make_cleanup (xfree, filename);
+
+  flags = O_BINARY | O_LARGEFILE;
+  if (write_files)
+    flags |= O_RDWR;
+  else
+    flags |= O_RDONLY;
+  scratch_chan = open (filename, flags, 0);
+  if (scratch_chan < 0)
+    perror_with_name (filename);
+
+  temp_bfd = bfd_fopen (filename, gnutarget, 
+                       write_files ? FOPEN_RUB : FOPEN_RB,
+                       scratch_chan);
+  if (temp_bfd == NULL)
+    perror_with_name (filename);
+
+  if (!bfd_check_format (temp_bfd, bfd_core) &&
+      !gdb_check_format (temp_bfd))
+    {
+      /* 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);
+      return 0;
+    }
+
+  make_cleanup_bfd_close (temp_bfd);
+  return 1;
+}
+
 /* The default function that core file handlers can use to examine a
    core file BFD and decide whether or not to accept the job of
    reading the core file. */
@@ -352,7 +406,7 @@ core_open (char *filename, int from_tty)
      core file.  We don't do this unconditionally since an exec file
      typically contains more information that helps us determine the
      architecture than a core file.  */
-  if (!exec_bfd)
+  if (!(first_exec && first_exec->ebfd))
     set_gdbarch_from_file (core_bfd);
 
   push_target (&core_ops);
@@ -539,7 +593,7 @@ get_core_registers (struct regcache *regcache, int regno)
 static void
 core_files_info (struct target_ops *t)
 {
-  print_section_info (t, core_bfd);
+  print_section_info (t, core_bfd, NULL);
 }
 \f
 static LONGEST
index 4b45f6c89759fb85aa9819e46c3b9038c7d10851..16764b828e1c0124d7204cd13f5332155ac36412 100644 (file)
@@ -297,6 +297,7 @@ struct symbol *
 cp_lookup_symbol_nonlocal (const char *name,
                           const char *linkage_name,
                           const struct block *block,
+                          const struct exec *exec,
                           const domain_enum domain)
 {
   return lookup_namespace_scope (name, linkage_name, block, domain,
@@ -429,7 +430,7 @@ lookup_symbol_file (const char *name,
 {
   struct symbol *sym = NULL;
 
-  sym = lookup_symbol_static (name, linkage_name, block, domain);
+  sym = lookup_symbol_static (name, linkage_name, block, NULL, domain);
   if (sym != NULL)
     return sym;
 
@@ -447,7 +448,7 @@ lookup_symbol_file (const char *name,
     }
   else
     {
-      sym = lookup_symbol_global (name, linkage_name, block, domain);
+      sym = lookup_symbol_global (name, linkage_name, block, NULL, domain);
     }
 
   if (sym != NULL)
index a004783b99217533ee9d0a86f849575dae94110b..cf0dd59b85ab46ef24987303d7e3b4551b7ae298 100644 (file)
@@ -35,6 +35,7 @@ struct block;
 struct objfile;
 struct type;
 struct demangle_component;
+struct exec;
 
 /* This struct is designed to store data from using directives.  It
    says that names from namespace INNER should be visible within
@@ -96,6 +97,7 @@ extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol);
 extern struct symbol *cp_lookup_symbol_nonlocal (const char *name,
                                                 const char *linkage_name,
                                                 const struct block *block,
+                                                const struct exec *exec,
                                                 const domain_enum domain);
 
 extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
index aef5308156fa3c6232b9cd8209a78e07cb871535..75d3af6df8a6394852d10d25e4fc4e35d1d94898 100644 (file)
@@ -864,6 +864,25 @@ option processing.
 This will cause @code{@value{GDBP}} to debug @code{gcc}, and to set
 @code{gcc}'s command-line arguments (@pxref{Arguments}) to @samp{-O2 -c foo.c}.
 
+To debug several programs at the same time, you can supply several
+program names on the command line:
+
+@smallexample
+@value{GDBP} @var{program1} @var{program2} @var{program3}
+@end smallexample
+
+You can supply pids and corefiles as well; @value{GDBN} assumes each
+such argument applies to the program immediately preceding.  So in this
+example:
+
+@smallexample
+@value{GDBP} @var{program1} @var{pid1} @var{program2} @var{program3} @var{pid3}
+@end smallexample
+
+@noindent
+attaches to processes with @var{pid1} and @var{pid3}, and also
+prepares to debug @var{program2}.
+
 You can run @code{@value{GDBP}} without printing the front material, which describes
 @value{GDBN}'s non-warranty, by specifying @code{-silent}:
 
@@ -900,9 +919,10 @@ in sequential order.  The order makes a difference when the
 @node File Options
 @subsection Choosing Files
 
+@c reword the following to explain the multiprocess argument case better.
 When @value{GDBN} starts, it reads any arguments other than options as
-specifying an executable file and core file (or process ID).  This is
-the same as if the arguments were specified by the @samp{-se} and
+specifying executable files, core files, or process IDs.  This is
+similar to if the arguments were specified by the @samp{-se} and
 @samp{-c} (or @samp{-p}) options respectively.  (@value{GDBN} reads the
 first argument that does not have an associated option flag as
 equivalent to the @samp{-se} option followed by that argument; and the
@@ -933,19 +953,24 @@ than @samp{-}, though we illustrate the more usual convention.)
 @itemx -s @var{file}
 @cindex @code{--symbols}
 @cindex @code{-s}
-Read symbol table from file @var{file}.
+Read symbol table from file @var{file}.  This option overrides
+multiple files on the command line, replacing them with just this one
+file.
 
 @item -exec @var{file}
 @itemx -e @var{file}
 @cindex @code{--exec}
 @cindex @code{-e}
-Use file @var{file} as the executable file to execute when appropriate,
-and for examining pure data in conjunction with a core dump.
+Use file @var{file} as the executable file to execute when
+appropriate, and for examining pure data in conjunction with a core
+dump.  This option overrides multiple files on the command line,
+replacing them with just this one file.
 
 @item -se @var{file}
 @cindex @code{--se}
 Read symbol table from file @var{file} and use it as the executable
-file.
+file.  This open overrides multiple files on the command line,
+replacing them with just the one file.
 
 @item -core @var{file}
 @itemx -c @var{file}
@@ -1786,9 +1811,9 @@ kill a child process.
 * Attach::                      Debugging an already-running process
 * Kill Process::                Killing the child process
 
-* Inferiors::                   Debugging multiple inferiors
+* Multiple Programs::           Debugging multiple programs
 * Threads::                     Debugging programs with multiple threads
-* Processes::                   Debugging programs with multiple processes
+* Forks::                       Debugging forks
 * Checkpoint/Restart::          Setting a @emph{bookmark} to return to later
 @end menu
 
@@ -2312,6 +2337,8 @@ can step and continue; you can modify storage.  If you would rather the
 process continue running, you may use the @code{continue} command after
 attaching @value{GDBN} to the process.
 
+@c how does attach know to add vs replace?
+
 @table @code
 @kindex detach
 @item detach
@@ -2331,6 +2358,9 @@ things; you can control whether or not you need to confirm by using the
 @code{set confirm} command (@pxref{Messages/Warnings, ,Optional Warnings and
 Messages}).
 
+In the multi-process case, @code{detach} detaches from all inferiors
+in the current i/t set.
+
 @node Kill Process
 @section Killing the Child Process
 
@@ -2402,6 +2432,226 @@ Show whether messages will be printed when @value{GDBN} detects that
 inferiors have started, exited or have been detached.
 @end table
 
+In the multi-process case, @code{kill} kills all inferiors in the
+current i/t set.
+
+@node Multiple Programs
+@section Debugging Multiple Programs
+
+@value{GDBN} lets you run and debug multiple programs in a single
+session.  In addition, @value{GDBN} on some systems may let you run
+several programs simultaneously (otherwise you have to exit from one
+before starting another).  In the most general case, you can have
+multiple threads of execution in each of multiple processes, launched
+from multiple executables.
+
+You can get multiple executables into a debugging session by either
+supplying them as several arguments on @value{GDBN}'s command line, or
+via the @code{add-file} command.
+
+Many commands will work the same with multiple programs as with a
+single program: @code{print myglobal} will simply display the value of
+@code{myglobal}.  However, if several of the programs have variables
+named @var{myglobal}, things can get very confusing, and it gets worse
+if multiple running processes have been launched from the same
+executable.
+
+@cindex inferior
+To keep everything straight, @value{GDBN} represents the state of each
+program execution with an object called an @dfn{inferior}.  An inferior
+typically corresponds to a process, but is more general and applies
+also to targets that don't have processes.  Inferiors may be created
+before a process runs, and may (in future) be retained after a process
+exits.  Each run of an executable creates a new inferior, as does each
+attachment to an existing process.  Inferiors have unique identifiers
+that are different from process ids, and may optionally be named as
+well.  Usually each inferior will also have its own distinct address
+space, although some embedded targets may have several inferiors
+running in different parts of a single space.
+
+Each inferior may in turn have multiple threads running in it.
+
+@cindex inferior/thread set
+@cindex i/t set
+@cindex itset
+Since there may be very many inferiors, we introduce the
+@dfn{inferior/thread set}, also written as @dfn{i/t set} or
+@dfn{itset} for short.  An i/t set consists of a set of inferiors, and
+for each inferior, a set of threads.  Inferior/thread sets have a specification
+defining the members, normally delimited by square brackets (although
+the brackets may omitted in some contexts).  The basic syntax takes the
+form @code{[@var{inf}.@var{thr}]}, where both @var{inf} and @var{thr}
+may be wildcarded with @code{*}, indicating that the set is to include
+all inferiors or all threads.  In addition, the syntax includes
+provisions for ranges and unions, and special keywords for
+commonly-used sets.
+
+@cindex focus
+@cindex current i/t set
+One of the most important uses for i/t sets is to set the @dfn{focus},
+which is the i/t set to which commands apply by default:
+
+@table @code
+@kindex focus
+@item focus @var{i/t-set}
+Set the current focus to @var{i/t-set}.  Subsequent commands will take
+this set as the collection of inferiors and/or threads on which to
+operate.
+@end table
+
+For instance, @code{focus hello} sets the focus to be on the program
+@code{hello}, while @code{focus 6} sets commands to use inferior 6 by
+default.
+
+Another way to refer to symbols or sources of a particular executable
+is to prefix them with the name of the executable, delimited with
+@code{#}-signs.  For instance @code{#myprog#myglobal} is the version of
+the symbol @code{myglobal} in the executable @code{myprog}, and
+@code{#server#main.c:101} is line 101 of @file{main.c} in the program
+named @code{server}.
+
+@cindex create inferiors
+In many cases it will suffice to simply say @code{run} for each
+executable.  But you may wish to prepare to run several inferiors all
+launched from the same executable.  The commands @code{add-inferior}
+and @code{remove-inferior} let you manage the list of inferiors to be
+run.
+
+@table @code
+@kindex add-inferior
+@item add-inferior @var{exec} [ -copies @var{n} ] [ -name @var{basename} ]
+Adds @var{n} inferiors to be run using @var{exec} as the
+executable.  @var{n} defaults to 1.  The inferiors will be unnamed; to
+give them names, specify @var{basename}, which will be suffixed with
+consecutive numbers.
+
+@kindex remove-inferior
+@item remove-inferior @var{i/t-set}
+Removes any inferior belonging to @var{i/t-set}.  The inferiors
+corresponding to executables will not be removed.
+
+@kindex name-inferior
+@item name-inferior @var{old-name-or-id} @var{new-name}
+Sets the name of the inferior found as @var{old-name-or-id} to @var{new-name}.
+
+@kindex set-exec
+@item set-exec @var{i/t-set} @var{exec}
+Sets the executable of every inferior in @var{i/t-set} to the one
+named by @var{exec}.  @value{GDBN} is usually able to determine the
+executable used to start up an inferior, but in some situations (such
+as attaching to a process) there is no way to know for sure; use this
+command to set the executable correctly. The executable must have
+already been supplied to @value{GDBN}.
+
+@kindex info inferiors
+@item info inferiors
+Print a list of all inferiors currently being managed by @value{GDBN}.
+
+@end table
+
+One of the uses of explicit inferiors is to set different arguments
+for each of them before running.  Commands such as @code{set args}
+apply to every inferior in the current i/t set, so one can do setups
+like this:
+
+@smallexample
+(@value{GDBP}) add-inferior myprog -copies 4 -name instance
+(@value{GDBP}) focus instance1
+(@value{GDBP}) set args a b c
+(@value{GDBP}) focus instance2
+(@value{GDBP}) set args d e f
+(@value{GDBP}) focus all
+(@value{GDBP}) run
+@end smallexample
+
+@noindent
+which will results in four inferiors running, with two of them getting
+the argument lists @code{a b c} and @code{d e f}, and the other two
+having been started without any arguments being passed.
+
+To be informed of inferior creation during running, set the
+@code{inferior-events} variable:
+
+@table @code
+@kindex set print inferior-events
+@cindex print messages on inferior start and exit
+@item set print inferior-events
+@itemx set print inferior-events on
+@itemx set print inferior-events off
+The @code{set print inferior-events} command allows you to enable or
+disable printing of messages when @value{GDBN} notices that new
+inferiors have started or that inferiors have exited or have been
+detached.  By default, these messages will not be printed.
+
+@kindex show print inferior-events
+@item show print inferior-events
+Show whether messages will be printed when @value{GDBN} detects that
+inferiors have started, exited or have been detached.
+@end table
+
+@subsection Inferior/Thread Sets
+
+The inferior/thread set is a compact way to refer to groups of
+inferiors and threads.  Its syntax is as follows:
+
+@table @code
+@item @var{itset-spec} @expansion{}
+@code{"[" @var{raw-itset-spec} "]"}
+
+@item @var{raw-itset-spec} @expansion{}
+@code{[ "!" ] @var{itset-list}}
+
+@item @var{itset-list} @expansion{}
+@code{@var{itset-range} ( "," @var{itset-list} )* }
+
+@item @var{itset-range} @expansion{}
+@code{@var{itset-pair} [ ":" @var{itset-pair} ] }
+
+@item @var{itset-pair} @expansion{}
+@code{[ @var{inferior-spec} ] [ "." @var{thread-spec} ] }
+
+@item @var{inferior-spec} @expansion{}
+@code{@var{number} | @var{name} | "*" | "all" }
+
+@item @var{thread-spec} @expansion{}
+@code{@var{number} | "*" }
+
+@end table
+
+@code{!} preceding a spec indicates a ``static'' i/t set, in which the
+membership is decided when the i/t set is first mentioned, and does
+not change thereafter.  (Note that a static set may become empty
+without warning, if all of its inferiors or threads exit.)  A dynamic
+set updates its membership so as to be current whenever it is used.
+
+The range specification @code{:} calls for the inclusion of every
+inferior and/or thread whose id falls in a numeric range.  For
+instance, @code{[3.4:5.6]} includes inferiors 3, 4, and 5, but only
+the threads numbered 4, 5, or 6 in those inferiors.
+
+The basic @code{@var{inferior}.@var{thread}} syntax allows for
+wildcards and missing components, so both @code{[45.*]} and
+@code{[45]} refer to every thread of inferior 45, while @code{[*.*]}
+and @code{[*]} include every thread of every inferior.
+
+Some examples:
+
+@table @code
+@item [myinf.4:myinf.10]
+Threads 4 through 6 of inferior @code{myinf}.
+
+@item [1]
+The first inferior.
+
+@item [!1:5]
+A static set of the first five inferiors.
+
+@item [myinf,4.7,5.6:5.99]
+A set of three inferiors (@code{myinf}, 4, and 6), plus thread 7 of
+inferior 4, and threads 5 through 99 of inferior 6.
+
+@end table
+
 @node Threads
 @section Debugging Programs with Multiple Threads
 
@@ -2646,12 +2896,12 @@ programs with multiple threads.
 @xref{Set Watchpoints,,Setting Watchpoints}, for information about
 watchpoints in programs with multiple threads.
 
-@node Processes
-@section Debugging Programs with Multiple Processes
+@node Forks
+@section Debugging Forks
 
-@cindex fork, debugging programs which call
 @cindex multiple processes
 @cindex processes, multiple
+@cindex fork, debugging programs which call
 On most systems, @value{GDBN} has no special support for debugging
 programs which create additional processes using the @code{fork}
 function.  When a program forks, @value{GDBN} will continue to debug the
@@ -5504,6 +5754,10 @@ Print lines just before the lines last printed.
 As described in the preceding table.
 @end table
 
+In the case of multiple executables, if the location is ambiguous
+between the several programs, the sources to use will be gotten from
+the first executable in the current i/t set.
+
 @node Specify Location
 @section Specifying a Location
 @cindex specifying location
@@ -5584,6 +5838,14 @@ functions with identical names in different source files.
 
 @end table
 
+Any of these forms may be prefixed with @code{#@var{exec}#}, where
+@var{exec} is the name of any executable that has been given to
+@value{GDBN}.  So if @value{GDBN} was started with @code{gdb prog1
+prog2}, then @code{list #prog2#main.c:10} will list the source code
+around line 10 of @file{main.c} in @code{prog2}.  The name of the
+executable may be either the file name proper, or a pathname with
+which the executable was specified to @value{GDBN}; the latter may be
+useful if there are several executables with the same file name.
 
 @node Edit
 @section Editing Source Files
@@ -6117,6 +6379,10 @@ to programming languages:
 @samp{::} allows you to specify a variable in terms of the file or
 function where it is defined.  @xref{Variables, ,Program Variables}.
 
+@item #
+@samp{#} allows you to specify a variable in terms of the program
+where it is defined.  @xref{Variables, ,Program Variables}.
+
 @cindex @{@var{type}@}
 @cindex type casting memory
 @cindex memory, viewing as typed object
@@ -6290,6 +6556,28 @@ scope resolution operator in @value{GDBN} expressions.
 @c FIXME: Um, so what happens in one of those rare cases where it's in
 @c conflict??  --mew
 
+@cindex sharp, context for variables/functions
+@cindex @code{#}, context for variables/functions
+Similarly, when working with multiple programs in a session, you may
+find symbols that have definitions in several different programs.  You
+can specify a particular executable by prefixing the symbol with the
+executable's name, delimited by @samp{#}:
+
+@smallexample
+#@var{exec}#@var{variable}
+@end smallexample
+
+@var{exec} may be either just the file name, or the pathname by which
+the executable was supplied to @value{GDBN} originally.
+
+The value of the #-qualified symbol is a normal value, available for other
+operations, for instance arithmetic:
+
+@smallexample
+(@value{GDBP}) print #client#sent_size - #server#rcvd_size
+$45 = 16
+@end smallexample
+
 @cindex wrong values
 @cindex variable values, wrong
 @cindex function entry/exit, wrong values of variables
@@ -12567,6 +12855,15 @@ via @code{gdbserver} (@pxref{Server, file, Using the @code{gdbserver}
 Program}).  In these situations the @value{GDBN} commands to specify
 new files are useful.
 
+@value{GDBN} is capable of working with multiple programs at once, so
+you have the option of adding executables instead of replacing them,
+using commands such as @code{add-file}.  While this can be useful, for
+instance to debug both client and server programs from the same
+@value{GDBN}, it can also be confusing to have several functions named
+@code{main}, several globals with the same name but different values,
+and so forth.  You may wish to try using @value{GDBN} each way before
+deciding which is the better approach.
+
 @table @code
 @cindex executable file
 @kindex file
@@ -12595,12 +12892,24 @@ the wrong place.  But this feature is still handy from time to time.
 @code{file} with no argument makes @value{GDBN} discard any information it
 has on both executable file and the symbol table.
 
+@item add-file @var{filename}
+Add @var{filename} to the set of programs being debugged.  As with
+@code{file}, the given file is both used as an executable and as a
+source of symbols.  Each distinct file is added only once (as decided
+by pathname; @value{GDBN} considers files with different full paths to
+be different, even if they are byte-wise identical.)
+
 @kindex exec-file
 @item exec-file @r{[} @var{filename} @r{]}
 Specify that the program to be run (but not the symbol table) is found
-in @var{filename}.  @value{GDBN} searches the environment variable @code{PATH}
-if necessary to locate your program.  Omitting @var{filename} means to
-discard information on the executable file.
+in @var{filename}.  @value{GDBN} searches the environment variable
+@code{PATH} if necessary to locate your program.  Omitting
+@var{filename} means to discard information on the executable file.
+With or without an argument, if there are multiple executables, all
+will be discarded.
+
+@item add-exec-file @var{filename}
+Add @var{filename} to the set of executables that may be run.
 
 @kindex symbol-file
 @item symbol-file @r{[} @var{filename} @r{]}
@@ -12779,12 +13088,12 @@ their addresses.
 @kindex info target
 @item info files
 @itemx info target
-@code{info files} and @code{info target} are synonymous; both print the
-current target (@pxref{Targets, ,Specifying a Debugging Target}),
-including the names of the executable and core dump files currently in
-use by @value{GDBN}, and the files from which symbols were loaded.  The
-command @code{help target} lists all possible targets rather than
-current ones.
+@code{info files} and @code{info target} are synonymous; both print
+the current target (@pxref{Targets, ,Specifying a Debugging Target}),
+including the names of all the executables and core dump files
+currently in use by @value{GDBN}, and the files from which symbols
+were loaded.  The command @code{help target} lists all possible
+targets rather than current ones.
 
 @kindex maint info sections
 @item maint info sections
@@ -24481,6 +24790,11 @@ The register groups info looks like this:
 @item flushregs
 This command forces @value{GDBN} to flush its internal register cache.
 
+@kindex maint print execs
+@cindex info for known executables
+@item maint print execs
+Print a dump of all known executables.
+
 @kindex maint print objfiles
 @cindex info for known object files
 @item maint print objfiles
index 92450e6e2d52c8ef3db5db554f64ab6e6ab7d534..cf4e844f16f52564efb92731d80fe8b5058925d4 100644 (file)
@@ -32,6 +32,7 @@
 #include "exec.h"
 #include "observer.h"
 #include "arch-utils.h"
+#include "vec.h"
 
 #include <fcntl.h>
 #include "readline/readline.h"
@@ -52,8 +53,12 @@ void (*deprecated_file_changed_hook) (char *);
 
 static void exec_close (int);
 
+static void exec_file_command (char *, int);
+
 static void file_command (char *, int);
 
+static void add_file_command (char *, int);
+
 static void set_section_command (char *, int);
 
 static void exec_files_info (struct target_ops *);
@@ -66,10 +71,19 @@ void _initialize_exec (void);
 
 struct target_ops exec_ops;
 
+/* The vector of all executables in use.  */
+
+VEC(exec_p) *execs = NULL;
+
 /* The Binary File Descriptor handle for the executable file.  */
 
 bfd *exec_bfd = NULL;
-long exec_bfd_mtime = 0;
+
+struct exec *last_exec_created;
+
+struct exec *current_exec;
+
+struct exec *first_exec;
 
 /* Whether to open exec and core files read-only or read-write.  */
 
@@ -97,6 +111,8 @@ exec_close (int quitting)
 {
   int need_symtab_cleanup = 0;
   struct vmap *vp, *nxt;
+  int ix;
+  struct exec *ex;
 
   for (nxt = vmap; nxt != NULL;)
     {
@@ -128,6 +144,23 @@ exec_close (int quitting)
 
   vmap = NULL;
 
+  /* Clear all the exec objects.  */
+  if (execs)
+    {
+      for (ix = 0; VEC_iterate (exec_p, execs, ix, ex); ++ix)
+       {
+         /* We don't free objfiles because other code does it.  */
+         if (ex->inferior)
+           delete_inferior (ex->inferior->pid);
+       }
+#if 0
+      VEC_block_remove (exec_p, execs, 0, VEC_length (exec_p, execs));
+#endif
+      execs = NULL;
+      first_exec = NULL;
+      current_exec = NULL;
+    }
+
   if (exec_bfd)
     {
       char *name = bfd_get_filename (exec_bfd);
@@ -137,7 +170,6 @@ exec_close (int quitting)
                 name, bfd_errmsg (bfd_get_error ()));
       xfree (name);
       exec_bfd = NULL;
-      exec_bfd_mtime = 0;
     }
 
   if (exec_ops.to_sections)
@@ -155,10 +187,10 @@ exec_file_clear (int from_tty)
   unpush_target (&exec_ops);
 
   if (from_tty)
-    printf_unfiltered (_("No executable file now.\n"));
+    printf_unfiltered (_("No executable files now.\n"));
 }
 
-/*  Process the first arg in ARGS as the new exec file.
+/* Process the first arg in ARGS as a new exec file.
 
    This function is intended to be behave essentially the same
    as exec_file_command, except that the latter will detect when
@@ -177,18 +209,44 @@ exec_file_clear (int from_tty)
    
    ARGS is assumed to be the filename. */
 
+void exec_file_attach_1 (char *filename, int from_tty);
+
 void
 exec_file_attach (char *filename, int from_tty)
 {
-  /* Remove any previous exec file.  */
+  /* (should clear all existing execs?) */
   unpush_target (&exec_ops);
 
+  exec_file_attach_1 (filename, from_tty);
+}
+
+void
+exec_file_add (char *filename, int from_tty)
+{
+  struct exec *exec;
+
+  /* We don't want more than one of each executable.  */
+  exec = find_exec_by_name (filename);
+  if (exec)
+    {
+      printf_unfiltered (_("Exec '%s' is already present.\n"), filename);
+      return;
+    }
+
+  exec_file_attach_1 (filename, from_tty);
+}
+
+void
+exec_file_attach_1 (char *filename, int from_tty)
+{
+  struct exec *exec = NULL;
+
   /* Now open and digest the file the user requested, if any.  */
 
   if (!filename)
     {
       if (from_tty)
-        printf_unfiltered (_("No executable file now.\n"));
+        printf_unfiltered (_("No executable files now.\n"));
 
       set_gdbarch_from_file (NULL);
     }
@@ -265,13 +323,46 @@ exec_file_attach (char *filename, int from_tty)
                 scratch_pathname, bfd_errmsg (bfd_get_error ()));
        }
 
-      exec_bfd_mtime = bfd_get_mtime (exec_bfd);
-
       validate_files ();
 
       set_gdbarch_from_file (exec_bfd);
 
-      push_target (&exec_ops);
+      /* If this is the first exec, then we need to set up the target
+        vector. We don't need to do it for subsequent execs
+        however.  */
+      if (execs == NULL)
+       push_target (&exec_ops);
+
+      exec = create_exec (filename, exec_bfd, bfd_get_mtime (exec_bfd));
+
+      exec->sections = exec_ops.to_sections;
+      exec->sections_end = exec_ops.to_sections_end;
+
+      if (number_of_execs () == 1)
+       {
+         first_exec = exec;
+
+         if (symfile_objfile
+             && symfile_objfile->exec == NULL)
+           {
+             symfile_objfile->exec = exec;
+             exec->objfile = symfile_objfile;
+           }
+         else
+           {
+             struct objfile *ofile;
+
+             ALL_OBJFILES (ofile)
+               {
+                 if (ofile->name
+                     && strcmp (ofile->name, exec->name) == 0)
+                   {
+                     ofile->exec = exec;
+                     exec->objfile = ofile;
+                   }
+               }
+           }
+       }
 
       /* Tell display code (if any) about the changed file name.  */
       if (deprecated_exec_file_display_hook)
@@ -281,6 +372,169 @@ exec_file_attach (char *filename, int from_tty)
   observer_notify_executable_changed ();
 }
 
+void
+exec_file_update (struct exec *exec)
+{
+  char *filename;
+
+  filename = exec->name;
+
+  {
+    char *scratch_pathname;
+    int scratch_chan;
+
+    scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, filename,
+                         write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, 0,
+                         &scratch_pathname);
+#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
+    if (scratch_chan < 0)
+      {
+       char *exename = alloca (strlen (filename) + 5);
+       strcat (strcpy (exename, filename), ".exe");
+       scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename,
+                             write_files ? O_RDWR | O_BINARY : O_RDONLY | O_BINARY, 0,
+                             &scratch_pathname);
+      }
+#endif
+    if (scratch_chan < 0)
+      perror_with_name (filename);
+    exec->ebfd = bfd_fopen (scratch_pathname, gnutarget,
+                         write_files ? FOPEN_RUB : FOPEN_RB,
+                         scratch_chan);
+
+    if (!exec->ebfd)
+      error (_("\"%s\": could not open as an executable file: %s"),
+            scratch_pathname, bfd_errmsg (bfd_get_error ()));
+
+      /* At this point, scratch_pathname and exec->ebfd->name both point to the
+         same malloc'd string.  However exec_close() will attempt to free it
+         via the exec->ebfd->name pointer, so we need to make another copy and
+         leave exec->ebfd as the new owner of the original copy. */
+      scratch_pathname = xstrdup (scratch_pathname);
+      make_cleanup (xfree, scratch_pathname);
+
+      if (!bfd_check_format (exec->ebfd, bfd_object))
+       {
+         /* Make sure to close exec->ebfd, or else "run" might try to use
+            it.  */
+         exec_close (0);
+         error (_("\"%s\": not in executable format: %s"),
+                scratch_pathname, bfd_errmsg (bfd_get_error ()));
+       }
+
+      /* FIXME - This should only be run for RS6000, but the ifdef is a poor
+         way to accomplish.  */
+#ifdef DEPRECATED_IBM6000_TARGET
+      /* Setup initial vmap. */
+
+      map_vmap (exec->ebfd, 0);
+      if (vmap == NULL)
+       {
+         /* Make sure to close exec->ebfd, or else "run" might try to use
+            it.  */
+         exec_close (0);
+         error (_("\"%s\": can't find the file sections: %s"),
+                scratch_pathname, bfd_errmsg (bfd_get_error ()));
+       }
+#endif /* DEPRECATED_IBM6000_TARGET */
+
+      if (build_section_table (exec->ebfd, &(exec->sections),
+                              &(exec->sections_end)))
+       {
+         /* Make sure to close exec->ebfd, or else "run" might try to use
+            it.  */
+         exec_close (0);
+         error (_("\"%s\": can't find the file sections: %s"),
+                scratch_pathname, bfd_errmsg (bfd_get_error ()));
+       }
+
+      exec->ebfd_mtime = bfd_get_mtime (exec_bfd);
+
+      validate_files ();
+
+      set_gdbarch_from_file (exec->ebfd);
+
+      /* Tell display code (if any) about the changed file name.  */
+      if (deprecated_exec_file_display_hook)
+       (*deprecated_exec_file_display_hook) (filename);
+    }
+
+  observer_notify_executable_changed ();
+}
+
+/* Create an exec object representing the given executable.  */
+
+struct exec *
+create_exec (char *filename, bfd *abfd, long mtime)
+{
+  struct exec *exec;
+  struct inferior *inf;
+
+  exec = (struct exec *) xmalloc (sizeof (struct exec));
+
+  /* Save the full pathname in the exec object.  This may be
+     user-unfriendly at times, since the short name may be
+     ambiguous. Alternatively, when searching for a matching exec,
+     allow any partial path supplied by the user.  */
+  filename = bfd_get_filename (abfd);
+
+  exec->name = savestring (filename, strlen (filename));
+  exec->shortname = (char *) lbasename (exec->name);
+  exec->ebfd = abfd;
+  exec->ebfd_mtime = mtime;
+  exec->objfile = NULL;
+
+  /* Add it to the vector of execs.  */
+  VEC_safe_push (exec_p, execs, exec);
+
+  inf = add_inferior_silent (0);
+  inf->exec = exec;
+  /* Need to ensure unique name? */
+  inf->name = exec->shortname;
+  exec->inferior = inf;
+
+  last_exec_created = exec;
+
+  return exec;
+}
+
+struct exec *
+find_exec_by_name (char *name)
+{
+  return find_exec_by_substr (name, name + strlen (name));
+}
+
+struct exec *
+find_exec_by_substr (char *name, char *name_end)
+{
+  int len, ix;
+  struct exec *exec;
+
+  if (!execs)
+    return NULL;
+
+  len = name_end - name;
+  for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+    {
+      if (strncmp (exec->name, name, len) == 0 && strlen (exec->name) == len)
+       return exec;
+    }
+
+  for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+    {
+      if (strncmp (exec->shortname, name, len) == 0 && strlen (exec->shortname) == len)
+       return exec;
+    }
+
+  return NULL;
+}
+
+int
+number_of_execs ()
+{
+  return VEC_length (exec_p, execs);
+}
+
 /*  Process the first arg in ARGS as the new exec file.
 
    Note that we have to explicitly ignore additional args, since we can
@@ -296,9 +550,13 @@ exec_file_command (char *args, int from_tty)
   char *filename;
 
   if (from_tty && target_has_execution
-      && !query (_("A program is being debugged already.\n"
-                  "Are you sure you want to change the file? ")))
-    error (_("File not changed."));
+      && !((number_of_execs () > 1)
+          ? query (_("%d programs are being debugged already.\n"
+                     "Are you sure you want to change the file? "),
+                   number_of_execs ())
+          : query (_("A program is being debugged already.\n"
+                     "Are you sure you want to change the file? "))))
+    error (_("File(s) not changed."));
 
   if (args)
     {
@@ -320,6 +578,49 @@ exec_file_command (char *args, int from_tty)
     }
   else
     exec_file_attach (NULL, from_tty);
+
+  if (number_of_execs () == 1)
+    set_current_exec (first_exec);
+}
+
+static void
+add_exec_file_command (char *args, int from_tty)
+{
+  char **argv;
+  char *filename;
+
+  if (args)
+    {
+      /* Scan through the args and pick up the first non option arg
+         as the filename.  */
+
+      argv = buildargv (args);
+      if (argv == NULL)
+        nomem (0);
+
+      make_cleanup_freeargv (argv);
+
+      for (; (*argv != NULL) && (**argv == '-'); argv++)
+        {;
+        }
+      if (*argv == NULL)
+        error (_("No executable file name was specified"));
+
+      filename = tilde_expand (*argv);
+      make_cleanup (xfree, filename);
+
+      /* Warn even before starting execution, most users only want to
+        debug a single program at a time.  */
+      if (from_tty
+         && number_of_execs () == 1
+         && !query (_("A program is being debugged already.\n"
+                      "Are you sure you want to add another executable file? ")))
+       error (_("File not added."));
+
+      exec_file_add (filename, from_tty);
+    }
+  else
+    error (_("No executable file name was specified"));
 }
 
 /* Set both the exec file and the symbol file, in one command.  
@@ -333,6 +634,22 @@ file_command (char *arg, int from_tty)
      the exec file, but that's rough.  */
   exec_file_command (arg, from_tty);
   symbol_file_command (arg, from_tty);
+  if (number_of_execs () == 1)
+    set_current_exec (first_exec);
+  if (deprecated_file_changed_hook)
+    deprecated_file_changed_hook (arg);
+}
+
+/* Add the given file as both exec and symbol file.  */
+
+static void
+add_file_command (char *arg, int from_tty)
+{
+  /* FIXME, if we lose on reading the symbol file, we should revert
+     the exec file, but that's rough.  */
+  add_exec_file_command (arg, from_tty);
+  /* Note that symbol_file_command is intrinsically additive.  */
+  symbol_file_command (arg, from_tty);
   if (deprecated_file_changed_hook)
     deprecated_file_changed_hook (arg);
 }
@@ -375,8 +692,13 @@ build_section_table (struct bfd *some_bfd, struct section_table **start,
   unsigned count;
 
   count = bfd_count_sections (some_bfd);
+  /* This function is reused in ways that make it hard to tell when
+     the old one should be discarded, allow this leak until callers
+     are cleaned up.  */
+#if 0
   if (*start)
     xfree (* start);
+#endif
   *start = (struct section_table *) xmalloc (count * sizeof (**start));
   *end = *start;
   bfd_map_over_sections (some_bfd, add_to_section_table, (char *) end);
@@ -464,13 +786,21 @@ xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
             struct mem_attrib *attrib, struct target_ops *target)
 {
   int res;
-  struct section_table *p;
+  struct section_table *p, *sections, *sections_end;
   CORE_ADDR nextsectaddr, memend;
   struct obj_section *section = NULL;
 
   if (len <= 0)
     internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 
+  sections = target->to_sections;
+  sections_end = target->to_sections_end;
+  if (tmp_inf && current_exec && tmp_inf->exec != current_exec)
+    {
+      sections = tmp_inf->exec->sections;
+      sections_end = tmp_inf->exec->sections_end;
+    }
+
   if (overlay_debugging)
     {
       section = find_pc_overlay (memaddr);
@@ -481,7 +811,7 @@ xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
   memend = memaddr + len;
   nextsectaddr = memend;
 
-  for (p = target->to_sections; p < target->to_sections_end; p++)
+  for (p = sections; p < sections_end; p++)
     {
       if (overlay_debugging && section
          && strcmp (section->the_bfd_section->name,
@@ -534,19 +864,30 @@ xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
 \f
 
 void
-print_section_info (struct target_ops *t, bfd *abfd)
+print_section_info (struct target_ops *t, bfd *abfd, struct exec *exec)
 {
-  struct section_table *p;
+  struct section_table *sections, *sections_end, *p;
   /* FIXME: 16 is not wide enough when gdbarch_addr_bit > 64.  */
   int wid = gdbarch_addr_bit (gdbarch_from_bfd (abfd)) <= 32 ? 8 : 16;
 
+  if (exec)
+    {
+      sections = exec->sections;
+      sections_end = exec->sections_end;
+    }
+  else
+    {
+      sections = t->to_sections;
+      sections_end = t->to_sections_end;
+    }
+
   printf_filtered ("\t`%s', ", bfd_get_filename (abfd));
   wrap_here ("        ");
   printf_filtered (_("file type %s.\n"), bfd_get_target (abfd));
-  if (abfd == exec_bfd)
+  if (exec && abfd == exec->ebfd)
     printf_filtered (_("\tEntry point: %s\n"),
                      paddress (bfd_get_start_address (abfd)));
-  for (p = t->to_sections; p < t->to_sections_end; p++)
+  for (p = sections; p < sections_end; p++)
     {
       printf_filtered ("\t%s", hex_string_custom (p->addr, wid));
       printf_filtered (" - %s", hex_string_custom (p->endaddr, wid));
@@ -570,7 +911,23 @@ print_section_info (struct target_ops *t, bfd *abfd)
 static void
 exec_files_info (struct target_ops *t)
 {
-  print_section_info (t, exec_bfd);
+  struct exec *exec;
+  int ix;
+
+  /* Quick summary of the execs present. Only do in the multiprogram
+     case, for compatibility and simplicity.  */
+  if (number_of_execs () > 1)
+    {
+      printf_filtered (_("  Executables:\n"));
+      for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+       printf_filtered (_("   %s `%s'\n"),
+                        (exec == current_exec ? "*" : " "), exec->name);
+      printf_filtered (_("  Sections:\n"));
+    }
+
+  /* Now dump all the section info.  */
+  for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+    print_section_info (t, exec->ebfd, exec);
 
   if (vmap)
     {
@@ -597,6 +954,39 @@ exec_files_info (struct target_ops *t)
     }
 }
 
+/* The maintenance command for execs displays more detail data, such
+   as host addresses for objects.  */
+
+void
+maintenance_print_execs (char *ignore, int from_tty)
+{
+  struct exec *exec;
+  int ix;
+
+  for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+    {
+      printf_filtered ("Executable %s: exec at ", exec->name);
+      gdb_print_host_address (exec, gdb_stdout);
+      printf_filtered (", objfile at ");
+      gdb_print_host_address (exec->objfile, gdb_stdout);
+      printf_filtered (", bfd at ");
+      gdb_print_host_address (exec->ebfd, gdb_stdout);
+      printf_filtered (", inf %d at ",
+                      (exec->inferior ? exec->inferior->num : -1));
+      gdb_print_host_address (exec->inferior, gdb_stdout);
+      printf_filtered ("\n");
+    }
+  printf_filtered ("Current exec is %s, at ",
+                  (current_exec ? current_exec->name : "(null)"));
+  gdb_print_host_address (current_exec, gdb_stdout);
+  printf_filtered ("\n");
+  printf_filtered ("First exec is %s, at ",
+                  (first_exec ? first_exec->name : "(null)"));
+  gdb_print_host_address (first_exec, gdb_stdout);
+  printf_filtered ("\n");
+}
+
+
 static void
 set_section_command (char *args, int from_tty)
 {
@@ -721,6 +1111,13 @@ 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);
       set_cmd_completer (c, filename_completer);
+      c = add_cmd ("add-file", class_files, add_file_command, _("\
+Add FILE to the programs being 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."), &cmdlist);
+      set_cmd_completer (c, filename_completer);
     }
 
   c = add_cmd ("exec-file", class_files, exec_file_command, _("\
@@ -730,6 +1127,12 @@ is searched for a command of that name.\n\
 No arg means have no executable file."), &cmdlist);
   set_cmd_completer (c, filename_completer);
 
+  c = add_cmd ("add-exec-file", class_files, add_exec_file_command, _("\
+Use FILE as program for getting contents of pure memory.\n\
+If FILE cannot be found as specified, your execution directory path\n\
+is searched for a command of that name."), &cmdlist);
+  set_cmd_completer (c, filename_completer);
+
   add_com ("section", class_files, set_section_command, _("\
 Change the base address of section SECTION of the exec file to ADDR.\n\
 This can be used if the exec file does not contain section addresses,\n\
index 3b19d15e1a6a0024b25b36c09f217bd853b8f4e3..9dcc02df17c352bb8fef70c747c72210fcb603b5 100644 (file)
 #define EXEC_H
 
 #include "target.h"
+#include "vec.h"
 
 struct section_table;
 struct target_ops;
 struct bfd;
+struct objfile;
+struct inferior;
 
 extern struct target_ops exec_ops;
 
+/* This object represents an executable program. GDB can handle
+   arbitrarily many, although the traditional debugging scenario just
+   involves one. An executable always has a BFD managing the file
+   itself, but may or may not have an associated symbol table.  */
+
+struct exec
+  {
+    /* The full name of the executable.  */
+    char *name;
+
+    /* An abbreviated name, typically formed by pruning the directory
+       from the full name.  */
+    char *shortname;
+
+    /* The BFD for this executable.  */
+    bfd *ebfd;
+
+    /* The main objfile for this executable.  */
+    struct objfile *objfile;
+
+    /* The last-modified time, from when the exec was brought in.  */
+    long ebfd_mtime;
+
+    /* The "proto-inferior" that we use when setting things up.  */
+    struct inferior *inferior;
+
+    /* Pointers to section table for this executable.  */
+    struct section_table *sections;
+    struct section_table *sections_end;
+  };
+
+typedef struct exec *exec_p;
+DEF_VEC_P(exec_p);
+
+extern VEC(exec_p) *execs;
+
+extern struct exec *current_exec;
+
+extern struct exec *first_exec;
+
 /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
    Returns 0 if OK, 1 on error.  */
 
@@ -37,4 +80,22 @@ extern int build_section_table (struct bfd *, struct section_table **,
 /* Set the loaded address of a section.  */
 extern void exec_set_section_address (const char *, int, CORE_ADDR);
 
+/* Return the first exec whose name matches the given string.  */
+extern struct exec *find_exec_by_name (char *name);
+
+/* Return the first exec whose name matches the chars between the
+   given bounds.  */
+extern struct exec *find_exec_by_substr (char *name, char *name_end);
+
+/* Return the number of executables present.  */
+extern int number_of_execs ();
+
+extern void exec_file_update (struct exec *exec);
+
+extern struct exec *create_exec (char *filename, bfd *abfd, long mtime);
+
+extern void set_current_exec (struct exec *exec);
+
+extern void maintenance_print_execs (char *, int);
+
 #endif
index 75b9d4ef125eec47b2568bc340950126dc622475..5325d36c4dfa2ba262a3f9ed9a6615eadec14aca 100644 (file)
@@ -23,6 +23,7 @@
 #include "defs.h"
 #include "gdb_string.h"
 #include "frame.h"             /* required by inferior.h */
+#include "exec.h"
 #include "inferior.h"
 #include "target.h"
 #include "gdb_wait.h"
@@ -34,6 +35,8 @@
 #include "gdbcmd.h"
 #include "solib.h"
 
+extern int detach_fork;
+
 #include <signal.h>
 
 /* This just gets used as a default if we can't find SHELL.  */
@@ -138,6 +141,8 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
   int shell = 0;
   static char **argv;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
+  struct inferior *inf;
+  struct exec *exec;
 
   /* If no exec file handed to us, get it from the exec-file command
      -- with a good, common error message if none is specified.  */
@@ -394,7 +399,15 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
 
   init_thread_list ();
 
-  add_inferior (pid);
+  inf = add_inferior (pid);
+
+  exec = find_exec_by_name (exec_file_arg);
+
+  if (exec)
+    set_inferior_exec (inf, exec);
+  else
+    warning (_("Could not find exec for \"%s\", breakpoints will not work"),
+            exec_file_arg);
 
   /* Needed for wait_for_inferior stuff below.  */
   inferior_ptid = pid_to_ptid (pid);
index a877494307624b03bdde5b6e1d62a57a33d43cc2..dfd6b2b35f94e8cbfacc9c91a9e7266d5214dfb9 100644 (file)
@@ -67,6 +67,8 @@ struct frame_info
      moment leave this as speculation.  */
   int level;
 
+  struct inferior *inferior;
+
   /* The frame's low-level unwinder and corresponding cache.  The
      low-level unwinder is responsible for unwinding register values
      for the previous frame.  The low-level unwind methods are
@@ -173,6 +175,7 @@ fprint_frame_id (struct ui_file *file, struct frame_id id)
   fprint_field (file, "code", id.code_addr_p, id.code_addr);
   fprintf_unfiltered (file, ",");
   fprint_field (file, "special", id.special_addr_p, id.special_addr);
+  fprintf_unfiltered (file, ",inf=%d", id.inferior_num);
   fprintf_unfiltered (file, "}");
 }
 
@@ -259,6 +262,8 @@ get_frame_id (struct frame_info *fi)
        fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
       /* Find THIS frame's ID.  */
       fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value);
+      if (fi->inferior)
+       fi->this_id.value.inferior_num = fi->inferior->num;
       fi->this_id.p = 1;
       if (frame_debug)
        {
@@ -354,6 +359,9 @@ frame_id_eq (struct frame_id l, struct frame_id r)
   else if (l.special_addr == r.special_addr)
     /* Frames are equal.  */
     eq = 1;
+  else if (l.inferior_num != r.inferior_num)
+    /* If the inferiors are different, the frames are different.  */
+    eq = 0;
   else
     /* No luck.  */
     eq = 0;
@@ -900,6 +908,9 @@ create_sentinel_frame (struct regcache *regcache)
 {
   struct frame_info *frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
   frame->level = -1;
+  /* Frame inferiors will all inherit from the sentinel's inferior.
+     In future we may want to set this from a parameter.  */
+  frame->inferior = current_inferior ();
   /* Explicitly initialize the sentinel frame's cache.  Provide it
      with the underlying regcache.  In the future additional
      information, such as the frame's thread will be added.  */
@@ -1103,6 +1114,8 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc)
 
   fi->next = create_sentinel_frame (get_current_regcache ());
 
+  fi->inferior = fi->next->inferior;
+
   /* Select/initialize both the unwind function and the frame's type
      based on the PC.  */
   fi->unwind = frame_unwind_find_by_frame (fi, &fi->prologue_cache);
@@ -1356,6 +1369,8 @@ get_prev_frame_1 (struct frame_info *this_frame)
   prev_frame = FRAME_OBSTACK_ZALLOC (struct frame_info);
   prev_frame->level = this_frame->level + 1;
 
+  prev_frame->inferior = this_frame->inferior;
+
   /* Don't yet compute ->unwind (and hence ->type).  It is computed
      on-demand in get_frame_type, frame_register_unwind, and
      get_frame_id.  */
@@ -1648,7 +1663,7 @@ pc_notcurrent (struct frame_info *frame)
 void
 find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
 {
-  (*sal) = find_pc_line (get_frame_pc (frame), pc_notcurrent (frame));
+  (*sal) = find_pc_inf_line (get_frame_pc (frame), get_frame_inferior (frame), pc_notcurrent (frame));
 }
 
 /* Per "frame.h", return the ``address'' of the frame.  Code should
@@ -1761,6 +1776,12 @@ deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
   frame->this_id.value.stack_addr = base;
 }
 
+struct inferior *
+get_frame_inferior (struct frame_info *frame)
+{
+  return frame->inferior;
+}
+
 /* Memory access methods.  */
 
 void
index 231aa32e35509d0f6195fa4e5948aa57b5a86005..90e7098400d65fa6b58bbe12809e53ea79a196f2 100644 (file)
@@ -122,6 +122,11 @@ struct frame_id
   unsigned int stack_addr_p : 1;
   unsigned int code_addr_p : 1;
   unsigned int special_addr_p : 1;
+
+  /* The frame's inferior. This field is always valid, but since no
+     inferiors have an ID of zero, a zero value here indicates that
+     the frame is not associated with any inferior.  */
+  int inferior_num;
 };
 
 /* Methods for constructing and comparing Frame IDs.  */
@@ -369,6 +374,8 @@ extern int frame_relative_level (struct frame_info *fi);
 
 extern enum frame_type get_frame_type (struct frame_info *);
 
+extern struct inferior *get_frame_inferior (struct frame_info *);
+
 /* For frames where we can not unwind further, describe why.  */
 
 enum unwind_stop_reason
index 6d8d2eb46801b1175b82f5fcbc5ea2884744c6b2..15a0527223d757150bd4103aff53de747d393dee 100644 (file)
@@ -104,9 +104,6 @@ extern void specify_exec_file_hook (void (*hook) (char *filename));
 extern bfd *core_bfd;
 extern bfd *exec_bfd;
 
-/* The mtime when we last opened exec_bfd.  */
-extern long exec_bfd_mtime;
-
 /* Whether to open exec and core files read-only or read-write.  */
 
 extern int write_files;
@@ -115,6 +112,8 @@ extern void core_file_command (char *filename, int from_tty);
 
 extern void exec_file_attach (char *filename, int from_tty);
 
+extern void exec_file_add (char *filename, int from_tty);
+
 extern void exec_file_clear (int from_tty);
 
 extern void validate_files (void);
index bf3d0a868c507667d01d51582137acee7ae28d9b..eed454f05d06828ed04dc2c941529625b1863f8c 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "defs.h"
 #include "command.h"
+#include "exec.h"
 #include "inferior.h"
 #include "inflow.h"
 #include "gdbcore.h"
@@ -225,7 +226,7 @@ inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty)
     {
       exec_file = get_exec_file (0);
 
-      if (exec_file)
+      if (exec_file && number_of_execs () == 1)
        printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
                           target_pid_to_str (pid_to_ptid (pid)));
       else
@@ -284,11 +285,14 @@ inf_ptrace_detach (struct target_ops *ops, char *args, int from_tty)
 
   if (from_tty)
     {
-      char *exec_file = get_exec_file (0);
-      if (exec_file == 0)
-       exec_file = "";
-      printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
-                        target_pid_to_str (pid_to_ptid (pid)));
+      struct inferior *inf = find_inferior_pid (pid);
+      if (inf && inf->exec)
+       printf_unfiltered (_("Detaching from program: %s, %s\n"),
+                          inf->exec->name,
+                          target_pid_to_str (pid_to_ptid (pid)));
+      else
+       printf_unfiltered (_("Detaching from %s\n"),
+                          target_pid_to_str (pid_to_ptid (pid)));
       gdb_flush (gdb_stdout);
     }
   if (args)
index 810b3b706fcb814b04650bf8dfea0c91a1e3a9e5..a9bfd3e6cb0f1178793bfd362ccbfcf0d357f249 100644 (file)
@@ -33,6 +33,7 @@
 #include "gdbcore.h"
 #include "target.h"
 #include "language.h"
+#include "exec.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "completer.h"
@@ -53,6 +54,8 @@
 #include "gdbthread.h"
 #include "valprint.h"
 
+struct inferior *current_inf;
+
 /* Functions exported for general use, in inferior.h: */
 
 void all_registers_info (char *, int);
@@ -171,7 +174,78 @@ struct gdb_environ *inferior_environ;
 int suppress_resume_observer = 0;
 /* When set, normal_stop will not call the normal_stop observer.  */
 int suppress_stop_observer = 0;
-\f
+
+struct itset *current_itset = NULL;
+
+void
+set_current_exec (struct exec *exec)
+{
+  current_exec = exec;
+  /* As a transitional step, copy exec properties into old crufty globals.  */
+  exec_bfd = current_exec->ebfd;
+  exec_ops.to_sections = current_exec->sections;
+  exec_ops.to_sections_end = current_exec->sections_end;
+  symfile_objfile = current_exec->objfile;
+  clear_symtab_users ();
+}
+
+void
+focus_command (char *spec, int from_tty)
+{
+  struct itset *itset;
+  struct itset_entry *entry;
+  struct inferior *inf;
+  int ix;
+
+  if (!spec)
+    {
+      if (current_itset)
+       printf_filtered ("Focus is [%s]", current_itset->spec);
+      else
+       printf_filtered ("No focus has been set.");
+      if (current_exec)
+       printf_filtered (" (current exec is %s)", current_exec->name);
+      else
+       printf_filtered (" (no current exec)");
+      printf_filtered ("\n");
+      return;
+    }
+
+  itset = make_itset_from_spec (spec);
+
+  if (itset_is_empty (itset))
+    {
+      error ("Cannot focus on an empty set, focus is unchanged");
+      return;
+    }
+
+  current_itset = itset;
+
+  /* For now, set a current exec from the first element of the focus
+     set.  */
+  entry = VEC_index (itset_entry, itset->inferiors, 0);
+  inf = entry->inferior;
+  if (VEC_length (itset_entry, itset->inferiors) > 1)
+    warning ("%d inferiors in the current i/t set, using inf %d to get current exec",
+            VEC_length (itset_entry, itset->inferiors), inf->num);
+  if (inf->exec)
+    set_current_exec (inf->exec);
+  /* (find first live thread?) */
+  if (VEC_length (thread_p, entry->threads) > 1)
+    warning ("%d threads for inferior %d in the current i/t set, switching to first",
+            VEC_length (thread_p, entry->threads), inf->num);
+  if (VEC_length (thread_p, entry->threads) > 0)
+    switch_to_thread ((VEC_index (thread_p, entry->threads, 0))->ptid);
+
+  /* Confirm the choice of focus.  */
+  printf_filtered ("New focus: ");
+  dump_itset (current_itset);
+  if (current_exec)
+    printf_filtered ("Current exec is %s.\n", current_exec->name);
+  else
+    printf_filtered ("No current exec.\n");
+}
+
 /* Accessor routines. */
 
 void 
@@ -195,6 +269,16 @@ get_inferior_io_terminal (void)
 char *
 get_inferior_args (void)
 {
+  struct inferior *inf;
+
+  inf = first_inferior_in_set (current_itset);
+  if (inf)
+    {
+      inferior_args = inf->args;
+      inferior_argc = inf->argc;
+      inferior_argv = inf->argv;
+    }
+
   if (inferior_argc != 0)
     {
       char *n, *old;
@@ -215,27 +299,56 @@ char *
 set_inferior_args (char *newargs)
 {
   char *saved_args = inferior_args;
+  struct inferior *inf;
 
   inferior_args = newargs;
   inferior_argc = 0;
   inferior_argv = 0;
 
+  inf = first_inferior_in_set (current_itset);
+  if (inf)
+    {
+      inf->args = newargs;
+      inf->argc = 0;
+      inf->argv = 0;
+    }
+
   return saved_args;
 }
 
 void
 set_inferior_args_vector (int argc, char **argv)
 {
+  struct inferior *inf;
+
   inferior_argc = argc;
   inferior_argv = argv;
+
+  inf = first_inferior_in_set (current_itset);
+  if (inf)
+    {
+      inf->argc = argc;
+      inf->argv = argv;
+    }
+
 }
 
 /* Notice when `set args' is run.  */
 static void
 notice_args_set (char *args, int from_tty, struct cmd_list_element *c)
 {
+  struct inferior *inf;
+
   inferior_argc = 0;
   inferior_argv = 0;
+
+  inf = first_inferior_in_set (current_itset);
+  if (inf)
+    {
+      inf->args = xstrdup (inferior_args);
+      inf->argc = 0;
+      inf->argv = 0;
+    }
 }
 
 /* Notice when `show args' is run.  */
@@ -2115,6 +2228,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
   char *exec_file;
   char *full_exec_path = NULL;
   struct inferior *inferior;
+  struct exec *exec;
 
   inferior = current_inferior ();
   inferior->stop_soon = NO_STOP_QUIETLY;
@@ -2238,7 +2352,10 @@ attach_command (char *args, int from_tty)
     ;
   else if (target_has_execution)
     {
-      if (query ("A program is being debugged already.  Kill it? "))
+      if ((number_of_execs () > 1)
+         ? query ("%d programs are being debugged already.  Kill them? ",
+                  number_of_execs ())
+         : query ("A program is being debugged already.  Kill it? "))
        target_kill ();
       else
        error (_("Not killed."));
@@ -2328,6 +2445,19 @@ attach_command (char *args, int from_tty)
     }
 
   attach_command_post_wait (args, from_tty, async_exec);
+
+  /* As a heuristic, if there is no exec assigned to the attached
+     inferior, but only one exec known to GDB, guess that it is the
+     exec for the the process just attached. (If GDB has guessed
+     wrong, it will be up to the user to use set-exec to fix
+     matters.)  */
+  {
+    struct inferior *inferior = current_inferior ();
+
+    if (!inferior->exec && number_of_execs () == 1)
+      set_inferior_exec (inferior, first_exec);
+  }
+
   discard_cleanups (back_to);
 }
 
@@ -2478,6 +2608,9 @@ _initialize_infcmd (void)
 {
   struct cmd_list_element *c = NULL;
 
+  add_com ("focus", no_class, focus_command, _("\
+Change the set of current inferiors/threads."));
+
   /* add the filename of the terminal connected to inferior I/O */
   add_setshow_filename_cmd ("inferior-tty", class_run,
                            &inferior_io_terminal, _("\
index 24f8fa6b5d87e8abcd66ab6d9b879406b7999285..b2a8bf6ade4798b02831e27201356c03a0edd2b3 100644 (file)
@@ -18,6 +18,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "exec.h"
 #include "inferior.h"
 #include "target.h"
 #include "command.h"
 
 void _initialize_inferiors (void);
 
-static struct inferior *inferior_list = NULL;
+/*static*/ struct inferior *inferior_list = NULL;
 static int highest_inferior_num;
 
+struct inferior *tmp_inf;
+
 /* Print notices on inferior events (attach, detach, etc.), set with
    `set print inferior-events'.  */
 static int print_inferior_events = 0;
 
+/* Commands with a prefix of `inferiors'.  */
+extern struct cmd_list_element *inferior_cmd_list;
+
+struct inferior *find_inferior_id (int num);
+static void info_inferiors_command (char *, int);
+
 struct inferior*
 current_inferior (void)
 {
@@ -46,11 +55,18 @@ current_inferior (void)
 static void
 free_inferior (struct inferior *inf)
 {
+  /* FIXME: We can't safely free inferior data until all refs to it
+     have been removed, such as from breakpoint locations etc.  */
+#if 0
   discard_all_inferior_continuations (inf);
   xfree (inf->private);
   xfree (inf);
+#endif
 }
 
+/* TODO: I'm not calling this anywhere.  If we stick with the one
+   target vector fits all inferiors notion, maybe this should be
+   called when the target is pushed on the stack.  */
 void
 init_inferior_list (void)
 {
@@ -78,8 +94,6 @@ add_inferior_silent (int pid)
   memset (inf, 0, sizeof (*inf));
   inf->pid = pid;
 
-  inf->stop_soon = NO_STOP_QUIETLY;
-
   inf->num = ++highest_inferior_num;
   inf->next = inferior_list;
   inferior_list = inf;
@@ -190,7 +204,7 @@ discard_all_inferiors (void)
     }
 }
 
-static struct inferior *
+struct inferior *
 find_inferior_id (int num)
 {
   struct inferior *inf;
@@ -202,6 +216,7 @@ find_inferior_id (int num)
   return NULL;
 }
 
+/* Find a inferior by matching PID.  */
 struct inferior *
 find_inferior_pid (int pid)
 {
@@ -214,6 +229,18 @@ find_inferior_pid (int pid)
   return NULL;
 }
 
+struct inferior *
+find_inferior_by_name (char *name)
+{
+  struct inferior *inf;
+
+  for (inf = inferior_list; inf; inf = inf->next)
+    if (inf->name && strcmp (inf->name, name) == 0)
+      return inf;
+
+  return NULL;
+}
+
 struct inferior *
 iterate_over_inferiors (int (*callback) (struct inferior *, void *),
                        void *data)
@@ -282,6 +309,18 @@ have_inferiors (void)
   return inferior_list != NULL;
 }
 
+int
+number_of_inferiors (void)
+{
+  struct inferior *inf;
+  int rslt = 0;
+
+  for (inf = inferior_list; inf; inf = inf->next)
+    ++rslt;
+  return rslt;
+}
+
+
 /* Prints the list of inferiors and their details on UIOUT.  This is a
    version of 'info_inferior_command' suitable for use from MI.
 
@@ -291,6 +330,7 @@ void
 print_inferior (struct ui_out *uiout, int requested_inferior)
 {
   struct inferior *inf;
+  char *extra_info;
   struct cleanup *old_chain;
 
   old_chain = make_cleanup_ui_out_list_begin_end (uiout, "inferiors");
@@ -304,7 +344,7 @@ print_inferior (struct ui_out *uiout, int requested_inferior)
 
       chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
 
-      if (inf->pid == ptid_get_pid (inferior_ptid))
+      if (inf->pid > 0 && inf->pid == PIDGET (inferior_ptid))
        ui_out_text (uiout, "* ");
       else
        ui_out_text (uiout, "  ");
@@ -312,7 +352,46 @@ print_inferior (struct ui_out *uiout, int requested_inferior)
       ui_out_field_int (uiout, "id", inf->num);
       ui_out_text (uiout, " ");
       ui_out_field_int (uiout, "target-id", inf->pid);
-
+      if (inf->name)
+       {
+         ui_out_text (uiout, " #");
+         ui_out_field_string (uiout, "name", inf->name);
+         ui_out_text (uiout, "#");
+       }
+      if (inf->exec)
+       {
+         ui_out_text (uiout, " ");
+         /* Use short names for execs, except for exec's own
+            inferior.  */
+         ui_out_field_string (uiout, "exec",
+                              (inf->exec->inferior == inf
+                               ? inf->exec->name
+                               : inf->exec->shortname));
+         if (inf->args)
+           {
+             ui_out_text (uiout, " ");
+             ui_out_field_string (uiout, "args", inf->args);
+           }
+         if (inf->inf_environ)
+           {
+             ui_out_text (uiout, " ");
+             ui_out_field_string (uiout, "environ", "env=X");
+           }
+         if (inf->io_terminal)
+           {
+             ui_out_text (uiout, " ");
+             ui_out_field_string (uiout, "io_terminal", "term=Y");
+           }
+       }
+#if 0
+      extra_info = target_extra_inferior_info (inf);
+      if (extra_info)
+       {
+         ui_out_text (uiout, " (");
+         ui_out_field_string (uiout, "details", extra_info);
+         ui_out_text (uiout, ")");
+       }
+#endif
       ui_out_text (uiout, "\n");
       do_cleanups (chain2);
     }
@@ -336,11 +415,695 @@ show_print_inferior_events (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Printing of inferior events is %s.\n"), value);
 }
 
+void
+add_inferior_command (char *args, int from_tty)
+{
+  struct exec *ex = NULL;
+  struct inferior *inf;
+  int i, copies = 1;
+  char *namebase = "", *namebuf;
+  char **argv;
+
+  if (args)
+    {
+      argv = buildargv (args);
+      for (; *argv != NULL; argv++)
+       {
+         if (**argv == '-')
+           {
+             if (strcmp (*argv, "-copies") == 0)
+               {
+                 ++argv;
+                 if (!*argv)
+                   error ("No argument to -copies");
+                 copies = strtol (*argv, NULL, 10);
+               }
+             else if (strcmp (*argv, "-name") == 0)
+               {
+                 ++argv;
+                 if (!*argv)
+                   error ("No argument to -name");
+                 namebase = xstrdup (*argv);
+               }
+           }
+         else
+           {
+             ex = find_exec_by_name (*argv);
+             if (!ex)
+               {
+                 printf_unfiltered ("No exec found named '%s'\n", *argv);
+                 /* Should ask whether to continue.  */
+               }
+           }
+       }
+    }
+
+  if (ex)
+    ;
+  else if (current_exec)
+    ex = current_exec;
+
+  for (i = 0; i < copies; ++i)
+    {
+      inf = add_inferior (0);
+      inf->exec = ex;
+      inf->removable = 1;
+      namebuf = (char *) xmalloc (strlen (namebase) + 10);
+      sprintf (namebuf, "%s%d", namebase, inf->num);
+      set_inferior_name (inf, namebuf);
+      /* Should flag as not having run yet.  */
+    }
+
+  printf_filtered ("%d inferiors added.\n", copies);
+}
+
+void
+remove_inferior_command (char *args, int from_tty)
+{
+  struct itset *itset;
+  struct itset_entry *entry;
+  struct inferior *inf;
+  int ix;
+
+  itset = make_itset_from_spec (args);
+
+  dump_itset (itset);
+
+  for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
+    {
+#if 0
+      if (entry->inferior->removable)
+       delete_inferior (entry->inferior);
+      /* (should remove threads?) */
+#endif
+    }
+}
+
+void
+set_inferior_name (struct inferior *inf, char *name)
+{
+  inf->name = name;
+}
+
+void
+name_inferior_command (char *args, int from_tty)
+{
+  char *oldname, *newname;
+  struct inferior *inf;
+
+  if (args == NULL)
+    return;
+
+  while (*args == ' ' || *args == '\t')
+    args++;
+  oldname = args;
+  while (*args && !(*args == ' ' || *args == '\t'))
+    args++;
+  oldname = savestring (oldname, args - oldname);
+  while (*args == ' ' || *args == '\t')
+    args++;
+  if (*args)
+    {
+      inf = find_inferior_by_name (oldname);
+      newname = args;
+      while (*args && !(*args == ' ' || *args == '\t'))
+       args++;
+      newname = savestring (newname, args - newname);
+    }
+  else
+    {
+      /* One-argument case.  */
+      inf = first_inferior_in_set (current_itset);
+      newname = oldname;
+    }
+  if (!inf)
+    {
+      printf_unfiltered("No inferior '%s' to rename.\n", oldname);
+      return;
+    }
+  printf_unfiltered("Rename '%s' to '%s'\n", inf->name, newname);
+  set_inferior_name (inf, newname);
+  printf_unfiltered("Inferior %d now named '%s'\n", inf->num, inf->name);
+}
+
+void
+set_inferior_exec (struct inferior *inf, struct exec *exec)
+{
+  inf->exec = exec;
+}
+
+/* set-exec ITSET EXEC
+   Set the inferiors found in ITSET to have the executable EXEC. Since
+   this command is primarily useful to repairing cases where GDB can't
+   do the right thing on its own, we only do minimal error checking,
+   and it is possible to overwrite a valid executable with one whose
+   addresses don't match up with the inferior.  */
+
+void
+set_inferior_exec_command (char *args, int from_tty)
+{
+  struct exec *exec, *old_exec;
+  struct inferior *inf;
+  struct itset *itset;
+  struct itset_entry *entry;
+  char **argv, *itset_spec = NULL, *exec_name = NULL;
+  int ix;
+
+  if (!args)
+    return;
+
+  argv = buildargv (args);
+  itset_spec = *argv++;
+  if (!itset_spec)
+    error ("No i/t set supplied");
+  exec_name = *argv++;
+  if (!exec_name)
+    error ("No executable name supplied");
+  if (*argv)
+    warning ("Extra arguments ignored");
+
+  itset = make_itset_from_spec (itset_spec);
+  if (itset_is_empty (itset))
+    error ("No inferiors in [%s]", itset_spec);
+
+  exec = find_exec_by_name (exec_name);
+  if (!exec)
+    error ("No exec named `%s'", exec_name);
+
+  for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
+    {
+      inf = entry->inferior;
+      old_exec = inf->exec;
+      if (exec == old_exec)
+       continue;
+      /* Don't touch the exec's own inferior.  */
+      if (old_exec && inf == old_exec->inferior)
+       continue;
+      set_inferior_exec (inf, exec);
+      if (old_exec)
+       printf_filtered ("Inferior %d exec changed from `%s' to `%s'.\n",
+                        inf->num, old_exec->name, exec->name);
+      else
+       printf_filtered ("Inferior %d now has exec `%s'.\n",
+                        inf->num, exec->name);
+    }
+
+  /* should free itset here? */
+}
+
+/* Inferior/thread sets.  */
+
+struct itid_pair { char *infspec; char *tidspec; };
+
+extern void parse_itset_spec (struct itset *itset);
+extern void parse_itset_list (struct itset *itset);
+extern void parse_itset_range (struct itset *itset);
+extern struct itid_pair parse_itset_itid (struct itset *itset);
+extern char *parse_itset_iid (struct itset *itset);
+extern char *parse_itset_tid (struct itset *itset);
+extern void get_inferior_or_pid (char *spec, struct inferior **infp, int *pidp);
+extern void add_inferior_to_itset (struct itset *itset, struct inferior *inf,
+                                  char *lo_tidspec, char *hi_tidspec);
+extern void add_threads_to_itset (struct itset_entry *entry,
+                                 char *lo_tidspec, char *hi_tidspec);
+
+
+/* Create a new i/t set, doing a test parse to check syntax.  */
+
+struct itset *
+new_itset (char *spec)
+{
+  struct itset *itset;
+
+  /* We must have a specification to work with.  */
+  if (!spec)
+    return NULL;
+
+  /* FIXME need to dispose of these properly */
+  itset = (struct itset *) xmalloc (sizeof (struct itset));
+
+  itset->name = NULL;
+  itset->spec = xstrdup (spec);
+  itset->dynamic = 1;
+  itset->inferiors = NULL;
+
+  /* Do a first test parse to check syntax.  */
+  itset->parsed = 0;
+  itset->parse_errors = 0;
+  parse_itset_spec (itset);
+  itset->parsed = 1;
+
+  /* Do a second time to get in all the semantic actions, aka adding
+     items to vectors.  */
+  if (!itset->parse_errors)
+    parse_itset_spec (itset);
+
+  return itset;
+}
+
+void
+update_itset (struct itset *itset)
+{
+  if (!itset)
+    return;
+
+  /* Don't touch static itsets.  */
+  if (!itset->dynamic)
+    return;
+
+  /* If the spec has a syntax error, don't try to work with it.  */
+  if (itset->parse_errors)
+    return;
+
+  /* Clear the vectors in preparation.  */
+  /* FIXME clear thread subvectors too */
+  VEC_truncate (itset_entry, itset->inferiors, 0);
+  parse_itset_spec (itset);
+}
+
+void
+parse_itset_spec (struct itset *itset)
+{
+  itset->parse_head = itset->spec;
+
+  if (*(itset->parse_head) == '!')
+    {
+      ++(itset->parse_head);
+      if (itset->parsed && !itset->parse_errors)
+       itset->dynamic = 0;
+    }
+
+  parse_itset_list (itset);
+}
+
+void
+parse_itset_list (struct itset *itset)
+{
+  /* This is the empty set case.  */
+  if (*(itset->parse_head) == '\0')
+    return;
+
+  parse_itset_range (itset);
+  while (*itset->parse_head == ',')
+    {
+      ++(itset->parse_head);
+      parse_itset_range (itset);
+    }
+}
+
+void
+parse_itset_range (struct itset *itset)
+{
+  struct itid_pair lopair, hipair;
+  struct inferior *lo_inf, *hi_inf, *inf;
+  int lo_pid, hi_pid;
+  struct itset_entry *entry;
+
+  hipair.infspec = hipair.tidspec = NULL;
+
+  lopair = parse_itset_itid (itset);
+  if (*(itset->parse_head) == ':')
+    {
+      ++(itset->parse_head);
+      hipair = parse_itset_itid (itset);
+    }
+  if (itset->parsed && !itset->parse_errors)
+    {
+      if (strcmp (lopair.infspec, "all") == 0
+         || strcmp (lopair.infspec, "*") == 0
+         || (hipair.infspec && strcmp (hipair.infspec, "*") == 0))
+       {
+         /* Wildcards override everything else.  We need to do the
+            addition incrementally, in case it's supplementing a
+            previous spec; for instance, "2.3,*.5" should add the 3rd
+            thread of inferior 2 and threads 5 of all inferiors.  */
+         for (inf = inferior_list; inf; inf = inf->next)
+           add_inferior_to_itset (itset, inf, lopair.tidspec, hipair.tidspec);
+       }
+      else
+       {
+         get_inferior_or_pid (lopair.infspec, &lo_inf, &lo_pid);
+         if (hipair.infspec)
+           {
+             get_inferior_or_pid (hipair.infspec, &hi_inf, &hi_pid);
+             /* This is a hack to use raw id's for range.  */
+             if (lo_inf && lo_inf->pid == 0 && hi_inf && hi_inf->pid == 0)
+               {
+                 for (inf = inferior_list; inf; inf = inf->next)
+                   if (inf->num >= lo_inf->num && inf->num <= hi_inf->num)
+                     add_inferior_to_itset (itset, inf,
+                                            lopair.tidspec, hipair.tidspec);
+                 return;
+               }
+             /* Find every inferior in the range of the two supplied
+                pids.  */
+             if (lo_pid >= 0 && hi_pid >= 0)
+               {
+                 for (inf = inferior_list; inf; inf = inf->next)
+                   if (inf->pid >= lo_pid && inf->pid <= hi_pid)
+                     add_inferior_to_itset (itset, inf,
+                                            lopair.tidspec, hipair.tidspec);
+               }
+             /* (else error?) */
+           }
+         else
+           {
+             /* Only the low part of a range is found, just add the
+                one inferior.  */
+             if (lo_inf)
+               add_inferior_to_itset (itset, lo_inf,
+                                      lopair.tidspec, hipair.tidspec);
+             /* (else error?) */
+           }
+       }
+    }
+}
+
+/* Given a spec string, find a name or number plausibly representing
+   an inferior name or a process pid.  */
+
+void
+get_inferior_or_pid (char *spec, struct inferior **infp, int *pidp)
+{
+  struct inferior *inf;
+  int num;
+  char *endspec;
+
+  *infp = NULL;
+  *pidp = -1;
+  /* Look for an inferior with a matching name.  Note that we
+     want to allow names with leading digits.  */
+  for (inf = inferior_list; inf; inf = inf->next)
+    {
+      if (inf->name && strcmp (spec, inf->name) == 0)
+       {
+         *infp = inf;
+         *pidp = inf->pid;
+         return;
+       }
+    }
+  num = strtol (spec, &endspec, 10);
+  if (*endspec != '\0')
+    {
+      /* (should error?) */
+      return;
+    }
+  *infp = find_inferior_pid (num);
+  if (*infp)
+    {
+      *pidp = (*infp)->pid;
+      return;
+    }
+  /* Hack fallback that look at raw inferior id.  */
+  *infp = find_inferior_id (num);
+  if (*infp)
+    {
+      *pidp = (*infp)->pid;
+      return;
+    }
+  /* Assume number is being used as a range bound, don't insist that
+     it correspond to an actual inferior.  */
+  *pidp = num;
+}  
+
+void
+add_inferior_to_itset (struct itset *itset, struct inferior *inf,
+                      char *lo_tidspec, char *hi_tidspec)
+{
+  struct inferior *inf2;
+  struct itset_entry new_entry, *entry;
+  int ix, found = 0;
+  
+  /* Only add one copy of each inferior to the set.  */
+  /* FIXME: this will be a performance problem when we have thousands
+     of inferiors.  */
+  for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
+    if (inf == entry->inferior)
+      {
+       found = 1;
+       break;
+      }
+
+  if (!found)
+    {
+      new_entry.inferior = inf;
+      new_entry.threads = NULL;
+      entry = VEC_safe_push (itset_entry, itset->inferiors, &new_entry);
+    }
+
+  add_threads_to_itset (entry, lo_tidspec, hi_tidspec);
+
+  /* The inclusion of an exec's own inferior directs the addition of
+     all inferiors derived from that exec.  */
+  if (inf->exec && inf->exec->inferior == inf)
+    {
+      for (inf2 = inferior_list; inf2; inf2 = inf2->next)
+       {
+         if (inf2 != inf && inf2->exec == inf->exec)
+           add_inferior_to_itset (itset, inf2, lo_tidspec, hi_tidspec);
+       }
+    }
+}
+
+/* Encapsulation for data passed to thread callback.  */
+
+struct addbits
+{
+  struct itset_entry *entry;
+  int lo, hi;
+};
+
+static int
+itset_add_thread_callback (struct thread_info *thread, void *data)
+{
+  struct addbits *addbits = data;
+  struct itset_entry *entry;
+  struct thread_info *thr;
+  int ix;
+
+  entry = addbits->entry;
+  if ((thread->ptid.pid == entry->inferior->pid)
+      && (addbits->lo < 0
+         || (thread->num >= addbits->lo && thread->num <= addbits->hi)))
+    {
+      /* Skip adding dups of thread info.  */
+      for (ix = 0; VEC_iterate (thread_p, entry->threads, ix, thr); ++ix)
+       if (thread == thr)
+         return 0;
+      VEC_safe_push (thread_p, entry->threads, thread);
+    }
+  return 0;
+}
+
+void
+add_threads_to_itset (struct itset_entry *entry,
+                     char *lo_tidspec, char *hi_tidspec)
+{
+  struct addbits data;
+  int lo_tid, hi_tid;
+  char *endspec;
+
+  /* Treat a missing thread spec as equivalent to '*'.  */
+  if (!lo_tidspec)
+    lo_tidspec = "*";
+
+  data.entry = entry;
+  if (strcmp (lo_tidspec, "*") == 0
+      || (hi_tidspec && strcmp (hi_tidspec, "*") == 0))
+    {
+      data.lo = data.hi = -1;
+    }
+  else
+    {
+      data.lo = strtol (lo_tidspec, &endspec, 10);
+      data.hi = data.lo;
+      if (hi_tidspec)
+       data.hi = strtol (hi_tidspec, &endspec, 10);
+      /* (should detect non-empty endspec and warn) */
+    }
+  iterate_over_threads (itset_add_thread_callback, &data);
+}
+
+/* Parse an inferior.thread pair and return it as a two-element struct.  */
+
+struct itid_pair
+parse_itset_itid (struct itset *itset)
+{
+  struct itid_pair rslt;
+
+  rslt.infspec = parse_itset_iid (itset);
+  rslt.tidspec = NULL;
+  if (*(itset->parse_head) == '.')
+    {
+      ++(itset->parse_head);
+      rslt.tidspec = parse_itset_tid (itset);
+    }
+  return rslt;
+}
+
+/* Recognize an inferior id, which can be just about anything; not
+   much to do here, pass it back up for semantic analysis.  */
+
+char *
+parse_itset_iid (struct itset *itset)
+{
+  char *endpos = itset->parse_head;
+  char *term;
+
+  while (strchr ("],:.", *endpos) == NULL)
+    ++endpos;
+  /* FIXME arrange to discard */
+  term = savestring (itset->parse_head, endpos - itset->parse_head);
+  itset->parse_head = endpos;
+
+  return term;
+}
+
+/* Parse a thread id, which may be a decimal number or "*".  */
+
+char *
+parse_itset_tid (struct itset *itset)
+{
+  char *endpos = itset->parse_head;
+  char *term, *endterm;
+
+  while (strchr ("],:.", *endpos) == NULL)
+    ++endpos;
+  /* FIXME arrange to discard */
+  term = savestring (itset->parse_head, endpos - itset->parse_head);
+  itset->parse_head = endpos;
+  if (strcmp (term, "*") == 0)
+    return term;
+  else
+    {
+      strtol (term, &endterm, 10);
+      if (*endterm == '\0')
+       return term;
+      else
+       {
+         warning ("'%s' is not a valid thread id\n", term);
+         itset->parse_errors = 1;
+         return NULL;
+       }
+    }
+}
+
+struct itset *
+make_itset_from_spec (char *spec)
+{
+  int len;
+  struct itset *itset;
+
+  /* Canonicalize by removing brackets.  */
+  if (spec[0] == '[')
+    ++spec;
+  len = strlen (spec);
+  if (spec[len - 1] == ']')
+    --len;
+  /* FIXME arrange to discard later */
+  spec = savestring (spec, len);
+
+  itset = new_itset (spec);
+
+  return itset;
+}
+
+int
+itset_is_empty (struct itset *itset)
+{
+  return (itset == NULL || VEC_length (itset_entry, itset->inferiors) == 0);
+}
+
+/* See if a given inferior and thread is in the i/t set.  */
+
+int
+itset_member (struct itset *itset, struct inferior *inf, int thread_id)
+{
+  struct itset_entry *entry;
+  struct thread_info *thr;
+  int ix, iy;
+
+  /* FIXME: this will be a performance problem when we have thousands
+     of inferiors.  */
+  for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
+    if (inf == entry->inferior)
+      {
+       for (iy = 0; VEC_iterate (thread_p, entry->threads, iy, thr); ++ix)
+         if (thread_id == thr->num)
+           return 1;
+      }
+  return 0;
+}
+
+/* Return the first inferior found in the i/t set.  */
+
+struct inferior *
+first_inferior_in_set (struct itset *itset)
+{
+  struct itset_entry *entry;
+
+  if (!itset
+      || !itset->inferiors
+      || VEC_length (itset_entry, itset->inferiors) == 0)
+    return NULL;
+
+  entry = VEC_index (itset_entry, itset->inferiors, 0);
+
+  if (!entry)
+    return NULL;
+
+  return entry->inferior;
+}
+
+/* Debugging dump for i/t sets.  */
+
+void
+dump_itset (struct itset *itset)
+{
+  struct itset_entry *entry;
+  struct inferior *inf;
+  struct thread_info *thr;
+  int ix, iy;
+
+  if (!itset)
+    {
+      printf_unfiltered ("null itset\n");
+      return;
+    }
+
+  printf_unfiltered ("i/t set specified as '%s' (%s)",
+                    itset->spec, (itset->dynamic ? "dynamic" : "static"));
+
+  printf_unfiltered (" {%di", VEC_length (itset_entry, itset->inferiors));
+  for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
+    {
+      printf_unfiltered (",%d", entry->inferior->num);
+      printf_unfiltered (".{%dt", VEC_length (thread_p, entry->threads));
+      for (iy = 0; VEC_iterate (thread_p, entry->threads, iy, thr); ++iy)
+       printf_unfiltered (",%d", thr->num);
+      printf_unfiltered ("}");
+    }
+  printf_unfiltered ("}");
+  printf_unfiltered ("\n");
+}
+
 void
 _initialize_inferiors (void)
 {
-  add_info ("inferiors", info_inferiors_command,
-           _("IDs of currently known inferiors."));
+  add_com ("add-inferior", no_class, add_inferior_command, _("\
+Add more inferiors to be run for EXEC."));
+
+  add_com ("remove-inferior", no_class, remove_inferior_command, _("\
+Remove the inferiors in ITSET."));
+
+  add_com ("name-inferior", no_class, name_inferior_command, _("\
+Change the name of inferior OLDNAME to NEWNAME."));
+
+  add_com ("set-exec", no_class, set_inferior_exec_command, _("\
+Change the exec of inferiors in ITSET to EXECNAME"));
+
+  add_info ("inferiors", info_inferiors_command, _("\
+Info about currently known inferiors."));
 
   add_setshow_boolean_cmd ("inferior-events", no_class,
          &print_inferior_events, _("\
index aa582cb8a987d0d6ac5f97fa62a0ad32104d3f41..6b49bfc846bd60b5813d554ef45d14eaa78ed664 100644 (file)
@@ -30,6 +30,7 @@ struct type;
 struct gdbarch;
 struct regcache;
 struct ui_out;
+struct gdb_environ;
 
 /* For bpstat.  */
 #include "breakpoint.h"
@@ -40,6 +41,8 @@ struct ui_out;
 /* For struct frame_id.  */
 #include "frame.h"
 
+struct exec;
+
 /* Structure in which to save the status of the inferior.  Create/Save
    through "save_inferior_status", restore through
    "restore_inferior_status".
@@ -414,6 +417,21 @@ struct inferior
      the ptid_t.pid member of threads of this inferior.  */
   int pid;
 
+  char *name;
+
+  /* Nonzero if this inferior can be removed by the user.  */
+  int removable;
+
+  struct exec *exec;
+
+  char *args;
+  int argc;
+  char **argv;
+
+  struct gdb_environ *inf_environ;
+
+  char *io_terminal;
+
   /* See the definition of stop_kind above.  */
   enum stop_kind stop_soon;
 
@@ -430,6 +448,67 @@ struct inferior
   struct private_inferior *private;
 };
 
+typedef struct inferior *inferior_p;
+DEF_VEC_P(inferior_p);
+
+/* Scratchpad used to smuggle an inferior down to targets.  */
+extern struct inferior *tmp_inf;
+
+typedef struct thread_info *thread_p;
+DEF_VEC_P(thread_p);
+
+/* This struct is one entry in the i/t set's vectors of inferiors and
+   their associated threads.  */
+
+struct itset_entry
+{
+  /* The inferior for this entry.  */
+  struct inferior *inferior;
+
+  /* The vector of threads belonging to this inferior.  */
+  VEC(thread_p) *threads;
+};
+
+typedef struct itset_entry itset_entry;
+DEF_VEC_O(itset_entry);
+
+/* An inferior/thread set, or itset for short, is a collection of
+   inferiors (running or not) and threads associated with those
+   inferiors.  Itsets are used for various things, including to
+   restrict the effects of commands to only particular programs,
+   processes, or threads, and to set context and defaults for the
+   user. The syntax for itsets includes wildcards, range matching, and
+   lists, so that users can more easily choose the membership of a
+   set. For instance, "[4.*,5.6:5.9]" specifies all threads of process
+   4, and any threads with a number between 6 and 9, inclusive, in
+   process 5.  */
+
+struct itset
+{
+  /* A user-assigned name for the set. This will be NULL for unnamed
+     sets.  */
+  char *name;
+
+  /* True if the set is to be constructed on-the-fly.  */
+  int dynamic;
+
+  /* Instructions for construction of an itset.  */
+  char *spec;
+
+  /* The vector of inferiors belonging to this set.  */
+  VEC(itset_entry) *inferiors;
+
+  /* Pointer to the location of the next char in the spec string
+     during parsing.  */
+  char *parse_head;
+
+  /* Set to 1 when the spec has been parsed.  */
+  int parsed;
+
+  /* Any parse failures set this to 1.  */
+  int parse_errors;
+};
+
 /* Create an empty inferior list, or empty the existing one.  */
 extern void init_inferior_list (void);
 
@@ -497,8 +576,44 @@ extern void print_inferior (struct ui_out *uiout, int requested_inferior);
 /* Returns true if the inferior list is not empty.  */
 extern int have_inferiors (void);
 
+extern int have_real_inferiors (void);
+
+extern int number_of_inferiors (void);
+
+extern int number_of_inferiors (void);
+
 /* Return a pointer to the current inferior.  It is an error to call
    this if there is no current inferior.  */
 extern struct inferior *current_inferior (void);
 
+extern void set_inferior_name (struct inferior *inf, char *name);
+
+extern void set_inferior_exec (struct inferior *inf, struct exec *exec);
+
+extern void set_inferior_exec (struct inferior *inf, struct exec *exec);
+
+/* Itset definitions.  */
+
+extern struct itset *current_itset;
+
+extern struct itset *new_itset (char *spec);
+
+extern struct itset *make_itset_from_spec (char *spec);
+
+extern void update_itset (struct itset *itset);
+
+extern int itset_is_empty (struct itset *itset);
+
+extern int itset_member (struct itset *itset, struct inferior *inf, int thread_id);
+
+extern struct inferior *first_inferior_in_set (struct itset *itset);
+
+extern struct inferior *first_inferior_in_set (struct itset *itset);
+
+extern void dump_itset (struct itset *itset);
+
+extern struct inferior *inferior_list;
+
+extern struct inferior *inferior_list;
+
 #endif /* !defined (INFERIOR_H) */
index f218fa0e1f98d4bc1ea44261b932cdd56a730306..a459c97f6b680e5f0874cec2c3addbaa337aba32 100644 (file)
@@ -272,6 +272,9 @@ static struct
 }
 pending_follow;
 
+int detach_fork = 1;           /* Default behavior is to detach
+                                  newly forked processes (legacy).  */
+
 static const char follow_fork_mode_child[] = "child";
 static const char follow_fork_mode_parent[] = "parent";
 
index c92c57c536b96dea38ce1d3e04ebd22db19f5a1b..64cf27f70db63c7539d6c8bab62292bbc3ec71c7 100644 (file)
@@ -31,6 +31,7 @@ struct frame_info;
 struct expression;
 struct ui_file;
 struct value_print_options;
+struct exec;
 
 #define MAX_FORTRAN_DIMS  7    /* Maximum number of F77 array dims */
 
@@ -238,6 +239,7 @@ struct language_defn
     struct symbol *(*la_lookup_symbol_nonlocal) (const char *,
                                                 const char *,
                                                 const struct block *,
+                                                const struct exec *,
                                                 const domain_enum);
 
     /* Find the definition of the type with the given name.  */
index 8020cb539a6726305d556ca8d86dbf00edb0d8c5..38c8d5f3fcc0ec6e8844d9c6517772105c24001e 100644 (file)
 #include "symtab.h"
 #include "frame.h"
 #include "command.h"
+#include "exec.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "source.h"
+#include "inferior.h"
 #include "demangle.h"
 #include "value.h"
 #include "completer.h"
@@ -51,6 +53,8 @@ static void initialize_defaults (struct symtab **default_symtab,
 
 static void set_flags (char *arg, int *is_quoted, char **paren_pointer);
 
+extern struct exec *decode_sharp (char **argptr);
+
 static struct symtabs_and_lines decode_indirect (char **argptr);
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
@@ -129,6 +133,7 @@ static struct symtabs_and_lines decode_variable (char *copy,
                                                 int funfirstline,
                                                 char ***canonical,
                                                 struct symtab *file_symtab,
+                                                struct exec *exec,
                                                 int *not_found_ptr);
 
 static struct
@@ -393,6 +398,9 @@ build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
   char **canonical_arr;
   char *canonical_name;
   char *filename;
+  char *exec_name;
+  int exec_space;
+
   struct symtab *s = sal->symtab;
 
   if (s == (struct symtab *) NULL
@@ -403,16 +411,31 @@ build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
   canonical_arr = (char **) xmalloc (sizeof (char *));
   *canonical = canonical_arr;
 
+  /* Maybe add the exec's name to the front of the canonical name.  */
+  exec_name = NULL;
+  exec_space = 0;
+  if (number_of_execs () > 1
+      && s->objfile
+      && s->objfile->exec)
+    {
+      exec_name = s->objfile->exec->shortname;
+      exec_space = strlen (exec_name) + 2;
+    }
+
   filename = s->filename;
   if (symname != NULL)
     {
-      canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
-      sprintf (canonical_name, "%s:%s", filename, symname);
+      canonical_name = xmalloc (exec_space + strlen (filename) + strlen (symname) + 2);
+      if (exec_name)
+       sprintf (canonical_name, "#%s#", exec_name);
+      sprintf (canonical_name + exec_space, "%s:%s", filename, symname);
     }
   else
     {
-      canonical_name = xmalloc (strlen (filename) + 30);
-      sprintf (canonical_name, "%s:%d", filename, sal->line);
+      canonical_name = xmalloc (exec_space + strlen (filename) + 30);
+      if (exec_name)
+       sprintf (canonical_name, "#%s#", exec_name);
+      sprintf (canonical_name + exec_space, "%s:%d", filename, sal->line);
     }
   canonical_arr[0] = canonical_name;
 }
@@ -688,7 +711,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   char *q;
   /* If a file name is specified, this is its symtab.  */
   struct symtab *file_symtab = NULL;
-
+  struct exec *exec;
   char *copy;
   /* This is NULL if there are no parens in *ARGPTR, or a pointer to
      the closing parenthesis if there are parens.  */
@@ -707,7 +730,13 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   /* Defaults have defaults.  */
 
   initialize_defaults (&default_symtab, &default_line);
-  
+
+  /* Start with a plausible default for the executable.  */
+  exec = (number_of_execs () > 1 ? current_exec : NULL);
+
+  if (**argptr == '#')
+    exec = decode_sharp (argptr);
+
   /* See if arg is *PC.  */
 
   if (**argptr == '*')
@@ -876,7 +905,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
      If file specified, use that file's per-file block to start with.  */
 
   return decode_variable (copy, funfirstline, canonical,
-                         file_symtab, not_found_ptr);
+                         file_symtab, exec, not_found_ptr);
 }
 
 \f
@@ -964,6 +993,30 @@ set_flags (char *arg, int *is_quoted, char **paren_pointer)
 
 \f
 
+/* The #-sign introduces a specification of an executable.  */
+
+struct exec *
+decode_sharp (char **argptr)
+{
+  char *exec_spec, *spec_end;
+  struct exec *exec = NULL;
+
+  /* Skip over the '#'.  */
+  (*argptr)++;
+  exec_spec = *argptr;
+  spec_end = strchr (exec_spec, '#');
+  if (!spec_end)
+    error (_("Unmatched '#'."));
+  exec = find_exec_by_substr (exec_spec, spec_end);
+  if (!exec)
+    {
+      char *name = savestring (exec_spec, spec_end - exec_spec);
+      error (_("No exec named `%s'"), name);
+    }
+  *argptr = spec_end + 1;
+  return exec;
+}
+
 /* Decode arg of the form *PC.  */
 
 static struct symtabs_and_lines
@@ -971,7 +1024,7 @@ decode_indirect (char **argptr)
 {
   struct symtabs_and_lines values;
   CORE_ADDR pc;
-  
+
   (*argptr)++;
   pc = parse_and_eval_address_1 (argptr);
 
@@ -1740,23 +1793,24 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
 
 static struct symtabs_and_lines
 decode_variable (char *copy, int funfirstline, char ***canonical,
-                struct symtab *file_symtab, int *not_found_ptr)
+                struct symtab *file_symtab, struct exec *exec, int *not_found_ptr)
 {
   struct symbol *sym;
 
   struct minimal_symbol *msymbol;
 
-  sym = lookup_symbol (copy,
+  sym = lookup_symbol_in_exec (copy,
                       (file_symtab
                        ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
                                             STATIC_BLOCK)
                        : get_selected_block (0)),
+                      exec,
                       VAR_DOMAIN, 0);
 
   if (sym != NULL)
     return symbol_found (funfirstline, canonical, copy, sym, file_symtab);
 
-  msymbol = lookup_minimal_symbol (copy, NULL, NULL);
+  msymbol = lookup_minimal_symbol_in_exec (copy, NULL, exec);
 
   if (msymbol != NULL)
     return minsym_found (funfirstline, msymbol);
@@ -1805,9 +1859,14 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
        {
          struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym));
          struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-         if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
-           build_canonical_line_spec (values.sals, copy, canonical);
+         if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL
+             || number_of_execs () > 1)
+           {
+             build_canonical_line_spec (values.sals, copy, canonical);
+           }
        }
+      else if (number_of_execs () > 1)
+       build_canonical_line_spec (values.sals, copy, canonical);
       return values;
     }
   else
@@ -1823,6 +1882,8 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
          memset (&values.sals[0], 0, sizeof (values.sals[0]));
          values.sals[0].symtab = SYMBOL_SYMTAB (sym);
          values.sals[0].line = SYMBOL_LINE (sym);
+         if (number_of_execs () > 1)
+           build_canonical_line_spec (values.sals, copy, canonical);
          return values;
        }
       else
index f80fe5fa0a8317d2e5d5d646988a0a1f0d51643e..498db30189bee3446dca217beb4588a8bf6bf3ed 100644 (file)
 #include "gdb_dirent.h"
 #include <ctype.h>
 
+extern int detach_fork;
+
 struct fork_info *fork_list;
 static int highest_fork_num;
 
 /* Prevent warning from -Wmissing-prototypes.  */
 extern void _initialize_linux_fork (void);
 
-int detach_fork = 1;           /* Default behavior is to detach
-                                  newly forked processes (legacy).  */
-
 /* Fork list data structure:  */
 struct fork_info
 {
index cea1fc9041f9a10e4d38788ec23b6707ed941fdf..227ebb3fe77e72af56bb8ad49f532b97115c8977 100644 (file)
@@ -27,5 +27,3 @@ extern int  forks_exist_p (void);
 
 struct fork_info *fork_list;
 
-extern int detach_fork;
-
index 913bfecc659863d5d65b961c5ec23d9f198e64ea..6400dc3b9b6191af58cde00679bcb4da018684e0 100644 (file)
@@ -50,6 +50,8 @@
 #include "event-loop.h"
 #include "event-top.h"
 
+extern int detach_fork;
+
 #ifdef HAVE_PERSONALITY
 # include <sys/personality.h>
 # if !HAVE_DECL_ADDR_NO_RANDOMIZE
@@ -688,6 +690,8 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
   struct target_waitstatus last_status;
   int has_vforked;
   int parent_pid, child_pid;
+  struct inferior *child_inf, *parent_inf;
+  struct exec *parent_exec = NULL;
 
   if (target_can_async_p ())
     target_async (NULL, 0);
@@ -699,6 +703,10 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
     parent_pid = ptid_get_pid (last_ptid);
   child_pid = PIDGET (last_status.value.related_pid);
 
+  parent_inf = find_inferior_pid (parent_pid);
+  if (parent_inf)
+    parent_exec = parent_inf->exec;
+
   if (! follow_child)
     {
       /* We're already attached to the parent, by default. */
@@ -728,7 +736,9 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
          struct fork_info *fp;
 
          /* Add process to GDB's tables.  */
-         add_inferior (child_pid);
+         child_inf = add_inferior (child_pid);
+
+         set_inferior_exec (child_inf, parent_exec);
 
          /* Retain child fork in ptrace (stopped) state.  */
          fp = find_fork_pid (child_pid);
@@ -858,7 +868,9 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
        target_detach (NULL, 0);
 
       inferior_ptid = ptid_build (child_pid, child_pid, 0);
-      add_inferior (child_pid);
+      child_inf = add_inferior (child_pid);
+
+      set_inferior_exec (child_inf, parent_exec);
 
       /* Reinstall ourselves, since we might have been removed in
         target_detach (which does other necessary cleanup).  */
index 5f98e99b6710a6d62e61f23054c9b25dc90e36ea..02bc103e79c7ff662daa81b6216b05cd19c09b28 100644 (file)
@@ -28,6 +28,7 @@
 #include "bfd.h"
 #include "exceptions.h"
 #include "gdbthread.h"
+#include "exec.h"
 #include "inferior.h"
 #include "symfile.h"
 #include "objfiles.h"
@@ -474,11 +475,11 @@ enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp)
     return err;
 
   /* Set up the breakpoint.  */
-  gdb_assert (exec_bfd);
+  gdb_assert (first_exec && first_exec->ebfd);
   (*bp) = (gdbarch_convert_from_func_ptr_addr
           (current_gdbarch,
            /* Do proper sign extension for the target.  */
-           (bfd_get_sign_extend_vma (exec_bfd) > 0
+           (bfd_get_sign_extend_vma (first_exec->ebfd) > 0
             ? (CORE_ADDR) (intptr_t) notify.u.bptaddr
             : (CORE_ADDR) (uintptr_t) notify.u.bptaddr),
            &current_target));
@@ -1130,8 +1131,8 @@ thread_db_get_thread_local_address (ptid_t ptid,
 
       /* Cast assuming host == target.  Joy.  */
       /* Do proper sign extension for the target.  */
-      gdb_assert (exec_bfd);
-      return (bfd_get_sign_extend_vma (exec_bfd) > 0
+      gdb_assert (first_exec && first_exec->ebfd);
+      return (bfd_get_sign_extend_vma (first_exec->ebfd) > 0
              ? (CORE_ADDR) (intptr_t) address
              : (CORE_ADDR) (uintptr_t) address);
     }
index 15a6558d78ef6b958f0f973db3f52a685abcf190..8f4fd7f10c5e9a386265edfb36cbd37fdfce845a 100644 (file)
 #include "top.h"
 #include "target.h"
 #include "inferior.h"
+#include "exec.h"
+extern struct exec *last_exec_created;
 #include "symfile.h"
 #include "gdbcore.h"
-
+extern int is_core_file (char *filename);
 #include "exceptions.h"
 #include "getopt.h"
 
@@ -128,9 +130,10 @@ captured_main (void *data)
   char *execarg = NULL;
   char *pidarg = NULL;
   char *corearg = NULL;
-  char *pid_or_core_arg = NULL;
   char *cdarg = NULL;
   char *ttyarg = NULL;
+  char **miscargs = NULL;
+  int nmisc = 0;
 
   /* These are static so that we can take their address in an initializer.  */
   static int print_help;
@@ -182,6 +185,8 @@ captured_main (void *data)
   dirsize = 1;
   dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
   ndir = 0;
+  miscargs = (char **) xmalloc (argc * sizeof (char *));
+  nmisc = 0;
 
   quit_flag = 0;
   line = (char *) xmalloc (linesize);
@@ -566,34 +571,13 @@ extern int gdbtk_test (char *);
       }
     else
       {
-       /* OK, that's all the options.  */
-
-       /* The first argument, if specified, is the name of the
-          executable.  */
-       if (optind < argc)
+       /* OK, that's all the options. The remaining arguments will be
+          a mix of execnames, pids, and corefiles.  */
+       while (optind < argc)
          {
-           symarg = argv[optind];
-           execarg = argv[optind];
+           miscargs[nmisc++] = argv[optind];
            optind++;
          }
-
-       /* If the user hasn't already specified a PID or the name of a
-          core file, then a second optional argument is allowed.  If
-          present, this argument should be interpreted as either a
-          PID or a core file, whichever works.  */
-       if (pidarg == NULL && corearg == NULL && optind < argc)
-         {
-           pid_or_core_arg = argv[optind];
-           optind++;
-         }
-
-       /* Any argument left on the command line is unexpected and
-          will be ignored.  Inform the user.  */
-       if (optind < argc)
-         fprintf_unfiltered (gdb_stderr, _("\
-Excess command line arguments ignored. (%s%s)\n"),
-                             argv[optind],
-                             (optind == argc - 1) ? "" : " ...");
       }
     if (batch)
       quiet = 1;
@@ -735,6 +719,8 @@ Excess command line arguments ignored. (%s%s)\n"),
        catch_command_errors (symbol_file_add_main, symarg, 0, RETURN_MASK_ALL);
     }
 
+  last_exec_created = NULL;
+
   if (corearg && pidarg)
     error (_("\
 Can't attach to process and specify a core file at the same time."));
@@ -745,23 +731,48 @@ Can't attach to process and specify a core file at the same time."));
   else if (pidarg != NULL)
     catch_command_errors (attach_command, pidarg,
                          !batch, RETURN_MASK_ALL);
-  else if (pid_or_core_arg)
-    {
-      /* The user specified 'gdb program pid' or gdb program core'.
-        If pid_or_core_arg's first character is a digit, try attach
-        first and then corefile.  Otherwise try just corefile.  */
 
-      if (isdigit (pid_or_core_arg[0]))
-       {
-         if (catch_command_errors (attach_command, pid_or_core_arg,
-                                   !batch, RETURN_MASK_ALL) == 0)
-           catch_command_errors (core_file_command, pid_or_core_arg,
-                                 !batch, RETURN_MASK_ALL);
-       }
-      else /* Can't be a pid, better be a corefile.  */
-       catch_command_errors (core_file_command, pid_or_core_arg,
-                             !batch, RETURN_MASK_ALL);
-    }
+  /* Handle random mixes of executables, corefiles, and pids.  */
+  {
+    int require_exec = 1;
+    for (i = 0; i < nmisc; ++i)
+      {
+       if (!require_exec)
+         {
+           /* Digits might indicate a pid to attach to, so try that.  */
+           if (pidarg == NULL
+               && isdigit (*(miscargs[i]))
+               && (catch_command_errors (attach_command, miscargs[i],
+                                         !batch, RETURN_MASK_ALL)))
+             {
+               require_exec = 1;
+               continue;
+             }
+           /* OK, then maybe it's a corefile.  */
+           else if (corearg == NULL
+                    && is_core_file (miscargs[i])
+                    && catch_command_errors (core_file_command, miscargs[i],
+                                             0, RETURN_MASK_ALL))
+             {
+               require_exec = 1;
+               continue;
+             }
+           /* Presumably it's yet another executable, drop through.  */
+           else
+             require_exec = 1;
+         }
+       if (require_exec)
+         {
+           if (catch_command_errors (exec_file_add, miscargs[i], !batch,
+                                     RETURN_MASK_ALL))
+             catch_command_errors (symbol_file_add_main, miscargs[i], 0,
+                                   RETURN_MASK_ALL);
+           last_exec_created = NULL;
+           /* The executable may be followed by anything.  */
+           require_exec = 0;
+         }
+      }
+  }
 
   if (ttyarg != NULL)
     catch_command_errors (tty_command, ttyarg, !batch, RETURN_MASK_ALL);
index c46bdc0bbd58035d5bdac3a7b06fbf4067345213..4d8c7f945024b9389c8eac325cf1f2137efe8ec0 100644 (file)
@@ -32,6 +32,7 @@
 #include "gdbcore.h"
 #include "expression.h"                /* For language.h */
 #include "language.h"
+#include "exec.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "value.h"
@@ -359,36 +360,44 @@ print_objfile_section_info (bfd *abfd,
 static void
 maintenance_info_sections (char *arg, int from_tty)
 {
-  if (exec_bfd)
+  int allobj;
+  struct exec *exec;
+  int ix;
+
+  allobj = (arg && *arg && match_substring (arg, "ALLOBJ"));
+
+  for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
     {
       printf_filtered (_("Exec file:\n"));
-      printf_filtered ("    `%s', ", bfd_get_filename (exec_bfd));
+      printf_filtered ("    `%s', ", exec->name);
       wrap_here ("        ");
-      printf_filtered (_("file type %s.\n"), bfd_get_target (exec_bfd));
-      if (arg && *arg && match_substring (arg, "ALLOBJ"))
-       {
-         struct objfile *ofile;
-         struct obj_section *osect;
-
-         /* Only this function cares about the 'ALLOBJ' argument; 
-            if 'ALLOBJ' is the only argument, discard it rather than
-            passing it down to print_objfile_section_info (which 
-            wouldn't know how to handle it).  */
-         if (strcmp (arg, "ALLOBJ") == 0)
-           arg = NULL;
+      printf_filtered (_("file type %s.\n"), bfd_get_target (exec->ebfd));
+      if (!allobj)
+       bfd_map_over_sections (exec->ebfd, print_bfd_section_info, arg);
+    }
 
-         ALL_OBJFILES (ofile)
+  if (allobj)
+    {
+      struct objfile *ofile;
+      struct obj_section *osect;
+
+      /* Only this function cares about the 'ALLOBJ' argument; 
+        if 'ALLOBJ' is the only argument, discard it rather than
+        passing it down to print_objfile_section_info (which 
+        wouldn't know how to handle it).  */
+
+      if (strcmp (arg, "ALLOBJ") == 0)
+       arg = NULL;
+
+      ALL_OBJFILES (ofile)
+        {
+         printf_filtered (_("  Object file: %s\n"), 
+                          bfd_get_filename (ofile->obfd));
+         ALL_OBJFILE_OSECTIONS (ofile, osect)
            {
-             printf_filtered (_("  Object file: %s\n"), 
-                              bfd_get_filename (ofile->obfd));
-             ALL_OBJFILE_OSECTIONS (ofile, osect)
-               {
-                 print_objfile_section_info (ofile->obfd, osect, arg);
-               }
+             print_objfile_section_info (ofile->obfd, osect, arg);
            }
        }
-      else 
-       bfd_map_over_sections (exec_bfd, print_bfd_section_info, arg);
     }
 
   if (core_bfd)
@@ -843,6 +852,10 @@ If a SOURCE file is specified, dump only that file's partial symbols."),
           _("Print dump of current object file definitions."),
           &maintenanceprintlist);
 
+  add_cmd ("execs", class_maintenance, maintenance_print_execs,
+          _("Print dump of current executable file definitions."),
+          &maintenanceprintlist);
+
   add_cmd ("symtabs", class_maintenance, maintenance_info_symtabs, _("\
 List the full symbol tables for all object files.\n\
 This does not include information about individual symbols, blocks, or\n\
index f020cb56bf97d2aad3fecef0262944b980e954a5..9ebf9c23a18c0d4278a61fcfb8348181287bf5db 100644 (file)
@@ -174,9 +174,28 @@ msymbol_objfile (struct minimal_symbol *sym)
    Obviously, there must be distinct mangled names for each of these,
    but the demangled names are all the same: S::S or S::~S.  */
 
+extern struct minimal_symbol *lookup_minimal_symbol_in_exec_1 (const char *name,
+                                                              const char *sfile,
+                                                              struct objfile *objf,
+                                                              struct exec *exec);
+
 struct minimal_symbol *
 lookup_minimal_symbol (const char *name, const char *sfile,
                       struct objfile *objf)
+{
+  return lookup_minimal_symbol_in_exec_1 (name, sfile, objf, NULL);
+}
+
+struct minimal_symbol *
+lookup_minimal_symbol_in_exec (const char *name, const char *sfile,
+                              struct exec *exec)
+{
+  return lookup_minimal_symbol_in_exec_1 (name, sfile, NULL, exec);
+}
+
+struct minimal_symbol *
+lookup_minimal_symbol_in_exec_1 (const char *name, const char *sfile,
+                                struct objfile *objf, struct exec *exec)
 {
   struct objfile *objfile;
   struct minimal_symbol *msymbol;
@@ -198,6 +217,10 @@ lookup_minimal_symbol (const char *name, const char *sfile,
        objfile != NULL && found_symbol == NULL;
        objfile = objfile->next)
     {
+      /* If an exec is specified, limit to objfiles associated with it.  */
+      if (exec != NULL && exec != objfile->exec)
+       continue;
+
       if (objf == NULL || objf == objfile
          || objf->separate_debug_objfile == objfile)
        {
index d0aee52b8c48f9d4a6e331958298880ff916cc2a..9e935dd48747073635eff665d9081dac33161918 100644 (file)
@@ -201,6 +201,8 @@ allocate_objfile (bfd *abfd, int flags)
       objfile->name = xstrdup ("<<anonymous objfile>>");
     }
 
+  objfile->exec = NULL;
+
   /* Initialize the section indexes for this objfile, so that we can
      later detect if they are used w/o being properly assigned to. */
 
index fe42f549f5304cf44e158eba60664708c04ebe27..e9f4255b117644faa1fdba250ce79ed08f5db1a6 100644 (file)
 
 #include "gdb_obstack.h"       /* For obstack internals.  */
 #include "symfile.h"           /* For struct psymbol_allocation_list */
+#include "vec.h"
 
 struct bcache;
 struct htab;
 struct symtab;
 struct objfile_data;
+struct exec;
 
 /* This structure maintains information on a per-objfile basis about the
    "entry point" of the objfile, and the scope within which the entry point
@@ -200,6 +202,10 @@ struct objfile
 
     unsigned short flags;
 
+    /* The executable associated with this objfile, if known.  */
+
+    struct exec *exec;
+
     /* Each objfile points to a linked list of symtabs derived from this file,
        one symtab structure for each compilation unit (source file).  Each link
        in the symtab list contains a backpointer to this objfile. */
@@ -419,6 +425,9 @@ struct objfile
 
 extern struct objfile *symfile_objfile;
 
+typedef struct objfile *objfile_p;
+DEF_VEC_P(objfile_p);
+
 /* The object file that contains the runtime common minimal symbols
    for SunOS4. Note that this objfile has no associated BFD.  */
 
@@ -515,6 +524,10 @@ extern void *objfile_data (struct objfile *objfile,
        (obj) != NULL? ((nxt)=(obj)->next,1) :0;        \
        (obj) = (nxt))
 
+#define        ALL_OBJFILES_FOR_EXEC(obj,ex)                                   \
+  for ((obj) = object_files; (obj) != NULL; (obj) = (obj)->next)       \
+    if ((ex) == NULL || (obj)->exec == NULL || (obj)->exec == (ex))
+
 /* Traverse all symtabs in one objfile.  */
 
 #define        ALL_OBJFILE_SYMTABS(objfile, s) \
@@ -544,12 +557,21 @@ extern void *objfile_data (struct objfile *objfile,
     ALL_OBJFILE_SYMTABS (objfile, s)   \
       if ((s)->primary)
 
+#define ALL_PRIMARY_SYMTABS_FOR_EXEC(objfile, ex, s)   \
+  ALL_OBJFILES_FOR_EXEC (objfile, ex)                  \
+    ALL_OBJFILE_SYMTABS (objfile, s)   \
+      if ((s)->primary)
+
 /* Traverse all psymtabs in all objfiles.  */
 
 #define        ALL_PSYMTABS(objfile, p) \
   ALL_OBJFILES (objfile)        \
     ALL_OBJFILE_PSYMTABS (objfile, p)
 
+#define        ALL_PSYMTABS_FOR_EXEC(objfile, ex, p)   \
+  ALL_OBJFILES_FOR_EXEC (objfile, ex)          \
+    ALL_OBJFILE_PSYMTABS (objfile, p)
+
 /* Traverse all minimal symbols in all objfiles.  */
 
 #define        ALL_MSYMBOLS(objfile, m) \
index 4580c771f97ab18d03cab5610eac530c94003f7c..47eb98213abca0473e56686c6de5df05c17df6ed 100644 (file)
@@ -25,6 +25,7 @@
 #include "gdb_string.h"
 #include <ctype.h>
 #include <fcntl.h>
+#include "exec.h"
 #include "inferior.h"
 #include "bfd.h"
 #include "symfile.h"
@@ -2505,6 +2506,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
   struct start_remote_args *args = opaque;
   struct remote_state *rs = get_remote_state ();
   struct packet_config *noack_config;
+  struct inferior *inf;
   char *wait_status = NULL;
 
   immediate_quit++;            /* Allow user to interrupt it.  */
@@ -5680,7 +5682,14 @@ remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, int mem_len,
 {
   int res;
 
-  set_general_thread (inferior_ptid);
+  if (tmp_inf && tmp_inf->pid != ptid_get_pid (inferior_ptid))
+    {
+      ptid_t tmp_ptid;
+      tmp_ptid = ptid_build (tmp_inf->pid, 0, 0);
+      set_general_thread (tmp_ptid);
+    }
+  else
+    set_general_thread (inferior_ptid);
 
   if (should_write)
     res = remote_write_bytes (mem_addr, buffer, mem_len);
@@ -6661,6 +6670,8 @@ static void
 extended_remote_create_inferior_1 (char *exec_file, char *args,
                                   char **env, int from_tty)
 {
+  struct inferior *inf;
+
   /* If running asynchronously, register the target file descriptor
      with the event loop.  */
   if (target_can_async_p ())
@@ -6692,7 +6703,10 @@ extended_remote_create_inferior_1 (char *exec_file, char *args,
   /* Now, if we have thread information, update inferior_ptid.  */
   inferior_ptid = remote_current_thread (inferior_ptid);
 
-  add_inferior (ptid_get_pid (inferior_ptid));
+  inf = add_inferior (ptid_get_pid (inferior_ptid));
+
+  set_inferior_exec (inf, find_exec_by_name (exec_file));
+
   add_thread_silent (inferior_ptid);
 
   target_mark_running (&extended_remote_ops);
@@ -7249,7 +7263,15 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
   char *p2;
   char query_type;
 
-  set_general_thread (inferior_ptid);
+  
+  if (tmp_inf && tmp_inf->pid != ptid_get_pid (inferior_ptid))
+    {
+      ptid_t tmp_ptid;
+      tmp_ptid = ptid_build (tmp_inf->pid, 0, 0);
+      set_general_thread (tmp_ptid);
+    }
+  else
+    set_general_thread (inferior_ptid);
 
   rs = get_remote_state ();
 
index 006f28063a828047aee8e89d6f80a32c399a6326..033d3dedffde1190a8bbea76b24c4e3ffff8021e 100644 (file)
@@ -63,9 +63,9 @@ scm_inferior_print (LONGEST value, struct ui_file *stream,
     {
       /* XXX: Should we cache these symbols?  */
       gdb_output_sym =
-       lookup_symbol_global ("gdb_output", NULL, NULL, VAR_DOMAIN);
+       lookup_symbol_global ("gdb_output", NULL, NULL, NULL, VAR_DOMAIN);
       gdb_output_len_sym =
-       lookup_symbol_global ("gdb_output_length", NULL, NULL, VAR_DOMAIN);
+       lookup_symbol_global ("gdb_output_length", NULL, NULL, NULL, VAR_DOMAIN);
 
       if ((gdb_output_sym == NULL) || (gdb_output_len_sym == NULL))
        ret = -1;
index d04a9071c10e64ca5768c02540dcaac899c4720b..aa709312c78021a1d009768193397df3a96db7d1 100644 (file)
@@ -866,8 +866,8 @@ clear_solib (void)
      around to it.
 
      So: disable breakpoints only if we're using ELF shared libs.  */
-  if (exec_bfd != NULL
-      && bfd_get_flavour (exec_bfd) != bfd_target_aout_flavour)
+  if (first_exec != NULL
+      && bfd_get_flavour (first_exec->ebfd) != bfd_target_aout_flavour)
     disable_breakpoints_in_shlibs ();
 
   while (so_list_head)
index c41c193039cd020016fbc0a445309a0841f4b42b..f23b07b0ab00eb74fd5ba76dad27c8b445daacf5 100644 (file)
@@ -35,6 +35,7 @@
 #include <fcntl.h>
 #include "gdbcore.h"
 #include "gdb_regex.h"
+#include "exec.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "annotate.h"
@@ -239,7 +240,7 @@ select_source_symtab (struct symtab *s)
 
   /* Make the default place to list be the function `main'
      if one exists.  */
-  if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0))
+  if (lookup_symbol_in_exec (main_name (), 0, current_exec, VAR_DOMAIN, 0))
     {
       sals = decode_line_spec (main_name (), 1);
       sal = sals.sals[0];
@@ -255,7 +256,7 @@ select_source_symtab (struct symtab *s)
 
   current_source_line = 1;
 
-  for (ofp = object_files; ofp != NULL; ofp = ofp->next)
+  ALL_OBJFILES_FOR_EXEC (ofp, current_exec)
     {
       for (s = ofp->symtabs; s; s = s->next)
        {
@@ -271,7 +272,7 @@ select_source_symtab (struct symtab *s)
 
   /* How about the partial symbol tables?  */
 
-  for (ofp = object_files; ofp != NULL; ofp = ofp->next)
+  ALL_OBJFILES_FOR_EXEC (ofp, current_exec)
     {
       for (ps = ofp->psymtabs; ps != NULL; ps = ps->next)
        {
@@ -1125,8 +1126,8 @@ find_source_lines (struct symtab *s, int desc)
 
   if (s->objfile && s->objfile->obfd)
     mtime = s->objfile->mtime;
-  else if (exec_bfd)
-    mtime = exec_bfd_mtime;
+  else if (s->objfile && s->objfile->exec)
+    mtime = s->objfile->exec->ebfd_mtime;
 
   if (mtime && mtime < st.st_mtime)
     warning (_("Source file is more recent than executable."));
index d9aff2f1e1c50cbeea03da3f916c3b2d687e0fbf..7e2b568d472fc51be76deabb62dee15881d85cc5 100644 (file)
@@ -49,6 +49,7 @@
 #include "block.h"
 #include "observer.h"
 #include "exec.h"
+extern struct exec *last_exec_created;
 #include "parser-defs.h"
 #include "varobj.h"
 #include "elf-bfd.h"
@@ -790,8 +791,8 @@ syms_from_objfile (struct objfile *objfile,
       make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
 
       /* Since no error yet, throw away the old symbol table.  */
-
-      if (symfile_objfile != NULL)
+      /* (But not in the multiprocess case.)  */
+      if (symfile_objfile != NULL && number_of_execs () <= 1)
        {
          free_objfile (symfile_objfile);
          symfile_objfile = NULL;
@@ -917,6 +918,16 @@ new_symfile_objfile (struct objfile *objfile, int mainline, int verbo)
       /* OK, make it the "real" symbol file.  */
       symfile_objfile = objfile;
 
+      /* Use the exec object smuggled through this global (a
+        workaround due to the inability of command processing in
+        main.c to pass additional arguments).  */
+      if (last_exec_created)
+       {
+         last_exec_created->objfile = objfile;
+         objfile->exec = last_exec_created;
+         last_exec_created = NULL;
+       }
+
       clear_symtab_users ();
     }
   else
@@ -1149,10 +1160,7 @@ symbol_file_clear (int from_tty)
 {
   if ((have_full_symbols () || have_partial_symbols ())
       && from_tty
-      && (symfile_objfile
-         ? !query (_("Discard symbol table from `%s'? "),
-                   symfile_objfile->name)
-         : !query (_("Discard symbol table? "))))
+      && !query (_("Discard all symbol tables? ")))
     error (_("Not confirmed."));
     free_all_objfiles ();
 
@@ -1164,7 +1172,7 @@ symbol_file_clear (int from_tty)
 
     symfile_objfile = NULL;
     if (from_tty)
-      printf_unfiltered (_("No symbol file now.\n"));
+      printf_unfiltered (_("No symbol files now.\n"));
 }
 
 struct build_id
@@ -2303,13 +2311,11 @@ reread_symbols (void)
              /* We need to do this whenever any symbols go away.  */
              make_cleanup (clear_symtab_users_cleanup, 0 /*ignore*/);
 
-             if (exec_bfd != NULL && strcmp (bfd_get_filename (objfile->obfd),
-                                             bfd_get_filename (exec_bfd)) == 0)
-               {
-                 /* Reload EXEC_BFD without asking anything.  */
-
-                 exec_file_attach (bfd_get_filename (objfile->obfd), 0);
-               }
+             /* If this objfile is also one of our executables,
+                update that.  */
+             if (objfile->exec
+                 && objfile->exec->objfile == objfile)
+               exec_file_update (objfile->exec);
 
              /* Clean up any state BFD has sitting around.  We don't need
                 to close the descriptor but BFD lacks a way of closing the
@@ -3196,6 +3202,32 @@ init_psymbol_list (struct objfile *objfile, int total_symbols)
     }
 }
 
+/* Given a pc and inferior, return a section.  */
+
+struct obj_section *
+find_pc_inf_sect (CORE_ADDR pc, struct inferior *inf)
+{
+  struct objfile *objfile;
+  struct obj_section *osect;
+  asection *section;
+  int size;
+
+  ALL_OBJSECTIONS (objfile, osect)
+    {
+      if (!inf || objfile->exec == inf->exec)
+       {
+         section = osect->the_bfd_section;
+         if (section)
+           {
+             size = bfd_get_section_size (section);
+             if (section->vma <= pc && pc < section->vma + size)
+               return osect;
+           }
+       }
+    }
+  return NULL;
+}
+
 /* OVERLAYS:
    The following code implements an abstraction for debugging overlay sections.
 
index f0087d0e317d61a7ebbf57d94c064872f94abf19..b74572b16a69bf11538a162e7bec5f055aa1268e 100644 (file)
@@ -309,6 +309,8 @@ extern bfd *symfile_bfd_open (char *);
 
 extern int get_section_index (struct objfile *, char *);
 
+extern struct obj_section *find_pc_inf_sect (CORE_ADDR, struct inferior *);
+
 /* Utility functions for overlay sections: */
 extern enum overlay_debugging_state
 {
index ae524482ed78e2e00751af7b23671b55662a0145..0169eae69656abc5d0ab038bc6dc7aa3c810a4ee 100644 (file)
@@ -23,6 +23,7 @@
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "bfd.h"
+#include "exec.h"
 #include "symfile.h"
 #include "objfiles.h"
 #include "breakpoint.h"
@@ -213,8 +214,13 @@ dump_objfile (struct objfile *objfile)
   gdb_print_host_address (objfile, gdb_stdout);
   printf_filtered (", bfd at ");
   gdb_print_host_address (objfile->obfd, gdb_stdout);
-  printf_filtered (", %d minsyms\n\n",
+  printf_filtered (", %d minsyms\n",
                   objfile->minimal_symbol_count);
+  if (objfile->exec)
+    printf_filtered ("  Exec file %s", objfile->exec->name);
+  else
+    printf_filtered ("  (No exec file)");
+  printf_filtered ("\n\n");
 
   if (objfile->psymtabs)
     {
@@ -916,6 +922,10 @@ maintenance_print_objfiles (char *ignore, int from_tty)
   immediate_quit++;
   ALL_OBJFILES (objfile)
     dump_objfile (objfile);
+  printf_filtered ("Symfile_objfile is %s, at ",
+                  (symfile_objfile ? symfile_objfile->name : "(null)"));
+  gdb_print_host_address (symfile_objfile, gdb_stdout);
+  printf_filtered ("\n");
   immediate_quit--;
 }
 
index 3af3e8a00129b855a09d344a28450931b5c955f9..1631188c5513ec1bea2aae248e3c65dca7f691ae 100644 (file)
@@ -28,6 +28,7 @@
 #include "value.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "exec.h"
 #include "gdbcmd.h"
 #include "call-cmds.h"
 #include "gdb_regex.h"
@@ -86,6 +87,7 @@ char *operator_chars (char *p, char **end);
 static struct symbol *lookup_symbol_aux (const char *name,
                                         const char *linkage_name,
                                         const struct block *block,
+                                        const struct exec *exec,
                                         const domain_enum domain,
                                         enum language language,
                                         int *is_a_field_of_this);
@@ -100,12 +102,14 @@ static
 struct symbol *lookup_symbol_aux_symtabs (int block_index,
                                          const char *name,
                                          const char *linkage_name,
+                                         const struct exec *exec,
                                          const domain_enum domain);
 
 static
 struct symbol *lookup_symbol_aux_psymtabs (int block_index,
                                           const char *name,
                                           const char *linkage_name,
+                                          const struct exec *exec,
                                           const domain_enum domain);
 
 static int file_matches (char *, char **, int);
@@ -697,6 +701,7 @@ init_sal (struct symtab_and_line *sal)
   sal->line = 0;
   sal->pc = 0;
   sal->end = 0;
+  sal->inferior = NULL;
   sal->explicit_pc = 0;
   sal->explicit_line = 0;
 }
@@ -852,6 +857,7 @@ struct partial_symtab *
 find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
 {
   struct objfile *objfile;
+  struct exec *exec;
   struct minimal_symbol *msymbol;
 
   /* If we know that this is not a text address, return failure.  This is
@@ -868,8 +874,22 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
 
   /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
      than the later used TEXTLOW/TEXTHIGH one.  */
+  exec = NULL;
+#if 0
+  if (section)
+    {
+      int ix;
+      struct exec *ex;
+      for (ix = 0; VEC_iterate(exec_p, execs, ix, ex); ++ix)
+       if (strcmp (section->owner->filename, ex->ebfd->filename) == 0)
+         {
+           exec = ex;
+           break;
+         }
+    }
+#endif
 
-  ALL_OBJFILES (objfile)
+  ALL_OBJFILES_FOR_EXEC (objfile, exec)
     if (objfile->psymtabs_addrmap != NULL)
       {
        struct partial_symtab *pst;
@@ -909,7 +929,7 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
      present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
      so far.  */
 
-  ALL_OBJFILES (objfile)
+  ALL_OBJFILES_FOR_EXEC (objfile, exec)
     {
       struct partial_symtab *pst;
 
@@ -1189,10 +1209,36 @@ fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
    variable and thus can probably assume it will never hit the C++
    code).  */
 
+extern struct symbol *
+lookup_symbol_in_language_1 (const char *name, const struct block *block,
+                            const struct exec *exec,
+                            const domain_enum domain, enum language lang,
+                            int *is_a_field_of_this);
+
 struct symbol *
 lookup_symbol_in_language (const char *name, const struct block *block,
                           const domain_enum domain, enum language lang,
                           int *is_a_field_of_this)
+{
+  return lookup_symbol_in_language_1 (name, block, current_exec, domain, lang,
+                                     is_a_field_of_this);
+}
+
+struct symbol *
+lookup_symbol_in_exec_in_language (const char *name, const struct block *block,
+                                  const struct exec *exec,
+                                  const domain_enum domain, enum language lang,
+                                  int *is_a_field_of_this)
+{
+  return lookup_symbol_in_language_1 (name, block, exec, domain, lang,
+                                     is_a_field_of_this);
+}
+
+struct symbol *
+lookup_symbol_in_language_1 (const char *name, const struct block *block,
+                            const struct exec *exec,
+                            const domain_enum domain, enum language lang,
+                            int *is_a_field_of_this)
 {
   char *demangled_name = NULL;
   const char *modified_name = NULL;
@@ -1239,7 +1285,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,
       modified_name = copy;
     }
 
-  returnval = lookup_symbol_aux (modified_name, mangled_name, block,
+  returnval = lookup_symbol_aux (modified_name, mangled_name, block, exec,
                                 domain, lang, is_a_field_of_this);
   if (needtofreename)
     xfree (demangled_name);
@@ -1254,11 +1300,35 @@ struct symbol *
 lookup_symbol (const char *name, const struct block *block,
               domain_enum domain, int *is_a_field_of_this)
 {
+  if (*name == '#')
+    {
+      char *name2 = strchr (name + 1, '#');
+      struct exec *exec = current_exec;
+
+      if (name2)
+       {
+         exec = find_exec_by_substr (((char *) name) + 1, name2);
+         return lookup_symbol_in_exec_in_language (name2 + 1, block, exec, domain,
+                                                   current_language->la_language,
+                                                   is_a_field_of_this);
+       }
+    }
+
   return lookup_symbol_in_language (name, block, domain,
                                    current_language->la_language,
                                    is_a_field_of_this);
 }
 
+struct symbol *
+lookup_symbol_in_exec (const char *name, const struct block *block,
+                      const struct exec *exec,
+                      domain_enum domain, int *is_a_field_of_this)
+{
+  return lookup_symbol_in_exec_in_language (name, block, exec, domain,
+                                           current_language->la_language,
+                                           is_a_field_of_this);
+}
+
 /* Behave like lookup_symbol except that NAME is the natural name
    of the symbol that we're looking for and, if LINKAGE_NAME is
    non-NULL, ensure that the symbol's linkage name matches as
@@ -1266,7 +1336,8 @@ lookup_symbol (const char *name, const struct block *block,
 
 static struct symbol *
 lookup_symbol_aux (const char *name, const char *linkage_name,
-                  const struct block *block, const domain_enum domain,
+                  const struct block *block, const struct exec *exec,
+                  const domain_enum domain,
                   enum language language, int *is_a_field_of_this)
 {
   struct symbol *sym;
@@ -1331,7 +1402,7 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
   /* Now do whatever is appropriate for LANGUAGE to look
      up static and global variables.  */
 
-  sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name, block, domain);
+  sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name, block, exec, domain);
   if (sym != NULL)
     return sym;
 
@@ -1341,11 +1412,11 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
      desired name as a file-level static, then do psymtab-to-symtab
      conversion on the fly and return the found symbol. */
 
-  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, linkage_name, domain);
+  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, linkage_name, exec, domain);
   if (sym != NULL)
     return sym;
   
-  sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, linkage_name, domain);
+  sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, linkage_name, exec, domain);
   if (sym != NULL)
     return sym;
 
@@ -1479,6 +1550,7 @@ lookup_global_symbol_from_objfile (const struct objfile *objfile,
 static struct symbol *
 lookup_symbol_aux_symtabs (int block_index,
                           const char *name, const char *linkage_name,
+                          const struct exec *exec,                        
                           const domain_enum domain)
 {
   struct symbol *sym;
@@ -1487,7 +1559,7 @@ lookup_symbol_aux_symtabs (int block_index,
   const struct block *block;
   struct symtab *s;
 
-  ALL_PRIMARY_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS_FOR_EXEC (objfile, exec, s)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, block_index);
@@ -1510,6 +1582,7 @@ lookup_symbol_aux_symtabs (int block_index,
 static struct symbol *
 lookup_symbol_aux_psymtabs (int block_index, const char *name,
                            const char *linkage_name,
+                           const struct exec *exec,
                            const domain_enum domain)
 {
   struct symbol *sym;
@@ -1520,7 +1593,7 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name,
   struct symtab *s;
   const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
 
-  ALL_PSYMTABS (objfile, ps)
+  ALL_PSYMTABS_FOR_EXEC (objfile, exec, ps)
   {
     if (!ps->readin
        && lookup_partial_symbol (ps, name, linkage_name,
@@ -1567,6 +1640,7 @@ struct symbol *
 basic_lookup_symbol_nonlocal (const char *name,
                              const char *linkage_name,
                              const struct block *block,
+                             const struct exec *exec,
                              const domain_enum domain)
 {
   struct symbol *sym;
@@ -1599,11 +1673,11 @@ basic_lookup_symbol_nonlocal (const char *name,
      than that one, so I don't think we should worry about that for
      now.  */
 
-  sym = lookup_symbol_static (name, linkage_name, block, domain);
+  sym = lookup_symbol_static (name, linkage_name, block, exec, domain);
   if (sym != NULL)
     return sym;
 
-  return lookup_symbol_global (name, linkage_name, block, domain);
+  return lookup_symbol_global (name, linkage_name, block, exec, domain);
 }
 
 /* Lookup a symbol in the static block associated to BLOCK, if there
@@ -1613,6 +1687,7 @@ struct symbol *
 lookup_symbol_static (const char *name,
                      const char *linkage_name,
                      const struct block *block,
+                     const struct exec *exec,
                      const domain_enum domain)
 {
   const struct block *static_block = block_static_block (block);
@@ -1630,6 +1705,7 @@ struct symbol *
 lookup_symbol_global (const char *name,
                      const char *linkage_name,
                      const struct block *block,
+                     const struct exec *exec,
                      const domain_enum domain)
 {
   struct symbol *sym = NULL;
@@ -1642,11 +1718,11 @@ lookup_symbol_global (const char *name,
   if (sym != NULL)
     return sym;
 
-  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name, exec, domain);
   if (sym != NULL)
     return sym;
 
-  return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+  return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name, exec, domain);
 }
 
 int
@@ -1794,7 +1870,7 @@ basic_lookup_transparent_type (const char *name)
      of the desired name as a global, then do psymtab-to-symtab
      conversion on the fly and return the found symbol.  */
 
-  ALL_PRIMARY_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS_FOR_EXEC (objfile, current_exec, s)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
@@ -1842,7 +1918,7 @@ basic_lookup_transparent_type (const char *name)
      conversion on the fly and return the found symbol.
    */
 
-  ALL_PRIMARY_SYMTABS (objfile, s)
+  ALL_PRIMARY_SYMTABS_FOR_EXEC (objfile, current_exec, s)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
@@ -1983,6 +2059,7 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
   struct symtab *best_s = NULL;
   struct partial_symtab *ps;
   struct objfile *objfile;
+  struct exec *exec;
   CORE_ADDR distance = 0;
   struct minimal_symbol *msymbol;
 
@@ -2015,7 +2092,22 @@ find_pc_sect_symtab (CORE_ADDR pc, struct obj_section *section)
      It also happens for objfiles that have their functions reordered.
      For these, the symtab we are looking for is not necessarily read in.  */
 
-  ALL_PRIMARY_SYMTABS (objfile, s)
+  exec = NULL;
+#if 0
+  if (section)
+    {
+      int ix;
+      struct exec *ex;
+      for (ix = 0; VEC_iterate(exec_p, execs, ix, ex); ++ix)
+       if (strcmp (section->owner->filename, ex->ebfd->filename) == 0)
+         {
+           exec = ex;
+           break;
+         }
+    }
+#endif
+
+  ALL_PRIMARY_SYMTABS_FOR_EXEC (objfile, exec, s)
   {
     bv = BLOCKVECTOR (s);
     b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
@@ -2335,6 +2427,38 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
   return val;
 }
 
+struct symtab_and_line
+find_pc_inf_line (CORE_ADDR pc, struct inferior *inf, int notcurrent)
+{
+  struct objfile *objfile;
+  struct obj_section *osect;
+  asection *section;
+  int size;
+  struct symtab_and_line sal;
+
+  if (!inf || number_of_execs () <= 1)
+    return find_pc_line (pc, notcurrent);
+
+  ALL_OBJSECTIONS (objfile, osect)
+    {
+      if (objfile->exec == inf->exec)
+       {
+         section = osect->the_bfd_section;
+         if (section)
+           {
+             size = bfd_get_section_size (section);
+             if (section->vma <= pc && pc < section->vma + size)
+               {
+                 sal = find_pc_sect_line (pc, osect, notcurrent);
+                 sal.inferior = inf;
+                 return sal;
+               }
+           }
+       }
+    }
+  return find_pc_line (pc, notcurrent);
+}
+
 /* Backward compatibility (no section) */
 
 struct symtab_and_line
@@ -2607,8 +2731,10 @@ find_function_start_sal (struct symbol *sym, int funfirstline)
   fixup_symbol_section (sym, objfile);
   if (funfirstline)
     {
+      tmp_inf = ((objfile && objfile->exec) ? objfile->exec->inferior : NULL);
       /* Skip "first line" of function (which is actually its prologue).  */
       pc = find_function_start_pc (gdbarch, pc, SYMBOL_OBJ_SECTION (sym));
+      tmp_inf = NULL;
     }
   sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
 
@@ -4420,23 +4546,25 @@ symtab_observer_executable_changed (void)
 
 /* Helper to expand_line_sal below.  Appends new sal to SAL,
    initializing it from SYMTAB, LINENO and PC.  */
-static void
+/*static*/ struct symtab_and_line *
 append_expanded_sal (struct symtabs_and_lines *sal,
                     struct symtab *symtab,
                     int lineno, CORE_ADDR pc)
 {
-  CORE_ADDR func_addr, func_end;
+  struct symtab_and_line *new_sal;
   
   sal->sals = xrealloc (sal->sals, 
                        sizeof (sal->sals[0]) 
                        * (sal->nelts + 1));
-  init_sal (sal->sals + sal->nelts);
-  sal->sals[sal->nelts].symtab = symtab;
-  sal->sals[sal->nelts].section = NULL;
-  sal->sals[sal->nelts].end = 0;
-  sal->sals[sal->nelts].line = lineno;  
-  sal->sals[sal->nelts].pc = pc;
+  new_sal = sal->sals + sal->nelts;
+  init_sal (new_sal);
+  new_sal->symtab = symtab;
+  new_sal->section = NULL;
+  new_sal->end = 0;
+  new_sal->line = lineno;  
+  new_sal->pc = pc;
   ++sal->nelts;      
+  return new_sal;
 }
 
 /* Compute a set of all sals in
@@ -4519,6 +4647,7 @@ expand_line_sal (struct symtab_and_line sal)
                    {
                      exact = 1;
                      append_expanded_sal (&ret, symtab, lineno, item->pc);
+                     ret.sals[ret.nelts-1].section = sal.section;
                    }      
                  else if (!exact && item->line > lineno
                           && (best_item == NULL || item->line < best_item->line))
@@ -4548,7 +4677,7 @@ expand_line_sal (struct symtab_and_line sal)
   for (i = 0; i < ret.nelts; ++i)
     {
       filter[i] = 1;
-      blocks[i] = block_for_pc (ret.sals[i].pc);
+      blocks[i] = block_for_pc_sect (ret.sals[i].pc, ret.sals[i].section);
     }
 
   for (i = 0; i < ret.nelts; ++i)
index a1dee4fceb061784b343e14fef667251dca4236f..cf60f2022c59af9404067518e655bd6af14e19fa 100644 (file)
@@ -32,6 +32,8 @@ struct block;
 struct blockvector;
 struct axs_value;
 struct agent_expr;
+struct exec;
+struct inferior;
 
 /* Some of the structures in this file are space critical.
    The space-critical structures are:
@@ -945,18 +947,30 @@ extern struct symbol *lookup_symbol_in_language (const char *,
                                                 enum language,
                                                 int *);
 
+extern struct symbol *lookup_symbol_in_exec_in_language (const char *,
+                                                        const struct block *,
+                                                        const struct exec *,
+                                                        const domain_enum,
+                                                        enum language,
+                                                        int *);
+
 /* lookup a symbol by name (optional block, optional symtab)
    in the current language */
 
 extern struct symbol *lookup_symbol (const char *, const struct block *,
                                     const domain_enum, int *);
 
+extern struct symbol *lookup_symbol_in_exec (const char *, const struct block *,
+                                            const struct exec *,
+                                            const domain_enum, int *);
+
 /* A default version of lookup_symbol_nonlocal for use by languages
    that can't think of anything better to do.  */
 
 extern struct symbol *basic_lookup_symbol_nonlocal (const char *,
                                                    const char *,
                                                    const struct block *,
+                                                   const struct exec *,
                                                    const domain_enum);
 
 /* Some helper functions for languages that need to write their own
@@ -968,6 +982,7 @@ extern struct symbol *basic_lookup_symbol_nonlocal (const char *,
 extern struct symbol *lookup_symbol_static (const char *name,
                                            const char *linkage_name,
                                            const struct block *block,
+                                           const struct exec *exec,
                                            const domain_enum domain);
 
 /* Lookup a symbol in all files' global blocks (searching psymtabs if
@@ -976,6 +991,7 @@ extern struct symbol *lookup_symbol_static (const char *name,
 extern struct symbol *lookup_symbol_global (const char *name,
                                            const char *linkage_name,
                                            const struct block *block,
+                                           const struct exec *exec,
                                            const domain_enum domain);
 
 /* Lookup a symbol within the block BLOCK.  This, unlike
@@ -1103,6 +1119,10 @@ extern struct minimal_symbol *lookup_minimal_symbol (const char *,
                                                     const char *,
                                                     struct objfile *);
 
+extern struct minimal_symbol *lookup_minimal_symbol_in_exec (const char *,
+                                                            const char *,
+                                                            struct exec *);
+
 extern struct minimal_symbol *lookup_minimal_symbol_text (const char *,
                                                          struct objfile *);
 
@@ -1144,6 +1164,7 @@ struct symtab_and_line
 
   CORE_ADDR pc;
   CORE_ADDR end;
+  struct inferior *inferior;
   int explicit_pc;
   int explicit_line;
 };
@@ -1182,6 +1203,8 @@ extern struct symtab_and_line find_pc_line (CORE_ADDR, int);
 extern struct symtab_and_line find_pc_sect_line (CORE_ADDR,
                                                 struct obj_section *, int);
 
+extern struct symtab_and_line find_pc_inf_line (CORE_ADDR, struct inferior *, int);
+
 /* Given a symtab and line number, return the pc there.  */
 
 extern int find_line_pc (struct symtab *, int, CORE_ADDR *);
index 3901ee7585b4bdb1c7372a4a355d9309f69a27a0..4a5905c611aa736d8d563dd7dcf822a38e69150f 100644 (file)
@@ -30,6 +30,7 @@
 #include "inferior.h"
 #include "bfd.h"
 #include "symfile.h"
+#include "exec.h"
 #include "objfiles.h"
 #include "gdb_wait.h"
 #include "dcache.h"
@@ -2268,6 +2269,8 @@ target_resize_to_sections (struct target_ops *target, int num_added)
   struct target_ops **t;
   struct section_table *old_value;
   int old_count;
+  struct exec *exec;
+  int ix;
 
   old_value = target->to_sections;
 
@@ -2307,6 +2310,15 @@ target_resize_to_sections (struct target_ops *target, int num_added)
          current_target.to_sections = target->to_sections;
          current_target.to_sections_end = target->to_sections_end;
        }
+      
+      for (ix = 0; VEC_iterate (exec_p, execs, ix, exec); ++ix)
+       {
+         if (exec->sections == old_value)
+           {
+             exec->sections = target->to_sections;
+             exec->sections_end = target->to_sections_end;
+           }
+       }
     }
 
   return old_count;
index 05b681d0447ced9b26e3ef6c13531e2d0411d19e..ade81cb6e686dcabc652429def5caa9cf1d5fc2f 100644 (file)
@@ -24,6 +24,7 @@
 #if !defined (TARGET_H)
 #define TARGET_H
 
+struct exec;
 struct objfile;
 struct ui_file;
 struct mem_attrib;
@@ -733,7 +734,7 @@ extern int inferior_has_execd (ptid_t pid, char **execd_pathname);
 
 /* From exec.c */
 
-extern void print_section_info (struct target_ops *, bfd *);
+extern void print_section_info (struct target_ops *, bfd *, struct exec *);
 
 /* Print a line about the current target.  */
 
index a7378724e4ea86064db69138b4a1941c74380266..947e5fe9b6326a3f7aa3eac13455260a06040733 100644 (file)
@@ -1,3 +1,23 @@
+2008-11-20  Stan Shebs  <stan@codesourcery.com>
+
+       2008-09-14  Stan Shebs  <stan@codesourcery.com>
+
+       * gdb.gdb/selftest.exp: Update to reflect current sources.
+       * Makefile.in (ALL_SUBDIRS): Add gdb.multi.
+       * configure.ac (AC_OUTPUT): Add gdb.multi/Makefile.
+       * configure: Regenerate.
+
+       * gdb.multi/Makefile.in: New.
+       * gdb.multi/hello.c, hangout.c, goodbye.c: New source files.
+       * gdb.multi/base.exp: New file, basic multiprocess tests.
+
+       2008-08-25  Stan Shebs  <stan@codesourcery.com>
+
+       * config/monitor.exp: Match on rephrased message.
+       * gdb.base/attach.exp: Ditto.
+       * gdb.base/default.exp: Ditto.
+       * lib/gdb.exp: Ditto.
+
 2008-11-18  Thiago Jung Bauermann  <bauerman@br.ibm.com>
 
        * gdb.arch/ppc-dfp.exp: New file.
index 11fc26efe61c22d67cd0dd3e94e3ac5cc03b3ec2..a3d683fee88be86f99a67bb8342ac45edc273352 100644 (file)
@@ -35,7 +35,7 @@ SUBDIRS = @subdirs@
 RPATH_ENVVAR = @RPATH_ENVVAR@
 ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cp gdb.disasm \
        gdb.dwarf2 \
-       gdb.fortran gdb.server gdb.java gdb.mi \
+       gdb.fortran gdb.server gdb.java gdb.mi gdb.multi \
        gdb.objc gdb.opt gdb.pascal gdb.python gdb.threads gdb.trace \
        gdb.xml \
        $(SUBDIRS)
index 4e13b0ce6888916c083b0ba461552106aee3306f..60257be3b16ec38cc5147775e72fd62f090a5293 100644 (file)
@@ -123,7 +123,7 @@ proc gdb_target_monitor { exec_file } {
 }
 
 proc gdb_target_exec { } {
-    gdb_test "target exec" "No executable file now." "" ".*Kill it.*y or n.*" "y"
+    gdb_test "target exec" "No executable files now." "" ".*Kill it.*y or n.*" "y"
     
 }
 #
index ef35b13865731449ad74d8bd285f4ed41125ee17..3350eb40b48e31ae998bb9a6d4760bdf5cf4d979 100755 (executable)
@@ -3131,7 +3131,7 @@ done
 
 
 
-                                                                                                                                                                                                        ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+                                                                                                                                                                                                                  ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.mi/Makefile gdb.multi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -3694,6 +3694,7 @@ do
   "gdb.server/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.server/Makefile" ;;
   "gdb.java/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.java/Makefile" ;;
   "gdb.mi/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.mi/Makefile" ;;
+  "gdb.multi/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.multi/Makefile" ;;
   "gdb.modula2/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.modula2/Makefile" ;;
   "gdb.objc/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.objc/Makefile" ;;
   "gdb.opt/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.opt/Makefile" ;;
index 3d8fae4a616897ac6157eccbba4ce55e46571511..a9065f10cc4f2de20baaf04cc4ee488d0209dc11 100644 (file)
@@ -115,7 +115,8 @@ AC_OUTPUT([Makefile \
   gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
   gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
   gdb.fortran/Makefile gdb.server/Makefile \
-  gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile \
+  gdb.java/Makefile gdb.mi/Makefile gdb.multi/Makefile \
+  gdb.modula2/Makefile \
   gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
   gdb.python/Makefile \
   gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile])
index 45297151ce7b17458ff6af016ff909fb65c793b3..b4c290edf0c9aafd0ce900c188038c64bcdbe0b6 100644 (file)
@@ -205,8 +205,8 @@ proc do_attach_tests {} {
     set timeout 15 
     set test "attach1, purging symbols after detach"
     gdb_test_multiple "file" "$test" {
-       -re "No executable file now.*Discard symbol table.*y or n. $" {
-           gdb_test "y" "No symbol file now." "$test"
+       -re "No executable files now.*Discard all symbol tables.*y or n. $" {
+           gdb_test "y" "No symbol files now." "$test"
        }
     }
     set timeout $old_timeout
@@ -297,16 +297,16 @@ proc do_attach_tests {} {
 
     set test "before attach3, flush symbols"
     gdb_test_multiple "symbol" "$test" {
-       -re "Discard symbol table from.*y or n. $" {
-           gdb_test "y" "No symbol file now." \
+       -re "Discard all symbol tables.*y or n. $" {
+           gdb_test "y" "No symbol files now." \
                "$test"
        }
-       -re "No symbol file now.*$gdb_prompt $" {
+       -re "No symbol files now.*$gdb_prompt $" {
            pass "$test"
        }
     }
 
-    gdb_test "exec" "No executable file now." \
+    gdb_test "exec" "No executable files now." \
        "before attach3, flush exec"
 
     gdb_test "attach $testpid" \
index c041e1335fddc30fd699b7f4a704a3076727fb6e..944e66e54b8696dbc98ab03156526446e1e56864 100644 (file)
@@ -46,6 +46,9 @@ gdb_exit
 gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 gdb_load ${binfile}
+set prev_timeout $timeout
+set timeout 600        
+verbose "Timeout now 600 sec.\n"
 
 global gdb_prompt
 
@@ -383,3 +386,7 @@ gdb_test "kill" "" "kill all one" \
 #
 
 remote_exec build "rm -f pi.txt"
+
+# Restore old timeout
+set timeout $prev_timeout
+verbose "Timeout now $timeout sec.\n"
index 5cae74212e83589203315afb0684e7553233b57c..3d18a29d5cd1e164d0c560220f07f75e0db9d582 100644 (file)
@@ -209,7 +209,7 @@ gdb_test "enable" "" "enable"
 #test exec-file
 send_gdb "exec-file\n"
 gdb_expect {
-    -re "No executable file now..*$gdb_prompt $" {
+    -re "No executable files now..*$gdb_prompt $" {
        pass "exec-file"
     }
     -re "exec-file.*A program is being debugged already.  Kill it. .y or n.*$" {
@@ -234,7 +234,7 @@ gdb_test "fg" "The program is not being run." "fg"
 #test file
 send_gdb "file\n"
 gdb_expect {
-    -re "No executable file now..*$gdb_prompt $"\
+    -re "No executable files now..*$gdb_prompt $"\
            { pass "file" }
     -re ".*A program is being debugged already.  Kill it. .y or n.*$" {
        send_gdb "n\n"
@@ -712,7 +712,7 @@ gdb_expect {
 #test target exec
 send_gdb "target exec\n"
 gdb_expect {
-       -re "No executable file now..*$gdb_prompt $"\
+       -re "No executable files now..*$gdb_prompt $"\
                        { pass "target exec" }
        -re ".*A program is being debugged already.  Kill it. .y or n.*$" {
            send_gdb "n\n"
index 4abe21aa93c138e8e4bc73c30e23438e9abd0bff..6ef73889cc3f3a97a31b034c46a2b06ce951001b 100644 (file)
@@ -83,10 +83,6 @@ proc do_steps_and_nexts {} {
                set description "step over corearg initialization"
                set command "step"
            }
-           -re ".*pid_or_core_arg = NULL.*$gdb_prompt $" {
-               set description "step over pid_or_core_arg initialization"
-               set command "step"
-           }
            -re ".*cdarg = NULL.*$gdb_prompt $" {
                set description "step over cdarg initialization"
                set command "step"
@@ -95,6 +91,14 @@ proc do_steps_and_nexts {} {
                set description "step over ttyarg initialization"
                set command "step"
            }
+           -re ".*miscargs = NULL.*$gdb_prompt $" {
+               set description "step over miscargs initialization"
+               set command "step"
+           }
+           -re ".*nmisc = 0.*$gdb_prompt $" {
+               set description "step over nmisc initialization"
+               set command "step"
+           }
            -re ".*time_at_startup = get_run_time.*$gdb_prompt $" {
                set description "next over get_run_time and everything it calls"
                set command "next"
index 72448cd57affad6601992a544caeda97167d1cbf..43ba08af2bbba0cd05bb8149bbfdb805ea804c2a 100644 (file)
@@ -135,14 +135,14 @@ proc gdb_unload {} {
     global gdb_prompt
     send_gdb "file\n"
     gdb_expect 60 {
-       -re "No executable file now\[^\r\n\]*\[\r\n\]" { exp_continue }
-       -re "No symbol file now\[^\r\n\]*\[\r\n\]" { exp_continue }
+       -re "No executable files now\[^\r\n\]*\[\r\n\]" { exp_continue }
+       -re "No symbol files now\[^\r\n\]*\[\r\n\]" { exp_continue }
        -re "A program is being debugged already..*Kill it.*y or n. $"\
            { send_gdb "y\n"
                verbose "\t\tKilling previous program being debugged"
            exp_continue
        }
-       -re "Discard symbol table from .*y or n.*$" {
+       -re "Discard all symbol tables.*y or n.*$" {
            send_gdb "y\n"
            exp_continue
        }
index d0ba466582d88ba13111776faea82a7755f5751b..c77ba9761f8b26e9472d823d2b57365b0ff3cd55 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -439,6 +439,10 @@ Cannot execute this command without a live selected thread.  See `help thread'."
          *(p + 1) = '\0';
        }
 
+      /* Make sure the current i/t set is actually current and
+        accurate.  */
+      update_itset (current_itset);
+
       /* If this command has been pre-hooked, run the hook first. */
       execute_cmd_pre_hook (c);
 
index f95688223d6885c302b45205001b5e294a722aa1..6119df25ccd2e23f77d298a67feb94638064a2e4 100644 (file)
@@ -384,7 +384,7 @@ regs : the register display\n"));
   add_com_alias ("wh", "winheight", class_tui, 0);
   add_info ("win", tui_all_windows_info,
            _("List of all displayed windows.\n"));
-  add_com ("focus", class_tui, tui_set_focus_command, _("\
+  add_com ("ffocus", class_tui, tui_set_focus_command, _("\
 Set focus to named window or next/prev window.\n\
 Usage: focus {<win> | next | prev}\n\
 Valid Window names are:\n\
index d14009fa98ee1593a38acbb199ae2d0f21718f4b..bd2ebeb792aca8f15e2043d6f091751eb47e3aad 100644 (file)
@@ -51,6 +51,7 @@
 #include "charset.h"
 #include "annotate.h"
 #include "filenames.h"
+#include "exec.h"
 #include "symfile.h"
 #include "gdb_obstack.h"
 #include "gdbcore.h"
@@ -3044,8 +3045,8 @@ string_to_core_addr (const char *my_string)
          be determined by the target architecture, not by the object
          file.  */
       if (i - 2 == addr_bit / 4
-         && exec_bfd
-         && bfd_get_sign_extend_vma (exec_bfd))
+         && first_exec
+         && bfd_get_sign_extend_vma (first_exec->ebfd))
        addr = (addr ^ ((CORE_ADDR) 1 << (addr_bit - 1)))
               - ((CORE_ADDR) 1 << (addr_bit - 1));
     }