Refactor
This commit is contained in:
parent
84e37b572b
commit
e11c3d5a03
@ -19,6 +19,7 @@ add_executable(runtime
|
|||||||
)
|
)
|
||||||
|
|
||||||
# QEMU
|
# QEMU
|
||||||
|
include(CheckSymbolExists)
|
||||||
check_symbol_exists("__x86_64__" "" USE_QEMU)
|
check_symbol_exists("__x86_64__" "" USE_QEMU)
|
||||||
if(USE_QEMU)
|
if(USE_QEMU)
|
||||||
add_subdirectory(qemu)
|
add_subdirectory(qemu)
|
||||||
@ -39,9 +40,13 @@ target_link_libraries(runtime
|
|||||||
trampoline-headers
|
trampoline-headers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# External Library
|
||||||
|
set(TRAMPOLINE_LIBRARY_NAME "trampoline" CACHE STRING "Trampoline Library That The Runtime Uses")
|
||||||
|
target_compile_definitions(runtime PRIVATE "TRAMPOLINE_LIBRARY=\"lib${TRAMPOLINE_LIBRARY_NAME}.so\"")
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
if(DEFINED MCPI_BIN_DIR)
|
if(DEFINED MCPI_LIB_DIR)
|
||||||
install(TARGETS runtime DESTINATION "${MCPI_BIN_DIR}")
|
install(TARGETS runtime DESTINATION "${MCPI_LIB_DIR}")
|
||||||
# License
|
# License
|
||||||
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION "${MCPI_LEGAL_DIR}/${PROJECT_NAME}")
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION "${MCPI_LEGAL_DIR}/${PROJECT_NAME}")
|
||||||
endif()
|
endif()
|
@ -1,13 +1,13 @@
|
|||||||
# Reborn Runtime
|
# Reborn Runtime
|
||||||
This is a simple program allowing ARM32 code to easily call "native" code.
|
This is a simple program allowing ARM32 code to easily call "native" code.
|
||||||
|
|
||||||
By running an ARM32 program inside this runtime, it gains the ability to call `raw_trampoline`. This function copies its arguments and passes them to the `trampoline` function inside `libmedia-layer-trampoline.so`.
|
By running an ARM32 program inside this runtime, it gains the ability to call `raw_trampoline`. This function copies its arguments and passes them to the `trampoline` function inside `libtrampoline.so`.
|
||||||
|
|
||||||
The runtime also automatically uses QEMU on x86_64 systems.
|
The runtime also automatically uses QEMU on x86_64 systems.
|
||||||
|
|
||||||
## Terminology
|
## Terminology
|
||||||
- "Guest" code is the main ARM32 program.
|
- "Guest" code is the main ARM32 program. It is running inside the runtime.
|
||||||
- "Host" code is the native code located in `libmedia-layer-trampoline.so`.
|
- "Host" code is the native code located in `libtrampoline.so`. It is running "alongside" the runtime.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
There is a simple C example [here](./example). It sends a given string to the host, which returns the string's length multiplied by two.
|
There is a simple C example [here](./example). It sends a given string to the host, which returns the string's length multiplied by two.
|
||||||
@ -15,7 +15,7 @@ There is a simple C example [here](./example). It sends a given string to the ho
|
|||||||
## Early Returning
|
## Early Returning
|
||||||
`raw_trampoline` supports returning before the host code has finished executing. This can be enabled by passing `true` to `allow_early_return`. However, this is only supported in certain circumstances, can cause race-conditions, and prevents the guest code from receiving the host's return value.
|
`raw_trampoline` supports returning before the host code has finished executing. This can be enabled by passing `true` to `allow_early_return`. However, this is only supported in certain circumstances, can cause race-conditions, and prevents the guest code from receiving the host's return value.
|
||||||
|
|
||||||
## Syscall Versus Pipe Trampolines
|
## Syscall Vs. Pipe Trampolines
|
||||||
The runtime supports two methods of passing data between the guest and host.
|
The runtime supports two methods of passing data between the guest and host.
|
||||||
- System Call
|
- System Call
|
||||||
- Data is passed through a custom system-call added to QEMU.
|
- Data is passed through a custom system-call added to QEMU.
|
||||||
|
@ -13,30 +13,21 @@ out 'set -e'
|
|||||||
chmod +x "${RUN}"
|
chmod +x "${RUN}"
|
||||||
|
|
||||||
# Create Build Directory
|
# Create Build Directory
|
||||||
rm -rf build
|
|
||||||
dir() {
|
dir() {
|
||||||
mkdir "$1"
|
mkdir -p "$1"
|
||||||
cd "$1"
|
cd "$1"
|
||||||
}
|
}
|
||||||
dir build
|
dir build
|
||||||
|
|
||||||
# Build Runtime
|
|
||||||
dir runtime
|
|
||||||
build() {
|
|
||||||
cmake -GNinja "../../$1"
|
|
||||||
cmake --build .
|
|
||||||
}
|
|
||||||
build ../
|
|
||||||
out "export PATH=\"$(pwd):\${PATH}\""
|
|
||||||
cd ../
|
|
||||||
|
|
||||||
# Build Host Component
|
# Build Host Component
|
||||||
build_example_part() {
|
build_example_part() {
|
||||||
dir "$1"
|
dir "$1"
|
||||||
build "$1"
|
cmake -GNinja "../../$1"
|
||||||
|
cmake --build .
|
||||||
}
|
}
|
||||||
build_example_part host
|
build_example_part host
|
||||||
out "export LD_LIBRARY_PATH=\"$(pwd):\${LD_LIBRARY_PATH}\""
|
out "export LD_LIBRARY_PATH=\"$(pwd):\${LD_LIBRARY_PATH}\""
|
||||||
|
out "export PATH=\"$(pwd)/runtime:\${PATH}\""
|
||||||
cd ../
|
cd ../
|
||||||
|
|
||||||
# Build Guest Component
|
# Build Guest Component
|
||||||
|
@ -10,7 +10,7 @@ set(CMAKE_SYSTEM_PROCESSOR "arm")
|
|||||||
project(guest)
|
project(guest)
|
||||||
|
|
||||||
# Build Library
|
# Build Library
|
||||||
add_subdirectory(../../lib lib)
|
add_subdirectory(../../ runtime)
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_executable(example src/example.c)
|
add_executable(example src/example.c)
|
||||||
|
@ -1,19 +1,28 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <trampoline/types.h>
|
#include <trampoline/types.h>
|
||||||
|
|
||||||
|
// Call Trampoline With String
|
||||||
void run(uint32_t cmd, const char *str) {
|
void run(uint32_t cmd, const char *str) {
|
||||||
// Arguments Must Be Modifiable
|
unsigned char *args = (unsigned char *) str;
|
||||||
unsigned char *args = (unsigned char *) strdup(str);
|
// Send Command
|
||||||
// Sned Command
|
|
||||||
fprintf(stderr, "Guest Is Sending: %u: %s\n", cmd, str);
|
fprintf(stderr, "Guest Is Sending: %u: %s\n", cmd, str);
|
||||||
uint32_t ret = raw_trampoline(cmd, 0, strlen(str) + 1, args);
|
uint32_t ret;
|
||||||
|
raw_trampoline(cmd, &ret, strlen(str) + 1, args);
|
||||||
fprintf(stderr, "Guest Has Received: %u\n", ret);
|
fprintf(stderr, "Guest Has Received: %u\n", ret);
|
||||||
free(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main
|
||||||
|
#define INFO(str) fprintf(stderr, "==== %s ====\n", str)
|
||||||
int main() {
|
int main() {
|
||||||
|
// Normal Calls
|
||||||
|
INFO("Testing Normal Trampoline Calls");
|
||||||
run(0, "Hello World!");
|
run(0, "Hello World!");
|
||||||
run(1, "Bye World!");
|
run(1, "Bye World!");
|
||||||
|
// Calls without a return value *may* return control
|
||||||
|
// to guest code before the call has finished.
|
||||||
|
INFO("Testing Trampoline Call That May Return Early");
|
||||||
|
raw_trampoline(100, NULL, 0, NULL);
|
||||||
|
fprintf(stderr, "Control Returned To Guest\n");
|
||||||
}
|
}
|
@ -4,8 +4,8 @@ cmake_minimum_required(VERSION 3.17.0)
|
|||||||
project(host)
|
project(host)
|
||||||
|
|
||||||
# Build Library
|
# Build Library
|
||||||
add_subdirectory(../../lib lib)
|
add_subdirectory(../../ runtime)
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
add_library(media-layer-trampoline SHARED src/trampoline.c)
|
add_library("${TRAMPOLINE_LIBRARY_NAME}" SHARED src/trampoline.c)
|
||||||
target_link_libraries(media-layer-trampoline trampoline-headers)
|
target_link_libraries("${TRAMPOLINE_LIBRARY_NAME}" trampoline-headers)
|
@ -1,5 +1,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <trampoline/types.h>
|
#include <trampoline/types.h>
|
||||||
|
|
||||||
@ -8,7 +9,16 @@
|
|||||||
// args: Pointer To Command Arguments
|
// args: Pointer To Command Arguments
|
||||||
// Return Value: Returned To The Guest (Unless Early Return Is Enabled)
|
// Return Value: Returned To The Guest (Unless Early Return Is Enabled)
|
||||||
uint32_t trampoline(trampoline_writer_t writer, uint32_t id, const unsigned char *args) {
|
uint32_t trampoline(trampoline_writer_t writer, uint32_t id, const unsigned char *args) {
|
||||||
const char *str = (const char *) args;
|
if (id == 100 /* Defined In ../../guest/src/example.c */) {
|
||||||
fprintf(stderr, "Host Has Recieved: %u: %s\n", id, str);
|
// Early Return Allowed
|
||||||
return strlen(str) * 2;
|
fprintf(stderr, "Early Return Call Started\n");
|
||||||
|
sleep(1);
|
||||||
|
fprintf(stderr, "Early Return Call Done\n");
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
// Normal Call
|
||||||
|
const char *str = (const char *) args;
|
||||||
|
fprintf(stderr, "Host Has Received: %u: %s\n", id, str);
|
||||||
|
return strlen(str) * 2;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,3 @@
|
|||||||
cmake_minimum_required(VERSION 3.17.0)
|
|
||||||
|
|
||||||
# Start Project
|
|
||||||
project(trampoline)
|
project(trampoline)
|
||||||
|
|
||||||
# Headers
|
# Headers
|
||||||
@ -16,5 +13,9 @@ if(NOT TRAMPOLINE_IS_GUEST)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Library To Call Trampoline
|
# Library To Call Trampoline
|
||||||
add_library(trampoline OBJECT src/guest.cpp)
|
add_library(trampoline OBJECT
|
||||||
|
src/lib.cpp
|
||||||
|
src/syscall.cpp
|
||||||
|
src/pipe.cpp
|
||||||
|
)
|
||||||
target_link_libraries(trampoline trampoline-headers)
|
target_link_libraries(trampoline trampoline-headers)
|
@ -38,7 +38,7 @@ typedef trampoline_raw_t *trampoline_t;
|
|||||||
|
|
||||||
// Call Trampoline From Guest Code
|
// Call Trampoline From Guest Code
|
||||||
#ifndef MCPI_BUILD_RUNTIME
|
#ifndef MCPI_BUILD_RUNTIME
|
||||||
uint32_t raw_trampoline(uint32_t id, int allow_early_return, uint32_t length, unsigned char *args);
|
uint32_t raw_trampoline(uint32_t id, uint32_t *ret /* Can Be Null */, uint32_t length, const unsigned char *args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// C++
|
// C++
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include <string>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include <trampoline/types.h>
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
#define ERR(format, ...) \
|
|
||||||
({ \
|
|
||||||
fprintf(stderr, "TRAMPOLINE ERROR: " format "\n", ##__VA_ARGS__); \
|
|
||||||
exit(EXIT_FAILURE); \
|
|
||||||
})
|
|
||||||
|
|
||||||
// Syscall Method
|
|
||||||
static uint32_t trampoline_syscall(const uint32_t id, unsigned char *args) {
|
|
||||||
// Make Syscall
|
|
||||||
const long ret = syscall(TRAMPOLINE_SYSCALL, id, args); // This Modifies Arguments
|
|
||||||
if (ret == -1) {
|
|
||||||
// Error
|
|
||||||
ERR("System Call Error: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
// Return
|
|
||||||
return *(uint32_t *) args;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pipe Method
|
|
||||||
static int get_pipe(const char *env) {
|
|
||||||
const char *value = getenv(env);
|
|
||||||
if (value == nullptr) {
|
|
||||||
ERR("Missing Variable: %s", env);
|
|
||||||
}
|
|
||||||
const std::string str = value;
|
|
||||||
return std::stoi(str);
|
|
||||||
}
|
|
||||||
static uint32_t trampoline_pipe(const uint32_t id, const bool allow_early_return, const uint32_t length, const unsigned char *args) {
|
|
||||||
// Get Pipes
|
|
||||||
static int arguments_pipe = -1;
|
|
||||||
static int return_value_pipe = -1;
|
|
||||||
if (arguments_pipe == -1) {
|
|
||||||
arguments_pipe = get_pipe(_MCPI_TRAMPOLINE_ARGUMENTS_ENV);
|
|
||||||
return_value_pipe = get_pipe(_MCPI_TRAMPOLINE_RETURN_VALUE_ENV);
|
|
||||||
}
|
|
||||||
// Write Command
|
|
||||||
const trampoline_pipe_arguments cmd = {
|
|
||||||
.id = id,
|
|
||||||
.allow_early_return = allow_early_return,
|
|
||||||
.length = length
|
|
||||||
};
|
|
||||||
if (write(arguments_pipe, &cmd, sizeof(trampoline_pipe_arguments)) != sizeof(trampoline_pipe_arguments)) {
|
|
||||||
ERR("Unable To Write Command");
|
|
||||||
}
|
|
||||||
// Write Arguments
|
|
||||||
size_t position = 0;
|
|
||||||
while (position < length) {
|
|
||||||
const ssize_t ret = write(arguments_pipe, args + position, length - position);
|
|
||||||
if (ret == -1) {
|
|
||||||
ERR("Unable To Write Arguments");
|
|
||||||
} else {
|
|
||||||
position += ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allow_early_return) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// Return
|
|
||||||
uint32_t ret;
|
|
||||||
if (read(return_value_pipe, &ret, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
|
||||||
ERR("Unable To Read Return Value");
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main Function
|
|
||||||
uint32_t raw_trampoline(const uint32_t id, const int allow_early_return, const uint32_t length, unsigned char *args) {
|
|
||||||
if (length > MAX_TRAMPOLINE_ARGS_SIZE) {
|
|
||||||
ERR("Command Too Big");
|
|
||||||
}
|
|
||||||
// Configure Method
|
|
||||||
static bool use_syscall = getenv(MCPI_USE_PIPE_TRAMPOLINE_ENV) == nullptr;
|
|
||||||
// Use Correct Method
|
|
||||||
if (use_syscall) {
|
|
||||||
return trampoline_syscall(id, args);
|
|
||||||
} else {
|
|
||||||
return trampoline_pipe(id, allow_early_return, length, args);
|
|
||||||
}
|
|
||||||
}
|
|
22
lib/src/lib.cpp
Normal file
22
lib/src/lib.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
// Call
|
||||||
|
static Trampoline::Error trampoline(const uint32_t id, uint32_t *ret, const uint32_t length, const unsigned char *args) {
|
||||||
|
// Check Arguments Length
|
||||||
|
if (length > MAX_TRAMPOLINE_ARGS_SIZE) {
|
||||||
|
return Trampoline::Error::COMMAND_TOO_BIG;
|
||||||
|
}
|
||||||
|
// Configure Method
|
||||||
|
static bool use_syscall = SyscallTrampoline::should_use();
|
||||||
|
// Use Correct Method
|
||||||
|
if (use_syscall) {
|
||||||
|
static SyscallTrampoline syscall;
|
||||||
|
return syscall.call(id, ret, length, args);
|
||||||
|
} else {
|
||||||
|
static PipeTrampoline pipe;
|
||||||
|
return pipe.call(id, ret, length, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t raw_trampoline(const uint32_t id, uint32_t *ret, const uint32_t length, const unsigned char *args) {
|
||||||
|
return uint32_t(trampoline(id, ret, length, args));
|
||||||
|
}
|
41
lib/src/lib.h
Normal file
41
lib/src/lib.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <trampoline/types.h>
|
||||||
|
|
||||||
|
// Common
|
||||||
|
struct Trampoline {
|
||||||
|
virtual ~Trampoline() = default;
|
||||||
|
// Error Codes
|
||||||
|
enum class Error : uint32_t {
|
||||||
|
NONE = 0,
|
||||||
|
// Generic
|
||||||
|
COMMAND_TOO_BIG,
|
||||||
|
// System Call
|
||||||
|
SYSCALL,
|
||||||
|
// Pipe
|
||||||
|
MISSING_PIPE,
|
||||||
|
INVALID_PIPE,
|
||||||
|
PIPE_WRITE,
|
||||||
|
PIPE_READ
|
||||||
|
};
|
||||||
|
// Call
|
||||||
|
virtual Error call(uint32_t id, uint32_t *ret_ptr, uint32_t length, const unsigned char *args) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Syscall Method
|
||||||
|
struct SyscallTrampoline final : Trampoline {
|
||||||
|
static bool should_use();
|
||||||
|
Error call(uint32_t id, uint32_t *ret_ptr, uint32_t length, const unsigned char *args) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pipe Method
|
||||||
|
struct PipeTrampoline final : Trampoline {
|
||||||
|
PipeTrampoline();
|
||||||
|
Error call(uint32_t id, uint32_t *ret_ptr, uint32_t length, const unsigned char *args) override;
|
||||||
|
private:
|
||||||
|
Error status;
|
||||||
|
int arguments_pipe;
|
||||||
|
int return_value_pipe;
|
||||||
|
};
|
71
lib/src/pipe.cpp
Normal file
71
lib/src/pipe.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
// Load Pipes
|
||||||
|
static std::variant<int, Trampoline::Error> get_pipe(const char *env) {
|
||||||
|
const char *value = getenv(env);
|
||||||
|
if (value == nullptr) {
|
||||||
|
return Trampoline::Error::MISSING_PIPE;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const int val = std::stoi(value);
|
||||||
|
if (val >= 0) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
return Trampoline::Error::INVALID_PIPE;
|
||||||
|
}
|
||||||
|
#define set(var, env) \
|
||||||
|
val = get_pipe(env); \
|
||||||
|
if (std::holds_alternative<Error>(val)) { \
|
||||||
|
status = std::get<Error>(val); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
var = std::get<int>(val)
|
||||||
|
PipeTrampoline::PipeTrampoline() {
|
||||||
|
std::variant<int, Error> val;
|
||||||
|
set(arguments_pipe, _MCPI_TRAMPOLINE_ARGUMENTS_ENV);
|
||||||
|
set(return_value_pipe, _MCPI_TRAMPOLINE_RETURN_VALUE_ENV);
|
||||||
|
// Success
|
||||||
|
status = Error::NONE;
|
||||||
|
}
|
||||||
|
#undef set
|
||||||
|
|
||||||
|
// Call
|
||||||
|
Trampoline::Error PipeTrampoline::call(const uint32_t id, uint32_t *ret_ptr, const uint32_t length, const unsigned char *args) {
|
||||||
|
// Check
|
||||||
|
if (status != Error::NONE) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
// Write Command
|
||||||
|
const trampoline_pipe_arguments cmd = {
|
||||||
|
.id = id,
|
||||||
|
.allow_early_return = ret_ptr == nullptr,
|
||||||
|
.length = length
|
||||||
|
};
|
||||||
|
if (write(arguments_pipe, &cmd, sizeof(trampoline_pipe_arguments)) != sizeof(trampoline_pipe_arguments)) {
|
||||||
|
return Error::PIPE_WRITE;
|
||||||
|
}
|
||||||
|
// Write Arguments
|
||||||
|
size_t position = 0;
|
||||||
|
while (position < length) {
|
||||||
|
const ssize_t ret = write(arguments_pipe, args + position, length - position);
|
||||||
|
if (ret == -1) {
|
||||||
|
return Error::PIPE_WRITE;
|
||||||
|
} else {
|
||||||
|
position += ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return Value
|
||||||
|
if (ret_ptr != nullptr && read(return_value_pipe, ret_ptr, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||||
|
return Error::PIPE_READ;
|
||||||
|
}
|
||||||
|
// Success
|
||||||
|
return Error::NONE;
|
||||||
|
}
|
14
lib/src/syscall.cpp
Normal file
14
lib/src/syscall.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
|
// Check
|
||||||
|
bool SyscallTrampoline::should_use() {
|
||||||
|
return getenv(MCPI_USE_PIPE_TRAMPOLINE_ENV) == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call
|
||||||
|
Trampoline::Error SyscallTrampoline::call(const uint32_t id, uint32_t *ret_ptr, uint32_t length, const unsigned char *args) {
|
||||||
|
return syscall(TRAMPOLINE_SYSCALL, id, ret_ptr, args) != 0 ? Error::SYSCALL : Error::NONE;
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
int, __to_dfd, const char *, __to_pathname, unsigned int, flag)
|
int, __to_dfd, const char *, __to_pathname, unsigned int, flag)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
+extern int trampoline_handle_syscall(int32_t num, uint32_t arg1, uint32_t arg2);
|
+extern int trampoline_handle_syscall(int32_t num, uint32_t arg1, uint32_t arg2, uint32_t arg3);
|
||||||
+
|
+
|
||||||
/* This is an internal helper for do_syscall so that it is easier
|
/* This is an internal helper for do_syscall so that it is easier
|
||||||
* to have a single return point, so that actions, such as logging
|
* to have a single return point, so that actions, such as logging
|
||||||
@ -22,7 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
+ if (trampoline_handle_syscall(num, arg1, arg2)) {
|
+ if (trampoline_handle_syscall(num, arg1, arg2, arg3)) {
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
// Access QEMU's Memory
|
// Access QEMU's Memory
|
||||||
void *QEMU::guest_to_host(const uint32_t guest_addr) {
|
void *QEMU::guest_to_host(const uint32_t guest_addr) {
|
||||||
|
if (guest_addr == 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return (void *) (uintptr_t) (guest_addr + QEMU_GUEST_BASE);;
|
return (void *) (uintptr_t) (guest_addr + QEMU_GUEST_BASE);;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// QEMU API
|
// QEMU API
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// Called By Patched QEMU
|
// Called By Patched QEMU
|
||||||
int trampoline_handle_syscall(int32_t num, uint32_t arg1, uint32_t arg2);
|
int trampoline_handle_syscall(int32_t num, uint32_t arg1, uint32_t arg2, uint32_t arg3);
|
||||||
// Main
|
// Main
|
||||||
int qemu_main(int argc, char **argv, char **envp);
|
int qemu_main(int argc, char **argv, char **envp);
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,23 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
// Handle Syscall
|
// Handle Syscall
|
||||||
int trampoline_handle_syscall(const int32_t num, const uint32_t arg1, uint32_t arg2) {
|
int trampoline_handle_syscall(const int32_t num, const uint32_t arg1, const uint32_t arg2, const uint32_t arg3) {
|
||||||
// Check Syscall
|
// Check Syscall
|
||||||
if (num != TRAMPOLINE_SYSCALL) {
|
if (num != TRAMPOLINE_SYSCALL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Run
|
// Run
|
||||||
SyscallImplementation::instance->handle_syscall(arg1, arg2);
|
SyscallImplementation::instance->handle_syscall(arg1, arg2, arg3);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
void SyscallImplementation::handle_syscall(const uint32_t arg1, const uint32_t arg2) const {
|
void SyscallImplementation::handle_syscall(const uint32_t arg1, const uint32_t arg2, const uint32_t arg3) const {
|
||||||
|
// Get Arguments
|
||||||
const uint32_t id = arg1;
|
const uint32_t id = arg1;
|
||||||
const unsigned char *args = (const unsigned char *) QEMU::guest_to_host(arg2);
|
uint32_t *ret_ptr = (uint32_t *) QEMU::guest_to_host(arg2);
|
||||||
|
const unsigned char *args = (const unsigned char *) QEMU::guest_to_host(arg3);
|
||||||
|
// Call
|
||||||
const uint32_t ret = trampoline(id, args);
|
const uint32_t ret = trampoline(id, args);
|
||||||
*(uint32_t *) args = ret;
|
if (ret_ptr != nullptr) {
|
||||||
|
*ret_ptr = ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
struct SyscallImplementation final : Implementation {
|
struct SyscallImplementation final : Implementation {
|
||||||
int main(int argc, char *argv[]) override;
|
int main(int argc, char *argv[]) override;
|
||||||
void memory_writer(uint32_t guest_addr, const void *data, uint32_t size) const override;
|
void memory_writer(uint32_t guest_addr, const void *data, uint32_t size) const override;
|
||||||
void handle_syscall(uint32_t arg1, uint32_t arg2) const;
|
void handle_syscall(uint32_t arg1, uint32_t arg2, uint32_t arg3) const;
|
||||||
static SyscallImplementation *instance;
|
static SyscallImplementation *instance;
|
||||||
};
|
};
|
@ -20,11 +20,11 @@ uint32_t Trampoline::operator()(const uint32_t id, const unsigned char *args) co
|
|||||||
void Trampoline::init(const Implementation *impl) {
|
void Trampoline::init(const Implementation *impl) {
|
||||||
stored_impl = impl;
|
stored_impl = impl;
|
||||||
// Open Library
|
// Open Library
|
||||||
void *handle = dlopen("libmedia-layer-trampoline.so", RTLD_NOW);
|
void *handle = dlopen(TRAMPOLINE_LIBRARY, RTLD_NOW);
|
||||||
if (handle != nullptr) {
|
if (handle != nullptr) {
|
||||||
func = (trampoline_t) dlsym(handle, "trampoline");
|
func = (trampoline_t) dlsym(handle, "trampoline");
|
||||||
}
|
}
|
||||||
if (func == nullptr) {
|
if (func == nullptr) {
|
||||||
ERR("Unable To Load Media Layer Trampoline: %s", dlerror());
|
ERR("Unable To Trampoline: %s", dlerror());
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user