From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stephen Smith To: Elena Zannoni , Andrew Cagney , GDB patches , Kevin Buettner Subject: Re-submit: shared libraries and a remote target Date: Fri, 20 Jul 2001 17:17:00 -0000 Message-id: <3B58CA4D.FE9AAD02@home.com> References: <3B55CD58.13771694@home.com> <15189.59080.526458.935802@krustylu.cygnus.com> <3B575CCC.E4B5E759@home.com> <3B586202.2E1504ED@home.com> X-SW-Source: 2001-07/msg00538.html 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 +#include #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: + [-mapped] [-readnow] [-s ]* 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: + [-mapped] [-readnow] [-s ]* */ +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 (§ion_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 [-mapped] [-readnow] [-s ]*"); + } + } + 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, §ion_addrs, 0, flags); + + /* Getting new symbols may change our opinion about what is frameless. */ + reinit_frame_cache (); + do_cleanups (my_cleanups); }