2007-08-02 Michael Snyder <msnyder@access-company.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index f4f267b420d0be43f5e3fe0de8b97dd16e9baa46..9021d5a777e7a48aafdfd6fb4a376d664ecb5818 100644 (file)
@@ -85,8 +85,6 @@ static void handle_remote_sigint_twice (int);
 static void async_remote_interrupt (gdb_client_data);
 void async_remote_interrupt_twice (gdb_client_data);
 
-static void build_remote_gdbarch_data (void);
-
 static void remote_files_info (struct target_ops *ignore);
 
 static void remote_prepare_to_store (struct regcache *regcache);
@@ -907,6 +905,7 @@ enum {
   PACKET_Z4,
   PACKET_qXfer_auxv,
   PACKET_qXfer_features,
+  PACKET_qXfer_libraries,
   PACKET_qXfer_memory_map,
   PACKET_qXfer_spu_read,
   PACKET_qXfer_spu_write,
@@ -2016,9 +2015,13 @@ get_offsets (void)
   struct remote_state *rs = get_remote_state ();
   char *buf;
   char *ptr;
-  int lose;
-  CORE_ADDR text_addr, data_addr, bss_addr;
+  int lose, num_segments = 0, do_sections, do_segments;
+  CORE_ADDR text_addr, data_addr, bss_addr, segments[2];
   struct section_offsets *offs;
+  struct symfile_segment_data *data;
+
+  if (symfile_objfile == NULL)
+    return;
 
   putpkt ("qOffsets");
   getpkt (&rs->buf, &rs->buf_size, 0);
@@ -2047,47 +2050,109 @@ get_offsets (void)
       /* Don't use strtol, could lose on big values.  */
       while (*ptr && *ptr != ';')
        text_addr = (text_addr << 4) + fromhex (*ptr++);
-    }
-  else
-    lose = 1;
 
-  if (!lose && strncmp (ptr, ";Data=", 6) == 0)
-    {
-      ptr += 6;
-      while (*ptr && *ptr != ';')
-       data_addr = (data_addr << 4) + fromhex (*ptr++);
-    }
-  else
-    lose = 1;
+      if (strncmp (ptr, ";Data=", 6) == 0)
+       {
+         ptr += 6;
+         while (*ptr && *ptr != ';')
+           data_addr = (data_addr << 4) + fromhex (*ptr++);
+       }
+      else
+       lose = 1;
 
-  if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+      if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+       {
+         ptr += 5;
+         while (*ptr && *ptr != ';')
+           bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+
+         if (bss_addr != data_addr)
+           warning (_("Target reported unsupported offsets: %s"), buf);
+       }
+      else
+       lose = 1;
+    }
+  else if (strncmp (ptr, "TextSeg=", 8) == 0)
     {
-      ptr += 5;
+      ptr += 8;
+      /* Don't use strtol, could lose on big values.  */
       while (*ptr && *ptr != ';')
-       bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+       text_addr = (text_addr << 4) + fromhex (*ptr++);
+      num_segments = 1;
+
+      if (strncmp (ptr, ";DataSeg=", 9) == 0)
+       {
+         ptr += 9;
+         while (*ptr && *ptr != ';')
+           data_addr = (data_addr << 4) + fromhex (*ptr++);
+         num_segments++;
+       }
     }
   else
     lose = 1;
 
   if (lose)
     error (_("Malformed response to offset query, %s"), buf);
-
-  if (symfile_objfile == NULL)
-    return;
+  else if (*ptr != '\0')
+    warning (_("Target reported unsupported offsets: %s"), buf);
 
   offs = ((struct section_offsets *)
          alloca (SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections)));
   memcpy (offs, symfile_objfile->section_offsets,
          SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections));
 
-  offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+  data = get_symfile_segment_data (symfile_objfile->obfd);
+  do_segments = (data != NULL);
+  do_sections = num_segments == 0;
+
+  /* Text= and Data= specify offsets for the text and data sections,
+     but symfile_map_offsets_to_segments expects base addresses
+     instead of offsets.  If we have two segments, we can still
+     try to relocate the whole segments instead of just ".text"
+     and ".data".  */
+  if (num_segments == 0)
+    {
+      do_sections = 1;
+      if (data == NULL || data->num_segments != 2)
+       do_segments = 0;
+      else
+       {
+         segments[0] = data->segment_bases[0] + text_addr;
+         segments[1] = data->segment_bases[1] + data_addr;
+       }
+    }
+  else
+    {
+      do_sections = 0;
+      segments[0] = text_addr;
+      segments[1] = data_addr;
+    }
 
