* [PATCH v3 00/15] linux-user: Implement VDSOs
@ 2023-08-11 16:50 Richard Henderson
2023-08-11 16:50 ` [PATCH v3 01/15] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
` (15 more replies)
0 siblings, 16 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
It's time for another round on implementing the VDSO for linux-user.
We are now seeing applications built that absolutely require it,
and have no fallback for the VDSO to be absent.
For instance,
https://gitlab.com/qemu-project/qemu/-/issues/1267
uses musl and will currently branch to NULL executing the mmap
syscall, because the __kernel_vsyscall symbol is not found.
This is just a rebase of v2 from 2021:
https://lists.nongnu.org/archive/html/qemu-devel/2021-07/msg01311.html
and does nothing to address the cross-compilation issues.
I am more hopful that cross-compilation can be solved now, due
to the work on Native Library Calls:
https://patchew.org/QEMU/20230808141739.3110740-1-fufuyqqqqqq@gmail.com/
But frankly, even with cross-compilation enabled there will be
hosts which do not have the cross-compilers and I believe we will
still have to check the binaries into the repository. As they are
all on the order of 5 to 6k, I really do not see this as a problem.
r~
PS: This patch set is now 13 years old:
https://lists.nongnu.org/archive/html/qemu-devel/2010-04/msg00187.html
https://lists.gnu.org/archive/html/qemu-devel/2013-07/msg04036.html
Let's see if we can get this resolved before it can vote.
Richard Henderson (15):
linux-user: Introduce imgsrc_read, imgsrc_read_alloc
linux-user: Tidy loader_exec
linux-user: Do not clobber bprm_buf swapping ehdr
linux-user: Use ImageSource in load_elf_image
linux-user: Use ImageSource in load_symbols
linux-user: Replace bprm->fd with bprm->src.fd
linux-user: Load vdso image if available
linux-user: Add gen-vdso tool
linux-user/aarch64: Add vdso and use it for rt_sigreturn
target/arm: Add isar_feature_aa32_a32
linux-user/arm: Add vdso and use it for rt_sigreturn
linux-user/hppa: Add vdso and use it for rt_sigreturn
linux-user/i386: Add vdso and use it for sigreturn
linux-user/x86_64: Add vdso
linux-user/riscv: Add vdso and use it for sigreturn
linux-user/loader.h | 60 ++++-
target/arm/cpu.h | 5 +
linux-user/arm/signal.c | 30 ++-
linux-user/elfload.c | 365 ++++++++++++++++++++-----------
linux-user/flatload.c | 8 +-
linux-user/gen-vdso.c | 223 +++++++++++++++++++
linux-user/hppa/signal.c | 1 -
linux-user/linuxload.c | 137 ++++++++++--
target/arm/tcg/cpu32.c | 7 +
linux-user/gen-vdso-elfn.c.inc | 306 ++++++++++++++++++++++++++
linux-user/aarch64/Makefile.vdso | 11 +
linux-user/aarch64/meson.build | 11 +
linux-user/aarch64/vdso-be.so | Bin 0 -> 6000 bytes
linux-user/aarch64/vdso-le.so | Bin 0 -> 6000 bytes
linux-user/aarch64/vdso.S | 77 +++++++
linux-user/aarch64/vdso.ld | 74 +++++++
linux-user/arm/Makefile.vdso | 17 ++
linux-user/arm/meson.build | 18 ++
linux-user/arm/vdso-arm-be.so | Bin 0 -> 5648 bytes
linux-user/arm/vdso-arm-le.so | Bin 0 -> 5648 bytes
linux-user/arm/vdso-thm-be.so | Bin 0 -> 5620 bytes
linux-user/arm/vdso-thm-le.so | Bin 0 -> 5620 bytes
linux-user/arm/vdso.S | 209 ++++++++++++++++++
linux-user/arm/vdso.ld | 74 +++++++
linux-user/hppa/Makefile.vdso | 6 +
linux-user/hppa/meson.build | 6 +
linux-user/hppa/vdso.S | 149 +++++++++++++
linux-user/hppa/vdso.ld | 75 +++++++
linux-user/hppa/vdso.so | Bin 0 -> 5196 bytes
linux-user/i386/Makefile.vdso | 5 +
linux-user/i386/meson.build | 7 +
linux-user/i386/vdso.S | 181 +++++++++++++++
linux-user/i386/vdso.ld | 76 +++++++
linux-user/i386/vdso.so | Bin 0 -> 5528 bytes
linux-user/meson.build | 8 +-
linux-user/riscv/Makefile.vdso | 11 +
linux-user/riscv/meson.build | 9 +
linux-user/riscv/vdso-32.so | Bin 0 -> 5624 bytes
linux-user/riscv/vdso-64.so | Bin 0 -> 6120 bytes
linux-user/riscv/vdso.S | 207 ++++++++++++++++++
linux-user/riscv/vdso.ld | 76 +++++++
linux-user/x86_64/Makefile.vdso | 5 +
linux-user/x86_64/meson.build | 6 +
linux-user/x86_64/vdso.S | 122 +++++++++++
linux-user/x86_64/vdso.ld | 74 +++++++
linux-user/x86_64/vdso.so | Bin 0 -> 6008 bytes
46 files changed, 2467 insertions(+), 189 deletions(-)
create mode 100644 linux-user/gen-vdso.c
create mode 100644 linux-user/gen-vdso-elfn.c.inc
create mode 100644 linux-user/aarch64/Makefile.vdso
create mode 100644 linux-user/aarch64/meson.build
create mode 100755 linux-user/aarch64/vdso-be.so
create mode 100755 linux-user/aarch64/vdso-le.so
create mode 100644 linux-user/aarch64/vdso.S
create mode 100644 linux-user/aarch64/vdso.ld
create mode 100644 linux-user/arm/Makefile.vdso
create mode 100755 linux-user/arm/vdso-arm-be.so
create mode 100755 linux-user/arm/vdso-arm-le.so
create mode 100755 linux-user/arm/vdso-thm-be.so
create mode 100755 linux-user/arm/vdso-thm-le.so
create mode 100644 linux-user/arm/vdso.S
create mode 100644 linux-user/arm/vdso.ld
create mode 100644 linux-user/hppa/Makefile.vdso
create mode 100644 linux-user/hppa/vdso.S
create mode 100644 linux-user/hppa/vdso.ld
create mode 100755 linux-user/hppa/vdso.so
create mode 100644 linux-user/i386/Makefile.vdso
create mode 100644 linux-user/i386/vdso.S
create mode 100644 linux-user/i386/vdso.ld
create mode 100755 linux-user/i386/vdso.so
create mode 100644 linux-user/riscv/Makefile.vdso
create mode 100644 linux-user/riscv/meson.build
create mode 100755 linux-user/riscv/vdso-32.so
create mode 100755 linux-user/riscv/vdso-64.so
create mode 100644 linux-user/riscv/vdso.S
create mode 100644 linux-user/riscv/vdso.ld
create mode 100644 linux-user/x86_64/Makefile.vdso
create mode 100644 linux-user/x86_64/vdso.S
create mode 100644 linux-user/x86_64/vdso.ld
create mode 100755 linux-user/x86_64/vdso.so
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v3 01/15] linux-user: Introduce imgsrc_read, imgsrc_read_alloc
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 02/15] linux-user: Tidy loader_exec Richard Henderson
` (14 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Introduced and initialized, but not yet really used.
These will tidy the current tests vs BPRM_BUF_SIZE.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/loader.h | 61 +++++++++++++++++++++++-----
linux-user/linuxload.c | 90 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 142 insertions(+), 9 deletions(-)
diff --git a/linux-user/loader.h b/linux-user/loader.h
index 59cbeacf24..311d20f5d1 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -18,6 +18,48 @@
#ifndef LINUX_USER_LOADER_H
#define LINUX_USER_LOADER_H
+typedef struct {
+ const void *cache;
+ unsigned int cache_size;
+ int fd;
+} ImageSource;
+
+/**
+ * imgsrc_read: Read from ImageSource
+ * @dst: destination for read
+ * @offset: offset within file for read
+ * @len: size of the read
+ * @img: ImageSource to read from
+ * @errp: Error details.
+ *
+ * Read into @dst, using the cache when possible.
+ */
+bool imgsrc_read(void *dst, off_t offset, size_t len,
+ const ImageSource *img, Error **errp);
+
+/**
+ * imgsrc_read_alloc: Read from ImageSource
+ * @offset: offset within file for read
+ * @size: size of the read
+ * @img: ImageSource to read from
+ * @errp: Error details.
+ *
+ * Read into newly allocated memory, using the cache when possible.
+ */
+void *imgsrc_read_alloc(off_t offset, size_t len,
+ const ImageSource *img, Error **errp);
+
+/**
+ * imgsrc_mmap: Map from ImageSource
+ *
+ * If @src has a file descriptor, pass on to target_mmap. Otherwise,
+ * this is "mapping" from a host buffer, which resolves to memcpy.
+ * Therefore, flags must be MAP_PRIVATE | MAP_FIXED; the argument is
+ * retained for clarity.
+ */
+abi_long imgsrc_mmap(abi_ulong start, abi_ulong len, int prot,
+ int flags, const ImageSource *src, abi_ulong offset);
+
/*
* Read a good amount of data initially, to hopefully get all the
* program headers loaded.
@@ -29,15 +71,16 @@
* used when loading binaries.
*/
struct linux_binprm {
- char buf[BPRM_BUF_SIZE] __attribute__((aligned));
- abi_ulong p;
- int fd;
- int e_uid, e_gid;
- int argc, envc;
- char **argv;
- char **envp;
- char *filename; /* Name of binary */
- int (*core_dump)(int, const CPUArchState *); /* coredump routine */
+ char buf[BPRM_BUF_SIZE] __attribute__((aligned));
+ ImageSource src;
+ abi_ulong p;
+ int fd;
+ int e_uid, e_gid;
+ int argc, envc;
+ char **argv;
+ char **envp;
+ char *filename; /* Name of binary */
+ int (*core_dump)(int, const CPUArchState *); /* coredump routine */
};
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 745cce70ab..3536dd8104 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -3,7 +3,9 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "user-internals.h"
+#include "user-mmap.h"
#include "loader.h"
+#include "qapi/error.h"
#define NGROUPS 32
@@ -76,6 +78,10 @@ static int prepare_binprm(struct linux_binprm *bprm)
/* Make sure the rest of the loader won't read garbage. */
memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
}
+
+ bprm->src.cache = bprm->buf;
+ bprm->src.cache_size = retval;
+
return retval;
}
@@ -139,6 +145,7 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
int retval;
bprm->fd = fdexec;
+ bprm->src.fd = fdexec;
bprm->filename = (char *)filename;
bprm->argc = count(argv);
bprm->argv = argv;
@@ -173,3 +180,86 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
return retval;
}
+
+bool imgsrc_read(void *dst, off_t offset, size_t len,
+ const ImageSource *img, Error **errp)
+{
+ ssize_t ret;
+
+ if (offset + len <= img->cache_size) {
+ memcpy(dst, img->cache + offset, len);
+ return true;
+ }
+
+ if (img->fd < 0) {
+ error_setg(errp, "read past end of buffer");
+ return false;
+ }
+
+ ret = pread(img->fd, dst, len, offset);
+ if (ret == len) {
+ return true;
+ }
+ if (ret < 0) {
+ error_setg_errno(errp, errno, "Error reading file header");
+ } else {
+ error_setg(errp, "Incomplete read of file header");
+ }
+ return false;
+}
+
+void *imgsrc_read_alloc(off_t offset, size_t len,
+ const ImageSource *img, Error **errp)
+{
+ void *alloc = g_malloc(len);
+ bool ok = imgsrc_read(alloc, offset, len, img, errp);
+
+ if (!ok) {
+ g_free(alloc);
+ alloc = NULL;
+ }
+ return alloc;
+}
+
+abi_long imgsrc_mmap(abi_ulong start, abi_ulong len, int prot,
+ int flags, const ImageSource *src, abi_ulong offset)
+{
+ const int prot_write = PROT_READ | PROT_WRITE;
+ abi_long ret;
+ void *haddr;
+
+ assert(flags == (MAP_PRIVATE | MAP_FIXED));
+
+ if (src->fd >= 0) {
+ return target_mmap(start, len, prot, flags, src->fd, offset);
+ }
+
+ /*
+ * This case is for the vdso; we don't expect bad images.
+ * The mmap may extend beyond the end of the image, especially
+ * to the end of the page. Zero fill.
+ */
+ assert(offset < src->cache_size);
+
+ ret = target_mmap(start, len, prot_write, flags | MAP_ANON, -1, 0);
+ if (ret == -1) {
+ return ret;
+ }
+
+ haddr = lock_user(VERIFY_WRITE, start, len, 0);
+ assert(haddr != NULL);
+ if (offset + len <= src->cache_size) {
+ memcpy(haddr, src->cache + offset, len);
+ } else {
+ size_t rest = src->cache_size - offset;
+ memcpy(haddr, src->cache + offset, rest);
+ memset(haddr + rest, 0, len - rest);
+ }
+ unlock_user(haddr, start, len);
+
+ if (prot != prot_write) {
+ target_mprotect(start, len, prot);
+ }
+
+ return ret;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 02/15] linux-user: Tidy loader_exec
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
2023-08-11 16:50 ` [PATCH v3 01/15] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 03/15] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
` (13 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd, Philippe Mathieu-Daudé
Reorg the if cases to reduce indentation.
Test for 4 bytes in the file before checking the signatures.
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/linuxload.c | 42 +++++++++++++++++++++---------------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 3536dd8104..5b7e9ab983 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -154,31 +154,31 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
retval = prepare_binprm(bprm);
- if (retval >= 0) {
- if (bprm->buf[0] == 0x7f
- && bprm->buf[1] == 'E'
- && bprm->buf[2] == 'L'
- && bprm->buf[3] == 'F') {
- retval = load_elf_binary(bprm, infop);
-#if defined(TARGET_HAS_BFLT)
- } else if (bprm->buf[0] == 'b'
- && bprm->buf[1] == 'F'
- && bprm->buf[2] == 'L'
- && bprm->buf[3] == 'T') {
- retval = load_flt_binary(bprm, infop);
-#endif
- } else {
- return -ENOEXEC;
- }
+ if (retval < 4) {
+ return -ENOEXEC;
}
-
- if (retval >= 0) {
- /* success. Initialize important registers */
- do_init_thread(regs, infop);
+ if (bprm->buf[0] == 0x7f
+ && bprm->buf[1] == 'E'
+ && bprm->buf[2] == 'L'
+ && bprm->buf[3] == 'F') {
+ retval = load_elf_binary(bprm, infop);
+#if defined(TARGET_HAS_BFLT)
+ } else if (bprm->buf[0] == 'b'
+ && bprm->buf[1] == 'F'
+ && bprm->buf[2] == 'L'
+ && bprm->buf[3] == 'T') {
+ retval = load_flt_binary(bprm, infop);
+#endif
+ } else {
+ return -ENOEXEC;
+ }
+ if (retval < 0) {
return retval;
}
- return retval;
+ /* Success. Initialize important registers. */
+ do_init_thread(regs, infop);
+ return 0;
}
bool imgsrc_read(void *dst, off_t offset, size_t len,
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 03/15] linux-user: Do not clobber bprm_buf swapping ehdr
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
2023-08-11 16:50 ` [PATCH v3 01/15] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
2023-08-11 16:50 ` [PATCH v3 02/15] linux-user: Tidy loader_exec Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 04/15] linux-user: Use ImageSource in load_elf_image Richard Henderson
` (12 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd, Philippe Mathieu-Daudé
Rearrange the allocation of storage for ehdr between load_elf_image
and load_elf_binary. The same set of copies are done, but we don't
modify bprm_buf, which will be important later.
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ac03beb01b..11bbf4e99b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3019,16 +3019,17 @@ static bool parse_elf_properties(int image_fd,
On return: INFO values will be filled in, as necessary or available. */
static void load_elf_image(const char *image_name, int image_fd,
- struct image_info *info, char **pinterp_name,
+ struct image_info *info, struct elfhdr *ehdr,
+ char **pinterp_name,
char bprm_buf[BPRM_BUF_SIZE])
{
- struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
struct elf_phdr *phdr;
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
int i, retval, prot_exec;
Error *err = NULL;
/* First of all, some simple consistency checks */
+ memcpy(ehdr, bprm_buf, sizeof(*ehdr));
if (!elf_check_ident(ehdr)) {
error_setg(&err, "Invalid ELF image for this architecture");
goto exit_errmsg;
@@ -3343,6 +3344,7 @@ static void load_elf_image(const char *image_name, int image_fd,
static void load_elf_interp(const char *filename, struct image_info *info,
char bprm_buf[BPRM_BUF_SIZE])
{
+ struct elfhdr ehdr;
int fd, retval;
Error *err = NULL;
@@ -3364,7 +3366,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
}
- load_elf_image(filename, fd, info, NULL, bprm_buf);
+ load_elf_image(filename, fd, info, &ehdr, NULL, bprm_buf);
}
static int symfind(const void *s0, const void *s1)
@@ -3557,8 +3559,14 @@ uint32_t get_elf_eflags(int fd)
int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
{
+ /*
+ * We need a copy of the elf header for passing to create_elf_tables.
+ * We will have overwritten the original when we re-use bprm->buf
+ * while loading the interpreter. Allocate the storage for this now
+ * and let elf_load_image do any swapping that may be required.
+ */
+ struct elfhdr ehdr;
struct image_info interp_info;
- struct elfhdr elf_ex;
char *elf_interpreter = NULL;
char *scratch;
@@ -3570,12 +3578,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
info->start_mmap = (abi_ulong)ELF_START_MMAP;
load_elf_image(bprm->filename, bprm->fd, info,
- &elf_interpreter, bprm->buf);
-
- /* ??? We need a copy of the elf header for passing to create_elf_tables.
- If we do nothing, we'll have overwritten this when we re-use bprm->buf
- when we load the interpreter. */
- elf_ex = *(struct elfhdr *)bprm->buf;
+ &ehdr, &elf_interpreter, bprm->buf);
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
@@ -3662,7 +3665,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
}
- bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+ bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr,
info, (elf_interpreter ? &interp_info : NULL));
info->start_stack = bprm->p;
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 04/15] linux-user: Use ImageSource in load_elf_image
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (2 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 03/15] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 05/15] linux-user: Use ImageSource in load_symbols Richard Henderson
` (11 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Change parse_elf_properties as well, as the bprm_buf argument
ties the two functions closely.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 128 +++++++++++++++++--------------------------
1 file changed, 49 insertions(+), 79 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 11bbf4e99b..f3511ae766 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2922,10 +2922,9 @@ static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
}
/* Process NT_GNU_PROPERTY_TYPE_0. */
-static bool parse_elf_properties(int image_fd,
+static bool parse_elf_properties(const ImageSource *src,
struct image_info *info,
const struct elf_phdr *phdr,
- char bprm_buf[BPRM_BUF_SIZE],
Error **errp)
{
union {
@@ -2953,14 +2952,8 @@ static bool parse_elf_properties(int image_fd,
return false;
}
- if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
- memcpy(¬e, bprm_buf + phdr->p_offset, n);
- } else {
- ssize_t len = pread(image_fd, ¬e, n, phdr->p_offset);
- if (len != n) {
- error_setg_errno(errp, errno, "Error reading file header");
- return false;
- }
+ if (!imgsrc_read(¬e, phdr->p_offset, n, src, errp)) {
+ return false;
}
/*
@@ -3006,30 +2999,34 @@ static bool parse_elf_properties(int image_fd,
}
}
-/* Load an ELF image into the address space.
+/**
+ * load_elf_image: Load an ELF image into the address space.
+ * @image_name: the filename of the image, to use in error messages.
+ * @src: the ImageSource from which to read.
+ * @info: info collected from the loaded image.
+ * @ehdr: the ELF header, not yet bswapped.
+ * @pinterp_name: record any PT_INTERP string found.
+ *
+ * On return: @info values will be filled in, as necessary or available.
+ */
- IMAGE_NAME is the filename of the image, to use in error messages.
- IMAGE_FD is the open file descriptor for the image.
-
- BPRM_BUF is a copy of the beginning of the file; this of course
- contains the elf file header at offset 0. It is assumed that this
- buffer is sufficiently aligned to present no problems to the host
- in accessing data at aligned offsets within the buffer.
-
- On return: INFO values will be filled in, as necessary or available. */
-
-static void load_elf_image(const char *image_name, int image_fd,
+static void load_elf_image(const char *image_name, const ImageSource *src,
struct image_info *info, struct elfhdr *ehdr,
- char **pinterp_name,
- char bprm_buf[BPRM_BUF_SIZE])
+ char **pinterp_name)
{
- struct elf_phdr *phdr;
+ g_autofree struct elf_phdr *phdr = NULL;
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
- int i, retval, prot_exec;
+ int i, prot_exec;
Error *err = NULL;
- /* First of all, some simple consistency checks */
- memcpy(ehdr, bprm_buf, sizeof(*ehdr));
+ /*
+ * First of all, some simple consistency checks.
+ * Note that we rely on the bswapped ehdr staying in bprm_buf,
+ * for later use by load_elf_binary and create_elf_tables.
+ */
+ if (!imgsrc_read(ehdr, 0, sizeof(*ehdr), src, &err)) {
+ goto exit_errmsg;
+ }
if (!elf_check_ident(ehdr)) {
error_setg(&err, "Invalid ELF image for this architecture");
goto exit_errmsg;
@@ -3040,15 +3037,11 @@ static void load_elf_image(const char *image_name, int image_fd,
goto exit_errmsg;
}
- i = ehdr->e_phnum * sizeof(struct elf_phdr);
- if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
- phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
- } else {
- phdr = (struct elf_phdr *) alloca(i);
- retval = pread(image_fd, phdr, i, ehdr->e_phoff);
- if (retval != i) {
- goto exit_read;
- }
+ phdr = imgsrc_read_alloc(ehdr->e_phoff,
+ ehdr->e_phnum * sizeof(struct elf_phdr),
+ src, &err);
+ if (phdr == NULL) {
+ goto exit_errmsg;
}
bswap_phdr(phdr, ehdr->e_phnum);
@@ -3085,17 +3078,10 @@ static void load_elf_image(const char *image_name, int image_fd,
goto exit_errmsg;
}
- interp_name = g_malloc(eppnt->p_filesz);
-
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
- memcpy(interp_name, bprm_buf + eppnt->p_offset,
- eppnt->p_filesz);
- } else {
- retval = pread(image_fd, interp_name, eppnt->p_filesz,
- eppnt->p_offset);
- if (retval != eppnt->p_filesz) {
- goto exit_read;
- }
+ interp_name = imgsrc_read_alloc(eppnt->p_offset, eppnt->p_filesz,
+ src, &err);
+ if (interp_name == NULL) {
+ goto exit_errmsg;
}
if (interp_name[eppnt->p_filesz - 1] != 0) {
error_setg(&err, "Invalid PT_INTERP entry");
@@ -3103,7 +3089,7 @@ static void load_elf_image(const char *image_name, int image_fd,
}
*pinterp_name = g_steal_pointer(&interp_name);
} else if (eppnt->p_type == PT_GNU_PROPERTY) {
- if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
+ if (!parse_elf_properties(src, info, eppnt, &err)) {
goto exit_errmsg;
}
} else if (eppnt->p_type == PT_GNU_STACK) {
@@ -3256,9 +3242,9 @@ static void load_elf_image(const char *image_name, int image_fd,
* but no backing file segment.
*/
if (eppnt->p_filesz != 0) {
- error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+ error = imgsrc_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
elf_prot, MAP_PRIVATE | MAP_FIXED,
- image_fd, eppnt->p_offset - vaddr_po);
+ src, eppnt->p_offset - vaddr_po);
if (error == -1) {
goto exit_mmap;
}
@@ -3290,20 +3276,11 @@ static void load_elf_image(const char *image_name, int image_fd,
#ifdef TARGET_MIPS
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
Mips_elf_abiflags_v0 abiflags;
- if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
- error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
+
+ if (!imgsrc_read(&abiflags, eppnt->p_offset, sizeof(abiflags),
+ src, &err)) {
goto exit_errmsg;
}
- if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
- memcpy(&abiflags, bprm_buf + eppnt->p_offset,
- sizeof(Mips_elf_abiflags_v0));
- } else {
- retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
- eppnt->p_offset);
- if (retval != sizeof(Mips_elf_abiflags_v0)) {
- goto exit_read;
- }
- }
bswap_mips_abiflags(&abiflags);
info->fp_abi = abiflags.fp_abi;
#endif
@@ -3316,23 +3293,16 @@ static void load_elf_image(const char *image_name, int image_fd,
}
if (qemu_log_enabled()) {
- load_symbols(ehdr, image_fd, load_bias);
+ load_symbols(ehdr, src->fd, load_bias);
}
- debuginfo_report_elf(image_name, image_fd, load_bias);
+ debuginfo_report_elf(image_name, src->fd, load_bias);
mmap_unlock();
- close(image_fd);
+ close(src->fd);
return;
- exit_read:
- if (retval >= 0) {
- error_setg(&err, "Incomplete read of file header");
- } else {
- error_setg_errno(&err, errno, "Error reading file header");
- }
- goto exit_errmsg;
exit_mmap:
error_setg_errno(&err, errno, "Error mapping file");
goto exit_errmsg;
@@ -3345,6 +3315,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
char bprm_buf[BPRM_BUF_SIZE])
{
struct elfhdr ehdr;
+ ImageSource src;
int fd, retval;
Error *err = NULL;
@@ -3362,11 +3333,11 @@ static void load_elf_interp(const char *filename, struct image_info *info,
exit(-1);
}
- if (retval < BPRM_BUF_SIZE) {
- memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
- }
+ src.fd = fd;
+ src.cache = bprm_buf;
+ src.cache_size = retval;
- load_elf_image(filename, fd, info, &ehdr, NULL, bprm_buf);
+ load_elf_image(filename, &src, info, &ehdr, NULL);
}
static int symfind(const void *s0, const void *s1)
@@ -3577,8 +3548,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
info->start_mmap = (abi_ulong)ELF_START_MMAP;
- load_elf_image(bprm->filename, bprm->fd, info,
- &ehdr, &elf_interpreter, bprm->buf);
+ load_elf_image(bprm->filename, &bprm->src, info, &ehdr, &elf_interpreter);
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 05/15] linux-user: Use ImageSource in load_symbols
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (3 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 04/15] linux-user: Use ImageSource in load_elf_image Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 06/15] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
` (10 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Aside from the section headers, we're unlikely to hit the
ImageSource cache on guest executables. But the interface
for imgsrc_read_* is better.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 87 ++++++++++++++++++++++++--------------------
1 file changed, 48 insertions(+), 39 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f3511ae766..19d3cac039 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2048,7 +2048,8 @@ static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
#ifdef USE_ELF_CORE_DUMP
static int elf_core_dump(int, const CPUArchState *);
#endif /* USE_ELF_CORE_DUMP */
-static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
+static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
+ abi_ulong load_bias);
/* Verify the portions of EHDR within E_IDENT for the target.
This can be performed before bswapping the entire header. */
@@ -3293,7 +3294,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
}
if (qemu_log_enabled()) {
- load_symbols(ehdr, src->fd, load_bias);
+ load_symbols(ehdr, src, load_bias);
}
debuginfo_report_elf(image_name, src->fd, load_bias);
@@ -3384,19 +3385,20 @@ static int symcmp(const void *s0, const void *s1)
}
/* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
+static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
+ abi_ulong load_bias)
{
int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
- uint64_t segsz;
- struct elf_shdr *shdr;
+ g_autofree struct elf_shdr *shdr = NULL;
char *strings = NULL;
- struct syminfo *s = NULL;
- struct elf_sym *new_syms, *syms = NULL;
+ struct elf_sym *syms = NULL;
+ struct elf_sym *new_syms;
+ uint64_t segsz;
shnum = hdr->e_shnum;
- i = shnum * sizeof(struct elf_shdr);
- shdr = (struct elf_shdr *)alloca(i);
- if (pread(fd, shdr, i, hdr->e_shoff) != i) {
+ shdr = imgsrc_read_alloc(hdr->e_shoff, shnum * sizeof(struct elf_shdr),
+ src, NULL);
+ if (shdr == NULL) {
return;
}
@@ -3414,31 +3416,33 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
found:
/* Now know where the strtab and symtab are. Snarf them. */
- s = g_try_new(struct syminfo, 1);
- if (!s) {
- goto give_up;
- }
segsz = shdr[str_idx].sh_size;
- s->disas_strtab = strings = g_try_malloc(segsz);
- if (!strings ||
- pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) {
+ strings = g_try_malloc(segsz);
+ if (!strings) {
+ goto give_up;
+ }
+ if (!imgsrc_read(strings, shdr[str_idx].sh_offset, segsz, src, NULL)) {
goto give_up;
}
segsz = shdr[sym_idx].sh_size;
- syms = g_try_malloc(segsz);
- if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) {
- goto give_up;
- }
-
if (segsz / sizeof(struct elf_sym) > INT_MAX) {
- /* Implausibly large symbol table: give up rather than ploughing
- * on with the number of symbols calculation overflowing
+ /*
+ * Implausibly large symbol table: give up rather than ploughing
+ * on with the number of symbols calculation overflowing.
*/
goto give_up;
}
nsyms = segsz / sizeof(struct elf_sym);
+ syms = g_try_malloc(segsz);
+ if (!syms) {
+ goto give_up;
+ }
+ if (!imgsrc_read(syms, shdr[sym_idx].sh_offset, segsz, src, NULL)) {
+ goto give_up;
+ }
+
for (i = 0; i < nsyms; ) {
bswap_sym(syms + i);
/* Throw away entries which we do not need. */
@@ -3463,10 +3467,12 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
goto give_up;
}
- /* Attempt to free the storage associated with the local symbols
- that we threw away. Whether or not this has any effect on the
- memory allocation depends on the malloc implementation and how
- many symbols we managed to discard. */
+ /*
+ * Attempt to free the storage associated with the local symbols
+ * that we threw away. Whether or not this has any effect on the
+ * memory allocation depends on the malloc implementation and how
+ * many symbols we managed to discard.
+ */
new_syms = g_try_renew(struct elf_sym, syms, nsyms);
if (new_syms == NULL) {
goto give_up;
@@ -3475,20 +3481,23 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
qsort(syms, nsyms, sizeof(*syms), symcmp);
- s->disas_num_syms = nsyms;
-#if ELF_CLASS == ELFCLASS32
- s->disas_symtab.elf32 = syms;
-#else
- s->disas_symtab.elf64 = syms;
-#endif
- s->lookup_symbol = lookup_symbolxx;
- s->next = syminfos;
- syminfos = s;
+ {
+ struct syminfo *s = g_new(struct syminfo, 1);
+ s->disas_strtab = strings;
+ s->disas_num_syms = nsyms;
+#if ELF_CLASS == ELFCLASS32
+ s->disas_symtab.elf32 = syms;
+#else
+ s->disas_symtab.elf64 = syms;
+#endif
+ s->lookup_symbol = lookup_symbolxx;
+ s->next = syminfos;
+ syminfos = s;
+ }
return;
-give_up:
- g_free(s);
+ give_up:
g_free(strings);
g_free(syms);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 06/15] linux-user: Replace bprm->fd with bprm->src.fd
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (4 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 05/15] linux-user: Use ImageSource in load_symbols Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 07/15] linux-user: Load vdso image if available Richard Henderson
` (9 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd, Philippe Mathieu-Daudé
There are only a couple of uses of bprm->fd remaining.
Migrate to the other field.
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/loader.h | 1 -
linux-user/flatload.c | 8 ++++----
linux-user/linuxload.c | 5 ++---
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/linux-user/loader.h b/linux-user/loader.h
index 311d20f5d1..5b4cdddd50 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -74,7 +74,6 @@ struct linux_binprm {
char buf[BPRM_BUF_SIZE] __attribute__((aligned));
ImageSource src;
abi_ulong p;
- int fd;
int e_uid, e_gid;
int argc, envc;
char **argv;
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 8f5e9f489b..15e3ec5f6b 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -463,7 +463,7 @@ static int load_flat_file(struct linux_binprm * bprm,
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
textpos = target_mmap(0, text_len, PROT_READ|PROT_EXEC,
- MAP_PRIVATE, bprm->fd, 0);
+ MAP_PRIVATE, bprm->src.fd, 0);
if (textpos == -1) {
fprintf(stderr, "Unable to mmap process text\n");
return -1;
@@ -490,7 +490,7 @@ static int load_flat_file(struct linux_binprm * bprm,
} else
#endif
{
- result = target_pread(bprm->fd, datapos,
+ result = target_pread(bprm->src.fd, datapos,
data_len + (relocs * sizeof(abi_ulong)),
fpos);
}
@@ -540,10 +540,10 @@ static int load_flat_file(struct linux_binprm * bprm,
else
#endif
{
- result = target_pread(bprm->fd, textpos,
+ result = target_pread(bprm->src.fd, textpos,
text_len, 0);
if (result >= 0) {
- result = target_pread(bprm->fd, datapos,
+ result = target_pread(bprm->src.fd, datapos,
data_len + (relocs * sizeof(abi_ulong)),
ntohl(hdr->data_start));
}
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 5b7e9ab983..4a794f8cea 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -39,7 +39,7 @@ static int prepare_binprm(struct linux_binprm *bprm)
int mode;
int retval;
- if (fstat(bprm->fd, &st) < 0) {
+ if (fstat(bprm->src.fd, &st) < 0) {
return -errno;
}
@@ -69,7 +69,7 @@ static int prepare_binprm(struct linux_binprm *bprm)
bprm->e_gid = st.st_gid;
}
- retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+ retval = read(bprm->src.fd, bprm->buf, BPRM_BUF_SIZE);
if (retval < 0) {
perror("prepare_binprm");
exit(-1);
@@ -144,7 +144,6 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
{
int retval;
- bprm->fd = fdexec;
bprm->src.fd = fdexec;
bprm->filename = (char *)filename;
bprm->argc = count(argv);
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 07/15] linux-user: Load vdso image if available
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (5 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 06/15] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 08/15] linux-user: Add gen-vdso tool Richard Henderson
` (8 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
The vdso image will be pre-processed into a C data array, with
a simple list of relocations to perform, and identifying the
location of signal trampolines.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 87 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 78 insertions(+), 9 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 19d3cac039..5025611886 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -33,6 +33,19 @@
#undef ELF_ARCH
#endif
+#ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE
+#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 */
@@ -2291,7 +2304,8 @@ static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong s
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
struct elfhdr *exec,
struct image_info *info,
- struct image_info *interp_info)
+ struct image_info *interp_info,
+ struct image_info *vdso_info)
{
abi_ulong sp;
abi_ulong u_argc, u_argv, u_envp, u_auxv;
@@ -2379,10 +2393,15 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
}
size = (DLINFO_ITEMS + 1) * 2;
- if (k_base_platform)
+ if (k_base_platform) {
size += 2;
- if (k_platform)
+ }
+ if (k_platform) {
size += 2;
+ }
+ if (vdso_info) {
+ size += 2;
+ }
#ifdef DLINFO_ARCH_ITEMS
size += DLINFO_ARCH_ITEMS * 2;
#endif
@@ -2464,6 +2483,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
if (u_platform) {
NEW_AUX_ENT(AT_PLATFORM, u_platform);
}
+ if (vdso_info) {
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, vdso_info->load_addr);
+ }
NEW_AUX_ENT (AT_NULL, 0);
#undef NEW_AUX_ENT
@@ -3341,6 +3363,49 @@ static void load_elf_interp(const char *filename, struct image_info *info,
load_elf_image(filename, &src, info, &ehdr, NULL);
}
+#ifndef vdso_image_info
+#define vdso_image_info() NULL
+#endif
+
+static void load_elf_vdso(struct image_info *info, const VdsoImageInfo *vdso)
+{
+ ImageSource src;
+ struct elfhdr ehdr;
+ abi_ulong load_bias, load_addr;
+
+ src.fd = -1;
+ src.cache = vdso->image;
+ src.cache_size = vdso->image_size;
+
+ load_elf_image("<internal-vdso>", &src, info, &ehdr, NULL);
+ load_addr = info->load_addr;
+ load_bias = info->load_bias;
+
+ /*
+ * We need to relocate the VDSO image. The one built into the kernel
+ * is built for a fixed address. The one built for QEMU is not, since
+ * that requires close control of the guest address space.
+ * We pre-processed the image to locate all of the addresses that need
+ * to be updated.
+ */
+ for (unsigned i = 0, n = vdso->reloc_count; i < n; i++) {
+ abi_ulong *addr = g2h_untagged(load_addr + vdso->relocs[i]);
+ *addr = tswapal(tswapal(*addr) + load_bias);
+ }
+
+ /* Install signal trampolines, if present. */
+ if (vdso->sigreturn_ofs) {
+ default_sigreturn = load_addr + vdso->sigreturn_ofs;
+ }
+ if (vdso->rt_sigreturn_ofs) {
+ default_rt_sigreturn = load_addr + vdso->rt_sigreturn_ofs;
+ }
+
+ /* Mark the VDSO writable segment read-only. */
+ target_mprotect(info->start_data, info->end_data - info->start_data,
+ PROT_READ);
+}
+
static int symfind(const void *s0, const void *s1)
{
struct elf_sym *sym = (struct elf_sym *)s1;
@@ -3546,7 +3611,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
* and let elf_load_image do any swapping that may be required.
*/
struct elfhdr ehdr;
- struct image_info interp_info;
+ struct image_info interp_info, vdso_info;
char *elf_interpreter = NULL;
char *scratch;
@@ -3629,10 +3694,13 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
}
/*
- * TODO: load a vdso, which would also contain the signal trampolines.
- * Otherwise, allocate a private page to hold them.
+ * Load a vdso if available, which will amongst other things contain the
+ * signal trampolines. Otherwise, allocate a separate page for them.
*/
- if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
+ const VdsoImageInfo *vdso = vdso_image_info();
+ if (vdso) {
+ load_elf_vdso(&vdso_info, vdso);
+ } else if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -3644,8 +3712,9 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
}
- bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr,
- info, (elf_interpreter ? &interp_info : NULL));
+ bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr, info,
+ elf_interpreter ? &interp_info : NULL,
+ vdso ? &vdso_info : NULL);
info->start_stack = bprm->p;
/* If we have an interpreter, set that as the program's entry point.
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 08/15] linux-user: Add gen-vdso tool
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (6 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 07/15] linux-user: Load vdso image if available Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 09/15] linux-user/aarch64: Add vdso and use it for rt_sigreturn Richard Henderson
` (7 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
This tool will be used for post-processing the linked vdso image,
turning it into something that is easy to include into elfload.c.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/gen-vdso.c | 223 ++++++++++++++++++++++++
linux-user/gen-vdso-elfn.c.inc | 306 +++++++++++++++++++++++++++++++++
linux-user/meson.build | 6 +-
3 files changed, 534 insertions(+), 1 deletion(-)
create mode 100644 linux-user/gen-vdso.c
create mode 100644 linux-user/gen-vdso-elfn.c.inc
diff --git a/linux-user/gen-vdso.c b/linux-user/gen-vdso.c
new file mode 100644
index 0000000000..0550804ea0
--- /dev/null
+++ b/linux-user/gen-vdso.c
@@ -0,0 +1,223 @@
+/*
+ * Post-process a vdso elf image for inclusion into qemu.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <endian.h>
+#include <unistd.h>
+#include "elf.h"
+
+
+#define bswap_(p) _Generic(*(p), \
+ uint16_t: __builtin_bswap16, \
+ uint32_t: __builtin_bswap32, \
+ uint64_t: __builtin_bswap64, \
+ int16_t: __builtin_bswap16, \
+ int32_t: __builtin_bswap32, \
+ int64_t: __builtin_bswap64)
+#define bswaps(p) (*(p) = bswap_(p)(*(p)))
+
+static void output_reloc(FILE *outf, void *buf, void *loc)
+{
+ fprintf(outf, " 0x%08lx,\n", (unsigned long)(loc - buf));
+}
+
+static const char *sigreturn_sym;
+static const char *rt_sigreturn_sym;
+
+static unsigned sigreturn_addr;
+static unsigned rt_sigreturn_addr;
+
+#define N 32
+#define elfN(x) elf32_##x
+#define ElfN(x) Elf32_##x
+#include "gen-vdso-elfn.c.inc"
+#undef N
+#undef elfN
+#undef ElfN
+
+#define N 64
+#define elfN(x) elf64_##x
+#define ElfN(x) Elf64_##x
+#include "gen-vdso-elfn.c.inc"
+#undef N
+#undef elfN
+#undef ElfN
+
+
+int main(int argc, char **argv)
+{
+ FILE *inf, *outf;
+ long total_len;
+ const char *prefix = "vdso";
+ const char *inf_name;
+ const char *outf_name = NULL;
+ unsigned char *buf;
+ bool need_bswap;
+
+ while (1) {
+ int opt = getopt(argc, argv, "o:p:r:s:");
+ if (opt < 0) {
+ break;
+ }
+ switch (opt) {
+ case 'o':
+ outf_name = optarg;
+ break;
+ case 'p':
+ prefix = optarg;
+ break;
+ case 'r':
+ rt_sigreturn_sym = optarg;
+ break;
+ case 's':
+ sigreturn_sym = optarg;
+ break;
+ default:
+ usage:
+ fprintf(stderr, "usage: [-p prefix] [-r rt-sigreturn-name] "
+ "[-s sigreturn-name] -o output-file input-file\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (optind >= argc || outf_name == NULL) {
+ goto usage;
+ }
+ inf_name = argv[optind];
+
+ /*
+ * Open the input and output files.
+ */
+ inf = fopen(inf_name, "rb");
+ if (inf == NULL) {
+ goto perror_inf;
+ }
+ outf = fopen(outf_name, "w");
+ if (outf == NULL) {
+ goto perror_outf;
+ }
+
+ /*
+ * Read the input file into a buffer.
+ * We expect the vdso to be small, on the order of one page,
+ * therefore we do not expect a partial read.
+ */
+ fseek(inf, 0, SEEK_END);
+ total_len = ftell(inf);
+ fseek(inf, 0, SEEK_SET);
+
+ buf = malloc(total_len);
+ if (buf == NULL) {
+ goto perror_inf;
+ }
+
+ errno = 0;
+ if (fread(buf, 1, total_len, inf) != total_len) {
+ if (errno) {
+ goto perror_inf;
+ }
+ fprintf(stderr, "%s: incomplete read\n", inf_name);
+ return EXIT_FAILURE;
+ }
+ fclose(inf);
+
+ /*
+ * Write out the vdso image now, before we make local changes.
+ */
+
+ fprintf(outf,
+ "/* Automatically generated from linux-user/gen-vdso.c. */\n"
+ "\n"
+ "static const uint8_t %s_image[] = {",
+ prefix);
+ for (long i = 0; i < total_len; ++i) {
+ if (i % 12 == 0) {
+ fputs("\n ", outf);
+ }
+ fprintf(outf, " 0x%02x,", buf[i]);
+ }
+ fprintf(outf, "\n};\n\n");
+
+ /*
+ * Identify which elf flavor we're processing.
+ * The first 16 bytes of the file are e_ident.
+ */
+
+ if (buf[EI_MAG0] != ELFMAG0 || buf[EI_MAG1] != ELFMAG1 ||
+ buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3) {
+ fprintf(stderr, "%s: not an elf file\n", inf_name);
+ return EXIT_FAILURE;
+ }
+ switch (buf[EI_DATA]) {
+ case ELFDATA2LSB:
+ need_bswap = BYTE_ORDER != LITTLE_ENDIAN;
+ break;
+ case ELFDATA2MSB:
+ need_bswap = BYTE_ORDER != BIG_ENDIAN;
+ break;
+ default:
+ fprintf(stderr, "%s: invalid elf EI_DATA (%u)\n",
+ inf_name, buf[EI_DATA]);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * We need to relocate the VDSO image. The one built into the kernel
+ * is built for a fixed address. The one we built for QEMU is not,
+ * since that requires close control of the guest address space.
+ *
+ * Output relocation addresses as we go.
+ */
+
+ fprintf(outf, "static const unsigned %s_relocs[] = {\n", prefix);
+
+ switch (buf[EI_CLASS]) {
+ case ELFCLASS32:
+ elf32_process(outf, buf, need_bswap);
+ break;
+ case ELFCLASS64:
+ elf64_process(outf, buf, need_bswap);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid elf EI_CLASS (%u)\n",
+ inf_name, buf[EI_CLASS]);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(outf, "};\n\n"); /* end vdso_relocs. */
+
+ fprintf(outf, "static const VdsoImageInfo %s_image_info = {\n", prefix);
+ fprintf(outf, " .image = %s_image,\n", prefix);
+ fprintf(outf, " .relocs = %s_relocs,\n", prefix);
+ fprintf(outf, " .image_size = sizeof(%s_image),\n", prefix);
+ fprintf(outf, " .reloc_count = ARRAY_SIZE(%s_relocs),\n", prefix);
+ fprintf(outf, " .sigreturn_ofs = 0x%x,\n", sigreturn_addr);
+ fprintf(outf, " .rt_sigreturn_ofs = 0x%x,\n", rt_sigreturn_addr);
+ fprintf(outf, "};\n");
+
+ /*
+ * Everything should have gone well.
+ */
+ if (fclose(outf)) {
+ goto perror_outf;
+ }
+ return EXIT_SUCCESS;
+
+ perror_inf:
+ perror(inf_name);
+ return EXIT_FAILURE;
+
+ perror_outf:
+ perror(outf_name);
+ return EXIT_FAILURE;
+}
diff --git a/linux-user/gen-vdso-elfn.c.inc b/linux-user/gen-vdso-elfn.c.inc
new file mode 100644
index 0000000000..1a5b0099fd
--- /dev/null
+++ b/linux-user/gen-vdso-elfn.c.inc
@@ -0,0 +1,306 @@
+/*
+ * Post-process a vdso elf image for inclusion into qemu.
+ * Elf size specialization.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+static void elfN(bswap_ehdr)(ElfN(Ehdr) *ehdr)
+{
+ bswaps(&ehdr->e_type); /* Object file type */
+ bswaps(&ehdr->e_machine); /* Architecture */
+ bswaps(&ehdr->e_version); /* Object file version */
+ bswaps(&ehdr->e_entry); /* Entry point virtual address */
+ bswaps(&ehdr->e_phoff); /* Program header table file offset */
+ bswaps(&ehdr->e_shoff); /* Section header table file offset */
+ bswaps(&ehdr->e_flags); /* Processor-specific flags */
+ bswaps(&ehdr->e_ehsize); /* ELF header size in bytes */
+ bswaps(&ehdr->e_phentsize); /* Program header table entry size */
+ bswaps(&ehdr->e_phnum); /* Program header table entry count */
+ bswaps(&ehdr->e_shentsize); /* Section header table entry size */
+ bswaps(&ehdr->e_shnum); /* Section header table entry count */
+ bswaps(&ehdr->e_shstrndx); /* Section header string table index */
+}
+
+static void elfN(bswap_phdr)(ElfN(Phdr) *phdr)
+{
+ bswaps(&phdr->p_type); /* Segment type */
+ bswaps(&phdr->p_flags); /* Segment flags */
+ bswaps(&phdr->p_offset); /* Segment file offset */
+ bswaps(&phdr->p_vaddr); /* Segment virtual address */
+ bswaps(&phdr->p_paddr); /* Segment physical address */
+ bswaps(&phdr->p_filesz); /* Segment size in file */
+ bswaps(&phdr->p_memsz); /* Segment size in memory */
+ bswaps(&phdr->p_align); /* Segment alignment */
+}
+
+static void elfN(bswap_shdr)(ElfN(Shdr) *shdr)
+{
+ bswaps(&shdr->sh_name);
+ bswaps(&shdr->sh_type);
+ bswaps(&shdr->sh_flags);
+ bswaps(&shdr->sh_addr);
+ bswaps(&shdr->sh_offset);
+ bswaps(&shdr->sh_size);
+ bswaps(&shdr->sh_link);
+ bswaps(&shdr->sh_info);
+ bswaps(&shdr->sh_addralign);
+ bswaps(&shdr->sh_entsize);
+}
+
+static void elfN(bswap_sym)(ElfN(Sym) *sym)
+{
+ bswaps(&sym->st_name);
+ bswaps(&sym->st_value);
+ bswaps(&sym->st_size);
+ bswaps(&sym->st_shndx);
+}
+
+static void elfN(bswap_dyn)(ElfN(Dyn) *dyn)
+{
+ bswaps(&dyn->d_tag); /* Dynamic type tag */
+ bswaps(&dyn->d_un.d_ptr); /* Dynamic ptr or val, in union */
+}
+
+static void elfN(search_symtab)(ElfN(Shdr) *shdr, unsigned sym_idx,
+ void *buf, bool need_bswap)
+{
+ unsigned str_idx = shdr[sym_idx].sh_link;
+ ElfN(Sym) *sym = buf + shdr[sym_idx].sh_offset;
+ unsigned sym_n = shdr[sym_idx].sh_size / sizeof(*sym);
+ const char *str = buf + shdr[str_idx].sh_offset;
+
+ for (unsigned i = 0; i < sym_n; ++i) {
+ const char *name;
+
+ if (need_bswap) {
+ elfN(bswap_sym)(sym + i);
+ }
+ name = str + sym[i].st_name;
+
+ if (sigreturn_sym && strcmp(sigreturn_sym, name) == 0) {
+ sigreturn_addr = sym[i].st_value;
+ }
+ if (rt_sigreturn_sym && strcmp(rt_sigreturn_sym, name) == 0) {
+ rt_sigreturn_addr = sym[i].st_value;
+ }
+ }
+}
+
+static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
+{
+ ElfN(Ehdr) *ehdr = buf;
+ ElfN(Phdr) *phdr;
+ ElfN(Shdr) *shdr;
+ unsigned phnum, shnum;
+ unsigned dynamic_ofs = 0;
+ unsigned dynamic_addr = 0;
+ unsigned symtab_idx = 0;
+ unsigned dynsym_idx = 0;
+ unsigned first_segsz = 0;
+ int errors = 0;
+
+ if (need_bswap) {
+ elfN(bswap_ehdr)(ehdr);
+ }
+
+ phnum = ehdr->e_phnum;
+ phdr = buf + ehdr->e_phoff;
+ if (need_bswap) {
+ for (unsigned i = 0; i < phnum; ++i) {
+ elfN(bswap_phdr)(phdr + i);
+ }
+ }
+
+ shnum = ehdr->e_shnum;
+ shdr = buf + ehdr->e_shoff;
+ if (need_bswap) {
+ for (unsigned i = 0; i < shnum; ++i) {
+ elfN(bswap_shdr)(shdr + i);
+ }
+ }
+ for (unsigned i = 0; i < shnum; ++i) {
+ switch (shdr[i].sh_type) {
+ case SHT_SYMTAB:
+ symtab_idx = i;
+ break;
+ case SHT_DYNSYM:
+ dynsym_idx = i;
+ break;
+ }
+ }
+
+ /*
+ * Validate the VDSO is created as we expect: that PT_PHDR,
+ * PT_DYNAMIC, and PT_NOTE located in a writable data segment.
+ * PHDR and DYNAMIC require relocation, and NOTE will get the
+ * linux version number.
+ */
+ for (unsigned i = 0; i < phnum; ++i) {
+ if (phdr[i].p_type == PT_LOAD && phdr[i].p_vaddr == 0) {
+ if (first_segsz != 0) {
+ fprintf(stderr, "Multiple load segments covering EHDR\n");
+ errors++;
+ }
+ if (phdr[i].p_offset != 0) {
+ fprintf(stderr, "First vdso segment does not cover EHDR\n");
+ errors++;
+ }
+ if (phdr[i].p_vaddr != 0) {
+ fprintf(stderr, "First vdso segment not loaded at address 0\n");
+ errors++;
+ }
+ if ((phdr[i].p_flags & (PF_R | PF_W)) != (PF_R | PF_W)) {
+ fprintf(stderr, "First vdso segment is not read-write\n");
+ errors++;
+ }
+ first_segsz = phdr[i].p_filesz;
+ if (first_segsz < ehdr->e_phoff + phnum * sizeof(*phdr)) {
+ fprintf(stderr, "First vdso segment does not cover PHDRs\n");
+ errors++;
+ }
+ }
+ }
+ for (unsigned i = 0; i < phnum; ++i) {
+ const char *which;
+
+ switch (phdr[i].p_type) {
+ case PT_PHDR:
+ which = "PT_PHDR";
+ break;
+ case PT_NOTE:
+ which = "PT_NOTE";
+ break;
+ case PT_DYNAMIC:
+ dynamic_ofs = phdr[i].p_offset;
+ dynamic_addr = phdr[i].p_vaddr;
+ which = "PT_DYNAMIC";
+ break;
+ default:
+ continue;
+ }
+ if (first_segsz < phdr[i].p_vaddr + phdr[i].p_filesz) {
+ fprintf(stderr, "First vdso segment does not cover %s\n", which);
+ errors++;
+ }
+ }
+ if (errors) {
+ exit(EXIT_FAILURE);
+ }
+
+ /* Relocate the program headers. */
+ for (unsigned i = 0; i < phnum; ++i) {
+ output_reloc(outf, buf, &phdr[i].p_vaddr);
+ output_reloc(outf, buf, &phdr[i].p_paddr);
+ }
+
+ /* Relocate the DYNAMIC entries. */
+ if (dynamic_addr) {
+ ElfN(Dyn) *dyn = buf + dynamic_ofs;
+ __typeof(dyn->d_tag) tag;
+
+ do {
+
+ if (need_bswap) {
+ elfN(bswap_dyn)(dyn);
+ }
+ tag = dyn->d_tag;
+
+ switch (tag) {
+ case DT_HASH:
+ case DT_SYMTAB:
+ case DT_STRTAB:
+ case DT_VERDEF:
+ case DT_VERSYM:
+ case DT_PLTGOT:
+ case DT_ADDRRNGLO ... DT_ADDRRNGHI:
+ /* These entries store an address in the entry. */
+ output_reloc(outf, buf, &dyn->d_un.d_val);
+ break;
+
+ case DT_NULL:
+ case DT_STRSZ:
+ case DT_SONAME:
+ case DT_DEBUG:
+ case DT_FLAGS:
+ case DT_FLAGS_1:
+ case DT_SYMBOLIC:
+ case DT_BIND_NOW:
+ case DT_VERDEFNUM:
+ case DT_VALRNGLO ... DT_VALRNGHI:
+ /* These entries store an integer in the entry. */
+ break;
+
+ case DT_SYMENT:
+ if (dyn->d_un.d_val != sizeof(ElfN(Sym))) {
+ fprintf(stderr, "VDSO has incorrect dynamic symbol size\n");
+ errors++;
+ }
+ break;
+
+ case DT_REL:
+ case DT_RELSZ:
+ case DT_RELA:
+ case DT_RELASZ:
+ /*
+ * These entries indicate that the VDSO was built incorrectly.
+ * It should not have any real relocations.
+ * ??? The RISC-V toolchain will emit these even when there
+ * are no relocations. Validate zeros.
+ */
+ if (dyn->d_un.d_val != 0) {
+ fprintf(stderr, "VDSO has dynamic relocations\n");
+ errors++;
+ }
+ break;
+ case DT_RELENT:
+ case DT_RELAENT:
+ case DT_TEXTREL:
+ /* These entries store an integer in the entry. */
+ /* Should not be required; see above. */
+ break;
+
+ case DT_NEEDED:
+ case DT_VERNEED:
+ case DT_PLTREL:
+ case DT_JMPREL:
+ case DT_RPATH:
+ case DT_RUNPATH:
+ fprintf(stderr, "VDSO has external dependencies\n");
+ errors++;
+ break;
+
+ default:
+ /* This is probably something target specific. */
+ fprintf(stderr, "VDSO has unknown DYNAMIC entry (%lx)\n",
+ (unsigned long)tag);
+ errors++;
+ break;
+ }
+ dyn++;
+ } while (tag != DT_NULL);
+ if (errors) {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Relocate the dynamic symbol table. */
+ if (dynsym_idx) {
+ ElfN(Sym) *sym = buf + shdr[dynsym_idx].sh_offset;
+ unsigned sym_n = shdr[dynsym_idx].sh_size / sizeof(*sym);
+
+ for (unsigned i = 0; i < sym_n; ++i) {
+ output_reloc(outf, buf, &sym[i].st_value);
+ }
+ }
+
+ /* Search both dynsym and symtab for the signal return symbols. */
+ if (dynsym_idx) {
+ elfN(search_symtab)(shdr, dynsym_idx, buf, need_bswap);
+ }
+ if (symtab_idx) {
+ elfN(search_symtab)(shdr, symtab_idx, buf, need_bswap);
+ }
+}
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 7171dc60be..e4cb70ed2d 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -28,9 +28,13 @@ linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
linux_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING', if_true: files('semihost.c'))
-
syscall_nr_generators = {}
+gen_vdso_exe = executable('gen-vdso', 'gen-vdso.c',
+ native: true, build_by_default: false)
+gen_vdso = generator(gen_vdso_exe, output: '@BASENAME@.c.inc',
+ arguments: ['-o', '@OUTPUT@', '@EXTRA_ARGS@', '@INPUT@'])
+
subdir('alpha')
subdir('arm')
subdir('hppa')
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 09/15] linux-user/aarch64: Add vdso and use it for rt_sigreturn
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (7 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 08/15] linux-user: Add gen-vdso tool Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 10/15] target/arm: Add isar_feature_aa32_a32 Richard Henderson
` (6 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Building of the vdsos are not actually wired up to anything, since
we require a cross-compiler. Just check in the files for now.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 4 ++
linux-user/aarch64/Makefile.vdso | 11 +++++
linux-user/aarch64/meson.build | 11 +++++
linux-user/aarch64/vdso-be.so | Bin 0 -> 6000 bytes
linux-user/aarch64/vdso-le.so | Bin 0 -> 6000 bytes
linux-user/aarch64/vdso.S | 77 +++++++++++++++++++++++++++++++
linux-user/aarch64/vdso.ld | 74 +++++++++++++++++++++++++++++
linux-user/meson.build | 1 +
8 files changed, 178 insertions(+)
create mode 100644 linux-user/aarch64/Makefile.vdso
create mode 100644 linux-user/aarch64/meson.build
create mode 100755 linux-user/aarch64/vdso-be.so
create mode 100755 linux-user/aarch64/vdso-le.so
create mode 100644 linux-user/aarch64/vdso.S
create mode 100644 linux-user/aarch64/vdso.ld
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5025611886..aff58cabfd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -576,10 +576,14 @@ static const char *get_elf_platform(void)
#define ELF_CLASS ELFCLASS64
#if TARGET_BIG_ENDIAN
# define ELF_PLATFORM "aarch64_be"
+# include "vdso-be.c.inc"
#else
# define ELF_PLATFORM "aarch64"
+# include "vdso-le.c.inc"
#endif
+#define vdso_image_info() &vdso_image_info
+
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
diff --git a/linux-user/aarch64/Makefile.vdso b/linux-user/aarch64/Makefile.vdso
new file mode 100644
index 0000000000..97ede674e5
--- /dev/null
+++ b/linux-user/aarch64/Makefile.vdso
@@ -0,0 +1,11 @@
+CROSS_CC ?= aarch64-linux-gnu-gcc
+LDFLAGS := -nostdlib -shared -Wl,-T,vdso.ld \
+ -Wl,-h,linux-vdso.so.1 -Wl,--hash-style=sysv -Wl,--build-id=sha1
+
+all: vdso-le.so vdso-be.so
+
+vdso-le.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mlittle-endian vdso.S -o $@
+
+vdso-be.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mbig-endian vdso.S -o $@
diff --git a/linux-user/aarch64/meson.build b/linux-user/aarch64/meson.build
new file mode 100644
index 0000000000..0b1b3a5560
--- /dev/null
+++ b/linux-user/aarch64/meson.build
@@ -0,0 +1,11 @@
+# ??? There does not seem to be a way to do
+# when: ['TARGET_AARCH64', !'TARGET_WORDS_BIGENDIAN']
+# so we'd need to add TARGET_WORDS_LITTLEENDIAN.
+# In the meantime, build both files for aarch64 and aarch64_be.
+
+gen = [
+ gen_vdso.process('vdso-be.so', extra_args: ['-r', '__kernel_rt_sigreturn']),
+ gen_vdso.process('vdso-le.so', extra_args: ['-r', '__kernel_rt_sigreturn'])
+]
+
+linux_user_ss.add(when: 'TARGET_AARCH64', if_true: gen)
diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so
new file mode 100755
index 0000000000000000000000000000000000000000..b0f4a83e32f300dd41110740a78f3172efbe9d1d
GIT binary patch
literal 6000
zcmeHLJ!~9B6n=ZVBmpPk9D{;nL=NNvA+ip!fbb)<Hol83E{^5=C`mKA+--ap-%qr+
z4(A973sHceNJ&e9L<b#IK$V6DAxwuvLyJOBWZs*3Z*FdLjueoncAVL7-uK>{pLa8(
zym`M|trQ9#*y6)C*k+<AbYvP+Uu%ru6zqct9*4sy@534xJ#waG&|5XMARIuM#vtDZ
zl;B&VWHhs)?<0nn`DHOP593!rAD*Yj{bmvFntm-FXrzD8+}SUPj6RDn!+wHfFBO~K
zZKKcPo_<fDy?=V;0=)jk!ky>7dv&h9-2TnG_s*S9+B=h`Fa4$XQ@LV5=ILKznd9Vt
z$TG*f@FmNSF}}+<!T1zmZ+G`^BM0<*k$lg{K(Qp5<K?p*YyV%kJ_);jjTv(B2mr6A
zc!KpsM9<;Hjn;S6;mM8);c<sA5s5|gM!N5-_mz*d>~Ck!T4RbK*#w}}Mx1oxwn|df
zZ>=YBx|wu`?0TH0txnv#)~Ia_*?PNI-%zX@Lnm<`+O6*9;P}l(zZc@am!P`5a^aFX
z8NL$Ey{6|;z+ck*d3YZ2@6ey$e~ud3e@|mI`-)~?0B^tg@nhB@z;*g~)BYO>wC`~(
z6F(uoiTFF>D&k$l239IMX5Ote2nNr1(+7_UhkI?}Q_(ZNh}=gRE<%p>vF-;kFL?y=
z2;>pSBalZRk3b%QJOX(H@(4U+1e%lEKjVMze>qn2cc`ivf9Lrp4flhue%12fQF+Oc
zA2b{$1e7^ok-XPP$m{$OdCtQvPx%lQo1bb4$v`*2KV^_5`wn39U9so9%jUhp?`O}E
zd=>lG`7I8^X#0QEv?SlRJm<|p(=e8oeAA`9V0?Z`dHgtg%Dtrj_uP*5=;x?s`yYvC
z34O=Se{N{+V~%Fa@*a8gMJN9~!Pb<6wH;nMq4<5^@RF+$e&+Bcb|}JZ+PN`XuMaj}
zE_W}7J(wB5Oas*7<(2s}%Wq>|i?1N6yre2?^JmIxX>kqI>FU{q`KmfwshlgHSLf#!
zs%15r+S-KLCdrfyTlU|l*%0=(I%(}HVwxCiN~_yTV+b2t-CCzr*A28qtfe&wo3(z^
zaA^YJdUrFt87KW#uR9{B283}_T}x`6ST!4HDH4QfJV-fe{|%<mozH<ihqq0a_MB2a
z?-o9PntB$$@~*+>RrZ~rem@f%a*}gJ```tv^3KHffSh+hp!twL-yhbW-la}DJdZE;
zf*_R8#w{{FA>ASTE+*@j`$G`${XxIYNFU-)ad^wo@%-hU5d?Wp6MtC;$rXGz+hv9L
z^L=FB(GH@X*QPDmPS5vT_8o3`Z`u2c)=2RaKbb#ub``74hxI{33hXD+VBT}MslomI
zZy=NPZyIBJAFjI2*mlRi<@nPavCy`lA_$QdhaamzipG|84J~x57#X5KcnIqhRw^<+
k?H{@m-Pn?z%aLtvd?gH{td~T(xA*X$nq~WKMgi;p4~13}umAu6
literal 0
HcmV?d00001
diff --git a/linux-user/aarch64/vdso-le.so b/linux-user/aarch64/vdso-le.so
new file mode 100755
index 0000000000000000000000000000000000000000..975d203e6b999e01221a40fb4d2d1a5dc83d3294
GIT binary patch
literal 6000
zcmeHLL1+|L82&etniw@2TTzJA74}f1PTB~v#Uc}%T@%>EC2G+kJl5SYyEVHjvlE+$
zU=R-#6uh<c)?07&rg+hNdk|62dg!f4dbh;?pLyRn^D-)0=xP2q^S$@||Nq{bf8Gv$
z?@Fms?#tx}X3-rAdfP(A(T>|6BZA1GB5mONRvKm`>gUVRZWF6|XyBlZ6IycLWOrpy
zHXwzo3hp0?L$A+7M|^BfaF<)SfIe=?kazWZOk9;vHXznn{mX9z&!^Yp7+46?2&mn`
zT++U!=Q9!Uz<Ay#oM-WMboM08+&uWxnH_(>m^$>}&wI~*xieq9dRe9%mK)o5Aq4YD
z^OPjA1vO&4ru(S%Z&C=hp%CZ?jhi&?()e<1tt-tzy|90EU#HWm?!VOI>$LwJzULW7
z=$|!n;z=g9(<b^t?-Ohnc^$%I-{3v()ciIhe!u4P2G4Y=VP8pEP;;3R?*mCvM~Ml_
ztJHbd>$nTb^Hr}k@45b>*P)1=cYVLrcDv^qwdL1reW6=Fue2|P_S_yVv^tAR`!6<n
zU7P=XNtNl@lc&_Ueb7Gem8_&M`pfa}ME-ug|6+^mzukOcZ^`=m*mwO8H6T7Qsk>Ni
z)H+mPlxKO!W&N7*8Do`km9fDn7S;dK9Q7}Knj77`C*Wki-FW>v0`7C>el$3Txoa_w
zyP0Jb$SROkAge%Dfvf^q1+ofc704>^o)u`0tUTiX-#^}yx1PwQ3f7a)c7)smOFa$x
z!^!?stpB#@EY=Lrz417U)dX}>lD7!@G|Bf<F-2!utg4`QlkpoO-J9eGC{3?gG#KgJ
zWc)^g-cRyF)C`1MoD~hUUZ99}>QB+9BSGr=_)uRB(dCr!)5a0qn&a`!dgg=i*RTJ8
zj;|W^oMt{vM}NzFnvP!3JcJ!|^i|E9I{IhL=S>|w=C?15)$6@-w>Um&cd4*Mg$Aj~
z)3XyZ)8DYJ<x>z<no{MtiJ6j`nw%qbv~ujoL`5AdmyefDs1p-MDkYVawvlv>M6#&i
zi2ZPxO?Gd&?bpsS`d)}lv^rhiCA+cQskK}6puw?>HNQr7v({^dobQo6-&wRTx?Zo<
z?Ib#?LAKje=e%0mRm}!RqDQvxF8N%<|7fF}Kfo8xaq#;Dik6R?xefQSQ_eN8eX#F<
zt2!BHAJ`Yr|NGd_yFQv9zjxrRSibyrkdJezapr`_{P->a^X!Wo@_|Km%2^DaAKwq4
zoIQwPeB_}HhqVv+I9~(eJS`Z6Z?e|7mASLVXJ^RA_XxOI2V;K30gtm^&f?I=`5aK5
zPfY4BF<8HFVrTi1H6b70H{iS8{{<r--$7uN{c$trzr;?NANvE}51<oI<~H^X==j>f
w2|7B^(GRwTIXSY%{MbJmnL};48QIGAu=#t$gbnlk$#**~e@vf`ue>Aw6>MP?*#H0l
literal 0
HcmV?d00001
diff --git a/linux-user/aarch64/vdso.S b/linux-user/aarch64/vdso.S
new file mode 100644
index 0000000000..41cda7eb24
--- /dev/null
+++ b/linux-user/aarch64/vdso.S
@@ -0,0 +1,77 @@
+/*
+ * aarch64 linux replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+/* ??? These are in include/elf.h, which is not ready for inclusion in asm. */
+#define NT_GNU_PROPERTY_TYPE_0 5
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0)
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1)
+
+#define GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT \
+ (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
+
+ .text
+
+/*
+ * TODO: The kernel makes a big deal of turning off the .cfi directives,
+ * because they cause libgcc to crash, but that's because they're wrong.
+ *
+ * For now, elide the unwind info for __kernel_rt_sigreturn and rely on
+ * the libgcc fallback routine as we have always done. This requires
+ * that the code sequence used be exact.
+ */
+ .align 4
+__kernel_rt_sigreturn:
+ /* No BTI C insn here -- we arrive via RET. */
+ mov x8, #__NR_rt_sigreturn
+ svc #0
+
+ .globl __kernel_rt_sigreturn
+ .type __kernel_rt_sigreturn, %function
+ .size __kernel_rt_sigreturn, . - __kernel_rt_sigreturn
+
+ .align 4
+__kernel_gettimeofday:
+ .cfi_startproc
+ bti c
+ mov x8, #__NR_gettimeofday
+ svc #0
+ ret
+ .cfi_endproc
+
+ .globl __kernel_gettimeofday
+ .type __kernel_gettimeofday, %function
+ .size __kernel_gettimeofday, . - __kernel_gettimeofday
+
+ .align 4
+__kernel_clock_gettime:
+ .cfi_startproc
+ bti c
+ mov x8, #__NR_clock_gettime
+ svc #0
+ ret
+ .cfi_endproc
+
+ .globl __kernel_clock_gettime
+ .type __kernel_clock_gettime, %function
+ .size __kernel_clock_gettime, . - __kernel_clock_gettime
+
+ .align 4
+__kernel_clock_getres:
+ .cfi_startproc
+ bti c
+ mov x8, #__NR_clock_getres
+ svc #0
+ ret
+ .cfi_endproc
+
+ .globl __kernel_clock_getres
+ .type __kernel_clock_getres, %function
+ .size __kernel_clock_getres, . - __kernel_clock_getres
diff --git a/linux-user/aarch64/vdso.ld b/linux-user/aarch64/vdso.ld
new file mode 100644
index 0000000000..579d27638f
--- /dev/null
+++ b/linux-user/aarch64/vdso.ld
@@ -0,0 +1,74 @@
+/*
+ * Linker script for linux aarch64 replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+ LINUX_2.6.39 {
+ global:
+ __kernel_rt_sigreturn;
+ __kernel_gettimeofday;
+ __kernel_clock_gettime;
+ __kernel_clock_getres;
+
+ local: *;
+ };
+}
+
+
+PHDRS {
+ phdr PT_PHDR FLAGS(4) PHDRS;
+ data PT_LOAD FLAGS(6) FILEHDR PHDRS;
+ text PT_LOAD FLAGS(5);
+ dynamic PT_DYNAMIC FLAGS(4);
+ eh_frame_hdr PT_GNU_EH_FRAME;
+ note PT_NOTE FLAGS(4);
+}
+
+SECTIONS {
+ /*
+ * We can't prelink to any address without knowing something about
+ * the virtual memory space of the host, since that leaks over into
+ * the available memory space of the guest.
+ */
+ . = SIZEOF_HEADERS;
+
+ /*
+ * The following, including the FILEHDRS and PHDRS, are modified
+ * when we relocate the binary. We want them to be initially
+ * writable for the relocation; we'll force them read-only after.
+ */
+ .note : { *(.note*) } :data :note
+ .dynamic : { *(.dynamic) } :data :dynamic
+ .dynsym : { *(.dynsym) } :data
+ /*
+ * There ought not be any real read-write data.
+ * But since we manipulated the segment layout,
+ * we have to put these sections somewhere.
+ */
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .rodata : { *(.rodata*) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :data :eh_frame_hdr
+ .eh_frame : { *(.eh_frame) } :data
+
+ . = ALIGN(4096);
+ .text : { *(.text*) } :text =0xd503201f
+}
diff --git a/linux-user/meson.build b/linux-user/meson.build
index e4cb70ed2d..dd24389052 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -35,6 +35,7 @@ gen_vdso_exe = executable('gen-vdso', 'gen-vdso.c',
gen_vdso = generator(gen_vdso_exe, output: '@BASENAME@.c.inc',
arguments: ['-o', '@OUTPUT@', '@EXTRA_ARGS@', '@INPUT@'])
+subdir('aarch64')
subdir('alpha')
subdir('arm')
subdir('hppa')
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 10/15] target/arm: Add isar_feature_aa32_a32
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (8 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 09/15] linux-user/aarch64: Add vdso and use it for rt_sigreturn Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 11/15] linux-user/arm: Add vdso and use it for rt_sigreturn Richard Henderson
` (5 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Add a probe for whether A32 mode is supported.
Fill in the field for the pre-v5 cpus.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 5 +++++
target/arm/tcg/cpu32.c | 7 +++++++
2 files changed, 12 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 88e5accda6..41d05839a2 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3462,6 +3462,11 @@ static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0;
}
+static inline bool isar_feature_aa32_a32(const ARMISARegisters *id)
+{
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, STATE0) != 0;
+}
+
static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
{
return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index 47d2e8e781..ea8ccf59a9 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -145,6 +145,8 @@ static void arm926_initfn(Object *obj)
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1);
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
+ /* Similarly, we need to set STATE0 for A32 support. */
+ cpu->isar.id_pfr0 = FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, STATE0, 1);
}
static void arm946_initfn(Object *obj)
@@ -158,6 +160,9 @@ static void arm946_initfn(Object *obj)
cpu->midr = 0x41059461;
cpu->ctr = 0x0f004006;
cpu->reset_sctlr = 0x00000078;
+
+ /* We need to set STATE0 for A32 support. */
+ cpu->isar.id_pfr0 = FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, STATE0, 1);
}
static void arm1026_initfn(Object *obj)
@@ -187,6 +192,8 @@ static void arm1026_initfn(Object *obj)
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1);
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
+ /* Similarly, we need to set STATE0 for A32 support. */
+ cpu->isar.id_pfr0 = FIELD_DP32(cpu->isar.id_pfr0, ID_PFR0, STATE0, 1);
{
/* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 11/15] linux-user/arm: Add vdso and use it for rt_sigreturn
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (9 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 10/15] target/arm: Add isar_feature_aa32_a32 Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 12/15] linux-user/hppa: " Richard Henderson
` (4 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Building of the vdsos are not actually wired up to anything, since
we require a cross-compiler. Just check in the files for now.
The thumb vdso will only be used for m-profile, as all of our
a-profile cpus support arm mode.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/arm/signal.c | 30 +++--
linux-user/elfload.c | 24 ++++
linux-user/arm/Makefile.vdso | 17 +++
linux-user/arm/meson.build | 18 +++
linux-user/arm/vdso-arm-be.so | Bin 0 -> 5648 bytes
linux-user/arm/vdso-arm-le.so | Bin 0 -> 5648 bytes
linux-user/arm/vdso-thm-be.so | Bin 0 -> 5620 bytes
linux-user/arm/vdso-thm-le.so | Bin 0 -> 5620 bytes
linux-user/arm/vdso.S | 209 ++++++++++++++++++++++++++++++++++
linux-user/arm/vdso.ld | 74 ++++++++++++
10 files changed, 355 insertions(+), 17 deletions(-)
create mode 100644 linux-user/arm/Makefile.vdso
create mode 100755 linux-user/arm/vdso-arm-be.so
create mode 100755 linux-user/arm/vdso-arm-le.so
create mode 100755 linux-user/arm/vdso-thm-be.so
create mode 100755 linux-user/arm/vdso-thm-le.so
create mode 100644 linux-user/arm/vdso.S
create mode 100644 linux-user/arm/vdso.ld
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index cf99fd7b8a..bd160b113b 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -167,9 +167,8 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
abi_ulong handler = 0;
abi_ulong handler_fdpic_GOT = 0;
abi_ulong retcode;
- int thumb, retcode_idx;
- int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
- bool copy_retcode;
+ bool thumb;
+ bool is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
if (is_fdpic) {
/* In FDPIC mode, ka->_sa_handler points to a function
@@ -184,9 +183,7 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
} else {
handler = ka->_sa_handler;
}
-
thumb = handler & 1;
- retcode_idx = thumb + (ka->sa_flags & TARGET_SA_SIGINFO ? 2 : 0);
uint32_t cpsr = cpsr_read(env);
@@ -202,24 +199,23 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
cpsr &= ~CPSR_E;
}
+ /* Our vdso default_sigreturn label is a table of entry points. */
+ int idx = is_fdpic * 2 + ((ka->sa_flags & TARGET_SA_SIGINFO) != 0);
+ retcode = default_sigreturn + idx * 16;
+
+ /*
+ * Put the sigreturn code on the stack no matter which return
+ * mechanism we use in order to remain ABI compliant.
+ */
+ memcpy(frame->retcode, g2h_untagged(retcode & ~1), 16);
+
if (ka->sa_flags & TARGET_SA_RESTORER) {
if (is_fdpic) {
+ /* Place the function descriptor in slot 3. */
__put_user((abi_ulong)ka->sa_restorer, &frame->retcode[3]);
- retcode = (sigreturn_fdpic_tramp +
- retcode_idx * RETCODE_BYTES + thumb);
- copy_retcode = true;
} else {
retcode = ka->sa_restorer;
- copy_retcode = false;
}
- } else {
- retcode = default_sigreturn + retcode_idx * RETCODE_BYTES + thumb;
- copy_retcode = true;
- }
-
- /* Copy the code to the stack slot for ABI compatibility. */
- if (copy_retcode) {
- memcpy(frame->retcode, g2h_untagged(retcode & ~1), RETCODE_BYTES);
}
env->regs[0] = usig;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index aff58cabfd..8e03bb6d76 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -568,6 +568,30 @@ static const char *get_elf_platform(void)
#undef END
}
+#if TARGET_BIG_ENDIAN
+# include "vdso-arm-be.c.inc"
+# include "vdso-thm-be.c.inc"
+#else
+# include "vdso-arm-le.c.inc"
+# include "vdso-thm-le.c.inc"
+#endif
+
+static const VdsoImageInfo *vdso_image_info(void)
+{
+ ARMCPU *cpu = ARM_CPU(thread_cpu);
+
+ /*
+ * The only cpus we support that do *not* have arm mode are m-profile.
+ * It's not really possible to run Linux on these, but this config is
+ * useful for testing gcc. In any case, choose the vdso image that
+ * will work for the target cpu.
+ */
+ return (cpu_isar_feature(aa32_a32, cpu)
+ ? &vdso_arm_image_info
+ : &vdso_thm_image_info);
+}
+#define vdso_image_info vdso_image_info
+
#else
/* 64 bit ARM definitions */
#define ELF_START_MMAP 0x80000000
diff --git a/linux-user/arm/Makefile.vdso b/linux-user/arm/Makefile.vdso
new file mode 100644
index 0000000000..89da6f91ae
--- /dev/null
+++ b/linux-user/arm/Makefile.vdso
@@ -0,0 +1,17 @@
+CROSS_CC ?= arm-linux-gnueabihf-gcc
+LDFLAGS := -nostdlib -shared -Wl,-T,vdso.ld \
+ -Wl,-h,linux-vdso.so.1 -Wl,--hash-style=sysv -Wl,--build-id=sha1
+
+all: vdso-arm-le.so vdso-arm-be.so vdso-thm-le.so vdso-thm-be.so
+
+vdso-arm-le.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mlittle-endian -marm vdso.S -o $@
+
+vdso-arm-be.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mbig-endian -marm vdso.S -o $@
+
+vdso-thm-le.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mlittle-endian -mthumb vdso.S -o $@
+
+vdso-thm-be.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mbig-endian -mthumb vdso.S -o $@
diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
index 5a93c925cf..66072411d6 100644
--- a/linux-user/arm/meson.build
+++ b/linux-user/arm/meson.build
@@ -5,3 +5,21 @@ syscall_nr_generators += {
arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
output: '@BASENAME@_nr.h')
}
+
+# ??? There does not seem to be a way to do
+# when: ['TARGET_ARM', !'TARGET_WORDS_BIGENDIAN']
+# so we'd need to add TARGET_WORDS_LITTLEENDIAN.
+# In the meantime, build both files for arm and armeb.
+
+gen = [
+ gen_vdso.process('vdso-arm-be.so',
+ extra_args: ['-s', 'sigreturn_codes', '-p', 'vdso_arm']),
+ gen_vdso.process('vdso-arm-le.so',
+ extra_args: ['-s', 'sigreturn_codes', '-p', 'vdso_arm']),
+ gen_vdso.process('vdso-thm-be.so',
+ extra_args: ['-s', 'sigreturn_codes', '-p', 'vdso_thm']),
+ gen_vdso.process('vdso-thm-le.so',
+ extra_args: ['-s', 'sigreturn_codes', '-p', 'vdso_thm']),
+]
+
+linux_user_ss.add(when: 'TARGET_ARM', if_true: gen)
diff --git a/linux-user/arm/vdso-arm-be.so b/linux-user/arm/vdso-arm-be.so
new file mode 100755
index 0000000000000000000000000000000000000000..197a8cc1b5303c0b5844272f2279eb79f9ddb724
GIT binary patch
literal 5648
zcmeHL%}*Ow5T9LRV+a^0p-m+?xGD!!g{37ZiqtB?1PqZ3iTIF`(_(A~y9FEBOMr+d
z?k8!Irbrx`OC?fq=q0^2Qd=d59{NZ0kSdClR#iVF)Ke<@`@Mb7n3PM^QzZ`>&-=~H
z&g`3gFVf7l;bg+HEvZsKy0L~LN>#te(T!lm<|-y3*rL(~eaN@buJ|D&xj}PHKxm}l
zxX*abx9IrHq4I2CK@Ms=5?U|qv8=#GR`E05lk+0>4|^;_u#ruE%AFeS!kS!bZwC&H
zj8Ds_r)S*W+>M{_de@q}J0CpydS~P+Y!UFZ|BUqvGKhSv4fbyFU7Nv0@F8%txVsA<
zdmHjEU>ovxh&x#SSIU|Ihh_H<tm8=cCS>%8pSuT3zE``(F9LIK2J2cI%(_-7fEB+b
z>q5dFtHdvb?;!LMaox+Aa?wrC7t?RMb6L;JFJuo?p6vgJx|A&&oqn=-DU({2`Fvq%
zrH64H{Ci!JXUC^6xP8t^mC;6a|Ifmyz+daH5AMRky>){5ZPZDHmlgPO=}#cqNUCO5
zN8k;t2f&RYt^EEMAWuOqLM9=vL(V{MK|&|^X05jnGz<xyg>&m4Q0vNs*lQ81qooxp
zl?Qcf`A)3|BjI)XHtWUwuR;It0R1TR-yEQyf&M=9QQ3>r4=l(ziKJ~zI#Y?h)AnxU
zz1H_zJ~;GY^Lo?u@JEd|LN|lA8a@u(wm)HV5cA_~w5&jON+R+|>tn#*L%#;uF40Kv
z>P|2eiZ(S;zS6)WATjVS@R^5<`aU7;6EZ$9)u~>AdIjngs8^s~fqDh%6{uIBUV(ZA
z{;w6N4D|fexVZJ$T3dhIXl?vfseJpCx=pRytkH$FE?lD<hi+W_=g>y|xD31u%r*HQ
z@Vy$m)A!kvu)X>8=x(pFdnfkeI0|_zl}*j&(ea@P3-(V*$PROT5baQj236br-WHgB
zD@gU}wEI1*Sm^H*(EYCJ>uJ<|uj=oKRYPR@cVP67Bzv2`z~~Q2oIxnuM2S^Q{ra;3
zETe?<=Zv6Az%2mPJvI1!{bAz|8~xGC1ymo1HD?V~(*DN~0zD`LskuN5&z}bzz~=cp
z`cVJ<u;%-nfv4KP_P+?7B0X0~<9YOs)w#klmfgT+j&Kv0{iVU51M_(w_j(J9z3KGy
zTPF&mMW-lTDe20HJ9Ke8K6dtul=E|?thZDuxand>jRP=wafe6U#6)~-*c~035O*Yb
zZZMv7&m|I*!&B~5d@woe*31O-1Y+L=;rXdV&7@)9q~d^~gc@LoQ(j&0QnQd=$(K2^
zDipn}IGNQ#Y9XIi3;05&yp%Y(R5|DCyplL`g(c^5wp7j+3;TeZ5ht5-FO^aYSvQw~
zr$OR)*%eQm_{5l#^1M=hcF99o{tb1&ndg#co%evu8HXW##^q%wc%E_W%uG$q()1Zu
zvmc)4SHV0th{t=Q?#>J_{diUxj~~2GW5&aIQfG?i*%1B6r@*{djQ7lEIS!2H6dAwM
zS_ePgKXnH=S2JYpNdhyqT`1{y$7gkqOg!jSEhfzj4shFN^)B28eVCUt3ubJ_!#!4a
zWrzk%#%~c=`vqcneX#ZXe)-51F#V8+Wg@GYCM8KJAS(!H-kItR{HS{jNizG@IejJk
ozJO^9h;zvoz<fW(<lU}`cVra!E3hFG5C6aH^J6WU+mQ168?PsKc>n+a
literal 0
HcmV?d00001
diff --git a/linux-user/arm/vdso-arm-le.so b/linux-user/arm/vdso-arm-le.so
new file mode 100755
index 0000000000000000000000000000000000000000..94c757a7e283fecc45847a7942c2943b989a1163
GIT binary patch
literal 5648
zcmeHL%}-oa6hChs3_}Y8{ZL78fsqAi;8Bq@O>7Lq$CR3ZHhdWB=JA-B!bF&v%sdJ-
z81a*8Yn_CcxKYtGjSFkyN*8VH!bSfGO*EuQO^jkBu4=~L@4k2G!?G}OW%ADOn{&^{
zJ?GxTdy|~=>QE|a7=~yvr9+g|EYb^Q<p{naQrjzS5{0c<n!r69?Zh1)HQ>a<Xb?c1
zP!ilntB#LgLR7$rT7dQlzFXj=u?(5e@z33JGvC8WV-Pk%+sStVXvdle+K)mufzzXt
zB412?khwA5GWFFDQy;&ub^DJ`?p}|>28-JB0B7OZI*^lhs6ajdUH}dPyvBoSwQwEw
zzrcC^ZSW7d_>Ytg>^~&GR}+v=At7@fM)of74hXyt<;TH~24oynIcqy>s)_gKeOMQg
zSATC!Hy)opifsF0rd+Vo^M&-w_H5R5a|>D7PkEyE5p^kB);fP@;X=k)k@;MHak-0e
zE&M$rsWYRKQ+AJaf*B*bA3ibseERLLjl9Q`0RJ~6@0^DGx%j0?8%fv9Xf>bfgIou+
zH;PPwp9C+0r@$|RPlIoQ7s0o|uY$)AbQ8Q29HmrbTpE+eYTRgTXjHXsf%dxwukO+x
zkF7_p8O(nixU-Lb82VfL=%=Co26~mpkJAes2|34+w24Wl*P35zdOiL|<C_g{9en%1
zdi~|tJ9Y0yuhd?xdC$BSd7pJ){!_p*;;}}OjQ>b|8*mp`)%ly_wXf{dMx)L3b>vUi
zM3v7k@R`?VQ9e=MC#rm44k@faSb?wtVFkhpgcS%Y5LO_pKv;qQaRt`;x_+)JZf+T?
z>sxh3<+ru9+xMy4@O2vjUCh_T0=iM?M#bBQuIZ;G$V-s9CT>E$8IX5+KDrl+Y}`Lm
z?N)a8*}Zb&2^7=GIx{&j(1Ky`Fd@+hJF-V<$5)xE3-sm%RGF%C_4;&A_PW?@KZ@yh
zyzJ{eyVv=$zxQNsQla~IQ+1Fc?C(8$OmWU1Jh@)+HosXm)pP(Vzj-v(lt8(tFH;))
z6MMQE^!10h)XgUR*~|6rHs72!JS6(FOuCmhAh$t2hy8uv5$rz>uFoe@F9VSE{po)m
zvL?<I(h!1kg(b+rxxy95!MVa`+>CrYC+7~*?Jg9%)9Ha1r;4SQtb(*V(w-4}@cd|E
z<jjDSbF-zayI9KG=|V=012B29hlcIsSYl+z9v&PM`*iATe<Ed{O(w^OChUnse`?4M
z%mn;l!=4GkKL-$jNyDB=#Xds`HNX(7yt3drGvIE?<8ykIFSuE;GAns!A(vJQ_<}pG
zBi5W#p7V5WNvzrYqIEG_D(4FMJ%XJPD?4XjC^-vRdoBY{Es5o3mtC<EV<VR1x~1IA
zqKmTpYiflj=Nfzj`5q9QacR;sou{DS)67RHI8XDQaBud*r}-GbSr+4QzC}!9O+UUS
zjK{~b$Cnw8&l7=>!7kB{I0^8rVm!WQL?_nVN78=JV@)0X`2G=`t7*bEMM->D{n;Ad
zOM-cIJcugBIJlm{@qHzD7T$wC%uAX97@NA_91)@-?N@}P{o0U>XwZj(P5WK){Zw69
zD4+tSi7L_>fDlElNfj74OVXr6>zrEuIs7)E<XrMGfO#2{zdX7ISjzBWk*~S%Nyp>w
POVF<hzlwGO*M5Hky@hy6
literal 0
HcmV?d00001
diff --git a/linux-user/arm/vdso-thm-be.so b/linux-user/arm/vdso-thm-be.so
new file mode 100755
index 0000000000000000000000000000000000000000..a83a7feb10d0e46b92531607d75d4564754f99dd
GIT binary patch
literal 5620
zcmeHL&2L*p5T9qqj+4fYTRw^iDn>*CA@cg6s1SiroF+~Rv4fmOY7x?lW5320jUCx9
zO;WYOK%s?}QmH~J<x)@%y#OcRfGT?6fcO(o5l9sh2ZZ>DI2DE8Z{Kd}gj^6Oq&Mk!
z_BT5_^LBQ((#*>v;~6Vt$vTDQQH-HTQq?bVmltV<I7&$rb4lrjKI+eLUhxe`a+~HB
zhtNpd<33}ZKcoFKhKe(f0Xd@Q5zxBt4$Bhe$jX1o`|){^(9Jt6!<ZwR_>`+H+>0@}
zb^dPP@MvyIzRgXQzqqvP+KcbT2KEf)7k|3-!YRxpz*GJj>o#Nr@t7Oz-MR?b39f;+
zfs?hhHQ0n!ApZgmLH-JH8RP#-u5qwk)_%h{jc^Y_#&-Cz`+)BO?$r2RV1ARq%r&#F
zG4r}kVT^c|%nJ#7Tqmx<IS6e;9OrncQFDsNYQ>kFS=aL_bMBVP{r&$?*WHHE>6Nvk
zrNXitt5g@3`smljzr8YkFgJDB*=O%p5krXX|5>;d_>2GY<p-GIxjg{p*{GWeD=Yl*
z!k<8#BdMHOJ>jP?9t5|G#CiUQA#F(9wfK{eXCa3muR=Zxi8G6r;WP$$5)${;zo6EM
zyo63Bte&noR4NYg*!300osv$(&V(*7UyQ#8`p>q|k3oNJ3;i_oSD=rz_~{20#GFLX
zZU&uhCSU1(HSt>fbl2<K-sn8jaW?j5`&-d-k@IbDhcATQVQ>)RKMj9*$Xzm;_(AJa
zz+Xd;{lg}ih@4uDM5D=$cFKp_cm*T{{uws-PV8CPM72%S*kCH4AOk@Lf(!&12r>|4
zAjm+Ffgl4x2L7)ZXns2Qd;3oLzImOaOL{c1dV0~<<sPBDk@@5gX_6O#&6x6|P5Aoz
zUEjQyNsbzu?>6By5_NyUEzDF<(V@<WJkghxXuLh!!BTTeTBR06s4ivv`W09&P_;Pc
z{W?`F)Nl&unpV~BoYb|gs^N)M(PL_KVAP1D&<cNnW0b%*`3u}ZiBU@ZvhGuqRKJ*K
z&Am>*T>$!<SzxQ$eY-9vX-9k1YhhLEVXXaeYTbS(T%gXRBegz-^?Lyav3agXt?7Rs
z#{9kmuvGik_D7&oq<aTNtZ(fdECRRo4$cA7ujw6p2+TeBc(*q<zq?qRn9mJ7H(=MK
z*OT6oIKxMB>FmJ+(x}YVU2maYb&9o;D*4e}aYn|ROg^0*amI%8;*5?@45i1NiA-j4
z<dAbHJv2VzwAB5&%dnwKu(|Wl(oNXVjo6~`pqdn7H<stT!VIKW_hs3Psx{9QyR=*_
z%vFkN09(j{R}i~gXq0`OR~LJ>x?mr7>y1jSx&b&PvE8zBv|gBVopK4528r#tOP<*2
zeAX^_UcEB2;2|ylhI(Mkd&#@bcR*$z!;rq?@(>if&$xD`Z>IWX`i`sq4)610V4g4h
z@!hDmGYw2To-_UNLhsX<{&1hvo#K5qL_0EjD12A+ciU%S&jjlf8M|k+4t9Kh>J74Y
zX2`sg4EknkP}1(Q&*~i+f6%L3OqxC$;EK=cTeuI}FfM5ZOyBf}cdXvZFefw_yLn)3
z7f$(a+}gZfE;*s?5Qk|ZtG*>ANhu(kaA>}nYCz#x8Z!IUF^xKT9-na)h`mR?OMV}H
d@@=>H+rb=v4mM=`;s2KncDH~p8Y4($_c!UoWV`?X
literal 0
HcmV?d00001
diff --git a/linux-user/arm/vdso-thm-le.so b/linux-user/arm/vdso-thm-le.so
new file mode 100755
index 0000000000000000000000000000000000000000..241fc569a4752fbe5642971f8dff72c3625799d1
GIT binary patch
literal 5620
zcmeHL-%lJ>6h6DdE>M<bTdi%xC`OEpf$5KsTBB)L3JX;h43wmO8kXHDyRrKtyF-Dd
zji|M)w$>)T_@fWiXyS|dq&_wF!I;K>L5)p}i4ToIB|cU0`|h1f2js!TCzCnw&3Dha
z=bn4#%*-a|yf8GHi9{k|#FAa2w3J96jNU!CL?zZIT@uG!N;<%Lj`PF~A5CE5ZZs&6
z9vBI(<E)8~U_#VDL=5136xW?_GFX64nE22A<Q2YylffY72s2M!37{KeA~=69bPE_B
zo08i%A3gW;*H`~ad{|E$od5P#_DoMSiMc6%%^jSDXWNB6c@I~hZvj_<Hh{NrXLYsu
z0p|Y%^Zd);w>bEZ;s(}lm0wrW&>zBvE#Pg~y%)S4I?qG>K5$z=$5AB`(3w*syno&g
z^Fq=2*JHZz`1DcYI428@s*^ua%|GwVx}H}myRw;af8RgMb+=(`{>tj{LT*t`lqz!z
zy^L$)f3J)l9-BJq?6dcC$LQK0-x&VA_vJ6`d~Oc_d^Qw)&WQXm_ld<hipg1|(|W2O
zdNa`7E^-uXgKOXe;0xdZ@HOx=;AL<T+=8H|!98H4PD$j{ghWp#Bb|wM;XXTouM#@%
zl1{dqk6w<@z6bbx6Z;74A8lfvhW#Db`8-XWK8_*Sa}t|&aMS6f)QcT2C0}kon|P(|
z+?MmL7g}Czel316cB$!g>vHrB=7IY^4NM^3gJ2m>-lDw=xCtDEoj#IE#?Gw7;_*~#
zGx?FGxbnG;sS)_7dsaSi-zTnoxHOb717QZj41^g7GZ1DV%s`ldFau!*{=XSm`mF!A
z<{k3G(shpB^he_>XXmwT>@o6<%%{K05-|_mjL9Ew(67In_~z|QYS{REzd=vmk6h*4
z+)PQ8r4oChH!Jb>=4|Wc#qx@uT1!=Wx+g%BrK(e1i)&q1s>>{RAeLX%vUb<Hu5MYw
zYh8CEOpR`-Dp7<ryq;GTnd&iUy;a$}{DRn06*o+NfoQ2tfO1h6OA`KxwXF%Y`&JH3
zK?#4>Vts1`HY@nMLjN65O}!q0-UWRx*7t*>Sic9%9*CA!IfQ|^fBGLYQ(*QE^59_a
zU><s~cW@DUuy^o2^kDBmc6;U8?tFeYT`NENtX-9EPr3`@3?3UxXAd8eMrpS0dUN%P
zldl$3$&c=eGc@94Ceqm<XJl|foZ->&f%K>|p2<uO9dVAN2S$gSK;7>*6xMYKHZ~ao
z-Gp`Bh)o&~s!1VsW3lYzX24!ubJ2_{RnHZ>uvp2JOL;YbFF5Dr#4hF<MQ!uyV$W9Q
z?2~T2QL0wfDNaFbx9A+N=gO{AEWp!fVtej_Cw6)wYv(+#UYeQnkd}Wfo$zGuf{&Qr
z0l_|&5!1JM7zV!0e3gPdGyR6^{tn;f#{u@M7>_+HVj5%m@iSpOzMlJho$>fS5oimn
z3H^uz0KY26<99~%V9a$C<985a+UUpck6`c22$m_y;JWJf&-h&u+}Ff|s$xunO`nb5
zE5WnyKIp@JDKh|L(-!O%LRDh?YS4^d7d9gj=1`b3ey4mtl~*PT;94UzQI-INSevS0
zg3r>332pW?_Dk@)1|xfq+X3#&nEd52IlxeQwuyYffiET=e_w)rKf>>daRM8^zX6tP
BWsm>>
literal 0
HcmV?d00001
diff --git a/linux-user/arm/vdso.S b/linux-user/arm/vdso.S
new file mode 100644
index 0000000000..1831b29efc
--- /dev/null
+++ b/linux-user/arm/vdso.S
@@ -0,0 +1,209 @@
+/*
+ * arm linux replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+ .text
+ .eabi_attribute Tag_FP_arch, 0
+
+#ifdef __thumb__
+ .thumb
+ .arch armv7-m
+ .eabi_attribute Tag_ARM_ISA_use, 0
+ .eabi_attribute Tag_CPU_arch, 13 /* TAG_CPU_ARCH_V7_M */
+
+.macro raw_syscall n
+ .ifne \n < 0x100
+ mov r7, #\n
+ .else
+ ldr r7, =\n
+ .endif
+ swi #0
+.endm
+
+.macro fdpic_thunk ofs
+ ldr r3, [sp, #\ofs]
+ ldmia r2, {r2, r3}
+ mov r9, r3
+ bx r2
+.endm
+
+#else
+ .arm
+ .arch armv4t
+ .eabi_attribute Tag_THUMB_ISA_use, 0
+
+.macro raw_syscall n
+ .ifne \n < 0x100
+ mov r7, #\n
+ .else
+ mov r7, #(\n & 0xff)
+ orr r7, r7, #(\n & 0xff00)
+ .endif
+ svc #(\n | __NR_OABI_SYSCALL_BASE)
+.endm
+
+.macro fdpic_thunk ofs
+ ldr r3, [sp, #\ofs]
+ ldmia r3, {r3, r9}
+ bx r3
+.endm
+
+#endif
+
+.macro FUNC name
+ .globl \name
+ .type \name, %function
+#ifdef __thumb__
+ .thumb_func
+#endif
+\name:
+.endm
+
+.macro ENDF name
+ .size \name, . - \name
+.endm
+
+/*
+ * We must save/restore r7 for the EABI syscall number.
+ * While we're doing that, we might as well save LR to get a free return,
+ * and a branch that is interworking back to ARMv5.
+ */
+
+.macro syscall n
+ .cfi_startproc
+ push {r7, lr}
+ .cfi_adjust_cfa_offset 8
+ .cfi_offset r7, -8
+ .cfi_offset lr, -4
+ raw_syscall \n
+ pop {r7, pc}
+ .cfi_endproc
+.endm
+
+FUNC __vdso_clock_gettime
+ syscall __NR_clock_gettime
+ENDF __vdso_clock_gettime
+
+FUNC __vdso_clock_gettime64
+ syscall __NR_clock_gettime64
+ENDF __vdso_clock_gettime64
+
+FUNC __vdso_clock_getres
+ syscall __NR_clock_getres
+ENDF __vdso_clock_getres
+
+FUNC __vdso_gettimeofday
+ syscall __NR_gettimeofday
+ENDF __vdso_gettimeofday
+
+
+/*
+ * We, like the real kernel, use a table of sigreturn trampolines.
+ * Unlike the real kernel, we do not attempt to pack this into as
+ * few bytes as possible -- simply use 16 bytes per slot.
+ *
+ * Within each slot, use the exact same code sequence as the kernel,
+ * lest we trip up someone doing code inspection.
+ */
+
+/* offsetof(struct sigframe, retcode[3]) */
+#define SIGFRAME_RC3_OFFSET 756
+#define RT_SIGFRAME_RC3_OFFSET 884
+
+.macro slot n
+ .balign 16
+ .org sigreturn_codes + 16 * \n
+.endm
+
+/*
+ * Start the unwind info at least one instruction before the signal
+ * trampoline, because the unwinder will assume we are returning
+ * after a call site.
+ */
+ .cfi_startproc simple
+ .cfi_signal_frame
+ .cfi_return_column 15
+
+ .cfi_def_cfa sp, 32 + 64
+ .cfi_offset r0, -16 * 4
+ .cfi_offset r1, -15 * 4
+ .cfi_offset r2, -14 * 4
+ .cfi_offset r3, -13 * 4
+ .cfi_offset r4, -12 * 4
+ .cfi_offset r5, -11 * 4
+ .cfi_offset r6, -10 * 4
+ .cfi_offset r7, -9 * 4
+ .cfi_offset r8, -8 * 4
+ .cfi_offset r9, -7 * 4
+ .cfi_offset r10, -6 * 4
+ .cfi_offset r11, -5 * 4
+ .cfi_offset r12, -4 * 4
+ .cfi_offset r13, -3 * 4
+ .cfi_offset r14, -2 * 4
+ .cfi_offset r15, -1 * 4
+
+ nop
+
+ .balign 16
+FUNC sigreturn_codes
+ /* [EO]ABI sigreturn */
+ slot 0
+ raw_syscall __NR_sigreturn
+
+ .cfi_def_cfa_offset 160 + 64
+
+ /* [EO]ABI rt_sigreturn */
+ slot 1
+ raw_syscall __NR_rt_sigreturn
+
+ .cfi_endproc
+
+ .macro cfi_fdpic_pc ofs
+ /*
+ * fd = *(r13 + ofs)
+ * pc = *fd
+ *
+ * DW_CFA_expression lr (14), length (5),
+ * DW_OP_breg13, ofs, DW_OP_deref, DW_OP_deref
+ */
+ .cfi_escape 0x10, 14, 5, 0x7d, (\ofs & 0x7f) + 0x80, (\ofs >> 7), 0x06, 0x06
+ .endm
+
+ .macro cfi_fdpic_r9 ofs
+ /*
+ * fd = *(r13 + ofs)
+ * r9 = *(fd + 4)
+ *
+ * DW_CFA_expression r9, length (7),
+ * DW_OP_breg13, ofs, DW_OP_deref,
+ * DW_OP_plus_uconst, 4, DW_OP_deref
+ */
+ .cfi_escape 0x10, 9, 7, 0x7d, (\ofs & 0x7f) + 0x80, (\ofs >> 7), 0x06, 0x23, 4, 0x06
+ .endm
+
+ /* FDPIC sigreturn */
+ .cfi_startproc
+ cfi_fdpic_pc SIGFRAME_RC3_OFFSET
+ cfi_fdpic_r9 SIGFRAME_RC3_OFFSET
+
+ slot 2
+ fdpic_thunk SIGFRAME_RC3_OFFSET
+ .cfi_endproc
+
+ /* FDPIC rt_sigreturn */
+ .cfi_startproc
+ cfi_fdpic_pc RT_SIGFRAME_RC3_OFFSET
+ cfi_fdpic_r9 RT_SIGFRAME_RC3_OFFSET
+
+ slot 3
+ fdpic_thunk RT_SIGFRAME_RC3_OFFSET
+ .cfi_endproc
+
+ .balign 16
+ENDF sigreturn_codes
diff --git a/linux-user/arm/vdso.ld b/linux-user/arm/vdso.ld
new file mode 100644
index 0000000000..3bddef97a5
--- /dev/null
+++ b/linux-user/arm/vdso.ld
@@ -0,0 +1,74 @@
+/*
+ * Linker script for linux arm replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+ LINUX_2.6 {
+ global:
+ __vdso_clock_gettime;
+ __vdso_gettimeofday;
+ __vdso_clock_getres;
+ __vdso_clock_gettime64;
+
+ local: *;
+ };
+}
+
+
+PHDRS {
+ phdr PT_PHDR FLAGS(4) PHDRS;
+ data PT_LOAD FLAGS(6) FILEHDR PHDRS;
+ text PT_LOAD FLAGS(5);
+ dynamic PT_DYNAMIC FLAGS(4);
+ eh_frame_hdr PT_GNU_EH_FRAME;
+ note PT_NOTE FLAGS(4);
+}
+
+SECTIONS {
+ /*
+ * We can't prelink to any address without knowing something about
+ * the virtual memory space of the host, since that leaks over into
+ * the available memory space of the guest.
+ */
+ . = SIZEOF_HEADERS;
+
+ /*
+ * The following, including the FILEHDRS and PHDRS, are modified
+ * when we relocate the binary. We want them to be initially
+ * writable for the relocation; we'll force them read-only after.
+ */
+ .note : { *(.note*) } :data :note
+ .dynamic : { *(.dynamic) } :data :dynamic
+ .dynsym : { *(.dynsym) } :data
+ /*
+ * There ought not be any real read-write data.
+ * But since we manipulated the segment layout,
+ * we have to put these sections somewhere.
+ */
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .rodata : { *(.rodata*) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :data :eh_frame_hdr
+ .eh_frame : { *(.eh_frame) } :data
+
+ . = ALIGN(4096);
+ .text : { *(.text*) } :text
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 12/15] linux-user/hppa: Add vdso and use it for rt_sigreturn
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (10 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 11/15] linux-user/arm: Add vdso and use it for rt_sigreturn Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 13/15] linux-user/i386: Add vdso and use it for sigreturn Richard Henderson
` (3 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Building the vdso itself is not actually wired up to anything, since
we require a cross-compiler. Just check in that file for now.
Drop the now-unused 9 trampoline words, and describe the frame
without the trampoline in __kernel_rt_sigreturn.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 4 +
linux-user/hppa/signal.c | 1 -
linux-user/hppa/Makefile.vdso | 6 ++
linux-user/hppa/meson.build | 6 ++
linux-user/hppa/vdso.S | 149 ++++++++++++++++++++++++++++++++++
linux-user/hppa/vdso.ld | 75 +++++++++++++++++
linux-user/hppa/vdso.so | Bin 0 -> 5196 bytes
7 files changed, 240 insertions(+), 1 deletion(-)
create mode 100644 linux-user/hppa/Makefile.vdso
create mode 100644 linux-user/hppa/vdso.S
create mode 100644 linux-user/hppa/vdso.ld
create mode 100755 linux-user/hppa/vdso.so
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8e03bb6d76..e389295b8d 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1778,6 +1778,10 @@ static inline void init_thread(struct target_pt_regs *regs,
#define STACK_GROWS_DOWN 0
#define STACK_ALIGNMENT 64
+#include "vdso.c.inc"
+
+#define vdso_image_info() &vdso_image_info
+
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
index f253a15864..881269f1ac 100644
--- a/linux-user/hppa/signal.c
+++ b/linux-user/hppa/signal.c
@@ -41,7 +41,6 @@ struct target_ucontext {
};
struct target_rt_sigframe {
- abi_uint tramp[2]; /* syscall restart return address */
target_siginfo_t info;
struct target_ucontext uc;
/* hidden location of upper halves of pa2.0 64-bit gregs */
diff --git a/linux-user/hppa/Makefile.vdso b/linux-user/hppa/Makefile.vdso
new file mode 100644
index 0000000000..d4362c4961
--- /dev/null
+++ b/linux-user/hppa/Makefile.vdso
@@ -0,0 +1,6 @@
+CROSS_CC ?= hppa-linux-gnu-gcc
+
+vdso.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) -nostdlib -shared -Wl,-T,vdso.ld \
+ -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
+ -Wl,--hash-style=sysv vdso.S -o $@
diff --git a/linux-user/hppa/meson.build b/linux-user/hppa/meson.build
index 4709508a09..e065a16a96 100644
--- a/linux-user/hppa/meson.build
+++ b/linux-user/hppa/meson.build
@@ -3,3 +3,9 @@ syscall_nr_generators += {
arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
output: '@BASENAME@_nr.h')
}
+
+gen = [
+ gen_vdso.process('vdso.so', extra_args: ['-r', '__kernel_rt_sigreturn'])
+]
+
+linux_user_ss.add(when: 'TARGET_HPPA', if_true: gen)
diff --git a/linux-user/hppa/vdso.S b/linux-user/hppa/vdso.S
new file mode 100644
index 0000000000..eeae2c999a
--- /dev/null
+++ b/linux-user/hppa/vdso.S
@@ -0,0 +1,149 @@
+/*
+ * hppa linux kernel vdso replacement.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+ .text
+
+#define sizeof_rt_sigframe 696
+#define offsetof_sigcontext 152
+#define offsetof_sigcontext_gr offsetof_sigcontext + 4
+#define offsetof_sigcontext_fr offsetof_sigcontext_gr + 32 * 4
+#define offsetof_sigcontext_iasq offsetof_sigcontext_fr + 32 * 8
+#define offsetof_sigcontext_iaoq offsetof_sigcontext_iasq + 8
+#define offsetof_sigcontext_sar offsetof_sigcontext_iaoq + 8
+
+ /*
+ * While this frame is marked as a signal frame, that only applies
+ * to how this return address is handled for the outer frame.
+ * The return address that arrived here, from the inner frame, is
+ * not marked as a signal frame and so the unwinder still tries to
+ * subtract 1 to examine the presumed call insn. Thus we must
+ * extend the unwind info to a nop before the start.
+ */
+
+ .cfi_startproc simple
+ .cfi_signal_frame
+
+ /* Compare pa32_fallback_frame_state from libgcc. */
+
+ /* Record the size of the stack frame. */
+ .cfi_def_cfa 30, -sizeof_rt_sigframe
+
+ /* Record save offset of general registers. */
+ .cfi_offset 1, offsetof_sigcontext_gr + 1 * 4
+ .cfi_offset 2, offsetof_sigcontext_gr + 2 * 4
+ .cfi_offset 3, offsetof_sigcontext_gr + 3 * 4
+ .cfi_offset 4, offsetof_sigcontext_gr + 4 * 4
+ .cfi_offset 5, offsetof_sigcontext_gr + 5 * 4
+ .cfi_offset 6, offsetof_sigcontext_gr + 6 * 4
+ .cfi_offset 7, offsetof_sigcontext_gr + 7 * 4
+ .cfi_offset 8, offsetof_sigcontext_gr + 8 * 4
+ .cfi_offset 9, offsetof_sigcontext_gr + 9 * 4
+ .cfi_offset 10, offsetof_sigcontext_gr + 10 * 4
+ .cfi_offset 11, offsetof_sigcontext_gr + 11 * 4
+ .cfi_offset 12, offsetof_sigcontext_gr + 12 * 4
+ .cfi_offset 13, offsetof_sigcontext_gr + 13 * 4
+ .cfi_offset 14, offsetof_sigcontext_gr + 14 * 4
+ .cfi_offset 15, offsetof_sigcontext_gr + 15 * 4
+ .cfi_offset 16, offsetof_sigcontext_gr + 16 * 4
+ .cfi_offset 17, offsetof_sigcontext_gr + 17 * 4
+ .cfi_offset 18, offsetof_sigcontext_gr + 18 * 4
+ .cfi_offset 19, offsetof_sigcontext_gr + 19 * 4
+ .cfi_offset 20, offsetof_sigcontext_gr + 20 * 4
+ .cfi_offset 21, offsetof_sigcontext_gr + 21 * 4
+ .cfi_offset 22, offsetof_sigcontext_gr + 22 * 4
+ .cfi_offset 23, offsetof_sigcontext_gr + 23 * 4
+ .cfi_offset 24, offsetof_sigcontext_gr + 24 * 4
+ .cfi_offset 25, offsetof_sigcontext_gr + 25 * 4
+ .cfi_offset 26, offsetof_sigcontext_gr + 26 * 4
+ .cfi_offset 27, offsetof_sigcontext_gr + 27 * 4
+ .cfi_offset 28, offsetof_sigcontext_gr + 28 * 4
+ .cfi_offset 29, offsetof_sigcontext_gr + 29 * 4
+ .cfi_offset 30, offsetof_sigcontext_gr + 30 * 4
+ .cfi_offset 31, offsetof_sigcontext_gr + 31 * 4
+
+ /* Record save offset of fp registers, left and right halves. */
+ .cfi_offset 32, offsetof_sigcontext_fr + 4 * 8
+ .cfi_offset 33, offsetof_sigcontext_fr + 4 * 8 + 4
+ .cfi_offset 34, offsetof_sigcontext_fr + 5 * 8
+ .cfi_offset 35, offsetof_sigcontext_fr + 5 * 8 + 4
+ .cfi_offset 36, offsetof_sigcontext_fr + 6 * 8
+ .cfi_offset 37, offsetof_sigcontext_fr + 6 * 8 + 4
+ .cfi_offset 38, offsetof_sigcontext_fr + 7 * 8
+ .cfi_offset 39, offsetof_sigcontext_fr + 7 * 8 + 4
+ .cfi_offset 40, offsetof_sigcontext_fr + 8 * 8
+ .cfi_offset 41, offsetof_sigcontext_fr + 8 * 8 + 4
+ .cfi_offset 42, offsetof_sigcontext_fr + 9 * 8
+ .cfi_offset 43, offsetof_sigcontext_fr + 9 * 8 + 4
+ .cfi_offset 44, offsetof_sigcontext_fr + 10 * 8
+ .cfi_offset 45, offsetof_sigcontext_fr + 10 * 8 + 4
+ .cfi_offset 46, offsetof_sigcontext_fr + 11 * 8
+ .cfi_offset 47, offsetof_sigcontext_fr + 11 * 8 + 4
+ .cfi_offset 48, offsetof_sigcontext_fr + 12 * 8
+ .cfi_offset 49, offsetof_sigcontext_fr + 12 * 8 + 4
+ .cfi_offset 50, offsetof_sigcontext_fr + 13 * 8
+ .cfi_offset 51, offsetof_sigcontext_fr + 13 * 8 + 4
+ .cfi_offset 52, offsetof_sigcontext_fr + 14 * 8
+ .cfi_offset 53, offsetof_sigcontext_fr + 14 * 8 + 4
+ .cfi_offset 54, offsetof_sigcontext_fr + 15 * 8
+ .cfi_offset 55, offsetof_sigcontext_fr + 15 * 8 + 4
+ .cfi_offset 56, offsetof_sigcontext_fr + 16 * 8
+ .cfi_offset 57, offsetof_sigcontext_fr + 16 * 8 + 4
+ .cfi_offset 58, offsetof_sigcontext_fr + 17 * 8
+ .cfi_offset 59, offsetof_sigcontext_fr + 17 * 8 + 4
+ .cfi_offset 60, offsetof_sigcontext_fr + 18 * 8
+ .cfi_offset 61, offsetof_sigcontext_fr + 18 * 8 + 4
+ .cfi_offset 62, offsetof_sigcontext_fr + 19 * 8
+ .cfi_offset 63, offsetof_sigcontext_fr + 19 * 8 + 4
+ .cfi_offset 64, offsetof_sigcontext_fr + 20 * 8
+ .cfi_offset 65, offsetof_sigcontext_fr + 20 * 8 + 4
+ .cfi_offset 66, offsetof_sigcontext_fr + 21 * 8
+ .cfi_offset 67, offsetof_sigcontext_fr + 21 * 8 + 4
+ .cfi_offset 68, offsetof_sigcontext_fr + 22 * 8
+ .cfi_offset 69, offsetof_sigcontext_fr + 22 * 8 + 4
+ .cfi_offset 70, offsetof_sigcontext_fr + 23 * 8
+ .cfi_offset 71, offsetof_sigcontext_fr + 23 * 8 + 4
+ .cfi_offset 72, offsetof_sigcontext_fr + 24 * 8
+ .cfi_offset 73, offsetof_sigcontext_fr + 24 * 8 + 4
+ .cfi_offset 74, offsetof_sigcontext_fr + 25 * 8
+ .cfi_offset 75, offsetof_sigcontext_fr + 25 * 8 + 4
+ .cfi_offset 76, offsetof_sigcontext_fr + 26 * 8
+ .cfi_offset 77, offsetof_sigcontext_fr + 26 * 8 + 4
+ .cfi_offset 78, offsetof_sigcontext_fr + 27 * 8
+ .cfi_offset 79, offsetof_sigcontext_fr + 27 * 8 + 4
+ .cfi_offset 80, offsetof_sigcontext_fr + 28 * 8
+ .cfi_offset 81, offsetof_sigcontext_fr + 28 * 8 + 4
+ .cfi_offset 82, offsetof_sigcontext_fr + 29 * 8
+ .cfi_offset 83, offsetof_sigcontext_fr + 29 * 8 + 4
+ .cfi_offset 84, offsetof_sigcontext_fr + 30 * 8
+ .cfi_offset 85, offsetof_sigcontext_fr + 30 * 8 + 4
+ .cfi_offset 86, offsetof_sigcontext_fr + 31 * 8
+ .cfi_offset 87, offsetof_sigcontext_fr + 31 * 8 + 4
+
+ /* Record save offset of %sar */
+ .cfi_offset 88, offsetof_sigcontext_sar
+
+ /* Record save offset of return address, iaoq[0]. */
+ .cfi_return_column 89
+ .cfi_offset 89, offsetof_sigcontext_iaoq
+
+ nop
+
+__kernel_rt_sigreturn:
+
+ ldi 0, %r25
+ ldi __NR_rt_sigreturn, %r20
+ be,l 0x100(%sr2, %r0), %sr0, %r31
+ nop
+
+ .cfi_endproc
+
+ .size __kernel_rt_sigreturn, . - __kernel_rt_sigreturn
+ .type __kernel_rt_sigreturn, @function
+ .globl __kernel_rt_sigreturn
diff --git a/linux-user/hppa/vdso.ld b/linux-user/hppa/vdso.ld
new file mode 100644
index 0000000000..fed994c3eb
--- /dev/null
+++ b/linux-user/hppa/vdso.ld
@@ -0,0 +1,75 @@
+/*
+ * Linker script for linux hppa vdso.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Note that the kernel does not implement a vdso for hppa.
+ * Mirror the symbol that other targets use for this, e.g. i386.
+ */
+
+VERSION {
+ QEMU {
+ global:
+ __kernel_rt_sigreturn;
+ local: *;
+ };
+}
+
+
+PHDRS {
+ phdr PT_PHDR FLAGS(4) PHDRS;
+ data PT_LOAD FLAGS(6) FILEHDR PHDRS;
+ text PT_LOAD FLAGS(5);
+ dynamic PT_DYNAMIC FLAGS(4);
+ note PT_NOTE FLAGS(4);
+ eh_frame_hdr PT_GNU_EH_FRAME;
+}
+
+SECTIONS {
+ . = SIZEOF_HEADERS;
+
+ /* The following, including the FILEHDRS and PHDRS, are modified
+ when we relocate the binary. We want them to be initially
+ writable for the relocation; we'll force them read-only after. */
+ .note : { *(.note*) } :data :note
+ .dynamic : { *(.dynamic) } :data :dynamic
+ .dynsym : { *(.dynsym) } :data
+ .data : {
+ /* There ought not be any real read-write data.
+ But since we manipulated the segment layout,
+ we have to put these sections somewhere. */
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .rodata : { *(.rodata) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :data :eh_frame_hdr
+ .eh_frame : { *(.eh_frame) } :data
+
+ . = ALIGN(4096);
+ .text : { *(.text*) } :text
+}
diff --git a/linux-user/hppa/vdso.so b/linux-user/hppa/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..bd77b8a5c33d66380a79b2f816237568998c8af3
GIT binary patch
literal 5196
zcmeHLTX2&_6y8m`h?i>1Fr!Y<(V03TLgZ2vMX_m{v|xHmQlRzno08B(+64dnt!Y&#
zrJ#tSAYi?V;vMhzD?akzLq~o0rOYtnjH5H?lUl!T|9?q4!-F$E`0}6R%h_|;v%6<E
z59e%)#G*1FgThcyT!5hzqKcY2A*xRa5vaoGGBHOig!O#r=eRc7HNFKWDm-BRObTX&
zAUIFQ_2P4^<@p#8%98`w!bN3>QP>C*pB(!-jarNeZBIKVI<V(t89FxOYrDrO2b<fv
z#Mtj0rSTI#{Pf3xiK*{Ke*U}EIrSrKJm-b3ubc$O-sDMeoIy^2p93rg&INb~<WNo)
zrl<eJx(mSnf-V65D;U@MuXLpeP%Wl^!<aebd8+2=JuqLIn0wwQa(J4gu&m7)JD=&d
zY{x3*`s|D|Xy-+LE<adWGL$YBLijEdosrfqP73JR5^La7`OC4x(D4il0Omxm4j(C0
z&lQl&`Sc!TO>h--%n9~VdDL|l%$<-U@r0<T=$19}F8zM%_Jw0t?N~H^_0Gk+mOL1G
z=$hS2A6~X+`6DYHt=oI;W7j=?{l1m^Z+POy1FH_+bm-<MS5MsXRQ=Q8XBwVue6H#F
z$P3XI+YfiV)cJD!NaB^`t6i_Hdwu;I8{X`GtLNx#Z{PmT9q-=xp7s7+AEZ9){b=LI
z=}$7BZu+e6^XwP7FYo?p^Vj{~3>?d=`hp5?Q4RN~Mq4!%Rm4%zLDf8@TJBYAN^0$}
zx^+aw?o+MztF{MJ`&QMlO?8e+72hsZVoa*!4yn4vrCPUBs`b01+OS8e?%hnkK0EIH
zydxN!+)(e6p8-Dueg^yu_!;ms;Ag<kfS&<B1AYenw+ze`f%>|OQN+)eJyT*#P!?yV
zQ&h9ab<J+Q3E8VNbxlk=Yfq3o&R+<uQ9-(fri?mT%eo$f%w7V>t&t(0<;koy=|9(#
zlb(FGCucpGbvTISruJt&jy<~jlWwgHpMahZ8|PnQ_UGAGK&Q#8tydymxwf{Ny4%97
zYZ_5RqhDY}TC8Y1+#0c3n&QH0j<q+0V^(`KnusK=WVj&~vD`ZP%q6!76^93$R4=$=
zyF6<~`GS)Xq4aP*HIUn=2k-??IVlm!rixit=h!0DmmdrbW$a?Eke?-3X%Wg~txa}n
zAY*0I@HCPLIhm4U4*KtS4cvGiykp)!Q41LI?p9n51@95pW%@Q^)YF0KH^6&b1n_>?
z-$4&WznP_wIhXHB=Nx>wCo|r07v>$nQtsp6p7eWSyh#^=eGtsk#CXJNfI9k}bfJ4U
zP-*hsw1}c#GYt*=_#X9}^v<RIpx3!bnEnn#yi-DOFZ87k*Ch1<jLmpS7qj{S#&63E
zKfLPzV73HHIo^ophjsYgiCOW?ByUZcNmV$Dq;n;}{vOw*%>RPP6^7Nd_-O+SnRwMu
O%=EJ%j~XX%?e`Db?gR4x
literal 0
HcmV?d00001
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 13/15] linux-user/i386: Add vdso and use it for sigreturn
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (11 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 12/15] linux-user/hppa: " Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 14/15] linux-user/x86_64: Add vdso Richard Henderson
` (2 subsequent siblings)
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Building the vdso itself is not actually wired up to anything, since
we require a cross-compiler. Just check in that file for now.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 16 ++-
linux-user/i386/Makefile.vdso | 5 +
linux-user/i386/meson.build | 7 ++
linux-user/i386/vdso.S | 181 ++++++++++++++++++++++++++++++++++
linux-user/i386/vdso.ld | 76 ++++++++++++++
linux-user/i386/vdso.so | Bin 0 -> 5528 bytes
6 files changed, 283 insertions(+), 2 deletions(-)
create mode 100644 linux-user/i386/Makefile.vdso
create mode 100644 linux-user/i386/vdso.S
create mode 100644 linux-user/i386/vdso.ld
create mode 100755 linux-user/i386/vdso.so
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index e389295b8d..486f5c4982 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -309,12 +309,24 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
(*regs)[15] = tswapreg(env->regs[R_ESP]);
(*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
}
-#endif
+
+/*
+ * i386 is the only target which supplies AT_SYSINFO for the vdso.
+ * All others only supply AT_SYSINFO_EHDR.
+ */
+#define DLINFO_ARCH_ITEMS 1
+#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry);
+
+#include "vdso.c.inc"
+
+#define vdso_image_info() &vdso_image_info
+
+#endif /* TARGET_X86_64 */
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
-#endif
+#endif /* TARGET_I386 */
#ifdef TARGET_ARM
diff --git a/linux-user/i386/Makefile.vdso b/linux-user/i386/Makefile.vdso
new file mode 100644
index 0000000000..42cfc1974b
--- /dev/null
+++ b/linux-user/i386/Makefile.vdso
@@ -0,0 +1,5 @@
+CROSS_CC ?= $(CC)
+
+vdso.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) -m32 -nostdlib -shared -Wl,-T,vdso.ld -Wl,--build-id=sha1 \
+ -Wl,-h,linux-gate.so.1 -Wl,--hash-style=both vdso.S -o $@
diff --git a/linux-user/i386/meson.build b/linux-user/i386/meson.build
index ee523019a5..b729d73686 100644
--- a/linux-user/i386/meson.build
+++ b/linux-user/i386/meson.build
@@ -3,3 +3,10 @@ syscall_nr_generators += {
arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
output: '@BASENAME@_nr.h')
}
+
+gen = [
+ gen_vdso.process('vdso.so', extra_args: ['-s', '__kernel_sigreturn',
+ '-r', '__kernel_rt_sigreturn'])
+]
+
+linux_user_ss.add(when: 'TARGET_I386', if_true: gen)
diff --git a/linux-user/i386/vdso.S b/linux-user/i386/vdso.S
new file mode 100644
index 0000000000..009f40696e
--- /dev/null
+++ b/linux-user/i386/vdso.S
@@ -0,0 +1,181 @@
+/*
+ * i386 linux replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+__kernel_vsyscall:
+ .cfi_startproc
+ int $0x80
+ ret
+ .cfi_endproc
+
+ .globl __kernel_vsyscall
+ .type __kernel_vsyscall, @function
+ .size __kernel_vsyscall, . - __kernel_vsyscall
+
+/*
+ * int __vdso_clock_gettime(clockid_t clock, struct old_timespec32 *ts);
+ */
+ .cfi_startproc
+__vdso_clock_gettime:
+ mov %ebx, %edx
+ .cfi_register %ebx, %edx
+ mov 4(%esp), %ebx
+ mov 8(%esp), %ecx
+ mov $__NR_clock_gettime, %eax
+ int $0x80
+ mov %edx, %ebx
+ ret
+ .cfi_endproc
+
+ .globl __vdso_clock_gettime
+ .type __vdso_clock_gettime, @function
+ .size __vdso_clock_gettime, . - __vdso_clock_gettime
+
+/*
+ * int __vdso_clock_gettime64(clockid_t clock, struct timespec *ts);
+ */
+ .cfi_startproc
+__vdso_clock_gettime64:
+ mov %ebx, %edx
+ .cfi_register %ebx, %edx
+ mov 4(%esp), %ebx
+ mov 8(%esp), %ecx
+ mov $__NR_clock_gettime64, %eax
+ int $0x80
+ mov %edx, %ebx
+ ret
+ .cfi_endproc
+
+ .globl __vdso_clock_gettime64
+ .type __vdso_clock_gettime64, @function
+ .size __vdso_clock_gettime64, . - __vdso_clock_gettime64
+
+/*
+ * int __vdso_clock_getres(clockid_t clock, struct old_timespec32 *res);
+ */
+ .cfi_startproc
+__vdso_clock_getres:
+ mov %ebx, %edx
+ .cfi_register %ebx, %edx
+ mov 4(%esp), %ebx
+ mov 8(%esp), %ecx
+ mov $__NR_clock_getres, %eax
+ int $0x80
+ mov %edx, %ebx
+ ret
+ .cfi_endproc
+
+ .globl __vdso_clock_getres
+ .type __vdso_clock_getres, @function
+ .size __vdso_clock_getres, . - __vdso_clock_getres
+
+/*
+ * int __vdso_gettimeofday(struct old_timeval *tv, struct timezone *tz);
+ */
+ .cfi_startproc
+__vdso_gettimeofday:
+ mov %ebx, %edx
+ .cfi_register %ebx, %edx
+ mov 4(%esp), %ebx
+ mov 8(%esp), %ecx
+ mov $__NR_gettimeofday, %eax
+ int $0x80
+ mov %edx, %ebx
+ ret
+ .cfi_endproc
+
+ .globl __vdso_gettimeofday
+ .type __vdso_gettimeofday, @function
+ .size __vdso_gettimeofday, . - __vdso_gettimeofday
+
+/*
+ * old_time_t __vdso_time(old_time_t *t);
+ */
+ .cfi_startproc
+__vdso_time:
+ mov %ebx, %edx
+ .cfi_register %ebx, %edx
+ mov 4(%esp), %ebx
+ mov $__NR_time, %eax
+ int $0x80
+ mov %edx, %ebx
+ ret
+ .cfi_endproc
+
+ .globl __vdso_time
+ .type __vdso_time, @function
+ .size __vdso_time, . - __vdso_time
+
+ /*
+ * While this frame is marked as a signal frame, that only applies
+ * to how this return address is handled for the outer frame.
+ * The return address that arrived here, from the inner frame, is
+ * not marked as a signal frame and so the unwinder still tries to
+ * subtract 1 to examine the presumed call insn. Thus we must
+ * extend the unwind info to a nop before the start.
+ */
+
+ .cfi_startproc simple
+ .cfi_signal_frame
+
+ /*
+ * For convenience, put the cfa just above eip in sigcontext,
+ * and count offsets backward from there. Re-compute the cfa
+ * in the several contexts we have for signal unwinding.
+ * This is far simpler than the DW_CFA_expression form that
+ * the kernel uses, and is equally correct.
+ */
+#define IA32_SIGCONTEXT_cfa 60
+#define IA32_RT_SIGFRAME_sigcontext 164
+
+ .cfi_def_cfa %esp, IA32_SIGCONTEXT_cfa + 4
+ .cfi_offset %eip, -4
+ /* err, -8 */
+ /* trapno, -12 */
+ .cfi_offset %eax, -16
+ .cfi_offset %ecx, -20
+ .cfi_offset %edx, -24
+ .cfi_offset %ebx, -28
+ .cfi_offset %esp, -32
+ .cfi_offset %ebp, -36
+ .cfi_offset %esi, -40
+ .cfi_offset %edi, -44
+
+ nop
+__kernel_sigreturn:
+ popl %eax /* pop sig */
+ .cfi_adjust_cfa_offset -4
+ movl $__NR_sigreturn, %eax
+ int $0x80
+
+ .globl __kernel_sigreturn
+ .type __kernel_sigreturn, @function
+ .size __kernel_sigreturn, . - __kernel_sigreturn
+
+ .cfi_adjust_cfa_offset IA32_RT_SIGFRAME_sigcontext - 4
+ nop
+__kernel_rt_sigreturn:
+ movl $__NR_rt_sigreturn, %eax
+ int $0x80
+
+ .globl __kernel_rt_sigreturn
+ .type __kernel_rt_sigreturn, @function
+ .size __kernel_rt_sigreturn, . - __kernel_rt_sigreturn
+ .cfi_endproc
+
+/*
+ * ??? Perhaps add elf notes. E.g.
+ *
+ * #include <linux/elfnote.h>
+ * ELFNOTE_START(Linux, 0, "a")
+ * .long LINUX_VERSION_CODE
+ * ELFNOTE_END
+ *
+ * but what version number would we set for QEMU?
+ */
diff --git a/linux-user/i386/vdso.ld b/linux-user/i386/vdso.ld
new file mode 100644
index 0000000000..b16e5c31bd
--- /dev/null
+++ b/linux-user/i386/vdso.ld
@@ -0,0 +1,76 @@
+/*
+ * Linker script for linux x86-64 replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+ENTRY(__kernel_vsyscall)
+
+VERSION {
+ LINUX_2.6 {
+ global:
+ __vdso_clock_gettime;
+ __vdso_gettimeofday;
+ __vdso_time;
+ __vdso_clock_getres;
+ __vdso_clock_gettime64;
+ };
+
+ LINUX_2.5 {
+ global:
+ __kernel_vsyscall;
+ __kernel_sigreturn;
+ __kernel_rt_sigreturn;
+ local: *;
+ };
+}
+
+PHDRS {
+ phdr PT_PHDR FLAGS(4) PHDRS;
+ data PT_LOAD FLAGS(6) FILEHDR PHDRS;
+ text PT_LOAD FLAGS(5);
+ dynamic PT_DYNAMIC FLAGS(4);
+ eh_frame_hdr PT_GNU_EH_FRAME;
+ note PT_NOTE FLAGS(4);
+}
+
+SECTIONS {
+ /* ??? We can't really prelink to any address without knowing
+ something about the virtual memory space of the host, since
+ that leaks over into the available memory space of the guest. */
+ . = SIZEOF_HEADERS;
+
+ /* The following, including the FILEHDRS and PHDRS, are modified
+ when we relocate the binary. We want them to be initially
+ writable for the relocation; we'll force them read-only after. */
+ .note : { *(.note*) } :data :note
+ .dynamic : { *(.dynamic) } :data :dynamic
+ .dynsym : { *(.dynsym) } :data
+ .data : {
+ /* There ought not be any real read-write data.
+ But since we manipulated the segment layout,
+ we have to put these sections somewhere. */
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .rodata : { *(.rodata*) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :data :eh_frame_hdr
+ .eh_frame : { *(.eh_frame) } :data
+
+ . = ALIGN(4096);
+ .text : { *(.text*) } :text =0x90909090
+}
diff --git a/linux-user/i386/vdso.so b/linux-user/i386/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..977ac01f5a2f06660560ee05d582b4804d842c59
GIT binary patch
literal 5528
zcmeHLO=w(I6u!?lZ6;}xHc@OPQ7nWSTODdiBWh`;>7-3D37S}}P<S0@UT22PkIs7;
z6P0%QV>=~aQ+3gW3qiq6D_w}pazJn)trQdlacNz+s*rT0#_zlDoyki(g5XMcCpkI4
z_uTu=y%+M`Q={Vt4Z~1ErZSbbHY+s<XZ%4gGN>L`>(zkTq`Dxz7~|xI&k;!SYBd<3
zfps2poI+ixPo3;SkddbC2Ozd0Nw^A|EcIWy?WUUsoC(Cp5~o}Wa6fc%F#Zs16MSg$
zh`QbL<i4$u&t@tYN{#1#Jh{BDulvm|#6I@NjA22`f31{ikX+*rko=Y_SYrod1H1vu
z&-r6zrF0dA|Ab`yJCGky`Hv($W2qj@HVrw93Hcqghaq<c>;c$Y0=5G?4Lj=RXCS9x
z<5!RW3R0+B{l0P@MghS#NY>{uFk#DlS0x#e`CJ!!p!XQE9W2BiaZj1UJzx*{J*>_3
zkQk$nd92a)Y;;>Z+E<l4*7)*V<#Y9I@AaumyRsv<>YcydsD9A-{$poqJHFZe+oie7
zk9>NdxBy*Q){I>)+Ig$u%sZ)MJ`YbN?UbxkzLc7=GPdjH3U*89(BOUUvh9e^A6Yt)
zPR@(ZFXhkZ<T7R3oh=s;_FZMyTJ`30#o4*1GfCHuIi=V$YW(ozk)zh`*icj3gD*AF
z2mVm<Mp9>gyr0W=zT3oo=mYbNlDys->hA0pro?2A7~`#8_G8SK{Wf~d7viwF7iyzY
z#~@6|Hz2n_)*yF6egZiRS%;j4yakzp+>GL!k7T?(rHpr@M(@T*qy|5Zi?>D`4DK(9
zxx2s%@ab_Q?IypC`WW~^3;%KW&$jT-!GEfSe-Zw7;OG3xuh08W!WyS#k@1>QjhtS0
zX8qZ=bJ6$O&v#&QuHz~2ix}U{0V7>|4|V;_7KRjdAnZWcfv^K%2f_}79SA!RcHn>C
zft%H@FaES}tUt0a-XE>E<Nw^7)r;Q;eIK^)b+qtJq8EX&^-i%DkJjJP`eOZ>miTiY
zE%_e*^+98Qx`=&9#M&gHArdh;$<&AvIHhUpR|JjGy|{-+1%sO&(ow|dUff5Z1g0R<
zN3MycP2>sEV1n@t8f)=wf@ENQI>XN=@_p0`>A%FrPf){nPDw2N9Apr?PcZHi^IwG?
z#NGwiL2Q2-b`aZNfgQx=>~aw6H(&>`zOoXpP41sKd;k~~?;qCan00V!|HP;@mY8b7
z(4kcTdoPM!gMtOX?pe)W19<O6-T^ed2937>-v5lOHJI076?5hbZt`_Vx9rKRXvLCi
zt5|xzm@MQ{T0yRgWs0-0Y|_bk9=GgyDt6h)m5OT&E3IO7);dv67Hlh<My6OQ=Gt>E
z`ucCF7m38!Jf=MBWWl6R{Zp*eHt0ODJS)NXFL_ttG2@Bd0R}|X^>{bP*I_dcs;<W)
zI|Sy9;Jmyu<T!Ny`0G5@+zq~qw<_lGE|JGu<n8r+%;P&4xdB~>bCVL_6~7+u9{FMT
zWL}OZzYOME8Fk)C@+;7#2V5KJIGDAWCyVABLXua6L-Kfs$-hVvq~!7KfO)#FY!o=S
zpYk123mKYR<W=G9gvB>P*5h!#cgeRwRZDn0xIx7ysmC{kU|yp~sgsffDS3Yb$_a-e
literal 0
HcmV?d00001
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 14/15] linux-user/x86_64: Add vdso
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (12 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 13/15] linux-user/i386: Add vdso and use it for sigreturn Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-11 16:50 ` [PATCH v3 15/15] linux-user/riscv: Add vdso and use it for sigreturn Richard Henderson
2023-08-14 9:52 ` [PATCH v3 00/15] linux-user: Implement VDSOs Alex Bennée
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Building the vdso itself is not actually wired up to anything, since
we require a cross-compiler. Just check in that file for now.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 4 +-
linux-user/x86_64/Makefile.vdso | 5 ++
linux-user/x86_64/meson.build | 6 ++
linux-user/x86_64/vdso.S | 122 ++++++++++++++++++++++++++++++++
linux-user/x86_64/vdso.ld | 74 +++++++++++++++++++
linux-user/x86_64/vdso.so | Bin 0 -> 6008 bytes
6 files changed, 209 insertions(+), 2 deletions(-)
create mode 100644 linux-user/x86_64/Makefile.vdso
create mode 100644 linux-user/x86_64/vdso.S
create mode 100644 linux-user/x86_64/vdso.ld
create mode 100755 linux-user/x86_64/vdso.so
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 486f5c4982..80587c155e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -317,12 +317,12 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
#define DLINFO_ARCH_ITEMS 1
#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry);
+#endif /* TARGET_X86_64 */
+
#include "vdso.c.inc"
#define vdso_image_info() &vdso_image_info
-#endif /* TARGET_X86_64 */
-
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
diff --git a/linux-user/x86_64/Makefile.vdso b/linux-user/x86_64/Makefile.vdso
new file mode 100644
index 0000000000..532c9d6964
--- /dev/null
+++ b/linux-user/x86_64/Makefile.vdso
@@ -0,0 +1,5 @@
+CROSS_CC ?= $(CC)
+
+vdso.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) -nostdlib -shared -Wl,-T,vdso.ld -Wl,--build-id=sha1 \
+ -Wl,-h,linux-vdso.so.1 -Wl,--hash-style=both vdso.S -o $@
diff --git a/linux-user/x86_64/meson.build b/linux-user/x86_64/meson.build
index 203af9a60c..f6a0015953 100644
--- a/linux-user/x86_64/meson.build
+++ b/linux-user/x86_64/meson.build
@@ -3,3 +3,9 @@ syscall_nr_generators += {
arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
output: '@BASENAME@_nr.h')
}
+
+gen = [
+ gen_vdso.process('vdso.so')
+]
+
+linux_user_ss.add(when: 'TARGET_X86_64', if_true: gen)
diff --git a/linux-user/x86_64/vdso.S b/linux-user/x86_64/vdso.S
new file mode 100644
index 0000000000..bbd75a79aa
--- /dev/null
+++ b/linux-user/x86_64/vdso.S
@@ -0,0 +1,122 @@
+/*
+ * x86-64 linux replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+ .globl __vdso_clock_gettime
+ .type __vdso_clock_gettime, @function
+ .balign 16
+ .cfi_startproc
+__vdso_clock_gettime:
+ mov $__NR_clock_gettime, %eax
+ syscall
+ ret
+ .cfi_endproc
+ .size __vdso_clock_gettime, . - __vdso_clock_gettime
+
+clock_gettime = __vdso_clock_gettime
+ .weak clock_gettime
+
+ .globl __vdso_clock_getres
+ .type __vdso_clock_getres, @function
+ .balign 16
+ .cfi_startproc
+__vdso_clock_getres:
+ mov $__NR_clock_getres, %eax
+ syscall
+ ret
+ .cfi_endproc
+ .size __vdso_clock_getres, . - __vdso_clock_getres
+
+clock_getres = __vdso_clock_getres
+ .weak clock_getres
+
+ .globl __vdso_gettimeofday
+ .type __vdso_gettimeofday, @function
+ .balign 16
+ .cfi_startproc
+__vdso_gettimeofday:
+ mov $__NR_gettimeofday, %eax
+ syscall
+ ret
+ .cfi_endproc
+ .size __vdso_gettimeofday, . - __vdso_gettimeofday
+
+gettimeofday = __vdso_gettimeofday
+ .weak gettimeofday
+
+
+ .globl __vdso_time
+ .type __vdso_time, @function
+ .balign 16
+ .cfi_startproc
+__vdso_time:
+ mov $__NR_time, %eax
+ syscall
+ ret
+ .cfi_endproc
+ .size __vdso_time, . - __vdso_time
+
+time = __vdso_time
+ .weak time
+
+
+ .globl __vdso_getcpu
+ .type __vdso_getcpu, @function
+ .balign 16
+ .cfi_startproc
+__vdso_getcpu:
+ /*
+ * ??? There is no syscall number for this allocated on x64.
+ * We can handle this several ways:
+ *
+ * (1) Invent a syscall number for use within qemu.
+ * It should be easy enough to pick a number that
+ * is well out of the way of the kernel numbers.
+ *
+ * (2) Force the emulated cpu to support the rdtscp insn,
+ * and initialize the TSC_AUX value the appropriate value.
+ *
+ * (3) Pretend that we're always running on cpu 0.
+ *
+ * This last is the one that's implemented here, with the
+ * tiny bit of extra code to support rdtscp in place.
+ */
+ xor %ecx, %ecx /* rdtscp w/ tsc_aux = 0 */
+
+ /* if (cpu != NULL) *cpu = (ecx & 0xfff); */
+ test %rdi, %rdi
+ jz 1f
+ mov %ecx, %eax
+ and $0xfff, %eax
+ mov %eax, (%rdi)
+
+ /* if (node != NULL) *node = (ecx >> 12); */
+1: test %rsi, %rsi
+ jz 2f
+ shr $12, %ecx
+ mov %ecx, (%rsi)
+
+2: xor %eax, %eax
+ ret
+ .cfi_endproc
+ .size __vdso_getcpu, . - __vdso_getcpu
+
+getcpu = __vdso_getcpu
+ .weak getcpu
+
+/*
+ * ??? Perhaps add elf notes. E.g.
+ *
+ * #include <linux/elfnote.h>
+ * ELFNOTE_START(Linux, 0, "a")
+ * .long LINUX_VERSION_CODE
+ * ELFNOTE_END
+ *
+ * but what version number would we set for QEMU?
+ */
diff --git a/linux-user/x86_64/vdso.ld b/linux-user/x86_64/vdso.ld
new file mode 100644
index 0000000000..6630193079
--- /dev/null
+++ b/linux-user/x86_64/vdso.ld
@@ -0,0 +1,74 @@
+/*
+ * Linker script for linux x86-64 replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+ LINUX_2.6 {
+ global:
+ clock_gettime;
+ __vdso_clock_gettime;
+ gettimeofday;
+ __vdso_gettimeofday;
+ getcpu;
+ __vdso_getcpu;
+ time;
+ __vdso_time;
+ clock_getres;
+ __vdso_clock_getres;
+
+ local: *;
+ };
+}
+
+
+PHDRS {
+ phdr PT_PHDR FLAGS(4) PHDRS;
+ data PT_LOAD FLAGS(6) FILEHDR PHDRS;
+ text PT_LOAD FLAGS(5);
+ dynamic PT_DYNAMIC FLAGS(4);
+ eh_frame_hdr PT_GNU_EH_FRAME;
+ note PT_NOTE FLAGS(4);
+}
+
+SECTIONS {
+ /* ??? We can't really prelink to any address without knowing
+ something about the virtual memory space of the host, since
+ that leaks over into the available memory space of the guest. */
+ . = SIZEOF_HEADERS;
+
+ /* The following, including the FILEHDRS and PHDRS, are modified
+ when we relocate the binary. We want them to be initially
+ writable for the relocation; we'll force them read-only after. */
+ .note : { *(.note*) } :data :note
+ .dynamic : { *(.dynamic) } :data :dynamic
+ .dynsym : { *(.dynsym) } :data
+ .data : {
+ /* There ought not be any real read-write data.
+ But since we manipulated the segment layout,
+ we have to put these sections somewhere. */
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .rodata : { *(.rodata*) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :data :eh_frame_hdr
+ .eh_frame : { *(.eh_frame) } :data
+
+ . = ALIGN(4096);
+ .text : { *(.text*) } :text =0x90909090
+}
diff --git a/linux-user/x86_64/vdso.so b/linux-user/x86_64/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..0397ef0f4f3c1e7006146a1113d49ba93b7f5042
GIT binary patch
literal 6008
zcmeHL&1+m$6hD*6bW%;4w2CP4BTB81(jh6O1S%zMlQ_{f#6U1z)R$>ynhDL!#F>{e
zBc*~EB_e)+D;LFL*V5(etQ1Pyzn}<i#QFh6bYXCzj^{V;{Khx8PhALZoHM!k-TS-e
z+>dkbd%SaAn>;?%6^jWaE{CPr8VHzi>!?3K4UusflWqFHUv?;pbZZ&6ZWm{5Xkw4)
zfrjm0$=yWILlj#N?3!KHCQm$N0}{!1DUWs5Z9Ogqn^pzu=Q?Na_*vME*?L?&pnVV`
zbRj^L_ia2EcSA{q2we#9K`n7D&&|xsOK11)tzA92?}KkI-@3ef_h>r#@}PF9=L1<V
zr2TCes{H(WqXZnX4qLvgS)0DE!!auN1t4X^`wbs9{IwB`7dT(!H*1@@{Alg3xDd1Z
zuL0-wl<4a1e()TJmEWcOki$P_`U4LCkm<YpsOh`o95($CXPimXcX?b3tjAqvUiqE!
zQ$wLmp4S%i$8CJ98}gzS?APUS4SKcUoN@N_gH~m`7MvT;9A}O7B(*?b%VR_xeJB`f
z^T1eQDkqnykFhSyfBA~s8octwz(*J7-W$ok`NGCGeeXX0`iIqv=O6jxSn=)Q>wETG
zIh`vkywwoTJD07LyrtFB(phgg=ld&#+&yGDS0QIAr8C(~ja=A9`<K?%Wp$;vUfqYG
zQ~Eb5$ERoJ7rgzcgSx)1$e(to#O!zJvmg5K+&!v=&lL99rTts$pT^M#!TCU9gYiRn
z=Hc5L>d0Be+lpDm?-Z+wzbL+=*rN{qSP{Z;Vz16gtU3@I>`nII-GF1o+-qvXvjR7w
zW!2#(l*>CD)|_>?Rpl0y<6Y5aM>-zpc%b8fjt4p(=y;&xfsP0M=N_nktq$l<T<d@0
zjix8+cbxX3)4ti>9=(~~X!zSVZ#>=T*XSUb-q`XJpMT%GxnuO|HC6pPiR-sD<KnPh
zT)(;*pSSaIVZ7STcMId*c0SRHf7|(OtvI-yPfAq$8pjtoKJ*=lYb3>dK)5Tek=0tH
z{-5z4^$}ylBKE7F?JD<<kN6@gzQs3wRNVNC@=<Xw;uVbJ#<zz|-;F1yjd%4^HqH=&
z6&1!VHLYWOH|{-ZygU9W<)h+Z<Riel<A^tLa^}d1>0=rbYM#WKOnXyvM@~$7>4~{e
z@MqCxR1j%_qZ^NgLeIz;wHbR#s!}WXnbV4XIlw$?#gd<sRJK;k6jqj+71fp0a&bMC
z&s6dO<Cg>GT&`SMDHYoqURF}MymzLYDdfC-RyEm@l%K2m>XCmhNFpKLXa0uIA#t}e
zMYq#_QrpM}AU^=%^Gei9-4y1TcrWal$guVz@4)%_ToZ>v_NdaH`6$Hoc*JPW=bt#C
zeGsmX_T0yQ?c36v744ZPBjWjhxb^`n@~rjIo_RGQ^Jvt!?XW3WUn4X>-#bL^lk;;P
zBJw`S!Li+XKiPX{%w~fBp~L+fEsI*gnrP4W7!kRRu+VShidqTV^L<A=Pens_{;JvY
zel!yx(6tMK_d!^AZ^(t`CI?(J#Rc0~pK{2Ra(?<1c`N!>t1YST3aS@cOi*#pZ>Q2x
M_6IFb{!jLQ0P{>E*#H0l
literal 0
HcmV?d00001
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v3 15/15] linux-user/riscv: Add vdso and use it for sigreturn
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (13 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 14/15] linux-user/x86_64: Add vdso Richard Henderson
@ 2023-08-11 16:50 ` Richard Henderson
2023-08-14 9:52 ` [PATCH v3 00/15] linux-user: Implement VDSOs Alex Bennée
15 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-11 16:50 UTC (permalink / raw)
To: qemu-devel; +Cc: alex.bennee, pbonzini, philmd
Building the vdso itself is not actually wired up to anything, since
we require a cross-compiler. Just check in those files for now.
This fixes a bug wrt libgcc fallback unwinding. It expects the stack
pointer to point to the siginfo_t, whereas we had inexplicably placed
our private signal trampoline at the start of the signal frame instead
of the end. Now moot because we have removed it from the stack
frame entirely.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 4 +
linux-user/meson.build | 1 +
linux-user/riscv/Makefile.vdso | 11 ++
linux-user/riscv/meson.build | 9 ++
linux-user/riscv/vdso-32.so | Bin 0 -> 5624 bytes
linux-user/riscv/vdso-64.so | Bin 0 -> 6120 bytes
linux-user/riscv/vdso.S | 207 +++++++++++++++++++++++++++++++++
linux-user/riscv/vdso.ld | 76 ++++++++++++
8 files changed, 308 insertions(+)
create mode 100644 linux-user/riscv/Makefile.vdso
create mode 100644 linux-user/riscv/meson.build
create mode 100755 linux-user/riscv/vdso-32.so
create mode 100755 linux-user/riscv/vdso-64.so
create mode 100644 linux-user/riscv/vdso.S
create mode 100644 linux-user/riscv/vdso.ld
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 80587c155e..6a943a74d8 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1752,8 +1752,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
#ifdef TARGET_RISCV32
#define ELF_CLASS ELFCLASS32
+#include "vdso-32.c.inc"
#else
#define ELF_CLASS ELFCLASS64
+#include "vdso-64.c.inc"
#endif
#define ELF_HWCAP get_elf_hwcap()
@@ -1770,6 +1772,8 @@ static uint32_t get_elf_hwcap(void)
#undef MISA_BIT
}
+#define vdso_image_info() &vdso_image_info
+
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
diff --git a/linux-user/meson.build b/linux-user/meson.build
index dd24389052..3ff3bc5bbc 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -45,6 +45,7 @@ subdir('microblaze')
subdir('mips64')
subdir('mips')
subdir('ppc')
+subdir('riscv')
subdir('s390x')
subdir('sh4')
subdir('sparc')
diff --git a/linux-user/riscv/Makefile.vdso b/linux-user/riscv/Makefile.vdso
new file mode 100644
index 0000000000..de55a0b9f9
--- /dev/null
+++ b/linux-user/riscv/Makefile.vdso
@@ -0,0 +1,11 @@
+CROSS_CC ?= riscv64-linux-gnu-gcc
+LDFLAGS := -nostdlib -shared -Wl,-T,vdso.ld \
+ -Wl,-h,linux-vdso.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
+
+all: vdso-64.so vdso-32.so
+
+vdso-64.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mabi=lp64d -march=rv64g -fpic -o $@ vdso.S
+
+vdso-32.so: vdso.S vdso.ld Makefile.vdso
+ $(CROSS_CC) $(LDFLAGS) -mabi=ilp32d -march=rv32g -fpic -o $@ vdso.S
diff --git a/linux-user/riscv/meson.build b/linux-user/riscv/meson.build
new file mode 100644
index 0000000000..475b816da1
--- /dev/null
+++ b/linux-user/riscv/meson.build
@@ -0,0 +1,9 @@
+gen32 = [
+ gen_vdso.process('vdso-32.so', extra_args: ['-r', '__vdso_rt_sigreturn']),
+]
+gen64 = [
+ gen_vdso.process('vdso-64.so', extra_args: ['-r', '__vdso_rt_sigreturn'])
+]
+
+linux_user_ss.add(when: 'TARGET_RISCV32', if_true: gen32)
+linux_user_ss.add(when: 'TARGET_RISCV64', if_true: gen64)
diff --git a/linux-user/riscv/vdso-32.so b/linux-user/riscv/vdso-32.so
new file mode 100755
index 0000000000000000000000000000000000000000..0925aae9f50145bab6ef5d1da4a58c2dcb2ebec3
GIT binary patch
literal 5624
zcmeHLU2KzO6n?*!!WeAqFi>z)fq_hvy5SI%iTmpqP{uMgord_ewB0)0I&3>K$iiEN
z5Ml@{LJT3q3?zgYLl!ke4N(&lHR=r!6R(UnMz4$p{7D4n^L$_5(jg{Zc;Q9Q_Uydp
z=RNP=`Ielc1Ho3yvXmjOx}qGZOsP63N6M9&241HYsp+a(m8m)4u8nr$qb%r0+>8bR
zwB6@|^AI2xpJU=27y&m&_JA!w5QF282@}8L`*ifU7rHF!VIz#4{AwPSVoc=Q=RwAF
zwV}ORUAq4JCtn`kJbAhA>*jA0=U=GFT>7pQwsdw*3pVuYjme==aPILUIL|VHJr;u>
z0cHU_&J2K5<T5oAd^T`xa&jny1+Rnid_RK+xq<(H8W<4d#R;9e$3}V}&&A3sz;{CC
z9w_ezHzewp$q<B-uyen(&j%0X`3E77<=NLm&g9woMmz@3NzU^-?+k9pc~=NrgKt3M
zmg!GUaE>K2Ya3Nr8D;u8clmk6#I_?f@ycU|CeOY%xOm~~&58Q?pPpDgu_LBzdsj3y
zWcS6=>HfjkP;WH6+vp+#Ly_l=<!{PlEM;_<9N9T+q~3wyRNU^5gd_1>_+;8n_4g%X
z>EUET4fH35M^<uKKYnXfaASLSk6q`lU5yQcJX3y{>+a8~4}U6Q&Q$`;D-z$zgTKT2
zhho}D=6$RR@4B^+c`tE1UI+MR;BoM8z(>J<1Rn$c1N;oQDsgiX&*PAHPp7g*Evur$
zqZoeyPzGP-hUzF?6h)HLw+85e9={Gz*8+6iqT{@dTXX}^1)($feibqaYj4Bi4OYc$
z&$!3epv2lMo>B4ck!d61+a=S}G9xKPJ7s1<iU(xYb22+FCB0G_l{q`4EF|)*%-t^K
z&&a$Ung68R(It0w%7PAA*e-VkrDBs*w#nVCa!-rg+a!w`Wbp@DmR!_Q^}d#+?`m0g
zLCbybXj%T2mg)&D_n+6Y;!Q0NyrJd6b6QrO)#5*+<)PDBYR0wHzNTf>Ni7eb&{B6?
z%j#FPJaSCSnpd=}9n<pYVJ(jx(z5PlE%gVrJbpmS`u$p-cuC{Dyt8XS8~zdCIto;{
zfx-<GZlG`jg&Qc`K;Z@oH&D2N|K$xt4)|2nIB?ph$}Q_gRrM)V?z7a<qMC&%?0DZ2
zOL?mr)xN41)xKqx1s_kO%;zchb^IBr^ukxE^3u%ux4-(>TQ%N|IK!$h10CiPCXUe^
zEebhtZ_1fsu481zGvlL06GgQB6Xj|Rr;>8}1@!eg6{TAXxw6*@(ZIqI#5$S8x}M~9
zI}eKWy(_yFEbDw%cB^_*uY0rAPRI?5`K*53euV4Ku7FaPb9QzIKr9kKUQ`II{a8Db
zEY#tgF_E=XUJ9B04VQ}58Vt<-Y2RW@;H=|Wo8{N(tjo9_^{neN;2FrQO(-7*&#(JW
zL(cCLT!0+P^H+Au)9sC0Ha07}qjPI>pryMrV59im+_)iNcQrNz12$@CbW`j=o88*k
zxFuk>wR9?bLvU+TW6<8(+PW>!WgPR0=4=UnySn>!W&PA@eM)7Xjg%|=^J@H@j%@;^
z{Hfi8>F^HlbkgN<GfE7lW6B@hod^&1N1OqC!NcjW^7kc%{qb-r?&{M?SF<aYO!W^X
zrU-Ua`D1arHyIv`+3_emjimhP*hm_e`!A^ie#}0mBJ-VKZWwYiS*gWPFl(7I`F%4t
zbKQOlYjpO5n2n6b{uMEXu~~!h@a$?8!1QE1<{e?yg31|Ft_RrPVLX0M#9E9^>e7dx
z?ze33i{Ba10Nt&AO<5hxPM?k6Ap2{ExF^ykU@{wz-z6~@IunociKhV5a|^*pa4-4i
zg{XP~#^#*-z9K}2%-Q*L#*g1OanNiEHsiN9>*xF@;e`U{zzk7EGO=6<J}_jUWdBhB
h#-p$4uVLs=H4giQ5x~tBI0swG(G~dZ&q+7^{sKo*m>d8A
literal 0
HcmV?d00001
diff --git a/linux-user/riscv/vdso-64.so b/linux-user/riscv/vdso-64.so
new file mode 100755
index 0000000000000000000000000000000000000000..75fe1db977ee1de538963a062e4da7c337ec6a54
GIT binary patch
literal 6120
zcmeHLU2GIp6u!Gdp|l0|6i~3JMNzQA+9C+b-?Vhgk4xK>5^G{IU3RzK#&%0~r=*zX
zP9OT936Um1LW~do5aWZ1O*94*6Y(cX&=_KjA;uUq{xrsrsz{7M>Nzv#EVI)Z6JLCA
zPnrGh{mwb}+&OdaFy}h4cuP1GQX+=>Rk^*0$C#{`T<kUGAed^inv1^?wFprukMs1V
z2dMR=ore}IXP#*C{X4nBN<j?f3i*{$i~B+Bbgh&U6nz+Zn&%mwPY~;w7nFIne`lx2
zuhtDZ6Ss0aL9!(wq-&hV4dN;?LJ=fe62c{T8F=k#J)mA|*wOa2GAiHOcCzVocbW6l
zJ9}S6m0CzYD7FW#A2rXBBg${rrw82z56sh7Cif-xlav^g3J=sV#!ALzjPn=;BtO!h
z&keD^Htofq<amE_pTnss?q6WNjPqZhf!RCDd6W3`*s4`kVVz;il{)5YdHo4LhCHaB
zr#-71zunlRapG(*d0WbSBrr~#c{5<Yo%#BJy{u!JK0O0MdRFp$vFVCDe~K?Dr)NR-
zgmk~;6N)ScGo<Q?BRluGpRbwNf2=;U;>6MEm);y$x%|bQ*{w@Id}j5;!L+ih!>RnB
z)tk2MzJc^$PbzUlxMcre@^R73Aam)waOj*oG$g&A{-J!v>Pse)nZocn+sgO#=F;|1
zF01<cvO~k`C~Oq}HK_QW)&pJEhG@e^oG?nb=+EOqc!%`&{M(lo(EeJ1m+T$7_b}>)
zoF6JkM?%k&BvfN;p}kGHxrCdf6LAVLgQ#$mj37i1#}R80Pb02DJj?r@AD1$o=un}N
zP^e}>*nK6@J{iMtWc`rcTD(RBoQd2>fTKAK2RNFKjhw8nIUFD3?#IApsHQ4B5iT<o
zghn7d42BJJ4nbKz%+0{O6qI+v{Kuf83o1LIsvQ=@Vc~9A)C>_5;4KHL&p5F7bqAJA
zII#2;2X1=Vftyb|u<SVpmOtyjEvFo)IpM&HaR+Wa>cDMJI&k}#1GS?Lth}z_j%yn3
z{6oX4-!<HIRm0s^G_3wb!<s1#_gvOc_mhTuf7GycQp39MHAKJFaNjo?>Mv<%_)5e2
zFE!l%g@z3mHEjG`!vmjb*z~D}%@;I0_=$#xKGv}1yoRmkG;I4o!}j+z?08pWPAIQc
zn2T=Q9Fl9KN>a)|DFdYplrm7tKq&*I4E%31aJ+oHB9C|9JE|0w_{Ym5^NRbmf&OTb
z{bDREZum}=lkY!?f#2Fv5BqHm{0f(PrkFRB)Tzb%%({*A2A&W|9b9aWU-44>_!I_K
zIp(Z<xtgs$HL%i>y4E)g#;quv6BP56s#^*$pTh9fmqOELdkE{uU>@+(-sQWcpkRkp
zF3ya*iS5r)f#;Kb*q*IU?LwaF)L`A&&%FB~jcxgc9%VjQk3P+Ou-<)v`C6X8jPnNb
z!8%x3&5yP=?%T6dS?wKdJ7diUI${<UdJi}5idmhFP4Sq8^&*~-Sh3w!OGo3rn6<mP
zLs`4xZB31FtF5JFf2>mseFY+ytFzUZvz4&Lm1$8G$|DtuTwgs~;HV^4Dw;nsU?&bD
z+Bpw1(#j6nX%$T!$tDK+l5PWS5fgSoMSHVD(M%$r@pwDuF^AK+eBWTUsAHv6G@Y?}
za*2Vol}Vwc^i<SN4@;qox&F6OgN}3-K<5G^vVR4=b?E8nH@KZvB1bi}EJs=2g7sXl
zy5|jOCv~hW_d4XTtS-ct_krL=)RD*>#b3^&)}xL>NPO8Bf?`i&kVs#U&H!i&%l*sy
zMQ}4Yp~(2+CwU<KRXp<&|3ZS;z$9mspufi|)x<jSm-m&RoZE>#r&GFWFSe$A@#VcH
zSk0CaU*ZTpf_gf`lfJzF1m*sN`IiawV1wo){=xH9%CBD}Z^F?M_WR5GRPaRLh9&>v
zPiFySLTk_!Sy+s8rs5Y-3+In59AOt5ntWq)E(>@`d|7{THb*{wImL<p$WLNBa69gp
T@@)L3N%~J4Wz2)ZZ_xiQ;17|*
literal 0
HcmV?d00001
diff --git a/linux-user/riscv/vdso.S b/linux-user/riscv/vdso.S
new file mode 100644
index 0000000000..31913e72cc
--- /dev/null
+++ b/linux-user/riscv/vdso.S
@@ -0,0 +1,207 @@
+/*
+ * RISC-V linux replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+.macro syscall nr
+ li a7, \nr
+ ecall
+.endm
+
+ .text
+ .balign 16
+__vdso_gettimeofday:
+ .cfi_startproc
+#ifdef __NR_gettimeofday
+ syscall __NR_gettimeofday
+ ret
+#else
+ /* No gettimeofday, fall back to clock_gettime64. */
+ beq a1, zero, 1f
+ sw zero, 0(a1) /* tz->tz_minuteswest = 0 */
+ sw zero, 4(a1) /* tz->tz_dsttime = 0 */
+1: addi sp, sp, -32
+ .cfi_adjust_cfa_offset 32
+ sw a0, 16(sp) /* save tv */
+ mv a0, sp
+ syscall __NR_clock_gettime64
+ lw t0, 0(sp) /* timespec.tv_sec.low */
+ lw t1, 4(sp) /* timespec.tv_sec.high */
+ lw t2, 8(sp) /* timespec.tv_nsec.low */
+ lw a1, 16(sp) /* restore tv */
+ addi sp, sp, 32
+ .cfi_adjust_cfa_offset -32
+ bne a0, zero, 9f /* syscall error? */
+ li a0, -EOVERFLOW
+ bne t1, zero, 9f /* y2038? */
+ li a0, 0
+ li t3, 1000
+ divu t2, t2, t3 /* nsec -> usec */
+ sw t0, 0(a1) /* tz->tv_sec */
+ sw t2, 4(a1) /* tz->tv_usec */
+9: ret
+#endif
+ .cfi_endproc
+
+ .globl __vdso_gettimeofday
+ .type __vdso_gettimeofday, %function
+ .size __vdso_gettimeofday, . - __vdso_gettimeofday
+
+ .balign 16
+__vdso_clock_gettime:
+ .cfi_startproc
+#ifdef __NR_clock_gettime
+ syscall __NR_clock_gettime
+#else
+ syscall __NR_clock_gettime64
+#endif
+ ret
+ .cfi_endproc
+
+ .globl __vdso_clock_gettime
+ .type __vdso_clock_gettime, %function
+ .size __vdso_clock_gettime, . - __vdso_clock_gettime
+
+ .balign 16
+__vdso_clock_getres:
+ .cfi_startproc
+#ifdef __NR_clock_getres
+ syscall __NR_clock_getres
+#else
+ syscall __NR_clock_getres_time64
+#endif
+ ret
+ .cfi_endproc
+
+ .globl __vdso_clock_getres
+ .type __vdso_clock_getres, %function
+ .size __vdso_clock_getres, . - __vdso_clock_getres
+
+ .balign 16
+__vdso_getcpu:
+ .cfi_startproc
+ syscall __NR_getcpu
+ ret
+ .cfi_endproc
+
+ .globl __vdso_getcpu
+ .type __vdso_getcpu, %function
+ .size __vdso_getcpu, . - __vdso_getcpu
+
+ .balign 16
+__vdso_flush_icache:
+ .cfi_startproc
+ /* qemu does not need to flush the icache */
+ li a0, 0
+ ret
+ .cfi_endproc
+
+ .globl __vdso_flush_icache
+ .type __vdso_flush_icache, %function
+ .size __vdso_flush_icache, . - __vdso_flush_icache
+
+/*
+ * Start the unwind info at least one instruction before the signal
+ * trampoline, because the unwinder will assume we are returning
+ * after a call site.
+ */
+
+ .cfi_startproc simple
+ .cfi_signal_frame
+
+#if __riscv_xlen == 32
+# define offsetof_uc_mcontext 0x120
+#else
+# define offsetof_uc_mcontext 0x130
+#endif
+#define sizeof_reg (__riscv_xlen / 4)
+#define sizeof_freg 8
+#define offsetof_freg0 (sizeof_reg * 32)
+
+ .cfi_def_cfa 2, offsetof_uc_mcontext
+
+ /* Return address */
+ .cfi_return_column 64
+ .cfi_offset 64, 0 /* pc */
+
+ /* Integer registers */
+ .cfi_offset 1, 1 * sizeof_reg /* r1 (ra) */
+ .cfi_offset 2, 2 * sizeof_reg /* r2 (sp) */
+ .cfi_offset 3, 3 * sizeof_reg
+ .cfi_offset 4, 4 * sizeof_reg
+ .cfi_offset 5, 5 * sizeof_reg
+ .cfi_offset 6, 6 * sizeof_reg
+ .cfi_offset 7, 7 * sizeof_reg
+ .cfi_offset 8, sizeof_reg * 8
+ .cfi_offset 9, 9 * sizeof_reg
+ .cfi_offset 10, 10 * sizeof_reg
+ .cfi_offset 11, 11 * sizeof_reg
+ .cfi_offset 12, 12 * sizeof_reg
+ .cfi_offset 13, 13 * sizeof_reg
+ .cfi_offset 14, 14 * sizeof_reg
+ .cfi_offset 15, 15 * sizeof_reg
+ .cfi_offset 16, 16 * sizeof_reg
+ .cfi_offset 17, 17 * sizeof_reg
+ .cfi_offset 18, 18 * sizeof_reg
+ .cfi_offset 19, 19 * sizeof_reg
+ .cfi_offset 20, 20 * sizeof_reg
+ .cfi_offset 21, 21 * sizeof_reg
+ .cfi_offset 22, 22 * sizeof_reg
+ .cfi_offset 23, 23 * sizeof_reg
+ .cfi_offset 24, 24 * sizeof_reg
+ .cfi_offset 25, 25 * sizeof_reg
+ .cfi_offset 26, 26 * sizeof_reg
+ .cfi_offset 27, 27 * sizeof_reg
+ .cfi_offset 28, 28 * sizeof_reg
+ .cfi_offset 29, 29 * sizeof_reg
+ .cfi_offset 30, 30 * sizeof_reg
+ .cfi_offset 31, 31 * sizeof_reg /* r31 */
+
+ .cfi_offset 32, offsetof_freg0 /* f0 */
+ .cfi_offset 33, offsetof_freg0 + 1 * sizeof_freg /* f1 */
+ .cfi_offset 34, offsetof_freg0 + 2 * sizeof_freg
+ .cfi_offset 35, offsetof_freg0 + 3 * sizeof_freg
+ .cfi_offset 36, offsetof_freg0 + 4 * sizeof_freg
+ .cfi_offset 37, offsetof_freg0 + 5 * sizeof_freg
+ .cfi_offset 38, offsetof_freg0 + 6 * sizeof_freg
+ .cfi_offset 39, offsetof_freg0 + 7 * sizeof_freg
+ .cfi_offset 40, offsetof_freg0 + 8 * sizeof_freg
+ .cfi_offset 41, offsetof_freg0 + 9 * sizeof_freg
+ .cfi_offset 42, offsetof_freg0 + 10 * sizeof_freg
+ .cfi_offset 43, offsetof_freg0 + 11 * sizeof_freg
+ .cfi_offset 44, offsetof_freg0 + 12 * sizeof_freg
+ .cfi_offset 45, offsetof_freg0 + 13 * sizeof_freg
+ .cfi_offset 46, offsetof_freg0 + 14 * sizeof_freg
+ .cfi_offset 47, offsetof_freg0 + 15 * sizeof_freg
+ .cfi_offset 48, offsetof_freg0 + 16 * sizeof_freg
+ .cfi_offset 49, offsetof_freg0 + 17 * sizeof_freg
+ .cfi_offset 50, offsetof_freg0 + 18 * sizeof_freg
+ .cfi_offset 51, offsetof_freg0 + 19 * sizeof_freg
+ .cfi_offset 52, offsetof_freg0 + 20 * sizeof_freg
+ .cfi_offset 53, offsetof_freg0 + 21 * sizeof_freg
+ .cfi_offset 54, offsetof_freg0 + 22 * sizeof_freg
+ .cfi_offset 55, offsetof_freg0 + 23 * sizeof_freg
+ .cfi_offset 56, offsetof_freg0 + 24 * sizeof_freg
+ .cfi_offset 57, offsetof_freg0 + 25 * sizeof_freg
+ .cfi_offset 58, offsetof_freg0 + 26 * sizeof_freg
+ .cfi_offset 59, offsetof_freg0 + 27 * sizeof_freg
+ .cfi_offset 60, offsetof_freg0 + 28 * sizeof_freg
+ .cfi_offset 61, offsetof_freg0 + 29 * sizeof_freg
+ .cfi_offset 62, offsetof_freg0 + 30 * sizeof_freg
+ .cfi_offset 63, offsetof_freg0 + 31 * sizeof_freg /* f31 */
+
+ nop
+
+__vdso_rt_sigreturn:
+ syscall __NR_rt_sigreturn
+ .cfi_endproc
+
+ .globl __vdso_rt_sigreturn
+ .type __vdso_rt_sigreturn, %function
+ .size __vdso_rt_sigreturn, . - __vdso_rt_sigreturn
diff --git a/linux-user/riscv/vdso.ld b/linux-user/riscv/vdso.ld
new file mode 100644
index 0000000000..57f3159415
--- /dev/null
+++ b/linux-user/riscv/vdso.ld
@@ -0,0 +1,76 @@
+/*
+ * Linker script for linux riscv replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+ LINUX_4.15 {
+ global:
+ __vdso_rt_sigreturn;
+ __vdso_gettimeofday;
+ __vdso_clock_gettime;
+ __vdso_clock_getres;
+ __vdso_getcpu;
+ __vdso_flush_icache;
+
+ local: *;
+ };
+}
+
+
+PHDRS {
+ phdr PT_PHDR FLAGS(4) PHDRS;
+ data PT_LOAD FLAGS(6) FILEHDR PHDRS;
+ text PT_LOAD FLAGS(5);
+ dynamic PT_DYNAMIC FLAGS(4);
+ eh_frame_hdr PT_GNU_EH_FRAME;
+ note PT_NOTE FLAGS(4);
+}
+
+SECTIONS {
+ /*
+ * We can't prelink to any address without knowing something about
+ * the virtual memory space of the host, since that leaks over into
+ * the available memory space of the guest.
+ */
+ . = SIZEOF_HEADERS;
+
+ /*
+ * The following, including the FILEHDRS and PHDRS, are modified
+ * when we relocate the binary. We want them to be initially
+ * writable for the relocation; we'll force them read-only after.
+ */
+ .note : { *(.note*) } :data :note
+ .dynamic : { *(.dynamic) } :data :dynamic
+ .dynsym : { *(.dynsym) } :data
+ /*
+ * There ought not be any real read-write data.
+ * But since we manipulated the segment layout,
+ * we have to put these sections somewhere.
+ */
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ *(.got.plt) *(.got)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ }
+
+ .rodata : { *(.rodata*) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :data :eh_frame_hdr
+ .eh_frame : { *(.eh_frame) } :data
+
+ . = ALIGN(4096);
+ .text : { *(.text*) } :text =0xd503201f
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v3 00/15] linux-user: Implement VDSOs
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
` (14 preceding siblings ...)
2023-08-11 16:50 ` [PATCH v3 15/15] linux-user/riscv: Add vdso and use it for sigreturn Richard Henderson
@ 2023-08-14 9:52 ` Alex Bennée
2023-08-16 18:06 ` Richard Henderson
15 siblings, 1 reply; 18+ messages in thread
From: Alex Bennée @ 2023-08-14 9:52 UTC (permalink / raw)
To: qemu-devel, Richard Henderson; +Cc: pbonzini, philmd
Richard Henderson <richard.henderson@linaro.org> writes:
> It's time for another round on implementing the VDSO for linux-user.
> We are now seeing applications built that absolutely require it,
> and have no fallback for the VDSO to be absent.
Something broke configure for me:
../../configure --disable-docs --disable-system
Gave:
Dependency glib-2.0 found: YES 2.74.6 (overridden)
Program indent found: NO
../../linux-user/hppa/meson.build:7:0: ERROR: File vdso.so does not exist.
A full log can be found at /home/alex/lsrc/qemu.git/builds/user/meson-logs/meson-log.txt
FAILED: build.ninja
/home/alex/lsrc/qemu.git/builds/user/pyvenv/bin/meson --internal regenerate /home/alex/lsrc/qemu.git /home/alex/lsrc/qemu.git/builds/user
ninja: error: rebuilding 'build.ninja': subcommand failed
make: Nothing to be done for 'all'.
Will there be linux-user targets that never support vdso?
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v3 00/15] linux-user: Implement VDSOs
2023-08-14 9:52 ` [PATCH v3 00/15] linux-user: Implement VDSOs Alex Bennée
@ 2023-08-16 18:06 ` Richard Henderson
0 siblings, 0 replies; 18+ messages in thread
From: Richard Henderson @ 2023-08-16 18:06 UTC (permalink / raw)
To: Alex Bennée, qemu-devel; +Cc: pbonzini, philmd
On 8/14/23 02:52, Alex Bennée wrote:
>
> Richard Henderson <richard.henderson@linaro.org> writes:
>
>> It's time for another round on implementing the VDSO for linux-user.
>> We are now seeing applications built that absolutely require it,
>> and have no fallback for the VDSO to be absent.
>
> Something broke configure for me:
>
> ../../configure --disable-docs --disable-system
>
>
> Gave:
>
> Dependency glib-2.0 found: YES 2.74.6 (overridden)
> Program indent found: NO
>
> ../../linux-user/hppa/meson.build:7:0: ERROR: File vdso.so does not exist.
>
> A full log can be found at /home/alex/lsrc/qemu.git/builds/user/meson-logs/meson-log.txt
> FAILED: build.ninja
> /home/alex/lsrc/qemu.git/builds/user/pyvenv/bin/meson --internal regenerate /home/alex/lsrc/qemu.git /home/alex/lsrc/qemu.git/builds/user
> ninja: error: rebuilding 'build.ninja': subcommand failed
> make: Nothing to be done for 'all'.
>
> Will there be linux-user targets that never support vdso?
>
Something must have gone wrong with the email, or patch apply, because that file should
definitely exist. I have just sent a v4. If that breaks too, let me know but then please
just pull from my branch.
r~
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2023-08-16 18:06 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-11 16:50 [PATCH v3 00/15] linux-user: Implement VDSOs Richard Henderson
2023-08-11 16:50 ` [PATCH v3 01/15] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
2023-08-11 16:50 ` [PATCH v3 02/15] linux-user: Tidy loader_exec Richard Henderson
2023-08-11 16:50 ` [PATCH v3 03/15] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
2023-08-11 16:50 ` [PATCH v3 04/15] linux-user: Use ImageSource in load_elf_image Richard Henderson
2023-08-11 16:50 ` [PATCH v3 05/15] linux-user: Use ImageSource in load_symbols Richard Henderson
2023-08-11 16:50 ` [PATCH v3 06/15] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
2023-08-11 16:50 ` [PATCH v3 07/15] linux-user: Load vdso image if available Richard Henderson
2023-08-11 16:50 ` [PATCH v3 08/15] linux-user: Add gen-vdso tool Richard Henderson
2023-08-11 16:50 ` [PATCH v3 09/15] linux-user/aarch64: Add vdso and use it for rt_sigreturn Richard Henderson
2023-08-11 16:50 ` [PATCH v3 10/15] target/arm: Add isar_feature_aa32_a32 Richard Henderson
2023-08-11 16:50 ` [PATCH v3 11/15] linux-user/arm: Add vdso and use it for rt_sigreturn Richard Henderson
2023-08-11 16:50 ` [PATCH v3 12/15] linux-user/hppa: " Richard Henderson
2023-08-11 16:50 ` [PATCH v3 13/15] linux-user/i386: Add vdso and use it for sigreturn Richard Henderson
2023-08-11 16:50 ` [PATCH v3 14/15] linux-user/x86_64: Add vdso Richard Henderson
2023-08-11 16:50 ` [PATCH v3 15/15] linux-user/riscv: Add vdso and use it for sigreturn Richard Henderson
2023-08-14 9:52 ` [PATCH v3 00/15] linux-user: Implement VDSOs Alex Bennée
2023-08-16 18:06 ` Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).