/* * Copyright (C) 2024 The Android Open Source Project * * 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 * * http://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. */ #include "translator.h" #include "berberis/base/checks.h" #include "berberis/guest_os_primitives/guest_map_shadow.h" #include "berberis/guest_state/guest_addr.h" #include "berberis/guest_state/guest_state_opaque.h" #include "berberis/interpreter/riscv64/interpreter.h" #include "berberis/runtime_primitives/host_code.h" #include "berberis/runtime_primitives/runtime_library.h" #include "berberis/runtime_primitives/translation_cache.h" namespace berberis { void InitTranslatorArch() {} void TranslateRegion(GuestAddr pc) { using Kind = GuestCodeEntry::Kind; TranslationCache* cache = TranslationCache::GetInstance(); GuestCodeEntry* entry = cache->AddAndLockForTranslation(pc, 0); if (!entry) { return; } GuestMapShadow* guest_map_shadow = GuestMapShadow::GetInstance(); auto [is_executable, insn_size] = IsPcExecutable(pc, guest_map_shadow); if (!is_executable) { cache->SetTranslatedAndUnlock(pc, entry, insn_size, Kind::kSpecialHandler, {kEntryNoExec, 0}); return; } cache->SetTranslatedAndUnlock(pc, entry, insn_size, Kind::kInterpreted, {kEntryInterpret, 0}); } // ATTENTION: This symbol gets called directly, without PLT. To keep text // sharable we should prevent preemption of this symbol, so do not export it! // TODO(b/232598137): may be set default visibility to protected instead? extern "C" __attribute__((used, __visibility__("hidden"))) void berberis_HandleNotTranslated( ThreadState* state) { TranslateRegion(state->cpu.insn_addr); } extern "C" __attribute__((used, __visibility__("hidden"))) void berberis_HandleInterpret( ThreadState* state) { InterpretInsn(state); } extern "C" __attribute__((used, __visibility__("hidden"))) const void* berberis_GetDispatchAddress( ThreadState* state) { CHECK(state); if (ArePendingSignalsPresent(*state)) { return AsHostCode(kEntryExitGeneratedCode); } return AsHostCode(TranslationCache::GetInstance()->GetHostCodePtr(state->cpu.insn_addr)->load()); } } // namespace berberis