tests/tcg: Replace -mpower8-vector with -mcpu=power8

linux-user: Fix GDB complaining about system-supplied DSO string table index
 linux-user: Allow custom rt signal mappings
 -----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmcqM2wdHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV86KQgAhR1OmVAhPYTJiYH6
 Bhp9s+PbdFw/UbxConf9+WFoa/vM1x/QvX1ybzNDl9aOeiH9RIX4hFWUH5WR8xu+
 gZrzplHDcsrUEs5Q7/GWGJaCbd92Rn6g5wcXyoVebMaVP1g/m+NJoxo2XOpZvY06
 G0BcNj4Ib/D0FgkgZrUJcf3DBWaW/9WCd17fBXLo1bpahdKvqV4PbmhhH+QZCVXr
 GHg03F+/35U85kNVnPcUg4PJARQHdK4ZmfE4etgGvVkTdS8r43qfO1nMT0ul8aOD
 uATdMQrbwKA0XLjWVOVxe4165c+luHpUweKNgiOie+s849YUM3TsFpunKoPBIEpQ
 Gu0ejw==
 =wipF
 -----END PGP SIGNATURE-----

Merge tag 'pull-lu-20241105' of https://gitlab.com/rth7680/qemu into staging

tests/tcg: Replace -mpower8-vector with -mcpu=power8
linux-user: Fix GDB complaining about system-supplied DSO string table index
linux-user: Allow custom rt signal mappings

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmcqM2wdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV86KQgAhR1OmVAhPYTJiYH6
# Bhp9s+PbdFw/UbxConf9+WFoa/vM1x/QvX1ybzNDl9aOeiH9RIX4hFWUH5WR8xu+
# gZrzplHDcsrUEs5Q7/GWGJaCbd92Rn6g5wcXyoVebMaVP1g/m+NJoxo2XOpZvY06
# G0BcNj4Ib/D0FgkgZrUJcf3DBWaW/9WCd17fBXLo1bpahdKvqV4PbmhhH+QZCVXr
# GHg03F+/35U85kNVnPcUg4PJARQHdK4ZmfE4etgGvVkTdS8r43qfO1nMT0ul8aOD
# uATdMQrbwKA0XLjWVOVxe4165c+luHpUweKNgiOie+s849YUM3TsFpunKoPBIEpQ
# Gu0ejw==
# =wipF
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 05 Nov 2024 15:02:04 GMT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* tag 'pull-lu-20241105' of https://gitlab.com/rth7680/qemu:
  tests/tcg: Add SIGRTMIN/SIGRTMAX test
  linux-user: Allow custom rt signal mappings
  linux-user: Fix GDB complaining about system-supplied DSO string table index
  tests/tcg: Replace -mpower8-vector with -mcpu=power8

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2024-11-06 15:01:16 +00:00
commit 851ed57d7a
10 changed files with 269 additions and 76 deletions

View File

