Make target_read_alloc & al return vectors
authorSimon Marchi <simon.marchi@ericsson.com>
Sat, 7 Apr 2018 17:19:12 +0000 (13:19 -0400)
committerSimon Marchi <simon.marchi@polymtl.ca>
Sat, 7 Apr 2018 17:19:12 +0000 (13:19 -0400)
This patch started by changing target_read_alloc_1 to return a
byte_vector, to avoid manual memory management (in target_read_alloc_1
and in the callers).  To communicate failures to the callers, it
actually returns a gdb::optional<gdb::byte_vector>.

Adjusting target_read_stralloc was a bit more tricky, since it wants to
return a buffer of char, and not gdb_byte.  Since you can't just cast a
gdb::byte_vector into a gdb::def_vector<char>, I made
target_read_alloc_1 templated, so both versions (that return vectors of
gdb_byte and char) are generated.  Since target_read_stralloc now
returns a gdb::char_vector instead of a gdb::unique_xmalloc_ptr<char>, a
few callers need to be adjusted.

gdb/ChangeLog:

* common/byte-vector.h (char_vector): New type.
* target.h (target_read_alloc): Return
gdb::optional<byte_vector>.
(target_read_stralloc): Return gdb::optional<char_vector>.
(target_get_osdata): Return gdb::optional<char_vector>.
* target.c (target_read_alloc_1): Templatize.  Replacement
manual memory management with vector.
(target_read_alloc): Change return type, adjust.
(target_read_stralloc): Change return type, adjust.
(target_get_osdata): Change return type, adjust.
* auxv.c (struct auxv_info) <length>: Remove.
<data>: Change type to gdb::optional<byte_vector>.
(auxv_inferior_data_cleanup): Free auxv_info with delete.
(get_auxv_inferior_data): Allocate auxv_info with new, adjust.
(target_auxv_search): Adjust.
(fprint_target_auxv): Adjust.
* avr-tdep.c (avr_io_reg_read_command): Adjust.
* linux-tdep.c (linux_spu_make_corefile_notes): Adjust.
(linux_make_corefile_notes): Adjust.
* osdata.c (get_osdata): Adjust.
* remote.c (remote_get_threads_with_qxfer): Adjust.
(remote_memory_map): Adjust.
(remote_traceframe_info): Adjust.
(btrace_read_config): Adjust.
(remote_read_btrace): Adjust.
(remote_pid_to_exec_file): Adjust.
* solib-aix.c (solib_aix_get_library_list): Adjust.
* solib-dsbt.c (decode_loadmap): Don't free buf.
(dsbt_get_initial_loadmaps): Adjust.
* solib-svr4.c (svr4_current_sos_via_xfer_libraries): Adjust.
* solib-target.c (solib_target_current_sos): Adjust.
* tracepoint.c (sdata_make_value): Adjust.
* xml-support.c (xinclude_start_include): Adjust.
(xml_fetch_content_from_file): Adjust.
* xml-support.h (xml_fetch_another): Change return type.
(xml_fetch_content_from_file): Change return type.
* xml-syscall.c (xml_init_syscalls_info): Adjust.
* xml-tdesc.c (file_read_description_xml): Adjust.
(fetch_available_features_from_target): Change return type.
(target_fetch_description_xml): Adjust.
(target_read_description_xml): Adjust.

18 files changed:
gdb/ChangeLog
gdb/auxv.c
gdb/avr-tdep.c
gdb/common/byte-vector.h
gdb/linux-tdep.c
gdb/osdata.c
gdb/remote.c
gdb/solib-aix.c
gdb/solib-dsbt.c
gdb/solib-svr4.c
gdb/solib-target.c
gdb/target.c
gdb/target.h
gdb/tracepoint.c
gdb/xml-support.c
gdb/xml-support.h
gdb/xml-syscall.c
gdb/xml-tdesc.c

