Modernized selfpatch interface - awaiting patchcompile update

This commit is contained in:
York Jasper Niebuhr 2026-04-06 18:53:56 +02:00
parent c57b3f03a3
commit b40222f0ae
12 changed files with 418 additions and 540 deletions

View File

@ -1,8 +1,8 @@
add_library(spslr_selfpatch STATIC src/selfpatch.c src/targets.c src/patcher.c) add_library(spslr_selfpatch STATIC src/selfpatch.c src/targets.c src/env.c)
target_include_directories(spslr_selfpatch PUBLIC target_include_directories(spslr_selfpatch PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
target_include_directories(spslr_patchcompile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_program.h target_include_directories(spslr_patchcompile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # For spslr_list.h

View File

@ -1,6 +1,6 @@
#ifndef SPSLR_SELFPATCH_H #ifndef SPSLR_SELFPATCH_H
#define SPSLR_SELFPATCH_H #define SPSLR_SELFPATCH_H
void spslr_selfpatch(); void spslr_selfpatch(void);
#endif #endif

109
selfpatch/src/env.c Normal file
View File

@ -0,0 +1,109 @@
#include "env.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#define PAGE_MASK ~(0x1000ull - 1)
static int spslr_env_get_prot(void* addr, int* prot) {
FILE* f = fopen("/proc/self/maps", "r");
if (!f)
return -1;
uintptr_t query = (uintptr_t)addr;
char line[512];
while (fgets(line, sizeof(line), f)) {
uintptr_t start, end;
char perms[5];
if (sscanf(line, "%lx-%lx %4s", &start, &end, perms) != 3)
continue;
if (query < start || query >= end)
continue;
*prot = 0;
if (perms[0] == 'r')
*prot |= PROT_READ;
if (perms[1] == 'w')
*prot |= PROT_WRITE;
if (perms[2] == 'x')
*prot |= PROT_EXEC;
fclose(f);
return 0;
}
fclose(f);
return -1;
}
static void spslr_env_poke_safe(void* dst, const void* src, uint32_t n) {
int original_prot;
if (spslr_env_get_prot(dst, &original_prot))
spslr_env_panic("failed to get prot of text poke destination");
uint64_t ptr_uint = (uint64_t)dst;
uint64_t ptr_page = ptr_uint & PAGE_MASK;
uint64_t prot_size = n + (ptr_uint - ptr_page);
int tmp_prot = original_prot | PROT_WRITE;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, prot_size, tmp_prot);
spslr_env_memcpy(dst, src, n);
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, prot_size, original_prot);
}
void spslr_env_panic(const char* reason) {
fprintf(stderr, "[spslr_panic] %s\n", reason);
exit(1);
}
void spslr_env_poke_text_8(void* dst, uint8_t value) {
spslr_env_poke_safe(dst, &value, sizeof(value));
}
void spslr_env_poke_text_16(void* dst, uint16_t value) {
spslr_env_poke_safe(dst, &value, sizeof(value));
}
void spslr_env_poke_text_32(void* dst, uint32_t value) {
spslr_env_poke_safe(dst, &value, sizeof(value));
}
void spslr_env_poke_text_64(void* dst, uint64_t value) {
spslr_env_poke_safe(dst, &value, sizeof(value));
}
void* spslr_env_malloc(uint32_t n) {
void* res = malloc(n);
if (!res)
spslr_env_panic("malloc failed");
return res;
}
void spslr_env_free(void* ptr) {
free(ptr);
}
void spslr_env_poke_data(void* dst, const void* src, uint32_t n) {
spslr_env_poke_safe(dst, src, n);
}
void spslr_env_memset(void* dst, int v, uint32_t n) {
memset(dst, v, n);
}
void spslr_env_memcpy(void* dst, const void* src, uint32_t n) {
memcpy(dst, src, n);
}

17
selfpatch/src/env.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef SPSLR_ENV_H
#define SPSLR_ENV_H
#include <stdint.h>
void spslr_env_panic(const char* reason);
void spslr_env_poke_text_8(void* dst, uint8_t value);
void spslr_env_poke_text_16(void* dst, uint16_t value);
void spslr_env_poke_text_32(void* dst, uint32_t value);
void spslr_env_poke_text_64(void* dst, uint64_t value);
void* spslr_env_malloc(uint32_t n); // Either return valid buffer or panic internally
void spslr_env_free(void* ptr);
void spslr_env_poke_data(void* dst, const void* src, uint32_t n);
void spslr_env_memset(void* dst, int v, uint32_t n);
void spslr_env_memcpy(void* dst, const void* src, uint32_t n);
#endif

View File

@ -1,138 +0,0 @@
#include "patcher.h"
#include "targets.h"
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#define PAGE_MASK ~(0x1000ull - 1)
static int get_prot(void* addr, int* prot) {
FILE* f = fopen("/proc/self/maps", "r");
if (!f)
return -1;
uintptr_t query = (uintptr_t)addr;
char line[512];
while (fgets(line, sizeof(line), f)) {
uintptr_t start, end;
char perms[5];
if (sscanf(line, "%lx-%lx %4s", &start, &end, perms) != 3)
continue;
if (query < start || query >= end)
continue;
*prot = 0;
if (perms[0] == 'r')
*prot |= PROT_READ;
if (perms[1] == 'w')
*prot |= PROT_WRITE;
if (perms[2] == 'x')
*prot |= PROT_EXEC;
fclose(f);
return 0;
}
fclose(f);
return -1;
}
static int patch_immediate(void* ptr, uint32_t size, uint32_t v) {
if (size != 4)
return -1;
memcpy(ptr, &v, size);
return 0;
}
int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field) {
uint32_t field_offset;
if (spslr_get_randomized_field_offset(target, field, &field_offset))
return -1;
int original_prot;
if (get_prot(ptr, &original_prot))
return -1;
uint64_t ptr_uint = (uint64_t)ptr;
uint64_t ptr_page = ptr_uint & PAGE_MASK;
uint64_t corrected_size = size + (ptr_uint - ptr_page);
int tmp_prot = original_prot | PROT_WRITE;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, tmp_prot);
if (patch_immediate(ptr, size, field_offset))
return -1;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, original_prot);
return 0;
}
static int reorder_object(const void* src, void* dst, uint32_t target) {
if (!src || !dst)
return -1;
uint32_t field_count;
if (spslr_get_target_fieldcnt(target, &field_count))
return -1;
const uint8_t* src_countable = (const uint8_t*)src;
uint8_t* dst_countable = (uint8_t*)dst;
for (uint32_t i = 0; i < field_count; i++) {
uint32_t field_offset, field_size, field_initial_offset;
if (spslr_get_target_field_ordered(target, i, &field_offset, &field_size, &field_initial_offset))
return -1;
memcpy(dst_countable + field_offset, src_countable + field_initial_offset, field_size);
}
return 0;
}
int spslr_dpatch(void* ptr, uint32_t target) {
uint32_t target_size;
if (spslr_get_target_size(target, &target_size))
return -1;
int original_prot;
if (get_prot(ptr, &original_prot))
return -1;
uint64_t ptr_uint = (uint64_t)ptr;
uint64_t ptr_page = ptr_uint & PAGE_MASK;
uint64_t corrected_size = target_size + (ptr_uint - ptr_page);
int tmp_prot = original_prot | PROT_WRITE | PROT_READ;
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, tmp_prot);
void* tmp_obj = malloc(target_size);
if (!tmp_obj)
return -1;
memset(tmp_obj, 0, target_size);
if (reorder_object(ptr, tmp_obj, target))
return -1;
memcpy(ptr, tmp_obj, target_size);
free(tmp_obj);
if (tmp_prot != original_prot)
mprotect((void*)ptr_page, corrected_size, original_prot);
return 0;
}

