Support $pdir and $sdir in libthread-db-search-path.
* NEWS: Mention $sdir,$pdir. * gdb_thread_db.h (LIBTHREAD_DB_SEARCH_PATH): Add $sdir:$pdir. * linux-thread-db.c (try_thread_db_load_from_pdir): New function. (try_thread_db_load_from_sdir): New function. (try_thread_db_load_from_dir): New function. (thread_db_load_search): Handle $pdir, $sdir. Remove trying of system directories if search of libthread-db-search-path fails, that is now done via $sdir. (has_libpthread): New function. (thread_db_load): Remove search for libthread_db in directory of libpthread, that is now done via $pdir. gdbserver/ * thread-db.c (try_thread_db_load_from_sdir): New function. (try_thread_db_load_from_dir): New function. (thread_db_load_search): Handle $sdir, ignore $pdir. Remove trying of system directories if search of libthread-db-search-path fails, that is now done via $sdir. doc/ * gdb.texinfo (Threads): Document $sdir,$pdir. (Server): Document $pdir exception.
This commit is contained in:
parent
dbaefcf757
commit
98a5dd1327
@ -1,5 +1,18 @@
|
||||
2011-05-13 Doug Evans <dje@google.com>
|
||||
|
||||
Support $pdir and $sdir in libthread-db-search-path.
|
||||
* NEWS: Mention $sdir,$pdir.
|
||||
* gdb_thread_db.h (LIBTHREAD_DB_SEARCH_PATH): Add $sdir:$pdir.
|
||||
* linux-thread-db.c (try_thread_db_load_from_pdir): New function.
|
||||
(try_thread_db_load_from_sdir): New function.
|
||||
(try_thread_db_load_from_dir): New function.
|
||||
(thread_db_load_search): Handle $pdir, $sdir. Remove trying of
|
||||
system directories if search of libthread-db-search-path fails,
|
||||
that is now done via $sdir.
|
||||
(has_libpthread): New function.
|
||||
(thread_db_load): Remove search for libthread_db in directory of
|
||||
libpthread, that is now done via $pdir.
|
||||
|
||||
* NEWS: Mention "info auto-load-scripts".
|
||||
* python/py-auto-load.c (struct auto_load_pspace_info): New member
|
||||
script_not_found_warning_printed.
|
||||
|
14
gdb/NEWS
14
gdb/NEWS
@ -3,6 +3,20 @@
|
||||
|
||||
*** Changes since GDB 7.3
|
||||
|
||||
* libthread-db-search-path now supports two special values: $sdir and $pdir.
|
||||
$sdir specifies the default system locations of shared libraries.
|
||||
$pdir specifies the directory where the libpthread used by the application
|
||||
lives.
|
||||
|
||||
GDB no longer looks in $sdir and $pdir after it has searched the directories
|
||||
mentioned in libthread-db-search-path. If you want to search those
|
||||
directories, they must be specified in libthread-db-search-path.
|
||||
The default value of libthread-db-search-path on GNU/Linux and Solaris
|
||||
systems is now "$sdir:$pdir".
|
||||
|
||||
$pdir is not supported by gdbserver, it is currently ignored.
|
||||
$sdir is supported by gdbserver.
|
||||
|
||||
* New configure option --with-iconv-bin.
|
||||
When using the internationalization support like the one in the GNU C
|
||||
library, GDB will invoke the "iconv" program to get a list of supported
|
||||
|
@ -1,5 +1,8 @@
|
||||
2011-05-13 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.texinfo (Threads): Document $sdir,$pdir.
|
||||
(Server): Document $pdir exception.
|
||||
|
||||
* gdb.texinfo (Auto-loading): Document "info auto-load-scripts".
|
||||
|
||||
* gdb.texinfo (Threads): Clarify default value for
|
||||
|
@ -2858,16 +2858,22 @@ watchpoints in programs with multiple threads.
|
||||
If this variable is set, @var{path} is a colon-separated list of
|
||||
directories @value{GDBN} will use to search for @code{libthread_db}.
|
||||
If you omit @var{path}, @samp{libthread-db-search-path} will be reset to
|
||||
its default value (an empty list on @sc{gnu}/Linux and Solaris systems).
|
||||
its default value (@code{$sdir:$pdir} on @sc{gnu}/Linux and Solaris systems).
|
||||
Internally, the default value comes from the @code{LIBTHREAD_DB_SEARCH_PATH}
|
||||
macro.
|
||||
|
||||
On @sc{gnu}/Linux and Solaris systems, @value{GDBN} uses a ``helper''
|
||||
@code{libthread_db} library to obtain information about threads in the
|
||||
inferior process. @value{GDBN} will use @samp{libthread-db-search-path}
|
||||
to find @code{libthread_db}. If that fails, @value{GDBN} will continue
|
||||
with default system shared library directories, and finally the directory
|
||||
from which @code{libpthread} was loaded in the inferior process.
|
||||
to find @code{libthread_db}.
|
||||
|
||||
A special entry @samp{$sdir} for @samp{libthread-db-search-path}
|
||||
refers to the default system directories that are
|
||||
normally searched for loading shared libraries.
|
||||
|
||||
A special entry @samp{$pdir} for @samp{libthread-db-search-path}
|
||||
refers to the directory from which @code{libpthread}
|
||||
was loaded in the inferior process.
|
||||
|
||||
For any @code{libthread_db} library @value{GDBN} finds in above directories,
|
||||
@value{GDBN} attempts to initialize it with the current inferior process.
|
||||
@ -16382,6 +16388,9 @@ directories to search for @code{libthread_db} (@pxref{Threads,,set
|
||||
libthread-db-search-path}). If you omit @var{path},
|
||||
@samp{libthread-db-search-path} will be reset to its default value.
|
||||
|
||||
The special entry @samp{$pdir} for @samp{libthread-db-search-path} is
|
||||
not supported in @code{gdbserver}.
|
||||
|
||||
@item monitor exit
|
||||
Tell gdbserver to exit immediately. This command should be followed by
|
||||
@code{disconnect} to close the debugging session. @code{gdbserver} will
|
||||
|
@ -6,7 +6,10 @@
|
||||
#endif
|
||||
|
||||
#ifndef LIBTHREAD_DB_SEARCH_PATH
|
||||
#define LIBTHREAD_DB_SEARCH_PATH ""
|
||||
/* $sdir appears before $pdir for some minimal security protection:
|
||||
we trust the system libthread_db.so a bit more than some random
|
||||
libthread_db associated with whatever libpthread the app is using. */
|
||||
#define LIBTHREAD_DB_SEARCH_PATH "$sdir:$pdir"
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -1,3 +1,11 @@
|
||||
2011-05-13 Doug Evans <dje@google.com>
|
||||
|
||||
* thread-db.c (try_thread_db_load_from_sdir): New function.
|
||||
(try_thread_db_load_from_dir): New function.
|
||||
(thread_db_load_search): Handle $sdir, ignore $pdir.
|
||||
Remove trying of system directories if search of
|
||||
libthread-db-search-path fails, that is now done via $sdir.
|
||||
|
||||
2011-05-12 Kwok Cheung Yeung <kcy@codesourcery.com>
|
||||
|
||||
* server.c (handle_query): Add EnableDisableTracepoints to the list
|
||||
|
@ -698,10 +698,50 @@ try_thread_db_load (const char *library)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle $sdir in libthread-db-search-path.
|
||||
Look for libthread_db in the system dirs, or wherever a plain
|
||||
dlopen(file_without_path) will look.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
try_thread_db_load_from_sdir (void)
|
||||
{
|
||||
return try_thread_db_load (LIBTHREAD_DB_SO);
|
||||
}
|
||||
|
||||
/* Try to load libthread_db from directory DIR of length DIR_LEN.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
try_thread_db_load_from_dir (const char *dir, size_t dir_len)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (dir_len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
|
||||
{
|
||||
char *cp = xmalloc (dir_len + 1);
|
||||
|
||||
memcpy (cp, dir, dir_len);
|
||||
cp[dir_len] = '\0';
|
||||
warning (_("libthread-db-search-path component too long,"
|
||||
" ignored: %s."), cp);
|
||||
free (cp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (path, dir, dir_len);
|
||||
path[dir_len] = '/';
|
||||
strcpy (path + dir_len + 1, LIBTHREAD_DB_SO);
|
||||
return try_thread_db_load (path);
|
||||
}
|
||||
|
||||
/* Search libthread_db_search_path for libthread_db which "agrees"
|
||||
to work on current inferior.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
thread_db_load_search (void)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *search_path;
|
||||
int rc = 0;
|
||||
|
||||
@ -712,49 +752,45 @@ thread_db_load_search (void)
|
||||
while (*search_path)
|
||||
{
|
||||
const char *end = strchr (search_path, ':');
|
||||
const char *this_dir = search_path;
|
||||
size_t this_dir_len;
|
||||
|
||||
if (end)
|
||||
{
|
||||
size_t len = end - search_path;
|
||||
if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
|
||||
{
|
||||
char *cp = xmalloc (len + 1);
|
||||
memcpy (cp, search_path, len);
|
||||
cp[len] = '\0';
|
||||
warning ("libthread_db_search_path component too long, "
|
||||
"ignored: %s.", cp);
|
||||
free (cp);
|
||||
search_path += len + 1;
|
||||
continue;
|
||||
}
|
||||
memcpy (path, search_path, len);
|
||||
path[len] = '\0';
|
||||
search_path += len + 1;
|
||||
this_dir_len = end - search_path;
|
||||
search_path += this_dir_len + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = strlen (search_path);
|
||||
this_dir_len = strlen (this_dir);
|
||||
search_path += this_dir_len;
|
||||
}
|
||||
|
||||
if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
|
||||
if (this_dir_len == sizeof ("$pdir") - 1
|
||||
&& strncmp (this_dir, "$pdir", this_dir_len) == 0)
|
||||
{
|
||||
/* We don't maintain a list of loaded libraries so we don't know
|
||||
where libpthread lives. We *could* fetch the info, but we don't
|
||||
do that yet. Ignore it. */
|
||||
}
|
||||
else if (this_dir_len == sizeof ("$sdir") - 1
|
||||
&& strncmp (this_dir, "$sdir", this_dir_len) == 0)
|
||||
{
|
||||
if (try_thread_db_load_from_sdir ())
|
||||
{
|
||||
warning ("libthread_db_search_path component too long,"
|
||||
" ignored: %s.", search_path);
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
memcpy (path, search_path, len + 1);
|
||||
search_path += len;
|
||||
}
|
||||
strcat (path, "/");
|
||||
strcat (path, LIBTHREAD_DB_SO);
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "thread_db_load_search trying %s\n", path);
|
||||
if (try_thread_db_load (path))
|
||||
else
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
if (try_thread_db_load_from_dir (this_dir, this_dir_len))
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rc == 0)
|
||||
rc = try_thread_db_load (LIBTHREAD_DB_SO);
|
||||
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "thread_db_load_search returning %d\n", rc);
|
||||
|
@ -812,95 +812,14 @@ try_thread_db_load (const char *library)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search libthread_db_search_path for libthread_db which "agrees"
|
||||
to work on current inferior. */
|
||||
/* Handle $pdir in libthread-db-search-path.
|
||||
Look for libthread_db in the directory of libpthread.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
thread_db_load_search (void)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *search_path = libthread_db_search_path;
|
||||
int rc = 0;
|
||||
|
||||
while (*search_path)
|
||||
{
|
||||
const char *end = strchr (search_path, ':');
|
||||
|
||||
if (end)
|
||||
{
|
||||
size_t len = end - search_path;
|
||||
|
||||
if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
|
||||
{
|
||||
char *cp = xmalloc (len + 1);
|
||||
|
||||
memcpy (cp, search_path, len);
|
||||
cp[len] = '\0';
|
||||
warning (_("libthread_db_search_path component too long,"
|
||||
" ignored: %s."), cp);
|
||||
xfree (cp);
|
||||
search_path += len + 1;
|
||||
continue;
|
||||
}
|
||||
memcpy (path, search_path, len);
|
||||
path[len] = '\0';
|
||||
search_path += len + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = strlen (search_path);
|
||||
|
||||
if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
|
||||
{
|
||||
warning (_("libthread_db_search_path component too long,"
|
||||
" ignored: %s."), search_path);
|
||||
break;
|
||||
}
|
||||
memcpy (path, search_path, len + 1);
|
||||
search_path += len;
|
||||
}
|
||||
strcat (path, "/");
|
||||
strcat (path, LIBTHREAD_DB_SO);
|
||||
if (try_thread_db_load (path))
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rc == 0)
|
||||
rc = try_thread_db_load (LIBTHREAD_DB_SO);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Attempt to load and initialize libthread_db.
|
||||
Return 1 on success. */
|
||||
|
||||
static int
|
||||
thread_db_load (void)
|
||||
try_thread_db_load_from_pdir (void)
|
||||
{
|
||||
struct objfile *obj;
|
||||
struct thread_db_info *info;
|
||||
|
||||
info = get_thread_db_info (GET_PID (inferior_ptid));
|
||||
|
||||
if (info != NULL)
|
||||
return 1;
|
||||
|
||||
/* Don't attempt to use thread_db on executables not running
|
||||
yet. */
|
||||
if (!target_has_registers)
|
||||
return 0;
|
||||
|
||||
/* Don't attempt to use thread_db for remote targets. */
|
||||
if (!(target_can_run (¤t_target) || core_bfd))
|
||||
return 0;
|
||||
|
||||
if (thread_db_load_search ())
|
||||
return 1;
|
||||
|
||||
/* None of the libthread_db's on our search path, not the system default
|
||||
ones worked. If the executable is dynamically linked against
|
||||
libpthread, try loading libthread_db from the same directory. */
|
||||
|
||||
ALL_OBJFILES (obj)
|
||||
if (libpthread_name_p (obj->name))
|
||||
@ -927,10 +846,157 @@ thread_db_load (void)
|
||||
if (try_thread_db_load (path))
|
||||
return 1;
|
||||
}
|
||||
warning (_("Unable to find libthread_db matching inferior's thread"
|
||||
" library, thread debugging will not be available."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle $sdir in libthread-db-search-path.
|
||||
Look for libthread_db in the system dirs, or wherever a plain
|
||||
dlopen(file_without_path) will look.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
try_thread_db_load_from_sdir (void)
|
||||
{
|
||||
return try_thread_db_load (LIBTHREAD_DB_SO);
|
||||
}
|
||||
|
||||
/* Try to load libthread_db from directory DIR of length DIR_LEN.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
try_thread_db_load_from_dir (const char *dir, size_t dir_len)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (dir_len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof (path))
|
||||
{
|
||||
char *cp = xmalloc (dir_len + 1);
|
||||
|
||||
memcpy (cp, dir, dir_len);
|
||||
cp[dir_len] = '\0';
|
||||
warning (_("libthread-db-search-path component too long,"
|
||||
" ignored: %s."), cp);
|
||||
xfree (cp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (path, dir, dir_len);
|
||||
path[dir_len] = '/';
|
||||
strcpy (path + dir_len + 1, LIBTHREAD_DB_SO);
|
||||
return try_thread_db_load (path);
|
||||
}
|
||||
|
||||
/* Search libthread_db_search_path for libthread_db which "agrees"
|
||||
to work on current inferior.
|
||||
The result is true for success. */
|
||||
|
||||
static int
|
||||
thread_db_load_search (void)
|
||||
{
|
||||
const char *search_path = libthread_db_search_path;
|
||||
int rc = 0;
|
||||
|
||||
while (*search_path)
|
||||
{
|
||||
const char *end = strchr (search_path, ':');
|
||||
const char *this_dir = search_path;
|
||||
size_t this_dir_len;
|
||||
|
||||
if (end)
|
||||
{
|
||||
this_dir_len = end - search_path;
|
||||
search_path += this_dir_len + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
this_dir_len = strlen (this_dir);
|
||||
search_path += this_dir_len;
|
||||
}
|
||||
|
||||
if (this_dir_len == sizeof ("$pdir") - 1
|
||||
&& strncmp (this_dir, "$pdir", this_dir_len) == 0)
|
||||
{
|
||||
if (try_thread_db_load_from_pdir ())
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (this_dir_len == sizeof ("$sdir") - 1
|
||||
&& strncmp (this_dir, "$sdir", this_dir_len) == 0)
|
||||
{
|
||||
if (try_thread_db_load_from_sdir ())
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (try_thread_db_load_from_dir (this_dir, this_dir_len))
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (libthread_db_debug)
|
||||
printf_unfiltered (_("thread_db_load_search returning %d\n"), rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Return non-zero if the inferior has a libpthread. */
|
||||
|
||||
static int
|
||||
has_libpthread (void)
|
||||
{
|
||||
struct objfile *obj;
|
||||
|
||||
ALL_OBJFILES (obj)
|
||||
if (libpthread_name_p (obj->name))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempt to load and initialize libthread_db.
|
||||
Return 1 on success. */
|
||||
|
||||
static int
|
||||
thread_db_load (void)
|
||||
{
|
||||
struct thread_db_info *info;
|
||||
|
||||
info = get_thread_db_info (GET_PID (inferior_ptid));
|
||||
|
||||
if (info != NULL)
|
||||
return 1;
|
||||
|
||||
/* Don't attempt to use thread_db on executables not running
|
||||
yet. */
|
||||
if (!target_has_registers)
|
||||
return 0;
|
||||
|
||||
/* Don't attempt to use thread_db for remote targets. */
|
||||
if (!(target_can_run (¤t_target) || core_bfd))
|
||||
return 0;
|
||||
|
||||
if (thread_db_load_search ())
|
||||
return 1;
|
||||
|
||||
/* We couldn't find a libthread_db.
|
||||
If the inferior has a libpthread warn the user. */
|
||||
if (has_libpthread ())
|
||||
{
|
||||
warning (_("Unable to find libthread_db matching inferior's thread"
|
||||
" library, thread debugging will not be available."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Either this executable isn't using libpthread at all, or it is
|
||||
statically linked. Since we can't easily distinguish these two cases,
|
||||
no warning is issued. */
|
||||
|
Loading…
Reference in New Issue
Block a user