Made selfpatch easier to port to kernel

This commit is contained in:
York Jasper Niebuhr 2026-04-08 16:52:35 +02:00
parent 32a73df1cd
commit a032f39cc5
10 changed files with 274 additions and 123 deletions

View File

@ -1,12 +1,28 @@
add_library(spslr_randomizer STATIC add_library(spslr_randomizer STATIC
src/randomizer.c src/spslr_randomizer.c
) )
target_include_directories(spslr_randomizer PUBLIC target_include_directories(spslr_randomizer PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
) )
add_library(spslr_selfpatch STATIC src/selfpatch.c src/randomizer.c src/env.c) target_compile_options(spslr_randomizer PRIVATE
-Wall
-Wextra
-Werror
-Wmissing-prototypes
-Wstrict-prototypes
-Wold-style-definition
-Wmissing-declarations
)
set_target_properties(spslr_randomizer PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED YES
C_EXTENSIONS YES
)
add_library(spslr_selfpatch STATIC src/spslr.c src/spslr_randomizer.c src/spslr_env.c)
target_link_libraries(spslr_selfpatch PUBLIC spslr_randomizer) target_link_libraries(spslr_selfpatch PUBLIC spslr_randomizer)
@ -15,6 +31,22 @@ target_include_directories(spslr_selfpatch PUBLIC
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
target_compile_options(spslr_selfpatch PRIVATE
-Wall
-Wextra
-Werror
-Wmissing-prototypes
-Wstrict-prototypes
-Wold-style-definition
-Wmissing-declarations
)
set_target_properties(spslr_selfpatch PROPERTIES
C_STANDARD 11
C_STANDARD_REQUIRED YES
C_EXTENSIONS YES
)
target_include_directories(spslr_patchcompile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_list.h target_include_directories(spslr_patchcompile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_list.h
add_subdirectory(test) add_subdirectory(test)

View File

@ -1,18 +0,0 @@
#ifndef SPSLR_ENV_H
#define SPSLR_ENV_H
#include "spslr_types.h"
void spslr_env_panic(const char* reason);
void spslr_env_poke_text_8(void* dst, spslr_u8 value);
void spslr_env_poke_text_16(void* dst, spslr_u16 value);
void spslr_env_poke_text_32(void* dst, spslr_u32 value);
void spslr_env_poke_text_64(void* dst, spslr_u64 value);
void* spslr_env_malloc(spslr_u32 n); // Either return valid buffer or panic internally
void spslr_env_free(void* ptr);
void spslr_env_poke_data(void* dst, const void* src, spslr_u32 n);
void spslr_env_memset(void* dst, int v, spslr_u32 n);
void spslr_env_memcpy(void* dst, const void* src, spslr_u32 n);
spslr_u32 spslr_env_random_u32();
#endif

View File

@ -1,7 +1,7 @@
#include <spslr.h> #include <spslr.h>
#include "randomizer.h" #include "spslr_randomizer.h"
#include "env.h" #include "spslr_env.h"
#include "spslr_list_link.h" #include "spslr_list_link.h"
#define SPSLR_SANITY_CHECK #define SPSLR_SANITY_CHECK
@ -13,18 +13,35 @@ static void spslr_selfpatch_patch_ipins(void);
static void reorder_object(void* dst, const void* src, spslr_u32 target); static void reorder_object(void* dst, const void* src, spslr_u32 target);
static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start); static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start);
static void* reorder_buffer = SPSLR_NULL; static void* reorder_buffer = NULL;
static void allocate_reorder_buffer(); static void allocate_reorder_buffer(void);
static void release_reorder_buffer(); static void release_reorder_buffer(void);
void spslr_selfpatch(void) { void __init spslr_selfpatch(void) {
if (spslr_randomizer_init() < 0) if (spslr_randomizer_init() < 0)
spslr_env_panic("failed to initialize randomizer"); spslr_env_panic("failed to initialize randomizer");
#ifdef SPSLR_SANITY_CHECK
for (spslr_u32 tidx = 0; tidx < spslr_target_cnt; tidx++) {
if (spslr_randomizer_validate_target(tidx) < 0)
spslr_env_panic("original layout of target %u is invalid", tidx);
}
#endif
if (spslr_randomize() < 0) if (spslr_randomize() < 0)
spslr_env_panic("failed to randomize targets"); spslr_env_panic("failed to randomize targets");
#ifdef SPSLR_SANITY_CHECK
for (spslr_u32 tidx = 0; tidx < spslr_target_cnt; tidx++) {
if (spslr_randomizer_debug_target(tidx) < 0)
spslr_env_panic("failed to debug print final layout of target %u", tidx);
if (spslr_randomizer_validate_target(tidx) < 0)
spslr_env_panic("final layout of target %u is invalid", tidx);
}
#endif
allocate_reorder_buffer(); allocate_reorder_buffer();
spslr_selfpatch_patch_dpins(); spslr_selfpatch_patch_dpins();
release_reorder_buffer(); release_reorder_buffer();
@ -34,7 +51,7 @@ void spslr_selfpatch(void) {
spslr_randomizer_clear(); spslr_randomizer_clear();
} }
static void allocate_reorder_buffer() { static void __init allocate_reorder_buffer(void) {
if (reorder_buffer) if (reorder_buffer)
return; return;
@ -46,28 +63,28 @@ static void allocate_reorder_buffer() {
reorder_buffer = spslr_env_malloc(max_target_size); reorder_buffer = spslr_env_malloc(max_target_size);
if (!reorder_buffer) if (!reorder_buffer)
spslr_env_panic("failed to allocate reorder buffer"); spslr_env_panic("failed to allocate reorder buffer of size %u", max_target_size);
} }
static void release_reorder_buffer() { static void __init release_reorder_buffer(void) {
if (!reorder_buffer) if (!reorder_buffer)
return; return;
spslr_env_free(reorder_buffer); spslr_env_free(reorder_buffer);
reorder_buffer = SPSLR_NULL; reorder_buffer = NULL;
} }
static void spslr_selfpatch_patch_dpins(void) { static void __init spslr_selfpatch_patch_dpins(void) {
for (spslr_u32 dpidx = 0; dpidx < spslr_dpin_cnt; dpidx++) { for (spslr_u32 dpidx = 0; dpidx < spslr_dpin_cnt; dpidx++) {
const struct spslr_dpin* dp = &spslr_dpins[dpidx]; const struct spslr_dpin* dp = &spslr_dpins[dpidx];
spslr_selfpatch_patch_dpin((void*)dp->addr, dp->target); spslr_selfpatch_patch_dpin((void*)dp->addr, dp->target);
} }
} }
static void reorder_object(void* dst, const void* src, spslr_u32 target) { static void __init reorder_object(void* dst, const void* src, spslr_u32 target) {
spslr_u32 field_count; spslr_u32 field_count;
if (spslr_randomizer_get_target(target, SPSLR_NULL, &field_count)) if (spslr_randomizer_get_target(target, NULL, &field_count))
spslr_env_panic("failed to get target field count"); spslr_env_panic("failed to get field count of target %u", target);
const spslr_u8* src_countable = (const spslr_u8*)src; const spslr_u8* src_countable = (const spslr_u8*)src;
spslr_u8* dst_countable = (spslr_u8*)dst; spslr_u8* dst_countable = (spslr_u8*)dst;
@ -75,16 +92,16 @@ static void reorder_object(void* dst, const void* src, spslr_u32 target) {
for (spslr_u32 i = 0; i < field_count; i++) { for (spslr_u32 i = 0; i < field_count; i++) {
struct spslr_randomizer_field_info finfo; struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(target, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL, &finfo)) if (spslr_randomizer_get_field(target, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL, &finfo))
spslr_env_panic("failed to get ordered field descriptor"); spslr_env_panic("failed to get descriptor of final field %u of target %u", i, target);
spslr_env_memcpy(dst_countable + finfo.offset, src_countable + finfo.initial_offset, finfo.size); spslr_env_memcpy(dst_countable + finfo.offset, src_countable + finfo.initial_offset, finfo.size);
} }
} }
static void spslr_selfpatch_patch_dpin(void* addr, spslr_u32 target) { static void __init spslr_selfpatch_patch_dpin(void* addr, spslr_u32 target) {
#ifdef SPSLR_SANITY_CHECK #ifdef SPSLR_SANITY_CHECK
if (target >= spslr_target_cnt) if (target >= spslr_target_cnt)
spslr_env_panic("dpin refers to invalid target"); spslr_env_panic("dpin refers to invalid target %u", target);
#endif #endif
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
@ -94,7 +111,7 @@ static void spslr_selfpatch_patch_dpin(void* addr, spslr_u32 target) {
spslr_env_poke_data(addr, reorder_buffer, t->size); spslr_env_poke_data(addr, reorder_buffer, t->size);
} }
static void spslr_selfpatch_patch_ipins(void) { static void __init spslr_selfpatch_patch_ipins(void) {
for (spslr_u32 ipidx = 0; ipidx < spslr_ipin_cnt; ipidx++) { for (spslr_u32 ipidx = 0; ipidx < spslr_ipin_cnt; ipidx++) {
const struct spslr_ipin* ip = &spslr_ipins[ipidx]; const struct spslr_ipin* ip = &spslr_ipins[ipidx];
@ -115,20 +132,20 @@ static void spslr_selfpatch_patch_ipins(void) {
break; break;
#ifdef SPSLR_SANITY_CHECK #ifdef SPSLR_SANITY_CHECK
default: default:
spslr_env_panic("invalid ipin size"); spslr_env_panic("invalid ipin size of %u bytes", ip->size);
#endif #endif
} }
} }
} }
static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start) { static spslr_s64 __init spslr_calculate_ipin_value(spslr_u32 start) {
spslr_s64 res = 0; spslr_s64 res = 0;
spslr_u32 pc = start; spslr_u32 pc = start;
while (true) { while (1) {
#ifdef SPSLR_SANITY_CHECK #ifdef SPSLR_SANITY_CHECK
if (pc >= spslr_ipin_op_cnt) if (pc >= spslr_ipin_op_cnt)
spslr_env_panic("ipin op out of bounds"); spslr_env_panic("ipin op %u out of bounds", pc);
#endif #endif
int end_flag = 0; int end_flag = 0;
@ -143,7 +160,8 @@ static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start) {
struct spslr_randomizer_field_info finfo; struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, if (spslr_randomizer_get_field(op->op0.add_initial_offset_target,
op->op1.add_initial_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo)) op->op1.add_initial_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo))
spslr_env_panic("failed to get initial field offset"); spslr_env_panic("failed to get info of initial field %u of target %u",
op->op1.add_initial_offset_field, op->op0.add_initial_offset_target);
res += finfo.initial_offset; res += finfo.initial_offset;
} }
@ -151,9 +169,10 @@ static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start) {
case SPSLR_IPIN_OP_ADD_OFFSET: case SPSLR_IPIN_OP_ADD_OFFSET:
{ {
struct spslr_randomizer_field_info finfo; struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, if (spslr_randomizer_get_field(op->op0.add_offset_target,
op->op1.add_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo)) op->op1.add_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo))
spslr_env_panic("failed to get initial field offset"); spslr_env_panic("failed to get info of initial field %u of target %u",
op->op1.add_offset_field, op->op0.add_offset_target);
res += finfo.offset; res += finfo.offset;
} }
@ -161,9 +180,10 @@ static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start) {
case SPSLR_IPIN_OP_SUB_INITIAL_OFFSET: case SPSLR_IPIN_OP_SUB_INITIAL_OFFSET:
{ {
struct spslr_randomizer_field_info finfo; struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, if (spslr_randomizer_get_field(op->op0.sub_initial_offset_target,
op->op1.sub_initial_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo)) op->op1.sub_initial_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo))
spslr_env_panic("failed to get initial field offset"); spslr_env_panic("failed to get info of initial field %u of target %u",
op->op1.sub_initial_offset_field, op->op0.sub_initial_offset_target);
res -= finfo.initial_offset; res -= finfo.initial_offset;
} }
@ -171,9 +191,10 @@ static spslr_s64 spslr_calculate_ipin_value(spslr_u32 start) {
case SPSLR_IPIN_OP_SUB_OFFSET: case SPSLR_IPIN_OP_SUB_OFFSET:
{ {
struct spslr_randomizer_field_info finfo; struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(op->op0.add_initial_offset_target, if (spslr_randomizer_get_field(op->op0.sub_offset_target,
op->op1.sub_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo)) op->op1.sub_offset_field, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo))
spslr_env_panic("failed to get initial field offset"); spslr_env_panic("failed to get info of initial field %u of target %u",
op->op1.sub_offset_field, op->op0.sub_offset_target);
res -= finfo.offset; res -= finfo.offset;
} }

