These variables will be populated from the vdso, and used
for detecting whether we are executing the sigreturn.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/loader.h | 2 ++
linux-user/signal-common.h | 2 ++
linux-user/elfload.c | 5 +++++
linux-user/gen-vdso.c | 6 ++++++
linux-user/signal.c | 2 ++
linux-user/gen-vdso-elfn.c.inc | 7 +++++--
6 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/linux-user/loader.h b/linux-user/loader.h
index e42b8fa1e3..da9ad28db5 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -117,6 +117,8 @@ typedef struct {
unsigned reloc_count;
unsigned sigreturn_ofs;
unsigned rt_sigreturn_ofs;
+ unsigned sigreturn_region_start_ofs;
+ unsigned sigreturn_region_end_ofs;
} VdsoImageInfo;
/* Note that both Elf32_Word and Elf64_Word are uint32_t. */
diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h
index 196d2406f8..0b04868727 100644
--- a/linux-user/signal-common.h
+++ b/linux-user/signal-common.h
@@ -25,6 +25,8 @@
/* Fallback addresses into sigtramp page. */
extern abi_ulong default_sigreturn;
extern abi_ulong default_rt_sigreturn;
+extern abi_ulong vdso_sigreturn_region_start;
+extern abi_ulong vdso_sigreturn_region_end;
void setup_sigtramp(abi_ulong tramp_page);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 26c090c95d..28f0909d1a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1659,6 +1659,11 @@ static void load_elf_vdso(struct image_info *info, const VdsoImageInfo *vdso)
if (vdso->rt_sigreturn_ofs) {
default_rt_sigreturn = load_addr + vdso->rt_sigreturn_ofs;
}
+ if (vdso->sigreturn_region_start_ofs) {
+ vdso_sigreturn_region_start =
+ load_addr + vdso->sigreturn_region_start_ofs;
+ vdso_sigreturn_region_end = load_addr + vdso->sigreturn_region_end_ofs;
+ }
/* Remove write from VDSO segment. */
target_mprotect(info->start_data, info->end_data - info->start_data,
diff --git a/linux-user/gen-vdso.c b/linux-user/gen-vdso.c
index aeaa927db8..d6a2cdaa83 100644
--- a/linux-user/gen-vdso.c
+++ b/linux-user/gen-vdso.c
@@ -36,6 +36,8 @@ static const char *rt_sigreturn_sym;
static unsigned sigreturn_addr;
static unsigned rt_sigreturn_addr;
+static unsigned sigreturn_region_start_addr;
+static unsigned sigreturn_region_end_addr;
#define N 32
#define elfN(x) elf32_##x
@@ -215,6 +217,10 @@ int main(int argc, char **argv)
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, " .sigreturn_region_start_ofs = 0x%x,\n",
+ sigreturn_region_start_addr);
+ fprintf(outf, " .sigreturn_region_end_ofs = 0x%x,\n",
+ sigreturn_region_end_addr);
fprintf(outf, "};\n");
ret = EXIT_SUCCESS;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index cd0e7398aa..804096bd44 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -50,6 +50,8 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
/* Fallback addresses into sigtramp page. */
abi_ulong default_sigreturn;
abi_ulong default_rt_sigreturn;
+abi_ulong vdso_sigreturn_region_start;
+abi_ulong vdso_sigreturn_region_end;
/*
* System includes define _NSIG as SIGRTMAX + 1, but qemu (like the kernel)
diff --git a/linux-user/gen-vdso-elfn.c.inc b/linux-user/gen-vdso-elfn.c.inc
index b47019e136..c2677a146c 100644
--- a/linux-user/gen-vdso-elfn.c.inc
+++ b/linux-user/gen-vdso-elfn.c.inc
@@ -84,9 +84,12 @@ static void elfN(search_symtab)(ElfN(Shdr) *shdr, unsigned sym_idx,
if (sigreturn_sym && strcmp(sigreturn_sym, name) == 0) {
sigreturn_addr = sym.st_value;
- }
- if (rt_sigreturn_sym && strcmp(rt_sigreturn_sym, name) == 0) {
+ } else if (rt_sigreturn_sym && strcmp(rt_sigreturn_sym, name) == 0) {
rt_sigreturn_addr = sym.st_value;
+ } else if (strcmp("sigreturn_region_start", name) == 0) {
+ sigreturn_region_start_addr = sym.st_value;
+ } else if (strcmp("sigreturn_region_end", name) == 0) {
+ sigreturn_region_end_addr = sym.st_value;
}
}
}
--
2.43.0