mirror of https://github.com/xemu-project/xemu.git
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:
commit
851ed57d7a
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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 ;;
|
||||
|
|
|
@ -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,$<))
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue