From 9018be22e022e6db2ba07c4e407c7244022bc69a Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Sat, 7 Apr 2018 13:19:12 -0400 Subject: [PATCH] Make target_read_alloc & al return vectors 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. 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, 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, 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. (target_read_stralloc): Return gdb::optional. (target_get_osdata): Return gdb::optional. * 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) : Remove. : Change type to gdb::optional. (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. --- gdb/ChangeLog | 44 ++++++++++++++++++++ gdb/auxv.c | 44 +++++++++----------- gdb/avr-tdep.c | 40 +++++++++---------- gdb/common/byte-vector.h | 1 + gdb/linux-tdep.c | 48 ++++++++++------------ gdb/osdata.c | 6 +-- gdb/remote.c | 32 +++++++-------- gdb/solib-aix.c | 8 ++-- gdb/solib-dsbt.c | 19 +++++---- gdb/solib-svr4.c | 6 +-- gdb/solib-target.c | 6 +-- gdb/target.c | 86 ++++++++++++++++------------------------ gdb/target.h | 37 +++++++---------- gdb/tracepoint.c | 16 +++----- gdb/xml-support.c | 20 +++++----- gdb/xml-support.h | 10 +++-- gdb/xml-syscall.c | 6 +-- gdb/xml-tdesc.c | 20 +++++----- 18 files changed, 224 insertions(+), 225 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c8e4dc489b..aad71e45e8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,47 @@ +2018-04-07 Simon Marchi + + * common/byte-vector.h (char_vector): New type. + * target.h (target_read_alloc): Return + gdb::optional. + (target_read_stralloc): Return gdb::optional. + (target_get_osdata): Return gdb::optional. + * 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) : Remove. + : Change type to gdb::optional. + (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 * value.c (~value): Update. diff --git a/gdb/auxv.c b/gdb/auxv.c index 26cc63e020..ce7a63b894 100644 --- a/gdb/auxv.c +++ b/gdb/auxv.c @@ -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 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; diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index c44a3aa967..2b9be5e313 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -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 (¤t_target, TARGET_OBJECT_AVR, - "avr.io_reg", &buf); - bufstr = (const char *) buf; + gdb::optional buf + = target_read_alloc (¤t_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 (¤t_target, TARGET_OBJECT_AVR, - query, &buf); + buf = target_read_alloc (¤t_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); } } diff --git a/gdb/common/byte-vector.h b/gdb/common/byte-vector.h index 03c4eb8f83..22a67b8431 100644 --- a/gdb/common/byte-vector.h +++ b/gdb/common/byte-vector.h @@ -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; +using char_vector = gdb::def_vector; } /* namespace gdb */ diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 0ac78c22f9..552a2a495b 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -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 (¤t_target, TARGET_OBJECT_SPU, - NULL, &spu_ids); + gdb::optional + spu_ids = target_read_alloc (¤t_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 (¤t_target, TARGET_OBJECT_SPU, - annex, &spu_data); - if (spu_len > 0) + gdb::optional spu_data + = target_read_alloc (¤t_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 (¤t_target, TARGET_OBJECT_AUXV, - NULL, &auxv); - if (auxv_len > 0) + gdb::optional auxv = + target_read_alloc (¤t_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; diff --git a/gdb/osdata.c b/gdb/osdata.c index 5c41cb1374..50548f7fb4 100644 --- a/gdb/osdata.c +++ b/gdb/osdata.c @@ -163,11 +163,11 @@ std::unique_ptr get_osdata (const char *type) { std::unique_ptr osdata; - gdb::unique_xmalloc_ptr xml = target_get_osdata (type); + gdb::optional 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) diff --git a/gdb/remote.c b/gdb/remote.c index 68c43f8312..1da11d1117 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -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 xml + gdb::optional 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 remote_memory_map (struct target_ops *ops) { std::vector result; - gdb::unique_xmalloc_ptr text + gdb::optional text = target_read_stralloc (¤t_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 text + gdb::optional text = target_read_stralloc (¤t_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 xml + gdb::optional xml = target_read_stralloc (¤t_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 xml + gdb::optional xml = target_read_stralloc (¤t_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 filename; + static gdb::optional 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 (¤t_target, TARGET_OBJECT_EXEC_FILE, annex); - return filename.get (); + return filename ? filename->data () : nullptr; } /* Implement the to_can_do_single_step target_ops method. */ diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c index 5339f11261..608a702a9c 100644 --- a/gdb/solib-aix.c +++ b/gdb/solib-aix.c @@ -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 library_document + gdb::optional library_document = target_read_stralloc (¤t_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); diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c index b3b66baffc..7a9b75480a 100644 --- a/gdb/solib-dsbt.c +++ b/gdb/solib-dsbt.c @@ -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 buf + = target_read_alloc (¤t_target, TARGET_OBJECT_FDPIC, "exec"); - if (0 >= target_read_alloc (¤t_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 (¤t_target, TARGET_OBJECT_FDPIC, - "interp", &buf)) + buf = target_read_alloc (¤t_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); } diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 11e29c1868..3b0af668bd 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -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 svr4_library_document + gdb::optional svr4_library_document = target_read_stralloc (¤t_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 diff --git a/gdb/solib-target.c b/gdb/solib-target.c index 0968e49eb2..7f96e80e1b 100644 --- a/gdb/solib-target.c +++ b/gdb/solib-target.c @@ -257,13 +257,13 @@ solib_target_current_sos (void) int ix; /* Fetch the list of shared libraries. */ - gdb::unique_xmalloc_ptr library_document + gdb::optional library_document = target_read_stralloc (¤t_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; diff --git a/gdb/target.c b/gdb/target.c index b9b2e757dd..8acdd8092c 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -48,6 +48,7 @@ #include #include "byte-vector.h" #include "terminal.h" +#include 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 +gdb::optional> 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 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 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 (ops, object, annex); } /* See target.h. */ -gdb::unique_xmalloc_ptr +gdb::optional 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 buf + = target_read_alloc_1 (ops, object, annex); - if (transferred == 0) - return gdb::unique_xmalloc_ptr (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 (bufstr); + return buf; } /* Memory transfer methods. */ @@ -2744,7 +2726,7 @@ target_supports_multi_process (void) /* See target.h. */ -gdb::unique_xmalloc_ptr +gdb::optional 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); } diff --git a/gdb/target.h b/gdb/target.h index 51ac884e01..b97f142534 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -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 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 target_read_stralloc +extern gdb::optional 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 target_get_osdata (const char *type); +extern gdb::optional target_get_osdata (const char *type); - /* Stuff that should be shared among the various remote targets. */ /* Debugging level. 0 is off, and non-zero values mean to print some debug diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 24bb91418a..f66cc686b8 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -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 (¤t_target, - TARGET_OBJECT_STATIC_TRACE_DATA, - NULL, &buf); - if (size >= 0) + gdb::optional buf + = target_read_alloc (¤t_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 diff --git a/gdb/xml-support.c b/gdb/xml-support.c index 25478825ab..3775e2c8c7 100644 --- a/gdb/xml-support.c +++ b/gdb/xml-support.c @@ -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 text = data->fetcher (href, - data->fetcher_baton); - if (text == NULL) + gdb::optional 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 +gdb::optional 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 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; } diff --git a/gdb/xml-support.h b/gdb/xml-support.h index 5947623e5a..3abae70993 100644 --- a/gdb/xml-support.h +++ b/gdb/xml-support.h @@ -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 (*xml_fetch_another) (const char *href, - void *baton); +typedef gdb::optional (*xml_fetch_another) (const char *href, + void *baton); /* Append the expansion of TEXT after processing 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 xml_fetch_content_from_file +extern gdb::optional xml_fetch_content_from_file (const char *filename, void *baton); #endif diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c index 0ba6d444f3..bf17642911 100644 --- a/gdb/xml-syscall.c +++ b/gdb/xml-syscall.c @@ -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 full_file + gdb::optional 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 ()); } diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c index 9190d5f3c6..1c3409d53b 100644 --- a/gdb/xml-tdesc.c +++ b/gdb/xml-tdesc.c @@ -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 tdesc_str + gdb::optional 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 . */ -static gdb::unique_xmalloc_ptr +static gdb::optional 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 tdesc_str + gdb::optional 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 + gdb::optional 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")); -- 2.34.1