Add -file-list-shared-libraries MI command
authorMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Mon, 20 Mar 2017 18:57:51 +0000 (14:57 -0400)
committerMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Mon, 20 Mar 2017 18:57:51 +0000 (14:57 -0400)
This change adds the MI equivalent for the "info sharedlibrary"
command. The command was already partially documented but ignored as
it was not implemented. The new MI command works similarly to the CLI
command, taking an optional regular expression as an argument and
outputting the library information.

I included a test for the new command in mi-solib.exp.

gdb/doc/ChangeLog:

* gdb.texinfo (gdb/mi Symbol Query Commands): Document new MI
command file-list-shared-libraries
(GDB/MI Async Records): Update documentation of library-loaded with new
field.

gdb/ChangeLog:

* NEWS: Add an entry about new '-file-list-shared-libraries' command.
* mi/mi-cmd-file.c (mi_cmd_file_list_shared_libraries):
New function definition.
* mi/mi-cmds.c (mi_cmds): Add -file-list-shared-libraries command.
* mi/mi-cmds.h (mi_cmd_file_list_shared_libraries):
New function declaration.
* mi/mi-interp.c (mi_output_solib_attribs): New Function.
* mi/mi-interp.h: New file.
* solib.c (info_sharedlibrary_command): Replace for loop with
ALL_SO_LIBS macro
* solib.h (update_solib_list): New function declaration.
(so_list_head): Move macro.
* solist.h (ALL_SO_LIBS): New macro.

gdb/testsuite/ChangeLog:

* gdb.mi/mi-solib.exp (test_file_list_shared_libraries):
New procedure.

Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
14 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/mi/mi-cmd-file.c
gdb/mi/mi-cmds.c
gdb/mi/mi-cmds.h
gdb/mi/mi-interp.c
gdb/mi/mi-interp.h [new file with mode: 0644]
gdb/solib.c
gdb/solib.h
gdb/solist.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.mi/mi-solib.exp

index 62db6b9d2c1b3347153e765c2a87d2b64ea5dd82..c1ad90c78afe1594216be6a9608a15fa6ec54c61 100644 (file)
@@ -1,3 +1,19 @@
+2017-03-20  Marc-Andre Laperle  <marc-andre.laperle@ericsson.com>
+
+       * NEWS: Add an entry about new '-file-list-shared-libraries' command.
+       * mi/mi-cmd-file.c (mi_cmd_file_list_shared_libraries):
+       New function definition.
+       * mi/mi-cmds.c (mi_cmds): Add -file-list-shared-libraries command.
+       * mi/mi-cmds.h (mi_cmd_file_list_shared_libraries):
+       New function declaration.
+       * mi/mi-interp.c (mi_output_solib_attribs): New Function.
+       * mi/mi-interp.h: New file.
+       * solib.c (info_sharedlibrary_command): Replace for loop with
+       ALL_SO_LIBS macro
+       * solib.h (update_solib_list): New function declaration.
+       (so_list_head): Move macro.
+       * solist.h (ALL_SO_LIBS): New macro.
+
 2017-03-20  Marc-Andre Laperle  <marc-andre.laperle@ericsson.com>
 
        * infcmd.c (post_create_inferior): Remove unused argument in
index cf585954d79186ef76cc3d16b3b3f3f5ebb58626..b5c68c5a5250c2bb557cadd54321bbe0d08edbce 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -84,6 +84,10 @@ flash-erase
   Erases all the flash memory regions reported by the target.  This is
   equivalent to the CLI command flash-erase.
 
+-file-list-shared-libraries
+  List the shared libraries in the program.  This is
+  equivalent to the CLI command "info shared".
+
 * New commands
 
 set disassembler-options
index 8b8820e98bd3f525f8f32c08f9e9af01149ff078..1657ab83d31188f5df9899451a87dc81f5dedeb5 100644 (file)
@@ -1,3 +1,10 @@
+2017-03-20  Marc-Andre Laperle  <marc-andre.laperle@ericsson.com>
+
+       * gdb.texinfo (gdb/mi Symbol Query Commands): Document new MI
+       command file-list-shared-libraries
+       (GDB/MI Async Records): Update documentation of library-loaded with new
+       field.
+
 2017-03-16  Doug Evans  <dje@google.com>
 
        * guile.texi (Lazy Strings In Guile): Mention arrays.