index c8e4dc4..aad71e4 100644 (file)
@@ -1,3 +1,47 @@
+2018-04-07  Simon Marchi  <simon.marchi@ericsson.com>
+
+       * common/byte-vector.h (char_vector): New type.
+       * target.h (target_read_alloc): Return
+       gdb::optional<byte_vector>.
+       (target_read_stralloc): Return gdb::optional<char_vector>.
+       (target_get_osdata): Return gdb::optional<char_vector>.
+       * target.c (target_read_alloc_1): Templatize.  Replacement
+       manual memory management with vector.
+       (target_read_alloc): Change return type, adjust.
+       (target_read_stralloc): Change return type, adjust.
+       (target_get_osdata): Change return type, adjust.
+       * auxv.c (struct auxv_info) <length>: Remove.
+       <data>: Change type to gdb::optional<byte_vector>.
+       (auxv_inferior_data_cleanup): Free auxv_info with delete.
+       (get_auxv_inferior_data): Allocate auxv_info with new, adjust.
+       (target_auxv_search): Adjust.
+       (fprint_target_auxv): Adjust.
+       * avr-tdep.c (avr_io_reg_read_command): Adjust.
+       * linux-tdep.c (linux_spu_make_corefile_notes): Adjust.
+       (linux_make_corefile_notes): Adjust.
+       * osdata.c (get_osdata): Adjust.
+       * remote.c (remote_get_threads_with_qxfer): Adjust.
+       (remote_memory_map): Adjust.
+       (remote_traceframe_info): Adjust.
+       (btrace_read_config): Adjust.
+       (remote_read_btrace): Adjust.
+       (remote_pid_to_exec_file): Adjust.
+       * solib-aix.c (solib_aix_get_library_list): Adjust.
+       * solib-dsbt.c (decode_loadmap): Don't free buf.
+       (dsbt_get_initial_loadmaps): Adjust.
+       * solib-svr4.c (svr4_current_sos_via_xfer_libraries): Adjust.
+       * solib-target.c (solib_target_current_sos): Adjust.
+       * tracepoint.c (sdata_make_value): Adjust.
+       * xml-support.c (xinclude_start_include): Adjust.
+       (xml_fetch_content_from_file): Adjust.
+       * xml-support.h (xml_fetch_another): Change return type.
+       (xml_fetch_content_from_file): Change return type.
+       * xml-syscall.c (xml_init_syscalls_info): Adjust.
+       * xml-tdesc.c (file_read_description_xml): Adjust.
+       (fetch_available_features_from_target): Change return type.
+       (target_fetch_description_xml): Adjust.
+       (target_read_description_xml): Adjust.
+
 2018-04-06  Tom Tromey  <tom@tromey.com>
 
        * value.c (~value): Update.
index 26cc63e..ce7a63b 100644 (file)
@@ -304,8 +304,7 @@ static const struct inferior_data *auxv_inferior_data;
     overhead of transfering data from a remote target to the local host.  */
 struct auxv_info
 {
-  LONGEST length;
-  gdb_byte *data;
+  gdb::optional<gdb::byte_vector> data;
 };
 
 /* Handles the cleanup of the auxv cache for inferior INF.  ARG is ignored.
@@ -323,8 +322,7 @@ auxv_inferior_data_cleanup (struct inferior *inf, void *arg)
   info = (struct auxv_info *) inferior_data (inf, auxv_inferior_data);
   if (info != NULL)
     {
-      xfree (info->data);
-      xfree (info);
+      delete info;
       set_inferior_data (inf, auxv_inferior_data, NULL);
     }
 }
@@ -358,9 +356,8 @@ get_auxv_inferior_data (struct target_ops *ops)
   info = (struct auxv_info *) inferior_data (inf, auxv_inferior_data);
   if (info == NULL)
     {
-      info = XCNEW (struct auxv_info);
-      info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV,
-                                       NULL, &info->data);
+      info = new auxv_info;
+      info->data = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL);
       set_inferior_data (inf, auxv_inferior_data, info);
     }
 
@@ -375,20 +372,17 @@ int
 target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
 {
   CORE_ADDR type, val;
-  gdb_byte *data;
-  gdb_byte *ptr;
-  struct auxv_info *info;
-
-  info = get_auxv_inferior_data (ops);
+  auxv_info *info = get_auxv_inferior_data (ops);
 
-  data = info->data;
-  ptr = data;
+  if (!info->data)
+    return -1;
 
-  if (info->length <= 0)
-    return info->length;
+  gdb_byte *data = info->data->data ();
+  gdb_byte *ptr = data;
+  size_t len = info->data->size ();
 
   while (1)
-    switch (target_auxv_parse (ops, &ptr, data + info->length, &type, &val))
+    switch (target_auxv_parse (ops, &ptr, data + len, &type, &val))
       {
       case 1:                  /* Here's an entry, check it.  */
        if (type == match)
