/* * The following handle_signal_* helpers are used by main default_handler * and are meant to return true when signal is handled successfully: * when false is returned instead, it means that the signal was somehow * unexpected in that context and it was NOT handled; default_handler will * take care of such unexpected situations.
*/
staticbool handle_signal_ok(struct tdescr *td,
siginfo_t *si, void *uc)
{ /* * it's a bug in the test code when this assert fail: * if sig_trig was defined, it must have been used before getting here.
*/
assert(!td->sig_trig || td->triggered);
fprintf(stderr, "SIG_OK -- SP:0x%llX si_addr@:%p si_code:%d token@:%p offset:%ld\n",
((ucontext_t *)uc)->uc_mcontext.sp,
si->si_addr, si->si_code, td->token, td->token - si->si_addr); /* * fake_sigreturn tests, which have sanity_enabled=1, set, at the very * last time, the token field to the SP address used to place the fake * sigframe: so token==0 means we never made it to the end, * segfaulting well-before, and the test is possibly broken.
*/ if (!td->sanity_disabled && !td->token) {
fprintf(stdout, "current->token ZEROED...test is probably broken!\n");
abort();
} if (td->sig_ok_code) { if (si->si_code != td->sig_ok_code) {
fprintf(stdout, "si_code is %d not %d\n",
si->si_code, td->sig_ok_code);
abort();
}
} else { /* * Trying to narrow down the SEGV to the ones * generated by Kernel itself via * arm64_notify_segfault(). This is a best-effort * check anyway, and the si_code check may need to * change if this aspect of the kernel ABI changes.
*/ if (td->sig_ok == SIGSEGV && si->si_code != SEGV_ACCERR) {
fprintf(stdout, "si_code != SEGV_ACCERR...test is probably broken!\n");
abort();
}
}
td->pass = 1; /* * Some tests can lead to SEGV loops: in such a case we want to * terminate immediately exiting straight away; some others are not * supposed to outlive the signal handler code, due to the content of * the fake sigframe which caused the signal itself.
*/
default_result(current, 1);
/* Mangling PC to avoid loops on original BRK instr */
uc->uc_mcontext.pc += 4;
/* * Check for an preserve any extra data too with fixups.
*/
head = (struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
head = get_header(head, EXTRA_MAGIC, td->live_sz, &offset); if (head) {
extra = (struct extra_context *)head;
/* * The extra buffer must be immediately after the * extra_context and a 16 byte terminator. Include it * in the copy, this was previously validated in * ASSERT_GOOD_CONTEXT().
*/
to_copy = __builtin_offsetof(ucontext_t,
uc_mcontext.__reserved);
to_copy += offset + sizeof(struct extra_context) + 16;
to_copy += extra->size;
copied_extra = (struct extra_context *)&(td->live_uc->uc_mcontext.__reserved[offset]);
} else {
copied_extra = NULL;
to_copy = sizeof(ucontext_t);
}
if (to_copy > td->live_sz) {
fprintf(stderr, "Not enough space to grab context, %lu/%lu bytes\n",
td->live_sz, to_copy); returnfalse;
}
memcpy(td->live_uc, uc, to_copy);
/* * If there was any EXTRA_CONTEXT fix up the size to be the * struct extra_context and the following terminator record, * this means that the rest of the code does not need to have * special handling for the record and we don't need to fix up * datap for the new location.
*/ if (copied_extra)
copied_extra->head.size = sizeof(*copied_extra) + 16;
td->live_uc_valid = 1;
fprintf(stderr, "%lu byte GOOD CONTEXT grabbed from sig_copyctx handler\n",
to_copy);
sa.sa_sigaction = default_handler;
sa.sa_flags = SA_SIGINFO | SA_RESTART;
sa.sa_flags |= td->sa_flags;
sigemptyset(&sa.sa_mask); /* uncatchable signals naturally skipped ... */ for (int sig = 1; sig < 32; sig++)
sigaction(sig, &sa, NULL); /* * RT Signals default disposition is Term but they cannot be * generated by the Kernel in response to our tests; so just catch * them all and report them as UNEXPECTED signals.
*/ for (int sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
sigaction(sig, &sa, NULL);
/* just in case...unblock explicitly all we need */ if (td->sig_trig)
unblock_signal(td->sig_trig); if (td->sig_ok)
unblock_signal(td->sig_ok); if (td->sig_unsupp)
unblock_signal(td->sig_unsupp);
if (td->timeout) {
unblock_signal(SIGALRM);
alarm(td->timeout);
}
fprintf(stderr, "Registered handlers for all signals.\n");
int test_init(struct tdescr *td)
{ if (td->sig_trig == sig_copyctx) {
fprintf(stdout, "Signal %d is RESERVED, cannot be used as a trigger. Aborting\n",
sig_copyctx); return 0;
} /* just in case */
unblock_signal(sig_copyctx);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.