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<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.
This commit is contained in:
Simon Marchi 2018-04-07 13:19:12 -04:00 committed by Simon Marchi
parent 43193fe9fc
commit 9018be22e0
18 changed files with 224 additions and 225 deletions

View 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> 2018-04-06 Tom Tromey <tom@tromey.com>
* value.c (~value): Update. * value.c (~value): Update.

View 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. */ overhead of transfering data from a remote target to the local host. */
struct auxv_info struct auxv_info
{ {
LONGEST length; gdb::optional<gdb::byte_vector> data;
gdb_byte *data;
}; };
/* Handles the cleanup of the auxv cache for inferior INF. ARG is ignored. /* 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); info = (struct auxv_info *) inferior_data (inf, auxv_inferior_data);
if (info != NULL) if (info != NULL)
{ {
xfree (info->data); delete info;
xfree (info);
set_inferior_data (inf, auxv_inferior_data, NULL); 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); info = (struct auxv_info *) inferior_data (inf, auxv_inferior_data);
if (info == NULL) if (info == NULL)
{ {
info = XCNEW (struct auxv_info); info = new auxv_info;
info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV, info->data = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL);
NULL, &info->data);
set_inferior_data (inf, auxv_inferior_data, info); 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) target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
{ {
CORE_ADDR type, val; CORE_ADDR type, val;
gdb_byte *data; auxv_info *info = get_auxv_inferior_data (ops);
gdb_byte *ptr;
struct auxv_info *info;
info = get_auxv_inferior_data (ops); if (!info->data)
return -1;
data = info->data; gdb_byte *data = info->data->data ();
ptr = data; gdb_byte *ptr = data;
size_t len = info->data->size ();
if (info->length <= 0)
return info->length;
while (1) 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. */ case 1: /* Here's an entry, check it. */
if (type == match) if (type == match)
@ -528,19 +522,17 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
{ {
struct gdbarch *gdbarch = target_gdbarch (); struct gdbarch *gdbarch = target_gdbarch ();
CORE_ADDR type, val; CORE_ADDR type, val;
gdb_byte *data;
gdb_byte *ptr;
struct auxv_info *info;
int ents = 0; 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; gdb_byte *data = info->data->data ();
ptr = data; gdb_byte *ptr = data;
if (info->length <= 0) size_t len = info->data->size ();
return info->length;
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); gdbarch_print_auxv_entry (gdbarch, file, type, val);
++ents; ++ents;

View file

@ -1549,21 +1549,15 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
static void static void
avr_io_reg_read_command (const char *args, int from_tty) avr_io_reg_read_command (const char *args, int from_tty)
{ {
LONGEST bufsiz = 0;
gdb_byte *buf;
const char *bufstr;
char query[400]; char query[400];
const char *p;
unsigned int nreg = 0; unsigned int nreg = 0;
unsigned int val; unsigned int val;
int i, j, k, step;
/* Find out how many io registers the target has. */ /* Find out how many io registers the target has. */
bufsiz = target_read_alloc (&current_target, TARGET_OBJECT_AVR, gdb::optional<gdb::byte_vector> buf
"avr.io_reg", &buf); = target_read_alloc (&current_target, TARGET_OBJECT_AVR, "avr.io_reg");
bufstr = (const char *) buf;
if (bufsiz <= 0) if (!buf)
{ {
fprintf_unfiltered (gdb_stderr, fprintf_unfiltered (gdb_stderr,
_("ERR: info io_registers NOT supported " _("ERR: info io_registers NOT supported "
@ -1571,36 +1565,42 @@ avr_io_reg_read_command (const char *args, int from_tty)
return; return;
} }
const char *bufstr = (const char *) buf->data ();
if (sscanf (bufstr, "%x", &nreg) != 1) if (sscanf (bufstr, "%x", &nreg) != 1)
{ {
fprintf_unfiltered (gdb_stderr, fprintf_unfiltered (gdb_stderr,
_("Error fetching number of io registers\n")); _("Error fetching number of io registers\n"));
xfree (buf);
return; return;
} }
xfree (buf);
reinitialize_more_filter (); reinitialize_more_filter ();
printf_unfiltered (_("Target has %u io registers:\n\n"), nreg); printf_unfiltered (_("Target has %u io registers:\n\n"), nreg);
/* only fetch up to 8 registers at a time to keep the buffer small */ /* 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? */ /* how many registers this round? */
j = step; int j = step;
if ((i+j) >= nreg) if ((i+j) >= nreg)
j = nreg - i; /* last block is less than 8 registers */ j = nreg - i; /* last block is less than 8 registers */
snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j); snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
bufsiz = target_read_alloc (&current_target, TARGET_OBJECT_AVR, buf = target_read_alloc (&current_target, TARGET_OBJECT_AVR, query);
query, &buf);
p = (const char *) buf; if (!buf)
for (k = i; k < (i + j); k++) {
fprintf_unfiltered (gdb_stderr,
_("ERR: error reading avr.io_reg:%x,%x\n"),
i, j);
return;
}
const char *p = (const char *) buf->data ();
for (int k = i; k < (i + j); k++)
{ {
if (sscanf (p, "%[^,],%x;", query, &val) == 2) if (sscanf (p, "%[^,],%x;", query, &val) == 2)
{ {
@ -1612,8 +1612,6 @@ avr_io_reg_read_command (const char *args, int from_tty)
break; break;
} }
} }
xfree (buf);
} }
} }

View file

@ -56,6 +56,7 @@ namespace gdb {
and providing the whole std::vector API, if you end up needing it. and providing the whole std::vector API, if you end up needing it.
*/ */
using byte_vector = gdb::def_vector<gdb_byte>; using byte_vector = gdb::def_vector<gdb_byte>;
using char_vector = gdb::def_vector<char>;
} /* namespace gdb */ } /* namespace gdb */

View 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 ()); enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
gdb_byte *spu_ids;
LONGEST i, j, size;
/* Determine list of SPU ids. */ /* Determine list of SPU ids. */
size = target_read_alloc (&current_target, TARGET_OBJECT_SPU, gdb::optional<gdb::byte_vector>
NULL, &spu_ids); spu_ids = target_read_alloc (&current_target, TARGET_OBJECT_SPU, NULL);
if (!spu_ids)
return nullptr;
/* Generate corefile notes for each SPU file. */ /* 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]; char annex[32], note_name[32];
gdb_byte *spu_data;
LONGEST spu_len;
xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[j]); xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[j]);
spu_len = target_read_alloc (&current_target, TARGET_OBJECT_SPU, gdb::optional<gdb::byte_vector> spu_data
annex, &spu_data); = target_read_alloc (&current_target, TARGET_OBJECT_SPU, annex);
if (spu_len > 0)
if (spu_data && !spu_data->empty ())
{ {
xsnprintf (note_name, sizeof note_name, "SPU/%s", annex); xsnprintf (note_name, sizeof note_name, "SPU/%s", annex);
note_data = elfcore_write_note (obfd, note_data, note_size, note_data = elfcore_write_note (obfd, note_data, note_size,
note_name, NT_SPU, note_name, NT_SPU,
spu_data, spu_len); spu_data->data (),
xfree (spu_data); spu_data->size ());
if (!note_data) if (!note_data)
{ return nullptr;
xfree (spu_ids);
return NULL;
}
} }
} }
} }
if (size > 0)
xfree (spu_ids);
return note_data; 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 linux_corefile_thread_data thread_args;
struct elf_internal_linux_prpsinfo prpsinfo; struct elf_internal_linux_prpsinfo prpsinfo;
char *note_data = NULL; char *note_data = NULL;
gdb_byte *auxv;
int auxv_len;
struct thread_info *curr_thr, *signalled_thr, *thr; struct thread_info *curr_thr, *signalled_thr, *thr;
if (! gdbarch_iterate_over_regset_sections_p (gdbarch)) 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; return NULL;
/* Auxillary vector. */ /* Auxillary vector. */
auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV, gdb::optional<gdb::byte_vector> auxv =
NULL, &auxv); target_read_alloc (&current_target, TARGET_OBJECT_AUXV, NULL);
if (auxv_len > 0) if (auxv && !auxv->empty ())
{ {
note_data = elfcore_write_note (obfd, note_data, note_size, note_data = elfcore_write_note (obfd, note_data, note_size,
"CORE", NT_AUXV, auxv, auxv_len); "CORE", NT_AUXV, auxv->data (),
xfree (auxv); auxv->size ());
if (!note_data) if (!note_data)
return NULL; return NULL;

View file

@ -163,11 +163,11 @@ std::unique_ptr<osdata>
get_osdata (const char *type) get_osdata (const char *type)
{ {
std::unique_ptr<osdata> osdata; 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)
{ {
if (xml.get ()[0] == '\0') if ((*xml)[0] == '\0')
{ {
if (type) if (type)
warning (_("Empty data returned by target. Wrong osdata 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?")); warning (_("Empty type list returned by target. No type data?"));
} }
else else
osdata = osdata_parse (xml.get ()); osdata = osdata_parse (xml->data ());
} }
if (osdata == NULL) if (osdata == NULL)

View file

@ -3151,13 +3151,13 @@ remote_get_threads_with_qxfer (struct target_ops *ops,
#if defined(HAVE_LIBEXPAT) #if defined(HAVE_LIBEXPAT)
if (packet_support (PACKET_qXfer_threads) == PACKET_ENABLE) 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); = 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", gdb_xml_parse_quick (_("threads"), "threads.dtd",
threads_elements, xml.get (), context); threads_elements, xml->data (), context);
} }
return 1; return 1;
@ -10790,11 +10790,11 @@ static std::vector<mem_region>
remote_memory_map (struct target_ops *ops) remote_memory_map (struct target_ops *ops)
{ {
std::vector<mem_region> result; 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); = target_read_stralloc (&current_target, TARGET_OBJECT_MEMORY_MAP, NULL);
if (text) if (text)
result = parse_memory_map (text.get ()); result = parse_memory_map (text->data ());
return result; return result;
} }
@ -12905,11 +12905,11 @@ remote_set_circular_trace_buffer (struct target_ops *self, int val)
static traceframe_info_up static traceframe_info_up
remote_traceframe_info (struct target_ops *self) 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, = target_read_stralloc (&current_target, TARGET_OBJECT_TRACEFRAME_INFO,
NULL); NULL);
if (text != NULL) if (text)
return parse_traceframe_info (text.get ()); return parse_traceframe_info (text->data ());
return NULL; return NULL;
} }
@ -13137,10 +13137,10 @@ btrace_sync_conf (const struct btrace_config *conf)
static void static void
btrace_read_config (struct btrace_config *conf) 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, ""); = target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE_CONF, "");
if (xml != NULL) if (xml)
parse_xml_btrace_conf (conf, xml.get ()); parse_xml_btrace_conf (conf, xml->data ());
} }
/* Maybe reopen target btrace. */ /* Maybe reopen target btrace. */
@ -13337,12 +13337,12 @@ remote_read_btrace (struct target_ops *self,
(unsigned int) type); (unsigned int) type);
} }
gdb::unique_xmalloc_ptr<char> xml gdb::optional<gdb::char_vector> xml
= target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE, annex); = target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE, annex);
if (xml == NULL) if (!xml)
return BTRACE_ERR_UNKNOWN; return BTRACE_ERR_UNKNOWN;
parse_xml_btrace (btrace, xml.get ()); parse_xml_btrace (btrace, xml->data ());
return BTRACE_ERR_NONE; return BTRACE_ERR_NONE;
} }
@ -13376,7 +13376,7 @@ remote_load (struct target_ops *self, const char *name, int from_tty)
static char * static char *
remote_pid_to_exec_file (struct target_ops *self, int pid) 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; struct inferior *inf;
char *annex = NULL; char *annex = NULL;
@ -13399,7 +13399,7 @@ remote_pid_to_exec_file (struct target_ops *self, int pid)
filename = target_read_stralloc (&current_target, filename = target_read_stralloc (&current_target,
TARGET_OBJECT_EXEC_FILE, annex); TARGET_OBJECT_EXEC_FILE, annex);
return filename.get (); return filename ? filename->data () : nullptr;
} }
/* Implement the to_can_do_single_step target_ops method. */ /* Implement the to_can_do_single_step target_ops method. */