@@ -528,19 +522,17 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
 {
   struct gdbarch *gdbarch = target_gdbarch ();
   CORE_ADDR type, val;
-  gdb_byte *data;
-  gdb_byte *ptr;
-  struct auxv_info *info;
   int ents = 0;
+  auxv_info *info = get_auxv_inferior_data (ops);
 
-  info = get_auxv_inferior_data (ops);
+  if (!info->data)
+    return -1;
 
-  data = info->data;
-  ptr = data;
-  if (info->length <= 0)
-    return info->length;
+  gdb_byte *data = info->data->data ();
+  gdb_byte *ptr = data;
+  size_t len = info->data->size ();
 
-  while (target_auxv_parse (ops, &ptr, data + info->length, &type, &val) > 0)
+  while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
     {
       gdbarch_print_auxv_entry (gdbarch, file, type, val);
       ++ents;
index c44a3aa..2b9be5e 100644 (file)
@@ -1549,21 +1549,15 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 static void
 avr_io_reg_read_command (const char *args, int from_tty)
 {
-  LONGEST bufsiz = 0;
-  gdb_byte *buf;
-  const char *bufstr;
   char query[400];
-  const char *p;
   unsigned int nreg = 0;
   unsigned int val;
-  int i, j, k, step;
 
   /* Find out how many io registers the target has.  */
-  bufsiz = target_read_alloc (&current_target, TARGET_OBJECT_AVR,
-                             "avr.io_reg", &buf);
-  bufstr = (const char *) buf;
+  gdb::optional<gdb::byte_vector> buf
+    = target_read_alloc (&current_target, TARGET_OBJECT_AVR, "avr.io_reg");
 
-  if (bufsiz <= 0)
+  if (!buf)
     {
       fprintf_unfiltered (gdb_stderr,
                          _("ERR: info io_registers NOT supported "
@@ -1571,36 +1565,42 @@ avr_io_reg_read_command (const char *args, int from_tty)
       return;
     }
 
+  const char *bufstr = (const char *) buf->data ();
+
   if (sscanf (bufstr, "%x", &nreg) != 1)
     {
       fprintf_unfiltered (gdb_stderr,
                          _("Error fetching number of io registers\n"));
-      xfree (buf);
       return;
     }
 
-  xfree (buf);
-
   reinitialize_more_filter ();
 
   printf_unfiltered (_("Target has %u io registers:\n\n"), nreg);
 
   /* only fetch up to 8 registers at a time to keep the buffer small */
-  step = 8;
+  int step = 8;
 
-  for (i = 0; i < nreg; i += step)
+  for (int i = 0; i < nreg; i += step)
     {
       /* how many registers this round? */
-      j = step;
+      int j = step;
       if ((i+j) >= nreg)
         j = nreg - i;           /* last block is less than 8 registers */
 
       snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
-      bufsiz = target_read_alloc (&current_target, TARGET_OBJECT_AVR,
-                                 query, &buf);
+      buf = target_read_alloc (&current_target, TARGET_OBJECT_AVR, query);
+
+      if (!buf)
+        {
+          fprintf_unfiltered (gdb_stderr,
+                             _("ERR: error reading avr.io_reg:%x,%x\n"),
+                             i, j);
+          return;
+        }
 
-      p = (const char *) buf;
-      for (k = i; k < (i + j); k++)
+      const char *p = (const char *) buf->data ();
+      for (int k = i; k < (i + j); k++)
        {
          if (sscanf (p, "%[^,],%x;", query, &val) == 2)
            {
@@ -1612,8 +1612,6 @@ avr_io_reg_read_command (const char *args, int from_tty)
                break;
            }
        }
-
-      xfree (buf);
     }
 }
 
index 03c4eb8..22a67b8 100644 (file)
@@ -56,6 +56,7 @@ namespace gdb {
    and providing the whole std::vector API, if you end up needing it.
 */
 using byte_vector = gdb::def_vector<gdb_byte>;
+using char_vector = gdb::def_vector<char>;
 
 } /* namespace gdb */
 
index 0ac78c2..552a2a4 100644 (file)
@@ -1420,47 +1420,41 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
    };
 
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
-  gdb_byte *spu_ids;
-  LONGEST i, j, size;
 
   /* Determine list of SPU ids.  */
-  size = target_read_alloc (&current_target, TARGET_OBJECT_SPU,
-                           NULL, &spu_ids);
+  gdb::optional<gdb::byte_vector>
+    spu_ids = target_read_alloc (&current_target, TARGET_OBJECT_SPU, NULL);
+
+  if (!spu_ids)
+    return nullptr;
 
   /* Generate corefile notes for each SPU file.  */
-  for (i = 0; i < size; i += 4)
+  for (size_t i = 0; i < spu_ids->size (); i += 4)
     {
-      int fd = extract_unsigned_integer (spu_ids + i, 4, byte_order);
+      int fd = extract_unsigned_integer (spu_ids->data () + i, 4, byte_order);
 
-      for (j = 0; j < sizeof (spu_files) / sizeof (spu_files[0]); j++)
+      for (size_t j = 0; j < sizeof (spu_files) / sizeof (spu_files[0]); j++)
        {
          char annex[32], note_name[32];
-         gdb_byte *spu_data;
-         LONGEST spu_len;
 
          xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[j]);
-         spu_len = target_read_alloc (&current_target, TARGET_OBJECT_SPU,
-                                      annex, &spu_data);
-         if (spu_len > 0)
+         gdb::optional<gdb::byte_vector> spu_data
+           = target_read_alloc (&current_target, TARGET_OBJECT_SPU, annex);
+
+         if (spu_data && !spu_data->empty ())
            {
              xsnprintf (note_name, sizeof note_name, "SPU/%s", annex);
              note_data = elfcore_write_note (obfd, note_data, note_size,
                                              note_name, NT_SPU,
-                                             spu_data, spu_len);
-             xfree (spu_data);
+                                             spu_data->data (),
+                                             spu_data->size ());
 
              if (!note_data)
-               {
-                 xfree (spu_ids);
-                 return NULL;
-               }
+               return nullptr;
            }
        }
     }
 
-  if (size > 0)
-    xfree (spu_ids);
-
   return note_data;
 }
 
@@ -1911,8 +1905,6 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
   struct linux_corefile_thread_data thread_args;
   struct elf_internal_linux_prpsinfo prpsinfo;
   char *note_data = NULL;
-  gdb_byte *auxv;
-  int auxv_len;
   struct thread_info *curr_thr, *signalled_thr, *thr;
 
   if (! gdbarch_iterate_over_regset_sections_p (gdbarch))
@@ -1977,13 +1969,13 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
     return NULL;
 
   /* Auxillary vector.  */
