* [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa
@ 2021-06-19 3:43 Richard Henderson
2021-06-19 3:43 ` [PATCH 01/12] linux-user: Fix style problems in linuxload.c Richard Henderson
` (12 more replies)
0 siblings, 13 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
Supersedes: 20200519194452.9009-1-richard.henderson@linaro.org
Based-on: 20210618192951.125651-1-richard.henderson@linaro.org
("[PATCH v2 00/23] linux-user: Move signal trampolines to new page")
Previous cover letter:
> The subject of AT_SYSINFO came up on launchpad recently.
>
> There is definite room for improvement in all of this:
>
> (1) We could build the vdso binary into qemu instead of really
> loading it from the file system. This would obviate the
> several problems of locating the .so file. It would also
> mean that --static builds continue to create a standalone
> qemu binary.
>
> (2) We could use our cross-build system to build the vdso.
> Though we'd still likely want to keep the image in git
> along side the other rom images for when cross-build is
> not available.
>
> (3) There are some ??? comments where some decisions could be made,
> and other ??? that are merely commenting on weirdness.
>
> (4) It shouldn't take too much effort to create vdsos for the
> other architectures. But we should get this one as clean
> as we can first.
Amusingly, this patch set has turned 11 years old.
First posted April 4, 2010.
Change since previous:
Point (1) has been addressed: the vdso binary pre-processed,
validating the VDSO image, emitting a C array for the image,
collecting the set of relocations required, and identifying
any signal return trampolines.
Point (2) is still an issue in that the cross-build system is
tied up in tests/ makefiles. It might be time to bite the bullet
and convert it all to meson.
I think there are fewer ??? than before.
r~
Richard Henderson (12):
linux-user: Fix style problems in linuxload.c
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: Introduce imgsrc_mmap
linux-user: Load vdso image if available
linux-user: Add gen-vdso tool
linux-user/x86_64: Add vdso
linux-user/hppa: Add vdso and use it for rt_sigreturn
linux-user/qemu.h | 60 ++++++-
linux-user/elfload.c | 305 ++++++++++++++++++--------------
linux-user/flatload.c | 8 +-
linux-user/gen-vdso.c | 168 ++++++++++++++++++
linux-user/hppa/signal.c | 8 +-
linux-user/linuxload.c | 171 +++++++++++++-----
linux-user/gen-vdso-elfn.c.inc | 299 +++++++++++++++++++++++++++++++
linux-user/hppa/Makefile.vdso | 4 +
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 -> 5192 bytes
linux-user/meson.build | 6 +-
linux-user/x86_64/Makefile.vdso | 3 +
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 -> 5912 bytes
18 files changed, 1272 insertions(+), 192 deletions(-)
create mode 100644 linux-user/gen-vdso.c
create mode 100644 linux-user/gen-vdso-elfn.c.inc
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/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.25.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/12] linux-user: Fix style problems in linuxload.c
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 9:47 ` Philippe Mathieu-Daudé
2021-06-19 3:43 ` [PATCH 02/12] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
` (11 subsequent siblings)
12 siblings, 1 reply; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/linuxload.c | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index a27e1d0d8b..9d4eb5e94b 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -1,59 +1,57 @@
/* Code for loading Linux executables. Mostly linux kernel code. */
#include "qemu/osdep.h"
-
#include "qemu.h"
#define NGROUPS 32
/* ??? This should really be somewhere else. */
-abi_long memcpy_to_target(abi_ulong dest, const void *src,
- unsigned long len)
+abi_long memcpy_to_target(abi_ulong dest, const void *src, unsigned long len)
{
void *host_ptr;
host_ptr = lock_user(VERIFY_WRITE, dest, len, 0);
- if (!host_ptr)
+ if (!host_ptr) {
return -TARGET_EFAULT;
+ }
memcpy(host_ptr, src, len);
unlock_user(host_ptr, dest, 1);
return 0;
}
-static int count(char ** vec)
+static int count(char **vec)
{
- int i;
+ int i;
- for(i = 0; *vec; i++) {
+ for (i = 0; *vec; i++) {
vec++;
}
-
- return(i);
+ return i;
}
static int prepare_binprm(struct linux_binprm *bprm)
{
- struct stat st;
+ struct stat st;
int mode;
int retval;
- if(fstat(bprm->fd, &st) < 0) {
- return(-errno);
+ if (fstat(bprm->fd, &st) < 0) {
+ return -errno;
}
mode = st.st_mode;
- if(!S_ISREG(mode)) { /* Must be regular file */
- return(-EACCES);
+ if (!S_ISREG(mode)) { /* Must be regular file */
+ return -EACCES;
}
- if(!(mode & 0111)) { /* Must have at least one execute bit set */
- return(-EACCES);
+ if (!(mode & 0111)) { /* Must have at least one execute bit set */
+ return -EACCES;
}
bprm->e_uid = geteuid();
bprm->e_gid = getegid();
/* Set-uid? */
- if(mode & S_ISUID) {
+ if (mode & S_ISUID) {
bprm->e_uid = st.st_uid;
}
@@ -125,8 +123,8 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
}
int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
- struct target_pt_regs * regs, struct image_info *infop,
- struct linux_binprm *bprm)
+ struct target_pt_regs *regs, struct image_info *infop,
+ struct linux_binprm *bprm)
{
int retval;
@@ -139,7 +137,7 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
retval = prepare_binprm(bprm);
- if(retval>=0) {
+ if (retval >= 0) {
if (bprm->buf[0] == 0x7f
&& bprm->buf[1] == 'E'
&& bprm->buf[2] == 'L'
@@ -157,11 +155,11 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
}
}
- if(retval>=0) {
+ if (retval >= 0) {
/* success. Initialize important registers */
do_init_thread(regs, infop);
return retval;
}
- return(retval);
+ return retval;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/12] linux-user: Introduce imgsrc_read, imgsrc_read_alloc
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
2021-06-19 3:43 ` [PATCH 01/12] linux-user: Fix style problems in linuxload.c Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 03/12] linux-user: Tidy loader_exec Richard Henderson
` (10 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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/qemu.h | 50 ++++++++++++++++++++++++++++++++++--------
linux-user/linuxload.c | 46 ++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+), 9 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 9e5e2aa499..f4cdfb16b3 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -168,6 +168,37 @@ extern unsigned long mmap_min_addr;
/* ??? See if we can avoid exposing so much of the loader internals. */
+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);
+
/* Read a good amount of data initially, to hopefully get all the
program headers loaded. */
#define BPRM_BUF_SIZE 1024
@@ -177,15 +208,16 @@ extern unsigned long mmap_min_addr;
* 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 */
};
typedef struct IOCTLEntry IOCTLEntry;
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 9d4eb5e94b..3b0bafc490 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -2,6 +2,7 @@
#include "qemu/osdep.h"
#include "qemu.h"
+#include "qapi/error.h"
#define NGROUPS 32
@@ -74,6 +75,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;
}
@@ -129,6 +134,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;
@@ -163,3 +169,43 @@ 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;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/12] linux-user: Tidy loader_exec
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
2021-06-19 3:43 ` [PATCH 01/12] linux-user: Fix style problems in linuxload.c Richard Henderson
2021-06-19 3:43 ` [PATCH 02/12] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 04/12] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
` (9 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
Reorg the if cases to reduce indentation.
Test for 4 bytes in the file before checking the signatures.
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 3b0bafc490..8b93b9704c 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -143,31 +143,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.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/12] linux-user: Do not clobber bprm_buf swapping ehdr
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (2 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 03/12] linux-user: Tidy loader_exec Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 9:50 ` Philippe Mathieu-Daudé
2021-06-19 3:43 ` [PATCH 05/12] linux-user: Use ImageSource in load_elf_image Richard Henderson
` (8 subsequent siblings)
12 siblings, 1 reply; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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.
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 c0236a0b09..1f9a69703a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2622,16 +2622,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;
@@ -2944,6 +2945,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;
@@ -2965,7 +2967,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)
@@ -3157,8 +3159,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;
@@ -3170,12 +3178,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 */
@@ -3245,7 +3248,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.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/12] linux-user: Use ImageSource in load_elf_image
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (3 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 04/12] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 06/12] linux-user: Use ImageSource in load_symbols Richard Henderson
` (7 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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 | 124 ++++++++++++++++---------------------------
1 file changed, 47 insertions(+), 77 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 1f9a69703a..425420f0cc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2525,10 +2525,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 {
@@ -2556,14 +2555,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;
}
/*
@@ -2609,30 +2602,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;
@@ -2643,15 +2640,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);
@@ -2687,17 +2680,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");
@@ -2705,7 +2691,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;
}
}
@@ -2847,7 +2833,7 @@ static void load_elf_image(const char *image_name, int image_fd,
vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po);
error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
MAP_PRIVATE | MAP_FIXED,
- image_fd, eppnt->p_offset - vaddr_po);
+ src->fd, eppnt->p_offset - vaddr_po);
if (error == -1) {
goto exit_mmap;
@@ -2893,20 +2879,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
@@ -2919,21 +2896,14 @@ 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);
}
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;
@@ -2946,6 +2916,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;
@@ -2963,11 +2934,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)
@@ -3177,8 +3148,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.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/12] linux-user: Use ImageSource in load_symbols
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (4 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 05/12] linux-user: Use ImageSource in load_elf_image Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 07/12] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
` (6 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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 425420f0cc..3c31a5e3b0 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1729,7 +1729,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. */
@@ -2896,7 +2897,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);
}
mmap_unlock();
@@ -2984,19 +2985,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;
}
@@ -3014,31 +3016,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. */
@@ -3063,10 +3067,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;
@@ -3075,20 +3081,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.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/12] linux-user: Replace bprm->fd with bprm->src.fd
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (5 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 06/12] linux-user: Use ImageSource in load_symbols Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 9:54 ` Philippe Mathieu-Daudé
2021-06-19 3:43 ` [PATCH 08/12] linux-user: Introduce imgsrc_mmap Richard Henderson
` (5 subsequent siblings)
12 siblings, 1 reply; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
There are only a couple of uses of bprm->fd remaining.
Migrate to the other field.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/qemu.h | 1 -
linux-user/flatload.c | 8 ++++----
linux-user/linuxload.c | 5 ++---
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index f4cdfb16b3..dafaae6293 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -211,7 +211,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 3e5594cf89..58d0d9352c 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -460,7 +460,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;
@@ -487,7 +487,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);
}
@@ -537,10 +537,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 8b93b9704c..d0d3f2ed0e 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -36,7 +36,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;
}
@@ -66,7 +66,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);
@@ -133,7 +133,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.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/12] linux-user: Introduce imgsrc_mmap
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (6 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 07/12] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 09/12] linux-user: Load vdso image if available Richard Henderson
` (4 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/qemu.h | 11 +++++++++++
linux-user/elfload.c | 4 ++--
linux-user/linuxload.c | 44 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index dafaae6293..255182e133 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -199,6 +199,17 @@ bool imgsrc_read(void *dst, off_t offset, size_t len,
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. */
#define BPRM_BUF_SIZE 1024
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 3c31a5e3b0..8a3a7ae3ac 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2832,9 +2832,9 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
*/
if (eppnt->p_filesz != 0) {
vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po);
- error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
+ error = imgsrc_mmap(vaddr_ps, vaddr_len, elf_prot,
MAP_PRIVATE | MAP_FIXED,
- src->fd, eppnt->p_offset - vaddr_po);
+ src, eppnt->p_offset - vaddr_po);
if (error == -1) {
goto exit_mmap;
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index d0d3f2ed0e..a437a22b49 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -208,3 +208,47 @@ void *imgsrc_read_alloc(off_t offset, size_t len,
}
return alloc;
}
+
+abi_long imgsrc_mmap(abi_ulong start, abi_ulong len, int prot,
+ int flags, const ImageSource *src, abi_ulong offset)
+{
+ abi_long ret;
+ int prot_write;
+ 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);
+
+ prot_write = prot | PROT_WRITE;
+ 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.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/12] linux-user: Load vdso image if available
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (7 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 08/12] linux-user: Introduce imgsrc_mmap Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 10/12] linux-user: Add gen-vdso tool Richard Henderson
` (3 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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 | 75 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 67 insertions(+), 8 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8a3a7ae3ac..a6ad454617 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1966,7 +1966,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;
@@ -2038,8 +2039,12 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
}
size = (DLINFO_ITEMS + 1) * 2;
- if (k_platform)
+ if (k_platform) {
size += 2;
+ }
+ if (vdso_info) {
+ size += 4;
+ }
#ifdef DLINFO_ARCH_ITEMS
size += DLINFO_ARCH_ITEMS * 2;
#endif
@@ -2116,6 +2121,10 @@ 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, vdso_info->entry);
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, vdso_info->load_addr);
+ }
NEW_AUX_ENT (AT_NULL, 0);
#undef NEW_AUX_ENT
@@ -2942,6 +2951,53 @@ static void load_elf_interp(const char *filename, struct image_info *info,
load_elf_image(filename, &src, info, &ehdr, NULL);
}
+#ifndef HAVE_VDSO
+#define HAVE_VDSO 0
+static uint8_t vdso_image[] = { };
+static uint32_t vdso_relocs[] = { };
+#define vdso_sigreturn 0
+#define vdso_rt_sigreturn 0
+#endif
+
+static void load_elf_vdso(struct image_info *info)
+{
+ ImageSource src;
+ struct elfhdr ehdr;
+ abi_ulong load_bias, load_addr;
+
+ src.fd = -1;
+ src.cache = vdso_image;
+ src.cache_size = sizeof(vdso_image);
+
+ 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 (size_t i = 0, n = ARRAY_SIZE(vdso_relocs); 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) {
+ default_sigreturn = load_addr + vdso_sigreturn;
+ }
+ if (vdso_rt_sigreturn) {
+ default_rt_sigreturn = load_addr + vdso_rt_sigreturn;
+ }
+
+ /* 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)
{
target_ulong addr = *(target_ulong *)s0;
@@ -3146,7 +3202,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;
@@ -3216,10 +3272,12 @@ 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) {
+ if (HAVE_VDSO) {
+ load_elf_vdso(&vdso_info);
+ } else if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
abi_ulong tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -3227,8 +3285,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,
+ HAVE_VDSO ? &vdso_info : NULL);
info->start_stack = bprm->p;
/* If we have an interpreter, set that as the program's entry point.
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/12] linux-user: Add gen-vdso tool
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (8 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 09/12] linux-user: Load vdso image if available Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 11/12] linux-user/x86_64: Add vdso Richard Henderson
` (2 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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 | 168 ++++++++++++++++++
linux-user/gen-vdso-elfn.c.inc | 299 +++++++++++++++++++++++++++++++++
linux-user/meson.build | 6 +-
3 files changed, 472 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..ccbb6c4725
--- /dev/null
+++ b/linux-user/gen-vdso.c
@@ -0,0 +1,168 @@
+/*
+ * 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 "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", loc - buf);
+}
+
+#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 ac, char **av)
+{
+ FILE *inf, *outf;
+ long total_len;
+ const char *inf_name;
+ const char *outf_name;
+ unsigned char *buf;
+ bool need_bswap;
+
+ if (ac != 3) {
+ fprintf(stderr, "usage: input-file output-file\n");
+ return EXIT_FAILURE;
+ }
+ inf_name = av[1];
+ outf_name = av[2];
+
+ /*
+ * 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.
+ */
+
+ fputs("/* Automatically generated from linux-user/gen-vdso.c. */\n"
+ "\n"
+ "static const uint8_t vdso_image[] = {",
+ outf);
+ for (long i = 0; i < total_len; ++i) {
+ if (i % 12 == 0) {
+ fputs("\n ", outf);
+ }
+ fprintf(outf, " 0x%02x,", buf[i]);
+ }
+ fputs("\n};\n\n", outf);
+
+ /*
+ * 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;
+ }
+ switch (buf[EI_CLASS]) {
+ case ELFCLASS32:
+ elf32_process(outf, buf, total_len, need_bswap);
+ break;
+ case ELFCLASS64:
+ elf64_process(outf, buf, total_len, need_bswap);
+ break;
+ default:
+ fprintf(stderr, "%s: invalid elf EI_CLASS (%u)\n",
+ inf_name, buf[EI_CLASS]);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * 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..4e9277aeff
--- /dev/null
+++ b/linux-user/gen-vdso-elfn.c.inc
@@ -0,0 +1,299 @@
+/*
+ * 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(process)(FILE *outf, void *buf, long total_len,
+ 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 dynsym_addr = 0;
+ unsigned sigreturn_addr = 0;
+ unsigned rt_sigreturn_addr = 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);
+ }
+ }
+
+ /*
+ * 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);
+ }
+
+ /*
+ * 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.
+ *
+ * ??? One might think that we'd need to relocate ehdr->e_entry,
+ * but for some reason glibc does that one itself, though that
+ * is also available via the AT_SYSINFO entry.
+ *
+ * Output relocation addresses as we go.
+ */
+ fputs("static const unsigned vdso_relocs[] = {\n", outf);
+
+ /* 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_SYMTAB:
+ dynsym_addr = dyn->d_un.d_val;
+ /* fall through */
+ case DT_HASH:
+ 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_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_RELENT:
+ case DT_RELA:
+ case DT_RELASZ:
+ case DT_RELAENT:
+ case DT_TEXTREL:
+ /*
+ * These entries indicate that the VDSO was built incorrectly.
+ * It should not have any real relocations.
+ */
+ fprintf(stderr, "VDSO has dynamic relocations\n");
+ errors++;
+ 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);
+ }
+ }
+
+ if (dynsym_addr) {
+ __typeof(shdr->sh_size) dynsym_n = 0;
+ ElfN(Sym) *sym = NULL;
+ const char *str = NULL;
+
+ for (unsigned i = 0; i < shnum; ++i) {
+ if (shdr[i].sh_addr == dynsym_addr) {
+ dynsym_n = shdr[i].sh_size / sizeof(*sym);
+ sym = buf + shdr[i].sh_offset;
+ str = buf + shdr[shdr[i].sh_link].sh_offset;
+ break;
+ }
+ }
+
+ for (unsigned i = 0; i < dynsym_n; ++i) {
+ if (need_bswap) {
+ elfN(bswap_sym)(sym + i);
+ }
+
+ /* Relocate the dynamic symbol table. */
+ output_reloc(outf, buf, &sym[i].st_value);
+
+ /* Locate the signal return symbols. */
+ const char *name = str + sym[i].st_name;
+ if (strcmp("__kernel_sigreturn", name) == 0) {
+ sigreturn_addr = sym[i].st_value;
+ } else if (strcmp("__kernel_rt_sigreturn", name) == 0) {
+ rt_sigreturn_addr = sym[i].st_value;
+ }
+ }
+ }
+
+ fputs("};\n\n", outf); /* end vdso_relocs. */
+
+ fprintf(outf, "#define vdso_sigreturn 0x%x\n", sigreturn_addr);
+ fprintf(outf, "#define vdso_rt_sigreturn 0x%x\n", rt_sigreturn_addr);
+}
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 9549f81682..c5e6ab058b 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -18,9 +18,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: ['@INPUT@', '@OUTPUT@'])
+
subdir('alpha')
subdir('arm')
subdir('hppa')
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/12] linux-user/x86_64: Add vdso
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (9 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 10/12] linux-user: Add gen-vdso tool Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 3:43 ` [PATCH 12/12] linux-user/hppa: Add vdso and use it for rt_sigreturn Richard Henderson
2021-06-19 4:06 ` [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa no-reply
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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 | 3 +
linux-user/x86_64/Makefile.vdso | 3 +
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 -> 5912 bytes
6 files changed, 208 insertions(+)
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 a6ad454617..b70a5c48a2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -154,6 +154,9 @@ static uint32_t get_elf_hwcap(void)
#define ELF_CLASS ELFCLASS64
#define ELF_ARCH EM_X86_64
+#define HAVE_VDSO 1
+#include "vdso.c.inc"
+
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
regs->rax = 0;
diff --git a/linux-user/x86_64/Makefile.vdso b/linux-user/x86_64/Makefile.vdso
new file mode 100644
index 0000000000..6111d6f21c
--- /dev/null
+++ b/linux-user/x86_64/Makefile.vdso
@@ -0,0 +1,3 @@
+vdso.so: vdso.S vdso.ld Makefile.vdso
+ $(CC) -nostdlib -shared -Wl,-T,vdso.ld -Wl,--build-id=none \
+ -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..7d0d653526
--- /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..baf261f045
--- /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..0cdb8f1706893abf221e42d3443d9f5d49fef080
GIT binary patch
literal 5912
zcmeHL&ud&&6h4#5G>PWNw2COv8bm7;9TF)LD3qy9;>5Ng1_DtiuhYzHCzzShnU^w=
zQbCLwDVjwW#YJgxFIg5hDiyK*1ybnF3T~t>3@+61eDlsXyt#d~g5c_%<jr^Qch5QR
z-gDm@=DY7qADih(rG%E2L(=YLLndznmmZ>rNM0somwpb*kfKPhUU?gKao$oB`^^tD
zV((?&WWo`m*nAMz9<n}p;t5MgB;TVv=DB6_aWP!9I@mbpIe$ASAuen4aq)nT!HDpM
z0oiU7_xa%chRtuukU6%~A@SQ^tr}XtTi>Q71#@Igx3FNf2SSj#;e&>c8vfA=^Zj7)
ze_G$d<&O2g;6yC${|40ODXhl!o%PzU{2t}U9R3OO&pP}g=I`<o=I`b?Wd7q$o@w)U
zc|1Otk2}w@^1J2NmO_`kqCNQMEkEWBdsQ#2*X6P8gL+|~vG=TlHf2CB?3>=bZP;tf
zr!VXZV!4fIV+<E^Z627+%=mJZ{>XKH@zz`N{pj}1?5CF(J{d2+e{|!gp^x{zd$D=>
z++&{|seZKo+kN}CPx+Ol4_e}RXG@Kmx4c?ge#1NC2f<3kzl*H<4RYpEJ6$TSlZ(da
z`0|@;vbs`TYd(+EIsKoIW3zLMOWq5)7j=F;v41+Cma@OAU;Z-mu=XF<i|-WH*rVe+
zYoDhv2E+cqQlsgEc$ZPzJ6gzjkXp!+LRPV<IHq_(aa{3=B8+)bZ!buynN5uj_VwdC
z2HT2zU(#IMD{$j_U39o9<+dCSbH3nktIB<-9G?~KCYDqnsX$VJqyk9=k_sdhNGgz2
z;9phX+K=islDR(e<a=%ZYqy>LNvD6KyFYQGu+a(zHotqOHKHn_uduNbWWN4+aC3O#
ztLy6ePnOo-;MCz!zqI~3r+)3`(?T8G&G&Zna5tan=;CgEm&EDWv??X);BNo^j{fiF
z2c!U@;8;4M|2PEA0ZrnrSAWK<-JKtLBTnz)H-DUtd{+559Sr?~Jg(k7X#TFgoHgF{
z&sm-^h!-_#nRRU=zpH~^GTzO9Lisp-jPnWbZXWTbUYk37eD;WH#Fyt5z3GBCvvBzM
zv{#r~h=@T`pK+qngruuaBT_V0v$nOU<QnUhpm<6#sE1f)tF&G%R#uiJrw#Rz+?ncH
zu3T)CLnf$)%vrzQSgBRJI$lX~e%U)+FIIf7TvAW=Bp3M2Kx^?|ZB!FL*F)#S_}mfo
zQEVF@U+$-EuRN`zDsS~o42|z2aV!##CgXXo1bvI#jOTkxoC?!+#u?vh{Bw#sdiKP4
zo_7)PT*Eld_>dLB`2g0=ah{J6c^*c8TMoN=3M$fy+@IeUM6Q$hT|BDsI7=hX?-k;t
z-HA1F=l{BnV@`~}*SVvm>747ZUv}d8Jw-f6M??4is1NSX^ThT+27K)S!FwDvJ~!l|
zb0-HpX^weY7|ybW^y2+lSDZib+0|ypuIve$=Q~W;aQAPw(sA*7?Hs##pZLE4>E9DK
literal 0
HcmV?d00001
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 12/12] linux-user/hppa: Add vdso and use it for rt_sigreturn
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (10 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 11/12] linux-user/x86_64: Add vdso Richard Henderson
@ 2021-06-19 3:43 ` Richard Henderson
2021-06-19 4:06 ` [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa no-reply
12 siblings, 0 replies; 17+ messages in thread
From: Richard Henderson @ 2021-06-19 3:43 UTC (permalink / raw
To: qemu-devel; +Cc: alex.bennee, laurent
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 | 3 +
linux-user/hppa/signal.c | 8 +-
linux-user/hppa/Makefile.vdso | 4 +
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 -> 5192 bytes
7 files changed, 238 insertions(+), 7 deletions(-)
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 b70a5c48a2..6cea556b70 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1457,6 +1457,9 @@ static inline void init_thread(struct target_pt_regs *regs,
#define STACK_GROWS_DOWN 0
#define STACK_ALIGNMENT 64
+#define HAVE_VDSO 1
+#include "vdso.c.inc"
+
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 0e266f472d..44e2db6d3e 100644
--- a/linux-user/hppa/signal.c
+++ b/linux-user/hppa/signal.c
@@ -40,7 +40,6 @@ struct target_ucontext {
};
struct target_rt_sigframe {
- abi_uint tramp[9];
target_siginfo_t info;
struct target_ucontext uc;
/* hidden location of upper halves of pa2.0 64-bit gregs */
@@ -138,14 +137,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
setup_sigcontext(&frame->uc.tuc_mcontext, env);
- __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
- __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
- __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
- __put_user(0x08000240, frame->tramp + 3); /* nop */
-
unlock_user_struct(frame, frame_addr, 1);
- env->gr[2] = h2g(frame->tramp);
+ env->gr[2] = default_rt_sigreturn;
env->gr[30] = sp;
env->gr[26] = sig;
env->gr[25] = h2g(&frame->info);
diff --git a/linux-user/hppa/Makefile.vdso b/linux-user/hppa/Makefile.vdso
new file mode 100644
index 0000000000..ce92d51a37
--- /dev/null
+++ b/linux-user/hppa/Makefile.vdso
@@ -0,0 +1,4 @@
+vdso.so: vdso.S vdso.ld Makefile.vdso
+ hppa-linux-gnu-gcc -nostdlib -shared -Wl,-T,vdso.ld \
+ -Wl,-h,linux-vdso.so.1 -Wl,--build-id=none \
+ -Wl,--hash-style=both vdso.S -o $@
diff --git a/linux-user/hppa/meson.build b/linux-user/hppa/meson.build
index 4709508a09..3febe8523a 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')
+]
+
+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..a314dc70f2ae8548bfb1e4137039f983fad094e6
GIT binary patch
literal 5192
zcmeHLS#MiK6rOQ1r7WRN6$wxP@lZs8)^rJ_&;oH{J1IDuleA3;+`6?Jn<h@Uz6nkV
zDNPr;0BzZq0xguKQ1-Ad<p=P@ZvY7i2^9%=DunNwJ5whp4@gKn-J=|zb<Umn=H%hb
zj(9R5L$X3xst^mHN+H7Z)Cp02Mu<=t+ErqnSd8e!@XzyOjBEZDl3ZyR>t|BMun=Uf
z({)XK>e{Y>LRQ8OLH}(A?}JXZ^(p5f9nW|_wqwtIW!AM>->&BwF7a(SH8lO#?>O>z
zu<?C)1`_*}<B%7Cmw+z>bECkC`O{}ndlBTH@P#0;CUiOU|4P@`0@Y&rSLnovdk!!3
z_drZY#FuwQoGj5to06=KX~>|#9zSsM?2*!;pM~RW%esZ^fa7{jG2icIy%Dz{2J(fG
z($djPaVUbn<)S0r(#>@tQ&FO#tor5jarlTM&r1CKFNF|Qy;s9xjHJ&YYb(}3CvMnJ
z)d@dY{KN#gJ=G~HD|=+^!YjX@*tvM}+FjS}zJAY=y-OdC?7LzAvIENxu6ShSqjitn
zcxct(n~to0{N^Wad2-EDYoEULncJSd{ki(*qc1cZZG18IQvBt_v9{ywuXMbcI??%B
z*X!MHtbcRE$&GLIyxn{1u6O$0z5Bg;-giFO^kMp=%~M-G&U}*nbn9pRpXa{Fe|hg$
z+rA$7X7F@D)eouYuxhwZHM%NRRB=xwMpV<NYQA5sE2%ri)ScT^@&VN{u38^dZ4;_}
zhw6Aps?<)YIwz&-+9g%@ZmHJqk!r(UsWu*zs%Jm1K%X7GanVue7908l3J?eo2oMMm
z2oMMm2oMMm2oMMm2oU(+5tuJR^>vqFh_8{oKZr>|Tg***_T&KUhxL5SA=J#E@)Z5B
zIhTUu6n|lGeg*0Inl@%^ZDTIdalR#h{P`L2^NhWS683y!_Zj<qV-FjfGdhT4rq1WA
z&OPe=N`H<<4&MVbas3rY(fc*=l_n<4+`St0%5%39>uHU)tZT&Z+|=6b#G9Q&D%uiv
znqw*9G$q>_qDiMMk?4$fIbG3)WZd!R=eb915h;!hdg;xOp6kn;)iPs+^k9CAh(JLW
zWZFxMNPl4@l1mqJzTb0w&uG>y=7$Qi3@0NZ*_^Z0O%G<BTn3re5)m(3^6WAHjjTly
z?*><J?k$FIFy_AWz4C5&PsAL3z@E^3vCQQ09yE@Sd`F>;dc<DiZ|)Y}^4rWR=<E^J
zLl5aby41JvTh3d7cb7kWKYL5}7x!ZN@!VU_TKISd)<e(f_Z{xVlIdp=L%nG@k;h)t
z{m8T0dX(f2`|bl1-y;k3i^hd<o|m)<%-ZnTx2Rcf05-2MBM&_t0^2PiQm$7rdDv4J
xDtT5tyU2W#VN$pT^_W}*=Gz{>OPl`(#KllG&(UfvNL#NO`pi5R_QXH){sy-o1nd9+
literal 0
HcmV?d00001
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
` (11 preceding siblings ...)
2021-06-19 3:43 ` [PATCH 12/12] linux-user/hppa: Add vdso and use it for rt_sigreturn Richard Henderson
@ 2021-06-19 4:06 ` no-reply
12 siblings, 0 replies; 17+ messages in thread
From: no-reply @ 2021-06-19 4:06 UTC (permalink / raw
To: richard.henderson; +Cc: alex.bennee, qemu-devel, laurent
Patchew URL: https://patchew.org/QEMU/20210619034329.532318-1-richard.henderson@linaro.org/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Type: series
Message-id: 20210619034329.532318-1-richard.henderson@linaro.org
Subject: [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
* [new tag] patchew/20210619034329.532318-1-richard.henderson@linaro.org -> patchew/20210619034329.532318-1-richard.henderson@linaro.org
Switched to a new branch 'test'
eb8d6c9 linux-user/hppa: Add vdso and use it for rt_sigreturn
52cca21 linux-user/x86_64: Add vdso
fd7f59e linux-user: Add gen-vdso tool
5228b92 linux-user: Load vdso image if available
0fc0b1b linux-user: Introduce imgsrc_mmap
e397043 linux-user: Replace bprm->fd with bprm->src.fd
832f702 linux-user: Use ImageSource in load_symbols
9d65bf5 linux-user: Use ImageSource in load_elf_image
b04a74d linux-user: Do not clobber bprm_buf swapping ehdr
acdaddc linux-user: Tidy loader_exec
63442e1 linux-user: Introduce imgsrc_read, imgsrc_read_alloc
a4d2a45 linux-user: Fix style problems in linuxload.c
=== OUTPUT BEGIN ===
1/12 Checking commit a4d2a4511b66 (linux-user: Fix style problems in linuxload.c)
2/12 Checking commit 63442e15ed05 (linux-user: Introduce imgsrc_read, imgsrc_read_alloc)
3/12 Checking commit acdaddc5dc89 (linux-user: Tidy loader_exec)
4/12 Checking commit b04a74dee4d8 (linux-user: Do not clobber bprm_buf swapping ehdr)
5/12 Checking commit 9d65bf56e0c7 (linux-user: Use ImageSource in load_elf_image)
6/12 Checking commit 832f702ccea5 (linux-user: Use ImageSource in load_symbols)
7/12 Checking commit e3970430bd3b (linux-user: Replace bprm->fd with bprm->src.fd)
8/12 Checking commit 0fc0b1bd7d79 (linux-user: Introduce imgsrc_mmap)
9/12 Checking commit 5228b920709c (linux-user: Load vdso image if available)
10/12 Checking commit fd7f59e94124 (linux-user: Add gen-vdso tool)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21:
new file mode 100644
ERROR: trailing whitespace
#31: FILE: linux-user/gen-vdso-elfn.c.inc:6:
+ * $
ERROR: spaces required around that '*' (ctx:WxV)
#92: FILE: linux-user/gen-vdso-elfn.c.inc:67:
+static void elfN(process)(FILE *outf, void *buf, long total_len,
^
ERROR: trailing whitespace
#184: FILE: linux-user/gen-vdso-elfn.c.inc:159:
+ $
ERROR: trailing whitespace
#335: FILE: linux-user/gen-vdso.c:5:
+ * $
ERROR: spaces required around that ':' (ctx:VxW)
#350: FILE: linux-user/gen-vdso.c:20:
+ uint16_t: __builtin_bswap16, \
^
ERROR: spaces required around that ':' (ctx:VxW)
#351: FILE: linux-user/gen-vdso.c:21:
+ uint32_t: __builtin_bswap32, \
^
ERROR: spaces required around that ':' (ctx:VxW)
#352: FILE: linux-user/gen-vdso.c:22:
+ uint64_t: __builtin_bswap64, \
^
ERROR: spaces required around that ':' (ctx:VxW)
#353: FILE: linux-user/gen-vdso.c:23:
+ int16_t: __builtin_bswap16, \
^
ERROR: spaces required around that ':' (ctx:VxW)
#354: FILE: linux-user/gen-vdso.c:24:
+ int32_t: __builtin_bswap32, \
^
ERROR: spaces required around that ':' (ctx:VxW)
#355: FILE: linux-user/gen-vdso.c:25:
+ int64_t: __builtin_bswap64)
^
WARNING: Block comments use a leading /* on a separate line
#436: FILE: linux-user/gen-vdso.c:106:
+ fputs("/* Automatically generated from linux-user/gen-vdso.c. */\n"
total: 10 errors, 2 warnings, 481 lines checked
Patch 10/12 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
11/12 Checking commit 52cca2161834 (linux-user/x86_64: Add vdso)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#38:
new file mode 100644
ERROR: trailing whitespace
#70: FILE: linux-user/x86_64/vdso.S:5:
+ * $
ERROR: trailing whitespace
#198: FILE: linux-user/x86_64/vdso.ld:5:
+ * $
total: 2 errors, 1 warnings, 217 lines checked
Patch 11/12 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
12/12 Checking commit eb8d6c9db1a6 (linux-user/hppa: Add vdso and use it for rt_sigreturn)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#42:
new file mode 100644
total: 0 errors, 1 warnings, 268 lines checked
Patch 12/12 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/20210619034329.532318-1-richard.henderson@linaro.org/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 01/12] linux-user: Fix style problems in linuxload.c
2021-06-19 3:43 ` [PATCH 01/12] linux-user: Fix style problems in linuxload.c Richard Henderson
@ 2021-06-19 9:47 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-06-19 9:47 UTC (permalink / raw
To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent
On 6/19/21 5:43 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/linuxload.c | 42 ++++++++++++++++++++----------------------
> 1 file changed, 20 insertions(+), 22 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 04/12] linux-user: Do not clobber bprm_buf swapping ehdr
2021-06-19 3:43 ` [PATCH 04/12] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
@ 2021-06-19 9:50 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-06-19 9:50 UTC (permalink / raw
To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent
On 6/19/21 5:43 AM, Richard Henderson wrote:
> 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.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/elfload.c | 25 ++++++++++++++-----------
> 1 file changed, 14 insertions(+), 11 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 07/12] linux-user: Replace bprm->fd with bprm->src.fd
2021-06-19 3:43 ` [PATCH 07/12] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
@ 2021-06-19 9:54 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-06-19 9:54 UTC (permalink / raw
To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent
On 6/19/21 5:43 AM, Richard Henderson wrote:
> There are only a couple of uses of bprm->fd remaining.
> Migrate to the other field.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/qemu.h | 1 -
> linux-user/flatload.c | 8 ++++----
> linux-user/linuxload.c | 5 ++---
> 3 files changed, 6 insertions(+), 8 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2021-06-19 9:56 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-06-19 3:43 [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa Richard Henderson
2021-06-19 3:43 ` [PATCH 01/12] linux-user: Fix style problems in linuxload.c Richard Henderson
2021-06-19 9:47 ` Philippe Mathieu-Daudé
2021-06-19 3:43 ` [PATCH 02/12] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
2021-06-19 3:43 ` [PATCH 03/12] linux-user: Tidy loader_exec Richard Henderson
2021-06-19 3:43 ` [PATCH 04/12] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
2021-06-19 9:50 ` Philippe Mathieu-Daudé
2021-06-19 3:43 ` [PATCH 05/12] linux-user: Use ImageSource in load_elf_image Richard Henderson
2021-06-19 3:43 ` [PATCH 06/12] linux-user: Use ImageSource in load_symbols Richard Henderson
2021-06-19 3:43 ` [PATCH 07/12] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
2021-06-19 9:54 ` Philippe Mathieu-Daudé
2021-06-19 3:43 ` [PATCH 08/12] linux-user: Introduce imgsrc_mmap Richard Henderson
2021-06-19 3:43 ` [PATCH 09/12] linux-user: Load vdso image if available Richard Henderson
2021-06-19 3:43 ` [PATCH 10/12] linux-user: Add gen-vdso tool Richard Henderson
2021-06-19 3:43 ` [PATCH 11/12] linux-user/x86_64: Add vdso Richard Henderson
2021-06-19 3:43 ` [PATCH 12/12] linux-user/hppa: Add vdso and use it for rt_sigreturn Richard Henderson
2021-06-19 4:06 ` [PATCH 00/12] linux-user: Load a vdso for x86_64 and hppa no-reply
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.