index 5cf0f973bb5aaedd8ab3bd68ec2562f6046664fd..c1dfdeb913f4d9b0fb3e5f7202a423044fd05f02 100644 (file)
@@ -26603,8 +26603,8 @@ that thread.
 
 @item =library-loaded,...
 Reports that a new library file was loaded by the program.  This
-notification has 4 fields---@var{id}, @var{target-name},
-@var{host-name}, and @var{symbols-loaded}.  The @var{id} field is an
+notification has 5 fields---@var{id}, @var{target-name},
+@var{host-name}, @var{symbols-loaded} and @var{ranges}.  The @var{id} field is an
 opaque identifier of the library.  For remote debugging case,
 @var{target-name} and @var{host-name} fields give the name of the
 library file on the target, and on the host respectively.  For native
@@ -26614,7 +26614,8 @@ and should not be relied on to convey any useful information.  The
 @var{thread-group} field, if present, specifies the id of the thread
 group in whose context the library was loaded.  If the field is
 absent, it means the library was loaded in the context of all present
-thread groups.
+thread groups.  The @var{ranges} field specifies the ranges of addresses belonging
+to this library.
 
 @item =library-unloaded,...
 Reports that a library was unloaded by the program.  This notification
@@ -31535,26 +31536,45 @@ The @value{GDBN} equivalent is @samp{info sources}.
 (gdb)
 @end smallexample
 
-@ignore
 @subheading The @code{-file-list-shared-libraries} Command
 @findex -file-list-shared-libraries
 
 @subsubheading Synopsis
 
 @smallexample
- -file-list-shared-libraries
+ -file-list-shared-libraries [ @var{regexp} ]
 @end smallexample
 
 List the shared libraries in the program.
+With a regular expression @var{regexp}, only those libraries whose
+names match @var{regexp} are listed.
 
 @subsubheading @value{GDBN} Command
 
-The corresponding @value{GDBN} command is @samp{info shared}.
+The corresponding @value{GDBN} command is @samp{info shared}.  The fields
+have a similar meaning to the @code{=library-loaded} notification.
+The @code{ranges} field specifies the multiple segments belonging to this
+library.  Each range has the following fields:
+
+@table @samp
+@item from
+The address defining the inclusive lower bound of the segment.
+@item to
+The address defining the exclusive upper bound of the segment.
+@end table
 
 @subsubheading Example
-N.A.
+@smallexample
+(gdb)
+-file-list-exec-source-files
+^done,shared-libraries=[
+@{id="/lib/libfoo.so",target-name="/lib/libfoo.so",host-name="/lib/libfoo.so",symbols-loaded="1",thread-group="i1",ranges=[@{from="0x72815989",to="0x728162c0"@}]@},
+@{id="/lib/libbar.so",target-name="/lib/libbar.so",host-name="/lib/libbar.so",symbols-loaded="1",thread-group="i1",ranges=[@{from="0x76ee48c0",to="0x76ee9160"@}]@}]
+(gdb)
+@end smallexample
 
 
+@ignore
 @subheading The @code{-file-list-symbol-files} Command
 @findex -file-list-symbol-files
 
index 71e2845a413807cc64f99c48f76db2552890c067..a2ad392c9fdc6fe75047dab46383ed5b29777706 100644 (file)
 #include "defs.h"
 #include "mi-cmds.h"
 #include "mi-getopt.h"
+#include "mi-interp.h"
 #include "ui-out.h"
 #include "symtab.h"
 #include "source.h"
 #include "objfiles.h"
 #include "psymtab.h"
+#include "solib.h"
+#include "solist.h"
+#include "gdb_regex.h"
 
 /* Return to the client the absolute path and line number of the 
    current file being executed.  */
@@ -106,3 +110,56 @@ mi_cmd_file_list_exec_source_files (char *command, char **argv, int argc)
 
   uiout->end (ui_out_type_list);
 }