-  auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
-                               NULL, &auxv);
-  if (auxv_len > 0)
+  gdb::optional<gdb::byte_vector> auxv =
+    target_read_alloc (&current_target, TARGET_OBJECT_AUXV, NULL);
+  if (auxv && !auxv->empty ())
     {
       note_data = elfcore_write_note (obfd, note_data, note_size,
-                                     "CORE", NT_AUXV, auxv, auxv_len);
-      xfree (auxv);
+                                     "CORE", NT_AUXV, auxv->data (),
+                                     auxv->size ());
 
       if (!note_data)
        return NULL;
index 5c41cb1..50548f7 100644 (file)
@@ -163,11 +163,11 @@ std::unique_ptr<osdata>
 get_osdata (const char *type)
 {
   std::unique_ptr<osdata> osdata;
-  gdb::unique_xmalloc_ptr<char> xml = target_get_osdata (type);
+  gdb::optional<gdb::char_vector> xml = target_get_osdata (type);
 
   if (xml)
     {
-      if (xml.get ()[0] == '\0')
+      if ((*xml)[0] == '\0')
        {
          if (type)
            warning (_("Empty data returned by target.  Wrong osdata type?"));
@@ -175,7 +175,7 @@ get_osdata (const char *type)
            warning (_("Empty type list returned by target.  No type data?"));
        }
       else
-       osdata = osdata_parse (xml.get ());
+       osdata = osdata_parse (xml->data ());
     }
 
   if (osdata == NULL)
index 68c43f8..1da11d1 100644 (file)
@@ -3151,13 +3151,13 @@ remote_get_threads_with_qxfer (struct target_ops *ops,
 #if defined(HAVE_LIBEXPAT)
   if (packet_support (PACKET_qXfer_threads) == PACKET_ENABLE)
     {
-      gdb::unique_xmalloc_ptr<char> xml
+      gdb::optional<gdb::char_vector> xml
        = target_read_stralloc (ops, TARGET_OBJECT_THREADS, NULL);
 
-      if (xml != NULL && *xml != '\0')
+      if (xml && (*xml)[0] != '\0')
        {
          gdb_xml_parse_quick (_("threads"), "threads.dtd",
-                              threads_elements, xml.get (), context);
+                              threads_elements, xml->data (), context);
        }
 
       return 1;
@@ -10790,11 +10790,11 @@ static std::vector<mem_region>
 remote_memory_map (struct target_ops *ops)
 {
   std::vector<mem_region> result;
-  gdb::unique_xmalloc_ptr<char> text
+  gdb::optional<gdb::char_vector> text
     = target_read_stralloc (&current_target, TARGET_OBJECT_MEMORY_MAP, NULL);
 
   if (text)
-    result = parse_memory_map (text.get ());
+    result = parse_memory_map (text->data ());
 
   return result;
 }
@@ -12905,11 +12905,11 @@ remote_set_circular_trace_buffer (struct target_ops *self, int val)
 static traceframe_info_up
 remote_traceframe_info (struct target_ops *self)
 {
-  gdb::unique_xmalloc_ptr<char> text
+  gdb::optional<gdb::char_vector> text
     = target_read_stralloc (&current_target, TARGET_OBJECT_TRACEFRAME_INFO,
                            NULL);
-  if (text != NULL)
-    return parse_traceframe_info (text.get ());
+  if (text)
+    return parse_traceframe_info (text->data ());
 
   return NULL;
 }
@@ -13137,10 +13137,10 @@ btrace_sync_conf (const struct btrace_config *conf)
 static void
 btrace_read_config (struct btrace_config *conf)
 {
-  gdb::unique_xmalloc_ptr<char> xml
+  gdb::optional<gdb::char_vector> xml
     = target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE_CONF, "");
-  if (xml != NULL)
-    parse_xml_btrace_conf (conf, xml.get ());
+  if (xml)
+    parse_xml_btrace_conf (conf, xml->data ());
 }
 
 /* Maybe reopen target btrace.  */
@@ -13337,12 +13337,12 @@ remote_read_btrace (struct target_ops *self,
                      (unsigned int) type);
     }
 
-  gdb::unique_xmalloc_ptr<char> xml
+  gdb::optional<gdb::char_vector> xml
     = target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE, annex);
-  if (xml == NULL)
+  if (!xml)
     return BTRACE_ERR_UNKNOWN;
 
-  parse_xml_btrace (btrace, xml.get ());
+  parse_xml_btrace (btrace, xml->data ());
 
   return BTRACE_ERR_NONE;
 }
@@ -13376,7 +13376,7 @@ remote_load (struct target_ops *self, const char *name, int from_tty)
 static char *
 remote_pid_to_exec_file (struct target_ops *self, int pid)
 {
-  static gdb::unique_xmalloc_ptr<char> filename;
+  static gdb::optional<gdb::char_vector> filename;
   struct inferior *inf;
   char *annex = NULL;
 
@@ -13399,7 +13399,7 @@ remote_pid_to_exec_file (struct target_ops *self, int pid)
   filename = target_read_stralloc (&current_target,
                                   TARGET_OBJECT_EXEC_FILE, annex);
 
-  return filename.get ();
+  return filename ? filename->data () : nullptr;
 }
 
 /* Implement the to_can_do_single_step target_ops method.  */
