aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-03-12 11:35:35 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-03-12 11:35:35 +0000
commit1c268991b3fe699fee16b1cbb9c6025d334c5b25 (patch)
treed57a6a7277fd3abdfd547ee4a30ad1dcc1cc0d55
parent05ec974671200814fa5c1d5db710e0e4b88a40af (diff)
parent5dd6bfd90d01e0cb27c349157208e5e4ce883846 (diff)
downloadqemu-1c268991b3fe699fee16b1cbb9c6025d334c5b25.zip
qemu-1c268991b3fe699fee16b1cbb9c6025d334c5b25.tar.gz
qemu-1c268991b3fe699fee16b1cbb9c6025d334c5b25.tar.bz2
Merge tag 'pull-target-arm-20240311' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * contrib/elf2dmp: Improve robustness to corrupt input files * docs: update copyright date to the year 2024 * hw/arm: Deprecate various old Arm machine types # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmXvV4gZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3oe5EACvvve9LOJ7UA4teEbn8zzs # O7GGsycpu3XWINX98sUi5Cuu+uexkcXsHf2Vg8GABj2fUuA+EEqPIdIWZhVcfB2t # RYGPgat/JVTwRUsl38OQ97l4joI2JeW18B20Pmh4/2tbZCJuIHoiHxxb+3aQl6Nl # gz/H137ayy+Q5utt1b6z1qXnw4etiUhk4wg2ltGVtAw63w5GZOvamTicSQ1DC3ZP # zfbIKW2WpGNjzrC1tCvaW/dNojt2blpZbsnpdPsL8cNE8puo01FnFLsUZCzOtu3m # 23uoQq0KjQZBJrU2oZMtshc+sKT/FGPADJ9B+J8jjU0EY6cV+Qo7FT4E78mxzoR0 # JbY9SLATtY7RE1Fbh3/Am+3OEyb3ZDor5nCux0CWOsuFoBk96dzD7r5MXxM2eft1 # pGmdJStYysZkdlSyx61bu6OifHOaGjnOe+lYWpaCrVy1U3cO3hbMWH2siSQygppM # 8EfjyfadzfST+nAnXfduSgWMv7Nc4ql4GIOxVnMIfGig32PIp545IvM9neh6GIp/ # 8fzw6TdoCQkHcWaazV1ibPF0ceH6JwRvLIMkWlNpr/QBSNdsx+zkdh7WZD+3S91U # XrCAA7hgf7OIvHauSD0ucSbztIiFRMROcHxIoh0ui6BermtaD6fnlei4QcsJI17o # 6XZSNSWm5/+JEsn+dcVh4g== # =UHyi # -----END PGP SIGNATURE----- # gpg: Signature made Mon 11 Mar 2024 19:12:08 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20240311' of https://git.linaro.org/people/pmaydell/qemu-arm: docs: update copyright date to the year 2024 contrib/elf2dmp: Ensure phdrs fit in file contrib/elf2dmp: Clamp QEMU note to file size contrib/elf2dmp: Use GPtrArray MAINTAINERS: Add Akihiko Odaki as a elf2dmp reviewer contrib/elf2dmp: Use rol64() to decode contrib/elf2dmp: Use lduw_le_p() to read PDB contrib/elf2dmp: Ensure segment fits in file contrib/elf2dmp: Always destroy PA space contrib/elf2dmp: Always check for PA resolution failure contrib/elf2dmp: Fix error reporting style in main.c contrib/elf2dmp: Fix error reporting style in qemu_elf.c contrib/elf2dmp: Fix error reporting style in pdb.c contrib/elf2dmp: Fix error reporting style in download.c contrib/elf2dmp: Fix error reporting style in addrspace.c contrib/elf2dmp: Change pa_space_create() signature contrib/elf2dmp: Continue even contexts are lacking contrib/elf2dmp: Assume error by default contrib/elf2dmp: Remove unnecessary err flags hw/arm: Deprecate various old Arm machine types Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS1
-rw-r--r--contrib/elf2dmp/addrspace.c63
-rw-r--r--contrib/elf2dmp/addrspace.h6
-rw-r--r--contrib/elf2dmp/download.c12
-rw-r--r--contrib/elf2dmp/download.h2
-rw-r--r--contrib/elf2dmp/main.c168
-rw-r--r--contrib/elf2dmp/pdb.c61
-rw-r--r--contrib/elf2dmp/pdb.h2
-rw-r--r--contrib/elf2dmp/qemu_elf.c150
-rw-r--r--contrib/elf2dmp/qemu_elf.h2
-rw-r--r--docs/about/deprecated.rst15
-rw-r--r--docs/conf.py2
-rw-r--r--hw/arm/gumstix.c2
-rw-r--r--hw/arm/mainstone.c1
-rw-r--r--hw/arm/nseries.c2
-rw-r--r--hw/arm/palm.c1
-rw-r--r--hw/arm/spitz.c1
-rw-r--r--hw/arm/tosa.c1
-rw-r--r--hw/arm/z2.c1
-rw-r--r--include/qemu/help-texts.h2
20 files changed, 263 insertions, 232 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4d96f85..12f5e47 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3587,6 +3587,7 @@ F: util/iova-tree.c
elf2dmp
M: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
+R: Akihiko Odaki <akihiko.odaki@daynix.com>
S: Maintained
F: contrib/elf2dmp/
diff --git a/contrib/elf2dmp/addrspace.c b/contrib/elf2dmp/addrspace.c
index 6f608a5..81295a1 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;
@@ -57,7 +70,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);
@@ -75,11 +88,12 @@ int 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;
@@ -87,8 +101,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)
@@ -108,19 +120,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)
@@ -133,11 +146,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)
@@ -150,11 +164,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)
@@ -186,13 +201,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;
}
@@ -200,8 +213,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;
}
@@ -209,8 +221,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;
}
@@ -228,8 +239,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;
@@ -240,7 +251,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) {
@@ -254,5 +265,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 039c70c..2ad30a9 100644
--- a/contrib/elf2dmp/addrspace.h
+++ b/contrib/elf2dmp/addrspace.h
@@ -33,13 +33,13 @@ 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);
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/download.c b/contrib/elf2dmp/download.c
index bd7650a..21306b3 100644
--- a/contrib/elf2dmp/download.c
+++ b/contrib/elf2dmp/download.c
@@ -9,19 +9,18 @@
#include <curl/curl.h>
#include "download.h"
-int download_url(const char *name, const char *url)
+bool download_url(const char *name, const char *url)
{
- int err = 0;
+ bool success = false;
FILE *file;
CURL *curl = curl_easy_init();
if (!curl) {
- return 1;
+ return false;
}
file = fopen(name, "wb");
if (!file) {
- err = 1;
goto out_curl;
}
@@ -33,13 +32,12 @@ 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);
+ 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 5c27492..f65adb5 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 cbc38a7..d046a72 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;
}
@@ -79,9 +75,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 +93,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 +118,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;
@@ -186,13 +182,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 +202,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 +216,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 +264,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 +280,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)) {
+ if (!va_space_rw(vs, KdVersionBlock, &kvb, sizeof(kvb), 0)) {
eprintf("Failed to extract KdVersionBlock\n");
- return 1;
+ return false;
}
h = (WinDumpHeader64) {
@@ -333,11 +330,16 @@ static int fill_header(WinDumpHeader64 *hdr, struct pa_space *ps,
*hdr = h;
- return 0;
+ return true;
}
-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;
@@ -347,10 +349,10 @@ static int 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);
- return 1;
+ continue;
}
if (!Prcb) {
@@ -358,26 +360,24 @@ static int 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);
- return 1;
+ continue;
}
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);
- return 1;
+ continue;
}
}
-
- return 0;
}
-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";
@@ -390,40 +390,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;
+ if (!va_space_rw(vs, base + dos_hdr->e_lfanew,
+ &nt_hdrs, sizeof(nt_hdrs), 0)) {
+ 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;
+ if (!va_space_rw(vs, base + data_dir[idx].VirtualAddress, entry, size, 0)) {
+ 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");
@@ -431,7 +429,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++) {
@@ -442,11 +440,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,
@@ -456,8 +454,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;
}
@@ -467,9 +465,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;
}
@@ -485,9 +482,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;
}
@@ -511,7 +508,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;
@@ -535,33 +532,27 @@ 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;
}
- if (pa_space_create(&ps, &qemu_elf)) {
- eprintf("Failed to initialize physical address space\n");
- err = 1;
- 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]);
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");
- err = 1;
- goto out_elf;
+ goto out_ps;
}
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");
- err = 1;
goto out_ps;
}
printf("CPU #0 IDT[0] -> 0x%016"PRIx64"\n", idt_desc_addr(first_idt_desc));
@@ -586,7 +577,6 @@ int main(int argc, char *argv[])
if (!kernel_found) {
eprintf("Failed to find NT kernel image\n");
- err = 1;
goto out_ps;
}
@@ -598,47 +588,40 @@ 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");
- err = 1;
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");
- 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;
+ if (!fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg,
+ KdVersionBlock, qemu_elf.state_nr)) {
goto out_kdbg;
}
- if (fill_context(kdbg, &vs, &qemu_elf)) {
- err = 1;
- 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");
- err = 1;
goto out_kdbg;
}
+ err = 0;
+
out_kdbg:
g_free(kdbg);
out_pdb:
@@ -647,7 +630,6 @@ out_pdb_file:
unlink(PDB_NAME);
out_ps:
pa_space_destroy(&ps);
-out_elf:
QEMU_Elf_exit(&qemu_elf);
return err;
diff --git a/contrib/elf2dmp/pdb.c b/contrib/elf2dmp/pdb.c
index 40991f5..492aca4 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"
@@ -158,36 +159,35 @@ 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)
{
- int err = 0;
PDB_SYMBOLS *symbols;
symbols = pdb_ds_read_file(r, 3);
if (!symbols) {
- return 1;
+ return false;
}
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 +
@@ -196,22 +196,21 @@ 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;
}
- return 0;
+ return true;
out_symbols:
g_free(symbols);
- return err;
+ 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));
@@ -220,42 +219,38 @@ 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)
{
- int err = 0;
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);
if (!r->ds.root) {
- err = 1;
goto out_ds;
}
- if (pdb_init_symbols(r)) {
- err = 1;
+ if (!pdb_init_symbols(r)) {
goto out_root;
}
- if (pdb_init_segments(r)) {
- err = 1;
+ if (!pdb_init_segments(r)) {
goto out_sym;
}
- return 0;
+ return true;
out_sym:
pdb_exit_symbols(r);
@@ -264,7 +259,7 @@ out_root:
out_ds:
pdb_reader_ds_exit(r);
- return err;
+ return false;
}
static void pdb_reader_exit(struct pdb_reader *r)
@@ -275,32 +270,30 @@ 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;
- int err = 0;
void *map;
reader->gmf = g_mapped_file_new(name, TRUE, &gerr);
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)) {
- err = 1;
+ if (!pdb_reader_init(reader, map)) {
goto out_unmap;
}
- return 0;
+ return true;
out_unmap:
g_mapped_file_unref(reader->gmf);
- return err;
+ return false;
}
void pdb_exit(struct pdb_reader *reader)
diff --git a/contrib/elf2dmp/pdb.h b/contrib/elf2dmp/pdb.h
index 2a50da5..feddf18 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);
diff --git a/contrib/elf2dmp/qemu_elf.c b/contrib/elf2dmp/qemu_elf.c
index 055e6f8..c9bad6e 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,54 +36,92 @@ Elf64_Half elf_getphdrnum(void *map)
return ehdr->e_phnum;
}
-static int init_states(QEMU_Elf *qe)
+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;
- size_t cpu_nr = 0;
+ 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");
- return 1;
+ return false;
}
qe->has_kernel_gs_base = 1;
+ offset = phdr[0].p_offset;
+ states = g_ptr_array_new();
+
+ if (uadd64_overflow(offset, phdr[0].p_memsz, &end_offset) ||
+ end_offset > qe->size) {
+ end_offset = qe->size;
+ }
- 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);
+ while (offset < end_offset) {
+ nhdr = (void *)((uint8_t *)qe->map + offset);
- if (state->size < sizeof(*state)) {
- eprintf("CPU #%zu: QEMU CPU state size %u doesn't match\n",
- cpu_nr, state->size);
+ 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);
/*
* 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);
-
- 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++;
- }
- }
+ printf("%u CPU states has been found\n", states->len);
- qe->state_nr = cpu_nr;
+ qe->state_nr = states->len;
+ qe->state = (void *)g_ptr_array_free(states, FALSE);
- return 0;
+ return true;
}
static void exit_states(QEMU_Elf *qe)
@@ -118,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");
@@ -159,10 +174,17 @@ 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;
}
-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 +195,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 +210,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 +223,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 +242,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 afa75f1..adc5023 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);
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index dfd681c..0d074d1 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/docs/conf.py b/docs/conf.py
index 1b2afa2..aae0304 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/hw/arm/gumstix.c b/hw/arm/gumstix.c
index d5de540..9146269 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 d2e2e68..3a6c22f 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 35deb74..3536431 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 8c4c831..e04ac92 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 643a02b..62cd55b 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 3ca2e44..5891f60 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 eb2ff8d..fc5672e 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);
}
diff --git a/include/qemu/help-texts.h b/include/qemu/help-texts.h
index d0359f8..353ab2a 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 */