-  /* This is a temporary kludge to force data and bss to use the same offsets
-     because that's what nlmconv does now.  The real solution requires changes
-     to the stub and remote.c that I don't have time to do right now.  */
+  if (do_segments)
+    {
+      int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data,
+                                                offs, num_segments, segments);
 
-  offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
-  offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+      if (ret == 0 && !do_sections)
+       error (_("Can not handle qOffsets TextSeg response with this symbol file"));
+
+      if (ret > 0)
+       do_sections = 0;
+    }
+
+  free_symfile_segment_data (data);
+
+  if (do_sections)
+    {
+      offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+
+      /* This is a temporary kludge to force data and bss to use the same offsets
+        because that's what nlmconv does now.  The real solution requires changes
+        to the stub and remote.c that I don't have time to do right now.  */
+
+      offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
+      offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+    }
 
   objfile_relocate (symfile_objfile, offs);
 }
@@ -2194,9 +2259,19 @@ remote_check_symbols (struct objfile *objfile)
       if (sym == NULL)
        xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]);
       else
-       xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
-                  paddr_nz (SYMBOL_VALUE_ADDRESS (sym)),
-                  &reply[8]);
+       {
+         CORE_ADDR sym_addr = SYMBOL_VALUE_ADDRESS (sym);
+
+         /* If this is a function address, return the start of code
+            instead of any data function descriptor.  */
+         sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+                                                        sym_addr,
+                                                        &current_target);
+
+         xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
+                    paddr_nz (sym_addr), &reply[8]);
+       }
+  
       putpkt (msg);
       getpkt (&rs->buf, &rs->buf_size, 0);
       reply = rs->buf;
@@ -2312,6 +2387,8 @@ static struct protocol_feature remote_protocol_features[] = {
     PACKET_qXfer_auxv },
   { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_features },
+  { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_libraries },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_memory_map },
   { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
@@ -3117,6 +3194,7 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status)
   struct remote_arch_state *rsa = get_remote_arch_state ();
   ULONGEST thread_num = -1;
   ULONGEST addr;
+  int solibs_changed = 0;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3202,6 +3280,16 @@ Packet: '%s'\n"),
                        p = unpack_varlen_hex (++p1, &addr);
                        remote_watch_data_address = (CORE_ADDR)addr;
                      }
+                   else if (strncmp (p, "library", p1 - p) == 0)
+                     {
+                       p1++;
+                       p_temp = p1;
+                       while (*p_temp && *p_temp != ';')
+                         p_temp++;
+
+                       solibs_changed = 1;
+                       p = p_temp;
+                     }
                    else
                      {
                        /* Silently skip unknown optional info.  */
@@ -3243,9 +3331,14 @@ Packet: '%s'\n"),
          }
          /* fall through */
        case 'S':               /* Old style status, just signal only.  */
