gdb/
* linux-thread-db.c (inferior_has_bug): New function. (thread_db_find_new_threads_silently): Return boolean as checked by inferior_has_bug, describe it in the comments. (try_thread_db_load_1): Move call to thread_db_find_new_threads_silently earlier. Abort the initialization if it returned non-zero. (thread_db_find_new_threads_2): Preinitialize ERR. Check errors also if UNTIL_NO_NEW, gdb/testsuite/ * gdb.threads/gcore-thread.exp: Remove variable libthread_db_seen. Wrap the test into loop for corefile and core0file.
This commit is contained in:
parent
0f3c2347e6
commit
fcb4437118
|
@ -1,3 +1,13 @@
|
||||||
|
2012-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
|
* linux-thread-db.c (inferior_has_bug): New function.
|
||||||
|
(thread_db_find_new_threads_silently): Return boolean as checked by
|
||||||
|
inferior_has_bug, describe it in the comments.
|
||||||
|
(try_thread_db_load_1): Move call to thread_db_find_new_threads_silently
|
||||||
|
earlier. Abort the initialization if it returned non-zero.
|
||||||
|
(thread_db_find_new_threads_2): Preinitialize ERR. Check errors also
|
||||||
|
if UNTIL_NO_NEW,
|
||||||
|
|
||||||
2012-07-02 Doug Evans <dje@google.com>
|
2012-07-02 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
* dwarf2read.c (maybe_queue_comp_unit): Move definition next to others
|
* dwarf2read.c (maybe_queue_comp_unit): Move definition next to others
|
||||||
|
|
|
@ -576,6 +576,37 @@ enable_thread_event (int event, CORE_ADDR *bp)
|
||||||
return TD_OK;
|
return TD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify inferior's '\0'-terminated symbol VER_SYMBOL starts with "%d.%d" and
|
||||||
|
return 1 if this version is lower (and not equal) to
|
||||||
|
VER_MAJOR_MIN.VER_MINOR_MIN. Return 0 in all other cases. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
inferior_has_bug (const char *ver_symbol, int ver_major_min, int ver_minor_min)
|
||||||
|
{
|
||||||
|
struct minimal_symbol *version_msym;
|
||||||
|
CORE_ADDR version_addr;
|
||||||
|
char *version;
|
||||||
|
int err, got, retval = 0;
|
||||||
|
|
||||||
|
version_msym = lookup_minimal_symbol (ver_symbol, NULL, NULL);
|
||||||
|
if (version_msym == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
version_addr = SYMBOL_VALUE_ADDRESS (version_msym);
|
||||||
|
got = target_read_string (version_addr, &version, 32, &err);
|
||||||
|
if (err == 0 && memchr (version, 0, got) == &version[got -1])
|
||||||
|
{
|
||||||
|
int major, minor;
|
||||||
|
|
||||||
|
retval = (sscanf (version, "%d.%d", &major, &minor) == 2
|
||||||
|
&& (major < ver_major_min
|
||||||
|
|| (major == ver_major_min && minor < ver_minor_min)));
|
||||||
|
}
|
||||||
|
xfree (version);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enable_thread_event_reporting (void)
|
enable_thread_event_reporting (void)
|
||||||
{
|
{
|
||||||
|
@ -643,9 +674,13 @@ enable_thread_event_reporting (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same as thread_db_find_new_threads_1, but silently ignore errors. */
|
/* Similar as thread_db_find_new_threads_1, but try to silently ignore errors
|
||||||
|
if appropriate.
|
||||||
|
|
||||||
static void
|
Return 1 if the caller should abort libthread_db initialization. Return 0
|
||||||
|
otherwise. */
|
||||||
|
|
||||||
|
static int
|
||||||
thread_db_find_new_threads_silently (ptid_t ptid)
|
thread_db_find_new_threads_silently (ptid_t ptid)
|
||||||
{
|
{
|
||||||
volatile struct gdb_exception except;
|
volatile struct gdb_exception except;
|
||||||
|
@ -655,11 +690,36 @@ thread_db_find_new_threads_silently (ptid_t ptid)
|
||||||
thread_db_find_new_threads_2 (ptid, 1);
|
thread_db_find_new_threads_2 (ptid, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (except.reason < 0 && libthread_db_debug)
|
if (except.reason < 0)
|
||||||
{
|
{
|
||||||
exception_fprintf (gdb_stderr, except,
|
if (libthread_db_debug)
|
||||||
"Warning: thread_db_find_new_threads_silently: ");
|
exception_fprintf (gdb_stderr, except,
|
||||||
|
"Warning: thread_db_find_new_threads_silently: ");
|
||||||
|
|
||||||
|
/* There is a bug fixed between nptl 2.6.1 and 2.7 by
|
||||||
|
commit 7d9d8bd18906fdd17364f372b160d7ab896ce909
|
||||||
|
where calls to td_thr_get_info fail with TD_ERR for statically linked
|
||||||
|
executables if td_thr_get_info is called before glibc has initialized
|
||||||
|
itself.
|
||||||
|
|
||||||
|
If the nptl bug is NOT present in the inferior and still thread_db
|
||||||
|
reports an error return 1. It means the inferior has corrupted thread
|
||||||
|
list and GDB should fall back only to LWPs.
|
||||||
|
|
||||||
|
If the nptl bug is present in the inferior return 0 to silently ignore
|
||||||
|
such errors, and let gdb enumerate threads again later. In such case
|
||||||
|
GDB cannot properly display LWPs if the inferior thread list is
|
||||||
|
corrupted. */
|
||||||
|
|
||||||
|
if (!inferior_has_bug ("nptl_version", 2, 7))
|
||||||
|
{
|
||||||
|
exception_fprintf (gdb_stderr, except,
|
||||||
|
_("Warning: couldn't activate thread debugging "
|
||||||
|
"using libthread_db: "));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup a library in which given symbol resides.
|
/* Lookup a library in which given symbol resides.
|
||||||
|
@ -762,6 +822,14 @@ try_thread_db_load_1 (struct thread_db_info *info)
|
||||||
info->td_thr_event_enable_p = dlsym (info->handle, "td_thr_event_enable");
|
info->td_thr_event_enable_p = dlsym (info->handle, "td_thr_event_enable");
|
||||||
info->td_thr_tls_get_addr_p = dlsym (info->handle, "td_thr_tls_get_addr");
|
info->td_thr_tls_get_addr_p = dlsym (info->handle, "td_thr_tls_get_addr");
|
||||||
|
|
||||||
|
if (thread_db_find_new_threads_silently (inferior_ptid) != 0)
|
||||||
|
{
|
||||||
|
/* Even if libthread_db initializes, if the thread list is
|
||||||
|
corrupted, we'd not manage to list any threads. Better reject this
|
||||||
|
thread_db, and fall back to at least listing LWPs. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
|
printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
|
||||||
|
|
||||||
if (libthread_db_debug || *libthread_db_search_path)
|
if (libthread_db_debug || *libthread_db_search_path)
|
||||||
|
@ -785,12 +853,6 @@ try_thread_db_load_1 (struct thread_db_info *info)
|
||||||
if (target_has_execution)
|
if (target_has_execution)
|
||||||
enable_thread_event_reporting ();
|
enable_thread_event_reporting ();
|
||||||
|
|
||||||
/* There appears to be a bug in glibc-2.3.6: calls to td_thr_get_info fail
|
|
||||||
with TD_ERR for statically linked executables if td_thr_get_info is
|
|
||||||
called before glibc has initialized itself. Silently ignore such
|
|
||||||
errors, and let gdb enumerate threads again later. */
|
|
||||||
thread_db_find_new_threads_silently (inferior_ptid);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,6 +1194,12 @@ thread_db_new_objfile (struct objfile *objfile)
|
||||||
correctly. */
|
correctly. */
|
||||||
|
|
||||||
if (objfile != NULL
|
if (objfile != NULL
|
||||||
|
/* libpthread with separate debug info has its debug info file already
|
||||||
|
loaded (and notified without successfult thread_db initialization))
|
||||||
|
the time observer_notify_new_objfile is called for the library itself.
|
||||||
|
Static executables have their separate debug info loaded already
|
||||||
|
before the inferior has started. */
|
||||||
|
&& objfile->separate_debug_objfile_backlink == NULL
|
||||||
/* Only check for thread_db if we loaded libpthread,
|
/* Only check for thread_db if we loaded libpthread,
|
||||||
or if this is the main symbol file.
|
or if this is the main symbol file.
|
||||||
We need to check OBJF_MAINLINE to handle the case of debugging
|
We need to check OBJF_MAINLINE to handle the case of debugging
|
||||||
|
@ -1612,7 +1680,7 @@ find_new_threads_once (struct thread_db_info *info, int iteration,
|
||||||
static void
|
static void
|
||||||
thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
|
thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
|
||||||
{
|
{
|
||||||
td_err_e err;
|
td_err_e err = TD_OK;
|
||||||
struct thread_db_info *info;
|
struct thread_db_info *info;
|
||||||
int pid = ptid_get_pid (ptid);
|
int pid = ptid_get_pid (ptid);
|
||||||
int i, loop;
|
int i, loop;
|
||||||
|
@ -1628,17 +1696,18 @@ thread_db_find_new_threads_2 (ptid_t ptid, int until_no_new)
|
||||||
The 4 is a heuristic: there is an inherent race here, and I have
|
The 4 is a heuristic: there is an inherent race here, and I have
|
||||||
seen that 2 iterations in a row are not always sufficient to
|
seen that 2 iterations in a row are not always sufficient to
|
||||||
"capture" all threads. */
|
"capture" all threads. */
|
||||||
for (i = 0, loop = 0; loop < 4; ++i, ++loop)
|
for (i = 0, loop = 0; loop < 4 && err == TD_OK; ++i, ++loop)
|
||||||
if (find_new_threads_once (info, i, NULL) != 0)
|
if (find_new_threads_once (info, i, &err) != 0)
|
||||||
/* Found some new threads. Restart the loop from beginning. */
|
{
|
||||||
loop = -1;
|
/* Found some new threads. Restart the loop from beginning. */
|
||||||
|
loop = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
find_new_threads_once (info, 0, &err);
|
||||||
find_new_threads_once (info, 0, &err);
|
|
||||||
if (err != TD_OK)
|
if (err != TD_OK)
|
||||||
error (_("Cannot find new threads: %s"), thread_db_err_str (err));
|
error (_("Cannot find new threads: %s"), thread_db_err_str (err));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2012-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
|
* gdb.threads/gcore-thread.exp: Remove variable libthread_db_seen.
|
||||||
|
Wrap the test into loop for corefile and core0file.
|
||||||
|
|
||||||
2012-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
|
2012-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
* gdb.dwarf2/fission-reread.S: Remove .section attributes.
|
* gdb.dwarf2/fission-reread.S: Remove .section attributes.
|
||||||
|
|
|
@ -141,11 +141,9 @@ proc load_core { corefile } {
|
||||||
global gdb_prompt
|
global gdb_prompt
|
||||||
global libthread_db_seen
|
global libthread_db_seen
|
||||||
|
|
||||||
set libthread_db_seen 0
|
|
||||||
gdb_test_multiple "core $corefile" \
|
gdb_test_multiple "core $corefile" \
|
||||||
"re-load generated corefile" {
|
"re-load generated corefile" {
|
||||||
-re "\\\[Thread debugging using \[^ \r\n\]* enabled\\\]\r\n" {
|
-re "\\\[Thread debugging using \[^ \r\n\]* enabled\\\]\r\n" {
|
||||||
set libthread_db_seen 1
|
|
||||||
exp_continue
|
exp_continue
|
||||||
}
|
}
|
||||||
-re " is not a core dump:.*\r\n$gdb_prompt $" {
|
-re " is not a core dump:.*\r\n$gdb_prompt $" {
|
||||||
|
@ -168,39 +166,27 @@ proc load_core { corefile } {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if ![load_core $corefile] {
|
foreach name { corefile core0file } { with_test_prefix $name {
|
||||||
return
|
if ![load_core [subst $$name]] {
|
||||||
}
|
continue
|
||||||
|
|
||||||
# FIXME: now what can we test about the thread state?
|
|
||||||
# We do not know for certain that there should be at least
|
|
||||||
# three threads, because who knows what kind of many-to-one
|
|
||||||
# mapping various OS's may do? Let's assume that there must
|
|
||||||
# be at least two threads:
|
|
||||||
|
|
||||||
gdb_test "info threads" ".*${nl} 2 ${horiz}${nl}\\* 1 .*" \
|
|
||||||
"corefile contains at least two threads"
|
|
||||||
|
|
||||||
# One thread in the corefile should be in the "thread2" function.
|
|
||||||
|
|
||||||
gdb_test "info threads" ".* thread2 .*" \
|
|
||||||
"a corefile thread is executing thread2"
|
|
||||||
|
|
||||||
# The thread2 thread should be marked as the current thread.
|
|
||||||
|
|
||||||
gdb_test "info threads" ".*${nl}\\* ${horiz} thread2 .*" \
|
|
||||||
"thread2 is current thread in corefile"
|
|
||||||
|
|
||||||
|
|
||||||
# Test the uninitialized thread list.
|
|
||||||
|
|
||||||
if {"$core0file" != "" && [load_core $core0file]} {
|
|
||||||
set test "zeroed-threads cannot be listed"
|
|
||||||
|
|
||||||
if {!$libthread_db_seen} {
|
|
||||||
verbose -log "No libthread_db loaded - -Wl,-z,relro compilation?"
|
|
||||||
xfail $test
|
|
||||||
} else {
|
|
||||||
gdb_test "info threads" "Cannot find new threads: .*" $test
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
# FIXME: now what can we test about the thread state?
|
||||||
|
# We do not know for certain that there should be at least
|
||||||
|
# three threads, because who knows what kind of many-to-one
|
||||||
|
# mapping various OS's may do? Let's assume that there must
|
||||||
|
# be at least two threads:
|
||||||
|
|
||||||
|
gdb_test "info threads" ".*${nl} 2 ${horiz}${nl}\\* 1 .*" \
|
||||||
|
"corefile contains at least two threads"
|
||||||
|
|
||||||
|
# One thread in the corefile should be in the "thread2" function.
|
||||||
|
|
||||||
|
gdb_test "info threads" ".* thread2 .*" \
|
||||||
|
"a corefile thread is executing thread2"
|
||||||
|
|
||||||
|
# The thread2 thread should be marked as the current thread.
|
||||||
|
|
||||||
|
gdb_test "info threads" ".*${nl}\\* ${horiz} thread2 .*" \
|
||||||
|
"thread2 is current thread in corefile"
|
||||||
|
}}
|
||||||
|
|
Loading…
Reference in New Issue