blob: deafa2a234107d0ddfba304ebd8b5df91180e552 [file] [log] [blame]
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DEMOS_MELTDOWN_LOCAL_CONTENT_H
#define DEMOS_MELTDOWN_LOCAL_CONTENT_H
#include "compiler_specifics.h"
#if SAFESIDE_LINUX || SAFESIDE_MAC
#include <signal.h>
#endif
#if SAFESIDE_ARM64
// Local handler necessary for avoiding local/global linking mismatches on ARM.
// When we use extern char[] declaration for a label defined in assembly, the
// compiler yields this sequence that fails loading the actual address of the
// label:
// adrp x0, :got:label
// ldr x0, [x0, #:got_lo12:label]
// On the other hand when we use this local handler, the compiler yield this
// sequence of instructions:
// adrp x0, label
// add x0, x0, :lo12:label
// and that works correctly because it if an effective equivalent of
// adr x0, label.
static void LocalHandler() {
asm volatile("b afterspeculation");
}
#endif
static void SignalHandler(
int /* signum */, siginfo_t * /* siginfo */, void *context) {
// On IA32, X64 and PPC moves the instruction pointer to the
// "afterspeculation" label. On ARM64 moves the instruction pointer to the
// "LocalHandler" label.
ucontext_t *ucontext = static_cast<ucontext_t *>(context);
#if SAFESIDE_LINUX && SAFESIDE_IA32
ucontext->uc_mcontext.gregs[REG_EIP] =
reinterpret_cast<greg_t>(afterspeculation);
#elif SAFESIDE_LINUX && SAFESIDE_X64
ucontext->uc_mcontext.gregs[REG_RIP] =
reinterpret_cast<greg_t>(afterspeculation);
#elif SAFESIDE_LINUX && SAFESIDE_ARM64
ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
#elif SAFESIDE_LINUX && SAFESIDE_PPC
ucontext->uc_mcontext.regs->nip =
reinterpret_cast<uintptr_t>(afterspeculation);
#elif SAFESIDE_MAC && SAFESIDE_IA32
ucontext->uc_mcontext->__ss.__eip =
reinterpret_cast<uintptr_t>(afterspeculation);
#elif SAFESIDE_MAC && SAFESIDE_X64
ucontext->uc_mcontext->__ss.__rip =
reinterpret_cast<uintptr_t>(afterspeculation);
#else
# error Unsupported OS/CPU combination.
#endif
}
// Sets up signal handling that moves the instruction pointer to the
// afterspeculation (or LocalHandler in case of ARM) label. See the commentary
// to LocalHandler function why we must treat ARM differently.
static void OnSignalMoveRipToAfterspeculation(int signal) {
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_sigaction = SignalHandler;
act.sa_flags = SA_SIGINFO;
sigaction(signal, &act, nullptr);
}
#endif // DEMOS_MELTDOWN_LOCAL_CONTENT_H