+
+/* See mi-cmds.h.  */
+
+void
+mi_cmd_file_list_shared_libraries (char *command, char **argv, int argc)
+{
+  struct ui_out *uiout = current_uiout;
+  const char *pattern;
+  struct so_list *so = NULL;
+  struct gdbarch *gdbarch = target_gdbarch ();
+
+  switch (argc)
+    {
+    case 0:
+      pattern = NULL;
+      break;
+    case 1:
+      pattern = argv[0];
+      break;
+    default:
+      error (_("Usage: -file-list-shared-libraries [REGEXP]"));
+    }
+
+  if (pattern != NULL)
+    {
+      const char *re_err = re_comp (pattern);
+
+      if (re_err != NULL)
+       error (_("Invalid regexp: %s"), re_err);
+    }
+
+  update_solib_list (1);
+
+  /* Print the table header.  */
+  struct cleanup *cleanup
+    = make_cleanup_ui_out_list_begin_end (uiout, "shared-libraries");
+
+  ALL_SO_LIBS (so)
+    {
+      if (so->so_name[0] == '\0')
+       continue;
+      if (pattern != NULL && !re_exec (so->so_name))
+       continue;
+
+      struct cleanup *tuple_clean_up
+        = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+      mi_output_solib_attribs (uiout, so);
+
+      do_cleanups (tuple_clean_up);
+    }
+
+  do_cleanups (cleanup);
+}
index abb70bde83dc965a813c9de84129cfc222880e5c..b7494ce838ea2921f43f862551468e6401ed8fab 100644 (file)
@@ -115,6 +115,8 @@ static struct mi_cmd mi_cmds[] =
                 mi_cmd_file_list_exec_source_file),
   DEF_MI_CMD_MI ("file-list-exec-source-files",
                 mi_cmd_file_list_exec_source_files),
+  DEF_MI_CMD_MI ("file-list-shared-libraries",
+                mi_cmd_file_list_shared_libraries),
   DEF_MI_CMD_CLI ("file-symbol-file", "symbol-file", 1),
   DEF_MI_CMD_MI ("gdb-exit", mi_cmd_gdb_exit),
   DEF_MI_CMD_CLI_1 ("gdb-set", "set", 1,
index d0906e6b6c8b2baafb4bcb33938d7a6d304adc1b..fcadfff92caf858fe9c1a1454f634f234e900972 100644 (file)
@@ -70,6 +70,7 @@ extern mi_cmd_argv_ftype mi_cmd_exec_step;
 extern mi_cmd_argv_ftype mi_cmd_exec_step_instruction;
 extern mi_cmd_argv_ftype mi_cmd_file_list_exec_source_file;
 extern mi_cmd_argv_ftype mi_cmd_file_list_exec_source_files;
+extern mi_cmd_argv_ftype mi_cmd_file_list_shared_libraries;
 extern mi_cmd_argv_ftype mi_cmd_gdb_exit;
 extern mi_cmd_argv_ftype mi_cmd_inferior_tty_set;
 extern mi_cmd_argv_ftype mi_cmd_inferior_tty_show;
index 86340e4a0815df8c2692e7e1e664feae42cfd88d..b2ac80037cf7dce1695b7eaf439d849af69ececf 100644 (file)
@@ -1114,6 +1114,33 @@ mi_on_resume (ptid_t ptid)
     }
 }
 
