Re-submit: shared libraries and a remote target

Stephen Smith
2001-07-20T17:17:00Z

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