Message ID | 20210330172149.1724381-1-simon.marchi@polymtl.ca |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
Simon> Before glibc 2.33, libthread_db always asked for symbols found in Simon> libpthread. There was no ordering problem: since we were always trying Simon> to load libthread_db in reaction to processing libpthread (and reading Simon> in its symbols) and libthread_db only asked symbols from libpthread, the Simon> requested symbols could always be found. Starting with glibc 2.33, Simon> libthread_db now asks for a symbol name that can be found in Simon> /lib/ld-linux-x86-64.so.2 (_rtld_global). And the ordering in which GDB Simon> reads the shared library list from the inferior is unfortunate, in that Simon> libpthread is processed before ld-linux. So when loading libthread_db Simon> in reaction to processing libpthread, and libthread_db requests the Simon> symbol that is from ld-linux, GDB is not yet able to supply it. Adding to my dislike of libthread_db. Linux would be improved if it were removed entirely. Simon> I think that's a good way to make it work: when attaching, the Simon> inferior_created observable is called once everything has stabilized, Simon> when we learned about all shared libraries, so that is a good time to Simon> try to load libthread_db. Yeah. We already have other code doing something similar -- SYMFILE_DEFER_BP_RESET was added to defer a breakpoint reset until all the available shared libraries were loaded, the idea here being to avoid multiple expensive resets one after another. Simon> I considered other solutions, like having a "new_objfiles" observable, Simon> which would fire once after a series of objfiles are created. When Simon> attaching, we would get a single "new_objfiles" notification after all Simon> shared library objfiles have been created, so that the thread-db code Simon> could use that. But it didn't seem nice anymore when actually Simon> implementing it. Perhaps the SYMFILE_DEFER_BP_RESET approach could be generalized somehow. Or is that too closely related to what you tried? Also, does gdbserver need a similar treatment? I know it has to load libthread_db (one of the problems with this library) but is the decision to do so drive by gdb or by itself? I don't recall. Tom
On Fri, 02 Apr 2021 11:14:23 -0600 Tom Tromey <tom@tromey.com> wrote: > Also, does gdbserver need a similar treatment? I know it has to load > libthread_db (one of the problems with this library) but is the decision > to do so drive by gdb or by itself? I don't recall. gdbserver definitely has problems too. It needs gdb to look up symbols (via the qSymbol packet), but is only able to do so at certain times. I'm trying to puzzle it out now... Kevin
On 2021-04-02 1:14 p.m., Tom Tromey wrote: > Simon> Before glibc 2.33, libthread_db always asked for symbols found in > Simon> libpthread. There was no ordering problem: since we were always trying > Simon> to load libthread_db in reaction to processing libpthread (and reading > Simon> in its symbols) and libthread_db only asked symbols from libpthread, the > Simon> requested symbols could always be found. Starting with glibc 2.33, > Simon> libthread_db now asks for a symbol name that can be found in > Simon> /lib/ld-linux-x86-64.so.2 (_rtld_global). And the ordering in which GDB > Simon> reads the shared library list from the inferior is unfortunate, in that > Simon> libpthread is processed before ld-linux. So when loading libthread_db > Simon> in reaction to processing libpthread, and libthread_db requests the > Simon> symbol that is from ld-linux, GDB is not yet able to supply it. > > Adding to my dislike of libthread_db. Linux would be improved if it > were removed entirely. > > Simon> I think that's a good way to make it work: when attaching, the > Simon> inferior_created observable is called once everything has stabilized, > Simon> when we learned about all shared libraries, so that is a good time to > Simon> try to load libthread_db. > > Yeah. We already have other code doing something similar -- > SYMFILE_DEFER_BP_RESET was added to defer a breakpoint reset until all > the available shared libraries were loaded, the idea here being to avoid > multiple expensive resets one after another. > > Simon> I considered other solutions, like having a "new_objfiles" observable, > Simon> which would fire once after a series of objfiles are created. When > Simon> attaching, we would get a single "new_objfiles" notification after all > Simon> shared library objfiles have been created, so that the thread-db code > Simon> could use that. But it didn't seem nice anymore when actually > Simon> implementing it. > > Perhaps the SYMFILE_DEFER_BP_RESET approach could be generalized somehow. > Or is that too closely related to what you tried? If I understand correctly, the "bp reset" mechanism is: pass SYMFILE_DEFER_BP_RESET when loading one or more objfile, and manually call breakpoint_re_set after that. I don't think we can directly use the same mechanism here: we don't really want to create a SYMFILE_DEFER_LOADING_LIBTHREAD_DB flag, that would be quite an abstraction breach. Or do you mean a SYMFILE_DEFER_CALLING_THE_NEW_OBJFILE_OBSERVABLE flag? > Also, does gdbserver need a similar treatment? I know it has to load > libthread_db (one of the problems with this library) but is the decision > to do so drive by gdb or by itself? I don't recall. Probably, I didn't think of testing with GDBserver, it's probably broken there too. I'll try next time I fiddle with this. Simon
On 2021-04-06 5:08 p.m., Kevin Buettner via Gdb-patches wrote: > On Fri, 02 Apr 2021 11:14:23 -0600 > Tom Tromey <tom@tromey.com> wrote: > >> Also, does gdbserver need a similar treatment? I know it has to load >> libthread_db (one of the problems with this library) but is the decision >> to do so drive by gdb or by itself? I don't recall. > > gdbserver definitely has problems too. It needs gdb to look up > symbols (via the qSymbol packet), but is only able to do so at certain > times. > > I'm trying to puzzle it out now... Hi Kevin, Just wondering, are you actively working on this problem? I am not currently assigned on this at $day_job, so all I can put on it is leftovers of time here and there. If you want to propose another patch / solution, feel free! Simon
On Tue, 6 Apr 2021 22:49:50 -0400 Simon Marchi <simon.marchi@polymtl.ca> wrote: > On 2021-04-06 5:08 p.m., Kevin Buettner via Gdb-patches wrote: > > On Fri, 02 Apr 2021 11:14:23 -0600 > > Tom Tromey <tom@tromey.com> wrote: > > > >> Also, does gdbserver need a similar treatment? I know it has to load > >> libthread_db (one of the problems with this library) but is the decision > >> to do so drive by gdb or by itself? I don't recall. > > > > gdbserver definitely has problems too. It needs gdb to look up > > symbols (via the qSymbol packet), but is only able to do so at certain > > times. > > > > I'm trying to puzzle it out now... > > Hi Kevin, > > Just wondering, are you actively working on this problem? I am not > currently assigned on this at $day_job, so all I can put on it is > leftovers of time here and there. If you want to propose another patch > / solution, feel free! Hi Simon, Yes, I'm actively working on it. I first came across it while doing some gdbserver testing, so that's where my focus is at the moment. We definitely need to come up with a solution (possibly different ones) for both gdb and gdbserver. Kevin
Simon> I don't think we can directly use the same mechanism here: we don't Simon> really want to create a SYMFILE_DEFER_LOADING_LIBTHREAD_DB flag, that Simon> would be quite an abstraction breach. Or do you mean a Simon> SYMFILE_DEFER_CALLING_THE_NEW_OBJFILE_OBSERVABLE flag? Not sure, it just seemed to me that the idea is the same: when a number of libraries become visible all at once, GDB should defer some work until after they've all been handled internally. Tom
diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 9b0186dd391c..aaac17cc73b7 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -347,6 +347,8 @@ post_create_inferior (int from_tty) if the now pushed target supports hardware watchpoints. */ breakpoint_re_set (); + current_inferior ()->needs_setup = 0; + gdb::observers::inferior_created.notify (current_inferior ()); } @@ -2418,11 +2420,6 @@ proceed_after_attach (inferior *inf) void setup_inferior (int from_tty) { - struct inferior *inferior; - - inferior = current_inferior (); - inferior->needs_setup = 0; - /* If no exec file is yet known, try to determine it from the process itself. */ if (get_exec_file (0) == NULL) diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c index de8687e99c73..b7a500079fb2 100644 --- a/gdb/linux-thread-db.c +++ b/gdb/linux-thread-db.c @@ -1011,8 +1011,19 @@ try_thread_db_load (const char *library, bool check_auto_load_safe) if (strchr (library, '/') != NULL) info->filename = gdb_realpath (library).release (); - if (try_thread_db_load_1 (info)) - return true; + try + { + if (try_thread_db_load_1 (info)) + return true; + } + catch (const gdb_exception &except) + { + if (libthread_db_debug) + { + exception_fprintf (gdb_stdlog, except, + "Warning: try_thread_db_load: "); + } + } /* This library "refused" to work on current inferior. */ delete_thread_db_info (current_inferior ()->process_target (), @@ -1183,10 +1194,13 @@ has_libpthread (void) static bool thread_db_load (void) { - struct thread_db_info *info; + inferior *inf = current_inferior (); - info = get_thread_db_info (current_inferior ()->process_target (), - inferior_ptid.pid ()); + if (inf->needs_setup) + return false; + + thread_db_info *info = get_thread_db_info (inf->process_target (), + inferior_ptid.pid ()); if (info != NULL) return true;