Message ID | 20220721132256.2171-5-frankja@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | dump: Add arch section and s390x PV dump | expand |
On Thu, Jul 21, 2022 at 5:23 PM Janosch Frank <frankja@linux.ibm.com> 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> you could have added from v2 Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> > --- > dump/dump.c | 127 +++++++++++++++++++++--------------------- > include/sysemu/dump.h | 1 + > 2 files changed, 64 insertions(+), 64 deletions(-) > > diff --git a/dump/dump.c b/dump/dump.c > index 5c9ed25c5a..2d04e06815 100644 > --- a/dump/dump.c > +++ b/dump/dump.c > @@ -98,6 +98,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) { > @@ -126,73 +127,49 @@ 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) > { > - /* > - * phnum in the elf header is 16 bit, if we have more segments we > - * set phnum to PN_XNUM and write the real number of segments to a > - * special section. > - */ > - uint16_t phnum = MIN(s->phdr_num, PN_XNUM); > - Elf64_Ehdr elf_header; > - int ret; > + uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num; > + 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, phnum); > 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) > { > - /* > - * phnum in the elf header is 16 bit, if we have more segments we > - * set phnum to PN_XNUM and write the real number of segments to a > - * special section. > - */ > - uint16_t phnum = MIN(s->phdr_num, PN_XNUM); > - Elf32_Ehdr elf_header; > - int ret; > + uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num; > + 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, phnum); > 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); > } > } > > @@ -528,6 +505,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) > { > @@ -557,12 +554,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 file descriptor */ > + write_elf_header(s, errp); > if (*errp) { > return; > } > @@ -1642,6 +1638,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 7025e50682..58f41bbf45 100644 > --- a/include/sysemu/dump.h > +++ b/include/sysemu/dump.h > @@ -171,6 +171,7 @@ typedef struct DumpState { > int64_t begin; /* Start address of the chunk we want to dump */ > int64_t length; /* Length of the dump we want to dump */ > > + 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.34.1 >
diff --git a/dump/dump.c b/dump/dump.c index 5c9ed25c5a..2d04e06815 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -98,6 +98,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) { @@ -126,73 +127,49 @@ 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) { - /* - * phnum in the elf header is 16 bit, if we have more segments we - * set phnum to PN_XNUM and write the real number of segments to a - * special section. - */ - uint16_t phnum = MIN(s->phdr_num, PN_XNUM); - Elf64_Ehdr elf_header; - int ret; + uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num; + 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, phnum); 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) { - /* - * phnum in the elf header is 16 bit, if we have more segments we - * set phnum to PN_XNUM and write the real number of segments to a - * special section. - */ - uint16_t phnum = MIN(s->phdr_num, PN_XNUM); - Elf32_Ehdr elf_header; - int ret; + uint16_t phnum = s->phdr_num >= PN_XNUM ? PN_XNUM : s->phdr_num; + 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, phnum); 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); } } @@ -528,6 +505,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) { @@ -557,12 +554,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 file descriptor */ + write_elf_header(s, errp); if (*errp) { return; } @@ -1642,6 +1638,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 7025e50682..58f41bbf45 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -171,6 +171,7 @@ typedef struct DumpState { int64_t begin; /* Start address of the chunk we want to dump */ int64_t length; /* Length of the dump we want to dump */ + 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 */
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 | 127 +++++++++++++++++++++--------------------- include/sysemu/dump.h | 1 + 2 files changed, 64 insertions(+), 64 deletions(-)