index 5339f11..608a702 100644 (file)
@@ -279,10 +279,10 @@ solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
   if (data->library_list != NULL)
     return data->library_list;
 
-  gdb::unique_xmalloc_ptr<char> library_document
+  gdb::optional<gdb::char_vector> library_document
     = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_AIX,
                            NULL);
-  if (library_document == NULL && warning_msg != NULL)
+  if (!library_document && warning_msg != NULL)
     {
       warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
               warning_msg);
@@ -292,9 +292,9 @@ solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
   if (solib_aix_debug)
     fprintf_unfiltered (gdb_stdlog,
                        "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
-                       library_document.get ());
+                       library_document->data ());
 
-  data->library_list = solib_aix_parse_libraries (library_document.get ());
+  data->library_list = solib_aix_parse_libraries (library_document->data ());
   if (data->library_list == NULL && warning_msg != NULL)
     {
       warning (_("%s (missing XML support?)"), warning_msg);
index b3b66ba..7a9b754 100644 (file)
@@ -224,10 +224,10 @@ dsbt_print_loadmap (struct int_elf32_dsbt_loadmap *map)
 /* Decode int_elf32_dsbt_loadmap from BUF.  */
 
 static struct int_elf32_dsbt_loadmap *
-decode_loadmap (gdb_byte *buf)
+decode_loadmap (const gdb_byte *buf)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
-  struct ext_elf32_dsbt_loadmap *ext_ldmbuf;
+  const struct ext_elf32_dsbt_loadmap *ext_ldmbuf;
   struct int_elf32_dsbt_loadmap *int_ldmbuf;
 
   int version, seg, nsegs;
@@ -278,7 +278,6 @@ decode_loadmap (gdb_byte *buf)
                                    byte_order);
     }
 
-  xfree (ext_ldmbuf);
   return int_ldmbuf;
 }
 
@@ -292,26 +291,26 @@ static struct dsbt_info *get_dsbt_info (void);
 static void
 dsbt_get_initial_loadmaps (void)
 {
-  gdb_byte *buf;
   struct dsbt_info *info = get_dsbt_info ();
+  gdb::optional<gdb::byte_vector> buf
+    = target_read_alloc (&current_target, TARGET_OBJECT_FDPIC, "exec");
 
-  if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC,
-                             "exec", &buf))
+  if (!buf || buf->empty ())
     {
       info->exec_loadmap = NULL;
       error (_("Error reading DSBT exec loadmap"));
     }
-  info->exec_loadmap = decode_loadmap (buf);
+  info->exec_loadmap = decode_loadmap (buf->data ());
   if (solib_dsbt_debug)
     dsbt_print_loadmap (info->exec_loadmap);
 
-  if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC,
-                             "interp", &buf))
+  buf = target_read_alloc (&current_target, TARGET_OBJECT_FDPIC, "exec");
+  if (!buf || buf->empty ())
     {
       info->interp_loadmap = NULL;
       error (_("Error reading DSBT interp loadmap"));
     }
-  info->interp_loadmap = decode_loadmap (buf);
+  info->interp_loadmap = decode_loadmap (buf->data ());
   if (solib_dsbt_debug)
     dsbt_print_loadmap (info->interp_loadmap);
 }
index 11e29c1..3b0af66 100644 (file)
@@ -1243,13 +1243,13 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
   gdb_assert (annex == NULL || target_augmented_libraries_svr4_read ());
 
   /* Fetch the list of shared libraries.  */
-  gdb::unique_xmalloc_ptr<char> svr4_library_document
+  gdb::optional<gdb::char_vector> svr4_library_document
     = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_SVR4,
                            annex);
-  if (svr4_library_document == NULL)
+  if (!svr4_library_document)
     return 0;
 
-  return svr4_parse_libraries (svr4_library_document.get (), list);
+  return svr4_parse_libraries (svr4_library_document->data (), list);
 }
 
 #else
index 0968e49..7f96e80 100644 (file)
@@ -257,13 +257,13 @@ solib_target_current_sos (void)
   int ix;
 
   /* Fetch the list of shared libraries.  */
-  gdb::unique_xmalloc_ptr<char> library_document
+  gdb::optional<gdb::char_vector> library_document
     = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES, NULL);
-  if (library_document == NULL)
+  if (!library_document)
     return NULL;
 
   /* Parse the list.  */
-  library_list = solib_target_parse_libraries (library_document.get ());
+  library_list = solib_target_parse_libraries (library_document->data ());
 
   if (library_list == NULL)
     return NULL;
index b9b2e75..8acdd80 100644 (file)
@@ -48,6 +48,7 @@
 #include <algorithm>
 #include "byte-vector.h"
 #include "terminal.h"
+#include <algorithm>
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
@@ -1937,18 +1938,17 @@ target_write (struct target_ops *ops,
                                     NULL, NULL);
 }
 
-/* Read OBJECT/ANNEX using OPS.  Store the result in *BUF_P and return
-   the size of the transferred data.  PADDING additional bytes are
-   available in *BUF_P.  This is a helper function for
-   target_read_alloc; see the declaration of that function for more
-   information.  */
+/* Help for target_read_alloc and target_read_stralloc.  See their comments
+   for details.  */
 
