285 lines
6.1 KiB
C
285 lines
6.1 KiB
C
#ifndef SPSLR_PROGRAM_H
|
|
#define SPSLR_PROGRAM_H
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
enum SPSLR_OPCODE {
|
|
SPSLR_TARGET, // uid, size, field count
|
|
SPSLR_FIELD, // offset, size, flags
|
|
SPSLR_RANDOMIZE, // target uid
|
|
SPSLR_MPROT, // ptr, page count, perm
|
|
SPSLR_IPATCH, // ptr, target uid, field idx (not offset!)
|
|
SPSLR_DPATCH, // ptr, target uid
|
|
SPSLR_EXIT
|
|
};
|
|
|
|
struct SPSLR_INST {
|
|
enum SPSLR_OPCODE opcode;
|
|
|
|
union {
|
|
uint32_t target_uid;
|
|
uint32_t field_offset;
|
|
uint32_t randomize_target;
|
|
uint64_t mprot_ptr;
|
|
uint64_t ipatch_ptr;
|
|
uint64_t dpatch_ptr;
|
|
} op0;
|
|
|
|
union {
|
|
uint32_t target_size;
|
|
uint32_t field_size;
|
|
uint32_t mprot_pagecnt;
|
|
uint32_t ipatch_target;
|
|
uint32_t dpatch_target;
|
|
} op1;
|
|
|
|
union {
|
|
uint32_t target_fieldcnt;
|
|
uint32_t field_flags;
|
|
uint8_t mprot_perm;
|
|
uint32_t ipatch_field;
|
|
} op2;
|
|
};
|
|
|
|
static inline int spslr_inst_dump_opcode(const struct SPSLR_INST* inst, uint8_t* buf) {
|
|
if (!inst || !buf)
|
|
return -1;
|
|
|
|
switch (inst->opcode) {
|
|
case SPSLR_TARGET:
|
|
*buf = 1; return 1;
|
|
case SPSLR_FIELD:
|
|
*buf = 2; return 1;
|
|
case SPSLR_RANDOMIZE:
|
|
*buf = 3; return 1;
|
|
case SPSLR_MPROT:
|
|
*buf = 4; return 1;
|
|
case SPSLR_IPATCH:
|
|
*buf = 5; return 1;
|
|
case SPSLR_DPATCH:
|
|
*buf = 6; return 1;
|
|
case SPSLR_EXIT:
|
|
*buf = 7; 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 1:
|
|
inst->opcode = SPSLR_TARGET; return 1;
|
|
case 2:
|
|
inst->opcode = SPSLR_FIELD; return 1;
|
|
case 3:
|
|
inst->opcode = SPSLR_RANDOMIZE; return 1;
|
|
case 4:
|
|
inst->opcode = SPSLR_MPROT; return 1;
|
|
case 5:
|
|
inst->opcode = SPSLR_IPATCH; return 1;
|
|
case 6:
|
|
inst->opcode = SPSLR_DPATCH; return 1;
|
|
case 7:
|
|
inst->opcode = 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->opcode) {
|
|
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_MPROT:
|
|
DUMP_OP_RET(inst->op0.mprot_ptr);
|
|
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->opcode) {
|
|
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_MPROT:
|
|
LOAD_OP_RET(inst->op0.mprot_ptr);
|
|
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->opcode) {
|
|
case SPSLR_TARGET:
|
|
DUMP_OP_RET(inst->op1.target_size);
|
|
case SPSLR_FIELD:
|
|
DUMP_OP_RET(inst->op1.field_size);
|
|
case SPSLR_MPROT:
|
|
DUMP_OP_RET(inst->op1.mprot_pagecnt);
|
|
case SPSLR_IPATCH:
|
|
DUMP_OP_RET(inst->op1.ipatch_target);
|
|
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->opcode) {
|
|
case SPSLR_TARGET:
|
|
LOAD_OP_RET(inst->op1.target_size);
|
|
case SPSLR_FIELD:
|
|
LOAD_OP_RET(inst->op1.field_size);
|
|
case SPSLR_MPROT:
|
|
LOAD_OP_RET(inst->op1.mprot_pagecnt);
|
|
case SPSLR_IPATCH:
|
|
LOAD_OP_RET(inst->op1.ipatch_target);
|
|
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->opcode) {
|
|
case SPSLR_TARGET:
|
|
DUMP_OP_RET(inst->op2.target_fieldcnt);
|
|
case SPSLR_FIELD:
|
|
DUMP_OP_RET(inst->op2.field_flags);
|
|
case SPSLR_MPROT:
|
|
DUMP_OP_RET(inst->op2.mprot_perm);
|
|
case SPSLR_IPATCH:
|
|
DUMP_OP_RET(inst->op2.ipatch_field);
|
|
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->opcode) {
|
|
case SPSLR_TARGET:
|
|
LOAD_OP_RET(inst->op2.target_fieldcnt);
|
|
case SPSLR_FIELD:
|
|
LOAD_OP_RET(inst->op2.field_flags);
|
|
case SPSLR_MPROT:
|
|
LOAD_OP_RET(inst->op2.mprot_perm);
|
|
case SPSLR_IPATCH:
|
|
LOAD_OP_RET(inst->op2.ipatch_field);
|
|
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;
|
|
|
|
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;
|
|
|
|
return opcode_sz + op0_sz + op1_sz + op2_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;
|
|
|
|
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;
|
|
|
|
return opcode_sz + op0_sz + op1_sz + op2_sz;
|
|
}
|
|
|
|
#endif
|