View file

@ -279,10 +279,10 @@ solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
if (data->library_list != NULL) if (data->library_list != NULL)
return data->library_list; 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, = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_AIX,
NULL); NULL);
if (library_document == NULL && warning_msg != NULL) if (!library_document && warning_msg != NULL)
{ {
warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"), warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
warning_msg); warning_msg);
@ -292,9 +292,9 @@ solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
if (solib_aix_debug) if (solib_aix_debug)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
"DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n", "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) if (data->library_list == NULL && warning_msg != NULL)
{ {
warning (_("%s (missing XML support?)"), warning_msg); warning (_("%s (missing XML support?)"), warning_msg);

View file

@ -224,10 +224,10 @@ dsbt_print_loadmap (struct int_elf32_dsbt_loadmap *map)
/* Decode int_elf32_dsbt_loadmap from BUF. */ /* Decode int_elf32_dsbt_loadmap from BUF. */
static struct int_elf32_dsbt_loadmap * 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 ()); 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; struct int_elf32_dsbt_loadmap *int_ldmbuf;
int version, seg, nsegs; int version, seg, nsegs;
@ -278,7 +278,6 @@ decode_loadmap (gdb_byte *buf)
byte_order); byte_order);
} }
xfree (ext_ldmbuf);
return int_ldmbuf; return int_ldmbuf;
} }
@ -292,26 +291,26 @@ static struct dsbt_info *get_dsbt_info (void);
static void static void
dsbt_get_initial_loadmaps (void) dsbt_get_initial_loadmaps (void)
{ {
gdb_byte *buf;
struct dsbt_info *info = get_dsbt_info (); 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, if (!buf || buf->empty ())
"exec", &buf))
{ {
info->exec_loadmap = NULL; info->exec_loadmap = NULL;
error (_("Error reading DSBT exec loadmap")); error (_("Error reading DSBT exec loadmap"));
} }
info->exec_loadmap = decode_loadmap (buf); info->exec_loadmap = decode_loadmap (buf->data ());
if (solib_dsbt_debug) if (solib_dsbt_debug)
dsbt_print_loadmap (info->exec_loadmap); dsbt_print_loadmap (info->exec_loadmap);
if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC, buf = target_read_alloc (&current_target, TARGET_OBJECT_FDPIC, "exec");
"interp", &buf)) if (!buf || buf->empty ())
{ {
info->interp_loadmap = NULL; info->interp_loadmap = NULL;
error (_("Error reading DSBT interp loadmap")); error (_("Error reading DSBT interp loadmap"));
} }
info->interp_loadmap = decode_loadmap (buf); info->interp_loadmap = decode_loadmap (buf->data ());
if (solib_dsbt_debug) if (solib_dsbt_debug)
dsbt_print_loadmap (info->interp_loadmap); dsbt_print_loadmap (info->interp_loadmap);
} }