-         status->kind = TARGET_WAITKIND_STOPPED;
-         status->value.sig = (enum target_signal)
-           (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+         if (solibs_changed)
+           status->kind = TARGET_WAITKIND_LOADED;
+         else
+           {
+             status->kind = TARGET_WAITKIND_STOPPED;
+             status->value.sig = (enum target_signal)
+               (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+           }
 
          if (buf[3] == 'p')
            {
@@ -3308,6 +3401,7 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
   struct remote_arch_state *rsa = get_remote_arch_state ();
   ULONGEST thread_num = -1;
   ULONGEST addr;
+  int solibs_changed = 0;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3369,7 +3463,7 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
                /* If this packet is an awatch packet, don't parse the 'a'
                   as a register number.  */
 
-               if (!strncmp (p, "awatch", strlen ("awatch")) != 0)
+               if (strncmp (p, "awatch", strlen("awatch")) != 0)
                  {
                    /* Read the register number.  */
                    pnum = strtol (p, &p_temp, 16);
@@ -3399,6 +3493,16 @@ Packet: '%s'\n"),
                        p = unpack_varlen_hex (++p1, &addr);
                        remote_watch_data_address = (CORE_ADDR)addr;
                      }
+                   else if (strncmp (p, "library", p1 - p) == 0)
+                     {
+                       p1++;
+                       p_temp = p1;
+                       while (*p_temp && *p_temp != ';')
+                         p_temp++;
+
+                       solibs_changed = 1;
+                       p = p_temp;
+                     }
                    else
                      {
                        /* Silently skip unknown optional info.  */
@@ -3440,9 +3544,14 @@ Packet: '%s'\n"),
          }
          /* fall through */
        case 'S':               /* Old style status, just signal only.  */
-         status->kind = TARGET_WAITKIND_STOPPED;
-         status->value.sig = (enum target_signal)
-           (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+         if (solibs_changed)
+           status->kind = TARGET_WAITKIND_LOADED;
+         else
+           {
+             status->kind = TARGET_WAITKIND_STOPPED;
+             status->value.sig = (enum target_signal)
+               (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+           }
 
          if (buf[3] == 'p')
            {
@@ -3927,13 +4036,18 @@ hexnumnstr (char *buf, ULONGEST num, int width)
 static CORE_ADDR
 remote_address_masked (CORE_ADDR addr)
 {
-  if (remote_address_size > 0
-      && remote_address_size < (sizeof (ULONGEST) * 8))
+  int address_size = remote_address_size;
+  /* If "remoteaddresssize" was not set, default to target address size.  */
+  if (!address_size)
+    address_size = gdbarch_addr_bit (current_gdbarch);
+
+  if (address_size > 0
+      && address_size < (sizeof (ULONGEST) * 8))
     {
       /* Only create a mask when that mask can safely be constructed
          in a ULONGEST variable.  */
       ULONGEST mask = 1;
-      mask = (mask << remote_address_size) - 1;
+      mask = (mask << address_size) - 1;
       addr &= mask;
     }
   return addr;
@@ -5730,6 +5844,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
        (ops, "features", annex, readbuf, offset, len,
         &remote_protocol_packets[PACKET_qXfer_features]);
 
+    case TARGET_OBJECT_LIBRARIES:
+      return remote_read_qxfer
+       (ops, "libraries", annex, readbuf, offset, len,
+        &remote_protocol_packets[PACKET_qXfer_libraries]);
+
     case TARGET_OBJECT_MEMORY_MAP:
       gdb_assert (annex == NULL);
       return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
@@ -6347,7 +6466,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_async_ops.to_memory_map = remote_memory_map;
   remote_async_ops.to_flash_erase = remote_flash_erase;
   remote_async_ops.to_flash_done = remote_flash_done;
-  remote_ops.to_read_description = remote_read_description;
+  remote_async_ops.to_read_description = remote_read_description;
 }
 
 /* Set up the async extended remote vector by making a copy of the standard
@@ -6409,11 +6528,6 @@ show_remote_cmd (char *args, int from_tty)
   do_cleanups (showlist_chain);
 }
 
-static void
-build_remote_gdbarch_data (void)
-{
-  remote_address_size = gdbarch_addr_bit (current_gdbarch);
-}
 
 /* Function to be called whenever a new objfile (shlib) is detected.  */
 static void
@@ -6434,11 +6548,6 @@ _initialize_remote (void)
   remote_g_packet_data_handle =
     gdbarch_data_register_pre_init (remote_g_packet_data_init);
 
-  /* Old tacky stuff.  NOTE: This comes after the remote protocol so
-     that the remote protocol has been initialized.  */
-  DEPRECATED_REGISTER_GDBARCH_SWAP (remote_address_size);
-  deprecated_register_gdbarch_swap (NULL, 0, build_remote_gdbarch_data);
-
   /* Initialize the per-target state.  At the moment there is only one
      of these, not one per target.  Only one target is active at a
      time.  The default buffer size is unimportant; it will be expanded
@@ -6597,6 +6706,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_features],
                         "qXfer:features:read", "target-features", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_libraries],
+                        "qXfer:libraries:read", "library-info", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
                         "qXfer:memory-map:read", "memory-map", 0);
 
This page took 0.03213 seconds and 4 git commands to generate.