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>
* 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. */
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;
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 (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;

View 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);
p = (const char *) buf;
for (k = i; k < (i + j); k++)
if (!buf)
{
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)
{
@ -1612,8 +1612,6 @@ avr_io_reg_read_command (const char *args, int from_tty)
break;
}
}
xfree (buf);
}
}

View 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 */

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 ());
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;

View 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)

View 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. */

View 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);

View 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);
}

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 ());
/* 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

View 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;

View 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;
gdb::optional<gdb::char_vector> buf
= target_read_alloc_1<char> (ops, object, annex);
transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
bufstr = (char *) buffer;
if (!buf)
return {};
if (transferred < 0)
return NULL;
if (transferred == 0)
return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
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);
}

View 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);
/* Stuff that should be shared among the various remote targets. */
/* 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,
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

View 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;
}

View 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

View 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 ());
}

View 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"));