summaryrefslogtreecommitdiff
path: root/gdb/linux-thread-db.c
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2012-04-17 15:51:41 +0000
committerJan Kratochvil <jan.kratochvil@redhat.com>2012-04-17 15:51:41 +0000
commit0acff7a79e754ba90c7d1622ad2c10debab3c732 (patch)
tree91143a9c85c0442cc852f23787babf8572434285 /gdb/linux-thread-db.c
parent0c4f1245d79b822f306dc2b7d2edefe4f67ed0a2 (diff)
downloadgdb-0acff7a79e754ba90c7d1622ad2c10debab3c732.tar.gz
gdb/
auto-load: Implementation. * NEWS: New descriptions for "info auto-load", "info auto-load gdb-scripts", "info auto-load python-scripts", "info auto-load local-gdbinit" and "info auto-load libthread-db". Deprecate "info auto-load-scripts", "set auto-load-scripts on|off" and "show auto-load-scripts". New description for "set auto-load", "show auto-load", "set auto-load gdb-scripts", "show auto-load gdb-scripts", "set auto-load python-scripts", "show auto-load python-scripts", "set auto-load local-gdbinit", "show auto-load local-gdbinit", "set auto-load libthread-db" and "show auto-load libthread-db". * auto-load.c: Remove include python/python-internal.h. Add includes exceptions.h, cli/cli-script.h, gdbcmd.h, cli/cli-decode.h and cli/cli-setshow.h. (GDB_AUTO_FILE_NAME, source_gdb_script_for_objfile) (auto_load_gdb_scripts, show_auto_load_gdb_scripts): New. (gdbpy_global_auto_load): Rename to ... (global_auto_load): ... here. (auto_load_local_gdbinit, auto_load_local_gdbinit_pathname) (auto_load_local_gdbinit_loaded, show_auto_load_local_gdbinit) (script_language_gdb, source_gdb_script_for_objfile): New. (struct loaded_script): New field language. (hash_loaded_script_entry, eq_loaded_script_entry): Calculate also LANGUAGE. (maybe_add_script): Add parameter language. Drop redundant entry.full_path initialization. Initialize entry.language and (*slot)->language. (auto_load_objfile_script): Change parameter suffix to language. Remove the call of maybe_add_script. Call language->source_script_for_objfile. (load_auto_scripts_for_objfile, struct collect_matching_scripts_data): New. (collect_matching_scripts): Adjust it for struct collect_matching_scripts_data. (auto_load_info_scripts_pattern_nl): New variable. (info_auto_load_scripts): Rename to ... (auto_load_info_scripts): ... here, add parameter language. Adjust it for struct collect_matching_scripts_data. (info_auto_load_gdb_scripts, info_auto_load_local_gdbinit) (set_auto_load_cmd, auto_load_set_cmdlist_get, show_auto_load_cmd) (auto_load_show_cmdlist_get, info_auto_load_cmd) (auto_load_info_cmdlist_get): New. (_initialize_auto_load): Move add_info of "auto-load-scripts" to python/py-auto-load.c. New installment for "set auto-load gdb-scripts", "info auto-load gdb-scripts", "set auto-load local-gdbinit" and "info auto-load local-gdbinit". * auto-load.h (struct script_language): New. (gdbpy_global_auto_load): Rename to ... (global_auto_load): ... here. (auto_load_local_gdbinit, auto_load_local_gdbinit_pathname) (auto_load_local_gdbinit_loaded): New declarations. (maybe_add_script): New parameter language. (auto_load_objfile_script): Change parameter suffix to language. (load_auto_scripts_for_objfile, auto_load_info_scripts_pattern_nl) (auto_load_info_scripts, auto_load_set_cmdlist_get) (auto_load_show_cmdlist_get, auto_load_info_cmdlist_get): New declarations. * linux-thread-db.c: Include auto-load.h and ctype.h. (auto_load_thread_db, show_auto_load_thread_db): New. (struct thread_db_info): New field filename. (delete_thread_db_info): Call xfree for FILENAME. (try_thread_db_load): Initialize FILENAME. (try_thread_db_load_from_pdir, try_thread_db_load_from_dir): Return if !AUTO_LOAD_THREAD_DB. (info_auto_load_libthread_db_compare, info_auto_load_libthread_db): New. (_initialize_thread_db): Install auto_load_thread_db as "set auto-load libthread-db" and install info_auto_load_libthread_db as "info auto-load libthread-db". * main.c (captured_main): Rename gdbpy_global_auto_load to global_auto_load. Initialize AUTO_LOAD_LOCAL_GDBINIT_PATHNAME and AUTO_LOAD_LOCAL_GDBINIT_LOADED. (print_gdb_help): Extend the help for 'local init file'. * python/py-auto-load.c: Remove a comment about gdb scripts extension. (GDBPY_AUTO_SECTION_NAME): Extend the comment it is Python specific. (auto_load_scripts): Rename to ... (auto_load_python_scripts): ... here, update the comment. (gdbpy_load_auto_script_for_objfile): New declaration. (show_auto_load_python_scripts, script_language_python) (gdbpy_load_auto_script_for_objfile): New. (source_section_scripts): Refactor the code. (load_auto_scripts_for_objfile): Rename to ... (gdbpy_load_auto_scripts_for_objfile): ... here, update the auto_load_objfile_script caller, drop GDBPY_GLOBAL_AUTO_LOAD checking. (info_auto_load_python_scripts): New. (gdbpy_initialize_auto_load): New variables cmd and cmd_name. Rename "set auto-load-scripts" to "set auto-load python-scripts". Register "set auto-load-scripts" as its deprecated alias. Register "info auto-load python-scripts". Register "info auto-load-scripts" as its deprecated alias. (load_auto_scripts_for_objfile): Rename to ... (gdbpy_load_auto_scripts_for_objfile): ... here. * python/python.h (load_auto_scripts_for_objfile): Rename to ... (gdbpy_load_auto_scripts_for_objfile): ... here. gdb/doc/ auto-load: Implementation. * gdb.texinfo (Mode Options): New anchor for -nx. (Startup): New anchors for Option -init-eval-command, Home Directory Init File and Init File in the Current Directory during Startup. Mention set auto-load local-gdbinit with a reference. Change the sample code to "set auto-load python-scripts". (Threads): New anchor set libthread-db-search-path. Provide references to libthread_db.so.1 file. (Controlling GDB): New menu item for Auto-loading. (Auto-loading, Init File in the Current Directory) (libthread_db.so.1 file, objfile-gdb.gdb file): New nodes. (Python): Rename the menu item Auto-loading to Python Auto-loading. (Writing a Pretty-Printer, Objfiles In Python): Update the renamed reference. (Auto-loading): Rename to ... (Python Auto-loading): ... here. Change "set auto-load-scripts" to "set auto-load python-scripts", new anchor for it. Change "show auto-load-scripts" to "show auto-load python-scripts", new anchor for it. Change "info auto-load-scripts" to "info auto-load python-scripts", new anchor for it. Change "scripts" to "Python scripts". gdb/testsuite/ auto-load: Implementation. * gdb.base/help.exp (test set height): Increase the height. * gdb.python/py-objfile-script.exp (info auto-load-scripts): Change to ... (info auto-load python-scripts): ... here. * gdb.python/py-section-script.exp (info auto-load-scripts *): Change to ... (info auto-load python-scripts *): ... here.
Diffstat (limited to 'gdb/linux-thread-db.c')
-rw-r--r--gdb/linux-thread-db.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 4d09c6e3ba2..4499b8fe49a 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -41,8 +41,10 @@
#include "linux-nat.h"
#include "linux-procfs.h"
#include "linux-osdata.h"
+#include "auto-load.h"
#include <signal.h>
+#include <ctype.h>
#ifdef HAVE_GNU_LIBC_VERSION_H
#include <gnu/libc-version.h>
@@ -76,6 +78,21 @@
static char *libthread_db_search_path;
+/* Set to non-zero if thread_db auto-loading is enabled
+ by the "set auto-load libthread-db" command. */
+static int auto_load_thread_db = 1;
+
+/* "show" command for the auto_load_thread_db configuration variable. */
+
+static void
+show_auto_load_thread_db (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Auto-loading of inferior specific libthread_db "
+ "is %s.\n"),
+ value);
+}
+
static void
set_libthread_db_search_path (char *ignored, int from_tty,
struct cmd_list_element *c)
@@ -120,6 +137,10 @@ struct thread_db_info
/* Handle from dlopen for libthread_db.so. */
void *handle;
+ /* Absolute pathname from gdb_realpath to disk file used for dlopen-ing
+ HANDLE. It may be NULL for system library. */
+ char *filename;
+
/* Structure that identifies the child process for the
<proc_service.h> interface. */
struct ps_prochandle proc_handle;
@@ -249,6 +270,8 @@ delete_thread_db_info (int pid)
if (info->handle != NULL)
dlclose (info->handle);
+ xfree (info->filename);
+
if (info_prev)
info_prev->next = info->next;
else
@@ -808,6 +831,10 @@ try_thread_db_load (const char *library)
info = add_thread_db_info (handle);
+ /* Do not save system library name, that one is always trusted. */
+ if (strchr (library, '/') != NULL)
+ info->filename = gdb_realpath (library);
+
if (try_thread_db_load_1 (info))
return 1;
@@ -857,6 +884,9 @@ try_thread_db_load_from_pdir (void)
{
struct objfile *obj;
+ if (!auto_load_thread_db)
+ return 0;
+
ALL_OBJFILES (obj)
if (libpthread_name_p (obj->name))
{
@@ -896,6 +926,9 @@ try_thread_db_load_from_dir (const char *dir, size_t dir_len)
char *path;
int result;
+ if (!auto_load_thread_db)
+ return 0;
+
path = xmalloc (dir_len + 1 + strlen (LIBTHREAD_DB_SO) + 1);
cleanup = make_cleanup (xfree, path);
@@ -1801,6 +1834,150 @@ thread_db_resume (struct target_ops *ops,
beneath->to_resume (beneath, ptid, step, signo);
}
+/* qsort helper function for info_auto_load_libthread_db, sort the
+ thread_db_info pointers primarily by their FILENAME and secondarily by their
+ PID, both in ascending order. */
+
+static int
+info_auto_load_libthread_db_compare (const void *ap, const void *bp)
+{
+ struct thread_db_info *a = *(struct thread_db_info **) ap;
+ struct thread_db_info *b = *(struct thread_db_info **) bp;
+ int retval;
+
+ retval = strcmp (a->filename, b->filename);
+ if (retval)
+ return retval;
+
+ return (a->pid > b->pid) - (a->pid - b->pid);
+}
+
+/* Implement 'info auto-load libthread-db'. */
+
+static void
+info_auto_load_libthread_db (char *args, int from_tty)
+{
+ struct ui_out *uiout = current_uiout;
+ const char *cs = args ? args : "";
+ struct thread_db_info *info, **array;
+ unsigned info_count, unique_filenames;
+ size_t max_filename_len, max_pids_len, pids_len;
+ struct cleanup *back_to;
+ char *pids;
+ int i;
+
+ while (isspace (*cs))
+ cs++;
+ if (*cs)
+ error (_("'info auto-load libthread-db' does not accept any parameters"));
+
+ info_count = 0;
+ for (info = thread_db_list; info; info = info->next)
+ if (info->filename != NULL)
+ info_count++;
+
+ array = xmalloc (sizeof (*array) * info_count);
+ back_to = make_cleanup (xfree, array);
+
+ info_count = 0;
+ for (info = thread_db_list; info; info = info->next)
+ if (info->filename != NULL)
+ array[info_count++] = info;
+
+ /* Sort ARRAY by filenames and PIDs. */
+
+ qsort (array, info_count, sizeof (*array),
+ info_auto_load_libthread_db_compare);
+
+ /* Calculate the number of unique filenames (rows) and the maximum string
+ length of PIDs list for the unique filenames (columns). */
+
+ unique_filenames = 0;
+ max_filename_len = 0;
+ max_pids_len = 0;
+ pids_len = 0;
+ for (i = 0; i < info_count; i++)
+ {
+ int pid = array[i]->pid;
+ size_t this_pid_len;
+
+ for (this_pid_len = 0; pid != 0; pid /= 10)
+ this_pid_len++;
+
+ if (i == 0 || strcmp (array[i - 1]->filename, array[i]->filename) != 0)
+ {
+ unique_filenames++;
+ max_filename_len = max (max_filename_len,
+ strlen (array[i]->filename));
+
+ if (i > 0)
+ {
+ pids_len -= strlen (", ");
+ max_pids_len = max (max_pids_len, pids_len);
+ }
+ pids_len = 0;
+ }
+ pids_len += this_pid_len + strlen (", ");
+ }
+ if (i)
+ {
+ pids_len -= strlen (", ");
+ max_pids_len = max (max_pids_len, pids_len);
+ }
+
+ /* Table header shifted right by preceding "libthread-db: " would not match
+ its columns. */
+ if (info_count > 0 && args == auto_load_info_scripts_pattern_nl)
+ ui_out_text (uiout, "\n");
+
+ make_cleanup_ui_out_table_begin_end (uiout, 2, unique_filenames,
+ "LinuxThreadDbTable");
+
+ ui_out_table_header (uiout, max_filename_len, ui_left, "filename",
+ "Filename");
+ ui_out_table_header (uiout, pids_len, ui_left, "PIDs", "Pids");
+ ui_out_table_body (uiout);
+
+ pids = xmalloc (max_pids_len + 1);
+ make_cleanup (xfree, pids);
+
+ /* Note I is incremented inside the cycle, not at its end. */
+ for (i = 0; i < info_count;)
+ {
+ struct cleanup *chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+ char *pids_end;
+
+ info = array[i];
+ ui_out_field_string (uiout, "filename", info->filename);
+ pids_end = pids;
+
+ while (i < info_count && strcmp (info->filename, array[i]->filename) == 0)
+ {
+ if (pids_end != pids)
+ {
+ *pids_end++ = ',';
+ *pids_end++ = ' ';
+ }
+ pids_end += xsnprintf (pids_end, &pids[max_pids_len + 1] - pids_end,
+ "%u", array[i]->pid);
+ gdb_assert (pids_end < &pids[max_pids_len + 1]);
+
+ i++;
+ }
+ *pids_end = '\0';
+
+ ui_out_field_string (uiout, "pids", pids);
+
+ ui_out_text (uiout, "\n");
+ do_cleanups (chain);
+ }
+
+ do_cleanups (back_to);
+
+ if (info_count == 0)
+ ui_out_message (uiout, 0, _("No auto-loaded libthread-db.\n"));
+}
+
static void
init_thread_db_ops (void)
{
@@ -1862,6 +2039,23 @@ When non-zero, libthread-db debugging is enabled."),
show_libthread_db_debug,
&setdebuglist, &showdebuglist);
+ add_setshow_boolean_cmd ("libthread-db", class_support,
+ &auto_load_thread_db, _("\
+Enable or disable auto-loading of inferior specific libthread_db."), _("\
+Show whether auto-loading inferior specific libthread_db is enabled."), _("\
+If enabled, libthread_db will be searched in 'set libthread-db-search-path'\n\
+locations to load libthread_db compatible with the inferior.\n\
+Standard system libthread_db still gets loaded even with this option off.\n\
+This options has security implications for untrusted inferiors."),
+ NULL, show_auto_load_thread_db,
+ auto_load_set_cmdlist_get (),
+ auto_load_show_cmdlist_get ());
+
+ add_cmd ("libthread-db", class_info, info_auto_load_libthread_db,
+ _("Print the list of loaded inferior specific libthread_db.\n\
+Usage: info auto-load libthread-db"),
+ auto_load_info_cmdlist_get ());
+
/* Add ourselves to objfile event chain. */
observer_attach_new_objfile (thread_db_new_objfile);