From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26004 invoked by alias); 27 Oct 2008 23:29:39 -0000 Received: (qmail 25994 invoked by uid 22791); 27 Oct 2008 23:29:37 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 27 Oct 2008 23:28:50 +0000 Received: (qmail 29195 invoked from network); 27 Oct 2008 23:28:47 -0000 Received: from unknown (HELO orlando.local) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 27 Oct 2008 23:28:47 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [RFC] Share the shared library list between inferiors Date: Tue, 28 Oct 2008 01:28:00 -0000 User-Agent: KMail/1.9.9 MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_A7kBJhwW2sUT8d5" Message-Id: <200810272329.04758.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-10/txt/msg00669.txt.bz2 --Boundary-00=_A7kBJhwW2sUT8d5 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 1563 Hi, (This is one of the last patches needed for correct multi-process + non-stop debugging against Ericsson DICOS. This one may turn out useful for some embedded OSs, when multi-process support for them is added.) When debugging against DICOS, we only need/should query the shared library list (using solib-target.c) once on initial connection --- not whenever we attach to a new process. (there's no notion of a main exec file in DICOS, it's all shared libraries, with a bunch of possible entry points). The same code is visible to all processes. Although each process has it's own address space, all code is loaded/relocated to the same addresses in all inferiors. It's like we're debugging a bunch of forks. The debug API then goes a step further, and makes it so that an inserted breakpoint is visible to all processes. Since both the code and inserted breakpoint locations are visible to all processes, it is bad to remove/clear them whenever we attach or detach to/from an inferior. This patch teaches GDB about this property. There are several ways to skin this cat. This one seemed like the smallest, most extensible and malleable one from GDB's side, because it doesn't cast to stone any new protocol extension --- which may prove limited to some systems (some memory regions shared, others not; some shared but visible at different addresses in different inferiors/cores, etc.). I was hoping we'd cross that bridge when we start seeing those systems reporting multi process support to GDB. What do people think about this? -- Pedro Alves --Boundary-00=_A7kBJhwW2sUT8d5 Content-Type: text/x-diff; charset="utf-8"; name="global_solist.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="global_solist.diff" Content-length: 12995 2008-10-27 Pedro Alves * remote.c (remote_start_remote): If the solib list is global, fetch libraries and insert breakpoints after connecting. * infcmd.c (post_create_inferior): If the solist is shared between inferiors, no need to refetch it on every new inferior. (detach_command): If the shared library list is shared between inferiors, then don't clear it on every inferior detach. * gdbarch.sh (has_global_solist): New. * i386-dicos-tdep.c (i386_dicos_init_abi): Set gdbarch_has_global_solist. * target.c (target_pre_inferior): If the shared library list is shared between inferiors, then don't clear it here, neither invalidate the memory regions or clear the target description. (target_detach): If the shared library list is shared between inferiors, then don't remove breakpoints from the target here. (target_disconnect): Remove breakpoints from the target here. * solib.c (update_solib_list): Check for null_ptid. * breakpoint.c (insert_breakpoints, update_global_location_list): If the shared library list is shared between inferiors, insert breakpoints even if there's no execution. (breakpoint_init_inferior): If the shared library list is shared between inferiors, don't delete breakpoints or mark them uninserted here. * gdbarch.c, gdbarch.h: Regenerate. --- gdb/breakpoint.c | 17 +++++++++++++---- gdb/gdbarch.c | 23 +++++++++++++++++++++++ gdb/gdbarch.h | 6 ++++++ gdb/gdbarch.sh | 4 ++++ gdb/i386-dicos-tdep.c | 4 ++++ gdb/infcmd.c | 13 +++++++++++-- gdb/remote.c | 11 +++++++++++ gdb/solib.c | 2 +- gdb/target.c | 29 +++++++++++++++++++++-------- 9 files changed, 94 insertions(+), 15 deletions(-) Index: src/gdb/remote.c =================================================================== --- src.orig/gdb/remote.c 2008-10-27 22:40:09.000000000 +0000 +++ src/gdb/remote.c 2008-10-27 23:03:06.000000000 +0000 @@ -2554,6 +2554,11 @@ remote_start_remote (struct ui_out *uiou getpkt (&rs->buf, &rs->buf_size, 0); } + /* On OSs where the list of libraries is global to all + processes, we fetch them early. */ + if (gdbarch_has_global_solist (target_gdbarch)) + solib_add (NULL, args->from_tty, args->target, auto_solib_add); + /* Next, if the target can specify a description, read it. We do this before anything involving memory or registers. */ target_find_description (); @@ -2721,6 +2726,12 @@ remote_start_remote (struct ui_out *uiou if (exec_bfd) /* No use without an exec file. */ remote_check_symbols (symfile_objfile); } + + /* If code is shared between processes, then breakpoints are global + too; Insert them now. */ + if (gdbarch_has_global_solist (target_gdbarch) + && breakpoints_always_inserted_mode ()) + insert_breakpoints (); } /* Open a connection to a remote debugger. Index: src/gdb/infcmd.c =================================================================== --- src.orig/gdb/infcmd.c 2008-10-27 20:38:49.000000000 +0000 +++ src/gdb/infcmd.c 2008-10-27 22:46:52.000000000 +0000 @@ -385,7 +385,9 @@ post_create_inferior (struct target_ops don't need to. */ target_find_description (); - if (exec_bfd) + /* If the solist is global across processes, there's no need to + refetch it here. */ + if (exec_bfd && !gdbarch_has_global_solist (target_gdbarch)) { /* Sometimes the platform-specific hook loads initial shared libraries, and sometimes it doesn't. Try to do so first, so @@ -397,7 +399,10 @@ post_create_inferior (struct target_ops #else solib_add (NULL, from_tty, target, auto_solib_add); #endif + } + if (exec_bfd) + { /* Create the hooks to handle shared library load and unload events. */ #ifdef SOLIB_CREATE_INFERIOR_HOOK @@ -2313,7 +2318,11 @@ detach_command (char *args, int from_tty { dont_repeat (); /* Not for the faint of heart. */ target_detach (args, from_tty); - no_shared_libraries (NULL, from_tty); + + /* If the solist is global across inferiors, don't clear it when we + detach from a single inferior. */ + if (!gdbarch_has_global_solist (target_gdbarch)) + no_shared_libraries (NULL, from_tty); /* If the current target interface claims there's still execution, then don't mess with threads of other processes. */ Index: src/gdb/gdbarch.c =================================================================== --- src.orig/gdb/gdbarch.c 2008-10-27 20:38:28.000000000 +0000 +++ src/gdb/gdbarch.c 2008-10-27 22:40:31.000000000 +0000 @@ -240,6 +240,7 @@ struct gdbarch gdbarch_target_signal_from_host_ftype *target_signal_from_host; gdbarch_target_signal_to_host_ftype *target_signal_to_host; gdbarch_record_special_symbol_ftype *record_special_symbol; + int has_global_solist; }; @@ -371,6 +372,7 @@ struct gdbarch startup_gdbarch = default_target_signal_from_host, /* target_signal_from_host */ default_target_signal_to_host, /* target_signal_to_host */ 0, /* record_special_symbol */ + 0, /* has_global_solist */ /* startup_gdbarch() */ }; @@ -623,6 +625,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of target_signal_from_host, invalid_p == 0 */ /* Skip verify of target_signal_to_host, invalid_p == 0 */ /* Skip verify of record_special_symbol, has predicate */ + /* Skip verify of has_global_solist, invalid_p == 0 */ buf = ui_file_xstrdup (log, &dummy); make_cleanup (xfree, buf); if (strlen (buf) > 0) @@ -832,6 +835,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: get_longjmp_target = <0x%lx>\n", (long) gdbarch->get_longjmp_target); fprintf_unfiltered (file, + "gdbarch_dump: has_global_solist = %s\n", + plongest (gdbarch->has_global_solist)); + fprintf_unfiltered (file, "gdbarch_dump: have_nonsteppable_watchpoint = %s\n", plongest (gdbarch->have_nonsteppable_watchpoint)); fprintf_unfiltered (file, @@ -3237,6 +3243,23 @@ set_gdbarch_record_special_symbol (struc gdbarch->record_special_symbol = record_special_symbol; } +int +gdbarch_has_global_solist (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + /* Skip verify of has_global_solist, invalid_p == 0 */ + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_has_global_solist called\n"); + return gdbarch->has_global_solist; +} + +void +set_gdbarch_has_global_solist (struct gdbarch *gdbarch, + int has_global_solist) +{ + gdbarch->has_global_solist = has_global_solist; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ Index: src/gdb/gdbarch.h =================================================================== --- src.orig/gdb/gdbarch.h 2008-10-27 20:38:28.000000000 +0000 +++ src/gdb/gdbarch.h 2008-10-27 22:40:31.000000000 +0000 @@ -811,6 +811,12 @@ typedef void (gdbarch_record_special_sym extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym); extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol); +/* True if the list of shared libraries is one and only for all + processes, as opposed to a list of shared libraries per inferior. */ + +extern int gdbarch_has_global_solist (struct gdbarch *gdbarch); +extern void set_gdbarch_has_global_solist (struct gdbarch *gdbarch, int has_global_solist); + extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); Index: src/gdb/gdbarch.sh =================================================================== --- src.orig/gdb/gdbarch.sh 2008-10-27 20:38:28.000000000 +0000 +++ src/gdb/gdbarch.sh 2008-10-27 22:40:31.000000000 +0000 @@ -707,6 +707,10 @@ m:int:target_signal_to_host:enum target_ # Record architecture-specific information from the symbol table. M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym + +# True if the list of shared libraries is one and only for all +# processes, as opposed to a list of shared libraries per inferior. +v:int:has_global_solist:::0:0::0 EOF } Index: src/gdb/i386-dicos-tdep.c =================================================================== --- src.orig/gdb/i386-dicos-tdep.c 2008-10-27 20:38:28.000000000 +0000 +++ src/gdb/i386-dicos-tdep.c 2008-10-27 22:40:31.000000000 +0000 @@ -49,6 +49,10 @@ i386_dicos_init_abi (struct gdbarch_info set_solib_ops (gdbarch, &solib_target_so_ops); + /* Every process, although has its own address space, sees the same + list of shared libraries. */ + set_gdbarch_has_global_solist (gdbarch, 1); + /* There's no (standard definition of) entry point or a guaranteed text location we could find with a symbol where to place the call dummy, so we put it on the stack. */ Index: src/gdb/target.c =================================================================== --- src.orig/gdb/target.c 2008-10-27 22:40:09.000000000 +0000 +++ src/gdb/target.c 2008-10-27 22:40:31.000000000 +0000 @@ -1756,11 +1756,18 @@ target_pre_inferior (int from_tty) (gdb) attach 4712 Cannot access memory at address 0xdeadbeef */ - no_shared_libraries (NULL, from_tty); - invalidate_target_mem_regions (); + /* In some OSs, the shared library list is the same/global/shared + across inferiors. If code is shared between processes, so are + memory regions and features. */ + if (!gdbarch_has_global_solist (target_gdbarch)) + { + no_shared_libraries (NULL, from_tty); + + invalidate_target_mem_regions (); - target_clear_description (); + target_clear_description (); + } } /* This is to be called by the open routine before it does @@ -1794,9 +1801,14 @@ target_preopen (int from_tty) void target_detach (char *args, int from_tty) { - /* If we're in breakpoints-always-inserted mode, have to - remove them before detaching. */ - remove_breakpoints (); + if (gdbarch_has_global_solist (target_gdbarch)) + /* Don't remove global breakpoints here. They're removed on + disconnection from the target. */ + ; + else + /* If we're in breakpoints-always-inserted mode, have to remove + them before detaching. */ + remove_breakpoints (); (current_target.to_detach) (args, from_tty); } @@ -1806,8 +1818,9 @@ target_disconnect (char *args, int from_ { struct target_ops *t; - /* If we're in breakpoints-always-inserted mode, have to - remove them before disconnecting. */ + /* If we're in breakpoints-always-inserted mode or if breakpoints + are global across processes, we have to remove them before + disconnecting. */ remove_breakpoints (); for (t = current_target.beneath; t != NULL; t = t->beneath) Index: src/gdb/solib.c =================================================================== --- src.orig/gdb/solib.c 2008-10-27 20:38:28.000000000 +0000 +++ src/gdb/solib.c 2008-10-27 22:40:31.000000000 +0000 @@ -510,7 +510,7 @@ update_solib_list (int from_tty, struct /* We can reach here due to changing solib-search-path or the sysroot, before having any inferior. */ - if (target_has_execution) + if (target_has_execution && !ptid_equal (inferior_ptid, null_ptid)) { struct inferior *inf = current_inferior (); Index: src/gdb/breakpoint.c =================================================================== --- src.orig/gdb/breakpoint.c 2008-10-27 20:38:28.000000000 +0000 +++ src/gdb/breakpoint.c 2008-10-27 22:42:16.000000000 +0000 @@ -1274,7 +1274,10 @@ insert_breakpoints (void) update_global_location_list (1); - if (!breakpoints_always_inserted_mode () && target_has_execution) + if (!breakpoints_always_inserted_mode () + && (target_has_execution + || (gdbarch_has_global_solist (target_gdbarch) + && target_supports_multi_process ()))) /* update_global_location_list does not insert breakpoints when always_inserted_mode is not enabled. Explicitly insert them now. */ @@ -1743,6 +1746,11 @@ breakpoint_init_inferior (enum inf_conte struct bp_location *bpt; int ix; + /* If breakpoint locations are shared across processes, then there's + nothing to do. */ + if (gdbarch_has_global_solist (target_gdbarch)) + return; + ALL_BP_LOCATIONS (bpt) if (bpt->owner->enable_state != bp_permanent) bpt->inserted = 0; @@ -7272,9 +7280,10 @@ update_global_location_list (int should_ check_duplicates (b); } - if (breakpoints_always_inserted_mode () - && should_insert - && target_has_execution) + if (breakpoints_always_inserted_mode () && should_insert + && (target_has_execution + || (gdbarch_has_global_solist (target_gdbarch) + && target_supports_multi_process ()))) insert_breakpoint_locations (); } --Boundary-00=_A7kBJhwW2sUT8d5--