View File

@ -1,9 +0,0 @@
#ifndef SPSLR_PATCHER_H
#define SPSLR_PATCHER_H
#include <stdint.h>
int spslr_ipatch(void* ptr, uint32_t size, uint32_t target, uint32_t field);
int spslr_dpatch(void* ptr, uint32_t target);
#endif

View File

@ -1,71 +1,198 @@
#include <spslr.h> #include <spslr.h>
#include <stdio.h> #include <stddef.h>
#include <stdlib.h>
#include "spslr_program.h"
#include "targets.h" #include "targets.h"
#include "patcher.h" #include "env.h"
extern const uint8_t __spslr_program[]; #include "spslr_list_link.h"
static int spslr_do(const struct SPSLR_INST* inst) { #define SPSLR_SANITY_CHECK
if (!inst)
return -1;
static uint32_t pending_fields = 0; static void spslr_selfpatch_load_targets(void);
static uint32_t pending_fields_target = 0; static void spslr_selfpatch_randomize_targets(void);
static void spslr_selfpatch_patch_dpins(void);
static void spslr_selfpatch_patch_dpin(void* addr, uint32_t target);
static void spslr_selfpatch_patch_ipins(void);
if (pending_fields) { static void reorder_object(void* dst, const void* src, uint32_t target);
if (inst->op != SPSLR_FIELD) { static int64_t spslr_calculate_ipin_value(uint32_t start);
fprintf(stderr, "spslr_do encountered non field instruction where a field instruction was expected\n");
return -1; void spslr_selfpatch(void) {
spslr_selfpatch_load_targets();
spslr_selfpatch_randomize_targets();
spslr_selfpatch_patch_dpins();
spslr_selfpatch_patch_ipins();
spslr_clear_targets();
}
void spslr_selfpatch_load_targets(void) {
for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) {
const struct spslr_target* t = &spslr_targets[tidx];
#ifdef SPSLR_SANITY_CHECK
if (t->fieldoff + t->fieldcnt > spslr_target_field_cnt)
spslr_env_panic("target field offset and count reference invalid fields");
#endif
if (spslr_register_target(tidx, t->size, t->fieldcnt) < 0)
spslr_env_panic("failed to register target");
for (uint32_t fidx = 0; fidx < t->fieldcnt; fidx++) {
const struct spslr_target_field* f = &spslr_target_fields[t->fieldoff + fidx];
#ifdef SPSLR_SANITY_CHECK
if (f->offset + f->size > t->size)
spslr_env_panic("target field resides beyond target size");
if (f->offset % f->alignment != 0)
spslr_env_panic("target field is misaligned");
#endif
if (spslr_register_target_field(tidx, f->offset, f->size, f->alignment, f->flags) < 0)
spslr_env_panic("failed to register target field");
} }
pending_fields--;
} else if (inst->op == SPSLR_FIELD) {
fprintf(stderr, "spslr_do encountered field instruction where none was expected\n");
return -1;
}
switch (inst->op) {
case SPSLR_TARGET:
pending_fields = inst->op2.target_fieldcnt;
pending_fields_target = inst->op0.target_uid;
return spslr_target(inst->op0.target_uid, inst->op1.target_size, inst->op2.target_fieldcnt);
case SPSLR_FIELD:
return spslr_field(pending_fields_target, inst->op0.field_offset, inst->op1.field_size,
inst->op2.field_alignment, inst->op3.field_flags);
case SPSLR_RANDOMIZE:
return spslr_randomize(inst->op0.randomize_target);
case SPSLR_IPATCH:
return spslr_ipatch((void*)(uintptr_t)inst->op0.ipatch_ptr, inst->op1.ipatch_size,
inst->op2.ipatch_target, inst->op3.ipatch_field);
case SPSLR_DPATCH:
return spslr_dpatch((void*)(uintptr_t)inst->op0.dpatch_ptr, inst->op1.dpatch_target);
default:
return -1;
} }
} }
void spslr_selfpatch() { void spslr_selfpatch_randomize_targets(void) {
const uint8_t* pc = __spslr_program; for (uint32_t tidx = 0; tidx < spslr_target_cnt; tidx++) {
if (spslr_randomize(tidx) < 0)
spslr_env_panic("failed to randomize target");
}
}
int sz; void spslr_selfpatch_patch_dpins(void) {
struct SPSLR_INST inst; for (uint32_t dpidx = 0; dpidx < spslr_dpin_cnt; dpidx++) {
while ((sz = spslr_inst_load(&inst, pc)) > 0) { const struct spslr_dpin* dp = &spslr_dpins[dpidx];
if (inst.op == SPSLR_EXIT) { spslr_selfpatch_patch_dpin((void*)dp->addr, dp->target);
spslr_targets_clear(); }
return; }
void reorder_object(void* dst, const void* src, uint32_t target) {
uint32_t field_count;
if (spslr_get_target_fieldcnt(target, &field_count))
spslr_env_panic("failed to get target field count");
const uint8_t* src_countable = (const uint8_t*)src;
uint8_t* dst_countable = (uint8_t*)dst;
for (uint32_t i = 0; i < field_count; i++) {
uint32_t field_offset, field_size, field_initial_offset;
if (spslr_get_target_field_ordered(target, i, &field_offset, &field_size, &field_initial_offset))
spslr_env_panic("failed to get ordered field descriptor");
spslr_env_memcpy(dst_countable + field_offset, src_countable + field_initial_offset, field_size);
}
}
void spslr_selfpatch_patch_dpin(void* addr, uint32_t target) {
#ifdef SPSLR_SANITY_CHECK
if (target >= spslr_target_cnt)
spslr_env_panic("dpin refers to invalid target");
#endif
const struct spslr_target* t = &spslr_targets[target];
void* reorder_buffer = spslr_env_malloc(t->size);
spslr_env_memset(reorder_buffer, 0, t->size);
reorder_object(reorder_buffer, addr, target);
spslr_env_poke_data(addr, reorder_buffer, t->size);
spslr_env_free(reorder_buffer);
}
void spslr_selfpatch_patch_ipins(void) {
for (uint32_t ipidx = 0; ipidx < spslr_ipin_cnt; ipidx++) {
const struct spslr_ipin* ip = &spslr_ipins[ipidx];
int64_t value = spslr_calculate_ipin_value(ip->program);
switch (ip->size) {
case 1:
spslr_env_poke_text_8((void*)ip->addr, (uint8_t)value);
break;
case 2:
spslr_env_poke_text_64((void*)ip->addr, (uint16_t)value);
break;
case 4:
spslr_env_poke_text_32((void*)ip->addr, (uint32_t)value);
break;
case 8:
spslr_env_poke_text_64((void*)ip->addr, (uint64_t)value);
break;
#ifdef SPSLR_SANITY_CHECK
default:
spslr_env_panic("invalid ipin size");
#endif
} }
}
}
if (spslr_do(&inst) < 0) { int64_t spslr_calculate_ipin_value(uint32_t start) {
fprintf(stderr, "spslr_selfpatch failed to execute an instruction\n"); int64_t res = 0;
exit(1);
uint32_t pc = start;
while (true) {
#ifdef SPSLR_SANITY_CHECK
if (pc >= spslr_ipin_op_cnt)
spslr_env_panic("ipin op out of bounds");
#endif
const struct spslr_ipin_op* op = &spslr_ipin_ops[pc++];
switch (op->code) {
case SPSLR_IPIN_OP_PATCH:
break;
case SPSLR_IPIN_OP_ADD_INITIAL_OFFSET:
{
uint32_t initial_offset;
if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target,
op->op1.add_initial_offset_field, NULL, NULL, &initial_offset))
spslr_env_panic("failed to get initial field offset");
res += initial_offset;
}
continue;
case SPSLR_IPIN_OP_ADD_OFFSET:
{
uint32_t offset;
if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target,
op->op1.add_initial_offset_field, &offset, NULL, NULL))
spslr_env_panic("failed to get initial field offset");
res += offset;
}
continue;
case SPSLR_IPIN_OP_SUB_INITIAL_OFFSET:
{
uint32_t initial_offset;
if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target,
op->op1.add_initial_offset_field, NULL, NULL, &initial_offset))
spslr_env_panic("failed to get initial field offset");
res -= initial_offset;
}
continue;
case SPSLR_IPIN_OP_SUB_OFFSET:
{
uint32_t offset;
if (spslr_get_target_field_ordered(op->op0.add_initial_offset_target,
op->op1.add_initial_offset_field, &offset, NULL, NULL))
spslr_env_panic("failed to get initial field offset");
res -= offset;
}
continue;
case SPSLR_IPIN_OP_ADD_CONST:
res += op->op0.add_const_value;
continue;
#ifdef SPSLR_SANITY_CHECK
default:
spslr_env_panic("invalid ipin op");
#endif
} }
pc += sz;
} }
fprintf(stderr, "spslr_selfpatch encountered invalid instruction\n"); return res;
exit(1);
} }