-static LONGEST
+template <typename T>
+gdb::optional<gdb::def_vector<T>>
 target_read_alloc_1 (struct target_ops *ops, enum target_object object,
-                    const char *annex, gdb_byte **buf_p, int padding)
+                    const char *annex)
 {
-  size_t buf_alloc, buf_pos;
-  gdb_byte *buf;
+  gdb::def_vector<T> buf;
+  size_t buf_pos = 0;
+  const int chunk = 4096;
 
   /* This function does not have a length parameter; it reads the
      entire OBJECT).  Also, it doesn't support objects fetched partly
@@ -1959,82 +1959,64 @@ target_read_alloc_1 (struct target_ops *ops, enum target_object object,
 
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
-  buf_alloc = 4096;
-  buf = (gdb_byte *) xmalloc (buf_alloc);
-  buf_pos = 0;
   while (1)
     {
       ULONGEST xfered_len;
       enum target_xfer_status status;
 
-      status = target_read_partial (ops, object, annex, &buf[buf_pos],
-                                   buf_pos, buf_alloc - buf_pos - padding,
+      buf.resize (buf_pos + chunk);
+
+      status = target_read_partial (ops, object, annex,
+                                   (gdb_byte *) &buf[buf_pos],
+                                   buf_pos, chunk,
                                    &xfered_len);
 
       if (status == TARGET_XFER_EOF)
        {
          /* Read all there was.  */
-         if (buf_pos == 0)
-           xfree (buf);
-         else
-           *buf_p = buf;
-         return buf_pos;
+         buf.resize (buf_pos);
+         return buf;
        }
       else if (status != TARGET_XFER_OK)
        {
          /* An error occurred.  */
-         xfree (buf);
-         return TARGET_XFER_E_IO;
+         return {};
        }
 
       buf_pos += xfered_len;
 
-      /* If the buffer is filling up, expand it.  */
-      if (buf_alloc < buf_pos * 2)
-       {
-         buf_alloc *= 2;
-         buf = (gdb_byte *) xrealloc (buf, buf_alloc);
-       }
-
       QUIT;
     }
 }
 
-/* Read OBJECT/ANNEX using OPS.  Store the result in *BUF_P and return
-   the size of the transferred data.  See the declaration in "target.h"
-   function for more information about the return value.  */
+/* See target.h  */
 
-LONGEST
+gdb::optional<gdb::byte_vector>
 target_read_alloc (struct target_ops *ops, enum target_object object,
-                  const char *annex, gdb_byte **buf_p)
+                  const char *annex)
 {
-  return target_read_alloc_1 (ops, object, annex, buf_p, 0);
+  return target_read_alloc_1<gdb_byte> (ops, object, annex);
 }
 
 /* See target.h.  */
 
