aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2025-08-30 08:24:48 +1000
committerRichard Henderson <richard.henderson@linaro.org>2025-08-30 08:24:48 +1000
commit4791f22a5f5571cb248b1eddff98630545b3fd3e (patch)
treee5ac7a50bb6007555a94bc1024dfb26d32b68f64
parent59f504bb43366594e97cf496c9a9ccf59be00b73 (diff)
parent3f1b9dbdf5452a2baab00d46bd149f6f8192fe44 (diff)
downloadqemu-4791f22a5f5571cb248b1eddff98630545b3fd3e.zip
qemu-4791f22a5f5571cb248b1eddff98630545b3fd3e.tar.gz
qemu-4791f22a5f5571cb248b1eddff98630545b3fd3e.tar.bz2
Merge tag 'pull-lu-20250830' of https://gitlab.com/rth7680/qemu into staging
linux-user: Finish elfload.c split linux-user: Drop deprecated -p option linux-user: Tidy print_socket_protocol hw/core: Dump cpu_reset in the reset.exit phase hw/core: Use qemu_log_trylock/unlock in cpu_common_reset_exit # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmiyKFIdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/LBggAgMBSVMz1BwkPvckY # paakdAwuOqRE5yF2YxQAHALJa3aH18Vqk06ENqM9R5iyqvHBGnvrw8fshIBVZnDP # eQDjNFwnCtSrXuSMdfr0r8jZc+y9R8foQKs9j+KL0ESOi+4VNhORfzFe/yrIEu0y # XM5XhBjBH0kK9+S20uy5x3WXhRkfqq2CZiUt1izqTOwtbdzYENxdvDj8iDk48FwL # fkrXUSnlBBsdsltQCsjbrUbWi1Wqj7skswRIzI8KXsj+psy0JJL2kHthaWzm8tTS # KIXVaOtxtU7LQWhTaknmpcNIkHpnjmEw2ZijxYT29V8WnZtstihVoqqCLbCv6u+7 # JwwQhQ== # =kHx+ # -----END PGP SIGNATURE----- # gpg: Signature made Sat 30 Aug 2025 08:23:14 AM AEST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * tag 'pull-lu-20250830' of https://gitlab.com/rth7680/qemu: (91 commits) linux-user: Remove target_pt_regs from target_syscall.h linux-user/sparc: Create target_ptrace.h linux-user: Remove a.out declarations from elfload.c linux-user: Move arch_parse_elf_property to aarch64/elfload.c linux-user: Remove MAP_DENYWRITE from elfload.c linux-user: Remove ELIBBAD from elfload.c linux-user: Rename elf_check_arch linux-user: Standardize on ELF_MACHINE not ELF_ARCH linux-user: Move elf parameters to hexagon/target_elf.h linux-user: Move elf parameters to xtensa/target_elf.h linux-user: Move elf parameters to hppa/target_elf.h linux-user: Move elf parameters to riscv/target_elf.h linux-user: Move elf parameters to s390x/target_elf.h linux-user: Move elf parameters to alpha/target_elf.h linux-user: Move elf parameters to m68k/target_elf.h linux-user: Move elf parameters to sh4/target_elf.h linux-user: Move elf parameters to openrisc/target_elf.h linux-user: Move elf parameters to microblaze/target_elf.h linux-user: Move elf parameters to {mips,mips64}/target_elf.h linux-user: Move elf parameters to loongarch64/target_elf.h ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--bsd-user/main.c8
-rw-r--r--docs/about/deprecated.rst10
-rw-r--r--docs/about/removed-features.rst8
-rw-r--r--docs/user/main.rst3
-rw-r--r--hw/core/cpu-common.c21
-rw-r--r--linux-user/aarch64/elfload.c29
-rw-r--r--linux-user/aarch64/target_elf.h21
-rw-r--r--linux-user/aarch64/target_ptrace.h14
-rw-r--r--linux-user/aarch64/target_syscall.h7
-rw-r--r--linux-user/alpha/target_elf.h3
-rw-r--r--linux-user/alpha/target_syscall.h40
-rw-r--r--linux-user/arm/elfload.c76
-rw-r--r--linux-user/arm/target_elf.h18
-rw-r--r--linux-user/arm/target_ptrace.h16
-rw-r--r--linux-user/arm/target_syscall.h8
-rw-r--r--linux-user/elfload.c918
-rw-r--r--linux-user/hexagon/target_elf.h3
-rw-r--r--linux-user/hexagon/target_syscall.h5
-rw-r--r--linux-user/hppa/elfload.c31
-rw-r--r--linux-user/hppa/target_elf.h8
-rw-r--r--linux-user/hppa/target_syscall.h18
-rw-r--r--linux-user/i386/elfload.c22
-rw-r--r--linux-user/i386/target_elf.h33
-rw-r--r--linux-user/i386/target_ptrace.h32
-rw-r--r--linux-user/i386/target_syscall.h18
-rw-r--r--linux-user/loader.h21
-rw-r--r--linux-user/loongarch64/elfload.c15
-rw-r--r--linux-user/loongarch64/target_elf.h13
-rw-r--r--linux-user/loongarch64/target_ptrace.h15
-rw-r--r--linux-user/loongarch64/target_syscall.h23
-rw-r--r--linux-user/m68k/elfload.c25
-rw-r--r--linux-user/m68k/target_elf.h27
-rw-r--r--linux-user/m68k/target_syscall.h16
-rw-r--r--linux-user/main.c12
-rw-r--r--linux-user/microblaze/elfload.c13
-rw-r--r--linux-user/microblaze/signal.c71
-rw-r--r--linux-user/microblaze/target_elf.h17
-rw-r--r--linux-user/microblaze/target_ptrace.h20
-rw-r--r--linux-user/microblaze/target_syscall.h44
-rw-r--r--linux-user/mips/elfload.c18
-rw-r--r--linux-user/mips/target_elf.h15
-rw-r--r--linux-user/mips/target_ptrace.h17
-rw-r--r--linux-user/mips/target_syscall.h19
-rw-r--r--linux-user/mips64/target_elf.h21
-rw-r--r--linux-user/mips64/target_ptrace.h16
-rw-r--r--linux-user/mips64/target_syscall.h16
-rw-r--r--linux-user/openrisc/elfload.c10
-rw-r--r--linux-user/openrisc/signal.c3
-rw-r--r--linux-user/openrisc/target_elf.h15
-rw-r--r--linux-user/openrisc/target_ptrace.h13
-rw-r--r--linux-user/openrisc/target_syscall.h11
-rw-r--r--linux-user/ppc/elfload.c15
-rw-r--r--linux-user/ppc/target_elf.h56
-rw-r--r--linux-user/ppc/target_ptrace.h26
-rw-r--r--linux-user/ppc/target_syscall.h28
-rw-r--r--linux-user/riscv/target_elf.h10
-rw-r--r--linux-user/riscv/target_syscall.h35
-rw-r--r--linux-user/s390x/elfload.c14
-rw-r--r--linux-user/s390x/signal.c1
-rw-r--r--linux-user/s390x/target_elf.h15
-rw-r--r--linux-user/s390x/target_ptrace.h18
-rw-r--r--linux-user/s390x/target_syscall.h22
-rw-r--r--linux-user/sh4/elfload.c15
-rw-r--r--linux-user/sh4/target_elf.h14
-rw-r--r--linux-user/sh4/target_ptrace.h18
-rw-r--r--linux-user/sh4/target_syscall.h11
-rw-r--r--linux-user/sparc/signal.c2
-rw-r--r--linux-user/sparc/target_elf.h11
-rw-r--r--linux-user/sparc/target_ptrace.h24
-rw-r--r--linux-user/sparc/target_syscall.h19
-rw-r--r--linux-user/strace.c96
-rw-r--r--linux-user/x86_64/elfload.c52
-rw-r--r--linux-user/x86_64/target_elf.h16
-rw-r--r--linux-user/x86_64/target_ptrace.h40
-rw-r--r--linux-user/x86_64/target_syscall.h28
-rw-r--r--linux-user/xtensa/elfload.c20
-rw-r--r--linux-user/xtensa/target_elf.h15
-rw-r--r--linux-user/xtensa/target_ptrace.h22
-rw-r--r--linux-user/xtensa/target_syscall.h35
79 files changed, 1116 insertions, 1438 deletions
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 7e5d4bb..9ba6964 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -367,14 +367,6 @@ int main(int argc, char **argv)
}
} else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++];
- } else if (!strcmp(r, "p")) {
- unsigned size, want = qemu_real_host_page_size();
-
- r = argv[optind++];
- if (qemu_strtoui(r, NULL, 10, &size) || size != want) {
- warn_report("Deprecated page size option cannot "
- "change host page size (%u)", want);
- }
} else if (!strcmp(r, "g")) {
gdbstub = g_strdup(argv[optind++]);
} else if (!strcmp(r, "r")) {
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index d50645a..5d1579d 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -81,16 +81,6 @@ kernel since 2001. None of the board types QEMU supports need
``param_struct`` support, so this option has been deprecated and will
be removed in a future QEMU version.
-User-mode emulator command line arguments
------------------------------------------
-
-``-p`` (since 9.0)
-''''''''''''''''''
-
-The ``-p`` option pretends to control the host page size. However,
-it is not possible to change the host page size, and using the
-option only causes failures.
-
QEMU Machine Protocol (QMP) commands
------------------------------------
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index d7c2113..25a9040 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -571,6 +571,14 @@ The ``-singlestep`` option has been given a name that better reflects
what it actually does. For both linux-user and bsd-user, use the
``-one-insn-per-tb`` option instead.
+``-p`` (removed in 10.2)
+''''''''''''''''''''''''
+
+The ``-p`` option pretends to control the host page size. However,
+it is not possible to change the host page size; we stopped trying
+to do anything with the option except print a warning from 9.0,
+and now the option is removed entirely.
+
QEMU Machine Protocol (QMP) commands
------------------------------------
diff --git a/docs/user/main.rst b/docs/user/main.rst
index 347bdfa..a8ddf91 100644
--- a/docs/user/main.rst
+++ b/docs/user/main.rst
@@ -262,9 +262,6 @@ Debug options:
Activate logging of the specified items (use '-d help' for a list of
log items)
-``-p pagesize``
- Act as if the host page size was 'pagesize' bytes
-
``-one-insn-per-tb``
Run the emulation with one guest instruction per translation block.
This slows down emulation a lot, but can be useful in some situations,
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 39e674a..259cf2a 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -119,11 +119,6 @@ static void cpu_common_reset_hold(Object *obj, ResetType type)
{
CPUState *cpu = CPU(obj);
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", cpu->cpu_index);
- log_cpu_state(cpu, cpu->cc->reset_dump_flags);
- }
-
cpu->interrupt_request = 0;
cpu->halted = cpu->start_powered_off;
cpu->mem_io_pc = 0;
@@ -137,6 +132,21 @@ static void cpu_common_reset_hold(Object *obj, ResetType type)
cpu_exec_reset_hold(cpu);
}
+static void cpu_common_reset_exit(Object *obj, ResetType type)
+{
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ FILE *f = qemu_log_trylock();
+
+ if (f) {
+ CPUState *cpu = CPU(obj);
+
+ fprintf(f, "CPU Reset (CPU %d)\n", cpu->cpu_index);
+ cpu_dump_state(cpu, f, cpu->cc->reset_dump_flags);
+ qemu_log_unlock(f);
+ }
+ }
+}
+
ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
{
ObjectClass *oc;
@@ -380,6 +390,7 @@ static void cpu_common_class_init(ObjectClass *klass, const void *data)
dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn;
rc->phases.hold = cpu_common_reset_hold;
+ rc->phases.exit = cpu_common_reset_exit;
cpu_class_init_props(dc);
/*
* Reason: CPUs still need special care by board code: wiring up
diff --git a/linux-user/aarch64/elfload.c b/linux-user/aarch64/elfload.c
index 1030cb8..8076968 100644
--- a/linux-user/aarch64/elfload.c
+++ b/linux-user/aarch64/elfload.c
@@ -1,9 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu.h"
#include "loader.h"
#include "target/arm/cpu-features.h"
+#include "target_elf.h"
+#include "elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -347,3 +350,29 @@ const char *get_elf_platform(CPUState *cs)
{
return TARGET_BIG_ENDIAN ? "aarch64_be" : "aarch64";
}
+
+bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
+ const uint32_t *data,
+ struct image_info *info,
+ Error **errp)
+{
+ if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
+ if (pr_datasz != sizeof(uint32_t)) {
+ error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
+ return false;
+ }
+ /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
+ info->note_flags = *data;
+ }
+ return true;
+}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUARMState *env)
+{
+ for (int i = 0; i < 31; i++) {
+ r->pt.regs[i] = tswap64(env->xregs[i]);
+ }
+ r->pt.sp = tswap64(env->xregs[31]);
+ r->pt.pc = tswap64(env->pc);
+ r->pt.pstate = tswap64(pstate_read((CPUARMState *)env));
+}
diff --git a/linux-user/aarch64/target_elf.h b/linux-user/aarch64/target_elf.h
index dee79ce..4cdeb64 100644
--- a/linux-user/aarch64/target_elf.h
+++ b/linux-user/aarch64/target_elf.h
@@ -8,8 +8,29 @@
#ifndef AARCH64_TARGET_ELF_H
#define AARCH64_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_MACHINE EM_AARCH64
+#define ELF_CLASS ELFCLASS64
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_HWCAP2 1
#define HAVE_ELF_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+#define HAVE_ELF_GNU_PROPERTY 1
+
+/*
+ * See linux kernel: arch/arm64/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct user_pt_regs via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_user_pt_regs pt;
+} target_elf_gregset_t;
+
+#if TARGET_BIG_ENDIAN
+# define VDSO_HEADER "vdso-be.c.inc"
+#else
+# define VDSO_HEADER "vdso-le.c.inc"
+#endif
#endif
diff --git a/linux-user/aarch64/target_ptrace.h b/linux-user/aarch64/target_ptrace.h
new file mode 100644
index 0000000..1068133
--- /dev/null
+++ b/linux-user/aarch64/target_ptrace.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef AARCH64_TARGET_PTRACE_H
+#define AARCH64_TARGET_PTRACE_H
+
+/* See arch/arm64/include/uapi/asm/ptrace.h. */
+struct target_user_pt_regs {
+ uint64_t regs[31];
+ uint64_t sp;
+ uint64_t pc;
+ uint64_t pstate;
+};
+
+#endif /* AARCH64_TARGET_PTRACE_H */
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
index c055133..bd05f6c 100644
--- a/linux-user/aarch64/target_syscall.h
+++ b/linux-user/aarch64/target_syscall.h
@@ -1,13 +1,6 @@
#ifndef AARCH64_TARGET_SYSCALL_H
#define AARCH64_TARGET_SYSCALL_H
-struct target_pt_regs {
- uint64_t regs[31];
- uint64_t sp;
- uint64_t pc;
- uint64_t pstate;
-};
-
#if TARGET_BIG_ENDIAN
#define UNAME_MACHINE "aarch64_be"
#else
diff --git a/linux-user/alpha/target_elf.h b/linux-user/alpha/target_elf.h
index 52b6868..864dc6e 100644
--- a/linux-user/alpha/target_elf.h
+++ b/linux-user/alpha/target_elf.h
@@ -8,4 +8,7 @@
#ifndef ALPHA_TARGET_ELF_H
#define ALPHA_TARGET_ELF_H
+#define ELF_CLASS ELFCLASS64
+#define ELF_MACHINE EM_ALPHA
+
#endif
diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h
index fda3a49..53706b7 100644
--- a/linux-user/alpha/target_syscall.h
+++ b/linux-user/alpha/target_syscall.h
@@ -1,46 +1,6 @@
#ifndef ALPHA_TARGET_SYSCALL_H
#define ALPHA_TARGET_SYSCALL_H
-/* default linux values for the selectors */
-#define __USER_DS (1)
-
-struct target_pt_regs {
- abi_ulong r0;
- abi_ulong r1;
- abi_ulong r2;
- abi_ulong r3;
- abi_ulong r4;
- abi_ulong r5;
- abi_ulong r6;
- abi_ulong r7;
- abi_ulong r8;
- abi_ulong r19;
- abi_ulong r20;
- abi_ulong r21;
- abi_ulong r22;
- abi_ulong r23;
- abi_ulong r24;
- abi_ulong r25;
- abi_ulong r26;
- abi_ulong r27;
- abi_ulong r28;
- abi_ulong hae;
-/* JRP - These are the values provided to a0-a2 by PALcode */
- abi_ulong trap_a0;
- abi_ulong trap_a1;
- abi_ulong trap_a2;
-/* These are saved by PAL-code: */
- abi_ulong ps;
- abi_ulong pc;
- abi_ulong gp;
- abi_ulong r16;
- abi_ulong r17;
- abi_ulong r18;
-/* Those is needed by qemu to temporary store the user stack pointer */
- abi_ulong usp;
- abi_ulong unique;
-};
-
#define UNAME_MACHINE "alpha"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/arm/elfload.c b/linux-user/arm/elfload.c
index 7de1f13..308ed23 100644
--- a/linux-user/arm/elfload.c
+++ b/linux-user/arm/elfload.c
@@ -3,7 +3,11 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "user-internals.h"
+#include "target_elf.h"
#include "target/arm/cpu-features.h"
+#include "target_elf.h"
+#include "elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -199,3 +203,75 @@ const char *get_elf_platform(CPUState *cs)
#undef END
}
+
+bool init_guest_commpage(void)
+{
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
+ int host_page_size = qemu_real_host_page_size();
+ abi_ptr commpage;
+ void *want;
+ void *addr;
+
+ /*
+ * M-profile allocates maximum of 2GB address space, so can never
+ * allocate the commpage. Skip it.
+ */
+ if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
+ return true;
+ }
+
+ commpage = HI_COMMPAGE & -host_page_size;
+ want = g2h_untagged(commpage);
+ addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE |
+ (commpage < reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE),
+ -1, 0);
+
+ if (addr == MAP_FAILED) {
+ perror("Allocating guest commpage");
+ exit(EXIT_FAILURE);
+ }
+ if (addr != want) {
+ return false;
+ }
+
+ /* Set kernel helper versions; rest of page is 0. */
+ __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu));
+
+ if (mprotect(addr, host_page_size, PROT_READ)) {
+ perror("Protecting guest commpage");
+ exit(EXIT_FAILURE);
+ }
+
+ page_set_flags(commpage, commpage | (host_page_size - 1),
+ PAGE_READ | PAGE_EXEC | PAGE_VALID);
+ return true;
+}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUARMState *env)
+{
+ for (int i = 0; i < 16; ++i) {
+ r->pt.regs[i] = tswapal(env->regs[i]);
+ }
+ r->pt.cpsr = tswapal(cpsr_read((CPUARMState *)env));
+ r->pt.orig_r0 = tswapal(env->regs[0]); /* FIXME */
+}
+
+#if TARGET_BIG_ENDIAN
+# include "vdso-be8.c.inc"
+# include "vdso-be32.c.inc"
+#else
+# include "vdso-le.c.inc"
+#endif
+
+const VdsoImageInfo *get_vdso_image_info(uint32_t elf_flags)
+{
+#if TARGET_BIG_ENDIAN
+ return (EF_ARM_EABI_VERSION(elf_flags) >= EF_ARM_EABI_VER4
+ && (elf_flags & EF_ARM_BE8)
+ ? &vdso_be8_image_info
+ : &vdso_be32_image_info);
+#else
+ return &vdso_image_info;
+#endif
+}
diff --git a/linux-user/arm/target_elf.h b/linux-user/arm/target_elf.h
index 856ca41..12cdc8e 100644
--- a/linux-user/arm/target_elf.h
+++ b/linux-user/arm/target_elf.h
@@ -8,8 +8,26 @@
#ifndef ARM_TARGET_ELF_H
#define ARM_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_MACHINE EM_ARM
+#define ELF_CLASS ELFCLASS32
+#define EXSTACK_DEFAULT true
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_HWCAP2 1
#define HAVE_ELF_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+#define HAVE_VDSO_IMAGE_INFO 1
+
+#define HI_COMMPAGE ((intptr_t)0xffff0f00u)
+
+/*
+ * See linux kernel: arch/arm/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct pt_regs via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_pt_regs pt;
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/arm/target_ptrace.h b/linux-user/arm/target_ptrace.h
new file mode 100644
index 0000000..1610b8e
--- /dev/null
+++ b/linux-user/arm/target_ptrace.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef ARM_TARGET_PTRACE_H
+#define ARM_TARGET_PTRACE_H
+
+/*
+ * See arch/arm/include/uapi/asm/ptrace.h.
+ * Instead of an array and ARM_xx defines, use proper fields.
+ */
+struct target_pt_regs {
+ abi_ulong regs[16];
+ abi_ulong cpsr;
+ abi_ulong orig_r0;
+};
+
+#endif /* ARM_TARGET_PTRACE_H */
diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h
index 412ad43..8c4ddba 100644
--- a/linux-user/arm/target_syscall.h
+++ b/linux-user/arm/target_syscall.h
@@ -1,14 +1,6 @@
#ifndef ARM_TARGET_SYSCALL_H
#define ARM_TARGET_SYSCALL_H
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
-/* uregs[0..15] are r0 to r15; uregs[16] is CPSR; uregs[17] is ORIG_r0 */
-struct target_pt_regs {
- abi_long uregs[18];
-};
-
#define ARM_SYSCALL_BASE 0x900000
#define ARM_THUMB_SYSCALL 0
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fce4c05..26c090c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -40,15 +40,6 @@
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
#endif
-typedef struct {
- const uint8_t *image;
- const uint32_t *relocs;
- unsigned image_size;
- unsigned reloc_count;
- unsigned sigreturn_ofs;
- unsigned rt_sigreturn_ofs;
-} VdsoImageInfo;
-
#define ELF_OSABI ELFOSABI_SYSV
/* from personality.h */
@@ -114,30 +105,12 @@ int info_is_fdpic(struct image_info *info)
return info->personality == PER_LINUX_FDPIC;
}
-/* this flag is uneffective under linux too, should be deleted */
-#ifndef MAP_DENYWRITE
-#define MAP_DENYWRITE 0
-#endif
-
-/* should probably go in elf.h */
-#ifndef ELIBBAD
-#define ELIBBAD 80
-#endif
-
#if TARGET_BIG_ENDIAN
#define ELF_DATA ELFDATA2MSB
#else
#define ELF_DATA ELFDATA2LSB
#endif
-#ifdef TARGET_ABI_MIPSN32
-typedef abi_ullong target_elf_greg_t;
-#define tswapreg(ptr) tswap64(ptr)
-#else
-typedef abi_ulong target_elf_greg_t;
-#define tswapreg(ptr) tswapal(ptr)
-#endif
-
#ifdef USE_UID16
typedef abi_ushort target_uid_t;
typedef abi_ushort target_gid_t;
@@ -147,789 +120,8 @@ typedef abi_uint target_gid_t;
#endif
typedef abi_int target_pid_t;
-#ifdef TARGET_I386
-
-#ifdef TARGET_X86_64
-#define ELF_CLASS ELFCLASS64
-#define ELF_ARCH EM_X86_64
-
-#define ELF_NREG 27
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-/*
- * Note that ELF_NREG should be 29 as there should be place for
- * TRAPNO and ERR "registers" as well but linux doesn't dump
- * those.
- *
- * See linux kernel: arch/x86/include/asm/elf.h
- */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
-{
- (*regs)[0] = tswapreg(env->regs[15]);
- (*regs)[1] = tswapreg(env->regs[14]);
- (*regs)[2] = tswapreg(env->regs[13]);
- (*regs)[3] = tswapreg(env->regs[12]);
- (*regs)[4] = tswapreg(env->regs[R_EBP]);
- (*regs)[5] = tswapreg(env->regs[R_EBX]);
- (*regs)[6] = tswapreg(env->regs[11]);
- (*regs)[7] = tswapreg(env->regs[10]);
- (*regs)[8] = tswapreg(env->regs[9]);
- (*regs)[9] = tswapreg(env->regs[8]);
- (*regs)[10] = tswapreg(env->regs[R_EAX]);
- (*regs)[11] = tswapreg(env->regs[R_ECX]);
- (*regs)[12] = tswapreg(env->regs[R_EDX]);
- (*regs)[13] = tswapreg(env->regs[R_ESI]);
- (*regs)[14] = tswapreg(env->regs[R_EDI]);
- (*regs)[15] = tswapreg(get_task_state(env_cpu_const(env))->orig_ax);
- (*regs)[16] = tswapreg(env->eip);
- (*regs)[17] = tswapreg(env->segs[R_CS].selector & 0xffff);
- (*regs)[18] = tswapreg(env->eflags);
- (*regs)[19] = tswapreg(env->regs[R_ESP]);
- (*regs)[20] = tswapreg(env->segs[R_SS].selector & 0xffff);
- (*regs)[21] = tswapreg(env->segs[R_FS].selector & 0xffff);
- (*regs)[22] = tswapreg(env->segs[R_GS].selector & 0xffff);
- (*regs)[23] = tswapreg(env->segs[R_DS].selector & 0xffff);
- (*regs)[24] = tswapreg(env->segs[R_ES].selector & 0xffff);
- (*regs)[25] = tswapreg(env->segs[R_FS].selector & 0xffff);
- (*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff);
-}
-
-#if ULONG_MAX > UINT32_MAX
-#define INIT_GUEST_COMMPAGE
-static bool init_guest_commpage(void)
-{
- /*
- * The vsyscall page is at a high negative address aka kernel space,
- * which means that we cannot actually allocate it with target_mmap.
- * We still should be able to use page_set_flags, unless the user
- * has specified -R reserved_va, which would trigger an assert().
- */
- if (reserved_va != 0 &&
- TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE - 1 > reserved_va) {
- error_report("Cannot allocate vsyscall page");
- exit(EXIT_FAILURE);
- }
- page_set_flags(TARGET_VSYSCALL_PAGE,
- TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK,
- PAGE_EXEC | PAGE_VALID);
- return true;
-}
-#endif
-#else
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_386
-
-#define EXSTACK_DEFAULT true
-
-#define ELF_NREG 17
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-/*
- * Note that ELF_NREG should be 19 as there should be place for
- * TRAPNO and ERR "registers" as well but linux doesn't dump
- * those.
- *
- * See linux kernel: arch/x86/include/asm/elf.h
- */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
-{
- (*regs)[0] = tswapreg(env->regs[R_EBX]);
- (*regs)[1] = tswapreg(env->regs[R_ECX]);
- (*regs)[2] = tswapreg(env->regs[R_EDX]);
- (*regs)[3] = tswapreg(env->regs[R_ESI]);
- (*regs)[4] = tswapreg(env->regs[R_EDI]);
- (*regs)[5] = tswapreg(env->regs[R_EBP]);
- (*regs)[6] = tswapreg(env->regs[R_EAX]);
- (*regs)[7] = tswapreg(env->segs[R_DS].selector & 0xffff);
- (*regs)[8] = tswapreg(env->segs[R_ES].selector & 0xffff);
- (*regs)[9] = tswapreg(env->segs[R_FS].selector & 0xffff);
- (*regs)[10] = tswapreg(env->segs[R_GS].selector & 0xffff);
- (*regs)[11] = tswapreg(get_task_state(env_cpu_const(env))->orig_ax);
- (*regs)[12] = tswapreg(env->eip);
- (*regs)[13] = tswapreg(env->segs[R_CS].selector & 0xffff);
- (*regs)[14] = tswapreg(env->eflags);
- (*regs)[15] = tswapreg(env->regs[R_ESP]);
- (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
-}
-
-/*
- * i386 is the only target which supplies AT_SYSINFO for the vdso.
- * All others only supply AT_SYSINFO_EHDR.
- */
-#define DLINFO_ARCH_ITEMS (vdso_info != NULL)
-#define ARCH_DLINFO \
- do { \
- if (vdso_info) { \
- NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry); \
- } \
- } while (0)
-
-#endif /* TARGET_X86_64 */
-
-#define VDSO_HEADER "vdso.c.inc"
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#endif /* TARGET_I386 */
-
-#ifdef TARGET_ARM
-
-#ifndef TARGET_AARCH64
-/* 32 bit ARM definitions */
-
-#define ELF_ARCH EM_ARM
-#define ELF_CLASS ELFCLASS32
-#define EXSTACK_DEFAULT true
-
-#define ELF_NREG 18
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env)
-{
- (*regs)[0] = tswapreg(env->regs[0]);
- (*regs)[1] = tswapreg(env->regs[1]);
- (*regs)[2] = tswapreg(env->regs[2]);
- (*regs)[3] = tswapreg(env->regs[3]);
- (*regs)[4] = tswapreg(env->regs[4]);
- (*regs)[5] = tswapreg(env->regs[5]);
- (*regs)[6] = tswapreg(env->regs[6]);
- (*regs)[7] = tswapreg(env->regs[7]);
- (*regs)[8] = tswapreg(env->regs[8]);
- (*regs)[9] = tswapreg(env->regs[9]);
- (*regs)[10] = tswapreg(env->regs[10]);
- (*regs)[11] = tswapreg(env->regs[11]);
- (*regs)[12] = tswapreg(env->regs[12]);
- (*regs)[13] = tswapreg(env->regs[13]);
- (*regs)[14] = tswapreg(env->regs[14]);
- (*regs)[15] = tswapreg(env->regs[15]);
-
- (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env));
- (*regs)[17] = tswapreg(env->regs[0]); /* XXX */
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-/* The commpage only exists for 32 bit kernels */
-
-#define HI_COMMPAGE (intptr_t)0xffff0f00u
-
-static bool init_guest_commpage(void)
-{
- ARMCPU *cpu = ARM_CPU(thread_cpu);
- int host_page_size = qemu_real_host_page_size();
- abi_ptr commpage;
- void *want;
- void *addr;
-
- /*
- * M-profile allocates maximum of 2GB address space, so can never
- * allocate the commpage. Skip it.
- */
- if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
- return true;
- }
-
- commpage = HI_COMMPAGE & -host_page_size;
- want = g2h_untagged(commpage);
- addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE,
- MAP_ANONYMOUS | MAP_PRIVATE |
- (commpage < reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE),
- -1, 0);
-
- if (addr == MAP_FAILED) {
- perror("Allocating guest commpage");
- exit(EXIT_FAILURE);
- }
- if (addr != want) {
- return false;
- }
-
- /* Set kernel helper versions; rest of page is 0. */
- __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu));
-
- if (mprotect(addr, host_page_size, PROT_READ)) {
- perror("Protecting guest commpage");
- exit(EXIT_FAILURE);
- }
-
- page_set_flags(commpage, commpage | (host_page_size - 1),
- PAGE_READ | PAGE_EXEC | PAGE_VALID);
- return true;
-}
-
-#if TARGET_BIG_ENDIAN
-#include "elf.h"
-#include "vdso-be8.c.inc"
-#include "vdso-be32.c.inc"
-
-static const VdsoImageInfo *vdso_image_info(uint32_t elf_flags)
-{
- return (EF_ARM_EABI_VERSION(elf_flags) >= EF_ARM_EABI_VER4
- && (elf_flags & EF_ARM_BE8)
- ? &vdso_be8_image_info
- : &vdso_be32_image_info);
-}
-#define vdso_image_info vdso_image_info
-#else
-# define VDSO_HEADER "vdso-le.c.inc"
-#endif
-
-#else
-/* 64 bit ARM definitions */
-
-#define ELF_ARCH EM_AARCH64
-#define ELF_CLASS ELFCLASS64
-
-#define ELF_NREG 34
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs,
- const CPUARMState *env)
-{
- int i;
-
- for (i = 0; i < 32; i++) {
- (*regs)[i] = tswapreg(env->xregs[i]);
- }
- (*regs)[32] = tswapreg(env->pc);
- (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env));
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#if TARGET_BIG_ENDIAN
-# define VDSO_HEADER "vdso-be.c.inc"
-#else
-# define VDSO_HEADER "vdso-le.c.inc"
-#endif
-
-#endif /* not TARGET_AARCH64 */
-
-#endif /* TARGET_ARM */
-
-#ifdef TARGET_SPARC
-
-#ifndef TARGET_SPARC64
-# define ELF_CLASS ELFCLASS32
-# define ELF_ARCH EM_SPARC
-#elif defined(TARGET_ABI32)
-# define ELF_CLASS ELFCLASS32
-# define elf_check_arch(x) ((x) == EM_SPARC32PLUS || (x) == EM_SPARC)
-#else
-# define ELF_CLASS ELFCLASS64
-# define ELF_ARCH EM_SPARCV9
-#endif
-
-#endif /* TARGET_SPARC */
-
-#ifdef TARGET_PPC
-
-#define ELF_MACHINE PPC_ELF_MACHINE
-
-#if defined(TARGET_PPC64)
-
-#define elf_check_arch(x) ( (x) == EM_PPC64 )
-
-#define ELF_CLASS ELFCLASS64
-
-#else
-
-#define ELF_CLASS ELFCLASS32
-#define EXSTACK_DEFAULT true
-
-#endif
-
-#define ELF_ARCH EM_PPC
-
-/*
- * The requirements here are:
- * - keep the final alignment of sp (sp & 0xf)
- * - make sure the 32-bit value at the first 16 byte aligned position of
- * AUXV is greater than 16 for glibc compatibility.
- * AT_IGNOREPPC is used for that.
- * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
- * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
- */
-#define DLINFO_ARCH_ITEMS 5
-#define ARCH_DLINFO \
- do { \
- PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); \
- /* \
- * Handle glibc compatibility: these magic entries must \
- * be at the lowest addresses in the final auxv. \
- */ \
- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
- NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \
- NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \
- NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
- } while (0)
-
-/* See linux kernel: arch/powerpc/include/asm/elf.h. */
-#define ELF_NREG 48
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env)
-{
- int i;
- target_ulong ccr = 0;
-
- for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
- (*regs)[i] = tswapreg(env->gpr[i]);
- }
-
- (*regs)[32] = tswapreg(env->nip);
- (*regs)[33] = tswapreg(env->msr);
- (*regs)[35] = tswapreg(env->ctr);
- (*regs)[36] = tswapreg(env->lr);
- (*regs)[37] = tswapreg(cpu_read_xer(env));
-
- ccr = ppc_get_cr(env);
- (*regs)[38] = tswapreg(ccr);
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#ifndef TARGET_PPC64
-# define VDSO_HEADER "vdso-32.c.inc"
-#elif TARGET_BIG_ENDIAN
-# define VDSO_HEADER "vdso-64.c.inc"
-#else
-# define VDSO_HEADER "vdso-64le.c.inc"
-#endif
-
-#endif
-
-#ifdef TARGET_LOONGARCH64
-
-#define ELF_CLASS ELFCLASS64
-#define ELF_ARCH EM_LOONGARCH
-#define EXSTACK_DEFAULT true
-
-#define elf_check_arch(x) ((x) == EM_LOONGARCH)
-
-#define VDSO_HEADER "vdso.c.inc"
-
-/* See linux kernel: arch/loongarch/include/asm/elf.h */
-#define ELF_NREG 45
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-enum {
- TARGET_EF_R0 = 0,
- TARGET_EF_CSR_ERA = TARGET_EF_R0 + 33,
- TARGET_EF_CSR_BADV = TARGET_EF_R0 + 34,
-};
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs,
- const CPULoongArchState *env)
-{
- int i;
-
- (*regs)[TARGET_EF_R0] = 0;
-
- for (i = 1; i < ARRAY_SIZE(env->gpr); i++) {
- (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]);
- }
-
- (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc);
- (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV);
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#endif /* TARGET_LOONGARCH64 */
-
-#ifdef TARGET_MIPS
-
-#ifdef TARGET_MIPS64
-#define ELF_CLASS ELFCLASS64
-#else
-#define ELF_CLASS ELFCLASS32
-#endif
-#define ELF_ARCH EM_MIPS
-#define EXSTACK_DEFAULT true
-
-#ifdef TARGET_ABI_MIPSN32
-#define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
-#else
-#define elf_check_abi(x) (!((x) & EF_MIPS_ABI2))
-#endif
-
-/* See linux kernel: arch/mips/include/asm/elf.h. */
-#define ELF_NREG 45
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-/* See linux kernel: arch/mips/include/asm/reg.h. */
-enum {
-#ifdef TARGET_MIPS64
- TARGET_EF_R0 = 0,
-#else
- TARGET_EF_R0 = 6,
-#endif
- TARGET_EF_R26 = TARGET_EF_R0 + 26,
- TARGET_EF_R27 = TARGET_EF_R0 + 27,
- TARGET_EF_LO = TARGET_EF_R0 + 32,
- TARGET_EF_HI = TARGET_EF_R0 + 33,
- TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
- TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
- TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
- TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
-};
-
-/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env)
-{
- int i;
-
- for (i = 0; i < TARGET_EF_R0; i++) {
- (*regs)[i] = 0;
- }
- (*regs)[TARGET_EF_R0] = 0;
-
- for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
- (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]);
- }
-
- (*regs)[TARGET_EF_R26] = 0;
- (*regs)[TARGET_EF_R27] = 0;
- (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]);
- (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]);
- (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC);
- (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr);
- (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status);
- (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause);
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#endif /* TARGET_MIPS */
-
-#ifdef TARGET_MICROBLAZE
-
-#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_MICROBLAZE
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#define USE_ELF_CORE_DUMP
-#define ELF_NREG 38
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env)
-{
- int i, pos = 0;
-
- for (i = 0; i < 32; i++) {
- (*regs)[pos++] = tswapreg(env->regs[i]);
- }
-
- (*regs)[pos++] = tswapreg(env->pc);
- (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env));
- (*regs)[pos++] = 0;
- (*regs)[pos++] = tswapreg(env->ear);
- (*regs)[pos++] = 0;
- (*regs)[pos++] = tswapreg(env->esr);
-}
-
-#endif /* TARGET_MICROBLAZE */
-
-#ifdef TARGET_OPENRISC
-
-#define ELF_ARCH EM_OPENRISC
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 8192
-
-/* See linux kernel arch/openrisc/include/asm/elf.h. */
-#define ELF_NREG 34 /* gprs and pc, sr */
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs,
- const CPUOpenRISCState *env)
-{
- int i;
-
- for (i = 0; i < 32; i++) {
- (*regs)[i] = tswapreg(cpu_get_gpr(env, i));
- }
- (*regs)[32] = tswapreg(env->pc);
- (*regs)[33] = tswapreg(cpu_get_sr(env));
-}
-
-#endif /* TARGET_OPENRISC */
-
-#ifdef TARGET_SH4
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_SH
-
-/* See linux kernel: arch/sh/include/asm/elf.h. */
-#define ELF_NREG 23
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-/* See linux kernel: arch/sh/include/asm/ptrace.h. */
-enum {
- TARGET_REG_PC = 16,
- TARGET_REG_PR = 17,
- TARGET_REG_SR = 18,
- TARGET_REG_GBR = 19,
- TARGET_REG_MACH = 20,
- TARGET_REG_MACL = 21,
- TARGET_REG_SYSCALL = 22
-};
-
-static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
- const CPUSH4State *env)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- (*regs)[i] = tswapreg(env->gregs[i]);
- }
-
- (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
- (*regs)[TARGET_REG_PR] = tswapreg(env->pr);
- (*regs)[TARGET_REG_SR] = tswapreg(env->sr);
- (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr);
- (*regs)[TARGET_REG_MACH] = tswapreg(env->mach);
- (*regs)[TARGET_REG_MACL] = tswapreg(env->macl);
- (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#endif
-
-#ifdef TARGET_M68K
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_68K
-
-/* See linux kernel: arch/m68k/include/asm/elf.h. */
-#define ELF_NREG 20
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env)
-{
- (*regs)[0] = tswapreg(env->dregs[1]);
- (*regs)[1] = tswapreg(env->dregs[2]);
- (*regs)[2] = tswapreg(env->dregs[3]);
- (*regs)[3] = tswapreg(env->dregs[4]);
- (*regs)[4] = tswapreg(env->dregs[5]);
- (*regs)[5] = tswapreg(env->dregs[6]);
- (*regs)[6] = tswapreg(env->dregs[7]);
- (*regs)[7] = tswapreg(env->aregs[0]);
- (*regs)[8] = tswapreg(env->aregs[1]);
- (*regs)[9] = tswapreg(env->aregs[2]);
- (*regs)[10] = tswapreg(env->aregs[3]);
- (*regs)[11] = tswapreg(env->aregs[4]);
- (*regs)[12] = tswapreg(env->aregs[5]);
- (*regs)[13] = tswapreg(env->aregs[6]);
- (*regs)[14] = tswapreg(env->dregs[0]);
- (*regs)[15] = tswapreg(env->aregs[7]);
- (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */
- (*regs)[17] = tswapreg(env->sr);
- (*regs)[18] = tswapreg(env->pc);
- (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 8192
-
-#endif
-
-#ifdef TARGET_ALPHA
-
-#define ELF_CLASS ELFCLASS64
-#define ELF_ARCH EM_ALPHA
-
-#define ELF_EXEC_PAGESIZE 8192
-
-#endif /* TARGET_ALPHA */
-
-#ifdef TARGET_S390X
-
-#define ELF_CLASS ELFCLASS64
-#define ELF_DATA ELFDATA2MSB
-#define ELF_ARCH EM_S390
-
-/* See linux kernel: arch/s390/include/uapi/asm/ptrace.h (s390_regs). */
-#define ELF_NREG 27
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-enum {
- TARGET_REG_PSWM = 0,
- TARGET_REG_PSWA = 1,
- TARGET_REG_GPRS = 2,
- TARGET_REG_ARS = 18,
- TARGET_REG_ORIG_R2 = 26,
-};
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs,
- const CPUS390XState *env)
-{
- int i;
- uint32_t *aregs;
-
- (*regs)[TARGET_REG_PSWM] = tswapreg(env->psw.mask);
- (*regs)[TARGET_REG_PSWA] = tswapreg(env->psw.addr);
- for (i = 0; i < 16; i++) {
- (*regs)[TARGET_REG_GPRS + i] = tswapreg(env->regs[i]);
- }
- aregs = (uint32_t *)&((*regs)[TARGET_REG_ARS]);
- for (i = 0; i < 16; i++) {
- aregs[i] = tswap32(env->aregs[i]);
- }
- (*regs)[TARGET_REG_ORIG_R2] = 0;
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#define VDSO_HEADER "vdso.c.inc"
-
-#endif /* TARGET_S390X */
-
-#ifdef TARGET_RISCV
-
-#define ELF_ARCH EM_RISCV
-
-#ifdef TARGET_RISCV32
-#define ELF_CLASS ELFCLASS32
-#define VDSO_HEADER "vdso-32.c.inc"
-#else
-#define ELF_CLASS ELFCLASS64
-#define VDSO_HEADER "vdso-64.c.inc"
-#endif
-
-#define ELF_EXEC_PAGESIZE 4096
-
-#endif /* TARGET_RISCV */
-
-#ifdef TARGET_HPPA
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_PARISC
-#define STACK_GROWS_DOWN 0
-#define STACK_ALIGNMENT 64
-
-#define VDSO_HEADER "vdso.c.inc"
-
-#define LO_COMMPAGE 0
-
-static bool init_guest_commpage(void)
-{
- /* If reserved_va, then we have already mapped 0 page on the host. */
- if (!reserved_va) {
- void *want, *addr;
-
- want = g2h_untagged(LO_COMMPAGE);
- addr = mmap(want, TARGET_PAGE_SIZE, PROT_NONE,
- MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
- if (addr == MAP_FAILED) {
- perror("Allocating guest commpage");
- exit(EXIT_FAILURE);
- }
- if (addr != want) {
- return false;
- }
- }
-
- /*
- * On Linux, page zero is normally marked execute only + gateway.
- * Normal read or write is supposed to fail (thus PROT_NONE above),
- * but specific offsets have kernel code mapped to raise permissions
- * and implement syscalls. Here, simply mark the page executable.
- * Special case the entry points during translation (see do_page_zero).
- */
- page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
- PAGE_EXEC | PAGE_VALID);
- return true;
-}
-
-#endif /* TARGET_HPPA */
-
-#ifdef TARGET_XTENSA
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_XTENSA
-
-/* See linux kernel: arch/xtensa/include/asm/elf.h. */
-#define ELF_NREG 128
-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
-
-enum {
- TARGET_REG_PC,
- TARGET_REG_PS,
- TARGET_REG_LBEG,
- TARGET_REG_LEND,
- TARGET_REG_LCOUNT,
- TARGET_REG_SAR,
- TARGET_REG_WINDOWSTART,
- TARGET_REG_WINDOWBASE,
- TARGET_REG_THREADPTR,
- TARGET_REG_AR0 = 64,
-};
-
-static void elf_core_copy_regs(target_elf_gregset_t *regs,
- const CPUXtensaState *env)
-{
- unsigned i;
-
- (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
- (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM);
- (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]);
- (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]);
- (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]);
- (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]);
- (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]);
- (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]);
- (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]);
- xtensa_sync_phys_from_window((CPUXtensaState *)env);
- for (i = 0; i < env->config->nareg; ++i) {
- (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]);
- }
-}
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE 4096
-
-#endif /* TARGET_XTENSA */
-
-#ifdef TARGET_HEXAGON
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_ARCH EM_HEXAGON
-
-#endif /* TARGET_HEXAGON */
-
-#ifndef ELF_MACHINE
-#define ELF_MACHINE ELF_ARCH
-#endif
-
-#ifndef elf_check_arch
-#define elf_check_arch(x) ((x) == ELF_ARCH)
+#ifndef elf_check_machine
+#define elf_check_machine(x) ((x) == ELF_MACHINE)
#endif
#ifndef elf_check_abi
@@ -974,59 +166,17 @@ const char *get_elf_platform(CPUState *cs) { return NULL; }
const char *get_elf_base_platform(CPUState *cs) { return NULL; }
#endif
-#include "elf.h"
-
-/* We must delay the following stanzas until after "elf.h". */
-#if defined(TARGET_AARCH64)
-
-static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
- const uint32_t *data,
- struct image_info *info,
- Error **errp)
-{
- if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
- if (pr_datasz != sizeof(uint32_t)) {
- error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
- return false;
- }
- /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
- info->note_flags = *data;
- }
- return true;
-}
-#define ARCH_USE_GNU_PROPERTY 1
-
-#else
-
-static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
- const uint32_t *data,
- struct image_info *info,
- Error **errp)
+#ifndef HAVE_ELF_GNU_PROPERTY
+bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
+ const uint32_t *data, struct image_info *info,
+ Error **errp)
{
g_assert_not_reached();
}
-#define ARCH_USE_GNU_PROPERTY 0
-
+#define HAVE_ELF_GNU_PROPERTY 0
#endif
-struct exec
-{
- unsigned int a_info; /* Use macros N_MAGIC, etc for access */
- unsigned int a_text; /* length of text, in bytes */
- unsigned int a_data; /* length of data, in bytes */
- unsigned int a_bss; /* length of uninitialized data area, in bytes */
- unsigned int a_syms; /* length of symbol table data in file, in bytes */
- unsigned int a_entry; /* start address */
- unsigned int a_trsize; /* length of relocation info for text, in bytes */
- unsigned int a_drsize; /* length of relocation info for data, in bytes */
-};
-
-
-#define N_MAGIC(exec) ((exec).a_info & 0xffff)
-#define OMAGIC 0407
-#define NMAGIC 0410
-#define ZMAGIC 0413
-#define QMAGIC 0314
+#include "elf.h"
#define DLINFO_ITEMS 16
@@ -1121,9 +271,9 @@ static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags)
}
#endif
-#ifdef USE_ELF_CORE_DUMP
+#ifdef HAVE_ELF_CORE_DUMP
static int elf_core_dump(int, const CPUArchState *);
-#endif /* USE_ELF_CORE_DUMP */
+#endif /* HAVE_ELF_CORE_DUMP */
static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
abi_ulong load_bias);
@@ -1144,7 +294,7 @@ static bool elf_check_ident(struct elfhdr *ehdr)
This has to wait until after bswapping the header. */
static bool elf_check_ehdr(struct elfhdr *ehdr)
{
- return (elf_check_arch(ehdr->e_machine)
+ return (elf_check_machine(ehdr->e_machine)
&& elf_check_abi(ehdr->e_flags)
&& ehdr->e_ehsize == sizeof(struct elfhdr)
&& ehdr->e_phentsize == sizeof(struct elf_phdr)
@@ -1605,8 +755,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
#else
#define HI_COMMPAGE 0
#define LO_COMMPAGE -1
-#ifndef INIT_GUEST_COMMPAGE
-#define init_guest_commpage() true
+#ifndef HAVE_GUEST_COMMPAGE
+bool init_guest_commpage(void) { return true; }
#endif
#endif
@@ -2041,7 +1191,7 @@ static bool parse_elf_properties(const ImageSource *src,
uint32_t prev_type;
/* Unless the arch requires properties, ignore them. */
- if (!ARCH_USE_GNU_PROPERTY) {
+ if (!HAVE_ELF_GNU_PROPERTY) {
return true;
}
@@ -2464,14 +1614,17 @@ static void load_elf_interp(const char *filename, struct image_info *info,
load_elf_image(filename, &src, info, &ehdr, NULL);
}
-#ifndef vdso_image_info
+#ifndef HAVE_VDSO_IMAGE_INFO
+const VdsoImageInfo *get_vdso_image_info(uint32_t elf_flags)
+{
#ifdef VDSO_HEADER
#include VDSO_HEADER
-#define vdso_image_info(flags) &vdso_image_info
+ return &vdso_image_info;
#else
-#define vdso_image_info(flags) NULL
-#endif /* VDSO_HEADER */
-#endif /* vdso_image_info */
+ return NULL;
+#endif
+}
+#endif /* HAVE_VDSO_IMAGE_INFO */
static void load_elf_vdso(struct image_info *info, const VdsoImageInfo *vdso)
{
@@ -2802,7 +1955,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
* Load a vdso if available, which will amongst other things contain the
* signal trampolines. Otherwise, allocate a separate page for them.
*/
- const VdsoImageInfo *vdso = vdso_image_info(info->elf_flags);
+ const VdsoImageInfo *vdso = get_vdso_image_info(info->elf_flags);
if (vdso) {
load_elf_vdso(&vdso_info, vdso);
info->vdso = vdso_info.load_bias;
@@ -2833,14 +1986,14 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
g_free(elf_interpreter);
}
-#ifdef USE_ELF_CORE_DUMP
+#ifdef HAVE_ELF_CORE_DUMP
bprm->core_dump = &elf_core_dump;
#endif
return 0;
}
-#ifdef USE_ELF_CORE_DUMP
+#ifdef HAVE_ELF_CORE_DUMP
/*
* Definitions to generate Intel SVR4-like core files.
@@ -2856,23 +2009,18 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
* Core dump code is copied from linux kernel (fs/binfmt_elf.c).
*
* Porting ELF coredump for target is (quite) simple process. First you
- * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
+ * define HAVE_ELF_CORE_DUMP in target ELF code (where init_thread() for
* the target resides):
*
- * #define USE_ELF_CORE_DUMP
- *
- * Next you define type of register set used for dumping. ELF specification
- * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
+ * #define HAVE_ELF_CORE_DUMP
*
- * typedef <target_regtype> target_elf_greg_t;
- * #define ELF_NREG <number of registers>
- * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
+ * Next you define type of register set used for dumping:
+ * typedef struct target_elf_gregset_t { ... } target_elf_gregset_t;
*
* Last step is to implement target specific function that copies registers
* from given cpu into just specified register set. Prototype is:
*
- * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
- * const CPUArchState *env);
+ * void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUArchState *env);
*
* Parameters:
* regs - copy register values into here (allocated and zeroed by caller)
@@ -3216,7 +2364,7 @@ static int wmr_fill_region_phdr(void *opaque, vaddr start,
phdr->p_flags = (flags & PAGE_READ ? PF_R : 0)
| (flags & PAGE_WRITE_ORG ? PF_W : 0)
| (flags & PAGE_EXEC ? PF_X : 0);
- phdr->p_align = ELF_EXEC_PAGESIZE;
+ phdr->p_align = TARGET_PAGE_SIZE;
bswap_phdr(phdr, 1);
d->phdr = phdr + 1;
@@ -3324,7 +2472,7 @@ static int elf_core_dump(int signr, const CPUArchState *env)
offset += size_note("CORE", sizeof(struct target_elf_prpsinfo));
offset += size_note("CORE", sizeof(struct target_elf_prstatus)) * cpus;
note_size = offset - note_offset;
- data_offset = ROUND_UP(offset, ELF_EXEC_PAGESIZE);
+ data_offset = TARGET_PAGE_ALIGN(offset);
/* Do not dump if the corefile size exceeds the limit. */
if (dumpsize.rlim_cur != RLIM_INFINITY
@@ -3403,4 +2551,4 @@ static int elf_core_dump(int signr, const CPUArchState *env)
}
return ret;
}
-#endif /* USE_ELF_CORE_DUMP */
+#endif /* HAVE_ELF_CORE_DUMP */
diff --git a/linux-user/hexagon/target_elf.h b/linux-user/hexagon/target_elf.h
index eccf207..f81ae38 100644
--- a/linux-user/hexagon/target_elf.h
+++ b/linux-user/hexagon/target_elf.h
@@ -18,4 +18,7 @@
#ifndef HEXAGON_TARGET_ELF_H
#define HEXAGON_TARGET_ELF_H
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_HEXAGON
+
#endif
diff --git a/linux-user/hexagon/target_syscall.h b/linux-user/hexagon/target_syscall.h
index 7f91a4a..d9c9473 100644
--- a/linux-user/hexagon/target_syscall.h
+++ b/linux-user/hexagon/target_syscall.h
@@ -18,11 +18,6 @@
#ifndef HEXAGON_TARGET_SYSCALL_H
#define HEXAGON_TARGET_SYSCALL_H
-struct target_pt_regs {
- abi_long sepc;
- abi_long sp;
-};
-
#define UNAME_MACHINE "hexagon"
#define UNAME_MINIMUM_RELEASE "4.15.0"
diff --git a/linux-user/hppa/elfload.c b/linux-user/hppa/elfload.c
index 9dd3fe0..018034f 100644
--- a/linux-user/hppa/elfload.c
+++ b/linux-user/hppa/elfload.c
@@ -3,6 +3,7 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -14,3 +15,33 @@ const char *get_elf_platform(CPUState *cs)
{
return "PARISC";
}
+
+bool init_guest_commpage(void)
+{
+ /* If reserved_va, then we have already mapped 0 page on the host. */
+ if (!reserved_va) {
+ void *want, *addr;
+
+ want = g2h_untagged(LO_COMMPAGE);
+ addr = mmap(want, TARGET_PAGE_SIZE, PROT_NONE,
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
+ if (addr == MAP_FAILED) {
+ perror("Allocating guest commpage");
+ exit(EXIT_FAILURE);
+ }
+ if (addr != want) {
+ return false;
+ }
+ }
+
+ /*
+ * On Linux, page zero is normally marked execute only + gateway.
+ * Normal read or write is supposed to fail (thus PROT_NONE above),
+ * but specific offsets have kernel code mapped to raise permissions
+ * and implement syscalls. Here, simply mark the page executable.
+ * Special case the entry points during translation (see do_page_zero).
+ */
+ page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
+ PAGE_EXEC | PAGE_VALID);
+ return true;
+}
diff --git a/linux-user/hppa/target_elf.h b/linux-user/hppa/target_elf.h
index 85be005..76930c9 100644
--- a/linux-user/hppa/target_elf.h
+++ b/linux-user/hppa/target_elf.h
@@ -8,6 +8,14 @@
#ifndef HPPA_TARGET_ELF_H
#define HPPA_TARGET_ELF_H
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_PARISC
+
#define HAVE_ELF_PLATFORM 1
+#define LO_COMMPAGE 0
+#define STACK_GROWS_DOWN 0
+#define STACK_ALIGNMENT 64
+#define VDSO_HEADER "vdso.c.inc"
+
#endif
diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h
index 9a8f8ca..4b21e85 100644
--- a/linux-user/hppa/target_syscall.h
+++ b/linux-user/hppa/target_syscall.h
@@ -1,24 +1,6 @@
#ifndef HPPA_TARGET_SYSCALL_H
#define HPPA_TARGET_SYSCALL_H
-struct target_pt_regs {
- target_ulong gr[32];
- uint64_t fr[32];
- target_ulong sr[8];
- target_ulong iasq[2];
- target_ulong iaoq[2];
- target_ulong cr27;
- target_ulong __pad0;
- target_ulong orig_r28;
- target_ulong ksp;
- target_ulong kpc;
- target_ulong sar;
- target_ulong iir;
- target_ulong isr;
- target_ulong ior;
- target_ulong ipsw;
-};
-
#define UNAME_MACHINE "parisc"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/i386/elfload.c b/linux-user/i386/elfload.c
index ef3a6c3..26b1200 100644
--- a/linux-user/i386/elfload.c
+++ b/linux-user/i386/elfload.c
@@ -3,6 +3,7 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -23,3 +24,24 @@ const char *get_elf_platform(CPUState *cs)
family = MAX(MIN(family, 6), 3);
return elf_platform[family - 3];
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUX86State *env)
+{
+ r->pt.bx = tswapal(env->regs[R_EBX]);
+ r->pt.cx = tswapal(env->regs[R_ECX]);
+ r->pt.dx = tswapal(env->regs[R_EDX]);
+ r->pt.si = tswapal(env->regs[R_ESI]);
+ r->pt.di = tswapal(env->regs[R_EDI]);
+ r->pt.bp = tswapal(env->regs[R_EBP]);
+ r->pt.ax = tswapal(env->regs[R_EAX]);
+ r->pt.ds = tswapal(env->segs[R_DS].selector & 0xffff);
+ r->pt.es = tswapal(env->segs[R_ES].selector & 0xffff);
+ r->pt.fs = tswapal(env->segs[R_FS].selector & 0xffff);
+ r->pt.gs = tswapal(env->segs[R_GS].selector & 0xffff);
+ r->pt.orig_ax = tswapal(get_task_state(env_cpu_const(env))->orig_ax);
+ r->pt.ip = tswapal(env->eip);
+ r->pt.cs = tswapal(env->segs[R_CS].selector & 0xffff);
+ r->pt.flags = tswapal(env->eflags);
+ r->pt.sp = tswapal(env->regs[R_ESP]);
+ r->pt.ss = tswapal(env->segs[R_SS].selector & 0xffff);
+}
diff --git a/linux-user/i386/target_elf.h b/linux-user/i386/target_elf.h
index 44dde1a..eafac8f 100644
--- a/linux-user/i386/target_elf.h
+++ b/linux-user/i386/target_elf.h
@@ -8,7 +8,40 @@
#ifndef I386_TARGET_ELF_H
#define I386_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_386
+#define EXSTACK_DEFAULT true
+#define VDSO_HEADER "vdso.c.inc"
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/x86/include/asm/elf.h, where elf_gregset_t
+ * is mapped to struct user_regs_struct via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_user_regs_struct pt;
+} target_elf_gregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_machine(x) ((x) == EM_386 || (x) == EM_486)
+
+/*
+ * i386 is the only target which supplies AT_SYSINFO for the vdso.
+ * All others only supply AT_SYSINFO_EHDR.
+ */
+#define DLINFO_ARCH_ITEMS (vdso_info != NULL)
+#define ARCH_DLINFO \
+ do { \
+ if (vdso_info) { \
+ NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry); \
+ } \
+ } while (0)
#endif
diff --git a/linux-user/i386/target_ptrace.h b/linux-user/i386/target_ptrace.h
new file mode 100644
index 0000000..bc57926
--- /dev/null
+++ b/linux-user/i386/target_ptrace.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef I386_TARGET_PTRACE_H
+#define I386_TARGET_PTRACE_H
+
+/*
+ * Note that arch/x86/include/uapi/asm/ptrace.h (struct pt_regs) and
+ * arch/x86/include/asm/user_32.h (struct user_regs_struct) have the
+ * same layout, though the exact types differ (int vs long vs unsigned).
+ * Define user_regs_struct because that's what's actually used.
+ */
+struct target_user_regs_struct {
+ abi_ulong bx;
+ abi_ulong cx;
+ abi_ulong dx;
+ abi_ulong si;
+ abi_ulong di;
+ abi_ulong bp;
+ abi_ulong ax;
+ abi_ulong ds;
+ abi_ulong es;
+ abi_ulong fs;
+ abi_ulong gs;
+ abi_ulong orig_ax;
+ abi_ulong ip;
+ abi_ulong cs;
+ abi_ulong flags;
+ abi_ulong sp;
+ abi_ulong ss;
+};
+
+#endif /* I386_TARGET_PTRACE_H */
diff --git a/linux-user/i386/target_syscall.h b/linux-user/i386/target_syscall.h
index aaade06..c214a90 100644
--- a/linux-user/i386/target_syscall.h
+++ b/linux-user/i386/target_syscall.h
@@ -5,24 +5,6 @@
#define __USER_CS (0x23)
#define __USER_DS (0x2B)
-struct target_pt_regs {
- long ebx;
- long ecx;
- long edx;
- long esi;
- long edi;
- long ebp;
- long eax;
- int xds;
- int xes;
- long orig_eax;
- long eip;
- int xcs;
- long eflags;
- long esp;
- int xss;
-};
-
/* ioctls */
#define TARGET_LDT_ENTRIES 8192
diff --git a/linux-user/loader.h b/linux-user/loader.h
index 6482c7c..e42b8fa 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -105,5 +105,26 @@ const char *elf_hwcap_str(uint32_t bit);
const char *elf_hwcap2_str(uint32_t bit);
const char *get_elf_platform(CPUState *cs);
const char *get_elf_base_platform(CPUState *cs);
+bool init_guest_commpage(void);
+
+struct target_elf_gregset_t;
+void elf_core_copy_regs(struct target_elf_gregset_t *, const CPUArchState *);
+
+typedef struct {
+ const uint8_t *image;
+ const uint32_t *relocs;
+ unsigned image_size;
+ unsigned reloc_count;
+ unsigned sigreturn_ofs;
+ unsigned rt_sigreturn_ofs;
+} VdsoImageInfo;
+
+/* Note that both Elf32_Word and Elf64_Word are uint32_t. */
+const VdsoImageInfo *get_vdso_image_info(uint32_t elf_flags);
+
+bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
+ const uint32_t *data,
+ struct image_info *info,
+ Error **errp);
#endif /* LINUX_USER_LOADER_H */
diff --git a/linux-user/loongarch64/elfload.c b/linux-user/loongarch64/elfload.c
index 9113528..ce3bd0c 100644
--- a/linux-user/loongarch64/elfload.c
+++ b/linux-user/loongarch64/elfload.c
@@ -3,6 +3,7 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -61,3 +62,17 @@ const char *get_elf_platform(CPUState *cs)
{
return "loongarch";
}
+
+#define tswapreg(ptr) tswapal(ptr)
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPULoongArchState *env)
+{
+ r->pt.regs[0] = 0;
+
+ for (int i = 1; i < ARRAY_SIZE(env->gpr); i++) {
+ r->pt.regs[i] = tswapreg(env->gpr[i]);
+ }
+
+ r->pt.csr_era = tswapreg(env->pc);
+ r->pt.csr_badv = tswapreg(env->CSR_BADV);
+}
diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h
index eb17927..3aa8c83 100644
--- a/linux-user/loongarch64/target_elf.h
+++ b/linux-user/loongarch64/target_elf.h
@@ -6,7 +6,20 @@
#ifndef LOONGARCH_TARGET_ELF_H
#define LOONGARCH_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_MACHINE EM_LOONGARCH
+#define EXSTACK_DEFAULT true
+#define VDSO_HEADER "vdso.c.inc"
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/* See linux kernel: arch/loongarch/include/asm/elf.h */
+typedef struct target_elf_gregset_t {
+ struct target_user_pt_regs pt;
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/loongarch64/target_ptrace.h b/linux-user/loongarch64/target_ptrace.h
new file mode 100644
index 0000000..2578e09
--- /dev/null
+++ b/linux-user/loongarch64/target_ptrace.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef LOONGARCH64_TARGET_PTRACE_H
+#define LOONGARCH64_TARGET_PTRACE_H
+
+/* See arch/loongarch/include/uapi/asm/ptrace.h. */
+struct target_user_pt_regs {
+ abi_ulong regs[32];
+ abi_ulong orig_a0;
+ abi_ulong csr_era;
+ abi_ulong csr_badv;
+ abi_ulong reserved[10];
+};
+
+#endif /* LOONGARCH64_TARGET_PTRACE_H */
diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h
index 39f229b..f7ced7b 100644
--- a/linux-user/loongarch64/target_syscall.h
+++ b/linux-user/loongarch64/target_syscall.h
@@ -8,29 +8,6 @@
#include "qemu/units.h"
-/*
- * this struct defines the way the registers are stored on the
- * stack during a system call.
- */
-
-struct target_pt_regs {
- /* Saved main processor registers. */
- target_ulong regs[32];
-
- /* Saved special registers. */
- struct {
- target_ulong era;
- target_ulong badv;
- target_ulong crmd;
- target_ulong prmd;
- target_ulong euen;
- target_ulong ecfg;
- target_ulong estat;
- } csr;
- target_ulong orig_a0;
- target_ulong __last[0];
-};
-
#define UNAME_MACHINE "loongarch64"
#define UNAME_MINIMUM_RELEASE "5.19.0"
diff --git a/linux-user/m68k/elfload.c b/linux-user/m68k/elfload.c
index 561ac5b..423d1f6 100644
--- a/linux-user/m68k/elfload.c
+++ b/linux-user/m68k/elfload.c
@@ -4,6 +4,7 @@
#include "qemu.h"
#include "loader.h"
#include "elf.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -16,3 +17,27 @@ const char *get_elf_cpu_model(uint32_t eflags)
/* Coldfire */
return "any";
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUM68KState *env)
+{
+ r->d1 = tswapal(env->dregs[1]);
+ r->d2 = tswapal(env->dregs[2]);
+ r->d3 = tswapal(env->dregs[3]);
+ r->d4 = tswapal(env->dregs[4]);
+ r->d5 = tswapal(env->dregs[5]);
+ r->d6 = tswapal(env->dregs[6]);
+ r->d7 = tswapal(env->dregs[7]);
+ r->a0 = tswapal(env->aregs[0]);
+ r->a1 = tswapal(env->aregs[1]);
+ r->a2 = tswapal(env->aregs[2]);
+ r->a3 = tswapal(env->aregs[3]);
+ r->a4 = tswapal(env->aregs[4]);
+ r->a5 = tswapal(env->aregs[5]);
+ r->a6 = tswapal(env->aregs[6]);
+ r->d0 = tswapal(env->dregs[0]);
+ r->usp = tswapal(env->aregs[7]);
+ r->orig_d0 = tswapal(env->dregs[0]); /* FIXME */
+ r->sr = tswapal(env->sr);
+ r->pc = tswapal(env->pc);
+ /* FIXME: regs->format | regs->vector */
+}
diff --git a/linux-user/m68k/target_elf.h b/linux-user/m68k/target_elf.h
index 62ff9d3..b997fa0 100644
--- a/linux-user/m68k/target_elf.h
+++ b/linux-user/m68k/target_elf.h
@@ -8,4 +8,31 @@
#ifndef M68K_TARGET_ELF_H
#define M68K_TARGET_ELF_H
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_68K
+
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/m68k/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct user_regs_struct via sizeof.
+ *
+ * Note that user_regs_struct has
+ * short stkadj, sr;
+ * ...
+ * short fmtvec, __fill;
+ * but ELF_CORE_COPY_REGS writes to unsigned longs.
+ * Therefore adjust the sr and fmtvec fields to match.
+ */
+typedef struct target_elf_gregset_t {
+ abi_ulong d1, d2, d3, d4, d5, d6, d7;
+ abi_ulong a0, a1, a2, a3, a4, a5, a6;
+ abi_ulong d0;
+ abi_ulong usp;
+ abi_ulong orig_d0;
+ abi_ulong sr;
+ abi_ulong pc;
+ abi_ulong fmtvec;
+} target_elf_gregset_t;
+
#endif
diff --git a/linux-user/m68k/target_syscall.h b/linux-user/m68k/target_syscall.h
index 8d4ddbd..3ca0231 100644
--- a/linux-user/m68k/target_syscall.h
+++ b/linux-user/m68k/target_syscall.h
@@ -1,22 +1,6 @@
#ifndef M68K_TARGET_SYSCALL_H
#define M68K_TARGET_SYSCALL_H
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
-struct target_pt_regs {
- abi_long d1, d2, d3, d4, d5, d6, d7;
- abi_long a0, a1, a2, a3, a4, a5, a6;
- abi_ulong d0;
- abi_ulong usp;
- abi_ulong orig_d0;
- int16_t stkadj;
- uint16_t sr;
- abi_ulong pc;
- uint16_t fntvex;
- uint16_t __fill;
-};
-
#define UNAME_MACHINE "m68k"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/main.c b/linux-user/main.c
index 6edeeec..7b0ccb6 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -340,16 +340,6 @@ static void handle_arg_ld_prefix(const char *arg)
interp_prefix = strdup(arg);
}
-static void handle_arg_pagesize(const char *arg)
-{
- unsigned size, want = qemu_real_host_page_size();
-
- if (qemu_strtoui(arg, NULL, 10, &size) || size != want) {
- warn_report("Deprecated page size option cannot "
- "change host page size (%u)", want);
- }
-}
-
static void handle_arg_seed(const char *arg)
{
seed_optarg = arg;
@@ -522,8 +512,6 @@ static const struct qemu_argument arg_table[] = {
"range[,...]","filter logging based on address range"},
{"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
"logfile", "write logs to 'logfile' (default stderr)"},
- {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
- "pagesize", "deprecated change to host page size"},
{"one-insn-per-tb",
"QEMU_ONE_INSN_PER_TB", false, handle_arg_one_insn_per_tb,
"", "run with one guest instruction per emulated TB"},
diff --git a/linux-user/microblaze/elfload.c b/linux-user/microblaze/elfload.c
index b92442d..7eb1b26 100644
--- a/linux-user/microblaze/elfload.c
+++ b/linux-user/microblaze/elfload.c
@@ -3,9 +3,22 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
{
return "any";
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUMBState *env)
+{
+ for (int i = 0; i < 32; i++) {
+ r->pt.r[i] = tswapal(env->regs[i]);
+ }
+
+ r->pt.pc = tswapal(env->pc);
+ r->pt.msr = tswapal(mb_cpu_read_msr(env));
+ r->pt.ear = tswapal(env->ear);
+ r->pt.esr = tswapal(env->esr);
+}
diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c
index f6d47d7..e874e4d 100644
--- a/linux-user/microblaze/signal.c
+++ b/linux-user/microblaze/signal.c
@@ -21,6 +21,7 @@
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
+#include "target_ptrace.h"
struct target_sigcontext {
struct target_pt_regs regs; /* needs to be first */
@@ -50,75 +51,17 @@ struct target_rt_sigframe {
static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
{
- __put_user(env->regs[0], &sc->regs.r0);
- __put_user(env->regs[1], &sc->regs.r1);
- __put_user(env->regs[2], &sc->regs.r2);
- __put_user(env->regs[3], &sc->regs.r3);
- __put_user(env->regs[4], &sc->regs.r4);
- __put_user(env->regs[5], &sc->regs.r5);
- __put_user(env->regs[6], &sc->regs.r6);
- __put_user(env->regs[7], &sc->regs.r7);
- __put_user(env->regs[8], &sc->regs.r8);
- __put_user(env->regs[9], &sc->regs.r9);
- __put_user(env->regs[10], &sc->regs.r10);
- __put_user(env->regs[11], &sc->regs.r11);
- __put_user(env->regs[12], &sc->regs.r12);
- __put_user(env->regs[13], &sc->regs.r13);
- __put_user(env->regs[14], &sc->regs.r14);
- __put_user(env->regs[15], &sc->regs.r15);
- __put_user(env->regs[16], &sc->regs.r16);
- __put_user(env->regs[17], &sc->regs.r17);
- __put_user(env->regs[18], &sc->regs.r18);
- __put_user(env->regs[19], &sc->regs.r19);
- __put_user(env->regs[20], &sc->regs.r20);
- __put_user(env->regs[21], &sc->regs.r21);
- __put_user(env->regs[22], &sc->regs.r22);
- __put_user(env->regs[23], &sc->regs.r23);
- __put_user(env->regs[24], &sc->regs.r24);
- __put_user(env->regs[25], &sc->regs.r25);
- __put_user(env->regs[26], &sc->regs.r26);
- __put_user(env->regs[27], &sc->regs.r27);
- __put_user(env->regs[28], &sc->regs.r28);
- __put_user(env->regs[29], &sc->regs.r29);
- __put_user(env->regs[30], &sc->regs.r30);
- __put_user(env->regs[31], &sc->regs.r31);
+ for (int i = 0; i < 32; ++i) {
+ __put_user(env->regs[i], &sc->regs.r[i]);
+ }
__put_user(env->pc, &sc->regs.pc);
}
static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env)
{
- __get_user(env->regs[0], &sc->regs.r0);
- __get_user(env->regs[1], &sc->regs.r1);
- __get_user(env->regs[2], &sc->regs.r2);
- __get_user(env->regs[3], &sc->regs.r3);
- __get_user(env->regs[4], &sc->regs.r4);
- __get_user(env->regs[5], &sc->regs.r5);
- __get_user(env->regs[6], &sc->regs.r6);
- __get_user(env->regs[7], &sc->regs.r7);
- __get_user(env->regs[8], &sc->regs.r8);
- __get_user(env->regs[9], &sc->regs.r9);
- __get_user(env->regs[10], &sc->regs.r10);
- __get_user(env->regs[11], &sc->regs.r11);
- __get_user(env->regs[12], &sc->regs.r12);
- __get_user(env->regs[13], &sc->regs.r13);
- __get_user(env->regs[14], &sc->regs.r14);
- __get_user(env->regs[15], &sc->regs.r15);
- __get_user(env->regs[16], &sc->regs.r16);
- __get_user(env->regs[17], &sc->regs.r17);
- __get_user(env->regs[18], &sc->regs.r18);
- __get_user(env->regs[19], &sc->regs.r19);
- __get_user(env->regs[20], &sc->regs.r20);
- __get_user(env->regs[21], &sc->regs.r21);
- __get_user(env->regs[22], &sc->regs.r22);
- __get_user(env->regs[23], &sc->regs.r23);
- __get_user(env->regs[24], &sc->regs.r24);
- __get_user(env->regs[25], &sc->regs.r25);
- __get_user(env->regs[26], &sc->regs.r26);
- __get_user(env->regs[27], &sc->regs.r27);
- __get_user(env->regs[28], &sc->regs.r28);
- __get_user(env->regs[29], &sc->regs.r29);
- __get_user(env->regs[30], &sc->regs.r30);
- __get_user(env->regs[31], &sc->regs.r31);
+ for (int i = 0; i < 32; ++i) {
+ __get_user(env->regs[i], &sc->regs.r[i]);
+ }
__get_user(env->pc, &sc->regs.pc);
}
diff --git a/linux-user/microblaze/target_elf.h b/linux-user/microblaze/target_elf.h
index bfe2997..7b3ef70 100644
--- a/linux-user/microblaze/target_elf.h
+++ b/linux-user/microblaze/target_elf.h
@@ -8,4 +8,21 @@
#ifndef MICROBLAZE_TARGET_ELF_H
#define MICROBLAZE_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_MICROBLAZE
+
+#define elf_check_machine(x) ((x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
+
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/microblaze/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct pt_regs via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_pt_regs pt;
+} target_elf_gregset_t;
+
#endif
diff --git a/linux-user/microblaze/target_ptrace.h b/linux-user/microblaze/target_ptrace.h
new file mode 100644
index 0000000..ead913e
--- /dev/null
+++ b/linux-user/microblaze/target_ptrace.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef MICROBLAZE_TARGET_PTRACE_H
+#define MICROBLAZE_TARGET_PTRACE_H
+
+/* We use microblaze_reg_t to keep things similar to the kernel sources. */
+typedef uint32_t microblaze_reg_t;
+
+struct target_pt_regs {
+ /* Note the kernel enumerates all 32 registers. */
+ microblaze_reg_t r[32];
+ microblaze_reg_t pc;
+ microblaze_reg_t msr;
+ microblaze_reg_t ear;
+ microblaze_reg_t esr;
+ microblaze_reg_t fsr;
+ uint32_t kernel_mode;
+};
+
+#endif /* MICROBLAZE_TARGET_PTRACE_H */
diff --git a/linux-user/microblaze/target_syscall.h b/linux-user/microblaze/target_syscall.h
index 43362a1..66f5a9e 100644
--- a/linux-user/microblaze/target_syscall.h
+++ b/linux-user/microblaze/target_syscall.h
@@ -4,50 +4,6 @@
#define UNAME_MACHINE "microblaze"
#define UNAME_MINIMUM_RELEASE "2.6.32"
-/* We use microblaze_reg_t to keep things similar to the kernel sources. */
-typedef uint32_t microblaze_reg_t;
-
-struct target_pt_regs {
- microblaze_reg_t r0;
- microblaze_reg_t r1;
- microblaze_reg_t r2;
- microblaze_reg_t r3;
- microblaze_reg_t r4;
- microblaze_reg_t r5;
- microblaze_reg_t r6;
- microblaze_reg_t r7;
- microblaze_reg_t r8;
- microblaze_reg_t r9;
- microblaze_reg_t r10;
- microblaze_reg_t r11;
- microblaze_reg_t r12;
- microblaze_reg_t r13;
- microblaze_reg_t r14;
- microblaze_reg_t r15;
- microblaze_reg_t r16;
- microblaze_reg_t r17;
- microblaze_reg_t r18;
- microblaze_reg_t r19;
- microblaze_reg_t r20;
- microblaze_reg_t r21;
- microblaze_reg_t r22;
- microblaze_reg_t r23;
- microblaze_reg_t r24;
- microblaze_reg_t r25;
- microblaze_reg_t r26;
- microblaze_reg_t r27;
- microblaze_reg_t r28;
- microblaze_reg_t r29;
- microblaze_reg_t r30;
- microblaze_reg_t r31;
- microblaze_reg_t pc;
- microblaze_reg_t msr;
- microblaze_reg_t ear;
- microblaze_reg_t esr;
- microblaze_reg_t fsr;
- uint32_t kernel_mode;
-};
-
#define TARGET_CLONE_BACKWARDS
#define TARGET_MCL_CURRENT 1
#define TARGET_MCL_FUTURE 2
diff --git a/linux-user/mips/elfload.c b/linux-user/mips/elfload.c
index c353ccc..e0c50f5 100644
--- a/linux-user/mips/elfload.c
+++ b/linux-user/mips/elfload.c
@@ -4,6 +4,7 @@
#include "qemu.h"
#include "loader.h"
#include "elf.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -122,3 +123,20 @@ const char *get_elf_base_platform(CPUState *cs)
}
#undef MATCH_PLATFORM_INSN
+
+/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUMIPSState *env)
+{
+ for (int i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
+ r->pt.regs[i] = tswapl(env->active_tc.gpr[i]);
+ }
+
+ r->pt.regs[26] = 0;
+ r->pt.regs[27] = 0;
+ r->pt.lo = tswapl(env->active_tc.LO[0]);
+ r->pt.hi = tswapl(env->active_tc.HI[0]);
+ r->pt.cp0_epc = tswapl(env->active_tc.PC);
+ r->pt.cp0_badvaddr = tswapl(env->CP0_BadVAddr);
+ r->pt.cp0_status = tswapl(env->CP0_Status);
+ r->pt.cp0_cause = tswapl(env->CP0_Cause);
+}
diff --git a/linux-user/mips/target_elf.h b/linux-user/mips/target_elf.h
index 08e699c..157306f 100644
--- a/linux-user/mips/target_elf.h
+++ b/linux-user/mips/target_elf.h
@@ -8,7 +8,22 @@
#ifndef MIPS_TARGET_ELF_H
#define MIPS_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_MIPS
+#define EXSTACK_DEFAULT true
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_BASE_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/* See linux kernel: arch/mips/include/asm/elf.h. */
+typedef struct target_elf_gregset_t {
+ union {
+ abi_ulong reserved[45];
+ struct target_pt_regs pt;
+ };
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/mips/target_ptrace.h b/linux-user/mips/target_ptrace.h
new file mode 100644
index 0000000..2f63b27
--- /dev/null
+++ b/linux-user/mips/target_ptrace.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef MIPS_TARGET_PTRACE_H
+#define MIPS_TARGET_PTRACE_H
+
+struct target_pt_regs {
+ abi_ulong pad0[6];
+ abi_ulong regs[32];
+ abi_ulong lo;
+ abi_ulong hi;
+ abi_ulong cp0_epc;
+ abi_ulong cp0_badvaddr;
+ abi_ulong cp0_status;
+ abi_ulong cp0_cause;
+};
+
+#endif /* MIPS_TARGET_PTRACE_H */
diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h
index 08ead67..dfcdf32 100644
--- a/linux-user/mips/target_syscall.h
+++ b/linux-user/mips/target_syscall.h
@@ -1,25 +1,6 @@
#ifndef MIPS_TARGET_SYSCALL_H
#define MIPS_TARGET_SYSCALL_H
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
-struct target_pt_regs {
- /* Pad bytes for argument save space on the stack. */
- abi_ulong pad0[6];
-
- /* Saved main processor registers. */
- abi_ulong regs[32];
-
- /* Saved special registers. */
- abi_ulong cp0_status;
- abi_ulong lo;
- abi_ulong hi;
- abi_ulong cp0_badvaddr;
- abi_ulong cp0_cause;
- abi_ulong cp0_epc;
-};
-
#define UNAME_MACHINE "mips"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/mips64/target_elf.h b/linux-user/mips64/target_elf.h
index 24bb7fc..061471a 100644
--- a/linux-user/mips64/target_elf.h
+++ b/linux-user/mips64/target_elf.h
@@ -8,7 +8,28 @@
#ifndef MIPS64_TARGET_ELF_H
#define MIPS64_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_MACHINE EM_MIPS
+#define EXSTACK_DEFAULT true
+
+#ifdef TARGET_ABI_MIPSN32
+#define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
+#else
+#define elf_check_abi(x) (!((x) & EF_MIPS_ABI2))
+#endif
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_BASE_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/* See linux kernel: arch/mips/include/asm/elf.h. */
+typedef struct target_elf_gregset_t {
+ union {
+ target_ulong reserved[45];
+ struct target_pt_regs pt;
+ };
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/mips64/target_ptrace.h b/linux-user/mips64/target_ptrace.h
new file mode 100644
index 0000000..41f0bf6
--- /dev/null
+++ b/linux-user/mips64/target_ptrace.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef MIPS64_TARGET_PTRACE_H
+#define MIPS64_TARGET_PTRACE_H
+
+struct target_pt_regs {
+ target_ulong regs[32];
+ target_ulong lo;
+ target_ulong hi;
+ target_ulong cp0_epc;
+ target_ulong cp0_badvaddr;
+ target_ulong cp0_status;
+ target_ulong cp0_cause;
+};
+
+#endif /* MIPS64_TARGET_PTRACE_H */
diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h
index 358dc2d..9135bf5 100644
--- a/linux-user/mips64/target_syscall.h
+++ b/linux-user/mips64/target_syscall.h
@@ -1,22 +1,6 @@
#ifndef MIPS64_TARGET_SYSCALL_H
#define MIPS64_TARGET_SYSCALL_H
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
-struct target_pt_regs {
- /* Saved main processor registers. */
- target_ulong regs[32];
-
- /* Saved special registers. */
- target_ulong cp0_status;
- target_ulong lo;
- target_ulong hi;
- target_ulong cp0_badvaddr;
- target_ulong cp0_cause;
- target_ulong cp0_epc;
-};
-
#define UNAME_MACHINE "mips64"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/openrisc/elfload.c b/linux-user/openrisc/elfload.c
index b92442d..6bf02bf 100644
--- a/linux-user/openrisc/elfload.c
+++ b/linux-user/openrisc/elfload.c
@@ -3,9 +3,19 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
{
return "any";
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUOpenRISCState *env)
+{
+ for (int i = 0; i < 32; i++) {
+ r->pt.gpr[i] = tswapal(cpu_get_gpr(env, i));
+ }
+ r->pt.pc = tswapal(env->pc);
+ r->pt.sr = tswapal(cpu_get_sr(env));
+}
diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c
index cb74a9f..4024909 100644
--- a/linux-user/openrisc/signal.c
+++ b/linux-user/openrisc/signal.c
@@ -21,9 +21,10 @@
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
+#include "target_ptrace.h"
typedef struct target_sigcontext {
- struct target_pt_regs regs;
+ struct target_user_regs_struct regs;
abi_ulong oldmask;
} target_sigcontext;
diff --git a/linux-user/openrisc/target_elf.h b/linux-user/openrisc/target_elf.h
index b34f2ff..e8554f5 100644
--- a/linux-user/openrisc/target_elf.h
+++ b/linux-user/openrisc/target_elf.h
@@ -8,4 +8,19 @@
#ifndef OPENRISC_TARGET_ELF_H
#define OPENRISC_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_MACHINE EM_OPENRISC
+#define ELF_CLASS ELFCLASS32
+
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/openrisc/include/uapi/asm/elf.h, where
+ * elf_gregset_t is mapped to struct user_regs_struct via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_user_regs_struct pt;
+} target_elf_gregset_t;
+
#endif
diff --git a/linux-user/openrisc/target_ptrace.h b/linux-user/openrisc/target_ptrace.h
new file mode 100644
index 0000000..563c648
--- /dev/null
+++ b/linux-user/openrisc/target_ptrace.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef OPENRISC_TARGET_PTRACE_H
+#define OPENRISC_TARGET_PTRACE_H
+
+/* See arch/openrisc/include/uapi/asm/ptrace.h. */
+struct target_user_regs_struct {
+ abi_ulong gpr[32];
+ abi_ulong pc;
+ abi_ulong sr;
+};
+
+#endif /* OPENRISC_TARGET_PTRACE_H */
diff --git a/linux-user/openrisc/target_syscall.h b/linux-user/openrisc/target_syscall.h
index 7fe5b73..c8394e9 100644
--- a/linux-user/openrisc/target_syscall.h
+++ b/linux-user/openrisc/target_syscall.h
@@ -1,17 +1,6 @@
#ifndef OPENRISC_TARGET_SYSCALL_H
#define OPENRISC_TARGET_SYSCALL_H
-/* Note that in linux/arch/openrisc/include/uapi/asm/ptrace.h,
- * this is called user_regs_struct. Given that this is what
- * is used within struct sigcontext we need this definition.
- * However, elfload.c wants this name.
- */
-struct target_pt_regs {
- abi_ulong gpr[32];
- abi_ulong pc;
- abi_ulong sr;
-};
-
#define UNAME_MACHINE "openrisc"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/ppc/elfload.c b/linux-user/ppc/elfload.c
index a214675..0d54da9 100644
--- a/linux-user/ppc/elfload.c
+++ b/linux-user/ppc/elfload.c
@@ -3,6 +3,7 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -129,3 +130,17 @@ abi_ulong get_elf_hwcap2(CPUState *cs)
return features;
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUPPCState *env)
+{
+ for (int i = 0; i < ARRAY_SIZE(env->gpr); i++) {
+ r->pt.gpr[i] = tswapal(env->gpr[i]);
+ }
+
+ r->pt.nip = tswapal(env->nip);
+ r->pt.msr = tswapal(env->msr);
+ r->pt.ctr = tswapal(env->ctr);
+ r->pt.link = tswapal(env->lr);
+ r->pt.xer = tswapal(cpu_read_xer(env));
+ r->pt.ccr = tswapal(ppc_get_cr(env));
+}
diff --git a/linux-user/ppc/target_elf.h b/linux-user/ppc/target_elf.h
index 4203a89..22854cf 100644
--- a/linux-user/ppc/target_elf.h
+++ b/linux-user/ppc/target_elf.h
@@ -8,7 +8,63 @@
#ifndef PPC_TARGET_ELF_H
#define PPC_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_MACHINE PPC_ELF_MACHINE
+
+#ifdef TARGET_PPC64
+# define ELF_CLASS ELFCLASS64
+#else
+# define ELF_CLASS ELFCLASS32
+# define EXSTACK_DEFAULT true
+#endif
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_HWCAP2 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * The size of 48 words is set in arch/powerpc/include/uapi/asm/elf.h.
+ * However PPC_ELF_CORE_COPY_REGS in arch/powerpc/include/asm/elf.h
+ * open-codes a memcpy from struct pt_regs, then zeros the rest.
+ */
+typedef struct target_elf_gregset_t {
+ union {
+ struct target_pt_regs pt;
+ abi_ulong reserved[48];
+ };
+} target_elf_gregset_t;
+
+#ifndef TARGET_PPC64
+# define VDSO_HEADER "vdso-32.c.inc"
+#elif TARGET_BIG_ENDIAN
+# define VDSO_HEADER "vdso-64.c.inc"
+#else
+# define VDSO_HEADER "vdso-64le.c.inc"
+#endif
+
+/*
+ * The requirements here are:
+ * - keep the final alignment of sp (sp & 0xf)
+ * - make sure the 32-bit value at the first 16 byte aligned position of
+ * AUXV is greater than 16 for glibc compatibility.
+ * AT_IGNOREPPC is used for that.
+ * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+ * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+ */
+#define DLINFO_ARCH_ITEMS 5
+#define ARCH_DLINFO \
+ do { \
+ PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); \
+ /* \
+ * Handle glibc compatibility: these magic entries must \
+ * be at the lowest addresses in the final auxv. \
+ */ \
+ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+ NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \
+ NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \
+ NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
+ } while (0)
#endif
diff --git a/linux-user/ppc/target_ptrace.h b/linux-user/ppc/target_ptrace.h
new file mode 100644
index 0000000..df77bfd
--- /dev/null
+++ b/linux-user/ppc/target_ptrace.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef PPC_TARGET_PTRACE_H
+#define PPC_TARGET_PTRACE_H
+
+struct target_pt_regs {
+ abi_ulong gpr[32];
+ abi_ulong nip;
+ abi_ulong msr;
+ abi_ulong orig_gpr3; /* Used for restarting system calls */
+ abi_ulong ctr;
+ abi_ulong link;
+ abi_ulong xer;
+ abi_ulong ccr;
+#if defined(TARGET_PPC64)
+ abi_ulong softe;
+#else
+ abi_ulong mq; /* 601 only (not used at present) */
+#endif
+ abi_ulong trap; /* Reason for being here */
+ abi_ulong dar; /* Fault registers */
+ abi_ulong dsisr;
+ abi_ulong result; /* Result of a system call */
+};
+
+#endif /* PPC_TARGET_PTRACE_H */
diff --git a/linux-user/ppc/target_syscall.h b/linux-user/ppc/target_syscall.h
index 77b36d0..976b4bb 100644
--- a/linux-user/ppc/target_syscall.h
+++ b/linux-user/ppc/target_syscall.h
@@ -20,34 +20,6 @@
#ifndef PPC_TARGET_SYSCALL_H
#define PPC_TARGET_SYSCALL_H
-/* XXX: ABSOLUTELY BUGGY:
- * for now, this is quite just a cut-and-paste from i386 target...
- */
-
-/* default linux values for the selectors */
-#define __USER_DS (1)
-
-struct target_pt_regs {
- abi_ulong gpr[32];
- abi_ulong nip;
- abi_ulong msr;
- abi_ulong orig_gpr3; /* Used for restarting system calls */
- abi_ulong ctr;
- abi_ulong link;
- abi_ulong xer;
- abi_ulong ccr;
-#if defined(TARGET_PPC64)
- abi_ulong softe;
-#else
- abi_ulong mq; /* 601 only (not used at present) */
-#endif
- /* Used on APUS to hold IPL value. */
- abi_ulong trap; /* Reason for being here */
- abi_ulong dar; /* Fault registers */
- abi_ulong dsisr;
- abi_ulong result; /* Result of a system call */
-};
-
/* ioctls */
struct target_revectored_struct {
abi_ulong __map[8]; /* 256 bits */
diff --git a/linux-user/riscv/target_elf.h b/linux-user/riscv/target_elf.h
index 48d9af5..dbbfdf5 100644
--- a/linux-user/riscv/target_elf.h
+++ b/linux-user/riscv/target_elf.h
@@ -8,6 +8,16 @@
#ifndef RISCV_TARGET_ELF_H
#define RISCV_TARGET_ELF_H
+#define ELF_MACHINE EM_RISCV
+
+#ifdef TARGET_RISCV32
+#define ELF_CLASS ELFCLASS32
+#define VDSO_HEADER "vdso-32.c.inc"
+#else
+#define ELF_CLASS ELFCLASS64
+#define VDSO_HEADER "vdso-64.c.inc"
+#endif
+
#define HAVE_ELF_HWCAP 1
#endif
diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h
index 7601f10..69a7b75 100644
--- a/linux-user/riscv/target_syscall.h
+++ b/linux-user/riscv/target_syscall.h
@@ -8,41 +8,6 @@
#ifndef LINUX_USER_RISCV_TARGET_SYSCALL_H
#define LINUX_USER_RISCV_TARGET_SYSCALL_H
-struct target_pt_regs {
- abi_long sepc;
- abi_long ra;
- abi_long sp;
- abi_long gp;
- abi_long tp;
- abi_long t0;
- abi_long t1;
- abi_long t2;
- abi_long s0;
- abi_long s1;
- abi_long a0;
- abi_long a1;
- abi_long a2;
- abi_long a3;
- abi_long a4;
- abi_long a5;
- abi_long a6;
- abi_long a7;
- abi_long s2;
- abi_long s3;
- abi_long s4;
- abi_long s5;
- abi_long s6;
- abi_long s7;
- abi_long s8;
- abi_long s9;
- abi_long s10;
- abi_long s11;
- abi_long t3;
- abi_long t4;
- abi_long t5;
- abi_long t6;
-};
-
#ifdef TARGET_RISCV32
#define UNAME_MACHINE "riscv32"
#define UNAME_MINIMUM_RELEASE "5.4.0"
diff --git a/linux-user/s390x/elfload.c b/linux-user/s390x/elfload.c
index 79ceaba..2710927 100644
--- a/linux-user/s390x/elfload.c
+++ b/linux-user/s390x/elfload.c
@@ -4,6 +4,7 @@
#include "qemu.h"
#include "loader.h"
#include "elf.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -66,3 +67,16 @@ const char *elf_hwcap_str(uint32_t bit)
return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUS390XState *env)
+{
+ r->pt.psw.mask = tswapal(env->psw.mask);
+ r->pt.psw.addr = tswapal(env->psw.addr);
+ for (int i = 0; i < 16; i++) {
+ r->pt.gprs[i] = tswapal(env->regs[i]);
+ }
+ for (int i = 0; i < 16; i++) {
+ r->pt.acrs[i] = tswap32(env->aregs[i]);
+ }
+ r->pt.orig_gpr2 = 0;
+}
diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index df49c24..96d1c8d 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -22,6 +22,7 @@
#include "signal-common.h"
#include "linux-user/trace.h"
#include "vdso-asmoffset.h"
+#include "target_ptrace.h"
#define __NUM_GPRS 16
#define __NUM_FPRS 16
diff --git a/linux-user/s390x/target_elf.h b/linux-user/s390x/target_elf.h
index cebace9..ef5edbd 100644
--- a/linux-user/s390x/target_elf.h
+++ b/linux-user/s390x/target_elf.h
@@ -8,6 +8,21 @@
#ifndef S390X_TARGET_ELF_H
#define S390X_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_MACHINE EM_S390
+#define VDSO_HEADER "vdso.c.inc"
+
#define HAVE_ELF_HWCAP 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/s390/include/asm/elf.h, where
+ * elf_gregset_t is typedef'd to struct s390_regs.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_s390_regs pt;
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/s390x/target_ptrace.h b/linux-user/s390x/target_ptrace.h
new file mode 100644
index 0000000..a5ceb75
--- /dev/null
+++ b/linux-user/s390x/target_ptrace.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef S390X_TARGET_PTRACE_H
+#define S390X_TARGET_PTRACE_H
+
+typedef struct {
+ abi_ulong mask;
+ abi_ulong addr;
+} target_psw_t;
+
+struct target_s390_regs {
+ target_psw_t psw;
+ abi_ulong gprs[16];
+ abi_uint acrs[16];
+ abi_ulong orig_gpr2;
+};
+
+#endif /* S390X_TARGET_PTRACE_H */
diff --git a/linux-user/s390x/target_syscall.h b/linux-user/s390x/target_syscall.h
index 4018988..f01f9a0 100644
--- a/linux-user/s390x/target_syscall.h
+++ b/linux-user/s390x/target_syscall.h
@@ -1,28 +1,6 @@
#ifndef S390X_TARGET_SYSCALL_H
#define S390X_TARGET_SYSCALL_H
-/* this typedef defines how a Program Status Word looks like */
-typedef struct {
- abi_ulong mask;
- abi_ulong addr;
-} __attribute__ ((aligned(8))) target_psw_t;
-
-/*
- * The pt_regs struct defines the way the registers are stored on
- * the stack during a system call.
- */
-
-#define TARGET_NUM_GPRS 16
-
-struct target_pt_regs {
- abi_ulong args[1];
- target_psw_t psw;
- abi_ulong gprs[TARGET_NUM_GPRS];
- abi_ulong orig_gpr2;
- unsigned short ilen;
- unsigned short trap;
-};
-
#define UNAME_MACHINE "s390x"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/sh4/elfload.c b/linux-user/sh4/elfload.c
index 99ad4f6..ddf2aaa 100644
--- a/linux-user/sh4/elfload.c
+++ b/linux-user/sh4/elfload.c
@@ -3,6 +3,7 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -36,3 +37,17 @@ abi_ulong get_elf_hwcap(CPUState *cs)
return hwcap;
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUSH4State *env)
+{
+ for (int i = 0; i < 16; i++) {
+ r->pt.regs[i] = tswapal(env->gregs[i]);
+ }
+
+ r->pt.pc = tswapal(env->pc);
+ r->pt.pr = tswapal(env->pr);
+ r->pt.sr = tswapal(env->sr);
+ r->pt.gbr = tswapal(env->gbr);
+ r->pt.mach = tswapal(env->mach);
+ r->pt.macl = tswapal(env->macl);
+}
diff --git a/linux-user/sh4/target_elf.h b/linux-user/sh4/target_elf.h
index badd0f5..d9e253d 100644
--- a/linux-user/sh4/target_elf.h
+++ b/linux-user/sh4/target_elf.h
@@ -8,6 +8,20 @@
#ifndef SH4_TARGET_ELF_H
#define SH4_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_SH
+
#define HAVE_ELF_HWCAP 1
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/sh/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct pt_regs via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_pt_regs pt;
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/sh4/target_ptrace.h b/linux-user/sh4/target_ptrace.h
new file mode 100644
index 0000000..b802185
--- /dev/null
+++ b/linux-user/sh4/target_ptrace.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef SH4_TARGET_PTRACE_H
+#define SH4_TARGET_PTRACE_H
+
+/* See arch/sh/include/uapi/asm/ptrace_32.h. */
+struct target_pt_regs {
+ abi_ulong regs[16];
+ abi_ulong pc;
+ abi_ulong pr;
+ abi_ulong sr;
+ abi_ulong gbr;
+ abi_ulong mach;
+ abi_ulong macl;
+ abi_long tra;
+};
+
+#endif /* SH4_TARGET_PTRACE_H */
diff --git a/linux-user/sh4/target_syscall.h b/linux-user/sh4/target_syscall.h
index 14839885..2f35577 100644
--- a/linux-user/sh4/target_syscall.h
+++ b/linux-user/sh4/target_syscall.h
@@ -1,17 +1,6 @@
#ifndef SH4_TARGET_SYSCALL_H
#define SH4_TARGET_SYSCALL_H
-struct target_pt_regs {
- unsigned long regs[16];
- unsigned long pc;
- unsigned long pr;
- unsigned long sr;
- unsigned long gbr;
- unsigned long mach;
- unsigned long macl;
- long tra;
-};
-
#define UNAME_MACHINE "sh4"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index 8181b8b..d339f89 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -21,6 +21,8 @@
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
+#include "target_ptrace.h"
+
/* A Sparc register window */
struct target_reg_window {
diff --git a/linux-user/sparc/target_elf.h b/linux-user/sparc/target_elf.h
index b7544db..7827767 100644
--- a/linux-user/sparc/target_elf.h
+++ b/linux-user/sparc/target_elf.h
@@ -8,6 +8,17 @@
#ifndef SPARC_TARGET_ELF_H
#define SPARC_TARGET_ELF_H
+#ifndef TARGET_SPARC64
+# define ELF_CLASS ELFCLASS32
+# define ELF_MACHINE EM_SPARC
+#elif defined(TARGET_ABI32)
+# define ELF_CLASS ELFCLASS32
+# define elf_check_machine(x) ((x) == EM_SPARC32PLUS || (x) == EM_SPARC)
+#else
+# define ELF_CLASS ELFCLASS64
+# define ELF_MACHINE EM_SPARCV9
+#endif
+
#define HAVE_ELF_HWCAP 1
#endif
diff --git a/linux-user/sparc/target_ptrace.h b/linux-user/sparc/target_ptrace.h
new file mode 100644
index 0000000..a4d5416
--- /dev/null
+++ b/linux-user/sparc/target_ptrace.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef SPARC_TARGET_PTRACE_H
+#define SPARC_TARGET_PTRACE_H
+
+/* See arch/sparc/include/uapi/asm/ptrace.h. */
+struct target_pt_regs {
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+ abi_ulong u_regs[16];
+ abi_ulong tstate;
+ abi_ulong pc;
+ abi_ulong npc;
+ uint32_t y;
+ uint32_t magic;
+#else
+ abi_ulong psr;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong u_regs[16];
+#endif
+};
+
+#endif /* SPARC_TARGET_PTRACE_H */
diff --git a/linux-user/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h
index e421165..a90ed29 100644
--- a/linux-user/sparc/target_syscall.h
+++ b/linux-user/sparc/target_syscall.h
@@ -1,25 +1,6 @@
#ifndef SPARC_TARGET_SYSCALL_H
#define SPARC_TARGET_SYSCALL_H
-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
-struct target_pt_regs {
- abi_ulong u_regs[16];
- abi_ulong tstate;
- abi_ulong pc;
- abi_ulong npc;
- uint32_t y;
- uint32_t magic;
-};
-#else
-struct target_pt_regs {
- abi_ulong psr;
- abi_ulong pc;
- abi_ulong npc;
- abi_ulong y;
- abi_ulong u_regs[16];
-};
-#endif
-
#ifdef TARGET_SPARC64
# define UNAME_MACHINE "sparc64"
#else
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 7863546..1233ebc 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -499,116 +499,118 @@ print_socket_type(int type)
static void
print_socket_protocol(int domain, int type, int protocol)
{
- if (domain == AF_PACKET ||
- (domain == AF_INET && type == TARGET_SOCK_PACKET)) {
+ const char *name = NULL;
+
+ switch (domain) {
+ case AF_PACKET:
switch (protocol) {
- case 0x0003:
- qemu_log("ETH_P_ALL");
+ case 3:
+ name = "ETH_P_ALL";
break;
- default:
- qemu_log("%d", protocol);
}
- return;
- }
+ break;
- if (domain == PF_NETLINK) {
+ case PF_NETLINK:
switch (protocol) {
case NETLINK_ROUTE:
- qemu_log("NETLINK_ROUTE");
+ name = "NETLINK_ROUTE";
break;
case NETLINK_UNUSED:
- qemu_log("NETLINK_UNUSED");
+ name = "NETLINK_UNUSED";
break;
case NETLINK_USERSOCK:
- qemu_log("NETLINK_USERSOCK");
+ name = "NETLINK_USERSOCK";
break;
case NETLINK_FIREWALL:
- qemu_log("NETLINK_FIREWALL");
+ name = "NETLINK_FIREWALL";
break;
case NETLINK_SOCK_DIAG:
- qemu_log("NETLINK_SOCK_DIAG");
+ name = "NETLINK_SOCK_DIAG";
break;
case NETLINK_NFLOG:
- qemu_log("NETLINK_NFLOG");
+ name = "NETLINK_NFLOG";
break;
case NETLINK_XFRM:
- qemu_log("NETLINK_XFRM");
+ name = "NETLINK_XFRM";
break;
case NETLINK_SELINUX:
- qemu_log("NETLINK_SELINUX");
+ name = "NETLINK_SELINUX";
break;
case NETLINK_ISCSI:
- qemu_log("NETLINK_ISCSI");
+ name = "NETLINK_ISCSI";
break;
case NETLINK_AUDIT:
- qemu_log("NETLINK_AUDIT");
+ name = "NETLINK_AUDIT";
break;
case NETLINK_FIB_LOOKUP:
- qemu_log("NETLINK_FIB_LOOKUP");
+ name = "NETLINK_FIB_LOOKUP";
break;
case NETLINK_CONNECTOR:
- qemu_log("NETLINK_CONNECTOR");
+ name = "NETLINK_CONNECTOR";
break;
case NETLINK_NETFILTER:
- qemu_log("NETLINK_NETFILTER");
+ name = "NETLINK_NETFILTER";
break;
case NETLINK_IP6_FW:
- qemu_log("NETLINK_IP6_FW");
+ name = "NETLINK_IP6_FW";
break;
case NETLINK_DNRTMSG:
- qemu_log("NETLINK_DNRTMSG");
+ name = "NETLINK_DNRTMSG";
break;
case NETLINK_KOBJECT_UEVENT:
- qemu_log("NETLINK_KOBJECT_UEVENT");
+ name = "NETLINK_KOBJECT_UEVENT";
break;
case NETLINK_GENERIC:
- qemu_log("NETLINK_GENERIC");
+ name = "NETLINK_GENERIC";
break;
case NETLINK_SCSITRANSPORT:
- qemu_log("NETLINK_SCSITRANSPORT");
+ name = "NETLINK_SCSITRANSPORT";
break;
case NETLINK_ECRYPTFS:
- qemu_log("NETLINK_ECRYPTFS");
+ name = "NETLINK_ECRYPTFS";
break;
case NETLINK_RDMA:
- qemu_log("NETLINK_RDMA");
+ name = "NETLINK_RDMA";
break;
case NETLINK_CRYPTO:
- qemu_log("NETLINK_CRYPTO");
+ name = "NETLINK_CRYPTO";
break;
case NETLINK_SMC:
- qemu_log("NETLINK_SMC");
- break;
- default:
- qemu_log("%d", protocol);
+ name = "NETLINK_SMC";
break;
}
- return;
- }
+ break;
- if (domain == AF_INET || domain == AF_INET6) {
+ case AF_INET:
+ case AF_INET6:
switch (protocol) {
+ case 3:
+ if (domain == AF_INET && type == TARGET_SOCK_PACKET) {
+ name = "ETH_P_ALL";
+ }
+ break;
case IPPROTO_IP:
- qemu_log("IPPROTO_IP");
+ name = "IPPROTO_IP";
break;
case IPPROTO_TCP:
- qemu_log("IPPROTO_TCP");
+ name = "IPPROTO_TCP";
break;
case IPPROTO_UDP:
- qemu_log("IPPROTO_UDP");
+ name = "IPPROTO_UDP";
break;
case IPPROTO_RAW:
- qemu_log("IPPROTO_RAW");
- break;
- default:
- qemu_log("%d", protocol);
+ name = "IPPROTO_RAW";
break;
}
- return;
+ break;
}
- qemu_log("%d", protocol);
-}
+ if (name) {
+ qemu_log("%s", name);
+ } else {
+ qemu_log("%d", protocol);
+ }
+}
#ifdef TARGET_NR__newselect
static void
diff --git a/linux-user/x86_64/elfload.c b/linux-user/x86_64/elfload.c
index 88541ea..1e7000c 100644
--- a/linux-user/x86_64/elfload.c
+++ b/linux-user/x86_64/elfload.c
@@ -1,8 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "qemu/osdep.h"
+#include "qemu/error-report.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
@@ -19,3 +21,53 @@ const char *get_elf_platform(CPUState *cs)
{
return "x86_64";
}
+
+bool init_guest_commpage(void)
+{
+ /*
+ * The vsyscall page is at a high negative address aka kernel space,
+ * which means that we cannot actually allocate it with target_mmap.
+ * We still should be able to use page_set_flags, unless the user
+ * has specified -R reserved_va, which would trigger an assert().
+ */
+ if (reserved_va != 0 &&
+ TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE - 1 > reserved_va) {
+ error_report("Cannot allocate vsyscall page");
+ exit(EXIT_FAILURE);
+ }
+ page_set_flags(TARGET_VSYSCALL_PAGE,
+ TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK,
+ PAGE_EXEC | PAGE_VALID);
+ return true;
+}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUX86State *env)
+{
+ r->pt.r15 = tswapal(env->regs[15]);
+ r->pt.r14 = tswapal(env->regs[14]);
+ r->pt.r13 = tswapal(env->regs[13]);
+ r->pt.r12 = tswapal(env->regs[12]);
+ r->pt.bp = tswapal(env->regs[R_EBP]);
+ r->pt.bx = tswapal(env->regs[R_EBX]);
+ r->pt.r11 = tswapal(env->regs[11]);
+ r->pt.r10 = tswapal(env->regs[10]);
+ r->pt.r9 = tswapal(env->regs[9]);
+ r->pt.r8 = tswapal(env->regs[8]);
+ r->pt.ax = tswapal(env->regs[R_EAX]);
+ r->pt.cx = tswapal(env->regs[R_ECX]);
+ r->pt.dx = tswapal(env->regs[R_EDX]);
+ r->pt.si = tswapal(env->regs[R_ESI]);
+ r->pt.di = tswapal(env->regs[R_EDI]);
+ r->pt.orig_ax = tswapal(get_task_state(env_cpu_const(env))->orig_ax);
+ r->pt.ip = tswapal(env->eip);
+ r->pt.cs = tswapal(env->segs[R_CS].selector & 0xffff);
+ r->pt.flags = tswapal(env->eflags);
+ r->pt.sp = tswapal(env->regs[R_ESP]);
+ r->pt.ss = tswapal(env->segs[R_SS].selector & 0xffff);
+ r->pt.fs_base = tswapal(env->segs[R_FS].base);
+ r->pt.gs_base = tswapal(env->segs[R_GS].base);
+ r->pt.ds = tswapal(env->segs[R_DS].selector & 0xffff);
+ r->pt.es = tswapal(env->segs[R_ES].selector & 0xffff);
+ r->pt.fs = tswapal(env->segs[R_FS].selector & 0xffff);
+ r->pt.gs = tswapal(env->segs[R_GS].selector & 0xffff);
+}
diff --git a/linux-user/x86_64/target_elf.h b/linux-user/x86_64/target_elf.h
index 498c3f7..840bddf 100644
--- a/linux-user/x86_64/target_elf.h
+++ b/linux-user/x86_64/target_elf.h
@@ -8,7 +8,23 @@
#ifndef X86_64_TARGET_ELF_H
#define X86_64_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_MACHINE EM_X86_64
+#define VDSO_HEADER "vdso.c.inc"
+
#define HAVE_ELF_HWCAP 1
#define HAVE_ELF_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+#define HAVE_GUEST_COMMPAGE 1
+
+/*
+ * See linux kernel: arch/x86/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct user_regs_struct via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_user_regs_struct pt;
+} target_elf_gregset_t;
#endif
diff --git a/linux-user/x86_64/target_ptrace.h b/linux-user/x86_64/target_ptrace.h
new file mode 100644
index 0000000..3352712
--- /dev/null
+++ b/linux-user/x86_64/target_ptrace.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef X86_64_TARGET_PTRACE_H
+#define X86_64_TARGET_PTRACE_H
+
+/*
+ * The struct pt_regs in arch/x86/include/uapi/asm/ptrace.h has missing
+ * register values and is not used. See arch/x86/include/asm/user_64.h.
+ */
+struct target_user_regs_struct {
+ abi_ulong r15;
+ abi_ulong r14;
+ abi_ulong r13;
+ abi_ulong r12;
+ abi_ulong bp;
+ abi_ulong bx;
+ abi_ulong r11;
+ abi_ulong r10;
+ abi_ulong r9;
+ abi_ulong r8;
+ abi_ulong ax;
+ abi_ulong cx;
+ abi_ulong dx;
+ abi_ulong si;
+ abi_ulong di;
+ abi_ulong orig_ax;
+ abi_ulong ip;
+ abi_ulong cs;
+ abi_ulong flags;
+ abi_ulong sp;
+ abi_ulong ss;
+ abi_ulong fs_base;
+ abi_ulong gs_base;
+ abi_ulong ds;
+ abi_ulong es;
+ abi_ulong fs;
+ abi_ulong gs;
+};
+
+#endif /* X86_64_TARGET_PTRACE_H */
diff --git a/linux-user/x86_64/target_syscall.h b/linux-user/x86_64/target_syscall.h
index fb55834..68f55f8 100644
--- a/linux-user/x86_64/target_syscall.h
+++ b/linux-user/x86_64/target_syscall.h
@@ -4,34 +4,6 @@
#define __USER_CS (0x33)
#define __USER_DS (0x2B)
-struct target_pt_regs {
- abi_ulong r15;
- abi_ulong r14;
- abi_ulong r13;
- abi_ulong r12;
- abi_ulong rbp;
- abi_ulong rbx;
-/* arguments: non interrupts/non tracing syscalls only save up to here */
- abi_ulong r11;
- abi_ulong r10;
- abi_ulong r9;
- abi_ulong r8;
- abi_ulong rax;
- abi_ulong rcx;
- abi_ulong rdx;
- abi_ulong rsi;
- abi_ulong rdi;
- abi_ulong orig_rax;
-/* end of arguments */
-/* cpu exception frame or undefined */
- abi_ulong rip;
- abi_ulong cs;
- abi_ulong eflags;
- abi_ulong rsp;
- abi_ulong ss;
-/* top of stack page */
-};
-
/* Maximum number of LDT entries supported. */
#define TARGET_LDT_ENTRIES 8192
/* The size of each LDT entry. */
diff --git a/linux-user/xtensa/elfload.c b/linux-user/xtensa/elfload.c
index e35ba69..68aeed8 100644
--- a/linux-user/xtensa/elfload.c
+++ b/linux-user/xtensa/elfload.c
@@ -3,9 +3,29 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "loader.h"
+#include "target_elf.h"
const char *get_elf_cpu_model(uint32_t eflags)
{
return XTENSA_DEFAULT_CPU_MODEL;
}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUXtensaState *env)
+{
+ r->pt.pc = tswap32(env->pc);
+ r->pt.ps = tswap32(env->sregs[PS] & ~PS_EXCM);
+ r->pt.lbeg = tswap32(env->sregs[LBEG]);
+ r->pt.lend = tswap32(env->sregs[LEND]);
+ r->pt.lcount = tswap32(env->sregs[LCOUNT]);
+ r->pt.sar = tswap32(env->sregs[SAR]);
+ r->pt.windowstart = tswap32(env->sregs[WINDOW_START]);
+ r->pt.windowbase = tswap32(env->sregs[WINDOW_BASE]);
+ r->pt.threadptr = tswap32(env->uregs[THREADPTR]);
+
+ xtensa_sync_phys_from_window((CPUXtensaState *)env);
+
+ for (unsigned i = 0; i < env->config->nareg; ++i) {
+ r->pt.a[i] = tswap32(env->phys_regs[i]);
+ }
+}
diff --git a/linux-user/xtensa/target_elf.h b/linux-user/xtensa/target_elf.h
index 2c55c22..1bf8f2a 100644
--- a/linux-user/xtensa/target_elf.h
+++ b/linux-user/xtensa/target_elf.h
@@ -8,4 +8,19 @@
#ifndef XTENSA_TARGET_ELF_H
#define XTENSA_TARGET_ELF_H
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_XTENSA
+
+#define HAVE_ELF_CORE_DUMP 1
+
+/*
+ * See linux kernel: arch/xtensa/include/asm/elf.h, where elf_gregset_t
+ * is mapped to struct user_pt_regs via typedef and sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_user_pt_regs pt;
+} target_elf_gregset_t;
+
#endif
diff --git a/linux-user/xtensa/target_ptrace.h b/linux-user/xtensa/target_ptrace.h
new file mode 100644
index 0000000..32443d0
--- /dev/null
+++ b/linux-user/xtensa/target_ptrace.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef XTENSA_TARGET_PTRACE_H
+#define XTENSA_TARGET_PTRACE_H
+
+/* See arch/xtensa/include/uapi/asm/ptrace.h. */
+struct target_user_pt_regs {
+ uint32_t pc;
+ uint32_t ps;
+ uint32_t lbeg;
+ uint32_t lend;
+ uint32_t lcount;
+ uint32_t sar;
+ uint32_t windowstart;
+ uint32_t windowbase;
+ uint32_t threadptr;
+ uint32_t syscall;
+ uint32_t reserved[6 + 48];
+ uint32_t a[64];
+};
+
+#endif /* XTENSA_TARGET_PTRACE_H */
diff --git a/linux-user/xtensa/target_syscall.h b/linux-user/xtensa/target_syscall.h
index afc86a1..5d4352a 100644
--- a/linux-user/xtensa/target_syscall.h
+++ b/linux-user/xtensa/target_syscall.h
@@ -8,41 +8,6 @@
#define MMAP_SHIFT TARGET_PAGE_BITS
-typedef uint32_t xtensa_reg_t;
-typedef struct {
-} xtregs_opt_t; /* TODO */
-
-struct target_pt_regs {
- xtensa_reg_t pc; /* 4 */
- xtensa_reg_t ps; /* 8 */
- xtensa_reg_t depc; /* 12 */
- xtensa_reg_t exccause; /* 16 */
- xtensa_reg_t excvaddr; /* 20 */
- xtensa_reg_t debugcause; /* 24 */
- xtensa_reg_t wmask; /* 28 */
- xtensa_reg_t lbeg; /* 32 */
- xtensa_reg_t lend; /* 36 */
- xtensa_reg_t lcount; /* 40 */
- xtensa_reg_t sar; /* 44 */
- xtensa_reg_t windowbase; /* 48 */
- xtensa_reg_t windowstart; /* 52 */
- xtensa_reg_t syscall; /* 56 */
- xtensa_reg_t icountlevel; /* 60 */
- xtensa_reg_t scompare1; /* 64 */
- xtensa_reg_t threadptr; /* 68 */
-
- /* Additional configurable registers that are used by the compiler. */
- xtregs_opt_t xtregs_opt;
-
- /* Make sure the areg field is 16 bytes aligned. */
- int align[0] __attribute__ ((aligned(16)));
-
- /* current register frame.
- * Note: The ESF for kernel exceptions ends after 16 registers!
- */
- xtensa_reg_t areg[16];
-};
-
#define TARGET_MCL_CURRENT 1
#define TARGET_MCL_FUTURE 2
#define TARGET_MCL_ONFAULT 4