+/* See mi-interp.h.  */
+
+void
+mi_output_solib_attribs (ui_out *uiout, struct so_list *solib)
+{
+  struct gdbarch *gdbarch = target_gdbarch ();
+
+  uiout->field_string ("id", solib->so_original_name);
+  uiout->field_string ("target-name", solib->so_original_name);
+  uiout->field_string ("host-name", solib->so_name);
+  uiout->field_int ("symbols-loaded", solib->symbols_loaded);
+  if (!gdbarch_has_global_solist (target_gdbarch ()))
+      uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
+
+  struct cleanup *cleanup
+    = make_cleanup_ui_out_list_begin_end (uiout, "ranges");
+  struct cleanup *tuple_clean_up
+    = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+  if (solib->addr_high != 0)
+    {
+      uiout->field_core_addr ("from", gdbarch, solib->addr_low);
+      uiout->field_core_addr ("to", gdbarch, solib->addr_high);
+    }
+  do_cleanups (tuple_clean_up);
+  do_cleanups (cleanup);
+}
+
 static void
 mi_solib_loaded (struct so_list *solib)
 {
@@ -1135,14 +1162,7 @@ mi_solib_loaded (struct so_list *solib)
 
       uiout->redirect (mi->event_channel);
 
-      uiout->field_string ("id", solib->so_original_name);
-      uiout->field_string ("target-name", solib->so_original_name);
-      uiout->field_string ("host-name", solib->so_name);
-      uiout->field_int ("symbols-loaded", solib->symbols_loaded);
-      if (!gdbarch_has_global_solist (target_gdbarch ()))
-       {
-         uiout->field_fmt ("thread-group", "i%d", current_inferior ()->num);
-       }
+      mi_output_solib_attribs (uiout, solib);
 
       uiout->redirect (NULL);
 
diff --git a/gdb/mi/mi-interp.h b/gdb/mi/mi-interp.h
new file mode 100644 (file)
index 0000000..5b7b9f2
--- /dev/null
@@ -0,0 +1,27 @@
+/* MI Interpreter Definitions and Commands for GDB, the GNU debugger.
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef MI_INTERP_H
+#define MI_INTERP_H
+
+/* Output the shared object attributes to UIOUT.  */
+
+void mi_output_solib_attribs (ui_out *uiout, struct so_list *solib);
+
+#endif
index 38737b60ca80ad748448fb068def07e33038d985..af94383de47e4eab4613ea40a80da0f102e76828 100644 (file)
@@ -89,9 +89,6 @@ set_solib_ops (struct gdbarch *gdbarch, const struct target_so_ops *new_ops)
    configuration needs to call set_solib_ops.  */
 struct target_so_ops *current_target_so_ops;
 
-/* List of known shared objects */
-#define so_list_head current_program_space->so_list
-
 /* Local function prototypes */
 
 /* If non-empty, this is a search path for loading non-absolute shared library
@@ -749,21 +746,7 @@ solib_used (const struct so_list *const known)
   return 0;
 }
 
-/* Synchronize GDB's shared object list with inferior's.
-
-   Extract the list of currently loaded shared objects from the
-   inferior, and compare it with the list of shared objects currently
-   in GDB's so_list_head list.  Edit so_list_head to bring it in sync
-   with the inferior's new list.
-
-   If we notice that the inferior has unloaded some shared objects,
-   free any symbolic info GDB had read about those shared objects.
-
-   Don't load symbolic info for any new shared objects; just add them
-   to the list, and leave their symbols_loaded flag clear.
-
-   If FROM_TTY is non-null, feel free to print messages about what
-   we're doing.  */
+/* See solib.h.  */
 
 void
 update_solib_list (int from_tty)
@@ -1105,7 +1088,7 @@ info_sharedlibrary_command (char *pattern, int from_tty)
 
   uiout->table_body ();
 
-  for (so = so_list_head; so; so = so->next)
+  ALL_SO_LIBS (so)
     {
       struct cleanup *lib_cleanup;
 
index 1b46849fee1281f1d83f93163e57cb78e3f9ade0..e91fb75d3de4af210d25ab52d523c966a19dee8e 100644 (file)
@@ -28,6 +28,9 @@ struct program_space;
 
 #include "symfile-add-flags.h"
 
+/* List of known shared objects */
+#define so_list_head current_program_space->so_list
+
 /* Called when we free all symtabs, to free the shared library information
    as well.  */
 
@@ -75,6 +78,24 @@ extern void no_shared_libraries (char *ignored, int from_tty);
 extern void set_solib_ops (struct gdbarch *gdbarch,
                           const struct target_so_ops *new_ops);
 
+/* Synchronize GDB's shared object list with inferior's.
+
+   Extract the list of currently loaded shared objects from the
+   inferior, and compare it with the list of shared objects currently
+   in GDB's so_list_head list.  Edit so_list_head to bring it in sync
+   with the inferior's new list.
+
+   If we notice that the inferior has unloaded some shared objects,
+   free any symbolic info GDB had read about those shared objects.
+
+   Don't load symbolic info for any new shared objects; just add them
+   to the list, and leave their symbols_loaded flag clear.
+
+   If FROM_TTY is non-null, feel free to print messages about what
+   we're doing.  */
+
+extern void update_solib_list (int from_tty);
+
 /* Return non-zero if NAME is the libpthread shared library.  */
 
 extern int libpthread_name_p (const char *name);
index 9c7e965ae6b199f76a492aa4b52019a4fae0ad9f..378d60d7b8330f3295aa988481f0e37e8c211c25 100644 (file)
 #include "symtab.h"
 #include "gdb_bfd.h"
 
+#define ALL_SO_LIBS(so) \
+    for (so = so_list_head; \
+        so != NULL; \
+        so = so->next)
+
 /* Forward declaration for target specific link map information.  This
    struct is opaque to all but the target specific file.  */
 struct lm_info;
@@ -74,7 +79,10 @@ struct so_list
 
     /* Record the range of addresses belonging to this shared library.
        There may not be just one (e.g. if two segments are relocated
-       differently); but this is only used for "info sharedlibrary".  */
+       differently).  This is used for "info sharedlibrary" and
+       the MI command "-file-list-shared-libraries".  The latter has a format
+       that supports outputting multiple segments once the related code
+       supports them.  */
     CORE_ADDR addr_low, addr_high;
   };
 
