libregexis024/src/libregexis024test/byte_code_disassembler.h

206 lines
8.7 KiB
C
Raw Normal View History

2024-07-28 16:54:57 +00:00
/* This file is used for testing purposes only. Do not copy this file to installation prefix. */
#ifndef LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H
#define LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H
#include "vibe_check.h"
#include <libregexis024vm/vm_opcodes.h>
#include <libregexis024vm/utils.h>
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
#include <inttypes.h>
// TODO: apply here my new change in near pointer size
struct landing_place_resolvance{
size_t name_id;
bool visited = false;
landing_place_resolvance() = default;
landing_place_resolvance(size_t nameId, bool visited) : name_id(nameId), visited(visited) {}
};
void print_disassembly(size_t prgSize, uint8_t* prg){
std::vector<std::string> names = {
"Александр", "Мария", "Иван", "Анна", "Дмитрий", "Екатерина", "Алексей",
"Ольга", "Михаил", "София", "Сергей", "Анастасия", "Артем", "Виктория",
"Андрей", "Елена", "Максим", "Алиса", "Павел", "Наталья", "Денис", "Юлия",
"Владимир", "Маргарита", "Никита", "Дарья", "Илья", "Алина", "Роман", "Евгения",
"Кирилл", "Елизавета", "Антон", "Татьяна", "Владислав", "Валерия", "Георгий",
"Ксения", "Арсений", "Милана", "Даниил", "Вероника", "Тимофей", "Арина",
"Николай", "Кристина", "Степан", "Алёна", "Игорь", "Алла", "Григорий", "Ева",
"Олег", "Яна", "Семен", "Марина", "Федор", "Светлана", "Василий", "Людмила"
};
uint64_t used_names = 0;
/* From program position -> to names[ind] & */
std::map<regex_near_ptr_t, landing_place_resolvance> bookmarks;
regex_near_ptr_t IP = 0;
auto check_inboundness = [&](int region){
if (!vmprog_check_inboundness(prgSize, IP, region))
exitf("This program can't be decomposed into commands in a trivial way");
};
auto extract_b = [&]() -> uint8_t{
check_inboundness(1);
return vmprog_extract_b(&IP, prg);
};
auto extract_w = [&]() -> uint16_t {
check_inboundness(2);
return vmprog_extract_w(&IP, prg);
};
auto extract_dw = [&]() -> uint32_t {
check_inboundness(4);
return vmprog_extract_dw(&IP, prg);
};
auto extract_qw = [&]() -> uint64_t {
check_inboundness(8);
return vmprog_extract_qw(&IP, prg);
};
auto extract_instruction = [&]() -> uint8_t{
return extract_b();
};
auto extract_sslot_id = [&]() -> regex_sslot_id_t{
return extract_dw();
};
auto extract_near_pointer = [&]() -> regex_near_ptr_t{
return extract_qw();
};
auto extract_track_array_index = [&]() -> regex_tai_t{
return extract_w();
};
bool second_phase = false;
auto fph_register_landing = [&](regex_near_ptr_t pos){
if (!second_phase){
if (bookmarks.count(pos) == 0){
if (used_names == names.size())
names.push_back("Закладка_" + std::to_string(used_names));
bookmarks.insert({pos, {used_names, false}});
used_names++;
}
}
};
auto get_bookmark_in_2phase = [&](regex_near_ptr_t pos) -> std::string {
if (bookmarks.count(pos) == 0)
exitf("bruh");
return names[bookmarks[pos].name_id];
};
auto one_reading = [&](){
while (IP < prgSize) {
regex_near_ptr_t start_pos = IP;
if (second_phase){
if (bookmarks.count(IP) != 0){
printf("%s:\n", get_bookmark_in_2phase(IP).c_str());
bookmarks[IP].visited = true;
}
}
uint8_t opcode = extract_instruction();
switch (opcode) {
#define secPrint(fmt, ...) if (second_phase) {printf("% 3lu) " fmt, start_pos, __VA_ARGS__);} } break;
#define secPrintNoArg(str) if (second_phase) {printf("% 3lu) " str, start_pos);} } break;
#define instCase(oper_code) case regex024_opcodes::oper_code: {
#define jcMess(cond, sz_uppercase, x_t, extract_method, printf_sign) \
instCase(JC ## cond ## _ ## sz_uppercase) \
x_t x = extract_method(); \
regex_near_ptr_t dest = extract_near_pointer(); \
fph_register_landing(dest); \
secPrint("JC" #cond "_" #sz_uppercase " %" printf_sign " $%s\n", x, get_bookmark_in_2phase(dest).c_str())
#define jcCacaphony(cond) \
jcMess(cond, B, uint8_t, extract_b, PRIu8) \
jcMess(cond, W, uint16_t, extract_w, PRIu16) \
jcMess(cond, DW, uint32_t, extract_dw, PRIu32) \
jcMess(cond, QW, uint64_t, extract_qw, PRIu64)
#define simpleDimple(name) instCase(name) secPrintNoArg(#name "\n")
instCase(READ)
uint32_t ssid = extract_sslot_id();
secPrint("READ %u\n", ssid)
simpleDimple(READZ)
instCase(JUMP)
uint32_t dest = extract_near_pointer();
fph_register_landing(dest);
secPrint("JUMP $%s\n", get_bookmark_in_2phase(dest).c_str())
jcCacaphony(EQUAL)
jcCacaphony(LESS)
jcCacaphony(GRTR)
instCase(FORK)
uint32_t ssid = extract_sslot_id();
regex_near_ptr_t dest = extract_near_pointer();
fph_register_landing(dest);
secPrint("FORK %u $%s\n", ssid, get_bookmark_in_2phase(dest).c_str())
simpleDimple(MATCH)
simpleDimple(DIE)
instCase(PARAM_READ_SS_NUMBER)
regex_sslot_id_t ssid_max_plus_one = extract_sslot_id();
secPrint("PARAM_READ_SS_NUMBER %u\n", ssid_max_plus_one)
instCase(PARAM_FORK_SS_NUMBER)
regex_sslot_id_t ssid_max_plus_one = extract_sslot_id();
secPrint("PARAM_FORK_SS_NUMBER %u\n", ssid_max_plus_one)
instCase(PARAM_SELARR_LEN)
regex_tai_t tai_max_plus_one = extract_track_array_index();
secPrint("PARAM_SELARR_LEN %hu\n", tai_max_plus_one)
instCase(PARAM_COLSIFTFUNC_SET)
regex_near_ptr_t entry = extract_near_pointer();
fph_register_landing(entry);
secPrint("PARAM_COLSIFTFUNC_SET $%s\n", get_bookmark_in_2phase(entry).c_str())
simpleDimple(PARAM_COLSIFTFUNC_WIPE)
instCase(MSG_MULTISTART_ALLOWED)
uint8_t is_allowed = extract_b();
secPrint("MSG_MULTISTART_ALLOWED %hhu\n", is_allowed)
instCase(MSG_FED_INPUT_EXTENDED)
uint8_t left = extract_b();
uint8_t right = extract_b();
regex_sslot_id_t part = extract_sslot_id();
secPrint("MSG_FED_INPUT_EXTENDED %hhu %hhu %u\n", left, right, part)
instCase(DMOV_RABX_SELARR)
regex_tai_t i = extract_track_array_index();
secPrint("DMOV_RABX_SELARR %hu\n", i)
instCase(DDIST_RABX_SELARR)
regex_tai_t s = extract_track_array_index();
regex_tai_t e = extract_track_array_index();
secPrint("DDIST_RABX_SELARR %hu %hu\n", s, e);
simpleDimple(SIFTPRIOR_MIN_RABX)
simpleDimple(SIFTPRIOR_MAX_RABX)
simpleDimple(SIFT_DONE)
instCase(MOV_COLARR_IMM)
regex_tai_t tai = extract_track_array_index();
uint64_t imm = extract_qw();
secPrint("MOV_COLARR_IMM %hu %lu\n", tai, imm);
instCase(MOV_COLARR_BTPOS)
regex_tai_t tai = extract_track_array_index();
secPrint("MOV_COLARR_BTPOS %hu\n", tai);
instCase(MOV_SELARR_IMM)
regex_tai_t tai = extract_track_array_index();
uint64_t imm = extract_qw();
secPrint("MOV_SELARR_IMM %hu %lu\n", tai, imm);
instCase(MOV_SELARR_CHPOS)
regex_tai_t tai = extract_track_array_index();
secPrint("MOV_SELARR_CHPOS %hu\n", tai);
simpleDimple(INIT)
simpleDimple(THROW)
default:
exitf("Bad opcode\n");
#undef secPrint
#undef secPrintNoArg
#undef instCase
#undef jcMess
#undef jcCacaphony
#undef simpleDimple
}
}
};
one_reading();
second_phase = true;
IP = 0;
one_reading();
}
#endif //LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H