@ -68,28 +68,45 @@ static void elfN(search_symtab)(ElfN(Shdr) *shdr, unsigned sym_idx,
void *buf, bool need_bswap)
{
unsigned str_idx = shdr[sym_idx].sh_link;
ElfN(Sym) *sym = buf + shdr[sym_idx].sh_offset;
unsigned sym_n = shdr[sym_idx].sh_size / sizeof(*sym);
ElfN(Sym) *target_sym = buf + shdr[sym_idx].sh_offset;
unsigned sym_n = shdr[sym_idx].sh_size / sizeof(*target_sym);
const char *str = buf + shdr[str_idx].sh_offset;
for (unsigned i = 0; i < sym_n; ++i) {
const char *name;
ElfN(Sym) sym;
memcpy(&sym, &target_sym[i], sizeof(sym));
if (need_bswap) {
elfN(bswap_sym)(sym + i);
elfN(bswap_sym)(&sym);
}
name = str + sym[i].st_name;
name = str + sym.st_name;
if (sigreturn_sym && strcmp(sigreturn_sym, name) == 0) {
sigreturn_addr = sym[i].st_value;
sigreturn_addr = sym.st_value;
}
if (rt_sigreturn_sym && strcmp(rt_sigreturn_sym, name) == 0) {
rt_sigreturn_addr = sym[i].st_value;
rt_sigreturn_addr = sym.st_value;
}
}
}
static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
static void elfN(bswap_ps_hdrs)(ElfN(Ehdr) *ehdr)
{
ElfN(Phdr) *phdr = (void *)ehdr + ehdr->e_phoff;
ElfN(Shdr) *shdr = (void *)ehdr + ehdr->e_shoff;
ElfN(Half) i;
for (i = 0; i < ehdr->e_phnum; ++i) {
elfN(bswap_phdr)(&phdr[i]);
}
for (i = 0; i < ehdr->e_shnum; ++i) {
elfN(bswap_shdr)(&shdr[i]);
}
}
static void elfN(process)(FILE *outf, void *buf, long len, bool need_bswap)
{
ElfN(Ehdr) *ehdr = buf;
ElfN(Phdr) *phdr;
@ -103,24 +120,14 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
int errors = 0;
if (need_bswap) {
elfN(bswap_ehdr)(ehdr);
elfN(bswap_ehdr)(buf);
elfN(bswap_ps_hdrs)(buf);
}
phnum = ehdr->e_phnum;
phdr = buf + ehdr->e_phoff;
if (need_bswap) {
for (unsigned i = 0; i < phnum; ++i) {
elfN(bswap_phdr)(phdr + i);
}
}
shnum = ehdr->e_shnum;
shdr = buf + ehdr->e_shoff;
if (need_bswap) {
for (unsigned i = 0; i < shnum; ++i) {
elfN(bswap_shdr)(shdr + i);
}
}
for (unsigned i = 0; i < shnum; ++i) {
switch (shdr[i].sh_type) {
case SHT_SYMTAB:
@ -154,7 +161,24 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
fprintf(stderr, "LOAD segment not loaded at address 0\n");
errors++;
}
first_segsz = phdr[i].p_filesz;
/*
* Extend the program header to cover the entire VDSO, so that
* load_elf_vdso() loads everything, including section headers.
*
* Require that there is no .bss, since it would break this
* approach.
*/
if (phdr[i].p_filesz != phdr[i].p_memsz) {
fprintf(stderr, "LOAD segment's filesz and memsz differ\n");
errors++;
}
if (phdr[i].p_filesz > len) {
fprintf(stderr, "LOAD segment is larger than the whole VDSO\n");
errors++;
}
phdr[i].p_filesz = len;
phdr[i].p_memsz = len;
first_segsz = len;
if (first_segsz < ehdr->e_phoff + phnum * sizeof(*phdr)) {
fprintf(stderr, "LOAD segment does not cover PHDRs\n");
errors++;
@ -197,17 +221,24 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
output_reloc(outf, buf, &phdr[i].p_paddr);
}
/* Relocate the section headers. */
for (unsigned i = 0; i < shnum; ++i) {
output_reloc(outf, buf, &shdr[i].sh_addr);
}
/* Relocate the DYNAMIC entries. */
if (dynamic_addr) {
ElfN(Dyn) *dyn = buf + dynamic_ofs;
__typeof(dyn->d_tag) tag;
ElfN(Dyn) *target_dyn = buf + dynamic_ofs;
__typeof(((ElfN(Dyn) *)target_dyn)->d_tag) tag;
do {
ElfN(Dyn) dyn;
memcpy(&dyn, target_dyn, sizeof(dyn));
if (need_bswap) {
elfN(bswap_dyn)(dyn);
elfN(bswap_dyn)(&dyn);
}
tag = dyn->d_tag;
tag = dyn.d_tag;
switch (tag) {
case DT_HASH:
@ -218,7 +249,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
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);
output_reloc(outf, buf, &target_dyn->d_un.d_val);
break;
case DT_NULL:
@ -235,7 +266,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
break;
case DT_SYMENT:
if (dyn->d_un.d_val != sizeof(ElfN(Sym))) {
if (dyn.d_un.d_val != sizeof(ElfN(Sym))) {
fprintf(stderr, "VDSO has incorrect dynamic symbol size\n");
errors++;
}
@ -251,7 +282,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
* ??? The RISC-V toolchain will emit these even when there
* are no relocations. Validate zeros.
*/
if (dyn->d_un.d_val != 0) {
if (dyn.d_un.d_val != 0) {
fprintf(stderr, "VDSO has dynamic relocations\n");
errors++;
}
@ -287,7 +318,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
errors++;
break;
}
dyn++;
target_dyn++;
} while (tag != DT_NULL);
if (errors) {
exit(EXIT_FAILURE);
@ -296,11 +327,11 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
/* Relocate the dynamic symbol table. */
if (dynsym_idx) {
ElfN(Sym) *sym = buf + shdr[dynsym_idx].sh_offset;
unsigned sym_n = shdr[dynsym_idx].sh_size / sizeof(*sym);
ElfN(Sym) *target_sym = buf + shdr[dynsym_idx].sh_offset;
unsigned sym_n = shdr[dynsym_idx].sh_size / sizeof(*target_sym);
for (unsigned i = 0; i < sym_n; ++i) {
output_reloc(outf, buf, &sym[i].st_value);
output_reloc(outf, buf, &target_sym[i].st_value);
}
}
@ -311,4 +342,9 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
if (symtab_idx) {
elfN(search_symtab)(shdr, symtab_idx, buf, need_bswap);
}
if (need_bswap) {
elfN(bswap_ps_hdrs)(buf);
elfN(bswap_ehdr)(buf);
}
}

View File

@ -131,23 +131,6 @@ int main(int argc, char **argv)
}
fclose(inf);
/*
* Write out the vdso image now, before we make local changes.
*/
fprintf(outf,
"/* Automatically generated from linux-user/gen-vdso.c. */\n"
"\n"
"static const uint8_t %s_image[] = {",
prefix);
for (long i = 0; i < total_len; ++i) {
if (i % 12 == 0) {
fputs("\n ", outf);
}
fprintf(outf, " 0x%02x,", buf[i]);
}
fprintf(outf, "\n};\n\n");
/*
* Identify which elf flavor we're processing.
* The first 16 bytes of the file are e_ident.
@ -179,14 +162,17 @@ int main(int argc, char **argv)
* Output relocation addresses as we go.
*/
fprintf(outf, "static const unsigned %s_relocs[] = {\n", prefix);
fprintf(outf,
"/* Automatically generated by linux-user/gen-vdso.c. */\n"
"\n"
"static const unsigned %s_relocs[] = {\n", prefix);
switch (buf[EI_CLASS]) {
case ELFCLASS32:
elf32_process(outf, buf, need_bswap);
elf32_process(outf, buf, total_len, need_bswap);
break;
case ELFCLASS64:
elf64_process(outf, buf, need_bswap);
elf64_process(outf, buf, total_len, need_bswap);
break;
default:
fprintf(stderr, "%s: invalid elf EI_CLASS (%u)\n",
@ -196,6 +182,20 @@ int main(int argc, char **argv)
fprintf(outf, "};\n\n"); /* end vdso_relocs. */
/*
* Write out the vdso image now, after we made local changes.
*/
fprintf(outf,
"static const uint8_t %s_image[] = {",
prefix);
for (long i = 0; i < total_len; ++i) {
if (i % 12 == 0) {
fputs("\n ", outf);
}
fprintf(outf, " 0x%02x,", buf[i]);
}
fprintf(outf, "\n};\n\n");
fprintf(outf, "static const VdsoImageInfo %s_image_info = {\n", prefix);
fprintf(outf, " .image = %s_image,\n", prefix);
fprintf(outf, " .relocs = %s_relocs,\n", prefix);

View File

@ -412,6 +412,13 @@ static void handle_arg_reserved_va(const char *arg)
reserved_va = val ? val - 1 : 0;
}
static const char *rtsig_map = CONFIG_QEMU_RTSIG_MAP;
static void handle_arg_rtsig_map(const char *arg)
{
rtsig_map = arg;
}
static void handle_arg_one_insn_per_tb(const char *arg)
{
opt_one_insn_per_tb = true;
@ -494,6 +501,9 @@ static const struct qemu_argument arg_table[] = {
"address", "set guest_base address to 'address'"},
{"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
"size", "reserve 'size' bytes for guest virtual address space"},
{"t", "QEMU_RTSIG_MAP", true, handle_arg_rtsig_map,
"tsig hsig n[,...]",
"map target rt signals [tsig,tsig+n) to [hsig,hsig+n]"},
{"d", "QEMU_LOG", true, handle_arg_log,
"item[,...]", "enable logging of specified items "
"(use '-d help' for a list of items)"},
@ -1002,7 +1012,7 @@ int main(int argc, char **argv, char **envp)
target_set_brk(info->brk);
syscall_init();
signal_init();
signal_init(rtsig_map);
/* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
generating the prologue until now so that the prologue can take

View File

@ -56,7 +56,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
target_sigset_t *set, CPUArchState *env);
void process_pending_signals(CPUArchState *cpu_env);
void signal_init(void);
void signal_init(const char *rtsig_map);
void queue_signal(CPUArchState *env, int sig, int si_type,
target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);

View File

@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "qemu/cutils.h"
#include "gdbstub/user.h"
#include "exec/page-protection.h"
#include "hw/core/tcg-cpu-ops.h"
@ -513,20 +514,81 @@ static int core_dump_signal(int sig)
}
}
static void signal_table_init(void)
static void signal_table_init(const char *rtsig_map)
{
int hsig, tsig, count;
if (rtsig_map) {
/*
* Map host RT signals to target RT signals according to the
* user-provided specification.
*/
const char *s = rtsig_map;
while (true) {
int i;
if (qemu_strtoi(s, &s, 10, &tsig) || *s++ != ' ') {
fprintf(stderr, "Malformed target signal in QEMU_RTSIG_MAP\n");
exit(EXIT_FAILURE);
}
if (qemu_strtoi(s, &s, 10, &hsig) || *s++ != ' ') {
fprintf(stderr, "Malformed host signal in QEMU_RTSIG_MAP\n");
exit(EXIT_FAILURE);
}
if (qemu_strtoi(s, &s, 10, &count) || (*s && *s != ',')) {
fprintf(stderr, "Malformed signal count in QEMU_RTSIG_MAP\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < count; i++, tsig++, hsig++) {
if (tsig < TARGET_SIGRTMIN || tsig > TARGET_NSIG) {
fprintf(stderr, "%d is not a target rt signal\n", tsig);
exit(EXIT_FAILURE);
}
if (hsig < SIGRTMIN || hsig > SIGRTMAX) {
fprintf(stderr, "%d is not a host rt signal\n", hsig);
exit(EXIT_FAILURE);
}
if (host_to_target_signal_table[hsig]) {
fprintf(stderr, "%d already maps %d\n",
hsig, host_to_target_signal_table[hsig]);
exit(EXIT_FAILURE);
}
host_to_target_signal_table[hsig] = tsig;
}
if (*s) {
s++;
} else {
break;
}
}
} else {
/*
* Default host-to-target RT signal mapping.
*
* Signals are supported starting from TARGET_SIGRTMIN and going up
* until we run out of host realtime signals. Glibc uses the lower 2
* RT signals and (hopefully) nobody uses the upper ones.
* This is why SIGRTMIN (34) is generally greater than __SIGRTMIN (32).
* To fix this properly we would need to do manual signal delivery
* multiplexed over a single host signal.
* Attempts for configure "missing" signals via sigaction will be
* silently ignored.
*
* Reserve one signal for internal usage (see below).
*/
hsig = SIGRTMIN + 1;
for (tsig = TARGET_SIGRTMIN;
hsig <= SIGRTMAX && tsig <= TARGET_NSIG;
hsig++, tsig++) {
host_to_target_signal_table[hsig] = tsig;
}
}
/*
* Signals are supported starting from TARGET_SIGRTMIN and going up
* until we run out of host realtime signals. Glibc uses the lower 2
* RT signals and (hopefully) nobody uses the upper ones.
* This is why SIGRTMIN (34) is generally greater than __SIGRTMIN (32).
* To fix this properly we would need to do manual signal delivery
* multiplexed over a single host signal.
* Attempts for configure "missing" signals via sigaction will be
* silently ignored.
*
* Remap the target SIGABRT, so that we can distinguish host abort
* from guest abort. When the guest registers a signal handler or
* calls raise(SIGABRT), the host will raise SIG_RTn. If the guest
@ -536,21 +598,27 @@ static void signal_table_init(void)
* parent sees the correct mapping from wait status.
*/
hsig = SIGRTMIN;
host_to_target_signal_table[SIGABRT] = 0;
host_to_target_signal_table[hsig++] = TARGET_SIGABRT;
for (tsig = TARGET_SIGRTMIN;
hsig <= SIGRTMAX && tsig <= TARGET_NSIG;
hsig++, tsig++) {
host_to_target_signal_table[hsig] = tsig;
for (hsig = SIGRTMIN; hsig <= SIGRTMAX; hsig++) {
if (!host_to_target_signal_table[hsig]) {
host_to_target_signal_table[hsig] = TARGET_SIGABRT;
break;
}
}
if (hsig > SIGRTMAX) {
fprintf(stderr, "No rt signals left for SIGABRT mapping\n");
exit(EXIT_FAILURE);
}
/* Invert the mapping that has already been assigned. */
for (hsig = 1; hsig < _NSIG; hsig++) {
tsig = host_to_target_signal_table[hsig];
if (tsig) {
assert(target_to_host_signal_table[tsig] == 0);
if (target_to_host_signal_table[tsig]) {
fprintf(stderr, "%d is already mapped to %d\n",
tsig, target_to_host_signal_table[tsig]);
exit(EXIT_FAILURE);
}
target_to_host_signal_table[tsig] = hsig;
}
}
@ -573,13 +641,13 @@ static void signal_table_init(void)
trace_signal_table_init(count);
}
void signal_init(void)
void signal_init(const char *rtsig_map)
{
TaskState *ts = get_task_state(thread_cpu);
struct sigaction act, oact;
/* initialize signal conversion tables */
signal_table_init();
signal_table_init(rtsig_map);
/* Set the signal mask from the host mask. */
sigprocmask(0, 0, &ts->signal_mask);

View File

@ -3178,7 +3178,8 @@ foreach target : target_dirs
config_target += {
'CONFIG_USER_ONLY': 'y',
'CONFIG_QEMU_INTERP_PREFIX':
get_option('interp_prefix').replace('%M', config_target['TARGET_NAME'])
get_option('interp_prefix').replace('%M', config_target['TARGET_NAME']),
'CONFIG_QEMU_RTSIG_MAP': get_option('rtsig_map'),
}
endif

View File

@ -27,6 +27,8 @@ option('block_drv_ro_whitelist', type : 'string', value : '',
description: 'set block driver read-only whitelist (by default affects only QEMU, not tools like qemu-img)')
option('interp_prefix', type : 'string', value : '/usr/gnemul/qemu-%M',
description: 'where to find shared libraries etc., use %M for cpu name')
option('rtsig_map', type : 'string', value : 'NULL',
description: 'default value of QEMU_RTSIG_MAP')
option('fuzzing_engine', type : 'string', value : '',
description: 'fuzzing engine library for OSS-Fuzz')
option('trace_file', type: 'string', value: 'trace',

View File

@ -72,6 +72,7 @@ meson_options_help() {
printf "%s\n" ' "manufacturer" name for qemu-ga registry entries'
printf "%s\n" ' [QEMU]'
printf "%s\n" ' --qemu-ga-version=VALUE version number for qemu-ga installer'
printf "%s\n" ' --rtsig-map=VALUE default value of QEMU_RTSIG_MAP [NULL]'
printf "%s\n" ' --smbd=VALUE Path to smbd for slirp networking'
printf "%s\n" ' --sysconfdir=VALUE Sysconf data directory [etc]'
printf "%s\n" ' --tls-priority=VALUE Default TLS protocol/cipher priority string'
@ -460,6 +461,7 @@ _meson_option_parse() {
--disable-replication) printf "%s" -Dreplication=disabled ;;
--enable-rng-none) printf "%s" -Drng_none=true ;;
--disable-rng-none) printf "%s" -Drng_none=false ;;
--rtsig-map=*) quote_sh "-Drtsig_map=$2" ;;
--enable-rust) printf "%s" -Drust=enabled ;;
--disable-rust) printf "%s" -Drust=disabled ;;
--enable-rutabaga-gfx) printf "%s" -Drutabaga_gfx=enabled ;;

View File

@ -179,10 +179,10 @@ run-plugin-%-with-libmem.so: PLUGIN_ARGS=$(COMMA)inline=true
ifeq ($(filter %-softmmu, $(TARGET)),)
run-%: %
$(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<)
$(call run-test, $<, env QEMU=$(QEMU) $(QEMU) $(QEMU_OPTS) $<)
run-plugin-%:
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
$(call run-test, $@, env QEMU=$(QEMU) $(QEMU) $(QEMU_OPTS) \
-plugin $(PLUGIN_LIB)/$(call extract-plugin,$@)$(PLUGIN_ARGS) \
-d plugin -D $*.pout \
$(call strip-plugin,$<))

View File

@ -0,0 +1,74 @@
/*
* Test the lowest and the highest real-time signals.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* For hexagon and microblaze. */
#ifndef __SIGRTMIN
#define __SIGRTMIN 32
#endif
extern char **environ;
static bool seen_sigrtmin, seen_sigrtmax;
static void handle_signal(int sig)
{
if (sig == SIGRTMIN) {
seen_sigrtmin = true;
} else if (sig == SIGRTMAX) {
seen_sigrtmax = true;
} else {
_exit(1);
}
}
int main(int argc, char **argv)
{
char *qemu = getenv("QEMU");
struct sigaction act;
assert(qemu);
if (!getenv("QEMU_RTSIG_MAP")) {
char **new_argv = malloc((argc + 2) + sizeof(char *));
int tsig1, hsig1, count1, tsig2, hsig2, count2;
char rt_sigmap[64];
/* Re-exec with a mapping that includes SIGRTMIN and SIGRTMAX. */
new_argv[0] = qemu;
memcpy(&new_argv[1], argv, (argc + 1) * sizeof(char *));
tsig1 = __SIGRTMIN;
/* The host must have a few signals starting from this one. */
hsig1 = 36;
count1 = SIGRTMIN - __SIGRTMIN + 1;
tsig2 = SIGRTMAX;
hsig2 = hsig1 + count1;
count2 = 1;
snprintf(rt_sigmap, sizeof(rt_sigmap), "%d %d %d,%d %d %d",
tsig1, hsig1, count1, tsig2, hsig2, count2);
setenv("QEMU_RTSIG_MAP", rt_sigmap, 0);
assert(execve(new_argv[0], new_argv, environ) == 0);
return EXIT_FAILURE;
}
memset(&act, 0, sizeof(act));
act.sa_handler = handle_signal;
assert(sigaction(SIGRTMIN, &act, NULL) == 0);
assert(sigaction(SIGRTMAX, &act, NULL) == 0);
assert(kill(getpid(), SIGRTMIN) == 0);
assert(seen_sigrtmin);
assert(kill(getpid(), SIGRTMAX) == 0);
assert(seen_sigrtmax);
return EXIT_SUCCESS;
}