View 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 ()); gdb_assert (annex == NULL || target_augmented_libraries_svr4_read ());
/* Fetch the list of shared libraries. */ /* 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, = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_SVR4,
annex); annex);
if (svr4_library_document == NULL) if (!svr4_library_document)
return 0; return 0;
return svr4_parse_libraries (svr4_library_document.get (), list); return svr4_parse_libraries (svr4_library_document->data (), list);
} }
#else #else

View file

@ -257,13 +257,13 @@ solib_target_current_sos (void)
int ix; int ix;
/* Fetch the list of shared libraries. */ /* 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); = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES, NULL);
if (library_document == NULL) if (!library_document)
return NULL; return NULL;
/* Parse the list. */ /* 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) if (library_list == NULL)
return NULL; return NULL;

View file

@ -48,6 +48,7 @@
#include <algorithm> #include <algorithm>
#include "byte-vector.h" #include "byte-vector.h"
#include "terminal.h" #include "terminal.h"
#include <algorithm>
static void generic_tls_error (void) ATTRIBUTE_NORETURN; static void generic_tls_error (void) ATTRIBUTE_NORETURN;
@ -1937,18 +1938,17 @@ target_write (struct target_ops *ops,
NULL, NULL); NULL, NULL);
} }
/* Read OBJECT/ANNEX using OPS. Store the result in *BUF_P and return /* Help for target_read_alloc and target_read_stralloc. See their comments
the size of the transferred data. PADDING additional bytes are for details. */
available in *BUF_P. This is a helper function for
target_read_alloc; see the declaration of that function for more
information. */
static LONGEST template <typename T>
gdb::optional<gdb::def_vector<T>>
target_read_alloc_1 (struct target_ops *ops, enum target_object object, 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::def_vector<T> buf;
gdb_byte *buf; size_t buf_pos = 0;
const int chunk = 4096;
/* This function does not have a length parameter; it reads the /* This function does not have a length parameter; it reads the
entire OBJECT). Also, it doesn't support objects fetched partly 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 /* Start by reading up to 4K at a time. The target will throttle
this number down if necessary. */ this number down if necessary. */
buf_alloc = 4096;
buf = (gdb_byte *) xmalloc (buf_alloc);
buf_pos = 0;
while (1) while (1)
{ {
ULONGEST xfered_len; ULONGEST xfered_len;
enum target_xfer_status status; enum target_xfer_status status;
status = target_read_partial (ops, object, annex, &buf[buf_pos], buf.resize (buf_pos + chunk);
buf_pos, buf_alloc - buf_pos - padding,
status = target_read_partial (ops, object, annex,
(gdb_byte *) &buf[buf_pos],
buf_pos, chunk,
&xfered_len); &xfered_len);
if (status == TARGET_XFER_EOF) if (status == TARGET_XFER_EOF)
{ {
/* Read all there was. */ /* Read all there was. */
if (buf_pos == 0) buf.resize (buf_pos);
xfree (buf); return buf;
else
*buf_p = buf;
return buf_pos;
} }
else if (status != TARGET_XFER_OK) else if (status != TARGET_XFER_OK)
{ {
/* An error occurred. */ /* An error occurred. */
xfree (buf); return {};
return TARGET_XFER_E_IO;
} }
buf_pos += xfered_len; 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; QUIT;
} }
} }
/* Read OBJECT/ANNEX using OPS. Store the result in *BUF_P and return /* See target.h */
the size of the transferred data. See the declaration in "target.h"
function for more information about the return value. */
LONGEST gdb::optional<gdb::byte_vector>
target_read_alloc (struct target_ops *ops, enum target_object object, 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. */ /* See target.h. */
gdb::unique_xmalloc_ptr<char> gdb::optional<gdb::char_vector>
target_read_stralloc (struct target_ops *ops, enum target_object object, target_read_stralloc (struct target_ops *ops, enum target_object object,
const char *annex) const char *annex)
{ {
gdb_byte *buffer; gdb::optional<gdb::char_vector> buf
char *bufstr; = target_read_alloc_1<char> (ops, object, annex);
LONGEST i, transferred;
transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1); if (!buf)
bufstr = (char *) buffer; return {};
if (transferred < 0) if (buf->back () != '\0')
return NULL; buf->push_back ('\0');
if (transferred == 0)
return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
bufstr[transferred] = 0;
/* Check for embedded NUL bytes; but allow trailing NULs. */ /* Check for embedded NUL bytes; but allow trailing NULs. */
for (i = strlen (bufstr); i < transferred; i++) for (auto it = std::find (buf->begin (), buf->end (), '\0');
if (bufstr[i] != 0) it != buf->end (); it++)
if (*it != '\0')
{ {
warning (_("target object %d, annex %s, " warning (_("target object %d, annex %s, "
"contained unexpected null characters"), "contained unexpected null characters"),
@ -2042,7 +2024,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
break; break;
} }
return gdb::unique_xmalloc_ptr<char> (bufstr); return buf;
} }
/* Memory transfer methods. */ /* Memory transfer methods. */
@ -2744,7 +2726,7 @@ target_supports_multi_process (void)
/* See target.h. */ /* See target.h. */
gdb::unique_xmalloc_ptr<char> gdb::optional<gdb::char_vector>
target_get_osdata (const char *type) target_get_osdata (const char *type)
{ {
struct target_ops *t; struct target_ops *t;
@ -2758,7 +2740,7 @@ target_get_osdata (const char *type)
t = find_default_run_target ("get OS data"); t = find_default_run_target ("get OS data");
if (!t) if (!t)
return NULL; return {};
return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type); return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
} }

View file

@ -324,29 +324,26 @@ LONGEST target_write_with_progress (struct target_ops *ops,
void (*progress) (ULONGEST, void *), void (*progress) (ULONGEST, void *),
void *baton); void *baton);
/* Wrapper to perform a full read of unknown size. OBJECT/ANNEX will /* Wrapper to perform a full read of unknown size. OBJECT/ANNEX will be read
be read using OPS. The return value will be -1 if the transfer using OPS. The return value will be uninstantiated if the transfer fails or
fails or is not supported; 0 if the object is empty; or the length is not supported.
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.
This method should be used for objects sufficiently small to store 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 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 size is known in advance. Don't try to read TARGET_OBJECT_MEMORY
through this function. */ through this function. */
extern LONGEST target_read_alloc (struct target_ops *ops, extern gdb::optional<gdb::byte_vector> target_read_alloc
enum target_object object, (struct target_ops *ops, enum target_object object, const char *annex);
const char *annex, gdb_byte **buf_p);
/* Read OBJECT/ANNEX using OPS. The result is NUL-terminated and /* Read OBJECT/ANNEX using OPS. The result is a NUL-terminated character vector
returned as a string. If an error occurs or the transfer is (therefore usable as a NUL-terminated string). If an error occurs or the
unsupported, NULL is returned. Empty objects are returned as transfer is unsupported, the return value will be uninstantiated. Empty
allocated but empty strings. A warning is issued if the result objects are returned as allocated but empty strings. Therefore, on success,
contains any embedded NUL bytes. */ 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); (struct target_ops *ops, enum target_object object, const char *annex);
/* See target_ops->to_xfer_partial. */ /* 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); struct target_ops *find_target_at (enum strata stratum);
/* Read OS data object of type TYPE from the target, and return it in /* Read OS data object of type TYPE from the target, and return it in XML
XML format. The result is NUL-terminated and returned as a string. format. The return value follows the same rules as target_read_stralloc. */
If an error occurs or the transfer is unsupported, NULL is
returned. Empty objects are returned as allocated but empty
strings. */
extern gdb::unique_xmalloc_ptr<char> target_get_osdata (const char *type); extern gdb::optional<gdb::char_vector> target_get_osdata (const char *type);
/* Stuff that should be shared among the various remote targets. */ /* Stuff that should be shared among the various remote targets. */
/* Debugging level. 0 is off, and non-zero values mean to print some debug /* Debugging level. 0 is off, and non-zero values mean to print some debug

View file

@ -3871,23 +3871,19 @@ static struct value *
sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var, sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
void *ignore) void *ignore)
{ {
LONGEST size;
gdb_byte *buf;
/* We need to read the whole object before we know its size. */ /* We need to read the whole object before we know its size. */
size = target_read_alloc (&current_target, gdb::optional<gdb::byte_vector> buf
TARGET_OBJECT_STATIC_TRACE_DATA, = target_read_alloc (&current_target, TARGET_OBJECT_STATIC_TRACE_DATA,
NULL, &buf); NULL);
if (size >= 0) if (buf)
{ {
struct value *v; struct value *v;
struct type *type; struct type *type;
type = init_vector_type (builtin_type (gdbarch)->builtin_true_char, type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
size); buf->size ());
v = allocate_value (type); v = allocate_value (type);
memcpy (value_contents_raw (v), buf, size); memcpy (value_contents_raw (v), buf->data (), buf->size ());
xfree (buf);
return v; return v;
} }
else else