-gdb::unique_xmalloc_ptr<char>
+gdb::optional<gdb::char_vector>
 target_read_stralloc (struct target_ops *ops, enum target_object object,
                      const char *annex)
 {
-  gdb_byte *buffer;
-  char *bufstr;
-  LONGEST i, transferred;
-
-  transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
-  bufstr = (char *) buffer;
-
-  if (transferred < 0)
-    return NULL;
+  gdb::optional<gdb::char_vector> buf
+    = target_read_alloc_1<char> (ops, object, annex);
 
-  if (transferred == 0)
-    return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
+  if (!buf)
+    return {};
 
-  bufstr[transferred] = 0;
+  if (buf->back () != '\0')
+    buf->push_back ('\0');
 
   /* Check for embedded NUL bytes; but allow trailing NULs.  */
-  for (i = strlen (bufstr); i < transferred; i++)
-    if (bufstr[i] != 0)
+  for (auto it = std::find (buf->begin (), buf->end (), '\0');
+       it != buf->end (); it++)
+    if (*it != '\0')
       {
        warning (_("target object %d, annex %s, "
                   "contained unexpected null characters"),
@@ -2042,7 +2024,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
        break;
       }
 
-  return gdb::unique_xmalloc_ptr<char> (bufstr);
+  return buf;
 }
 
 /* Memory transfer methods.  */
@@ -2744,7 +2726,7 @@ target_supports_multi_process (void)
 
 /* See target.h.  */
 
-gdb::unique_xmalloc_ptr<char>
+gdb::optional<gdb::char_vector>
 target_get_osdata (const char *type)
 {
   struct target_ops *t;
@@ -2758,7 +2740,7 @@ target_get_osdata (const char *type)
     t = find_default_run_target ("get OS data");
 
   if (!t)
-    return NULL;
+    return {};
 
   return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
 }
index 51ac884..b97f142 100644 (file)
@@ -324,29 +324,26 @@ LONGEST target_write_with_progress (struct target_ops *ops,
                                    void (*progress) (ULONGEST, void *),
                                    void *baton);
 
-/* Wrapper to perform a full read of unknown size.  OBJECT/ANNEX will
-   be read using OPS.  The return value will be -1 if the transfer
-   fails or is not supported; 0 if the object is empty; or the length
-   of the object otherwise.  If a positive value is returned, a
-   sufficiently large buffer will be allocated using xmalloc and
-   returned in *BUF_P containing the contents of the object.
+/* Wrapper to perform a full read of unknown size.  OBJECT/ANNEX will be read
+   using OPS.  The return value will be uninstantiated if the transfer fails or
+   is not supported.
 
    This method should be used for objects sufficiently small to store
    in a single xmalloc'd buffer, when no fixed bound on the object's
    size is known in advance.  Don't try to read TARGET_OBJECT_MEMORY
    through this function.  */
 
-extern LONGEST target_read_alloc (struct target_ops *ops,
-                                 enum target_object object,
-                                 const char *annex, gdb_byte **buf_p);
+extern gdb::optional<gdb::byte_vector> target_read_alloc
+    (struct target_ops *ops, enum target_object object, const char *annex);
 
-/* Read OBJECT/ANNEX using OPS.  The result is NUL-terminated and
-   returned as a string.  If an error occurs or the transfer is
-   unsupported, NULL is returned.  Empty objects are returned as
-   allocated but empty strings.  A warning is issued if the result
-   contains any embedded NUL bytes.  */
+/* Read OBJECT/ANNEX using OPS.  The result is a NUL-terminated character vector
+   (therefore usable as a NUL-terminated string).  If an error occurs or the
+   transfer is unsupported, the return value will be uninstantiated.  Empty
+   objects are returned as allocated but empty strings.  Therefore, on success,
+   the returned vector is guaranteed to have at least one element.  A warning is
+   issued if the result contains any embedded NUL bytes.  */
 
-extern gdb::unique_xmalloc_ptr<char> target_read_stralloc
+extern gdb::optional<gdb::char_vector> target_read_stralloc
     (struct target_ops *ops, enum target_object object, const char *annex);
 
 /* See target_ops->to_xfer_partial.  */
@@ -2384,15 +2381,11 @@ extern struct target_ops *find_target_beneath (struct target_ops *);
 
 struct target_ops *find_target_at (enum strata stratum);
 
-/* Read OS data object of type TYPE from the target, and return it in
-   XML format.  The result is NUL-terminated and returned as a string.
-   If an error occurs or the transfer is unsupported, NULL is
-   returned.  Empty objects are returned as allocated but empty
-   strings.  */
+/* Read OS data object of type TYPE from the target, and return it in XML
+   format.  The return value follows the same rules as target_read_stralloc.  */
 
-extern gdb::unique_xmalloc_ptr<char> target_get_osdata (const char *type);
+extern gdb::optional<gdb::char_vector> target_get_osdata (const char *type);
 
-\f
 /* Stuff that should be shared among the various remote targets.  */
 
 /* Debugging level.  0 is off, and non-zero values mean to print some debug
index 24bb914..f66cc68 100644 (file)
@@ -3871,23 +3871,19 @@ static struct value *
 sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
                  void *ignore)
 {
-  LONGEST size;
-  gdb_byte *buf;
-
   /* We need to read the whole object before we know its size.  */
-  size = target_read_alloc (&current_target,
-                           TARGET_OBJECT_STATIC_TRACE_DATA,
-                           NULL, &buf);
-  if (size >= 0)
+  gdb::optional<gdb::byte_vector> buf
+    = target_read_alloc (&current_target, TARGET_OBJECT_STATIC_TRACE_DATA,
+                        NULL);
+  if (buf)
     {
       struct value *v;
       struct type *type;
 
       type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
-                              size);
+                              buf->size ());
       v = allocate_value (type);
-      memcpy (value_contents_raw (v), buf, size);
-      xfree (buf);
+      memcpy (value_contents_raw (v), buf->data (), buf->size ());
       return v;
     }
   else
index 2547882..3775e2c 100644 (file)
@@ -793,13 +793,13 @@ xinclude_start_include (struct gdb_xml_parser *parser,
     gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
                   MAX_XINCLUDE_DEPTH);
 
-  gdb::unique_xmalloc_ptr<char> text = data->fetcher (href,
-                                                     data->fetcher_baton);
-  if (text == NULL)
+  gdb::optional<gdb::char_vector> text
+    = data->fetcher (href, data->fetcher_baton);
+  if (!text)
     gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
 
   if (!xml_process_xincludes (data->output, parser->name (),
-                             text.get (), data->fetcher,
+                             text->data (), data->fetcher,
                              data->fetcher_baton,
                              data->include_depth + 1))
     gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
@@ -971,7 +971,7 @@ show_debug_xml (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("XML debugging is %s.\n"), value);
 }
 
