mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
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
10 changed files with 269 additions and 76 deletions
|
@ -68,28 +68,45 @@ static void elfN(search_symtab)(ElfN(Shdr) *shdr, unsigned sym_idx,
|
||||||
void *buf, bool need_bswap)
|
void *buf, bool need_bswap)
|
||||||
{
|
{
|
||||||
unsigned str_idx = shdr[sym_idx].sh_link;
|
unsigned str_idx = shdr[sym_idx].sh_link;
|
||||||
ElfN(Sym) *sym = buf + shdr[sym_idx].sh_offset;
|
ElfN(Sym) *target_sym = buf + shdr[sym_idx].sh_offset;
|
||||||
unsigned sym_n = shdr[sym_idx].sh_size / sizeof(*sym);
|
unsigned sym_n = shdr[sym_idx].sh_size / sizeof(*target_sym);
|
||||||
const char *str = buf + shdr[str_idx].sh_offset;
|
const char *str = buf + shdr[str_idx].sh_offset;
|
||||||
|
|
||||||
for (unsigned i = 0; i < sym_n; ++i) {
|
for (unsigned i = 0; i < sym_n; ++i) {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
ElfN(Sym) sym;
|
||||||
|
|
||||||
|
memcpy(&sym, &target_sym[i], sizeof(sym));
|
||||||
if (need_bswap) {
|
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) {
|
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) {
|
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(Ehdr) *ehdr = buf;
|
||||||
ElfN(Phdr) *phdr;
|
ElfN(Phdr) *phdr;
|
||||||
|
@ -103,24 +120,14 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
if (need_bswap) {
|
if (need_bswap) {
|
||||||
elfN(bswap_ehdr)(ehdr);
|
elfN(bswap_ehdr)(buf);
|
||||||
|
elfN(bswap_ps_hdrs)(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
phnum = ehdr->e_phnum;
|
phnum = ehdr->e_phnum;
|
||||||
phdr = buf + ehdr->e_phoff;
|
phdr = buf + ehdr->e_phoff;
|
||||||
if (need_bswap) {
|
|
||||||
for (unsigned i = 0; i < phnum; ++i) {
|
|
||||||
elfN(bswap_phdr)(phdr + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shnum = ehdr->e_shnum;
|
shnum = ehdr->e_shnum;
|
||||||
shdr = buf + ehdr->e_shoff;
|
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) {
|
for (unsigned i = 0; i < shnum; ++i) {
|
||||||
switch (shdr[i].sh_type) {
|
switch (shdr[i].sh_type) {
|
||||||
case SHT_SYMTAB:
|
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");
|
fprintf(stderr, "LOAD segment not loaded at address 0\n");
|
||||||
errors++;
|
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)) {
|
if (first_segsz < ehdr->e_phoff + phnum * sizeof(*phdr)) {
|
||||||
fprintf(stderr, "LOAD segment does not cover PHDRs\n");
|
fprintf(stderr, "LOAD segment does not cover PHDRs\n");
|
||||||
errors++;
|
errors++;
|
||||||
|
@ -197,17 +221,24 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
|
||||||
output_reloc(outf, buf, &phdr[i].p_paddr);
|
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. */
|
/* Relocate the DYNAMIC entries. */
|
||||||
if (dynamic_addr) {
|
if (dynamic_addr) {
|
||||||
ElfN(Dyn) *dyn = buf + dynamic_ofs;
|
ElfN(Dyn) *target_dyn = buf + dynamic_ofs;
|
||||||
__typeof(dyn->d_tag) tag;
|
__typeof(((ElfN(Dyn) *)target_dyn)->d_tag) tag;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
ElfN(Dyn) dyn;
|
||||||
|
|
||||||
|
memcpy(&dyn, target_dyn, sizeof(dyn));
|
||||||
if (need_bswap) {
|
if (need_bswap) {
|
||||||
elfN(bswap_dyn)(dyn);
|
elfN(bswap_dyn)(&dyn);
|
||||||
}
|
}
|
||||||
tag = dyn->d_tag;
|
tag = dyn.d_tag;
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case DT_HASH:
|
case DT_HASH:
|
||||||
|
@ -218,7 +249,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
|
||||||
case DT_PLTGOT:
|
case DT_PLTGOT:
|
||||||
case DT_ADDRRNGLO ... DT_ADDRRNGHI:
|
case DT_ADDRRNGLO ... DT_ADDRRNGHI:
|
||||||
/* These entries store an address in the entry. */
|
/* 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;
|
break;
|
||||||
|
|
||||||
case DT_NULL:
|
case DT_NULL:
|
||||||
|
@ -235,7 +266,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_SYMENT:
|
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");
|
fprintf(stderr, "VDSO has incorrect dynamic symbol size\n");
|
||||||
errors++;
|
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
|
* ??? The RISC-V toolchain will emit these even when there
|
||||||
* are no relocations. Validate zeros.
|
* 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");
|
fprintf(stderr, "VDSO has dynamic relocations\n");
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
|
@ -287,7 +318,7 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
|
||||||
errors++;
|
errors++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dyn++;
|
target_dyn++;
|
||||||
} while (tag != DT_NULL);
|
} while (tag != DT_NULL);
|
||||||
if (errors) {
|
if (errors) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -296,11 +327,11 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
|
||||||
|
|
||||||
/* Relocate the dynamic symbol table. */
|
/* Relocate the dynamic symbol table. */
|
||||||
if (dynsym_idx) {
|
if (dynsym_idx) {
|
||||||
ElfN(Sym) *sym = buf + shdr[dynsym_idx].sh_offset;
|
ElfN(Sym) *target_sym = buf + shdr[dynsym_idx].sh_offset;
|
||||||
unsigned sym_n = shdr[dynsym_idx].sh_size / sizeof(*sym);
|
unsigned sym_n = shdr[dynsym_idx].sh_size / sizeof(*target_sym);
|
||||||
|
|
||||||
for (unsigned i = 0; i < sym_n; ++i) {
|
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) {
|
if (symtab_idx) {
|
||||||
elfN(search_symtab)(shdr, symtab_idx, buf, need_bswap);
|
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);
|
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.
|
* Identify which elf flavor we're processing.
|
||||||
* The first 16 bytes of the file are e_ident.
|
* 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.
|
* 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]) {
|
switch (buf[EI_CLASS]) {
|
||||||
case ELFCLASS32:
|
case ELFCLASS32:
|
||||||
elf32_process(outf, buf, need_bswap);
|
elf32_process(outf, buf, total_len, need_bswap);
|
||||||
break;
|
break;
|
||||||
case ELFCLASS64:
|
case ELFCLASS64:
|
||||||
elf64_process(outf, buf, need_bswap);
|
elf64_process(outf, buf, total_len, need_bswap);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: invalid elf EI_CLASS (%u)\n",
|
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. */
|
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, "static const VdsoImageInfo %s_image_info = {\n", prefix);
|
||||||
fprintf(outf, " .image = %s_image,\n", prefix);
|
fprintf(outf, " .image = %s_image,\n", prefix);
|
||||||
fprintf(outf, " .relocs = %s_relocs,\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;
|
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)
|
static void handle_arg_one_insn_per_tb(const char *arg)
|
||||||
{
|
{
|
||||||
opt_one_insn_per_tb = true;
|
opt_one_insn_per_tb = true;
|
||||||
|
@ -494,6 +501,9 @@ static const struct qemu_argument arg_table[] = {
|
||||||
"address", "set guest_base address to 'address'"},
|
"address", "set guest_base address to 'address'"},
|
||||||
{"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
|
{"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
|
||||||
"size", "reserve 'size' bytes for guest virtual address space"},
|
"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,
|
{"d", "QEMU_LOG", true, handle_arg_log,
|
||||||
"item[,...]", "enable logging of specified items "
|
"item[,...]", "enable logging of specified items "
|
||||||
"(use '-d help' for a list of 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);
|
target_set_brk(info->brk);
|
||||||
syscall_init();
|
syscall_init();
|
||||||
signal_init();
|
signal_init(rtsig_map);
|
||||||
|
|
||||||
/* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
|
/* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
|
||||||
generating the prologue until now so that the prologue can take
|
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);
|
target_sigset_t *set, CPUArchState *env);
|
||||||
|
|
||||||
void process_pending_signals(CPUArchState *cpu_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,
|
void queue_signal(CPUArchState *env, int sig, int si_type,
|
||||||
target_siginfo_t *info);
|
target_siginfo_t *info);
|
||||||
void host_to_target_siginfo(target_siginfo_t *tinfo, const 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/osdep.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
#include "gdbstub/user.h"
|
#include "gdbstub/user.h"
|
||||||
#include "exec/page-protection.h"
|
#include "exec/page-protection.h"
|
||||||
#include "hw/core/tcg-cpu-ops.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;
|
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
|
* Remap the target SIGABRT, so that we can distinguish host abort
|
||||||
* from guest abort. When the guest registers a signal handler or
|
* from guest abort. When the guest registers a signal handler or
|
||||||
* calls raise(SIGABRT), the host will raise SIG_RTn. If the guest
|
* 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.
|
* parent sees the correct mapping from wait status.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
hsig = SIGRTMIN;
|
|
||||||
host_to_target_signal_table[SIGABRT] = 0;
|
host_to_target_signal_table[SIGABRT] = 0;
|
||||||
host_to_target_signal_table[hsig++] = TARGET_SIGABRT;
|
for (hsig = SIGRTMIN; hsig <= SIGRTMAX; hsig++) {
|
||||||
|
if (!host_to_target_signal_table[hsig]) {
|
||||||
for (tsig = TARGET_SIGRTMIN;
|
host_to_target_signal_table[hsig] = TARGET_SIGABRT;
|
||||||
hsig <= SIGRTMAX && tsig <= TARGET_NSIG;
|
break;
|
||||||
hsig++, tsig++) {
|
}
|
||||||
host_to_target_signal_table[hsig] = tsig;
|
}
|
||||||
|
if (hsig > SIGRTMAX) {
|
||||||
|
fprintf(stderr, "No rt signals left for SIGABRT mapping\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invert the mapping that has already been assigned. */
|
/* Invert the mapping that has already been assigned. */
|
||||||
for (hsig = 1; hsig < _NSIG; hsig++) {
|
for (hsig = 1; hsig < _NSIG; hsig++) {
|
||||||
tsig = host_to_target_signal_table[hsig];
|
tsig = host_to_target_signal_table[hsig];
|
||||||
if (tsig) {
|
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;
|
target_to_host_signal_table[tsig] = hsig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -573,13 +641,13 @@ static void signal_table_init(void)
|
||||||
trace_signal_table_init(count);
|
trace_signal_table_init(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_init(void)
|
void signal_init(const char *rtsig_map)
|
||||||
{
|
{
|
||||||
TaskState *ts = get_task_state(thread_cpu);
|
TaskState *ts = get_task_state(thread_cpu);
|
||||||
struct sigaction act, oact;
|
struct sigaction act, oact;
|
||||||
|
|
||||||
/* initialize signal conversion tables */
|
/* initialize signal conversion tables */
|
||||||
signal_table_init();
|
signal_table_init(rtsig_map);
|
||||||
|
|
||||||
/* Set the signal mask from the host mask. */
|
/* Set the signal mask from the host mask. */
|
||||||
sigprocmask(0, 0, &ts->signal_mask);
|
sigprocmask(0, 0, &ts->signal_mask);
|
||||||
|
|
|
@ -3178,7 +3178,8 @@ foreach target : target_dirs
|
||||||
config_target += {
|
config_target += {
|
||||||
'CONFIG_USER_ONLY': 'y',
|
'CONFIG_USER_ONLY': 'y',
|
||||||
'CONFIG_QEMU_INTERP_PREFIX':
|
'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
|
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)')
|
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',
|
option('interp_prefix', type : 'string', value : '/usr/gnemul/qemu-%M',
|
||||||
description: 'where to find shared libraries etc., use %M for cpu name')
|
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 : '',
|
option('fuzzing_engine', type : 'string', value : '',
|
||||||
description: 'fuzzing engine library for OSS-Fuzz')
|
description: 'fuzzing engine library for OSS-Fuzz')
|
||||||
option('trace_file', type: 'string', value: 'trace',
|
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" ' "manufacturer" name for qemu-ga registry entries'
|
||||||
printf "%s\n" ' [QEMU]'
|
printf "%s\n" ' [QEMU]'
|
||||||
printf "%s\n" ' --qemu-ga-version=VALUE version number for qemu-ga installer'
|
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" ' --smbd=VALUE Path to smbd for slirp networking'
|
||||||
printf "%s\n" ' --sysconfdir=VALUE Sysconf data directory [etc]'
|
printf "%s\n" ' --sysconfdir=VALUE Sysconf data directory [etc]'
|
||||||
printf "%s\n" ' --tls-priority=VALUE Default TLS protocol/cipher priority string'
|
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 ;;
|
--disable-replication) printf "%s" -Dreplication=disabled ;;
|
||||||
--enable-rng-none) printf "%s" -Drng_none=true ;;
|
--enable-rng-none) printf "%s" -Drng_none=true ;;
|
||||||
--disable-rng-none) printf "%s" -Drng_none=false ;;
|
--disable-rng-none) printf "%s" -Drng_none=false ;;
|
||||||
|
--rtsig-map=*) quote_sh "-Drtsig_map=$2" ;;
|
||||||
--enable-rust) printf "%s" -Drust=enabled ;;
|
--enable-rust) printf "%s" -Drust=enabled ;;
|
||||||
--disable-rust) printf "%s" -Drust=disabled ;;
|
--disable-rust) printf "%s" -Drust=disabled ;;
|
||||||
--enable-rutabaga-gfx) printf "%s" -Drutabaga_gfx=enabled ;;
|
--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)),)
|
ifeq ($(filter %-softmmu, $(TARGET)),)
|
||||||
run-%: %
|
run-%: %
|
||||||
$(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<)
|
$(call run-test, $<, env QEMU=$(QEMU) $(QEMU) $(QEMU_OPTS) $<)
|
||||||
|
|
||||||
run-plugin-%:
|
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) \
|
-plugin $(PLUGIN_LIB)/$(call extract-plugin,$@)$(PLUGIN_ARGS) \
|
||||||
-d plugin -D $*.pout \
|
-d plugin -D $*.pout \
|
||||||
$(call strip-plugin,$<))
|
$(call strip-plugin,$<))
|
||||||
|
|
74
tests/tcg/multiarch/linux/linux-sigrtminmax.c
Normal file
74
tests/tcg/multiarch/linux/linux-sigrtminmax.c
Normal 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;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue