From a2531bb855079597444f2ef1dcd4118d6609baf1 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Mar 2024 17:16:21 +0000 Subject: [PATCH 01/20] hw/arm: Deprecate various old Arm machine types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU includes some models of old Arm machine types which are a bit problematic for us because: * they're written in a very old way that uses numerous APIs that we would like to get away from (eg they don't use qdev, they use qemu_system_reset_request(), they use vmstate_register(), etc) * they've been that way for a decade plus and nobody particularly has stepped up to try to modernise the code (beyond some occasional work here and there) * we often don't have test cases for them, which means that if we do try to do the necessary refactoring work on them we have no idea if they even still work at all afterwards All these machine types are also of hardware that has largely passed away into history and where I would not be surprised to find that e.g. the Linux kernel support was never tested on real hardware any more. After some consultation with the Linux kernel developers, we are going to deprecate: All PXA2xx machines: akita Sharp SL-C1000 (Akita) PDA (PXA270) borzoi Sharp SL-C3100 (Borzoi) PDA (PXA270) connex Gumstix Connex (PXA255) mainstone Mainstone II (PXA27x) spitz Sharp SL-C3000 (Spitz) PDA (PXA270) terrier Sharp SL-C3200 (Terrier) PDA (PXA270) tosa Sharp SL-6000 (Tosa) PDA (PXA255) verdex Gumstix Verdex Pro XL6P COMs (PXA270) z2 Zipit Z2 (PXA27x) All OMAP2 machines: n800 Nokia N800 tablet aka. RX-34 (OMAP2420) n810 Nokia N810 tablet aka. RX-44 (OMAP2420) One of the OMAP1 machines: cheetah Palm Tungsten|E aka. Cheetah PDA (OMAP310) Rationale: * for QEMU dropping individual machines is much less beneficial than if we can drop support for an entire SoC * the OMAP2 QEMU code in particular is large, old and unmaintained, and none of the OMAP2 kernel maintainers said they were using QEMU in any of their testing/development * although there is a setup that is booting test kernels on some of the PXA2xx machines, nobody seemed to be using them as part of their active kernel development and my impression from the email thread is that PXA is the closest of all these SoC families to being dropped from the kernel soon * nobody said they were using cheetah, so it's entirely untested and quite probably broken * on the other hand the OMAP1 sx1 model does seem to be being used as part of kernel development, and there was interest in keeping collie around In particular, the mainstone, tosa and z2 machine types have already been dropped from Linux. Mark all these machine types as deprecated. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240308171621.3749894-1-peter.maydell@linaro.org --- docs/about/deprecated.rst | 15 +++++++++++++++ hw/arm/gumstix.c | 2 ++ hw/arm/mainstone.c | 1 + hw/arm/nseries.c | 2 ++ hw/arm/palm.c | 1 + hw/arm/spitz.c | 1 + hw/arm/tosa.c | 1 + hw/arm/z2.c | 1 + 8 files changed, 24 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index dfd681cd02..0d074d1b29 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -245,6 +245,21 @@ to correct issues, mostly regarding migration compatibility. These are no longer maintained and removing them will make the code easier to read and maintain. Use versions 2.12 and above as a replacement. +Arm machines ``akita``, ``borzoi``, ``cheetah``, ``connex``, ``mainstone``, ``n800``, ``n810``, ``spitz``, ``terrier``, ``tosa``, ``verdex``, ``z2`` (since 9.0) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +QEMU includes models of some machine types where the QEMU code that +emulates their SoCs is very old and unmaintained. This code is now +blocking our ability to move forward with various changes across +the codebase, and over many years nobody has been interested in +trying to modernise it. We don't expect any of these machines to have +a large number of users, because they're all modelling hardware that +has now passed away into history. We are therefore dropping support +for all machine types using the PXA2xx and OMAP2 SoCs. We are also +dropping the ``cheetah`` OMAP1 board, because we don't have any +test images for it and don't know of anybody who does; the ``sx1`` +and ``sx1-v1`` OMAP1 machines remain supported for now. + Backend options --------------- diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c index d5de5409e1..9146269153 100644 --- a/hw/arm/gumstix.c +++ b/hw/arm/gumstix.c @@ -106,6 +106,7 @@ static void connex_class_init(ObjectClass *oc, void *data) mc->desc = "Gumstix Connex (PXA255)"; mc->init = connex_init; mc->ignore_memory_transaction_failures = true; + mc->deprecation_reason = "machine is old and unmaintained"; } static const TypeInfo connex_type = { @@ -121,6 +122,7 @@ static void verdex_class_init(ObjectClass *oc, void *data) mc->desc = "Gumstix Verdex Pro XL6P COMs (PXA270)"; mc->init = verdex_init; mc->ignore_memory_transaction_failures = true; + mc->deprecation_reason = "machine is old and unmaintained"; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0"); } diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c index d2e2e68aa3..3a6c22fddb 100644 --- a/hw/arm/mainstone.c +++ b/hw/arm/mainstone.c @@ -169,6 +169,7 @@ static void mainstone2_machine_init(MachineClass *mc) mc->init = mainstone_init; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c5"); + mc->deprecation_reason = "machine is old and unmaintained"; } DEFINE_MACHINE("mainstone", mainstone2_machine_init) diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 35deb74f65..35364312c7 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -1430,6 +1430,7 @@ static void n800_class_init(ObjectClass *oc, void *data) /* Actually two chips of 0x4000000 bytes each */ mc->default_ram_size = 0x08000000; mc->default_ram_id = "omap2.dram"; + mc->deprecation_reason = "machine is old and unmaintained"; machine_add_audiodev_property(mc); } @@ -1452,6 +1453,7 @@ static void n810_class_init(ObjectClass *oc, void *data) /* Actually two chips of 0x4000000 bytes each */ mc->default_ram_size = 0x08000000; mc->default_ram_id = "omap2.dram"; + mc->deprecation_reason = "machine is old and unmaintained"; machine_add_audiodev_property(mc); } diff --git a/hw/arm/palm.c b/hw/arm/palm.c index 8c4c831614..e04ac92eb7 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -309,6 +309,7 @@ static void palmte_machine_init(MachineClass *mc) mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t"); mc->default_ram_size = 0x02000000; mc->default_ram_id = "omap1.dram"; + mc->deprecation_reason = "machine is old and unmaintained"; machine_add_audiodev_property(mc); } diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 643a02b180..62cd55ba91 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -1041,6 +1041,7 @@ static void spitz_common_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_IDE; mc->ignore_memory_transaction_failures = true; mc->init = spitz_common_init; + mc->deprecation_reason = "machine is old and unmaintained"; machine_add_audiodev_property(mc); } diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 3ca2e4459c..5891f6064f 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -270,6 +270,7 @@ static void tosapda_machine_init(MachineClass *mc) mc->init = tosa_init; mc->block_default_type = IF_IDE; mc->ignore_memory_transaction_failures = true; + mc->deprecation_reason = "machine is old and unmaintained"; } DEFINE_MACHINE("tosa", tosapda_machine_init) diff --git a/hw/arm/z2.c b/hw/arm/z2.c index eb2ff8dbc8..fc5672e7ab 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -347,6 +347,7 @@ static void z2_machine_init(MachineClass *mc) mc->init = z2_init; mc->ignore_memory_transaction_failures = true; mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c5"); + mc->deprecation_reason = "machine is old and unmaintained"; machine_add_audiodev_property(mc); } From b48139d0d90e9a551f630760fa57732cfeee759f Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:44 +0900 Subject: [PATCH 02/20] contrib/elf2dmp: Remove unnecessary err flags They are always evaluated to 1. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-1-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/pdb.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c index 40991f5f4c..abf17c2e7c 100644 --- a/contrib/elf2dmp/pdb.c +++ b/contrib/elf2dmp/pdb.c @@ -177,7 +177,6 @@ static int pdb_init_segments(struct pdb_reader *r) static int pdb_init_symbols(struct pdb_reader *r) { - int err = 0; PDB_SYMBOLS *symbols; symbols = pdb_ds_read_file(r, 3); @@ -196,7 +195,6 @@ static int pdb_init_symbols(struct pdb_reader *r) /* Read global symbol table */ r->modimage = pdb_ds_read_file(r, symbols->gsym_file); if (!r->modimage) { - err = 1; goto out_symbols; } @@ -205,7 +203,7 @@ static int pdb_init_symbols(struct pdb_reader *r) out_symbols: g_free(symbols); - return err; + return 1; } static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr) @@ -228,7 +226,6 @@ static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr) static int pdb_reader_init(struct pdb_reader *r, void *data) { - int err = 0; const char pdb7[] = "Microsoft C/C++ MSF 7.00"; if (memcmp(data, pdb7, sizeof(pdb7) - 1)) { @@ -241,17 +238,14 @@ static int pdb_reader_init(struct pdb_reader *r, void *data) r->ds.root = pdb_ds_read_file(r, 1); if (!r->ds.root) { - err = 1; goto out_ds; } if (pdb_init_symbols(r)) { - err = 1; goto out_root; } if (pdb_init_segments(r)) { - err = 1; goto out_sym; } @@ -264,7 +258,7 @@ out_root: out_ds: pdb_reader_ds_exit(r); - return err; + return 1; } static void pdb_reader_exit(struct pdb_reader *r) @@ -278,7 +272,6 @@ static void pdb_reader_exit(struct pdb_reader *r) int pdb_init_from_file(const char *name, struct pdb_reader *reader) { GError *gerr = NULL; - int err = 0; void *map; reader->gmf = g_mapped_file_new(name, TRUE, &gerr); @@ -291,7 +284,6 @@ int pdb_init_from_file(const char *name, struct pdb_reader *reader) reader->file_size = g_mapped_file_get_length(reader->gmf); map = g_mapped_file_get_contents(reader->gmf); if (pdb_reader_init(reader, map)) { - err = 1; goto out_unmap; } @@ -300,7 +292,7 @@ int pdb_init_from_file(const char *name, struct pdb_reader *reader) out_unmap: g_mapped_file_unref(reader->gmf); - return err; + return 1; } void pdb_exit(struct pdb_reader *reader) From a4e58de14678503fd773e7920359028de77711f9 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:45 +0900 Subject: [PATCH 03/20] contrib/elf2dmp: Assume error by default A common construct in contrib/elf2dmp is to set "err" flag and goto in error paths. In such a construct, there is only one successful path while there are several error paths, so it will be more simpler to initialize "err" flag set, and clear it in the successful path. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-2-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/download.c | 4 +--- contrib/elf2dmp/main.c | 15 +++------------ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c index bd7650a7a2..902dc04ffa 100644 --- a/contrib/elf2dmp/download.c +++ b/contrib/elf2dmp/download.c @@ -11,7 +11,7 @@ int download_url(const char *name, const char *url) { - int err = 0; + int err = 1; FILE *file; CURL *curl = curl_easy_init(); @@ -21,7 +21,6 @@ int download_url(const char *name, const char *url) file = fopen(name, "wb"); if (!file) { - err = 1; goto out_curl; } @@ -33,7 +32,6 @@ int download_url(const char *name, const char *url) || curl_easy_perform(curl) != CURLE_OK) { unlink(name); fclose(file); - err = 1; } else { err = fclose(file); } diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index cbc38a7c10..9b278f392e 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -511,7 +511,7 @@ static void pe_get_pdb_symstore_hash(OMFSignatureRSDS *rsds, char *hash) int main(int argc, char *argv[]) { - int err = 0; + int err = 1; QEMU_Elf qemu_elf; struct pa_space ps; struct va_space vs; @@ -542,7 +542,6 @@ int main(int argc, char *argv[]) if (pa_space_create(&ps, &qemu_elf)) { eprintf("Failed to initialize physical address space\n"); - err = 1; goto out_elf; } @@ -552,7 +551,6 @@ int main(int argc, char *argv[]) va_space_create(&vs, &ps, state->cr[3]); if (fix_dtb(&vs, &qemu_elf)) { eprintf("Failed to find paging base\n"); - err = 1; goto out_elf; } @@ -561,7 +559,6 @@ int main(int argc, char *argv[]) if (va_space_rw(&vs, state->idt.base, &first_idt_desc, sizeof(first_idt_desc), 0)) { eprintf("Failed to get CPU #0 IDT[0]\n"); - err = 1; goto out_ps; } printf("CPU #0 IDT[0] -> 0x%016"PRIx64"\n", idt_desc_addr(first_idt_desc)); @@ -586,7 +583,6 @@ int main(int argc, char *argv[]) if (!kernel_found) { eprintf("Failed to find NT kernel image\n"); - err = 1; goto out_ps; } @@ -600,45 +596,40 @@ int main(int argc, char *argv[]) if (download_url(PDB_NAME, pdb_url)) { eprintf("Failed to download PDB file\n"); - err = 1; goto out_ps; } if (pdb_init_from_file(PDB_NAME, &pdb)) { eprintf("Failed to initialize PDB reader\n"); - err = 1; goto out_pdb_file; } if (!SYM_RESOLVE(KernBase, &pdb, KdDebuggerDataBlock) || !SYM_RESOLVE(KernBase, &pdb, KdVersionBlock)) { - err = 1; goto out_pdb; } kdbg = get_kdbg(KernBase, &pdb, &vs, KdDebuggerDataBlock); if (!kdbg) { - err = 1; goto out_pdb; } if (fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg, KdVersionBlock, qemu_elf.state_nr)) { - err = 1; goto out_kdbg; } if (fill_context(kdbg, &vs, &qemu_elf)) { - err = 1; goto out_kdbg; } if (write_dump(&ps, &header, argv[2])) { eprintf("Failed to save dump\n"); - err = 1; goto out_kdbg; } + err = 0; + out_kdbg: g_free(kdbg); out_pdb: From 87157ef3508dbc84dd74ebf099f86828b652d854 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:46 +0900 Subject: [PATCH 04/20] contrib/elf2dmp: Continue even contexts are lacking Let fill_context() continue even if it fails to fill contexts of some CPUs. A dump may still contain valuable information even if it lacks contexts of some CPUs due to dump corruption or a failure before starting CPUs. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-3-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/main.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 9b278f392e..86e709e6da 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -336,8 +336,13 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, return 0; } -static int fill_context(KDDEBUGGER_DATA64 *kdbg, - struct va_space *vs, QEMU_Elf *qe) +/* + * fill_context() continues even if it fails to fill contexts of some CPUs. + * A dump may still contain valuable information even if it lacks contexts of + * some CPUs due to dump corruption or a failure before starting CPUs. + */ +static void fill_context(KDDEBUGGER_DATA64 *kdbg, + struct va_space *vs, QEMU_Elf *qe) { int i; @@ -350,7 +355,7 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg, if (va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i, &Prcb, sizeof(Prcb), 0)) { eprintf("Failed to read CPU #%d PRCB location\n", i); - return 1; + continue; } if (!Prcb) { @@ -361,7 +366,7 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg, if (va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext, &Context, sizeof(Context), 0)) { eprintf("Failed to read CPU #%d ContextFrame location\n", i); - return 1; + continue; } printf("Filling context for CPU #%d...\n", i); @@ -369,11 +374,9 @@ static int fill_context(KDDEBUGGER_DATA64 *kdbg, if (va_space_rw(vs, Context, &ctx, sizeof(ctx), 1)) { eprintf("Failed to fill CPU #%d context\n", i); - return 1; + continue; } } - - return 0; } static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx, @@ -619,9 +622,7 @@ int main(int argc, char *argv[]) goto out_kdbg; } - if (fill_context(kdbg, &vs, &qemu_elf)) { - goto out_kdbg; - } + fill_context(kdbg, &vs, &qemu_elf); if (write_dump(&ps, &header, argv[2])) { eprintf("Failed to save dump\n"); From 262a0ff88029e86b29434d4b2e7f710ae73b646c Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:47 +0900 Subject: [PATCH 05/20] contrib/elf2dmp: Change pa_space_create() signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pa_space_create() used to return an integer to propagate error, but it never fails so let it return void. Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240307-elf2dmp-v4-4-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/addrspace.c | 4 +--- contrib/elf2dmp/addrspace.h | 2 +- contrib/elf2dmp/main.c | 5 +---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c index 6f608a517b..4c127c9b1e 100644 --- a/contrib/elf2dmp/addrspace.c +++ b/contrib/elf2dmp/addrspace.c @@ -57,7 +57,7 @@ static void pa_block_align(struct pa_block *b) b->paddr += low_align; } -int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf) +void pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf) { Elf64_Half phdr_nr = elf_getphdrnum(qemu_elf->map); Elf64_Phdr *phdr = elf64_getphdr(qemu_elf->map); @@ -87,8 +87,6 @@ int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf) } ps->block_nr = block_i; - - return 0; } void pa_space_destroy(struct pa_space *ps) diff --git a/contrib/elf2dmp/addrspace.h b/contrib/elf2dmp/addrspace.h index 039c70c5b0..c868d64738 100644 --- a/contrib/elf2dmp/addrspace.h +++ b/contrib/elf2dmp/addrspace.h @@ -33,7 +33,7 @@ struct va_space { struct pa_space *ps; }; -int pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf); +void pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf); void pa_space_destroy(struct pa_space *ps); void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb); diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 86e709e6da..8a71e2efd2 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -543,10 +543,7 @@ int main(int argc, char *argv[]) return 1; } - if (pa_space_create(&ps, &qemu_elf)) { - eprintf("Failed to initialize physical address space\n"); - goto out_elf; - } + pa_space_create(&ps, &qemu_elf); state = qemu_elf.state[0]; printf("CPU #0 CR3 is 0x%016"PRIx64"\n", state->cr[3]); From a15f9749490e8d813b8929c69a7365e3edc6ab8c Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:48 +0900 Subject: [PATCH 06/20] contrib/elf2dmp: Fix error reporting style in addrspace.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit include/qapi/error.h says: > We recommend > * bool-valued functions return true on success / false on failure, > ... Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240307-elf2dmp-v4-5-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/addrspace.c | 8 +++---- contrib/elf2dmp/addrspace.h | 4 ++-- contrib/elf2dmp/main.c | 47 +++++++++++++++++-------------------- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c index 4c127c9b1e..c995c723ae 100644 --- a/contrib/elf2dmp/addrspace.c +++ b/contrib/elf2dmp/addrspace.c @@ -226,8 +226,8 @@ void *va_space_resolve(struct va_space *vs, uint64_t va) return pa_space_resolve(vs->ps, pa); } -int va_space_rw(struct va_space *vs, uint64_t addr, - void *buf, size_t size, int is_write) +bool va_space_rw(struct va_space *vs, uint64_t addr, + void *buf, size_t size, int is_write) { while (size) { uint64_t page = addr & ELF2DMP_PFN_MASK; @@ -238,7 +238,7 @@ int va_space_rw(struct va_space *vs, uint64_t addr, ptr = va_space_resolve(vs, addr); if (!ptr) { - return 1; + return false; } if (is_write) { @@ -252,5 +252,5 @@ int va_space_rw(struct va_space *vs, uint64_t addr, addr += s; } - return 0; + return true; } diff --git a/contrib/elf2dmp/addrspace.h b/contrib/elf2dmp/addrspace.h index c868d64738..2ad30a9da4 100644 --- a/contrib/elf2dmp/addrspace.h +++ b/contrib/elf2dmp/addrspace.h @@ -39,7 +39,7 @@ void pa_space_destroy(struct pa_space *ps); void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb); void va_space_set_dtb(struct va_space *vs, uint64_t dtb); void *va_space_resolve(struct va_space *vs, uint64_t va); -int va_space_rw(struct va_space *vs, uint64_t addr, - void *buf, size_t size, int is_write); +bool va_space_rw(struct va_space *vs, uint64_t addr, + void *buf, size_t size, int is_write); #endif /* ADDRSPACE_H */ diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 8a71e2efd2..09af39422f 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -79,9 +79,9 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb, bool decode = false; uint64_t kwn, kwa, KdpDataBlockEncoded; - if (va_space_rw(vs, - KdDebuggerDataBlock + offsetof(KDDEBUGGER_DATA64, Header), - &kdbg_hdr, sizeof(kdbg_hdr), 0)) { + if (!va_space_rw(vs, + KdDebuggerDataBlock + offsetof(KDDEBUGGER_DATA64, Header), + &kdbg_hdr, sizeof(kdbg_hdr), 0)) { eprintf("Failed to extract KDBG header\n"); return NULL; } @@ -97,8 +97,8 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb, return NULL; } - if (va_space_rw(vs, KiWaitNever, &kwn, sizeof(kwn), 0) || - va_space_rw(vs, KiWaitAlways, &kwa, sizeof(kwa), 0)) { + if (!va_space_rw(vs, KiWaitNever, &kwn, sizeof(kwn), 0) || + !va_space_rw(vs, KiWaitAlways, &kwa, sizeof(kwa), 0)) { return NULL; } @@ -122,7 +122,7 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb, kdbg = g_malloc(kdbg_hdr.Size); - if (va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) { + if (!va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) { eprintf("Failed to extract entire KDBG\n"); g_free(kdbg); return NULL; @@ -286,7 +286,7 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, return 1; } - if (va_space_rw(vs, KdVersionBlock, &kvb, sizeof(kvb), 0)) { + if (!va_space_rw(vs, KdVersionBlock, &kvb, sizeof(kvb), 0)) { eprintf("Failed to extract KdVersionBlock\n"); return 1; } @@ -352,8 +352,8 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg, WinContext64 ctx; QEMUCPUState *s = qe->state[i]; - if (va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i, - &Prcb, sizeof(Prcb), 0)) { + if (!va_space_rw(vs, kdbg->KiProcessorBlock + sizeof(Prcb) * i, + &Prcb, sizeof(Prcb), 0)) { eprintf("Failed to read CPU #%d PRCB location\n", i); continue; } @@ -363,8 +363,8 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg, continue; } - if (va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext, - &Context, sizeof(Context), 0)) { + if (!va_space_rw(vs, Prcb + kdbg->OffsetPrcbContext, + &Context, sizeof(Context), 0)) { eprintf("Failed to read CPU #%d ContextFrame location\n", i); continue; } @@ -372,7 +372,7 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg, printf("Filling context for CPU #%d...\n", i); win_context_init_from_qemu_cpu_state(&ctx, s); - if (va_space_rw(vs, Context, &ctx, sizeof(ctx), 1)) { + if (!va_space_rw(vs, Context, &ctx, sizeof(ctx), 1)) { eprintf("Failed to fill CPU #%d context\n", i); continue; } @@ -396,8 +396,8 @@ static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx, return 1; } - if (va_space_rw(vs, base + dos_hdr->e_lfanew, - &nt_hdrs, sizeof(nt_hdrs), 0)) { + if (!va_space_rw(vs, base + dos_hdr->e_lfanew, + &nt_hdrs, sizeof(nt_hdrs), 0)) { return 1; } @@ -406,9 +406,7 @@ static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx, return 1; } - if (va_space_rw(vs, - base + data_dir[idx].VirtualAddress, - entry, size, 0)) { + if (!va_space_rw(vs, base + data_dir[idx].VirtualAddress, entry, size, 0)) { return 1; } @@ -470,9 +468,8 @@ static bool pe_check_pdb_name(uint64_t base, void *start_addr, return false; } - if (va_space_rw(vs, - base + debug_dir.AddressOfRawData, - rsds, sizeof(*rsds), 0)) { + if (!va_space_rw(vs, base + debug_dir.AddressOfRawData, + rsds, sizeof(*rsds), 0)) { eprintf("Failed to resolve OMFSignatureRSDS\n"); return false; } @@ -488,9 +485,9 @@ static bool pe_check_pdb_name(uint64_t base, void *start_addr, return false; } - if (va_space_rw(vs, base + debug_dir.AddressOfRawData + - offsetof(OMFSignatureRSDS, name), pdb_name, sizeof(PDB_NAME), - 0)) { + if (!va_space_rw(vs, base + debug_dir.AddressOfRawData + + offsetof(OMFSignatureRSDS, name), + pdb_name, sizeof(PDB_NAME), 0)) { eprintf("Failed to resolve PDB name\n"); return false; } @@ -556,8 +553,8 @@ int main(int argc, char *argv[]) printf("CPU #0 IDT is at 0x%016"PRIx64"\n", state->idt.base); - if (va_space_rw(&vs, state->idt.base, - &first_idt_desc, sizeof(first_idt_desc), 0)) { + if (!va_space_rw(&vs, state->idt.base, + &first_idt_desc, sizeof(first_idt_desc), 0)) { eprintf("Failed to get CPU #0 IDT[0]\n"); goto out_ps; } From 1b806c36bc88a975cc10af219f1a397942f43e8d Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:49 +0900 Subject: [PATCH 07/20] contrib/elf2dmp: Fix error reporting style in download.c include/qapi/error.h says: > We recommend > * bool-valued functions return true on success / false on failure, > ... Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Peter Maydell Message-id: 20240307-elf2dmp-v4-6-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/download.c | 10 +++++----- contrib/elf2dmp/download.h | 2 +- contrib/elf2dmp/main.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contrib/elf2dmp/download.c b/contrib/elf2dmp/download.c index 902dc04ffa..21306b3fd4 100644 --- a/contrib/elf2dmp/download.c +++ b/contrib/elf2dmp/download.c @@ -9,14 +9,14 @@ #include #include "download.h" -int download_url(const char *name, const char *url) +bool download_url(const char *name, const char *url) { - int err = 1; + bool success = false; FILE *file; CURL *curl = curl_easy_init(); if (!curl) { - return 1; + return false; } file = fopen(name, "wb"); @@ -33,11 +33,11 @@ int download_url(const char *name, const char *url) unlink(name); fclose(file); } else { - err = fclose(file); + success = !fclose(file); } out_curl: curl_easy_cleanup(curl); - return err; + return success; } diff --git a/contrib/elf2dmp/download.h b/contrib/elf2dmp/download.h index 5c274925f7..f65adb5d08 100644 --- a/contrib/elf2dmp/download.h +++ b/contrib/elf2dmp/download.h @@ -8,6 +8,6 @@ #ifndef DOWNLOAD_H #define DOWNLOAD_H -int download_url(const char *name, const char *url); +bool download_url(const char *name, const char *url); #endif /* DOWNLOAD_H */ diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 09af39422f..d295fd92be 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -591,7 +591,7 @@ int main(int argc, char *argv[]) sprintf(pdb_url, "%s%s/%s/%s", SYM_URL_BASE, PDB_NAME, pdb_hash, PDB_NAME); printf("PDB URL is %s\n", pdb_url); - if (download_url(PDB_NAME, pdb_url)) { + if (!download_url(PDB_NAME, pdb_url)) { eprintf("Failed to download PDB file\n"); goto out_ps; } From b1250455c71193ad92cb7c98ee54078ce33e0b04 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:50 +0900 Subject: [PATCH 08/20] contrib/elf2dmp: Fix error reporting style in pdb.c include/qapi/error.h says: > We recommend > * bool-valued functions return true on success / false on failure, > ... Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Peter Maydell Message-id: 20240307-elf2dmp-v4-7-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/main.c | 2 +- contrib/elf2dmp/pdb.c | 50 +++++++++++++++++++++--------------------- contrib/elf2dmp/pdb.h | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index d295fd92be..7a3a722590 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -596,7 +596,7 @@ int main(int argc, char *argv[]) goto out_ps; } - if (pdb_init_from_file(PDB_NAME, &pdb)) { + if (!pdb_init_from_file(PDB_NAME, &pdb)) { eprintf("Failed to initialize PDB reader\n"); goto out_pdb_file; } diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c index abf17c2e7c..1c50514251 100644 --- a/contrib/elf2dmp/pdb.c +++ b/contrib/elf2dmp/pdb.c @@ -158,30 +158,30 @@ static void *pdb_ds_read_file(struct pdb_reader* r, uint32_t file_number) return pdb_ds_read(r->ds.header, block_list, file_size[file_number]); } -static int pdb_init_segments(struct pdb_reader *r) +static bool pdb_init_segments(struct pdb_reader *r) { unsigned stream_idx = r->segments; r->segs = pdb_ds_read_file(r, stream_idx); if (!r->segs) { - return 1; + return false; } r->segs_size = pdb_get_file_size(r, stream_idx); if (!r->segs_size) { - return 1; + return false; } - return 0; + return true; } -static int pdb_init_symbols(struct pdb_reader *r) +static bool pdb_init_symbols(struct pdb_reader *r) { PDB_SYMBOLS *symbols; symbols = pdb_ds_read_file(r, 3); if (!symbols) { - return 1; + return false; } r->symbols = symbols; @@ -198,18 +198,18 @@ static int pdb_init_symbols(struct pdb_reader *r) goto out_symbols; } - return 0; + return true; out_symbols: g_free(symbols); - return 1; + return false; } -static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr) +static bool pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr) { if (hdr->block_size == 0) { - return 1; + return false; } memset(r->file_used, 0, sizeof(r->file_used)); @@ -218,22 +218,22 @@ static int pdb_reader_ds_init(struct pdb_reader *r, PDB_DS_HEADER *hdr) hdr->toc_page * hdr->block_size), hdr->toc_size); if (!r->ds.toc) { - return 1; + return false; } - return 0; + return true; } -static int pdb_reader_init(struct pdb_reader *r, void *data) +static bool pdb_reader_init(struct pdb_reader *r, void *data) { const char pdb7[] = "Microsoft C/C++ MSF 7.00"; if (memcmp(data, pdb7, sizeof(pdb7) - 1)) { - return 1; + return false; } - if (pdb_reader_ds_init(r, data)) { - return 1; + if (!pdb_reader_ds_init(r, data)) { + return false; } r->ds.root = pdb_ds_read_file(r, 1); @@ -241,15 +241,15 @@ static int pdb_reader_init(struct pdb_reader *r, void *data) goto out_ds; } - if (pdb_init_symbols(r)) { + if (!pdb_init_symbols(r)) { goto out_root; } - if (pdb_init_segments(r)) { + if (!pdb_init_segments(r)) { goto out_sym; } - return 0; + return true; out_sym: pdb_exit_symbols(r); @@ -258,7 +258,7 @@ out_root: out_ds: pdb_reader_ds_exit(r); - return 1; + return false; } static void pdb_reader_exit(struct pdb_reader *r) @@ -269,7 +269,7 @@ static void pdb_reader_exit(struct pdb_reader *r) pdb_reader_ds_exit(r); } -int pdb_init_from_file(const char *name, struct pdb_reader *reader) +bool pdb_init_from_file(const char *name, struct pdb_reader *reader) { GError *gerr = NULL; void *map; @@ -278,21 +278,21 @@ int pdb_init_from_file(const char *name, struct pdb_reader *reader) if (gerr) { eprintf("Failed to map PDB file \'%s\'\n", name); g_error_free(gerr); - return 1; + return false; } reader->file_size = g_mapped_file_get_length(reader->gmf); map = g_mapped_file_get_contents(reader->gmf); - if (pdb_reader_init(reader, map)) { + if (!pdb_reader_init(reader, map)) { goto out_unmap; } - return 0; + return true; out_unmap: g_mapped_file_unref(reader->gmf); - return 1; + return false; } void pdb_exit(struct pdb_reader *reader) diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h index 2a50da56ac..feddf1862f 100644 --- a/contrib/elf2dmp/pdb.h +++ b/contrib/elf2dmp/pdb.h @@ -233,7 +233,7 @@ struct pdb_reader { size_t segs_size; }; -int pdb_init_from_file(const char *name, struct pdb_reader *reader); +bool pdb_init_from_file(const char *name, struct pdb_reader *reader); void pdb_exit(struct pdb_reader *reader); uint64_t pdb_resolve(uint64_t img_base, struct pdb_reader *r, const char *name); uint64_t pdb_find_public_v3_symbol(struct pdb_reader *reader, const char *name); From 49760ccf862ff6cd0b18dd5897a60f8d708a6e52 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:51 +0900 Subject: [PATCH 09/20] contrib/elf2dmp: Fix error reporting style in qemu_elf.c include/qapi/error.h says: > We recommend > * bool-valued functions return true on success / false on failure, > ... Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Peter Maydell Message-id: 20240307-elf2dmp-v4-8-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/main.c | 2 +- contrib/elf2dmp/qemu_elf.c | 32 ++++++++++++++++---------------- contrib/elf2dmp/qemu_elf.h | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 7a3a722590..cb28971789 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -535,7 +535,7 @@ int main(int argc, char *argv[]) return 1; } - if (QEMU_Elf_init(&qemu_elf, argv[1])) { + if (!QEMU_Elf_init(&qemu_elf, argv[1])) { eprintf("Failed to initialize QEMU ELF dump\n"); return 1; } diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c index 055e6f8792..a22c057d3e 100644 --- a/contrib/elf2dmp/qemu_elf.c +++ b/contrib/elf2dmp/qemu_elf.c @@ -60,7 +60,7 @@ Elf64_Half elf_getphdrnum(void *map) return ehdr->e_phnum; } -static int init_states(QEMU_Elf *qe) +static bool init_states(QEMU_Elf *qe) { Elf64_Phdr *phdr = elf64_getphdr(qe->map); Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset); @@ -70,7 +70,7 @@ static int init_states(QEMU_Elf *qe) if (phdr[0].p_type != PT_NOTE) { eprintf("Failed to find PT_NOTE\n"); - return 1; + return false; } qe->has_kernel_gs_base = 1; @@ -107,7 +107,7 @@ static int init_states(QEMU_Elf *qe) qe->state_nr = cpu_nr; - return 0; + return true; } static void exit_states(QEMU_Elf *qe) @@ -162,7 +162,7 @@ static bool check_ehdr(QEMU_Elf *qe) return true; } -static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename) +static bool QEMU_Elf_map(QEMU_Elf *qe, const char *filename) { #ifdef CONFIG_LINUX struct stat st; @@ -173,13 +173,13 @@ static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename) fd = open(filename, O_RDONLY, 0); if (fd == -1) { eprintf("Failed to open ELF dump file \'%s\'\n", filename); - return 1; + return false; } if (fstat(fd, &st)) { eprintf("Failed to get size of ELF dump file\n"); close(fd); - return 1; + return false; } qe->size = st.st_size; @@ -188,7 +188,7 @@ static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename) if (qe->map == MAP_FAILED) { eprintf("Failed to map ELF file\n"); close(fd); - return 1; + return false; } close(fd); @@ -201,14 +201,14 @@ static int QEMU_Elf_map(QEMU_Elf *qe, const char *filename) if (gerr) { eprintf("Failed to map ELF dump file \'%s\'\n", filename); g_error_free(gerr); - return 1; + return false; } qe->map = g_mapped_file_get_contents(qe->gmf); qe->size = g_mapped_file_get_length(qe->gmf); #endif - return 0; + return true; } static void QEMU_Elf_unmap(QEMU_Elf *qe) @@ -220,25 +220,25 @@ static void QEMU_Elf_unmap(QEMU_Elf *qe) #endif } -int QEMU_Elf_init(QEMU_Elf *qe, const char *filename) +bool QEMU_Elf_init(QEMU_Elf *qe, const char *filename) { - if (QEMU_Elf_map(qe, filename)) { - return 1; + if (!QEMU_Elf_map(qe, filename)) { + return false; } if (!check_ehdr(qe)) { eprintf("Input file has the wrong format\n"); QEMU_Elf_unmap(qe); - return 1; + return false; } - if (init_states(qe)) { + if (!init_states(qe)) { eprintf("Failed to extract QEMU CPU states\n"); QEMU_Elf_unmap(qe); - return 1; + return false; } - return 0; + return true; } void QEMU_Elf_exit(QEMU_Elf *qe) diff --git a/contrib/elf2dmp/qemu_elf.h b/contrib/elf2dmp/qemu_elf.h index afa75f10b2..adc50238b4 100644 --- a/contrib/elf2dmp/qemu_elf.h +++ b/contrib/elf2dmp/qemu_elf.h @@ -42,7 +42,7 @@ typedef struct QEMU_Elf { int has_kernel_gs_base; } QEMU_Elf; -int QEMU_Elf_init(QEMU_Elf *qe, const char *filename); +bool QEMU_Elf_init(QEMU_Elf *qe, const char *filename); void QEMU_Elf_exit(QEMU_Elf *qe); Elf64_Phdr *elf64_getphdr(void *map); From fbc3d7d2f1d638f2c68a2af343be882717a9eed8 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:52 +0900 Subject: [PATCH 10/20] contrib/elf2dmp: Fix error reporting style in main.c include/qapi/error.h says: > We recommend > * bool-valued functions return true on success / false on failure, > ... Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Peter Maydell Message-id: 20240307-elf2dmp-v4-9-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/main.c | 63 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index cb28971789..9347b0cd5a 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -186,13 +186,13 @@ static void win_context_init_from_qemu_cpu_state(WinContext64 *ctx, * Finds paging-structure hierarchy base, * if previously set doesn't give access to kernel structures */ -static int fix_dtb(struct va_space *vs, QEMU_Elf *qe) +static bool fix_dtb(struct va_space *vs, QEMU_Elf *qe) { /* * Firstly, test previously set DTB. */ if (va_space_resolve(vs, SharedUserData)) { - return 0; + return true; } /* @@ -206,7 +206,7 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe) va_space_set_dtb(vs, s->cr[3]); printf("DTB 0x%016"PRIx64" has been found from CPU #%zu" " as system task CR3\n", vs->dtb, i); - return !(va_space_resolve(vs, SharedUserData)); + return va_space_resolve(vs, SharedUserData); } } @@ -220,16 +220,16 @@ static int fix_dtb(struct va_space *vs, QEMU_Elf *qe) uint64_t *cr3 = va_space_resolve(vs, Prcb + 0x7000); if (!cr3) { - return 1; + return false; } va_space_set_dtb(vs, *cr3); printf("DirectoryTableBase = 0x%016"PRIx64" has been found from CPU #0" " as interrupt handling CR3\n", vs->dtb); - return !(va_space_resolve(vs, SharedUserData)); + return va_space_resolve(vs, SharedUserData); } - return 1; + return true; } static void try_merge_runs(struct pa_space *ps, @@ -268,9 +268,10 @@ static void try_merge_runs(struct pa_space *ps, } } -static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, - struct va_space *vs, uint64_t KdDebuggerDataBlock, - KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock, int nr_cpus) +static bool fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, + struct va_space *vs, uint64_t KdDebuggerDataBlock, + KDDEBUGGER_DATA64 *kdbg, uint64_t KdVersionBlock, + int nr_cpus) { uint32_t *suite_mask = va_space_resolve(vs, SharedUserData + KUSD_OFFSET_SUITE_MASK); @@ -283,12 +284,12 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, QEMU_BUILD_BUG_ON(KUSD_OFFSET_PRODUCT_TYPE >= ELF2DMP_PAGE_SIZE); if (!suite_mask || !product_type) { - return 1; + return false; } if (!va_space_rw(vs, KdVersionBlock, &kvb, sizeof(kvb), 0)) { eprintf("Failed to extract KdVersionBlock\n"); - return 1; + return false; } h = (WinDumpHeader64) { @@ -333,7 +334,7 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, *hdr = h; - return 0; + return true; } /* @@ -379,8 +380,8 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg, } } -static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx, - void *entry, size_t size, struct va_space *vs) +static bool pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx, + void *entry, size_t size, struct va_space *vs) { const char e_magic[2] = "MZ"; const char Signature[4] = "PE\0\0"; @@ -393,38 +394,38 @@ static int pe_get_data_dir_entry(uint64_t base, void *start_addr, int idx, QEMU_BUILD_BUG_ON(sizeof(*dos_hdr) >= ELF2DMP_PAGE_SIZE); if (memcmp(&dos_hdr->e_magic, e_magic, sizeof(e_magic))) { - return 1; + return false; } if (!va_space_rw(vs, base + dos_hdr->e_lfanew, &nt_hdrs, sizeof(nt_hdrs), 0)) { - return 1; + return false; } if (memcmp(&nt_hdrs.Signature, Signature, sizeof(Signature)) || file_hdr->Machine != 0x8664 || opt_hdr->Magic != 0x020b) { - return 1; + return false; } if (!va_space_rw(vs, base + data_dir[idx].VirtualAddress, entry, size, 0)) { - return 1; + return false; } printf("Data directory entry #%d: RVA = 0x%08"PRIx32"\n", idx, (uint32_t)data_dir[idx].VirtualAddress); - return 0; + return true; } -static int write_dump(struct pa_space *ps, - WinDumpHeader64 *hdr, const char *name) +static bool write_dump(struct pa_space *ps, + WinDumpHeader64 *hdr, const char *name) { FILE *dmp_file = fopen(name, "wb"); size_t i; if (!dmp_file) { eprintf("Failed to open output file \'%s\'\n", name); - return 1; + return false; } printf("Writing header to file...\n"); @@ -432,7 +433,7 @@ static int write_dump(struct pa_space *ps, if (fwrite(hdr, sizeof(*hdr), 1, dmp_file) != 1) { eprintf("Failed to write dump header\n"); fclose(dmp_file); - return 1; + return false; } for (i = 0; i < ps->block_nr; i++) { @@ -443,11 +444,11 @@ static int write_dump(struct pa_space *ps, if (fwrite(b->addr, b->size, 1, dmp_file) != 1) { eprintf("Failed to write block\n"); fclose(dmp_file); - return 1; + return false; } } - return fclose(dmp_file); + return !fclose(dmp_file); } static bool pe_check_pdb_name(uint64_t base, void *start_addr, @@ -457,8 +458,8 @@ static bool pe_check_pdb_name(uint64_t base, void *start_addr, IMAGE_DEBUG_DIRECTORY debug_dir; char pdb_name[sizeof(PDB_NAME)]; - if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_DEBUG_DIRECTORY, - &debug_dir, sizeof(debug_dir), vs)) { + if (!pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_DEBUG_DIRECTORY, + &debug_dir, sizeof(debug_dir), vs)) { eprintf("Failed to get Debug Directory\n"); return false; } @@ -546,7 +547,7 @@ int main(int argc, char *argv[]) printf("CPU #0 CR3 is 0x%016"PRIx64"\n", state->cr[3]); va_space_create(&vs, &ps, state->cr[3]); - if (fix_dtb(&vs, &qemu_elf)) { + if (!fix_dtb(&vs, &qemu_elf)) { eprintf("Failed to find paging base\n"); goto out_elf; } @@ -611,14 +612,14 @@ int main(int argc, char *argv[]) goto out_pdb; } - if (fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg, - KdVersionBlock, qemu_elf.state_nr)) { + if (!fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg, + KdVersionBlock, qemu_elf.state_nr)) { goto out_kdbg; } fill_context(kdbg, &vs, &qemu_elf); - if (write_dump(&ps, &header, argv[2])) { + if (!write_dump(&ps, &header, argv[2])) { eprintf("Failed to save dump\n"); goto out_kdbg; } From a6a62ef5751371a82a9fb3ce67190d38a7f465fb Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:53 +0900 Subject: [PATCH 11/20] contrib/elf2dmp: Always check for PA resolution failure Not checking PA resolution failure can result in NULL deference. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-10-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/addrspace.c | 46 +++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c index c995c723ae..e01860d15b 100644 --- a/contrib/elf2dmp/addrspace.c +++ b/contrib/elf2dmp/addrspace.c @@ -22,7 +22,7 @@ static struct pa_block *pa_space_find_block(struct pa_space *ps, uint64_t pa) return NULL; } -static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa) +static void *pa_space_resolve(struct pa_space *ps, uint64_t pa) { struct pa_block *block = pa_space_find_block(ps, pa); @@ -33,6 +33,19 @@ static uint8_t *pa_space_resolve(struct pa_space *ps, uint64_t pa) return block->addr + (pa - block->paddr); } +static bool pa_space_read64(struct pa_space *ps, uint64_t pa, uint64_t *value) +{ + uint64_t *resolved = pa_space_resolve(ps, pa); + + if (!resolved) { + return false; + } + + *value = *resolved; + + return true; +} + static void pa_block_align(struct pa_block *b) { uint64_t low_align = ((b->paddr - 1) | ELF2DMP_PAGE_MASK) + 1 - b->paddr; @@ -106,19 +119,20 @@ void va_space_create(struct va_space *vs, struct pa_space *ps, uint64_t dtb) va_space_set_dtb(vs, dtb); } -static uint64_t get_pml4e(struct va_space *vs, uint64_t va) +static bool get_pml4e(struct va_space *vs, uint64_t va, uint64_t *value) { uint64_t pa = (vs->dtb & 0xffffffffff000) | ((va & 0xff8000000000) >> 36); - return *(uint64_t *)pa_space_resolve(vs->ps, pa); + return pa_space_read64(vs->ps, pa, value); } -static uint64_t get_pdpi(struct va_space *vs, uint64_t va, uint64_t pml4e) +static bool get_pdpi(struct va_space *vs, uint64_t va, uint64_t pml4e, + uint64_t *value) { uint64_t pdpte_paddr = (pml4e & 0xffffffffff000) | ((va & 0x7FC0000000) >> 27); - return *(uint64_t *)pa_space_resolve(vs->ps, pdpte_paddr); + return pa_space_read64(vs->ps, pdpte_paddr, value); } static uint64_t pde_index(uint64_t va) @@ -131,11 +145,12 @@ static uint64_t pdba_base(uint64_t pdpe) return pdpe & 0xFFFFFFFFFF000; } -static uint64_t get_pgd(struct va_space *vs, uint64_t va, uint64_t pdpe) +static bool get_pgd(struct va_space *vs, uint64_t va, uint64_t pdpe, + uint64_t *value) { uint64_t pgd_entry = pdba_base(pdpe) + pde_index(va) * 8; - return *(uint64_t *)pa_space_resolve(vs->ps, pgd_entry); + return pa_space_read64(vs->ps, pgd_entry, value); } static uint64_t pte_index(uint64_t va) @@ -148,11 +163,12 @@ static uint64_t ptba_base(uint64_t pde) return pde & 0xFFFFFFFFFF000; } -static uint64_t get_pte(struct va_space *vs, uint64_t va, uint64_t pgd) +static bool get_pte(struct va_space *vs, uint64_t va, uint64_t pgd, + uint64_t *value) { uint64_t pgd_val = ptba_base(pgd) + pte_index(va) * 8; - return *(uint64_t *)pa_space_resolve(vs->ps, pgd_val); + return pa_space_read64(vs->ps, pgd_val, value); } static uint64_t get_paddr(uint64_t va, uint64_t pte) @@ -184,13 +200,11 @@ static uint64_t va_space_va2pa(struct va_space *vs, uint64_t va) { uint64_t pml4e, pdpe, pgd, pte; - pml4e = get_pml4e(vs, va); - if (!is_present(pml4e)) { + if (!get_pml4e(vs, va, &pml4e) || !is_present(pml4e)) { return INVALID_PA; } - pdpe = get_pdpi(vs, va, pml4e); - if (!is_present(pdpe)) { + if (!get_pdpi(vs, va, pml4e, &pdpe) || !is_present(pdpe)) { return INVALID_PA; } @@ -198,8 +212,7 @@ static uint64_t va_space_va2pa(struct va_space *vs, uint64_t va) return get_1GB_paddr(va, pdpe); } - pgd = get_pgd(vs, va, pdpe); - if (!is_present(pgd)) { + if (!get_pgd(vs, va, pdpe, &pgd) || !is_present(pgd)) { return INVALID_PA; } @@ -207,8 +220,7 @@ static uint64_t va_space_va2pa(struct va_space *vs, uint64_t va) return get_2MB_paddr(va, pgd); } - pte = get_pte(vs, va, pgd); - if (!is_present(pte)) { + if (!get_pte(vs, va, pgd, &pte) || !is_present(pte)) { return INVALID_PA; } From 2aa205f7c6339cb46d26473a0434a292fc3d32cf Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:54 +0900 Subject: [PATCH 12/20] contrib/elf2dmp: Always destroy PA space Destroy PA space even if paging base couldn't be found, fixing memory leak. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-11-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 9347b0cd5a..32dc8bac6a 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -549,7 +549,7 @@ int main(int argc, char *argv[]) va_space_create(&vs, &ps, state->cr[3]); if (!fix_dtb(&vs, &qemu_elf)) { eprintf("Failed to find paging base\n"); - goto out_elf; + goto out_ps; } printf("CPU #0 IDT is at 0x%016"PRIx64"\n", state->idt.base); @@ -634,7 +634,6 @@ out_pdb_file: unlink(PDB_NAME); out_ps: pa_space_destroy(&ps); -out_elf: QEMU_Elf_exit(&qemu_elf); return err; From 667909478b09f9f16b03b7e7b11f3c42e7bdcdf3 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:55 +0900 Subject: [PATCH 13/20] contrib/elf2dmp: Ensure segment fits in file This makes elf2dmp more robust against corrupted inputs. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-12-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/addrspace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c index e01860d15b..81295a1153 100644 --- a/contrib/elf2dmp/addrspace.c +++ b/contrib/elf2dmp/addrspace.c @@ -88,11 +88,12 @@ void pa_space_create(struct pa_space *ps, QEMU_Elf *qemu_elf) ps->block = g_new(struct pa_block, ps->block_nr); for (i = 0; i < phdr_nr; i++) { - if (phdr[i].p_type == PT_LOAD) { + if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset < qemu_elf->size) { ps->block[block_i] = (struct pa_block) { .addr = (uint8_t *)qemu_elf->map + phdr[i].p_offset, .paddr = phdr[i].p_paddr, - .size = phdr[i].p_filesz, + .size = MIN(phdr[i].p_filesz, + qemu_elf->size - phdr[i].p_offset), }; pa_block_align(&ps->block[block_i]); block_i = ps->block[block_i].size ? (block_i + 1) : block_i; From 2aa501af351c25f91c56f3c9fd023df4bbea3f3c Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:56 +0900 Subject: [PATCH 14/20] contrib/elf2dmp: Use lduw_le_p() to read PDB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The relevant value may be unaligned and is little-endian. Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240307-elf2dmp-v4-13-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/pdb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c index 1c50514251..492aca4434 100644 --- a/contrib/elf2dmp/pdb.c +++ b/contrib/elf2dmp/pdb.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bswap.h" #include "pdb.h" #include "err.h" @@ -186,7 +187,7 @@ static bool pdb_init_symbols(struct pdb_reader *r) r->symbols = symbols; - r->segments = *(uint16_t *)((const char *)symbols + sizeof(PDB_SYMBOLS) + + r->segments = lduw_le_p((const char *)symbols + sizeof(PDB_SYMBOLS) + symbols->module_size + symbols->offset_size + symbols->hash_size + symbols->srcmodule_size + symbols->pdbimport_size + symbols->unknown2_size + From f024f5031ee570d952d3e93c4bb00ee111eb9dc6 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:57 +0900 Subject: [PATCH 15/20] contrib/elf2dmp: Use rol64() to decode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rol64() is roubust against too large shift values and fixes UBSan warnings. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240307-elf2dmp-v4-14-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/main.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index 32dc8bac6a..d046a72ae6 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -6,6 +6,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bitops.h" #include "err.h" #include "addrspace.h" @@ -47,11 +48,6 @@ static const uint64_t SharedUserData = 0xfffff78000000000; s ? printf(#s" = 0x%016"PRIx64"\n", s) :\ eprintf("Failed to resolve "#s"\n"), s) -static uint64_t rol(uint64_t x, uint64_t y) -{ - return (x << y) | (x >> (64 - y)); -} - /* * Decoding algorithm can be found in Volatility project */ @@ -64,7 +60,7 @@ static void kdbg_decode(uint64_t *dst, uint64_t *src, size_t size, uint64_t block; block = src[i]; - block = rol(block ^ kwn, (uint8_t)kwn); + block = rol64(block ^ kwn, kwn); block = __builtin_bswap64(block ^ kdbe) ^ kwa; dst[i] = block; } From a2de23c6e3e840e3e96ad0bb9e4314988e5a2f42 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:20:58 +0900 Subject: [PATCH 16/20] MAINTAINERS: Add Akihiko Odaki as a elf2dmp reviewer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Reviewed-by: Viktor Prutyanov Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240307-elf2dmp-v4-15-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 4d96f855de..12f5e47a11 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3587,6 +3587,7 @@ F: util/iova-tree.c elf2dmp M: Viktor Prutyanov +R: Akihiko Odaki S: Maintained F: contrib/elf2dmp/ From 0c94e32dff020f868a8125c5314fe9f318a8215d Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:21:00 +0900 Subject: [PATCH 17/20] contrib/elf2dmp: Use GPtrArray This removes the need to enumarate QEMUCPUState twice and saves code. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-17-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/qemu_elf.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c index a22c057d3e..7d896cac5b 100644 --- a/contrib/elf2dmp/qemu_elf.c +++ b/contrib/elf2dmp/qemu_elf.c @@ -66,7 +66,7 @@ static bool init_states(QEMU_Elf *qe) Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset); Elf64_Nhdr *end = (void *)((uint8_t *)start + phdr[0].p_memsz); Elf64_Nhdr *nhdr; - size_t cpu_nr = 0; + GPtrArray *states; if (phdr[0].p_type != PT_NOTE) { eprintf("Failed to find PT_NOTE\n"); @@ -74,38 +74,29 @@ static bool init_states(QEMU_Elf *qe) } qe->has_kernel_gs_base = 1; + states = g_ptr_array_new(); for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) { if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) { QEMUCPUState *state = nhdr_get_desc(nhdr); if (state->size < sizeof(*state)) { - eprintf("CPU #%zu: QEMU CPU state size %u doesn't match\n", - cpu_nr, state->size); + eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n", + states->len, state->size); /* * We assume either every QEMU CPU state has KERNEL_GS_BASE or * no one has. */ qe->has_kernel_gs_base = 0; } - cpu_nr++; + g_ptr_array_add(states, state); } } - printf("%zu CPU states has been found\n", cpu_nr); + printf("%u CPU states has been found\n", states->len); - qe->state = g_new(QEMUCPUState*, cpu_nr); - - cpu_nr = 0; - - for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) { - if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) { - qe->state[cpu_nr] = nhdr_get_desc(nhdr); - cpu_nr++; - } - } - - qe->state_nr = cpu_nr; + qe->state_nr = states->len; + qe->state = (void *)g_ptr_array_free(states, FALSE); return true; } From 9de37c288367ad22dd8abe069eeae17faf6e3ed9 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:21:01 +0900 Subject: [PATCH 18/20] contrib/elf2dmp: Clamp QEMU note to file size This fixes crashes with truncated dumps. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Tested-by: Viktor Prutyanov Message-id: 20240307-elf2dmp-v4-18-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/qemu_elf.c | 87 ++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c index 7d896cac5b..8d750adf90 100644 --- a/contrib/elf2dmp/qemu_elf.c +++ b/contrib/elf2dmp/qemu_elf.c @@ -6,6 +6,7 @@ */ #include "qemu/osdep.h" +#include "qemu/host-utils.h" #include "err.h" #include "qemu_elf.h" @@ -15,36 +16,11 @@ #define ROUND_UP(n, d) (((n) + (d) - 1) & -(0 ? (n) : (d))) #endif -#ifndef DIV_ROUND_UP -#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) -#endif - -#define ELF_NOTE_SIZE(hdr_size, name_size, desc_size) \ - ((DIV_ROUND_UP((hdr_size), 4) + \ - DIV_ROUND_UP((name_size), 4) + \ - DIV_ROUND_UP((desc_size), 4)) * 4) - int is_system(QEMUCPUState *s) { return s->gs.base >> 63; } -static char *nhdr_get_name(Elf64_Nhdr *nhdr) -{ - return (char *)nhdr + ROUND_UP(sizeof(*nhdr), 4); -} - -static void *nhdr_get_desc(Elf64_Nhdr *nhdr) -{ - return nhdr_get_name(nhdr) + ROUND_UP(nhdr->n_namesz, 4); -} - -static Elf64_Nhdr *nhdr_get_next(Elf64_Nhdr *nhdr) -{ - return (void *)((uint8_t *)nhdr + ELF_NOTE_SIZE(sizeof(*nhdr), - nhdr->n_namesz, nhdr->n_descsz)); -} - Elf64_Phdr *elf64_getphdr(void *map) { Elf64_Ehdr *ehdr = map; @@ -60,13 +36,35 @@ Elf64_Half elf_getphdrnum(void *map) return ehdr->e_phnum; } +static bool advance_note_offset(uint64_t *offsetp, uint64_t size, uint64_t end) +{ + uint64_t offset = *offsetp; + + if (uadd64_overflow(offset, size, &offset) || offset > UINT64_MAX - 3) { + return false; + } + + offset = ROUND_UP(offset, 4); + + if (offset > end) { + return false; + } + + *offsetp = offset; + + return true; +} + static bool init_states(QEMU_Elf *qe) { Elf64_Phdr *phdr = elf64_getphdr(qe->map); - Elf64_Nhdr *start = (void *)((uint8_t *)qe->map + phdr[0].p_offset); - Elf64_Nhdr *end = (void *)((uint8_t *)start + phdr[0].p_memsz); Elf64_Nhdr *nhdr; GPtrArray *states; + QEMUCPUState *state; + uint32_t state_size; + uint64_t offset; + uint64_t end_offset; + char *name; if (phdr[0].p_type != PT_NOTE) { eprintf("Failed to find PT_NOTE\n"); @@ -74,15 +72,40 @@ static bool init_states(QEMU_Elf *qe) } qe->has_kernel_gs_base = 1; + offset = phdr[0].p_offset; states = g_ptr_array_new(); - for (nhdr = start; nhdr < end; nhdr = nhdr_get_next(nhdr)) { - if (!strcmp(nhdr_get_name(nhdr), QEMU_NOTE_NAME)) { - QEMUCPUState *state = nhdr_get_desc(nhdr); + if (uadd64_overflow(offset, phdr[0].p_memsz, &end_offset) || + end_offset > qe->size) { + end_offset = qe->size; + } - if (state->size < sizeof(*state)) { + while (offset < end_offset) { + nhdr = (void *)((uint8_t *)qe->map + offset); + + if (!advance_note_offset(&offset, sizeof(*nhdr), end_offset)) { + break; + } + + name = (char *)qe->map + offset; + + if (!advance_note_offset(&offset, nhdr->n_namesz, end_offset)) { + break; + } + + state = (void *)((uint8_t *)qe->map + offset); + + if (!advance_note_offset(&offset, nhdr->n_descsz, end_offset)) { + break; + } + + if (!strcmp(name, QEMU_NOTE_NAME) && + nhdr->n_descsz >= offsetof(QEMUCPUState, kernel_gs_base)) { + state_size = MIN(state->size, nhdr->n_descsz); + + if (state_size < sizeof(*state)) { eprintf("CPU #%u: QEMU CPU state size %u doesn't match\n", - states->len, state->size); + states->len, state_size); /* * We assume either every QEMU CPU state has KERNEL_GS_BASE or * no one has. From 98d16e5f724cf4f884cab28956321a4a093474d7 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 7 Mar 2024 19:21:02 +0900 Subject: [PATCH 19/20] contrib/elf2dmp: Ensure phdrs fit in file Callers of elf64_getphdr() and elf_getphdrnum() assume phdrs are accessible. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2202 Signed-off-by: Akihiko Odaki Tested-by: Viktor Prutyanov Reviewed-by: Peter Maydell Message-id: 20240307-elf2dmp-v4-19-4f324ad4d99d@daynix.com Signed-off-by: Peter Maydell --- contrib/elf2dmp/qemu_elf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c index 8d750adf90..c9bad6e82c 100644 --- a/contrib/elf2dmp/qemu_elf.c +++ b/contrib/elf2dmp/qemu_elf.c @@ -132,6 +132,7 @@ static void exit_states(QEMU_Elf *qe) static bool check_ehdr(QEMU_Elf *qe) { Elf64_Ehdr *ehdr = qe->map; + uint64_t phendoff; if (sizeof(Elf64_Ehdr) > qe->size) { eprintf("Invalid input dump file size\n"); @@ -173,6 +174,13 @@ static bool check_ehdr(QEMU_Elf *qe) return false; } + if (umul64_overflow(ehdr->e_phnum, sizeof(Elf64_Phdr), &phendoff) || + uadd64_overflow(phendoff, ehdr->e_phoff, &phendoff) || + phendoff > qe->size) { + eprintf("phdrs do not fit in file\n"); + return false; + } + return true; } From 5dd6bfd90d01e0cb27c349157208e5e4ce883846 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Mon, 11 Mar 2024 17:33:46 +0530 Subject: [PATCH 20/20] docs: update copyright date to the year 2024 We are already in the third month of 2024 but the copyright notices still refer to 2023. Update the date to 2024 in documentation and help texts. Cc: peter.maydell@linaro.org Cc: qemu-trivial@nongnu.org Signed-off-by: Ani Sinha Reviewed-by: Peter Maydell Message-id: 20240311120346.9596-1-anisinha@redhat.com Signed-off-by: Peter Maydell --- docs/conf.py | 2 +- include/qemu/help-texts.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 1b2afa241c..aae0304ac6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -88,7 +88,7 @@ default_role = 'any' # General information about the project. project = u'QEMU' -copyright = u'2023, The QEMU Project Developers' +copyright = u'2024, The QEMU Project Developers' author = u'The QEMU Project Developers' # The version info for the project you're documenting, acts as replacement for diff --git a/include/qemu/help-texts.h b/include/qemu/help-texts.h index d0359f82e0..353ab2ad8b 100644 --- a/include/qemu/help-texts.h +++ b/include/qemu/help-texts.h @@ -2,7 +2,7 @@ #define QEMU_HELP_TEXTS_H /* Copyright string for -version arguments, About dialogs, etc */ -#define QEMU_COPYRIGHT "Copyright (c) 2003-2023 " \ +#define QEMU_COPYRIGHT "Copyright (c) 2003-2024 " \ "Fabrice Bellard and the QEMU Project developers" /* Bug reporting information for --help arguments, About dialogs, etc */