View File

@ -0,0 +1,65 @@
#ifndef SPSLR_LIST_H
#define SPSLR_LIST_H
#include <stdint.h>
#define __packed __attribute__((packed))
#define SPSLR_IPIN_OP_PATCH 1
#define SPSLR_IPIN_OP_ADD_INITIAL_OFFSET 2
#define SPSLR_IPIN_OP_SUB_INITIAL_OFFSET 3
#define SPSLR_IPIN_OP_ADD_OFFSET 4
#define SPSLR_IPIN_OP_SUB_OFFSET 5
#define SPSLR_IPIN_OP_ADD_CONST 6
#define SPSLR_FLAG_FIELD_FIXED 1
struct spslr_target {
uint32_t size;
uint32_t fieldcnt;
uint32_t fieldoff; // Offset into spslr_target_field array
} __packed;
struct spslr_target_field {
uint32_t offset;
uint32_t size;
uint32_t alignment;
uint32_t flags;
} __packed;
struct spslr_ipin {
uint64_t addr;
uint32_t size;
uint32_t program; // Index in spslr_ipin_op array
} __packed;
struct spslr_ipin_op {
uint32_t code;
union {
uint32_t patch_unused;
uint32_t add_initial_offset_target;
uint32_t sub_initial_offset_target;
uint32_t add_offset_target;
uint32_t sub_offset_target;
int32_t add_const_value;
} op0;
union {
uint32_t patch_unused;
uint32_t add_initial_offset_field;
uint32_t sub_initial_offset_field;
uint32_t add_offset_field;
uint32_t sub_offset_field;
uint32_t add_const_unused;
} op1;
} __packed;
struct spslr_dpin {
uint64_t addr;
uint32_t target; // Index in spslr_target array
} __packed;
#undef __packed
#endif

