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:
Doug Evans 2011-05-13 22:36:07 +00:00
parent dbaefcf757
commit 98a5dd1327
8 changed files with 275 additions and 123 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 (&current_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 (&current_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. */