View file

@ -793,13 +793,13 @@ xinclude_start_include (struct gdb_xml_parser *parser,
gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"), gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
MAX_XINCLUDE_DEPTH); MAX_XINCLUDE_DEPTH);
gdb::unique_xmalloc_ptr<char> text = data->fetcher (href, gdb::optional<gdb::char_vector> text
data->fetcher_baton); = data->fetcher (href, data->fetcher_baton);
if (text == NULL) if (!text)
gdb_xml_error (parser, _("Could not load XML document \"%s\""), href); gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
if (!xml_process_xincludes (data->output, parser->name (), if (!xml_process_xincludes (data->output, parser->name (),
text.get (), data->fetcher, text->data (), data->fetcher,
data->fetcher_baton, data->fetcher_baton,
data->include_depth + 1)) data->include_depth + 1))
gdb_xml_error (parser, _("Parsing \"%s\" failed"), href); 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); 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) xml_fetch_content_from_file (const char *filename, void *baton)
{ {
const char *dirname = (const char *) 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); file = gdb_fopen_cloexec (filename, FOPEN_RT);
if (file == NULL) if (file == NULL)
return NULL; return {};
/* Read in the whole file. */ /* Read in the whole file. */
@ -1001,16 +1001,16 @@ xml_fetch_content_from_file (const char *filename, void *baton)
len = ftell (file.get ()); len = ftell (file.get ());
rewind (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 ())) || ferror (file.get ()))
{ {
warning (_("Read error from \"%s\""), filename); warning (_("Read error from \"%s\""), filename);
return NULL; return {};
} }
text.get ()[len] = '\0'; text.back () = '\0';
return text; return text;
} }