View File

@ -0,0 +1,21 @@
#ifndef SPSLR_LIST_LINK_H
#define SPSLR_LIST_LINK_H
#include "spslr_list.h"
extern uint32_t spslr_target_cnt;
extern struct spslr_target spslr_targets[];
extern uint32_t spslr_target_field_cnt;
extern struct spslr_target_field spslr_target_fields[];
extern uint32_t spslr_ipin_cnt;
extern struct spslr_ipin spslr_ipins[];
extern uint32_t spslr_ipin_op_cnt;
extern struct spslr_ipin_op spslr_ipin_ops[];
extern uint32_t spslr_dpin_cnt;
extern struct spslr_dpin spslr_dpins[];
#endif

View File

@ -1,324 +0,0 @@
#ifndef SPSLR_PROGRAM_H
#define SPSLR_PROGRAM_H
#include <stdint.h>
#include <string.h>
#define SPSLR_FLAG_FIELD_FIXED 1
#define OPCODE_SPSLR_TARGET 1
#define OPCODE_SPSLR_FIELD 2
#define OPCODE_SPSLR_RANDOMIZE 3
#define OPCODE_SPSLR_IPATCH 4
#define OPCODE_SPSLR_DPATCH 5
#define OPCODE_SPSLR_EXIT 6
enum SPSLR_OP {
SPSLR_TARGET, // uid, size, field count
SPSLR_FIELD, // offset, size, alignment, flags
SPSLR_RANDOMIZE, // target uid
SPSLR_IPATCH, // ptr, size, target uid, field idx (not offset!)
SPSLR_DPATCH, // ptr, target uid
SPSLR_EXIT
};
struct SPSLR_INST {
enum SPSLR_OP op;
union {
uint32_t target_uid;
uint32_t field_offset;
uint32_t randomize_target;
uint64_t ipatch_ptr;
uint64_t dpatch_ptr;
} op0;
union {
uint32_t target_size;
uint32_t field_size;
uint32_t ipatch_size;
uint32_t dpatch_target;
} op1;
union {
uint32_t target_fieldcnt;
uint32_t field_alignment;
uint32_t ipatch_target;
} op2;
union {
uint32_t field_flags;
uint32_t ipatch_field;
} op3;
};
static inline int spslr_inst_dump_opcode(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
*buf = OPCODE_SPSLR_TARGET; return 1;
case SPSLR_FIELD:
*buf = OPCODE_SPSLR_FIELD; return 1;
case SPSLR_RANDOMIZE:
*buf = OPCODE_SPSLR_RANDOMIZE; return 1;
case SPSLR_IPATCH:
*buf = OPCODE_SPSLR_IPATCH; return 1;
case SPSLR_DPATCH:
*buf = OPCODE_SPSLR_DPATCH; return 1;
case SPSLR_EXIT:
*buf = OPCODE_SPSLR_EXIT; return 1;
default:
return -1;
}
}
static inline int spslr_inst_load_opcode(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (*buf) {
case OPCODE_SPSLR_TARGET:
inst->op = SPSLR_TARGET; return 1;
case OPCODE_SPSLR_FIELD:
inst->op = SPSLR_FIELD; return 1;
case OPCODE_SPSLR_RANDOMIZE:
inst->op = SPSLR_RANDOMIZE; return 1;
case OPCODE_SPSLR_IPATCH:
inst->op = SPSLR_IPATCH; return 1;
case OPCODE_SPSLR_DPATCH:
inst->op = SPSLR_DPATCH; return 1;
case OPCODE_SPSLR_EXIT:
inst->op = SPSLR_EXIT; return 1;
default:
return -1;
}
}
#define DUMP_OP_RET(field) { memcpy(buf, &field, sizeof(field)); return sizeof(field); }
#define LOAD_OP_RET(field) { memcpy(&field, buf, sizeof(field)); return sizeof(field); }
static inline int spslr_inst_dump_op0(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
DUMP_OP_RET(inst->op0.target_uid);
case SPSLR_FIELD:
DUMP_OP_RET(inst->op0.field_offset);
case SPSLR_RANDOMIZE:
DUMP_OP_RET(inst->op0.randomize_target);
case SPSLR_IPATCH:
DUMP_OP_RET(inst->op0.ipatch_ptr);
case SPSLR_DPATCH:
DUMP_OP_RET(inst->op0.dpatch_ptr);
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_load_op0(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
LOAD_OP_RET(inst->op0.target_uid);
case SPSLR_FIELD:
LOAD_OP_RET(inst->op0.field_offset);
case SPSLR_RANDOMIZE:
LOAD_OP_RET(inst->op0.randomize_target);
case SPSLR_IPATCH:
LOAD_OP_RET(inst->op0.ipatch_ptr);
case SPSLR_DPATCH:
LOAD_OP_RET(inst->op0.dpatch_ptr);
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_dump_op1(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
DUMP_OP_RET(inst->op1.target_size);
case SPSLR_FIELD:
DUMP_OP_RET(inst->op1.field_size);
case SPSLR_IPATCH:
DUMP_OP_RET(inst->op1.ipatch_size);
case SPSLR_DPATCH:
DUMP_OP_RET(inst->op1.dpatch_target);
case SPSLR_RANDOMIZE:
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_load_op1(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
LOAD_OP_RET(inst->op1.target_size);
case SPSLR_FIELD:
LOAD_OP_RET(inst->op1.field_size);
case SPSLR_IPATCH:
LOAD_OP_RET(inst->op1.ipatch_size);
case SPSLR_DPATCH:
LOAD_OP_RET(inst->op1.dpatch_target);
case SPSLR_RANDOMIZE:
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_dump_op2(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
DUMP_OP_RET(inst->op2.target_fieldcnt);
case SPSLR_FIELD:
DUMP_OP_RET(inst->op2.field_alignment);
case SPSLR_IPATCH:
DUMP_OP_RET(inst->op2.ipatch_target);
case SPSLR_DPATCH:
case SPSLR_RANDOMIZE:
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_load_op2(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_TARGET:
LOAD_OP_RET(inst->op2.target_fieldcnt);
case SPSLR_FIELD:
LOAD_OP_RET(inst->op2.field_alignment);
case SPSLR_IPATCH:
LOAD_OP_RET(inst->op2.ipatch_target);
case SPSLR_DPATCH:
case SPSLR_RANDOMIZE:
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_dump_op3(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_FIELD:
DUMP_OP_RET(inst->op3.field_flags);
case SPSLR_IPATCH:
DUMP_OP_RET(inst->op3.ipatch_field);
case SPSLR_TARGET:
case SPSLR_DPATCH:
case SPSLR_RANDOMIZE:
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_load_op3(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf)
return -1;
switch (inst->op) {
case SPSLR_FIELD:
LOAD_OP_RET(inst->op3.field_flags);
case SPSLR_IPATCH:
LOAD_OP_RET(inst->op3.ipatch_field);
case SPSLR_TARGET:
case SPSLR_DPATCH:
case SPSLR_RANDOMIZE:
case SPSLR_EXIT:
return 0;
default:
return -1;
}
}
static inline int spslr_inst_dump(const struct SPSLR_INST* inst, uint8_t* buf) {
if (!inst || !buf)
return -1;
int opcode_sz, op0_sz, op1_sz, op2_sz, op3_sz;
if ((opcode_sz = spslr_inst_dump_opcode(inst, buf)) < 0)
return -1;
buf += opcode_sz;
if ((op0_sz = spslr_inst_dump_op0(inst, buf)) < 0)
return -1;
buf += op0_sz;
if ((op1_sz = spslr_inst_dump_op1(inst, buf)) < 0)
return -1;
buf += op1_sz;
if ((op2_sz = spslr_inst_dump_op2(inst, buf)) < 0)
return -1;
buf += op2_sz;
if ((op3_sz = spslr_inst_dump_op3(inst, buf)) < 0)
return -1;
buf += op3_sz;
return opcode_sz + op0_sz + op1_sz + op2_sz + op3_sz;
}
static inline int spslr_inst_load(struct SPSLR_INST* inst, const uint8_t* buf) {
if (!inst || !buf)
return -1;
int opcode_sz, op0_sz, op1_sz, op2_sz, op3_sz;
if ((opcode_sz = spslr_inst_load_opcode(inst, buf)) < 0)
return -1;
buf += opcode_sz;
if ((op0_sz = spslr_inst_load_op0(inst, buf)) < 0)
return -1;
buf += op0_sz;
if ((op1_sz = spslr_inst_load_op1(inst, buf)) < 0)
return -1;
buf += op1_sz;
if ((op2_sz = spslr_inst_load_op2(inst, buf)) < 0)
return -1;
buf += op2_sz;
if ((op3_sz = spslr_inst_load_op3(inst, buf)) < 0)
return -1;
buf += op3_sz;
return opcode_sz + op0_sz + op1_sz + op2_sz + op3_sz;
}
#endif

View File

@ -1,5 +1,6 @@
#include "targets.h" #include "targets.h"
#include "spslr_program.h"
#include "spslr_list.h"
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
@ -96,14 +97,14 @@ static void clear_targets() {
targets = NULL; targets = NULL;
} }
int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) { int spslr_register_target(uint32_t uid, uint32_t size, uint32_t fieldcnt) {
if (find_target(uid)) if (find_target(uid))
return -1; return -1;
return add_target(uid, size, fieldcnt); return add_target(uid, size, fieldcnt);
} }
int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags) { int spslr_register_target_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags) {
struct Target* t = find_target(target); struct Target* t = find_target(target);
if (!t) if (!t)
return -1; return -1;
@ -380,30 +381,39 @@ int spslr_get_target_size(uint32_t target, uint32_t* size) {
int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt) { int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt) {
const struct Target* t = find_target(target); const struct Target* t = find_target(target);
if (!t || !cnt) if (!t)
return -1; return -1;
*cnt = t->field_count; if (cnt)
*cnt = t->field_count;
return 0; return 0;
} }
int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset, int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset,
uint32_t* size, uint32_t* initial_offset) { uint32_t* size, uint32_t* initial_offset) {
const struct Target* t = find_target(target); const struct Target* t = find_target(target);
if (!t || !offset || !size || !initial_offset) if (!t)
return -1; return -1;
if (field >= t->field_count) if (field >= t->field_count)
return -1; return -1;
const struct Field* f = &t->fields[field]; const struct Field* f = &t->fields[field];
*offset = f->offset;
*size = f->size; if (offset)
*initial_offset = f->initial_offset; *offset = f->offset;
if (size)
*size = f->size;
if (initial_offset)
*initial_offset = f->initial_offset;
return 0; return 0;
} }
void spslr_targets_clear() { void spslr_clear_targets() {
clear_targets(); clear_targets();
} }

View File

@ -3,8 +3,8 @@
#include <stdint.h> #include <stdint.h>
int spslr_target(uint32_t uid, uint32_t size, uint32_t fieldcnt); int spslr_register_target(uint32_t uid, uint32_t size, uint32_t fieldcnt);
int spslr_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags); int spslr_register_target_field(uint32_t target, uint32_t offset, uint32_t size, uint32_t alignment, uint32_t flags);
int spslr_randomize(uint32_t target); int spslr_randomize(uint32_t target);
int spslr_get_randomized_field_offset(uint32_t target, uint32_t field, uint32_t* offset); int spslr_get_randomized_field_offset(uint32_t target, uint32_t field, uint32_t* offset);
@ -13,6 +13,6 @@ int spslr_get_target_fieldcnt(uint32_t target, uint32_t* cnt);
int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset, int spslr_get_target_field_ordered(uint32_t target, uint32_t field, uint32_t* offset,
uint32_t* size, uint32_t* initial_offset); uint32_t* size, uint32_t* initial_offset);
void spslr_targets_clear(); void spslr_clear_targets();
#endif #endif