View File

@ -1,14 +1,15 @@
#include "env.h" #include "spslr_env.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <stdarg.h>
#define PAGE_MASK ~(0x1000ull - 1) #define PAGE_MASK ~(0x1000ull - 1)
static int spslr_env_get_prot(void* addr, int* prot) { static int __init spslr_env_get_prot(void* addr, int* prot) {
FILE* f = fopen("/proc/self/maps", "r"); FILE* f = fopen("/proc/self/maps", "r");
if (!f) if (!f)
return -1; return -1;
@ -43,10 +44,10 @@ static int spslr_env_get_prot(void* addr, int* prot) {
return -1; return -1;
} }
static void spslr_env_poke_safe(void* dst, const void* src, spslr_u32 n) { static void __init spslr_env_poke_safe(void* dst, const void* src, spslr_u32 n) {
int original_prot; int original_prot;
if (spslr_env_get_prot(dst, &original_prot)) if (spslr_env_get_prot(dst, &original_prot))
spslr_env_panic("failed to get prot of text poke destination"); spslr_env_panic("failed to get prot of text poke destination %p", dst);
spslr_u64 ptr_uint = (spslr_u64)dst; spslr_u64 ptr_uint = (spslr_u64)dst;
spslr_u64 ptr_page = ptr_uint & PAGE_MASK; spslr_u64 ptr_page = ptr_uint & PAGE_MASK;
@ -63,56 +64,75 @@ static void spslr_env_poke_safe(void* dst, const void* src, spslr_u32 n) {
mprotect((void*)ptr_page, prot_size, original_prot); mprotect((void*)ptr_page, prot_size, original_prot);
} }
void spslr_env_panic(const char* reason) { void __init spslr_env_panic(const char* fmt, ...) {
fprintf(stderr, "[spslr_panic] %s\n", reason); va_list args;
va_start(args, fmt);
fprintf(stderr, "[spslr_panic] ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(1); exit(1);
} }
void spslr_env_poke_text_8(void* dst, spslr_u8 value) { void __init spslr_env_debug(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
fprintf(stdout, "[spslr_debug] ");
vfprintf(stdout, fmt, args);
fprintf(stdout, "\n");
va_end(args);
}
void __init spslr_env_poke_text_8(void* dst, spslr_u8 value) {
spslr_env_poke_safe(dst, &value, sizeof(value)); spslr_env_poke_safe(dst, &value, sizeof(value));
} }
void spslr_env_poke_text_16(void* dst, spslr_u16 value) { void __init spslr_env_poke_text_16(void* dst, spslr_u16 value) {
spslr_env_poke_safe(dst, &value, sizeof(value)); spslr_env_poke_safe(dst, &value, sizeof(value));
} }
void spslr_env_poke_text_32(void* dst, spslr_u32 value) { void __init spslr_env_poke_text_32(void* dst, spslr_u32 value) {
spslr_env_poke_safe(dst, &value, sizeof(value)); spslr_env_poke_safe(dst, &value, sizeof(value));
} }
void spslr_env_poke_text_64(void* dst, spslr_u64 value) { void __init spslr_env_poke_text_64(void* dst, spslr_u64 value) {
spslr_env_poke_safe(dst, &value, sizeof(value)); spslr_env_poke_safe(dst, &value, sizeof(value));
} }
void* spslr_env_malloc(spslr_u32 n) { void* __init spslr_env_malloc(spslr_u32 n) {
void* res = malloc(n); void* res = malloc(n);
if (!res) if (!res)
spslr_env_panic("malloc failed"); spslr_env_panic("malloc of size %u failed", n);
return res; return res;
} }
void spslr_env_free(void* ptr) { void __init spslr_env_free(void* ptr) {
free(ptr); free(ptr);
} }
void spslr_env_poke_data(void* dst, const void* src, spslr_u32 n) { void __init spslr_env_poke_data(void* dst, const void* src, spslr_u32 n) {
spslr_env_poke_safe(dst, src, n); spslr_env_poke_safe(dst, src, n);
} }
void spslr_env_memset(void* dst, int v, spslr_u32 n) { void __init spslr_env_memset(void* dst, int v, spslr_u32 n) {
memset(dst, v, n); memset(dst, v, n);
} }
void spslr_env_memcpy(void* dst, const void* src, spslr_u32 n) { void __init spslr_env_memcpy(void* dst, const void* src, spslr_u32 n) {
memcpy(dst, src, n); memcpy(dst, src, n);
} }
static int rand_initialized = 0; static int rand_initialized = 0;
spslr_u32 spslr_env_random_u32() { spslr_u32 __init spslr_env_random_u32(void) {
if (!rand_initialized) { if (!rand_initialized) {
srand(time(SPSLR_NULL)); srand(time(NULL));
rand_initialized = 1; rand_initialized = 1;
} }

49
selfpatch/src/spslr_env.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef SPSLR_ENV_H
#define SPSLR_ENV_H
#include <stdint.h>
#include <stddef.h>
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#ifndef __init
#define __init /* only required in kernel */
#endif
#ifndef __noreturn
#define __noreturn __attribute__((noreturn))
#endif
#ifndef __printf
#define __printf(fmt_pos, arg_pos) __attribute__((format(printf, fmt_pos, arg_pos)))
#endif
#ifndef NULL
#define NULL ((void*)0)
#endif
typedef uint8_t spslr_u8;
typedef uint16_t spslr_u16;
typedef uint32_t spslr_u32;
typedef uint64_t spslr_u64;
typedef int32_t spslr_s32;
typedef int64_t spslr_s64;
typedef uintptr_t spslr_uintptr;
void __noreturn spslr_env_panic(const char* fmt, ...) __printf(1, 2);
void spslr_env_debug(const char* fmt, ...) __printf(1, 2);
void spslr_env_poke_text_8(void* dst, spslr_u8 value);
void spslr_env_poke_text_16(void* dst, spslr_u16 value);
void spslr_env_poke_text_32(void* dst, spslr_u32 value);
void spslr_env_poke_text_64(void* dst, spslr_u64 value);
void* spslr_env_malloc(spslr_u32 n); // Either return valid buffer or panic internally
void spslr_env_free(void* ptr);
void spslr_env_poke_data(void* dst, const void* src, spslr_u32 n);
void spslr_env_memset(void* dst, int v, spslr_u32 n);
void spslr_env_memcpy(void* dst, const void* src, spslr_u32 n);
spslr_u32 spslr_env_random_u32(void);
#endif

View File

@ -1,9 +1,7 @@
#ifndef SPSLR_LIST_H #ifndef SPSLR_LIST_H
#define SPSLR_LIST_H #define SPSLR_LIST_H
#include "spslr_types.h" #include "spslr_env.h"
#define __packed __attribute__((packed))
#define SPSLR_IPIN_OP_PATCH 1 #define SPSLR_IPIN_OP_PATCH 1
#define SPSLR_IPIN_OP_ADD_INITIAL_OFFSET 2 #define SPSLR_IPIN_OP_ADD_INITIAL_OFFSET 2

View File

@ -1,7 +1,7 @@
#include "randomizer.h" #include "spslr_randomizer.h"
#include "spslr_list_link.h" #include "spslr_list_link.h"
#include "env.h" #include "spslr_env.h"
struct Field { struct Field {
spslr_u32 offset; /* Final field offset -> fields[i].offset = offset of field i in final layout */ spslr_u32 offset; /* Final field offset -> fields[i].offset = offset of field i in final layout */
@ -11,7 +11,7 @@ struct Field {
static struct Field* fields; static struct Field* fields;
int spslr_randomizer_init() { int __init spslr_randomizer_init(void) {
fields = (struct Field*)spslr_env_malloc(sizeof(struct Field) * spslr_target_field_cnt); fields = (struct Field*)spslr_env_malloc(sizeof(struct Field) * spslr_target_field_cnt);
if (!fields) if (!fields)
return -1; return -1;
@ -34,15 +34,15 @@ int spslr_randomizer_init() {
return 0; return 0;
} }
void spslr_randomizer_clear() { void __init spslr_randomizer_clear(void) {
if (!fields) if (!fields)
return; return;
spslr_env_free(fields); spslr_env_free(fields);
fields = SPSLR_NULL; fields = NULL;
} }
int spslr_randomizer_get_target(spslr_u32 target, spslr_u32* size, spslr_u32* fieldcnt) { int __init spslr_randomizer_get_target(spslr_u32 target, spslr_u32* size, spslr_u32* fieldcnt) {
if (target >= spslr_target_cnt) if (target >= spslr_target_cnt)
return -1; return -1;
@ -57,7 +57,7 @@ int spslr_randomizer_get_target(spslr_u32 target, spslr_u32* size, spslr_u32* fi
return 0; return 0;
} }
int spslr_randomizer_get_field(spslr_u32 target, spslr_u32 field, int field_idx_mode, int __init spslr_randomizer_get_field(spslr_u32 target, spslr_u32 field, int field_idx_mode,
struct spslr_randomizer_field_info* info) { struct spslr_randomizer_field_info* info) {
if (target >= spslr_target_cnt) if (target >= spslr_target_cnt)
return -1; return -1;
@ -70,8 +70,8 @@ int spslr_randomizer_get_field(spslr_u32 target, spslr_u32 field, int field_idx_
if (field >= t->fieldcnt) if (field >= t->fieldcnt)
return -1; return -1;
const struct spslr_target_field* of = SPSLR_NULL; const struct spslr_target_field* of = NULL;
const struct Field* rf = SPSLR_NULL; const struct Field* rf = NULL;
switch (field_idx_mode) { switch (field_idx_mode) {
case SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL: case SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL:
@ -95,6 +95,57 @@ int spslr_randomizer_get_field(spslr_u32 target, spslr_u32 field, int field_idx_
return 0; return 0;
} }
int spslr_randomizer_debug_target(spslr_u32 target) {
spslr_u32 size, fieldcnt;
if (spslr_randomizer_get_target(target, &size, &fieldcnt) < 0)
return -1;
spslr_env_debug("Target %u (%u fields, %u bytes):", target, fieldcnt, size);
for (spslr_u32 i = 0; i < fieldcnt; i++) {
struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(target, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL, &finfo) < 0)
return -1;
spslr_env_debug(" Field %u (%u bytes) moved from offset %u to %u", i,
finfo.size, finfo.initial_offset, finfo.offset);
}
return 0;
}
int spslr_randomizer_validate_target(spslr_u32 target) {
spslr_u32 tsize, fieldcnt;
if (spslr_randomizer_get_target(target, &tsize, &fieldcnt) < 0)
return -1;
spslr_u32 cur_end = 0;
for (spslr_u32 i = 0; i < fieldcnt; i++) {
struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(target, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL, &finfo) < 0)
return -1;
if (finfo.offset < cur_end)
return -1;
if (finfo.offset % finfo.alignment != 0)
return -1;
if ((finfo.flags & SPSLR_FLAG_FIELD_FIXED) && finfo.offset != finfo.initial_offset)
return -1;
if (finfo.offset + finfo.size > tsize)
return -1;
cur_end = finfo.offset + finfo.size;
}
return 0;
}
// RANDOMIZATION CODE // RANDOMIZATION CODE
struct ShuffleRegion { struct ShuffleRegion {
@ -119,23 +170,23 @@ static spslr_u32 rand_u32(void) {
return spslr_env_random_u32(); return spslr_env_random_u32();
} }
static struct Field* get_rfield(spslr_u32 target, spslr_u32 final_idx) { static struct Field* __init get_rfield(spslr_u32 target, spslr_u32 final_idx) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
return &fields[t->fieldoff + final_idx]; return &fields[t->fieldoff + final_idx];
} }
static const struct spslr_target_field* get_ofield(spslr_u32 target, spslr_u32 orig_idx) { static const struct spslr_target_field* __init get_ofield(spslr_u32 target, spslr_u32 orig_idx) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
return &spslr_target_fields[t->fieldoff + orig_idx]; return &spslr_target_fields[t->fieldoff + orig_idx];
} }
static void get_origin_region(spslr_u32 target, spslr_u32 final_idx, struct ShuffleRegion* region) { static void __init get_origin_region(spslr_u32 target, spslr_u32 final_idx, struct ShuffleRegion* region) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
const struct Field* rf = get_rfield(target, final_idx); const struct Field* rf = get_rfield(target, final_idx);
const struct spslr_target_field* of = get_ofield(target, rf->oidx); const struct spslr_target_field* of = get_ofield(target, rf->oidx);
region->fill_begin = rf->offset; region->fill_begin = rf->offset;
region->fill_end = rf->offset + of->size; region->fill_end = region->fill_begin + of->size;
if (final_idx == 0) { if (final_idx == 0) {
region->begin = 0; region->begin = 0;
@ -153,7 +204,7 @@ static void get_origin_region(spslr_u32 target, spslr_u32 final_idx, struct Shuf
} }
} }
static int option_is_valid(spslr_u32 target, spslr_u32 origin_final_idx, const struct ShuffleRegion* origin, spslr_u32 offset) { static int __init option_is_valid(spslr_u32 target, spslr_u32 origin_final_idx, const struct ShuffleRegion* origin, spslr_u32 offset) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
const struct spslr_target_field* origin_of = const struct spslr_target_field* origin_of =
get_ofield(target, get_rfield(target, origin_final_idx)->oidx); get_ofield(target, get_rfield(target, origin_final_idx)->oidx);
@ -210,7 +261,7 @@ static int option_is_valid(spslr_u32 target, spslr_u32 origin_final_idx, const s
return 1; return 1;
} }
static int pick_shuffle_option(spslr_u32 target, spslr_u32 origin_final_idx, const struct ShuffleRegion* origin, static int __init pick_shuffle_option(spslr_u32 target, spslr_u32 origin_final_idx, const struct ShuffleRegion* origin,
spslr_u32 alignment, spslr_u32* selected) { spslr_u32 alignment, spslr_u32* selected) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
spslr_u32 seen = 0; spslr_u32 seen = 0;
@ -228,7 +279,7 @@ static int pick_shuffle_option(spslr_u32 target, spslr_u32 origin_final_idx, con
return seen ? 0 : -1; return seen ? 0 : -1;
} }
static void do_swap(spslr_u32 target, spslr_u32 origin_idx, static void __init do_swap(spslr_u32 target, spslr_u32 origin_idx,
const struct ShuffleRegion* origin_region, spslr_u32 new_offset) { const struct ShuffleRegion* origin_region, spslr_u32 new_offset) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
int pulled = 0; int pulled = 0;
@ -306,7 +357,7 @@ static void do_swap(spslr_u32 target, spslr_u32 origin_idx,
} }
} }
static void shuffle_one_target(spslr_u32 target) { static void __init shuffle_one_target(spslr_u32 target) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
if (t->fieldcnt == 0) if (t->fieldcnt == 0)
return; return;
@ -330,7 +381,7 @@ static void shuffle_one_target(spslr_u32 target) {
do_swap(target, origin_final_idx, &origin_region, selected_option); do_swap(target, origin_final_idx, &origin_region, selected_option);
} }
static void shuffle_target(spslr_u32 target) { static void __init shuffle_target(spslr_u32 target) {
const struct spslr_target* t = &spslr_targets[target]; const struct spslr_target* t = &spslr_targets[target];
spslr_u32 shuffle_count = t->fieldcnt * 2; spslr_u32 shuffle_count = t->fieldcnt * 2;
@ -338,7 +389,7 @@ static void shuffle_target(spslr_u32 target) {
shuffle_one_target(target); shuffle_one_target(target);
} }
int spslr_randomize() { int __init spslr_randomize(void) {
if (!fields) if (!fields)
return -1; return -1;

View File

@ -1,7 +1,7 @@
#ifndef SPSLR_RANDOMIZER_H #ifndef SPSLR_RANDOMIZER_H
#define SPSLR_RANDOMIZER_H #define SPSLR_RANDOMIZER_H
#include "spslr_types.h" #include "spslr_env.h"
#define SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL 1 #define SPSLR_RANDOMIZER_FIELD_IDX_MODE_ORIGINAL 1
#define SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL 2 #define SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL 2
@ -14,12 +14,15 @@ struct spslr_randomizer_field_info {
spslr_u32 flags; spslr_u32 flags;
}; };
int spslr_randomizer_init(); int spslr_randomizer_init(void);
int spslr_randomize(); int spslr_randomize(void);
void spslr_randomizer_clear(); void spslr_randomizer_clear(void);
int spslr_randomizer_get_target(spslr_u32 target, spslr_u32* size, spslr_u32* fieldcnt); int spslr_randomizer_get_target(spslr_u32 target, spslr_u32* size, spslr_u32* fieldcnt);
int spslr_randomizer_get_field(spslr_u32 target, spslr_u32 field, int field_idx_mode, int spslr_randomizer_get_field(spslr_u32 target, spslr_u32 field, int field_idx_mode,
struct spslr_randomizer_field_info* info); struct spslr_randomizer_field_info* info);
int spslr_randomizer_debug_target(spslr_u32 target);
int spslr_randomizer_validate_target(spslr_u32 target);
#endif #endif

View File

@ -1,17 +0,0 @@
#ifndef SPSLR_TYPES_H
#define SPSLR_TYPES_H
#include <stdint.h>
#include <stddef.h>
typedef uint8_t spslr_u8;
typedef uint16_t spslr_u16;
typedef uint32_t spslr_u32;
typedef uint64_t spslr_u64;
typedef int32_t spslr_s32;
typedef int64_t spslr_s64;
typedef uintptr_t spslr_uintptr;
#define SPSLR_NULL NULL
#endif

View File

@ -2,11 +2,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <stdarg.h>
#include <spslr_list_link.h> #include <spslr_list_link.h>
#include <randomizer.h> #include <spslr_randomizer.h>
void *spslr_env_malloc(size_t size) { void *spslr_env_malloc(spslr_u32 size) {
return malloc(size); return malloc(size);
} }
@ -14,12 +15,23 @@ void spslr_env_free(void *ptr) {
free(ptr); free(ptr);
} }
uint32_t spslr_env_random_u32(void) { spslr_u32 spslr_env_random_u32(void) {
return ((uint32_t)rand() << 16) ^ (uint32_t)rand(); return ((spslr_u32)rand() << 16) ^ (spslr_u32)rand();
} }
const uint32_t spslr_target_cnt = 1; void __init spslr_env_debug(const char* fmt, ...) {
const uint32_t spslr_target_field_cnt = 196; va_list args;
va_start(args, fmt);
fprintf(stdout, "[spslr_debug] ");
vfprintf(stdout, fmt, args);
fprintf(stdout, "\n");
va_end(args);
}
const spslr_u32 spslr_target_cnt = 1;
const spslr_u32 spslr_target_field_cnt = 196;
const struct spslr_target spslr_targets[] = { const struct spslr_target spslr_targets[] = {
{ {
@ -228,15 +240,15 @@ const struct spslr_target_field spslr_target_fields[] = {
{ .offset = 2816, .size = 16, .alignment = 8, .flags = 0 } { .offset = 2816, .size = 16, .alignment = 8, .flags = 0 }
}; };
static int check_target(uint32_t tidx) { static int check_target(spslr_u32 tidx) {
uint32_t tsize, fieldcnt; spslr_u32 tsize, fieldcnt;
if (spslr_randomizer_get_target(tidx, &tsize, &fieldcnt) < 0) if (spslr_randomizer_get_target(tidx, &tsize, &fieldcnt) < 0)
return -1; return -1;
uint32_t cur_end = 0; spslr_u32 cur_end = 0;
for (uint32_t i = 0; i < fieldcnt; i++) { for (spslr_u32 i = 0; i < fieldcnt; i++) {
struct spslr_randomizer_field_info finfo; struct spslr_randomizer_field_info finfo;
if (spslr_randomizer_get_field(tidx, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL, &finfo) < 0) { if (spslr_randomizer_get_field(tidx, i, SPSLR_RANDOMIZER_FIELD_IDX_MODE_FINAL, &finfo) < 0) {
fprintf(stderr, "failed to get field from randomizer\n"); fprintf(stderr, "failed to get field from randomizer\n");
@ -272,9 +284,9 @@ static int check_target(uint32_t tidx) {
int main(void) { int main(void) {
srand((unsigned)time(NULL)); srand((unsigned)time(NULL));
uint32_t rounds = 1000; spslr_u32 rounds = 1000;
for (uint32_t iter = 0; iter < rounds; iter++) { for (spslr_u32 iter = 0; iter < rounds; iter++) {
if (spslr_randomizer_init() < 0) { if (spslr_randomizer_init() < 0) {
fprintf(stderr, "init failed\n"); fprintf(stderr, "init failed\n");
return 1; return 1;
@ -285,7 +297,7 @@ int main(void) {
return 1; return 1;
} }
for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) { for (spslr_u32 tidx = 0; tidx < spslr_target_cnt; tidx++) {
if (check_target(tidx) < 0) { if (check_target(tidx) < 0) {
fprintf(stderr, "check failed at iter %u target %u\n", iter, tidx); fprintf(stderr, "check failed at iter %u target %u\n", iter, tidx);
return 1; return 1;