-gdb::unique_xmalloc_ptr<char>
+gdb::optional<gdb::char_vector>
 xml_fetch_content_from_file (const char *filename, void *baton)
 {
   const char *dirname = (const char *) baton;
@@ -990,7 +990,7 @@ xml_fetch_content_from_file (const char *filename, void *baton)
     file = gdb_fopen_cloexec (filename, FOPEN_RT);
 
   if (file == NULL)
-    return NULL;
+    return {};
 
   /* Read in the whole file.  */
 
@@ -1001,16 +1001,16 @@ xml_fetch_content_from_file (const char *filename, void *baton)
   len = ftell (file.get ());
   rewind (file.get ());
 
-  gdb::unique_xmalloc_ptr<char> text ((char *) xmalloc (len + 1));
+  gdb::char_vector text (len + 1);
 
-  if (fread (text.get (), 1, len, file.get ()) != len
+  if (fread (text.data (), 1, len, file.get ()) != len
       || ferror (file.get ()))
     {
       warning (_("Read error from \"%s\""), filename);
-      return NULL;
+      return {};
     }
 
-  text.get ()[len] = '\0';
+  text.back () = '\0';
   return text;
 }
 
index 5947623..3abae70 100644 (file)
@@ -24,6 +24,7 @@
 #include "gdb_obstack.h"
 #include "vec.h"
 #include "xml-utils.h"
+#include "common/byte-vector.h"
 
 struct gdb_xml_parser;
 struct gdb_xml_element;
@@ -52,8 +53,8 @@ extern const char *xml_builtin[][2];
 
 /* Callback to fetch a new XML file, based on the provided HREF.  */
 
-typedef gdb::unique_xmalloc_ptr<char> (*xml_fetch_another) (const char *href,
-                                                           void *baton);
+typedef gdb::optional<gdb::char_vector> (*xml_fetch_another) (const char *href,
+                                                             void *baton);
 
 /* Append the expansion of TEXT after processing <xi:include> tags in
    RESULT.  FETCHER will be called (with FETCHER_BATON) to retrieve
@@ -231,9 +232,10 @@ ULONGEST gdb_xml_parse_ulongest (struct gdb_xml_parser *parser,
                                 const char *value);
 
 /* Open FILENAME, read all its text into memory, close it, and return
-   the text.  If something goes wrong, return NULL and warn.  */
+   the text.  If something goes wrong, return an uninstantiated optional
+   and warn.  */
 
-extern gdb::unique_xmalloc_ptr<char> xml_fetch_content_from_file
+extern gdb::optional<gdb::char_vector> xml_fetch_content_from_file
     (const char *filename, void *baton);
 
 #endif
index 0ba6d44..bf17642 100644 (file)
@@ -305,12 +305,12 @@ syscall_parse_xml (const char *document, xml_fetch_another fetcher,
 static struct syscalls_info *
 xml_init_syscalls_info (const char *filename)
 {
-  gdb::unique_xmalloc_ptr<char> full_file
+  gdb::optional<gdb::char_vector> full_file
     = xml_fetch_content_from_file (filename, gdb_datadir);
-  if (full_file == NULL)
+  if (!full_file)
     return NULL;
 
-  return syscall_parse_xml (full_file.get (),
+  return syscall_parse_xml (full_file->data (),
                            xml_fetch_content_from_file,
                            (void *) ldirname (filename).c_str ());
 }
index 9190d5f..1c3409d 100644 (file)
@@ -668,15 +668,15 @@ tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
 const struct target_desc *
 file_read_description_xml (const char *filename)
 {
-  gdb::unique_xmalloc_ptr<char> tdesc_str
+  gdb::optional<gdb::char_vector> tdesc_str
     = xml_fetch_content_from_file (filename, NULL);
-  if (tdesc_str == NULL)
+  if (!tdesc_str)
     {
       warning (_("Could not open \"%s\""), filename);
       return NULL;
     }
 
-  return tdesc_parse_xml (tdesc_str.get (), xml_fetch_content_from_file,
+  return tdesc_parse_xml (tdesc_str->data (), xml_fetch_content_from_file,
                          (void *) ldirname (filename).c_str ());
 }
 
@@ -687,7 +687,7 @@ file_read_description_xml (const char *filename)
    is "target.xml".  Other calls may be performed for the DTD or
    for <xi:include>.  */
 
-static gdb::unique_xmalloc_ptr<char>
+static gdb::optional<gdb::char_vector>
 fetch_available_features_from_target (const char *name, void *baton_)
 {
   struct target_ops *ops = (struct target_ops *) baton_;
@@ -706,12 +706,12 @@ fetch_available_features_from_target (const char *name, void *baton_)
 const struct target_desc *
 target_read_description_xml (struct target_ops *ops)
 {
-  gdb::unique_xmalloc_ptr<char> tdesc_str
+  gdb::optional<gdb::char_vector> tdesc_str
     = fetch_available_features_from_target ("target.xml", ops);
-  if (tdesc_str == NULL)
+  if (!tdesc_str)
     return NULL;
 
-  return tdesc_parse_xml (tdesc_str.get (),
+  return tdesc_parse_xml (tdesc_str->data (),
                          fetch_available_features_from_target,
                          ops);
 }
@@ -735,15 +735,15 @@ target_fetch_description_xml (struct target_ops *ops)
 
   return {};
 #else
-  gdb::unique_xmalloc_ptr<char>
+  gdb::optional<gdb::char_vector>
     tdesc_str = fetch_available_features_from_target ("target.xml", ops);
-  if (tdesc_str == NULL)
+  if (!tdesc_str)
     return {};
 
   std::string output;
   if (!xml_process_xincludes (output,
                              _("target description"),
-                             tdesc_str.get (),
+                             tdesc_str->data (),
                              fetch_available_features_from_target, ops, 0))
     {
       warning (_("Could not load XML target description; ignoring"));