mirror of
https://github.com/pound-emu/ballistic.git
synced 2026-01-31 01:15:21 +01:00
memory: add flat translation interface
Defines the API for memory translation. Signed-off-by: Ronald Caesar <github43132@proton.me>
This commit is contained in:
@@ -13,7 +13,8 @@ typedef enum
|
||||
BAL_SUCCESS = 0,
|
||||
BAL_ERROR_INVALID_ARGUMENT = -1,
|
||||
BAL_ERROR_ALLOCATION_FAILED = -2,
|
||||
BAL_ERROR_ENGINE_STATE_INVALID = -3,
|
||||
BAL_ERROR_MEMORY_ALIGNMENT = -3,
|
||||
BAL_ERROR_ENGINE_STATE_INVALID = -4,
|
||||
|
||||
// IR Errors.
|
||||
//
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#define BALLISTIC_MEMORY_H
|
||||
|
||||
#include "bal_attributes.h"
|
||||
#include "bal_types.h"
|
||||
#include "bal_errors.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -38,6 +40,30 @@ typedef void (*bal_free_function_t)(void *allocator,
|
||||
void *pointer,
|
||||
size_t size);
|
||||
|
||||
/*!
|
||||
* @brief Translate a Guest Virtual Address to a Host Virtual Address.
|
||||
*
|
||||
* @details
|
||||
* Ballistic calls this when it needs to fetch instructions. The implementer
|
||||
* must return a pointer to the host memory corresponding to the requested
|
||||
* guest address.
|
||||
*
|
||||
* @param[in] context The oapque pointer provided in @ref
|
||||
* bal_memory_interface_t.
|
||||
* @param[in] guest_address The guest address to translate.
|
||||
* @param[out] max_readable_size The implementer MUST write the number of
|
||||
* contiguous bytes valid to read from the
|
||||
* returned pointer. This prevents Ballistic from
|
||||
* reading off the end of a mapped page or buffer.
|
||||
*
|
||||
* @return A pointer to the host memory containing the data at @p guest_address.
|
||||
* @return NULL if the address is unmapped or invalid.
|
||||
*/
|
||||
typedef const uint8_t *(*bal_translate_function_t)(
|
||||
void *context,
|
||||
bal_guest_address_t guest_address,
|
||||
size_t *max_readable_size);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*!
|
||||
@@ -58,15 +84,54 @@ typedef struct
|
||||
|
||||
} bal_allocator_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *context;
|
||||
bal_translate_function_t translate;
|
||||
} bal_memory_interface_t;
|
||||
|
||||
/*!
|
||||
* @brief Populates an allocator struct with the default implementation.
|
||||
*
|
||||
* @param[out] allocator The strict to populate. Must not be NULL.
|
||||
* @param[out] allocator The struct to populate. Must not be NULL.
|
||||
*
|
||||
* @warn Only supports Windows and POSIX systems.
|
||||
*/
|
||||
BAL_COLD void get_default_allocator(bal_allocator_t *out_allocator);
|
||||
BAL_COLD void bal_get_default_allocator(bal_allocator_t *out_allocator);
|
||||
|
||||
/*!
|
||||
* @brief Initializes a translation interface that uses a flat, contiguous
|
||||
* memory buffer.
|
||||
*
|
||||
* @params[in] allocator The allocator used to allocate the internal interface
|
||||
* structure.
|
||||
* @params[out] interface The interface struct to populate.
|
||||
* @params[in] buffer Pointer to the pre-allocated host memory containing
|
||||
* the guest code.
|
||||
* @params[in] size The size of the buffer in bytes.
|
||||
*
|
||||
* @return BAL_SUCCESS on success.
|
||||
* @return BAL_ERROR_INVALID_ARGUMENT if arguments are NULL.
|
||||
* @return BAL_ERROR_MEMORY_ALIGNMENT if buffer is not align to 4 bytes.
|
||||
*
|
||||
* @warning The caller retains ownership of buffer. It must remain valid for
|
||||
* the lifetime of the interface.
|
||||
*/
|
||||
BAL_COLD bal_error_t
|
||||
bal_memory_init_flat(bal_allocator_t *BAL_RESTRICT allocator,
|
||||
bal_memory_interface_t *BAL_RESTRICT interface,
|
||||
void *BAL_RESTRICT buffer,
|
||||
size_t size);
|
||||
|
||||
/*!
|
||||
* @brief Frees the interface's internal state.
|
||||
*
|
||||
* @details
|
||||
* This does not free the buffer passed during initialization, as Ballistic
|
||||
* does not own it.
|
||||
*/
|
||||
BAL_COLD void bal_memory_destroy_flat(bal_allocator_t *allocator,
|
||||
bal_memory_interface_t *interface);
|
||||
#endif /* BALLISTIC_MEMORY_H */
|
||||
|
||||
/*** end of file ***/
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef uint64_t bal_instruction_t;
|
||||
typedef uint64_t bal_guest_address_t;
|
||||
typedef uint16_t bal_instruction_count_t;
|
||||
typedef uint16_t bal_ssa_id_t;
|
||||
typedef uint8_t bal_bit_width_t;
|
||||
|
||||
103
src/bal_memory.c
103
src/bal_memory.c
@@ -1,22 +1,78 @@
|
||||
#include "bal_memory.h"
|
||||
#include "bal_platform.h"
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *default_allocate(void *, size_t, size_t);
|
||||
void default_free(void *, void *, size_t);
|
||||
static void *default_allocate(void *, size_t, size_t);
|
||||
static void default_free(void *, void *, size_t);
|
||||
BAL_HOT static const uint8_t *_bal_translate_flat(void *,
|
||||
bal_guest_address_t,
|
||||
size_t *);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *host_base;
|
||||
size_t size;
|
||||
} flat_translation_interface_t;
|
||||
|
||||
void
|
||||
get_default_allocator (bal_allocator_t *out_allocator)
|
||||
bal_get_default_allocator (bal_allocator_t *out_allocator)
|
||||
{
|
||||
out_allocator->allocator = NULL;
|
||||
out_allocator->allocate = default_allocate;
|
||||
out_allocator->free = default_free;
|
||||
}
|
||||
|
||||
bal_error_t
|
||||
bal_memory_init_flat (bal_allocator_t *BAL_RESTRICT allocator,
|
||||
bal_memory_interface_t *BAL_RESTRICT interface,
|
||||
void *BAL_RESTRICT buffer,
|
||||
size_t size)
|
||||
{
|
||||
if (NULL == allocator || NULL == interface || NULL == buffer || 0 == size)
|
||||
{
|
||||
return BAL_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (((uintptr_t)buffer & 3U) != 0)
|
||||
{
|
||||
// Buffer is not 4 byte aligned.
|
||||
//
|
||||
return BAL_ERROR_MEMORY_ALIGNMENT;
|
||||
}
|
||||
|
||||
size_t memory_alignment = 4U;
|
||||
flat_translation_interface_t *flat_interface
|
||||
= (flat_translation_interface_t *)allocator->allocate(
|
||||
allocator, memory_alignment, sizeof(flat_translation_interface_t));
|
||||
|
||||
flat_interface->host_base = (uint8_t *)buffer;
|
||||
flat_interface->size = size;
|
||||
interface->context = flat_interface;
|
||||
interface->translate = _bal_translate_flat;
|
||||
return BAL_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
bal_memory_destroy_flat (bal_allocator_t *allocator,
|
||||
bal_memory_interface_t *interface)
|
||||
{
|
||||
if (NULL == allocator || NULL == interface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL == interface->context)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
allocator->free(
|
||||
allocator, interface->context, sizeof(flat_translation_interface_t));
|
||||
}
|
||||
|
||||
#if BAL_PLATFORM_POSIX
|
||||
|
||||
void *
|
||||
static void *
|
||||
default_allocate (void *allocator, size_t alignment, size_t size)
|
||||
{
|
||||
if (0 == size)
|
||||
@@ -25,11 +81,10 @@ default_allocate (void *allocator, size_t alignment, size_t size)
|
||||
}
|
||||
|
||||
void *memory = aligned_alloc(alignment, size);
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
default_free (void *allocator, void *pointer, size_t size)
|
||||
{
|
||||
free(pointer);
|
||||
@@ -41,7 +96,7 @@ default_free (void *allocator, void *pointer, size_t size)
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
void *
|
||||
static void *
|
||||
default_allocate (void *allocator, size_t alignment, size_t size)
|
||||
{
|
||||
if (0 == size)
|
||||
@@ -50,16 +105,42 @@ default_allocate (void *allocator, size_t alignment, size_t size)
|
||||
}
|
||||
|
||||
void *memory = _aligned_malloc(alignment, size);
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
default_free (void *allocator, void *pointer, size_t size)
|
||||
{
|
||||
_aligned_free(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BAL_PLATFORM_WINDOWS */
|
||||
|
||||
static const uint8_t *
|
||||
_bal_translate_flat (void *BAL_RESTRICT interface,
|
||||
bal_guest_address_t guest_address,
|
||||
size_t *BAL_RESTRICT max_readable_size)
|
||||
{
|
||||
if (BAL_UNLIKELY(NULL == interface || 0 == guest_address
|
||||
|| NULL == max_readable_size))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
flat_translation_interface_t *BAL_RESTRICT context
|
||||
= (flat_translation_interface_t *)((bal_memory_interface_t *)interface)
|
||||
->context;
|
||||
|
||||
// Is address out of bounds.
|
||||
//
|
||||
if (guest_address >= context->size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*max_readable_size = context->size - guest_address;
|
||||
const uint8_t *host_address = context->host_base + guest_address;
|
||||
return host_address;
|
||||
}
|
||||
|
||||
/*** end of file ***/
|
||||
|
||||
Reference in New Issue
Block a user