View file

@ -24,6 +24,7 @@
#include "gdb_obstack.h" #include "gdb_obstack.h"
#include "vec.h" #include "vec.h"
#include "xml-utils.h" #include "xml-utils.h"
#include "common/byte-vector.h"
struct gdb_xml_parser; struct gdb_xml_parser;
struct gdb_xml_element; 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. */ /* Callback to fetch a new XML file, based on the provided HREF. */
typedef gdb::unique_xmalloc_ptr<char> (*xml_fetch_another) (const char *href, typedef gdb::optional<gdb::char_vector> (*xml_fetch_another) (const char *href,
void *baton); void *baton);
/* Append the expansion of TEXT after processing <xi:include> tags in /* Append the expansion of TEXT after processing <xi:include> tags in
RESULT. FETCHER will be called (with FETCHER_BATON) to retrieve 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); const char *value);
/* Open FILENAME, read all its text into memory, close it, and return /* 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); (const char *filename, void *baton);
#endif #endif

View file

@ -305,12 +305,12 @@ syscall_parse_xml (const char *document, xml_fetch_another fetcher,
static struct syscalls_info * static struct syscalls_info *
xml_init_syscalls_info (const char *filename) 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); = xml_fetch_content_from_file (filename, gdb_datadir);
if (full_file == NULL) if (!full_file)
return NULL; return NULL;
return syscall_parse_xml (full_file.get (), return syscall_parse_xml (full_file->data (),
xml_fetch_content_from_file, xml_fetch_content_from_file,
(void *) ldirname (filename).c_str ()); (void *) ldirname (filename).c_str ());
} }

View file

@ -668,15 +668,15 @@ tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
const struct target_desc * const struct target_desc *
file_read_description_xml (const char *filename) 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); = xml_fetch_content_from_file (filename, NULL);
if (tdesc_str == NULL) if (!tdesc_str)
{ {
warning (_("Could not open \"%s\""), filename); warning (_("Could not open \"%s\""), filename);
return NULL; 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 ()); (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 is "target.xml". Other calls may be performed for the DTD or
for <xi:include>. */ 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_) fetch_available_features_from_target (const char *name, void *baton_)
{ {
struct target_ops *ops = (struct target_ops *) 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 * const struct target_desc *
target_read_description_xml (struct target_ops *ops) 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); = fetch_available_features_from_target ("target.xml", ops);
if (tdesc_str == NULL) if (!tdesc_str)
return NULL; return NULL;
return tdesc_parse_xml (tdesc_str.get (), return tdesc_parse_xml (tdesc_str->data (),
fetch_available_features_from_target, fetch_available_features_from_target,
ops); ops);
} }
@ -735,15 +735,15 @@ target_fetch_description_xml (struct target_ops *ops)
return {}; return {};
#else #else
gdb::unique_xmalloc_ptr<char> gdb::optional<gdb::char_vector>
tdesc_str = fetch_available_features_from_target ("target.xml", ops); tdesc_str = fetch_available_features_from_target ("target.xml", ops);
if (tdesc_str == NULL) if (!tdesc_str)
return {}; return {};
std::string output; std::string output;
if (!xml_process_xincludes (output, if (!xml_process_xincludes (output,
_("target description"), _("target description"),
tdesc_str.get (), tdesc_str->data (),
fetch_available_features_from_target, ops, 0)) fetch_available_features_from_target, ops, 0))
{ {
warning (_("Could not load XML target description; ignoring")); warning (_("Could not load XML target description; ignoring"));