This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re-submit: shared libraries and a remote target


This patch supersedes http://sources.redhat.com/ml/gdb-patches/2001-07/msg00513.html.
It has all of Elena's and Kevin's comments implemented.


        * remote.c (remote_get_list_of_shared_libraries, find_file,
        parse_string_from_server): New functions which support
        an optional extension to the remote protocol.

Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.61
diff -u -p -r1.61 remote.c
--- remote.c 2001/07/17 01:23:44 1.61
+++ remote.c 2001/07/20 23:59:21
@@ -48,6 +48,7 @@
 #include "inf-loop.h"

 #include <signal.h>
+#include <string.h>
 #include "serial.h"

 #include "gdbcore.h" /* for exec_bfd */
@@ -202,6 +203,12 @@ static void show_packet_config_cmd (stru

 static void update_packet_config (struct packet_config *config);

+static void remote_get_list_of_shared_libraries(void);
+
+static char* find_file(char* basename);
+
+static void parse_string_from_server (char *args);
+
 /* Define the target subroutine names */

 void open_remote_target (char *, int, struct target_ops *, int);
@@ -686,6 +693,22 @@ show_remote_protocol_qSymbol_packet_cmd
   show_packet_config_cmd (&remote_protocol_qSymbol);
 }

+/* Should we try the 'qLibraries' (remote shared library) protocol? */
+static struct packet_config remote_protocol_qLibraries;
+
+static void
+set_remote_protocol_qLibraries_packet_cmd (char *args, int from_tty,
+      struct cmd_list_element *c)
+{
+  update_packet_config (&remote_protocol_qLibraries);
+}
+
+static void
+show_remote_protocol_qLibraries_packet_cmd (char *args, int from_tty)
+{
+  show_packet_config_cmd (&remote_protocol_qLibraries);
+}
+
 /* Should we try the 'e' (step over range) request? */
 static struct packet_config remote_protocol_e;

@@ -2087,6 +2110,7 @@ init_all_packet_configs (void)
   update_packet_config (&remote_protocol_E);
   update_packet_config (&remote_protocol_P);
   update_packet_config (&remote_protocol_qSymbol);
