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

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