-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of ARMv8 support #35
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,16 @@ | ||
cmake_minimum_required(VERSION 3.16) | ||
project(vmicore) | ||
|
||
set(X86_64 OFF) | ||
set(ARM64 OFF) | ||
|
||
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") | ||
set(X86_64 ON) | ||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64") | ||
set(ARM64 ON) | ||
else () | ||
message(FATAL_ERROR "Unknown architecture ${CMAKE_SYSTEM_PROCESSOR}") | ||
endif () | ||
|
||
# Options | ||
|
||
|
@@ -15,7 +25,11 @@ set(CMAKE_CXX_STANDARD 20) | |
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ||
|
||
set(core_compile_flags -m64 -Wall) | ||
if (${X86_64}) | ||
set(core_compile_flags -m64 -Wall) | ||
elseif (${ARM64}) | ||
set(core_compile_flags -march=armv8-a -Wall) | ||
endif () | ||
set(extra_compile_flags -Wunused -Wunreachable-code -Wextra -Wpedantic -Wno-dollar-in-identifier-extension) | ||
|
||
# Toolchain checks | ||
|
@@ -64,26 +78,40 @@ FetchContent_MakeAvailable(googletest) | |
|
||
# Setup libvmi | ||
|
||
FetchContent_Declare( | ||
libvmi | ||
GIT_REPOSITORY https://github.com/GDATASoftwareAG/libvmi | ||
GIT_TAG test | ||
) | ||
set(libvmi_ENABLE_STATIC OFF) | ||
set(libvmi_BUILD_EXAMPLES OFF) | ||
set(ENABLE_STATIC OFF CACHE INTERNAL "") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those are configurable options and it would therefore be confusing if they were not displayed by |
||
set(BUILD_EXAMPLES OFF CACHE INTERNAL "") | ||
set(ENABLE_VMIFS OFF CACHE INTERNAL "") | ||
set(ENABLE_FILE OFF CACHE INTERNAL "") | ||
set(ENABLE_BAREFLANK OFF CACHE INTERNAL "") | ||
set(ENABLE_PROFILES OFF CACHE INTERNAL "") | ||
set(ENABLE_TESTING OFF CACHE INTERNAL "") | ||
|
||
if (${X86_64}) | ||
FetchContent_Declare( | ||
libvmi | ||
GIT_REPOSITORY https://github.com/GDATASoftwareAG/libvmi | ||
GIT_TAG test | ||
) | ||
elseif (${ARM64}) | ||
FetchContent_Declare( | ||
libvmi | ||
GIT_REPOSITORY https://gitlab.sec.uni-passau.de/sis/vmi-on-arm/libvmi.git | ||
GIT_TAG master | ||
) | ||
endif () | ||
FetchContent_MakeAvailable(libvmi) | ||
|
||
include_directories(BEFORE SYSTEM ${libvmi_SOURCE_DIR}) | ||
|
||
# Setup yaml-cpp | ||
|
||
set(YAML_BUILD_SHARED_LIBS OFF CACHE INTERNAL "") | ||
set(YAML_CPP_BUILD_TOOLS OFF CACHE INTERNAL "") | ||
FetchContent_Declare( | ||
yaml-cpp | ||
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git | ||
GIT_TAG yaml-cpp-0.7.0 | ||
) | ||
set(yaml-cpp_YAML_BUILD_SHARED_LIBS OFF) | ||
set(yaml-cpp_YAML_CPP_BUILD_TOOLS OFF) | ||
FetchContent_MakeAvailable(yaml-cpp) | ||
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE TRUE) | ||
|
||
|
@@ -164,6 +192,9 @@ set(test_files | |
test/vmi/LibvmiInterface_UnitTest.cpp | ||
test/vmi/SingleStepSupervisor_UnitTest.cpp) | ||
|
||
configure_file(src/config.h.in ${PROJECT_BINARY_DIR}/config.h) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already add some definitions via |
||
include_directories(${PROJECT_BINARY_DIR}) | ||
|
||
# Link libraries | ||
|
||
set(libraries rust_grpc_server vmicore_public_headers vmi_shared dl yaml-cpp GSL fmt-header-only) | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -151,6 +151,9 @@ uint VmiHub::run(const std::unordered_map<std::string, std::vector<std::string>> | |||||
} | ||||||
case VMI_OS_WINDOWS: | ||||||
{ | ||||||
#if defined(ARM64) | ||||||
throw new std::runtime_error("No support for Windows on ARM yet."); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
#endif | ||||||
auto kernelObjectExtractor = std::make_shared<Windows::KernelAccess>(vmiInterface); | ||||||
activeProcessesSupervisor = std::make_shared<Windows::ActiveProcessesSupervisor>( | ||||||
vmiInterface, kernelObjectExtractor, loggingLib, eventStream); | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
#cmakedefine ARM64 | ||
#cmakedefine X86_64 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,7 +69,9 @@ void InterruptEvent::initialize() | |
void InterruptEvent::teardown() | ||
{ | ||
disableEvent(); | ||
interruptGuard->teardown(); | ||
|
||
if (interruptGuard) | ||
interruptGuard->teardown(); | ||
} | ||
|
||
InterruptEvent::~InterruptEvent() | ||
|
@@ -89,33 +91,32 @@ void InterruptEvent::setupVmiInterruptEvent() | |
|
||
void InterruptEvent::enableEvent() | ||
{ | ||
#if defined(X86_64) | ||
vmiInterface->write8PA(targetPA, INT3_BREAKPOINT); | ||
#elif defined(ARM64) | ||
vmiInterface->write32PA(targetPA, BRK64_BREAKPOINT); | ||
#endif | ||
logger->debug("Enabled interrupt event", {logfield::create("targetPA", targetPAString)}); | ||
} | ||
|
||
void InterruptEvent::disableEvent() | ||
{ | ||
#if defined(X86_64) | ||
vmiInterface->write8PA(targetPA, originalValue); | ||
#elif defined(ARM64) | ||
vmiInterface->write32PA(targetPA, originalValue); | ||
#endif | ||
logger->debug("Disabled interrupt event", {logfield::create("targetPA", targetPAString)}); | ||
} | ||
|
||
uint64_t InterruptEvent::getRcx() | ||
{ | ||
return event.x86_regs->rcx; | ||
} | ||
|
||
uint64_t InterruptEvent::getRdi() | ||
{ | ||
return event.x86_regs->rdi; | ||
} | ||
|
||
uint64_t InterruptEvent::getR8() | ||
registers_t* InterruptEvent::getRegisters() | ||
{ | ||
return event.x86_regs->r8; | ||
return (registers_t*)event.x86_regs; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the |
||
} | ||
|
||
void InterruptEvent::storeOriginalValue() | ||
{ | ||
#if defined(X86_64) | ||
originalValue = vmiInterface->read8PA(targetPA); | ||
logger->debug("Save original value", | ||
{logfield::create("targetPA", targetPAString), | ||
|
@@ -125,16 +126,34 @@ void InterruptEvent::storeOriginalValue() | |
throw VmiException(fmt::format( | ||
"{}: InterruptEvent originalValue @ {} is already an INT3 breakpoint.", __func__, targetPAString)); | ||
} | ||
#elif defined(ARM64) | ||
originalValue = vmiInterface->read32PA(targetPA); | ||
logger->debug("Save original value", | ||
{logfield::create("targetPA", targetPAString), | ||
logfield::create("originalValue", fmt::format("{:#x}", originalValue))}); | ||
if (originalValue == BRK64_BREAKPOINT) | ||
{ | ||
throw VmiException(fmt::format( | ||
"{}: InterruptEvent originalValue @ {} is already an BRK64 breakpoint.", __func__, targetPAString)); | ||
} | ||
#endif | ||
} | ||
|
||
event_response_t InterruptEvent::_defaultInterruptCallback(__attribute__((unused)) vmi_instance_t vmi, | ||
vmi_event_t* event) | ||
event_response_t InterruptEvent::_defaultInterruptCallback(vmi_instance_t vmi, vmi_event_t* event) | ||
{ | ||
auto eventResponse = VMI_EVENT_RESPONSE_NONE; | ||
try | ||
{ | ||
#if defined(X86_64) | ||
(void)(vmi); | ||
auto eventPA = | ||
(event->interrupt_event.gfn << PagingDefinitions::numberOfPageIndexBits) + event->interrupt_event.offset; | ||
#elif defined(ARM64) | ||
addr_t eventPA; | ||
if (VMI_SUCCESS != | ||
vmi_pagetable_lookup(vmi, event->arm_regs->ttbr1 & VMI_BIT_MASK(12, 47), event->arm_regs->pc, &eventPA)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer making the bitmask a named constant so it becomes clear what it is supposed to accomplish |
||
throw std::runtime_error("Failed address translation of breakpoint hit."); | ||
#endif | ||
auto interruptEventIterator = interruptsByPA.find(eventPA); | ||
if (interruptEventIterator != interruptsByPA.end()) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer the scoped notation instead of internal cache vars.