* [PATCH 1/5] dump: Allocate header
2022-03-10 11:16 [PATCH 0/5] dump: Add custom arch section support Janosch Frank
@ 2022-03-10 11:16 ` Janosch Frank
2022-03-11 20:06 ` Richard Henderson
2022-03-10 11:16 ` [PATCH 2/5] dump: Split write of section headers and data and add a prepare step Janosch Frank
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Janosch Frank @ 2022-03-10 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
Allocating the header lets us write it at a later time and hence also
allows us to change section and segment table offsets until we
finally write it.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
dump/dump.c | 115 ++++++++++++++++++++++--------------------
include/sysemu/dump.h | 1 +
2 files changed, 62 insertions(+), 54 deletions(-)
diff --git a/dump/dump.c b/dump/dump.c
index ae8ec527de..88343d7486 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -99,6 +99,7 @@ static int dump_cleanup(DumpState *s)
memory_mapping_list_free(&s->list);
close(s->fd);
g_free(s->guest_note);
+ g_free(s->elf_header);
s->guest_note = NULL;
if (s->resume) {
if (s->detached) {
@@ -127,63 +128,47 @@ static int fd_write_vmcore(const void *buf, size_t size, void *opaque)
return 0;
}
-static void write_elf64_header(DumpState *s, Error **errp)
+static void prepare_elf64_header(DumpState *s)
{
- uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num;
- Elf64_Ehdr elf_header;
- int ret;
+ Elf64_Ehdr *elf_header = s->elf_header;
- memset(&elf_header, 0, sizeof(Elf64_Ehdr));
- memcpy(&elf_header, ELFMAG, SELFMAG);
- elf_header.e_ident[EI_CLASS] = ELFCLASS64;
- elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
- elf_header.e_ident[EI_VERSION] = EV_CURRENT;
- elf_header.e_type = cpu_to_dump16(s, ET_CORE);
- elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
- elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
- elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
- elf_header.e_phoff = cpu_to_dump64(s, s->phdr_offset);
- elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
- elf_header.e_phnum = cpu_to_dump16(s, phnum);
+ memcpy(elf_header, ELFMAG, SELFMAG);
+ elf_header->e_ident[EI_CLASS] = ELFCLASS64;
+ elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
+ elf_header->e_ident[EI_VERSION] = EV_CURRENT;
+ elf_header->e_type = cpu_to_dump16(s, ET_CORE);
+ elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
+ elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
+ elf_header->e_ehsize = cpu_to_dump16(s, sizeof(*elf_header));
+ elf_header->e_phoff = cpu_to_dump64(s, s->phdr_offset);
+ elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr));
+ elf_header->e_phnum = cpu_to_dump16(s, s->phdr_num);
if (s->shdr_num) {
- elf_header.e_shoff = cpu_to_dump64(s, s->shdr_offset);
- elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
- elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num);
- }
-
- ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
- if (ret < 0) {
- error_setg_errno(errp, -ret, "dump: failed to write elf header");
+ elf_header->e_shoff = cpu_to_dump64(s, s->shdr_offset);
+ elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr));
+ elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num);
}
}
-static void write_elf32_header(DumpState *s, Error **errp)
+static void prepare_elf32_header(DumpState *s)
{
- uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num;
- Elf32_Ehdr elf_header;
- int ret;
+ Elf32_Ehdr *elf_header = s->elf_header;
- memset(&elf_header, 0, sizeof(Elf32_Ehdr));
- memcpy(&elf_header, ELFMAG, SELFMAG);
- elf_header.e_ident[EI_CLASS] = ELFCLASS32;
- elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
- elf_header.e_ident[EI_VERSION] = EV_CURRENT;
- elf_header.e_type = cpu_to_dump16(s, ET_CORE);
- elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
- elf_header.e_version = cpu_to_dump32(s, EV_CURRENT);
- elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header));
- elf_header.e_phoff = cpu_to_dump32(s, s->phdr_offset);
- elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
- elf_header.e_phnum = cpu_to_dump16(s, phnum);
+ memcpy(elf_header, ELFMAG, SELFMAG);
+ elf_header->e_ident[EI_CLASS] = ELFCLASS32;
+ elf_header->e_ident[EI_DATA] = s->dump_info.d_endian;
+ elf_header->e_ident[EI_VERSION] = EV_CURRENT;
+ elf_header->e_type = cpu_to_dump16(s, ET_CORE);
+ elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine);
+ elf_header->e_version = cpu_to_dump32(s, EV_CURRENT);
+ elf_header->e_ehsize = cpu_to_dump16(s, sizeof(*elf_header));
+ elf_header->e_phoff = cpu_to_dump32(s, s->phdr_offset);
+ elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr));
+ elf_header->e_phnum = cpu_to_dump16(s, s->phdr_num);
if (s->shdr_num) {
- elf_header.e_shoff = cpu_to_dump32(s, s->shdr_offset);
- elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf32_Shdr));
- elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num);
- }
-
- ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
- if (ret < 0) {
- error_setg_errno(errp, -ret, "dump: failed to write elf header");
+ elf_header->e_shoff = cpu_to_dump32(s, s->shdr_offset);
+ elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf32_Shdr));
+ elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num);
}
}
@@ -524,6 +509,26 @@ static void write_elf_notes(DumpState *s, Error **errp)
}
}
+static void prepare_elf_header(DumpState *s)
+{
+ if (dump_is_64bit(s)) {
+ prepare_elf64_header(s);
+ } else {
+ prepare_elf32_header(s);
+ }
+}
+
+static void write_elf_header(DumpState *s, Error **errp)
+{
+ size_t size = dump_is_64bit(s) ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
+ int ret;
+
+ ret = fd_write_vmcore(s->elf_header, size, s);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "dump: failed to write elf header");
+ }
+}
+
/* write elf header, PT_NOTE and elf note to vmcore. */
static void dump_begin(DumpState *s, Error **errp)
{
@@ -553,12 +558,11 @@ static void dump_begin(DumpState *s, Error **errp)
* vmcore.
*/
- /* write elf header to vmcore */
- if (dump_is_64bit(s)) {
- write_elf64_header(s, errp);
- } else {
- write_elf32_header(s, errp);
- }
+ /* Write elf header to buffer */
+ prepare_elf_header(s);
+
+ /* Start to write stuff into files*/
+ write_elf_header(s, errp);
if (*errp) {
return;
}
@@ -1683,6 +1687,9 @@ static void dump_init(DumpState *s, int fd, bool has_format,
goto cleanup;
}
+ s->elf_header = g_malloc0(dump_is_64bit(s) ?
+ sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr));
+
/*
* The goal of this block is to (a) update the previously guessed
* phys_base, (b) copy the guest note out of the guest.
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index ffc2ea1072..9c4a83156b 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -172,6 +172,7 @@ typedef struct DumpState {
int64_t begin;
int64_t length;
+ void *elf_header;
uint8_t *note_buf; /* buffer for notes */
size_t note_buf_offset; /* the writing place in note_buf */
uint32_t nr_cpus; /* number of guest's cpu */
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/5] dump: Allocate header
2022-03-10 11:16 ` [PATCH 1/5] dump: Allocate header Janosch Frank
@ 2022-03-11 20:06 ` Richard Henderson
0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-03-11 20:06 UTC (permalink / raw)
To: Janosch Frank, qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
On 3/10/22 03:16, Janosch Frank wrote:
> Allocating the header lets us write it at a later time and hence also
> allows us to change section and segment table offsets until we
> finally write it.
>
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> ---
> dump/dump.c | 115 ++++++++++++++++++++++--------------------
> include/sysemu/dump.h | 1 +
> 2 files changed, 62 insertions(+), 54 deletions(-)
You're collecting the important pieces that go into the header separately (phdr_offset,
phdr_num, etc), and you can certainly change those as you go along. But I don't see the
point of allocating the ehdr early. I think you should create it and write it out
immediately.
r~
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/5] dump: Split write of section headers and data and add a prepare step
2022-03-10 11:16 [PATCH 0/5] dump: Add custom arch section support Janosch Frank
2022-03-10 11:16 ` [PATCH 1/5] dump: Allocate header Janosch Frank
@ 2022-03-10 11:16 ` Janosch Frank
2022-03-11 20:26 ` Richard Henderson
2022-03-10 11:16 ` [PATCH 3/5] dump: Reorder struct DumpState Janosch Frank
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Janosch Frank @ 2022-03-10 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
By splitting the writing of the section headers and (future) section
data we prepare for the addition of a string table section and
architecture sections.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
dump/dump.c | 112 ++++++++++++++++++++++++++++++++----------
include/sysemu/dump.h | 4 ++
2 files changed, 90 insertions(+), 26 deletions(-)
diff --git a/dump/dump.c b/dump/dump.c
index 88343d7486..e4198e8f3e 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -341,30 +341,72 @@ static void write_elf_phdr_note(DumpState *s, Error **errp)
}
}
-static void write_elf_section(DumpState *s, int type, Error **errp)
+static size_t write_elf_section_hdr_zero(DumpState *s, void *buff)
{
- Elf32_Shdr shdr32;
- Elf64_Shdr shdr64;
- int shdr_size;
- void *shdr;
- int ret;
+ Elf32_Shdr *shdr32 = buff;
+ Elf64_Shdr *shdr64 = buff;
- if (type == 0) {
- shdr_size = sizeof(Elf32_Shdr);
- memset(&shdr32, 0, shdr_size);
- shdr32.sh_info = cpu_to_dump32(s, s->phdr_num);
- shdr = &shdr32;
+ if (dump_is_64bit(s)) {
+ memset(buff, 0, sizeof(Elf64_Shdr));
+ shdr64->sh_info = cpu_to_dump32(s, s->phdr_num);
} else {
- shdr_size = sizeof(Elf64_Shdr);
- memset(&shdr64, 0, shdr_size);
- shdr64.sh_info = cpu_to_dump32(s, s->phdr_num);
- shdr = &shdr64;
+ memset(buff, 0, sizeof(Elf32_Shdr));
+ shdr32->sh_info = cpu_to_dump32(s, s->phdr_num);
}
- ret = fd_write_vmcore(shdr, shdr_size, s);
+ return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
+}
+
+static void prepare_elf_section_hdrs(DumpState *s)
+{
+ uint8_t *buff_hdr;
+ size_t len, sizeof_shdr;
+
+ /*
+ * Section ordering:
+ * - HDR zero (if needed)
+ */
+ sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
+ len = sizeof_shdr * s->shdr_num ;
+ s->elf_section_hdrs = g_malloc0(len);
+ buff_hdr = s->elf_section_hdrs;
+
+ /* Write special section first */
+ if (s->phdr_num == PN_XNUM) {
+ write_elf_section_hdr_zero(s, buff_hdr);
+ }
+}
+
+static void prepare_elf_sections(DumpState *s, Error **errp)
+{
+ if (!s->shdr_num) {
+ return;
+ }
+
+ prepare_elf_section_hdrs(s);
+}
+
+static void write_elf_section_headers(DumpState *s, Error **errp)
+{
+ size_t sizeof_shdr;
+ int ret;
+
+ sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
+
+ ret = fd_write_vmcore(s->elf_section_hdrs, s->shdr_num * sizeof_shdr, s);
if (ret < 0) {
- error_setg_errno(errp, -ret,
- "dump: failed to write section header table");
+ error_setg_errno(errp, -ret, "dump: failed to write section data");
+ }
+}
+
+static void write_elf_sections(DumpState *s, Error **errp)
+{
+ int ret;
+
+ /* Write section zero */
+ ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "dump: failed to write section data");
}
}
@@ -561,12 +603,22 @@ static void dump_begin(DumpState *s, Error **errp)
/* Write elf header to buffer */
prepare_elf_header(s);
+ prepare_elf_sections(s, errp);
+ if (*errp) {
+ return;
+ }
+
/* Start to write stuff into files*/
write_elf_header(s, errp);
if (*errp) {
return;
}
+ write_elf_section_headers(s, errp);
+ if (*errp) {
+ return;
+ }
+
/* write PT_NOTE to vmcore */
write_elf_phdr_note(s, errp);
if (*errp) {
@@ -579,14 +631,6 @@ static void dump_begin(DumpState *s, Error **errp)
return;
}
- /* write section to vmcore */
- if (s->shdr_num) {
- write_elf_section(s, 1, errp);
- if (*errp) {
- return;
- }
- }
-
/* write notes to vmcore */
write_elf_notes(s, errp);
}
@@ -643,6 +687,19 @@ static void dump_iterate(DumpState *s, Error **errp)
} while (!get_next_block(s, block));
}
+static void dump_end(DumpState *s, Error **errp)
+{
+ ERRP_GUARD();
+
+ if (!s->elf_section_data_size) {
+ return;
+ }
+ s->elf_section_data = g_malloc0(s->elf_section_data_size);
+
+ /* write sections to vmcore */
+ write_elf_sections(s, errp);
+}
+
static void create_vmcore(DumpState *s, Error **errp)
{
ERRP_GUARD();
@@ -653,6 +710,9 @@ static void create_vmcore(DumpState *s, Error **errp)
}
dump_iterate(s, errp);
+
+ /* Write section data after memory has been dumped */
+ dump_end(s, errp);
}
static int write_start_flat_header(int fd)
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 9c4a83156b..4c5a593b81 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -173,6 +173,10 @@ typedef struct DumpState {
int64_t length;
void *elf_header;
+ void *elf_section_hdrs;
+ uint64_t elf_section_data_size;
+ void *elf_section_data;
+
uint8_t *note_buf; /* buffer for notes */
size_t note_buf_offset; /* the writing place in note_buf */
uint32_t nr_cpus; /* number of guest's cpu */
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/5] dump: Split write of section headers and data and add a prepare step
2022-03-10 11:16 ` [PATCH 2/5] dump: Split write of section headers and data and add a prepare step Janosch Frank
@ 2022-03-11 20:26 ` Richard Henderson
0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-03-11 20:26 UTC (permalink / raw)
To: Janosch Frank, qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
On 3/10/22 03:16, Janosch Frank wrote:
> -static void write_elf_section(DumpState *s, int type, Error **errp)
> +static size_t write_elf_section_hdr_zero(DumpState *s, void *buff)
> {
> - Elf32_Shdr shdr32;
> - Elf64_Shdr shdr64;
> - int shdr_size;
> - void *shdr;
> - int ret;
> + Elf32_Shdr *shdr32 = buff;
> + Elf64_Shdr *shdr64 = buff;
>
> - if (type == 0) {
> - shdr_size = sizeof(Elf32_Shdr);
> - memset(&shdr32, 0, shdr_size);
> - shdr32.sh_info = cpu_to_dump32(s, s->phdr_num);
> - shdr = &shdr32;
> + if (dump_is_64bit(s)) {
> + memset(buff, 0, sizeof(Elf64_Shdr));
> + shdr64->sh_info = cpu_to_dump32(s, s->phdr_num);
> } else {
> - shdr_size = sizeof(Elf64_Shdr);
> - memset(&shdr64, 0, shdr_size);
> - shdr64.sh_info = cpu_to_dump32(s, s->phdr_num);
> - shdr = &shdr64;
> + memset(buff, 0, sizeof(Elf32_Shdr));
> + shdr32->sh_info = cpu_to_dump32(s, s->phdr_num);
> }
I'd move those shdr* variables into the if blocks.
It looks odd to have them both in scope at once.
You're re-zeroing the data -- it was allocated with g_malloc0.
>
> - ret = fd_write_vmcore(shdr, shdr_size, s);
> + return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> +}
Return value here...
> +
> +static void prepare_elf_section_hdrs(DumpState *s)
> +{
> + uint8_t *buff_hdr;
> + size_t len, sizeof_shdr;
> +
> + /*
> + * Section ordering:
> + * - HDR zero (if needed)
> + */
> + sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> + len = sizeof_shdr * s->shdr_num ;
> + s->elf_section_hdrs = g_malloc0(len);
Perhaps save to s->shdr_len?
> + buff_hdr = s->elf_section_hdrs;
Why this extra variable?
> +
> + /* Write special section first */
> + if (s->phdr_num == PN_XNUM) {
> + write_elf_section_hdr_zero(s, buff_hdr);
> + }
... but not used here. Was there some other intended use? You already know the size, per
above...
> +static void write_elf_section_headers(DumpState *s, Error **errp)
> +{
> + size_t sizeof_shdr;
> + int ret;
> +
> + sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
> +
> + ret = fd_write_vmcore(s->elf_section_hdrs, s->shdr_num * sizeof_shdr, s);
Use saved s->shdr_len? Skip if 0?
> +static void write_elf_sections(DumpState *s, Error **errp)
> +{
> + int ret;
> +
> + /* Write section zero */
> + ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
Again skip if 0? Comment is misleading because section 0 should have no contents...
r~
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/5] dump: Reorder struct DumpState
2022-03-10 11:16 [PATCH 0/5] dump: Add custom arch section support Janosch Frank
2022-03-10 11:16 ` [PATCH 1/5] dump: Allocate header Janosch Frank
2022-03-10 11:16 ` [PATCH 2/5] dump: Split write of section headers and data and add a prepare step Janosch Frank
@ 2022-03-10 11:16 ` Janosch Frank
2022-03-11 20:13 ` Richard Henderson
2022-03-10 11:16 ` [PATCH 4/5] dump/dump: Add section string table support Janosch Frank
2022-03-10 11:16 ` [PATCH 5/5] dump/dump: Add arch section support Janosch Frank
4 siblings, 1 reply; 10+ messages in thread
From: Janosch Frank @ 2022-03-10 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
Let's move ELF related members into one block and guest memory related
ones into another to improve readability.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
include/sysemu/dump.h | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 4c5a593b81..186348a972 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -154,24 +154,28 @@ typedef struct DumpState {
GuestPhysBlockList guest_phys_blocks;
ArchDumpInfo dump_info;
MemoryMappingList list;
- uint32_t phdr_num;
- uint32_t shdr_num;
bool resume;
bool detached;
- ssize_t note_size;
- hwaddr shdr_offset;
- hwaddr phdr_offset;
- hwaddr section_offset;
- hwaddr note_offset;
hwaddr memory_offset;
int fd;
+ /* Guest memory related data */
GuestPhysBlock *next_block;
ram_addr_t start;
bool has_filter;
int64_t begin;
int64_t length;
+ /* Elf dump related data */
+ uint32_t phdr_num;
+ uint32_t shdr_num;
+ uint32_t sh_info;
+ ssize_t note_size;
+ hwaddr shdr_offset;
+ hwaddr phdr_offset;
+ hwaddr note_offset;
+ hwaddr section_offset;
+
void *elf_header;
void *elf_section_hdrs;
uint64_t elf_section_data_size;
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/5] dump/dump: Add section string table support
2022-03-10 11:16 [PATCH 0/5] dump: Add custom arch section support Janosch Frank
` (2 preceding siblings ...)
2022-03-10 11:16 ` [PATCH 3/5] dump: Reorder struct DumpState Janosch Frank
@ 2022-03-10 11:16 ` Janosch Frank
2022-03-12 14:18 ` Richard Henderson
2022-03-10 11:16 ` [PATCH 5/5] dump/dump: Add arch section support Janosch Frank
4 siblings, 1 reply; 10+ messages in thread
From: Janosch Frank @ 2022-03-10 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
Time to add a bit more descriptiveness to the dumps.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
dump/dump.c | 106 ++++++++++++++++++++++++++++++++++++------
include/sysemu/dump.h | 1 +
2 files changed, 94 insertions(+), 13 deletions(-)
diff --git a/dump/dump.c b/dump/dump.c
index e4198e8f3e..7b3fd6a065 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -100,6 +100,7 @@ static int dump_cleanup(DumpState *s)
close(s->fd);
g_free(s->guest_note);
g_free(s->elf_header);
+ g_array_unref(s->string_table_buf);
s->guest_note = NULL;
if (s->resume) {
if (s->detached) {
@@ -357,14 +358,47 @@ static size_t write_elf_section_hdr_zero(DumpState *s, void *buff)
return dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
}
+static void write_elf_section_hdr_string(DumpState *s, void *buff)
+{
+ Elf32_Shdr shdr32;
+ Elf64_Shdr shdr64;
+ int shdr_size;
+ void *shdr = buff;
+
+ if (dump_is_64bit(s)) {
+ shdr_size = sizeof(Elf64_Shdr);
+ memset(&shdr64, 0, shdr_size);
+ shdr64.sh_type = SHT_STRTAB;
+ shdr64.sh_offset = s->section_offset + s->elf_section_data_size;
+ shdr64.sh_name = s->string_table_buf->len;
+ g_array_append_vals(s->string_table_buf, ".strtab", sizeof(".strtab"));
+ shdr64.sh_size = s->string_table_buf->len;
+ shdr = &shdr64;
+ } else {
+ shdr_size = sizeof(Elf32_Shdr);
+ memset(&shdr32, 0, shdr_size);
+ shdr32.sh_type = SHT_STRTAB;
+ shdr32.sh_offset = s->section_offset + s->elf_section_data_size;
+ shdr32.sh_name = s->string_table_buf->len;
+ g_array_append_vals(s->string_table_buf, ".strtab", sizeof(".strtab"));
+ shdr32.sh_size = s->string_table_buf->len;
+ shdr = &shdr32;
+ }
+
+ memcpy(buff, shdr, shdr_size);
+}
+
static void prepare_elf_section_hdrs(DumpState *s)
{
uint8_t *buff_hdr;
- size_t len, sizeof_shdr;
+ size_t len, size = 0, sizeof_shdr;
+ Elf64_Ehdr *hdr64 = s->elf_header;
+ Elf32_Ehdr *hdr32 = s->elf_header;
/*
* Section ordering:
* - HDR zero (if needed)
+ * - String table hdr
*/
sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
len = sizeof_shdr * s->shdr_num ;
@@ -375,6 +409,22 @@ static void prepare_elf_section_hdrs(DumpState *s)
if (s->phdr_num == PN_XNUM) {
write_elf_section_hdr_zero(s, buff_hdr);
}
+ buff_hdr += size;
+
+ if (s->shdr_num < 2) {
+ return;
+ }
+
+ /*
+ * String table needs to be last section since strings are added
+ * via arch_sections_write_hdr().
+ */
+ write_elf_section_hdr_string(s, buff_hdr);
+ if (dump_is_64bit(s)) {
+ hdr64->e_shstrndx = cpu_to_dump16(s, s->shdr_num - 1);
+ } else {
+ hdr32->e_shstrndx = cpu_to_dump16(s, s->shdr_num - 1);
+ }
}
static void prepare_elf_sections(DumpState *s, Error **errp)
@@ -403,11 +453,18 @@ static void write_elf_sections(DumpState *s, Error **errp)
{
int ret;
- /* Write section zero */
+ /* Write section zero and arch sections */
ret = fd_write_vmcore(s->elf_section_data, s->elf_section_data_size, s);
if (ret < 0) {
error_setg_errno(errp, -ret, "dump: failed to write section data");
}
+
+ /* Write string table data */
+ ret = fd_write_vmcore(s->string_table_buf->data,
+ s->string_table_buf->len, s);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "dump: failed to write string table data");
+ }
}
static void write_data(DumpState *s, void *buf, int length, Error **errp)
@@ -595,6 +652,9 @@ static void dump_begin(DumpState *s, Error **errp)
* --------------
* | memory |
* --------------
+ * | sectn data |
+ * --------------
+
*
* we only know where the memory is saved after we write elf note into
* vmcore.
@@ -709,6 +769,7 @@ static void create_vmcore(DumpState *s, Error **errp)
return;
}
+ /* Iterate over memory and dump it to file */
dump_iterate(s, errp);
/* Write section data after memory has been dumped */
@@ -1704,6 +1765,13 @@ static void dump_init(DumpState *s, int fd, bool has_format,
s->has_filter = has_filter;
s->begin = begin;
s->length = length;
+ /* First index is 0, it's the special null name */
+ s->string_table_buf = g_array_new(FALSE, TRUE, 1);
+ /*
+ * Allocate the null name, due to the clearing option set to true
+ * it will be 0.
+ */
+ g_array_set_size(s->string_table_buf, 1);
memory_mapping_list_init(&s->list);
@@ -1864,19 +1932,31 @@ static void dump_init(DumpState *s, int fd, bool has_format,
}
}
- if (dump_is_64bit(s)) {
- s->phdr_offset = sizeof(Elf64_Ehdr);
- s->shdr_offset = s->phdr_offset + sizeof(Elf64_Phdr) * s->phdr_num;
- s->note_offset = s->shdr_offset + sizeof(Elf64_Shdr) * s->shdr_num;
- s->memory_offset = s->note_offset + s->note_size;
- } else {
-
- s->phdr_offset = sizeof(Elf32_Ehdr);
- s->shdr_offset = s->phdr_offset + sizeof(Elf32_Phdr) * s->phdr_num;
- s->note_offset = s->shdr_offset + sizeof(Elf32_Shdr) * s->shdr_num;
- s->memory_offset = s->note_offset + s->note_size;
+ /*
+ * calculate shdr_num and elf_section_data_size so we know the offsets and
+ * sizes of all parts.
+ *
+ * If phdr_num overflowed we have at least one section header
+ * More sections/hdrs can be added by the architectures
+ */
+ if (s->shdr_num > 1) {
+ /* Reserve the string table */
+ s->shdr_num += 1;
}
+ tmp = (s->phdr_num == PN_XNUM) ? s->sh_info : s->phdr_num;
+ if (dump_is_64bit(s)) {
+ s->shdr_offset = sizeof(Elf64_Ehdr);
+ s->phdr_offset = s->shdr_offset + sizeof(Elf64_Shdr) * s->shdr_num;
+ s->note_offset = s->phdr_offset + sizeof(Elf64_Phdr) * tmp;
+ } else {
+ s->shdr_offset = sizeof(Elf32_Ehdr);
+ s->phdr_offset = s->shdr_offset + sizeof(Elf32_Shdr) * s->shdr_num;
+ s->note_offset = s->phdr_offset + sizeof(Elf32_Phdr) * tmp;
+ }
+ s->memory_offset = s->note_offset + s->note_size;
+ s->section_offset = s->memory_offset + s->total_size;
+
return;
cleanup:
diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h
index 186348a972..9a000e7483 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -180,6 +180,7 @@ typedef struct DumpState {
void *elf_section_hdrs;
uint64_t elf_section_data_size;
void *elf_section_data;
+ GArray *string_table_buf; /* String table section */
uint8_t *note_buf; /* buffer for notes */
size_t note_buf_offset; /* the writing place in note_buf */
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 4/5] dump/dump: Add section string table support
2022-03-10 11:16 ` [PATCH 4/5] dump/dump: Add section string table support Janosch Frank
@ 2022-03-12 14:18 ` Richard Henderson
0 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2022-03-12 14:18 UTC (permalink / raw)
To: Janosch Frank, qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
On 3/10/22 03:16, Janosch Frank wrote:
> Time to add a bit more descriptiveness to the dumps.
>
> Signed-off-by: Janosch Frank<frankja@linux.ibm.com>
> ---
> dump/dump.c | 106 ++++++++++++++++++++++++++++++++++++------
> include/sysemu/dump.h | 1 +
> 2 files changed, 94 insertions(+), 13 deletions(-)
Hmm. I suppose. Depending on the scope of your intended end result, this is either
sufficient, or simplistic.
This is beginning to feel like a rewrite of <gelf.h> and <libdwelf.h>.
However,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/5] dump/dump: Add arch section support
2022-03-10 11:16 [PATCH 0/5] dump: Add custom arch section support Janosch Frank
` (3 preceding siblings ...)
2022-03-10 11:16 ` [PATCH 4/5] dump/dump: Add section string table support Janosch Frank
@ 2022-03-10 11:16 ` Janosch Frank
4 siblings, 0 replies; 10+ messages in thread
From: Janosch Frank @ 2022-03-10 11:16 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau, mhartmay, pbonzini
Add hooks which architectures can use to add arbitrary data to custom
sections.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
---
dump/dump.c | 21 ++++++++++++++++++---
include/sysemu/dump-arch.h | 27 +++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/dump/dump.c b/dump/dump.c
index 7b3fd6a065..a9d9ea514d 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -398,6 +398,7 @@ static void prepare_elf_section_hdrs(DumpState *s)
/*
* Section ordering:
* - HDR zero (if needed)
+ * - Arch section hdrs
* - String table hdr
*/
sizeof_shdr = dump_is_64bit(s) ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr);
@@ -415,6 +416,9 @@ static void prepare_elf_section_hdrs(DumpState *s)
return;
}
+ size = dump_arch_sections_write_hdr(&s->dump_info, s, buff_hdr);
+ buff_hdr += size;
+
/*
* String table needs to be last section since strings are added
* via arch_sections_write_hdr().
@@ -565,14 +569,23 @@ static void get_offset_range(hwaddr phys_addr,
}
}
-static void write_elf_loads(DumpState *s, Error **errp)
+static void write_elf_phdr_loads(DumpState *s, Error **errp)
{
ERRP_GUARD();
hwaddr offset, filesz;
MemoryMapping *memory_mapping;
uint32_t phdr_index = 1;
+ hwaddr min = 0, max = 0;
QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+ if (memory_mapping->phys_addr < min) {
+ min = memory_mapping->phys_addr;
+ }
+ if (memory_mapping->phys_addr + memory_mapping->length > max) {
+ max = memory_mapping->phys_addr + memory_mapping->length;
+ }
+
+
get_offset_range(memory_mapping->phys_addr,
memory_mapping->length,
s, &offset, &filesz);
@@ -685,8 +698,8 @@ static void dump_begin(DumpState *s, Error **errp)
return;
}
- /* write all PT_LOAD to vmcore */
- write_elf_loads(s, errp);
+ /* write all PT_LOADs to vmcore */
+ write_elf_phdr_loads(s, errp);
if (*errp) {
return;
}
@@ -755,6 +768,7 @@ static void dump_end(DumpState *s, Error **errp)
return;
}
s->elf_section_data = g_malloc0(s->elf_section_data_size);
+ dump_arch_sections_write(&s->dump_info, s, s->elf_section_data);
/* write sections to vmcore */
write_elf_sections(s, errp);
@@ -1939,6 +1953,7 @@ static void dump_init(DumpState *s, int fd, bool has_format,
* If phdr_num overflowed we have at least one section header
* More sections/hdrs can be added by the architectures
*/
+ dump_arch_sections_add(&s->dump_info, (void *)s);
if (s->shdr_num > 1) {
/* Reserve the string table */
s->shdr_num += 1;
diff --git a/include/sysemu/dump-arch.h b/include/sysemu/dump-arch.h
index e25b02e990..de77908424 100644
--- a/include/sysemu/dump-arch.h
+++ b/include/sysemu/dump-arch.h
@@ -21,6 +21,9 @@ typedef struct ArchDumpInfo {
uint32_t page_size; /* The target's page size. If it's variable and
* unknown, then this should be the maximum. */
uint64_t phys_base; /* The target's physmem base. */
+ void (*arch_sections_add_fn)(void *opaque);
+ uint64_t (*arch_sections_write_hdr_fn)(void *opaque, uint8_t *buff);
+ void (*arch_sections_write_fn)(void *opaque, uint8_t *buff);
} ArchDumpInfo;
struct GuestPhysBlockList; /* memory_mapping.h */
@@ -28,4 +31,28 @@ int cpu_get_dump_info(ArchDumpInfo *info,
const struct GuestPhysBlockList *guest_phys_blocks);
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus);
+static inline void dump_arch_sections_add(ArchDumpInfo *info, void *opaque)
+{
+ if (info->arch_sections_add_fn) {
+ info->arch_sections_add_fn(opaque);
+ }
+}
+
+static inline uint64_t dump_arch_sections_write_hdr(ArchDumpInfo *info,
+ void *opaque, uint8_t *buff)
+{
+ if (info->arch_sections_write_hdr_fn) {
+ return info->arch_sections_write_hdr_fn(opaque, buff);
+ }
+ return 0;
+}
+
+static inline void dump_arch_sections_write(ArchDumpInfo *info, void *opaque,
+ uint8_t *buff)
+{
+ if (info->arch_sections_write_fn) {
+ info->arch_sections_write_fn(opaque, buff);
+ }
+}
+
#endif
--
2.32.0
^ permalink raw reply related [flat|nested] 10+ messages in thread