From 53ee5f551e5743516c90a662425276cae4cf0aeb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 12 Apr 2024 00:33:22 -0700 Subject: [PATCH] util/hexdump: Use a GString for qemu_hexdump_line Allocate a new, or append to an existing GString instead of using a fixed sized buffer. Require the caller to determine the length of the line -- do not bound len here. Signed-off-by: Richard Henderson Message-Id: <20240412073346.458116-4-richard.henderson@linaro.org> --- hw/virtio/vhost-vdpa.c | 14 ++++++++------ include/qemu/cutils.h | 15 ++++++++++----- util/hexdump.c | 27 ++++++++++++++++----------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 7368b71902..419463c154 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -944,13 +944,15 @@ static int vhost_vdpa_set_config_call(struct vhost_dev *dev, static void vhost_vdpa_dump_config(struct vhost_dev *dev, const uint8_t *config, uint32_t config_len) { - int b, len; - char line[QEMU_HEXDUMP_LINE_LEN]; + g_autoptr(GString) str = g_string_sized_new(4 * 16); + size_t b, len; - for (b = 0; b < config_len; b += 16) { - len = config_len - b; - qemu_hexdump_line(line, config + b, len); - trace_vhost_vdpa_dump_config(dev, b, line); + for (b = 0; b < config_len; b += len) { + len = MIN(config_len - b, 16); + + g_string_truncate(str, 0); + qemu_hexdump_line(str, config + b, len); + trace_vhost_vdpa_dump_config(dev, b, str->str); } } diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index c5dea63742..14a3285343 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -282,12 +282,17 @@ static inline const char *yes_no(bool b) */ int parse_debug_env(const char *name, int max, int initial); -/* - * Hexdump a line of a byte buffer into a hexadecimal/ASCII buffer +/** + * qemu_hexdump_line: + * @str: GString into which to append + * @buf: buffer to dump + * @len: number of bytes to dump + * + * Append @len bytes of @buf as hexadecimal into @str. + * If @str is NULL, allocate a new string and return it; + * otherwise return @str. */ -#define QEMU_HEXDUMP_LINE_BYTES 16 /* Number of bytes to dump */ -#define QEMU_HEXDUMP_LINE_LEN 75 /* Number of characters in line */ -void qemu_hexdump_line(char *line, const void *bufptr, size_t len); +GString *qemu_hexdump_line(GString *str, const void *buf, size_t len); /* * Hexdump a buffer to a file. An optional string prefix is added to every line diff --git a/util/hexdump.c b/util/hexdump.c index 0f943e31e5..521e346bc6 100644 --- a/util/hexdump.c +++ b/util/hexdump.c @@ -16,22 +16,25 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" -void qemu_hexdump_line(char *line, const void *bufptr, size_t len) +GString *qemu_hexdump_line(GString *str, const void *vbuf, size_t len) { - const char *buf = bufptr; - int i; + const uint8_t *buf = vbuf; + size_t i; - if (len > QEMU_HEXDUMP_LINE_BYTES) { - len = QEMU_HEXDUMP_LINE_BYTES; + if (str == NULL) { + /* Estimate the length of the output to avoid reallocs. */ + i = len * 3 + len / 4; + str = g_string_sized_new(i + 1); } for (i = 0; i < len; i++) { if (i != 0 && (i % 4) == 0) { - *line++ = ' '; + g_string_append_c(str, ' '); } - line += sprintf(line, " %02x", (unsigned char)buf[i]); + g_string_append_printf(str, " %02x", buf[i]); } - *line = '\0'; + + return str; } static void asciidump_line(char *line, const void *bufptr, size_t len) @@ -49,24 +52,26 @@ static void asciidump_line(char *line, const void *bufptr, size_t len) *line = '\0'; } +#define QEMU_HEXDUMP_LINE_BYTES 16 #define QEMU_HEXDUMP_LINE_WIDTH \ (QEMU_HEXDUMP_LINE_BYTES * 2 + QEMU_HEXDUMP_LINE_BYTES / 4) void qemu_hexdump(FILE *fp, const char *prefix, const void *bufptr, size_t size) { - char line[QEMU_HEXDUMP_LINE_LEN]; + g_autoptr(GString) str = g_string_sized_new(QEMU_HEXDUMP_LINE_WIDTH + 1); char ascii[QEMU_HEXDUMP_LINE_BYTES + 1]; size_t b, len; for (b = 0; b < size; b += len) { len = MIN(size - b, QEMU_HEXDUMP_LINE_BYTES); - qemu_hexdump_line(line, bufptr + b, len); + g_string_truncate(str, 0); + qemu_hexdump_line(str, bufptr + b, len); asciidump_line(ascii, bufptr + b, len); fprintf(fp, "%s: %04zx: %-*s %s\n", - prefix, b, QEMU_HEXDUMP_LINE_WIDTH, line, ascii); + prefix, b, QEMU_HEXDUMP_LINE_WIDTH, str->str, ascii); } }