mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
1 Commits
gdb-17-bra
...
users/gben
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab3d1b33b4 |
@@ -1,3 +1,15 @@
|
||||
2018-05-23 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* linux-thread-db.c (valprint.h): New include.
|
||||
(struct check_thread_db_info): New structure.
|
||||
(check_thread_db_on_load, tdb_testinfo): New static globals.
|
||||
(check_thread_db, check_thread_db_callback): New functions.
|
||||
(try_thread_db_load_1): Run integrity checks if requested.
|
||||
(maintenance_check_libthread_db): New function.
|
||||
(_initialize_thread_db): Register "maint check libthread-db"
|
||||
and "maint set/show check-libthread-db".
|
||||
* NEWS: Mention the above new commands.
|
||||
|
||||
2018-05-20 Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
* common/traits.h (HAVE_IS_TRIVIALLY_COPYABLE): Rename the wrong
|
||||
|
||||
10
gdb/NEWS
10
gdb/NEWS
@@ -27,6 +27,16 @@ set|show record btrace cpu
|
||||
Controls the processor to be used for enabling errata workarounds for
|
||||
branch trace decode.
|
||||
|
||||
maint check libthread-db
|
||||
Run integrity checks on the current inferior's thread debugging
|
||||
library
|
||||
|
||||
maint set check-libthread-db (on|off)
|
||||
maint show check-libthread-db
|
||||
Control whether to run integrity checks on inferior specific thread
|
||||
debugging libraries as they are loaded. The default is not to
|
||||
perform such checks.
|
||||
|
||||
* Python API
|
||||
|
||||
** Type alignment is now exposed via the "align" attribute of a gdb.Type.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2018-05-23 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* gdb.texinfo (Maintenance Commands): Document "maint check
|
||||
libthread-db" and "maint set/show check-libthread-db".
|
||||
|
||||
2018-05-04 Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR python/22731:
|
||||
|
||||
@@ -35533,6 +35533,11 @@ modify XML target descriptions.
|
||||
Check that the target descriptions dynamically created by @value{GDBN}
|
||||
equal the descriptions created from XML files found in @var{dir}.
|
||||
|
||||
@kindex maint check libthread-db
|
||||
@item maint check libthread-db
|
||||
Run integrity checks on the current inferior's thread debugging
|
||||
library.
|
||||
|
||||
@kindex maint print dummy-frames
|
||||
@item maint print dummy-frames
|
||||
Prints the contents of @value{GDBN}'s internal dummy-frame stack.
|
||||
@@ -35840,6 +35845,14 @@ number of blocks in the blockvector
|
||||
@end enumerate
|
||||
@end table
|
||||
|
||||
@kindex maint set check-libthread-db
|
||||
@kindex maint show check-libthread-db
|
||||
@item maint set check-libthread-db [on|off]
|
||||
@itemx maint show check-libthread-db
|
||||
Control whether @value{GDBN} should run integrity checks on inferior
|
||||
specific thread debugging libraries as they are loaded. The default
|
||||
is not to perform such checks.
|
||||
|
||||
@kindex maint space
|
||||
@cindex memory used by commands
|
||||
@item maint space @var{value}
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "nat/linux-namespaces.h"
|
||||
#include <algorithm>
|
||||
#include "common/pathstuff.h"
|
||||
#include "valprint.h"
|
||||
|
||||
/* GNU/Linux libthread_db support.
|
||||
|
||||
@@ -117,6 +118,10 @@ static char *libthread_db_search_path;
|
||||
by the "set auto-load libthread-db" command. */
|
||||
static int auto_load_thread_db = 1;
|
||||
|
||||
/* Set to non-zero if load-time libthread_db tests have been enabled
|
||||
by the "maintenence set check-libthread-db" command. */
|
||||
static int check_thread_db_on_load = 0;
|
||||
|
||||
/* "show" command for the auto_load_thread_db configuration variable. */
|
||||
|
||||
static void
|
||||
@@ -534,6 +539,250 @@ dladdr_to_soname (const void *addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* State for check_thread_db_callback. */
|
||||
|
||||
struct check_thread_db_info
|
||||
{
|
||||
/* The libthread_db under test. */
|
||||
struct thread_db_info *info;
|
||||
|
||||
/* True if progress should be logged. */
|
||||
bool log_progress;
|
||||
|
||||
/* True if the callback was called. */
|
||||
bool threads_seen;
|
||||
|
||||
/* Name of last libthread_db function called. */
|
||||
const char *last_call;
|
||||
|
||||
/* Value returned by last libthread_db call. */
|
||||
td_err_e last_result;
|
||||
};
|
||||
|
||||
static struct check_thread_db_info *tdb_testinfo;
|
||||
|
||||
/* Callback for check_thread_db. */
|
||||
|
||||
static int
|
||||
check_thread_db_callback (const td_thrhandle_t *th, void *arg)
|
||||
{
|
||||
gdb_assert (tdb_testinfo != NULL);
|
||||
tdb_testinfo->threads_seen = true;
|
||||
|
||||
#define LOG(fmt, args...) \
|
||||
do \
|
||||
{ \
|
||||
if (tdb_testinfo->log_progress) \
|
||||
{ \
|
||||
debug_printf (fmt, ## args); \
|
||||
gdb_flush (gdb_stdlog); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define CHECK_1(expr, args...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
LOG (" ... FAIL!\n"); \
|
||||
error (args); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define CHECK(expr) \
|
||||
CHECK_1 (expr, "(%s) == false", #expr)
|
||||
|
||||
#define CALL_UNCHECKED(func, args...) \
|
||||
do \
|
||||
{ \
|
||||
tdb_testinfo->last_call = #func; \
|
||||
tdb_testinfo->last_result \
|
||||
= tdb_testinfo->info->func ## _p (args); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define CHECK_CALL() \
|
||||
CHECK_1 (tdb_testinfo->last_result == TD_OK, \
|
||||
_("%s failed: %s"), \
|
||||
tdb_testinfo->last_call, \
|
||||
thread_db_err_str (tdb_testinfo->last_result)) \
|
||||
|
||||
#define CALL(func, args...) \
|
||||
do \
|
||||
{ \
|
||||
CALL_UNCHECKED (func, args); \
|
||||
CHECK_CALL (); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
LOG (" Got thread");
|
||||
|
||||
/* Check td_ta_thr_iter passed consistent arguments. */
|
||||
CHECK (th != NULL);
|
||||
CHECK (arg == (void *) tdb_testinfo);
|
||||
CHECK (th->th_ta_p == tdb_testinfo->info->thread_agent);
|
||||
|
||||
LOG (" %s", core_addr_to_string_nz ((CORE_ADDR) th->th_unique));
|
||||
|
||||
/* Check td_thr_get_info. */
|
||||
td_thrinfo_t ti;
|
||||
CALL (td_thr_get_info, th, &ti);
|
||||
|
||||
LOG (" => %d", ti.ti_lid);
|
||||
|
||||
CHECK (ti.ti_ta_p == th->th_ta_p);
|
||||
CHECK (ti.ti_tid == (thread_t) th->th_unique);
|
||||
|
||||
/* Check td_ta_map_lwp2thr. */
|
||||
td_thrhandle_t th2;
|
||||
memset (&th2, 23, sizeof (td_thrhandle_t));
|
||||
CALL_UNCHECKED (td_ta_map_lwp2thr, th->th_ta_p, ti.ti_lid, &th2);
|
||||
|
||||
if (tdb_testinfo->last_result == TD_ERR && !target_has_execution)
|
||||
{
|
||||
/* Some platforms require execution for td_ta_map_lwp2thr. */
|
||||
LOG (_("; can't map_lwp2thr"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_CALL ();
|
||||
|
||||
LOG (" => %s", core_addr_to_string_nz ((CORE_ADDR) th2.th_unique));
|
||||
|
||||
CHECK (memcmp (th, &th2, sizeof (td_thrhandle_t)) == 0);
|
||||
}
|
||||
|
||||
/* Attempt TLS access. Assuming errno is TLS, this calls
|
||||
thread_db_get_thread_local_address, which in turn calls
|
||||
td_thr_tls_get_addr for live inferiors or td_thr_tlsbase
|
||||
for core files. This test is skipped if the thread has
|
||||
not been recorded; proceeding in that case would result
|
||||
in the test having the side-effect of noticing threads
|
||||
which seems wrong.
|
||||
|
||||
Note that in glibc's libthread_db td_thr_tls_get_addr is
|
||||
a thin wrapper around td_thr_tlsbase; this check always
|
||||
hits the bulk of the code.
|
||||
|
||||
Note also that we don't actually check any libthread_db
|
||||
calls are made, we just assume they were; future changes
|
||||
to how GDB accesses TLS could result in this passing
|
||||
without exercising the calls it's supposed to. */
|
||||
ptid_t ptid = ptid_build (tdb_testinfo->info->pid, ti.ti_lid, 0);
|
||||
struct thread_info *thread_info = find_thread_ptid (ptid);
|
||||
if (thread_info != NULL && thread_info->priv != NULL)
|
||||
{
|
||||
LOG ("; errno");
|
||||
|
||||
scoped_restore_current_thread restore_current_thread;
|
||||
switch_to_thread (ptid);
|
||||
|
||||
expression_up expr = parse_expression ("(int) errno");
|
||||
struct value *val = evaluate_expression (expr.get ());
|
||||
|
||||
if (tdb_testinfo->log_progress)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
get_user_print_options (&opts);
|
||||
LOG (" = ");
|
||||
value_print (val, gdb_stdlog, &opts);
|
||||
}
|
||||
}
|
||||
|
||||
LOG (" ... OK\n");
|
||||
|
||||
#undef LOG
|
||||
#undef CHECK_1
|
||||
#undef CHECK
|
||||
#undef CALL_UNCHECKED
|
||||
#undef CHECK_CALL
|
||||
#undef CALL
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Run integrity checks on the dlopen()ed libthread_db described by
|
||||
INFO. Returns true on success, displays a warning and returns
|
||||
false on failure. Logs progress messages to gdb_stdlog during
|
||||
the test if LOG_PROGRESS is true. */
|
||||
|
||||
static bool
|
||||
check_thread_db (struct thread_db_info *info, bool log_progress)
|
||||
{
|
||||
bool test_passed = true;
|
||||
|
||||
if (log_progress)
|
||||
debug_printf (_("Running libthread_db integrity checks:\n"));
|
||||
|
||||
/* GDB avoids using td_ta_thr_iter wherever possible (see comment
|
||||
in try_thread_db_load_1 below) so in order to test it we may
|
||||
have to locate it ourselves. */
|
||||
td_ta_thr_iter_ftype *td_ta_thr_iter_p = info->td_ta_thr_iter_p;
|
||||
if (td_ta_thr_iter_p == NULL)
|
||||
{
|
||||
void *thr_iter = verbose_dlsym (info->handle, "td_ta_thr_iter");
|
||||
if (thr_iter == NULL)
|
||||
return 0;
|
||||
|
||||
td_ta_thr_iter_p = (td_ta_thr_iter_ftype *) thr_iter;
|
||||
}
|
||||
|
||||
/* Set up the test state we share with the callback. */
|
||||
gdb_assert (tdb_testinfo == NULL);
|
||||
struct check_thread_db_info tdb_testinfo_buf;
|
||||
tdb_testinfo = &tdb_testinfo_buf;
|
||||
|
||||
memset (tdb_testinfo, 0, sizeof (struct check_thread_db_info));
|
||||
tdb_testinfo->info = info;
|
||||
tdb_testinfo->log_progress = log_progress;
|
||||
|
||||
/* td_ta_thr_iter shouldn't be used on running processes. Note that
|
||||
it's possible the inferior will stop midway through modifying one
|
||||
of its thread lists, in which case the check will spuriously
|
||||
fail. */
|
||||
linux_stop_and_wait_all_lwps ();
|
||||
|
||||
TRY
|
||||
{
|
||||
td_err_e err = td_ta_thr_iter_p (info->thread_agent,
|
||||
check_thread_db_callback,
|
||||
tdb_testinfo,
|
||||
TD_THR_ANY_STATE,
|
||||
TD_THR_LOWEST_PRIORITY,
|
||||
TD_SIGNO_MASK,
|
||||
TD_THR_ANY_USER_FLAGS);
|
||||
|
||||
if (err != TD_OK)
|
||||
error (_("td_ta_thr_iter failed: %s"), thread_db_err_str (err));
|
||||
|
||||
if (!tdb_testinfo->threads_seen)
|
||||
error (_("no threads seen"));
|
||||
}
|
||||
CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
if (warning_pre_print)
|
||||
fputs_unfiltered (warning_pre_print, gdb_stderr);
|
||||
|
||||
exception_fprintf (gdb_stderr, except,
|
||||
_("libthread_db integrity checks failed: "));
|
||||
|
||||
test_passed = false;
|
||||
}
|
||||
END_CATCH
|
||||
|
||||
if (test_passed && log_progress)
|
||||
debug_printf (_("libthread_db integrity checks passed.\n"));
|
||||
|
||||
tdb_testinfo = NULL;
|
||||
|
||||
linux_unstop_all_lwps ();
|
||||
|
||||
return test_passed;
|
||||
}
|
||||
|
||||
/* Attempt to initialize dlopen()ed libthread_db, described by INFO.
|
||||
Return 1 on success.
|
||||
Failure could happen if libthread_db does not have symbols we expect,
|
||||
@@ -627,6 +876,13 @@ try_thread_db_load_1 (struct thread_db_info *info)
|
||||
#undef TDB_DLSYM
|
||||
#undef CHK
|
||||
|
||||
/* Run integrity checks if requested. */
|
||||
if (check_thread_db_on_load)
|
||||
{
|
||||
if (!check_thread_db (info, libthread_db_debug))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info->td_ta_thr_iter_p == NULL)
|
||||
{
|
||||
struct lwp_info *lp;
|
||||
@@ -1668,6 +1924,24 @@ info_auto_load_libthread_db (const char *args, int from_tty)
|
||||
uiout->message (_("No auto-loaded libthread-db.\n"));
|
||||
}
|
||||
|
||||
/* Implement 'maintenance check libthread-db'. */
|
||||
|
||||
static void
|
||||
maintenance_check_libthread_db (const char *args, int from_tty)
|
||||
{
|
||||
int inferior_pid = ptid_get_pid (inferior_ptid);
|
||||
struct thread_db_info *info;
|
||||
|
||||
if (inferior_pid == 0)
|
||||
error (_("No inferior running"));
|
||||
|
||||
info = get_thread_db_info (inferior_pid);
|
||||
if (info == NULL)
|
||||
error (_("No libthread_db loaded"));
|
||||
|
||||
check_thread_db (info, true);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_thread_db (void)
|
||||
{
|
||||
@@ -1718,6 +1992,23 @@ This options has security implications for untrusted inferiors."),
|
||||
Usage: info auto-load libthread-db"),
|
||||
auto_load_info_cmdlist_get ());
|
||||
|
||||
add_cmd ("libthread-db", class_maintenance,
|
||||
maintenance_check_libthread_db, _("\
|
||||
Run integrity checks on the current inferior's libthread_db."),
|
||||
&maintenancechecklist);
|
||||
|
||||
add_setshow_boolean_cmd ("check-libthread-db",
|
||||
class_maintenance,
|
||||
&check_thread_db_on_load, _("\
|
||||
Set whether to check libthread_db at load time."), _("\
|
||||
Show whether to check libthread_db at load time."), _("\
|
||||
If enabled GDB will run integrity checks on inferior specific libthread_db\n\
|
||||
as they are loaded."),
|
||||
NULL,
|
||||
NULL,
|
||||
&maintenance_set_cmdlist,
|
||||
&maintenance_show_cmdlist);
|
||||
|
||||
/* Add ourselves to objfile event chain. */
|
||||
gdb::observers::new_objfile.attach (thread_db_new_objfile);
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
2018-05-23 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* gdb.threads/check-libthread-db.exp: New file.
|
||||
* gdb.threads/check-libthread-db.c: Likewise.
|
||||
|
||||
2018-05-18 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* gdb.base/ptype-offsets.exp: Update.
|
||||
|
||||
67
gdb/testsuite/gdb.threads/check-libthread-db.c
Normal file
67
gdb/testsuite/gdb.threads/check-libthread-db.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2017-2018 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void
|
||||
break_here (void)
|
||||
{
|
||||
}
|
||||
|
||||
static void *
|
||||
thread_routine (void *arg)
|
||||
{
|
||||
errno = 42;
|
||||
|
||||
break_here ();
|
||||
|
||||
while (1)
|
||||
sleep (1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv)
|
||||
{
|
||||
pthread_t the_thread;
|
||||
int err;
|
||||
|
||||
err = pthread_create (&the_thread, NULL, thread_routine, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
fprintf (stderr, "pthread_create: %s (%d)\n", strerror (err), err);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
errno = 23;
|
||||
|
||||
err = pthread_join (the_thread, NULL);
|
||||
if (err != 0)
|
||||
{
|
||||
fprintf (stderr, "pthread_join: %s (%d)\n", strerror (err), err);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
113
gdb/testsuite/gdb.threads/check-libthread-db.exp
Normal file
113
gdb/testsuite/gdb.threads/check-libthread-db.exp
Normal file
@@ -0,0 +1,113 @@
|
||||
# Copyright 2017-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This test only works for native processes on GNU/Linux.
|
||||
if {[target_info gdb_protocol] != "" || ![istarget *-linux*]} {
|
||||
continue
|
||||
}
|
||||
|
||||
standard_testfile
|
||||
|
||||
if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
|
||||
executable debug] != "" } {
|
||||
return -1
|
||||
}
|
||||
|
||||
# Manual check with libthread_db not loaded.
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
gdb_test "maint show check-libthread-db" \
|
||||
"Whether to check libthread_db at load time is off."
|
||||
|
||||
gdb_test_no_output "set stop-on-solib-events 1"
|
||||
gdb_run_cmd
|
||||
gdb_test "" \
|
||||
".*Stopped due to shared library event.*no libraries added or removed.*"
|
||||
|
||||
gdb_test "maint check libthread-db" \
|
||||
"No libthread_db loaded" \
|
||||
"user-initiated check with no libpthread.so loaded"
|
||||
|
||||
|
||||
# Manual check with NPTL uninitialized.
|
||||
# libthread_db should fake a single thread with th_unique == NULL.
|
||||
|
||||
gdb_test "continue" \
|
||||
".*Stopped due to shared library event.*Inferior loaded .*libpthread.*"
|
||||
|
||||
gdb_test_sequence "maint check libthread-db" \
|
||||
"user-initiated check with libpthread.so not initialized" {
|
||||
"\[\r\n\]+Running libthread_db integrity checks:"
|
||||
"\[\r\n\]+\[ \]+Got thread 0x0 => \[0-9\]+ => 0x0 ... OK"
|
||||
"\[\r\n\]+libthread_db integrity checks passed."
|
||||
}
|
||||
|
||||
|
||||
# Manual check with NPTL fully operational.
|
||||
|
||||
gdb_test_no_output "set stop-on-solib-events 0"
|
||||
gdb_breakpoint break_here
|
||||
gdb_continue_to_breakpoint break_here
|
||||
|
||||
gdb_test_sequence "maint check libthread-db" \
|
||||
"user-initiated check with libpthread.so fully initialized" {
|
||||
"\[\r\n\]+Running libthread_db integrity checks:"
|
||||
"\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+; errno = 23 ... OK"
|
||||
"\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+; errno = 42 ... OK"
|
||||
"\[\r\n\]+libthread_db integrity checks passed."
|
||||
}
|
||||
|
||||
|
||||
# Automated check with NPTL uninitialized.
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
gdb_test_no_output "maint set check-libthread-db 1"
|
||||
gdb_test_no_output "set debug libthread-db 1"
|
||||
gdb_breakpoint break_here
|
||||
gdb_run_cmd
|
||||
|
||||
gdb_test_sequence "" \
|
||||
"automated load-time check with libpthread.so not initialized" {
|
||||
"\[\r\n\]+Running libthread_db integrity checks:"
|
||||
"\[\r\n\]+\[ \]+Got thread 0x0 => \[0-9\]+ => 0x0 ... OK"
|
||||
"\[\r\n\]+libthread_db integrity checks passed."
|
||||
"\[\r\n\]+[Thread debugging using libthread_db enabled]"
|
||||
}
|
||||
|
||||
|
||||
# Automated check with NPTL fully operational.
|
||||
|
||||
clean_restart ${binfile}
|
||||
|
||||
gdb_test_no_output "maint set check-libthread-db 1"
|
||||
gdb_test_no_output "set debug libthread-db 1"
|
||||
|
||||
set test_spawn_id [spawn_wait_for_attach $binfile]
|
||||
set testpid [spawn_id_get_pid $test_spawn_id]
|
||||
|
||||
gdb_test_sequence "attach $testpid" \
|
||||
"automated load-time check with libpthread.so fully initialized" {
|
||||
"\[\r\n\]+Running libthread_db integrity checks:"
|
||||
"\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK"
|
||||
"\[\r\n\]+\[ \]+Got thread 0x\[1-9a-f\]\[0-9a-f\]+ => \[0-9\]+ => 0x\[1-9a-f\]\[0-9a-f\]+ ... OK"
|
||||
"\[\r\n\]+libthread_db integrity checks passed."
|
||||
"\[\r\n\]+[Thread debugging using libthread_db enabled]"
|
||||
}
|
||||
|
||||
|
||||
gdb_exit
|
||||
kill_wait_spawned_process $test_spawn_id
|
||||
Reference in New Issue
Block a user