Improved patch: shared libraries and a remote target

Stephen Smith
2001-07-20T09:52:00Z

This patch implements the comments in http://sources.redhat.com/ml/gdb-patches/2001-07/msg00504.html . Unless
someone can point me at how to add the command and then link it to the appropriate variable, the switch is my best
try (sorry Elena).

Other than the switch change this should have everything that was wanted.

* main.c (--remote-shared-libs, --no-remote-shared-libs): New
switches.
* remote.c (remote_get_list_of_shared_libraries, findFile): New
functions which support an option extention to the remote protocol.
* top.c (remote_shared_libs): New global variable.
* top.h (remote_shared_libs): Likewise.

Index: main.c
===================================================================
RCS file: /cvs/src/src/gdb/main.c,v
retrieving revision 1.12
diff -u -p -r1.12 main.c
--- main.c 2001/07/14 18:59:07 1.12
+++ main.c 2001/07/20 15:57:01
@@ -264,6 +264,8 @@ captured_main (void *data)
{"windows", no_argument, &use_windows, 1},
{"statistics", no_argument, 0, 13},
{"write", no_argument, &write_files, 1},
+ {"remote-shared-libs", no_argument, &remote_shared_libs, 1},
+ {"no-remote-shared-libs", no_argument, &remote_shared_libs, 0},
/* Allow machine descriptions to add more options... */
#ifdef ADDITIONAL_OPTIONS
ADDITIONAL_OPTIONS
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 15:57:04
@@ -48,8 +48,9 @@
#include "inf-loop.h"

#include <signal.h>
+#include <string.h>
#include "serial.h"
-
+#include "top.h" /* for remote_shared_libs */
#include "gdbcore.h" /* for exec_bfd */

/* Prototypes for local functions */
@@ -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);
@@ -3061,7 +3068,9 @@ Packet Dropped");
continue;
}
}
+
got_status:
+ remote_get_list_of_shared_libraries();
if (thread_num != -1)
{
return pid_to_ptid (thread_num);
@@ -3284,6 +3293,7 @@ Packet Dropped");
}
}
got_status:
+ remote_get_list_of_shared_libraries();
if (thread_num != -1)
{
return pid_to_ptid (thread_num);
@@ -6015,4 +6025,293 @@ 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;
+
+ /* We can't just check for a starting E for errors because the file name may
+ start with one */
+ char *error_string = "ENN: ";
+
+ char *buf = alloca (PBUFSIZ);
+ static char remote_does_not_suport = 0; /* If the remote doesn't
+ support this, then we will
+ turn off this function */
+
+ /* Has the user asked for this feature: Command line option:
+ remote-shared-libs */
+ if (remote_shared_libs == 0)
+ return;
+
+
+ /* The first times 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;
+ }
+
+ if (remote_does_not_suport) /* We've checked this and the stub doesn't
+ support this functionality */
+ {
+ return;
+ }
+
+ putpkt ("qNewLibraries");
+ getpkt (buf, PBUFSIZ, 0);
+
+ if (buf[0] == '\000')
+ {
+ remote_does_not_suport = 1; /* short circuit this function */
+ return; /* Return silently. Stub doesn't support this
+ command. */
+ }
+
+ if (strncmp (buf, error_string, strlen (error_string)) == 0)
+ {
+ warning ("Remote failure reply: %s", buf);
+ return;
+ }
+
+ 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);
+
+ if (buf[0] == '\000')
+ {
+ remote_does_not_suport = 1; /* short circuit this function */
+ return; /* Return silently. Stub doesn't support this
+ command. */
+ }
+
+ if (strncmp (buf, error_string, strlen (error_string)) == 0)
+ {
+ warning ("Remote failure reply: %s", buf);
+ return;
+ }
+
+ do
+ { /* buff should have the following layout:
+ <filename> <textaddress> [-mapped]
+ [-readnow] [-s <secname> <addr>]* */
+ 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);
+
+ /* Check for errors */
+ if (strncmp (buf, error_string, strlen (error_string)) == 0)
+ {
+ warning ("Remote failure reply: %s", buf);
+ break;
+ }
+ }
+ 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. */
+/* ARGSUSED */
+ 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: top.c
===================================================================
RCS file: /cvs/src/src/gdb/top.c,v
retrieving revision 1.41
diff -u -p -r1.41 top.c
--- top.c 2001/07/17 17:25:14 1.41
+++ top.c 2001/07/20 15:57:05
@@ -165,6 +165,12 @@ int remote_debug = 0;
target is off and running, which gdb is doing something else. */
int target_executing = 0;

+/* This variable is added to control the loading of shared libraries
+ by a remote stub or by gdbserver. The default is set to 0 so that
+ the behaviour will remain unchanged by default - i.e. we won't ask about
+ shared libraries. */
+int remote_shared_libs = 0;
+
/* Level of control structure. */
static int control_level;

Index: top.h
===================================================================
RCS file: /cvs/src/src/gdb/top.h,v
retrieving revision 1.5
diff -u -p -r1.5 top.h
--- top.h 2001/03/06 08:21:17 1.5
+++ top.h 2001/07/20 15:57:05
@@ -55,6 +55,7 @@ extern void set_prompt (char *);
/* From random places. */
extern int mapped_symbol_files;
extern int readnow_symbol_files;
+extern int remote_shared_libs;

/* Perform _initialize initialization */
extern void gdb_init (char *);