+  update_packet_config (&remote_protocol_qLibraries);
   for (i = 0; i < NR_Z_PACKET_TYPES; i++)
     update_packet_config (&remote_protocol_Z[i]);
   /* Force remote_write_bytes to check whether target supports binary
@@ -3061,7 +3085,9 @@ Packet Dropped");
    continue;
  }
     }
+
 got_status:
+  remote_get_list_of_shared_libraries();
   if (thread_num != -1)
     {
       return pid_to_ptid (thread_num);
@@ -3284,6 +3310,7 @@ Packet Dropped");
  }
     }
 got_status:
+  remote_get_list_of_shared_libraries();
   if (thread_num != -1)
     {
       return pid_to_ptid (thread_num);
@@ -5779,6 +5806,7 @@ show_remote_cmd (char *args, int from_tt
   show_remote_protocol_E_packet_cmd (args, from_tty);
   show_remote_protocol_P_packet_cmd (args, from_tty);
   show_remote_protocol_qSymbol_packet_cmd (args, from_tty);
+  show_remote_protocol_qLibraries_packet_cmd (args, from_tty);
   show_remote_protocol_binary_download_cmd (args, from_tty);
 }

@@ -5950,6 +5978,13 @@ in a memory packet.\n",
     &remote_set_cmdlist, &remote_show_cmdlist,
     0);

+  add_packet_config_cmd (&remote_protocol_qLibraries,
+                         "qLibraries", "shared-library-lookup",
+                         set_remote_protocol_qLibraries_packet_cmd,
+                         show_remote_protocol_qLibraries_packet_cmd,
+                         &remote_set_cmdlist, &remote_show_cmdlist,
+                         0 );
+
   add_packet_config_cmd (&remote_protocol_e,
     "e", "step-over-range",
     set_remote_protocol_e_packet_cmd,
@@ -6015,4 +6050,298 @@ Set use of remote protocol `Z' packets",
   add_cmd ("Z-packet", class_obscure, show_remote_protocol_Z_packet_cmd,
     "Show use of remote protocol `Z' packets ",
     &remote_show_cmdlist);
+}
+
+static void
+remote_get_list_of_shared_libraries (void)
+{
+  /* This is a counter that gets used so that we don't run while the GDB is
+     initializing */
+  static unsigned initializationBlock = 0;
+
+  char *buf = alloca (PBUFSIZ);
+
+  /* Has this feature been disabled? */
+  if (remote_protocol_qLibraries.support == PACKET_DISABLE)
+    {
+      return;
+    }
+
+  /* The first time through, I don't believe we want to do this because gdb
+     isn't completely initialized. With out this flag
+     parse_string_from_server() hangs. */
+  if (initializationBlock < 2)
+    {
+      ++initializationBlock;
+      return;
+    }
+
+  putpkt ("qNewLibraries");
+  getpkt (buf, PBUFSIZ, 0);
+  switch (packet_ok (buf, &remote_protocol_qLibraries))
+    {
+    case PACKET_OK:
+      break;
+    case PACKET_ERROR:
+    case PACKET_UNKNOWN:
+    default:
+      return;
+    }
+
+  if (buf[0] == '\000')
+    {
+      remote_protocol_qLibraries.support = PACKET_DISABLE;
+      return;   /* Return silently.  Stub doesn't support this
+       command. */
+    }
+
+  if (buf[0] == '1')  /* There are new shared libraries */
+    {
+      char *file = alloca (PBUFSIZ), *fqn;
+      int address, values, first_space;
+
+      putpkt ("qLibraries");
+      getpkt (buf, PBUFSIZ, 0);
+      switch (packet_ok (buf, &remote_protocol_qLibraries))
+ {
+ case PACKET_OK:
+   break;
+ case PACKET_ERROR:
+ case PACKET_UNKNOWN:
+ default:
+   return;
+ }
+
+      if (buf[0] == '\000')
+ {
+   remote_protocol_qLibraries.support = PACKET_DISABLE;
+   return;  /* Return silently.  Stub doesn't support this
+       command. */
+ }
+
+      do
+ {
+   /* buff should have the following layout: <filename> <textaddress>
+      [-mapped] [-readnow] [-s <secname> <addr>]* The reason that this
+      format was chosen is that it is file format independent and allows
+      for OS memory layouts that are non-standard. */
+   values = sscanf (buf, "%s %x", file, &address);
+   if (values < 2)
+     break;  /* check to make sure we have a minimum number
+       of fields */
+   first_space = strlen (file);
+   if ((fqn = find_file (file)) != 0)
+     {
+       strcpy (file, fqn);
+       strcat (file, &buf[first_space]);
+       parse_string_from_server (file);
+     }
+
+   /* Get the next file from remote */
+   putpkt ("qLibraries");
+   getpkt (buf, PBUFSIZ, 0);
+   switch (packet_ok (buf, &remote_protocol_qLibraries))
+     {
+     case PACKET_OK:
+       break;
+     case PACKET_ERROR:
+     case PACKET_UNKNOWN:
+     default:
+       return;
+     }
+
+   if (buf[0] == '\000')
+     {
+       remote_protocol_qLibraries.support = PACKET_DISABLE;
+       return;  /* Return silently.  Stub doesn't support this
+       command. */
+     }
+ }
+      while (buf[0] != '\000');
+
+    }
+  else if (buf[0] == '0')
+    {
+      /* There are no new shared libraries */
+    }
+  else
+    {
+      warning ("Remote reply is unrecognized: %s", buf);
+      return;
+    }
+
+  return;
+}
+
+static char *
+find_file (char *basename)
+{
+  int found_file;
+  static char *filename;
+  /* Search the $PATH environment variable. */
+  found_file = openp (getenv ("PATH"), 1, basename, O_RDONLY, 0, &filename);
+
+  /* If not found, next search $LD_LIBRARY_PATH environment variable. */
+  if (found_file < 0)
+    found_file =
+      openp (getenv ("LD_LIBRARY_PATH"), 1, basename, O_RDONLY, 0, &filename);
+
+  /* We really don't want the file open here, we just wanted the side effects
+     of this function call.  If the file was opened, close it. */
+  if (found_file >= 0)
+    close (found_file);
+  else
+    return 0;   /* Report that a file wasn't found */
+
+  return filename;
+}
+
+/* This function allows the addition of incrementally linked object files.
+   It does not modify any state in the target, only in the debugger.
+   args should have the following layout: <filename> <textaddress>
+   [-mapped] [-readnow] [-s <secname> <addr>]* */
+static void
+parse_string_from_server (char *args)
+{
+  char *filename = NULL;
+  int flags = OBJF_USERLOADED;
+  char *arg;
+  int expecting_option = 0;
+  int section_index = 0;
+  int argcnt = 0;
+  int sec_num = 0;
+  int i;
+  int expecting_sec_name = 0;
+  int expecting_sec_addr = 0;
+
+  struct
+  {
+    char *name;
+    char *value;
+  }
+  sect_opts[SECT_OFF_MAX];
+
+  struct section_addr_info section_addrs;
+  struct cleanup *my_cleanups = make_cleanup (null_cleanup, NULL);
+
+  dont_repeat ();
+
+  if (args == NULL)
+    error ("add-symbol-file takes a file name and an address");
+
+  /* Make a copy of the string that we can safely write into. */
+  args = xstrdup (args);
+
+  /* Ensure section_addrs is initialized */
+  memset (&section_addrs, 0, sizeof (section_addrs));
+
+  while (*args != '\000')
+    {
+      /* Any leading spaces? */
+      while (isspace (*args))
+ args++;
+
+      /* Point arg to the beginning of the argument. */
+      arg = args;
+
+      /* Move args pointer over the argument. */
+      while ((*args != '\000') && !isspace (*args))
+ args++;
+
+      /* If there are more arguments, terminate arg and proceed past it. */
+      if (*args != '\000')
+ *args++ = '\000';
+
+      /* Now process the argument. */
+      if (argcnt == 0)
+ {
+   /* The first argument is the file name. */
+   filename = tilde_expand (arg);
+   make_cleanup (xfree, filename);
+ }
+      else if (argcnt == 1)
+ {
+   /* The second argument is always the text address at which to load
+      the program. */
+   sect_opts[section_index].name = ".text";
+   sect_opts[section_index].value = arg;
+   section_index++;
+ }
+      else
+ {
+   /* It's an option (starting with '-') or it's an argument to an
+      option */
+
+   if (*arg == '-')
+     {
+       if (strcmp (arg, "-mapped") == 0)
+  flags |= OBJF_MAPPED;
+       else if (strcmp (arg, "-readnow") == 0)
+  flags |= OBJF_READNOW;
+       else if (strcmp (arg, "-s") == 0)
+  {
+    if (section_index >= SECT_OFF_MAX)
+      error ("Too many sections specified.");
+    expecting_sec_name = 1;
+    expecting_sec_addr = 1;
+  }
+     }
+   else
+     {
+       if (expecting_sec_name)
+  {
+    sect_opts[section_index].name = arg;
+    expecting_sec_name = 0;
+  }
+       else if (expecting_sec_addr)
+  {
+    sect_opts[section_index].value = arg;
+    expecting_sec_addr = 0;
+    section_index++;
+  }
+       else
+  error
+    ("USAGE: add-symbol-file <filename> <textaddress> [-mapped] [-readnow] [-s <secname> <addr>]*");
+     }
+ }
+      argcnt++;
+    }
+
+  /* Print the prompt for the query below. And save the arguments into a
+     sect_addr_info structure to be passed around to other functions.  We have
+     to split this up into separate print statements because local_hex_string
+     returns a local static string. */
+
+  printf_filtered ("add symbol table from file \"%s\" at\n", filename);
+  for (i = 0; i < section_index; i++)
+    {
+      CORE_ADDR addr;
+      char *val = sect_opts[i].value;
+      char *sec = sect_opts[i].name;
+
+      val = sect_opts[i].value;
+      if (val[0] == '0' && val[1] == 'x')
+ addr = strtoul (val + 2, NULL, 16);
+      else
+ addr = strtoul (val, NULL, 10);
+
+      /* Here we store the section offsets in the order they were entered on
+         the command line. */
+      section_addrs.other[sec_num].name = sec;
+      section_addrs.other[sec_num].addr = addr;
+      printf_filtered ("\t%s_addr = %s\n",
+         sec, local_hex_string ((unsigned long) addr));
+      sec_num++;
+
+      /* The object's sections are initialized when a call is made to
+         build_objfile_section_table (objfile). This happens in reread_symbols.
+         At this point, we don't know what file type this is, so we can't
+         determine what section names are valid.  */
+    }
+
+  symbol_file_add (filename, 0, &section_addrs, 0, flags);
+
+  /* Getting new symbols may change our opinion about what is frameless.  */
+  reinit_frame_cache ();
+  do_cleanups (my_cleanups);
 }



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]