index f29225119bb3d06a951487b50a4d75ba0f298d3e..edd3a39cb34df1d297cf01800d79c9b4302e8ad2 100644 (file)
@@ -1,3 +1,8 @@
+2017-03-20  Marc-Andre Laperle  <marc-andre.laperle@ericsson.com>
+
+       * gdb.mi/mi-solib.exp (test_file_list_shared_libraries):
+       New procedure.
+
 2017-03-20  Marc-Andre Laperle  <marc-andre.laperle@ericsson.com>
 
        * lib/mi-support.exp (mi_gdb_test): Add additional message
index 575cb97d1fc7d629460c013555ca8aaac9964b43..ff933e76c5f01454593b3b88c2ed66184d25290f 100644 (file)
@@ -48,27 +48,46 @@ if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
 
 mi_delete_breakpoints
 mi_gdb_reinitialize_dir $srcdir/$subdir
-mi_gdb_reinitialize_dir $srcdir/$subdir
 mi_gdb_load ${binfile}
 
 mi_load_shlibs $binfile_lib
 
-mi_gdb_test "777-gdb-set stop-on-solib-events 1" "777\\^done" \
-    "set stop-on-solib-events"
+proc_with_prefix test_stop_on_solib_events {} {
+    mi_gdb_test "777-gdb-set stop-on-solib-events 1" "777\\^done" \
+       "set stop-on-solib-events"
 
-# We use "run" rather than "-exec-run" here in order to test that CLI
-# commands still cause the correct MI output to be generated.
-mi_run_with_cli
+    # We use "run" rather than "-exec-run" here in order to test that CLI
+    # commands still cause the correct MI output to be generated.
+    mi_run_with_cli
 
-# Also test that the CLI solib event note is output.
-set test "CLI prints solib event"
-gdb_expect {
-    -re "~\"Stopped due to shared library event \\(no libraries added or removed\\)\\\\n" {
-       pass "$test"
-    }
-    timeout {
-       fail "$test (timeout)"
+    # Also test that the CLI solib event note is output.
+    set test "CLI prints solib event"
+    gdb_expect {
+       -re "~\"Stopped due to shared library event \\(no libraries added or removed\\)\\\\n" {
+           pass "$test"
+       }
+       timeout {
+           fail "$test (timeout)"
+       }
     }
+
+    mi_expect_stop solib-event .* .* .* .* .* "check for solib event"
+
+    # Unset solib events to avoid interfering with other tests.
+    mi_gdb_test "778-gdb-set stop-on-solib-events 0" "778\\^done" \
+       "unset stop-on-solib-events"
+}
+
+proc_with_prefix test_file_list_shared_libraries {} {
+    global libname
+    global binfile
+
+    mi_continue_to main
+
+    mi_gdb_test "222-file-list-shared-libraries" \
+       "222\\^done,shared-libraries=\\\[\{id=\".*${libname}.so\",target-name=\".*${libname}.so\",host-name=\".*${libname}.so\",symbols-loaded=\"1\",thread-group=\".*\",ranges=\\\[\{from=\".*\",to=\".*\"\}]\}]" \
+       "get the list of shared libraries"
 }
 
-mi_expect_stop solib-event .* .* .* .* .* "check for solib event"
+test_stop_on_solib_events
+test_file_list_shared_libraries