Add tilde

This commit is contained in:
gingerBill
2023-07-08 11:54:34 +01:00
parent 3072479c3c
commit d7af6de9b9
6 changed files with 1823 additions and 0 deletions
+1101
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+330
View File
@@ -0,0 +1,330 @@
// PE/COFF is the executable/object format used by Microsoft.
#ifndef TB_COFF_H
#define TB_COFF_H
#include "tb_formats.h"
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
#define IMAGE_SYM_CLASS_EXTERNAL 0x0002
#define IMAGE_SYM_CLASS_STATIC 0x0003
#define IMAGE_SYM_CLASS_LABEL 0x0006
#define IMAGE_SYM_CLASS_FILE 0x0067
#define IMAGE_SYM_CLASS_SECTION 0x0068
#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_REL_AMD64_ADDR64 0x0001
#define IMAGE_REL_AMD64_ADDR32 0x0002
#define IMAGE_REL_AMD64_ADDR32NB 0x0003
#define IMAGE_REL_AMD64_REL32 0x0004
#define IMAGE_REL_AMD64_REL32_1 0x0005
#define IMAGE_REL_AMD64_REL32_2 0x0006
#define IMAGE_REL_AMD64_REL32_3 0x0007
#define IMAGE_REL_AMD64_REL32_4 0x0008
#define IMAGE_REL_AMD64_REL32_5 0x0009
#define IMAGE_REL_AMD64_SECTION 0x000A
#define IMAGE_REL_AMD64_SECREL 0x000B
#define IMAGE_SCN_LNK_REMOVE 0x00000800
#define IMAGE_SCN_LNK_COMDAT 0x00001000
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
typedef enum {
TB_COFF_SECTION_NO_PAD = 0x00000008,
TB_COFF_SECTION_CODE = 0x00000020,
TB_COFF_SECTION_INIT = 0x00000040,
TB_COFF_SECTION_UNINIT = 0x00000080,
TB_COFF_SECTION_OTHER = 0x00000100,
TB_COFF_SECTION_INFO = 0x00000200,
TB_COFF_SECTION_REMOVE = 0x00000800,
TB_COFF_SECTION_COMDAT = 0x00001000,
// this is actually a 4bit field
TB_COFF_SECTION_ALIGN = 0x00F00000,
// if we have more than 65535 relocations we do this
TB_COFF_SECTION_RELOC_OVR = 0x00F00000,
// memory flags
TB_COFF_SECTION_DISCARDABLE = 0x02000000,
TB_COFF_SECTION_NOT_CACHED = 0x04000000,
TB_COFF_SECTION_NOT_PAGED = 0x08000000,
TB_COFF_SECTION_SHARED = 0x10000000,
TB_COFF_SECTION_EXECUTE = 0x20000000,
TB_COFF_SECTION_READ = 0x40000000,
TB_COFF_SECTION_WRITE = 0x80000000,
} TB_COFF_SectionFlags;
typedef struct TB_COFF_Parser {
// inputs
TB_Slice name, file;
// results
size_t section_count;
size_t symbol_table, symbol_count;
// private
TB_Slice string_table;
} TB_COFF_Parser;
// fills the parser with results from the COFF header
bool tb_coff_parse_init(TB_COFF_Parser* restrict parser);
bool tb_coff_parse_section(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSection* out_sec);
// how many symbols does this one symbol take up (basically 1 + aux symbols).
// returns 0 if error.
size_t tb_coff_parse_symbol(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSymbol* restrict out_sym);
#endif // TB_COFF_H
#ifdef TB_COFF_IMPL
#include <common.h>
#pragma pack(push, 2)
typedef struct COFF_SectionHeader {
char name[8];
union {
uint32_t physical_address;
uint32_t virtual_size;
} misc;
uint32_t virtual_address;
uint32_t raw_data_size;
uint32_t raw_data_pos;
uint32_t pointer_to_reloc;
uint32_t pointer_to_lineno;
uint16_t num_reloc;
uint16_t num_lineno;
uint32_t characteristics;
} COFF_SectionHeader;
typedef struct COFF_FileHeader {
uint16_t machine;
uint16_t section_count;
uint32_t timestamp;
uint32_t symbol_table;
uint32_t symbol_count;
uint16_t optional_header_size;
uint16_t flags;
} COFF_FileHeader;
typedef struct COFF_Symbol {
union {
uint8_t short_name[8];
uint32_t long_name[2];
};
uint32_t value;
int16_t section_number;
uint16_t type;
uint8_t storage_class;
uint8_t aux_symbols_count;
} COFF_Symbol;
typedef struct COFF_ImageReloc {
union {
uint32_t VirtualAddress;
uint32_t RelocCount;
};
uint32_t SymbolTableIndex;
uint16_t Type;
} COFF_ImageReloc;
#pragma pack(pop)
// sanity checks
static_assert(sizeof(COFF_SectionHeader) == 40, "COFF Section header size != 40 bytes");
static_assert(sizeof(COFF_ImageReloc) == 10, "COFF Image Relocation size != 10 bytes");
static_assert(sizeof(COFF_FileHeader) == 20, "COFF File header size != 20 bytes");
static_assert(sizeof(COFF_Symbol) == 18, "COFF Symbol size != 18 bytes");
bool tb_coff_parse_init(TB_COFF_Parser* restrict parser) {
TB_Slice file = parser->file;
if (file.length < sizeof(COFF_FileHeader)) return false;
COFF_FileHeader* header = (COFF_FileHeader*) &parser->file.data[0];
// locate string table (it spans until the end of the file)
size_t string_table_pos = header->symbol_table + (header->symbol_count * sizeof(COFF_Symbol));
if (file.length < string_table_pos) return false;
parser->symbol_count = header->symbol_count;
parser->symbol_table = header->symbol_table;
parser->section_count = header->section_count;
parser->string_table = (TB_Slice){
.length = file.length - string_table_pos,
.data = &file.data[string_table_pos]
};
return true;
}
static long long tb__parse_decimal_int(size_t n, const char* str) {
const char* end = &str[n];
int result = 0;
while (str != end) {
if (*str < '0' || *str > '9') break;
result *= 10;
result += *str - '0';
str++;
}
return result;
}
bool tb_coff_parse_section(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSection* restrict out_sec) {
TB_Slice file = parser->file;
size_t section_offset = sizeof(COFF_FileHeader) + (i * sizeof(COFF_SectionHeader));
if (file.length < section_offset + sizeof(COFF_SectionHeader)) {
return false;
}
COFF_SectionHeader* sec = (COFF_SectionHeader*) &file.data[section_offset];
*out_sec = (TB_ObjectSection) { .flags = sec->characteristics };
// Parse string table name stuff
if (sec->name[0] == '/') {
// string table access
int offset = tb__parse_decimal_int(7, &sec->name[1]);
if (file.length > offset) {
return false;
}
const uint8_t* data = &parser->string_table.data[offset];
out_sec->name = (TB_Slice){ strlen((const char*) data), data };
} else {
// normal inplace string
size_t len = strlen(sec->name);
out_sec->name = (TB_Slice){ len, (uint8_t*) sec->name };
}
// Parse relocations
if (sec->num_reloc > 0) {
out_sec->relocation_count = sec->num_reloc;
COFF_ImageReloc* src_relocs = (COFF_ImageReloc*) &file.data[sec->pointer_to_reloc];
TB_ObjectReloc* dst_relocs = tb_platform_heap_alloc(sec->num_reloc * sizeof(TB_ObjectReloc));
FOREACH_N(j, 0, sec->num_reloc) {
dst_relocs[j] = (TB_ObjectReloc){ 0 };
switch (src_relocs[j].Type) {
case IMAGE_REL_AMD64_ADDR32NB: dst_relocs[j].type = TB_OBJECT_RELOC_ADDR32NB; break;
case IMAGE_REL_AMD64_ADDR32: dst_relocs[j].type = TB_OBJECT_RELOC_ADDR32; break;
case IMAGE_REL_AMD64_ADDR64: dst_relocs[j].type = TB_OBJECT_RELOC_ADDR64; break;
case IMAGE_REL_AMD64_SECREL: dst_relocs[j].type = TB_OBJECT_RELOC_SECREL; break;
case IMAGE_REL_AMD64_SECTION: dst_relocs[j].type = TB_OBJECT_RELOC_SECTION; break;
case IMAGE_REL_AMD64_REL32:
case IMAGE_REL_AMD64_REL32_1:
case IMAGE_REL_AMD64_REL32_2:
case IMAGE_REL_AMD64_REL32_3:
case IMAGE_REL_AMD64_REL32_4:
case IMAGE_REL_AMD64_REL32_5:
dst_relocs[j].type = TB_OBJECT_RELOC_REL32;
break;
default: tb_todo();
}
if (src_relocs[j].Type >= IMAGE_REL_AMD64_REL32 && src_relocs[j].Type <= IMAGE_REL_AMD64_REL32_5) {
dst_relocs[j].addend = 4 + (src_relocs[j].Type - IMAGE_REL_AMD64_REL32);
}
dst_relocs[j].symbol_index = src_relocs[j].SymbolTableIndex;
dst_relocs[j].virtual_address = src_relocs[j].VirtualAddress;
}
out_sec->relocations = dst_relocs;
}
// Parse virtual region
out_sec->virtual_address = sec->virtual_address;
out_sec->virtual_size = sec->misc.virtual_size;
// Read raw data (if applies)
if (sec->raw_data_size) {
assert(sec->raw_data_pos + sec->raw_data_size < file.length);
out_sec->raw_data = (TB_Slice){ sec->raw_data_size, &file.data[sec->raw_data_pos] };
}
return true;
}
TB_ObjectSymbolType classify_symbol_type(uint16_t st_class) {
switch (st_class) {
case 2: return TB_OBJECT_SYMBOL_EXTERN;
case 3: return TB_OBJECT_SYMBOL_STATIC;
case 6: return TB_OBJECT_SYMBOL_STATIC;
case 0x68: return TB_OBJECT_SYMBOL_SECTION;
case 0x69: return TB_OBJECT_SYMBOL_WEAK_EXTERN;
default: return TB_OBJECT_SYMBOL_UNKNOWN;
}
}
size_t tb_coff_parse_symbol(TB_COFF_Parser* restrict parser, size_t i, TB_ObjectSymbol* restrict out_sym) {
TB_Slice file = parser->file;
size_t symbol_offset = parser->symbol_table + (i * sizeof(COFF_Symbol));
if (file.length < symbol_offset + sizeof(COFF_Symbol)) {
return 0;
}
COFF_Symbol* sym = (COFF_Symbol*) &file.data[symbol_offset];
*out_sym = (TB_ObjectSymbol) {
.ordinal = i,
.type = classify_symbol_type(sym->storage_class),
.section_num = sym->section_number,
.value = sym->value
};
// Parse string table name stuff
if (sym->long_name[0] == 0) {
// string table access (read a cstring)
// TODO(NeGate): bounds check this
const uint8_t* data = &parser->string_table.data[sym->long_name[1]];
out_sym->name = (TB_Slice){ strlen((const char*) data), data };
} else {
// normal inplace string
size_t len = strlen((const char*) sym->short_name);
out_sym->name = (TB_Slice){ len, sym->short_name };
}
// TODO(NeGate): Process aux symbols
if (sym->aux_symbols_count) {
out_sym->extra = &sym[1];
// FOREACH_N(j, 0, sym->aux_symbols_count) {}
}
return sym->aux_symbols_count + 1;
}
#endif // TB_COFF_IMPL
+170
View File
@@ -0,0 +1,170 @@
#ifndef TB_ELF_H
#define TB_ELF_H
#include <stdint.h>
#define TB_EI_MAG0 0
#define TB_EI_MAG1 1
#define TB_EI_MAG2 2
#define TB_EI_MAG3 3
#define TB_EI_CLASS 4 /* Class of machine. */
#define TB_EI_DATA 5 /* Data format. */
#define TB_EI_VERSION 6 /* ELF format version. */
#define TB_EI_OSABI 7 /* Operating system / ABI identification */
#define TB_EI_ABIVERSION 8 /* ABI version */
#define TB_OLD_EI_BRAND 8 /* Start of architecture identification. */
#define TB_EI_PAD 9 /* Start of padding (per SVR4 ABI). */
#define TB_EI_NIDENT 16 /* Size of e_ident array. */
/* Values for e_type. */
#define TB_ET_NONE 0 /* Unknown type. */
#define TB_ET_REL 1 /* Relocatable. */
#define TB_ET_EXEC 2 /* Executable. */
#define TB_ET_DYN 3 /* Shared object. */
#define TB_ET_CORE 4 /* Core file. */
#define TB_ET_LOOS 0xfe00 /* First operating system specific. */
#define TB_ET_HIOS 0xfeff /* Last operating system-specific. */
#define TB_ET_LOPROC 0xff00 /* First processor-specific. */
#define TB_ET_HIPROC 0xffff /* Last processor-specific. */
/* Values for e_machine. */
#define TB_EM_NONE 0 /* Unknown machine. */
#define TB_EM_X86_64 62 /* Advanced Micro Devices x86-64 */
#define TB_EM_AARCH64 183 /* AArch64 (64-bit ARM) */
/* sh_type */
#define TB_SHT_NULL 0 /* inactive */
#define TB_SHT_PROGBITS 1 /* program defined information */
#define TB_SHT_SYMTAB 2 /* symbol table section */
#define TB_SHT_STRTAB 3 /* string table section */
#define TB_SHT_RELA 4 /* relocation section with addends */
#define TB_SHT_NOBITS 8 /* no space section */
/* Flags for sh_flags. */
#define TB_SHF_WRITE 0x1 /* Section contains writable data. */
#define TB_SHF_ALLOC 0x2 /* Section occupies memory. */
#define TB_SHF_EXECINSTR 0x4 /* Section contains instructions. */
#define TB_SHF_MERGE 0x10 /* Section may be merged. */
#define TB_SHF_STRINGS 0x20 /* Section contains strings. */
#define TB_SHF_INFO_LINK 0x40 /* sh_info holds section index. */
#define TB_SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
#define TB_SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
#define TB_SHF_GROUP 0x200 /* Member of section group. */
#define TB_SHF_TLS 0x400 /* Section contains TLS data. */
#define TB_SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
#define TB_SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
/* Values for p_flags. */
#define TB_PF_X 0x1 /* Executable. */
#define TB_PF_W 0x2 /* Writable. */
#define TB_PF_R 0x4 /* Readable. */
#define TB_PF_MASKOS 0x0ff00000 /* Operating system-specific. */
#define TB_PF_MASKPROC 0xf0000000 /* Processor-specific. */
/* Values for p_type. */
#define TB_PT_NULL 0 /* Unused entry. */
#define TB_PT_LOAD 1 /* Loadable segment. */
#define TB_PT_DYNAMIC 2 /* Dynamic linking information segment. */
#define TB_PT_INTERP 3 /* Pathname of interpreter. */
#define TB_PT_NOTE 4 /* Auxiliary information. */
#define TB_PT_SHLIB 5 /* Reserved (not used). */
#define TB_PT_PHDR 6 /* Location of program header itself. */
#define TB_PT_TLS 7 /* Thread local storage segment */
/* Values for relocation */
typedef enum {
TB_ELF_X86_64_NONE = 0,
TB_ELF_X86_64_64 = 1,
TB_ELF_X86_64_PC32 = 2,
TB_ELF_X86_64_GOT32 = 3,
TB_ELF_X86_64_PLT32 = 4,
TB_ELF_X86_64_GOTPCREL = 9,
} TB_ELF_RelocType;
// ST_TYPE
#define TB_ELF64_STT_NOTYPE 0
#define TB_ELF64_STT_OBJECT 1
#define TB_ELF64_STT_FUNC 2
#define TB_ELF64_STT_SECTION 3
// ST_INFO
#define TB_ELF64_STB_LOCAL 0
#define TB_ELF64_STB_GLOBAL 1
#define TB_ELF64_STB_WEAK 2
/* Macros for accessing the fields of st_info. */
#define TB_ELF64_ST_BIND(info) ((info) >> 4)
#define TB_ELF64_ST_TYPE(info) ((info) & 0xf)
#define TB_ELF64_ST_INFO(b, t) (((b) << 4) | ((t) & 0xF))
#define TB_ELF64_R_SYM(i) ((i) >> 32u)
#define TB_ELF64_R_TYPE(i) ((i)&0xffffffffULL)
#define TB_ELF64_R_INFO(s, t) (((uint64_t)(s) << 32ULL) + ((uint64_t)(t) & 0xffffffffULL))
// http://web.mit.edu/freebsd/head/sys/sys/elf64.h
// https://cirosantilli.com/elf-hello-world#minimal-elf-file
// https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
typedef struct {
uint8_t ident[16];
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entry;
uint64_t phoff;
uint64_t shoff;
uint32_t flags;
uint16_t ehsize;
uint16_t phentsize;
uint16_t phnum;
uint16_t shentsize;
uint16_t shnum;
uint16_t shstrndx;
} TB_Elf64_Ehdr;
typedef struct {
uint32_t name;
uint32_t type;
uint64_t flags;
uint64_t addr;
uint64_t offset;
uint64_t size;
uint32_t link;
uint32_t info;
uint64_t addralign;
uint64_t entsize;
} TB_Elf64_Shdr;
// Segment header for ELF64.
typedef struct {
uint32_t type; // Type of segment
uint32_t flags; // Segment flags
uint64_t offset; // File offset where segment is located, in bytes
uint64_t vaddr; // Virtual address of beginning of segment
uint64_t paddr; // Physical addr of beginning of segment (OS-specific)
uint64_t filesz; // Num. of bytes in file image of segment (may be zero)
uint64_t memsz; // Num. of bytes in mem image of segment (may be zero)
uint64_t align; // Segment alignment constraint
} TB_Elf64_Phdr;
typedef struct {
uint32_t name;
uint8_t info;
uint8_t other;
uint16_t shndx;
uint64_t value;
uint64_t size;
} TB_Elf64_Sym;
typedef struct {
uint64_t offset;
uint64_t info;
int64_t addend;
} TB_Elf64_Rela;
typedef struct {
uint64_t offset;
uint64_t info;
} TB_Elf64_Rel;
#endif /* TB_ELF_H */
+132
View File
@@ -0,0 +1,132 @@
// This handles the generalized executable/object format parsing stuff
#ifndef TB_OBJECT_H
#define TB_OBJECT_H
#include <stdint.h>
#include <stddef.h>
typedef enum {
TB_OBJECT_RELOC_NONE, // how?
// Target independent
TB_OBJECT_RELOC_ADDR32,
TB_OBJECT_RELOC_ADDR64, // unsupported on 32bit platforms
TB_OBJECT_RELOC_SECREL,
TB_OBJECT_RELOC_SECTION,
// COFF only
TB_OBJECT_RELOC_ADDR32NB, // Relative virtual address
// x64 only
TB_OBJECT_RELOC_REL32, // relative 32bit displacement
// Aarch64 only
TB_OBJECT_RELOC_BRANCH26, // 26bit displacement for B and BL instructions
TB_OBJECT_RELOC_REL21, // for ADR instructions
// TODO(NeGate): fill in the rest of this later
} TB_ObjectRelocType;
typedef struct {
TB_ObjectRelocType type;
uint32_t symbol_index;
size_t virtual_address;
size_t addend;
} TB_ObjectReloc;
typedef enum {
TB_OBJECT_SYMBOL_UNKNOWN,
TB_OBJECT_SYMBOL_EXTERN, // exported
TB_OBJECT_SYMBOL_WEAK_EXTERN, // weak
TB_OBJECT_SYMBOL_IMPORT, // forward decl
TB_OBJECT_SYMBOL_STATIC, // local
TB_OBJECT_SYMBOL_SECTION, // local
} TB_ObjectSymbolType;
typedef struct {
TB_ObjectSymbolType type;
int section_num;
uint32_t ordinal;
uint32_t value;
TB_Slice name;
// for COFF, this is the auxillary
void* extra;
// this is zeroed out by the loader and left for the user to do crap with
void* user_data;
} TB_ObjectSymbol;
typedef struct {
TB_Slice name;
uint32_t flags;
size_t virtual_address;
size_t virtual_size;
// You can have a virtual size without having a raw
// data size, that's how the BSS section works
TB_Slice raw_data;
size_t relocation_count;
TB_ObjectReloc* relocations;
// this is zeroed out by the loader and left for the user to do crap with
void* user_data;
} TB_ObjectSection;
typedef enum {
TB_OBJECT_FILE_UNKNOWN,
TB_OBJECT_FILE_COFF,
TB_OBJECT_FILE_ELF64
} TB_ObjectFileType;
typedef struct {
TB_ObjectFileType type;
TB_Arch arch;
TB_Slice name;
TB_Slice ar_name;
size_t symbol_count;
TB_ObjectSymbol* symbols;
size_t section_count;
TB_ObjectSection sections[];
} TB_ObjectFile;
////////////////////////////////
// Archive parser
////////////////////////////////
typedef struct {
TB_Slice name;
// if import_name is empty, we're dealing with an object file
TB_Slice import_name;
uint16_t ordinal;
TB_Slice content;
} TB_ArchiveEntry;
typedef struct {
TB_Slice file;
size_t pos;
size_t member_count;
uint32_t* members;
size_t symbol_count;
uint16_t* symbols;
TB_Slice strtbl;
} TB_ArchiveFileParser;
// We do this to parse the header
bool tb_archive_parse(TB_Slice file, TB_ArchiveFileParser* restrict out_parser);
// After that we can enumerate any symbol entries to resolve imports
size_t tb_archive_parse_entries(TB_ArchiveFileParser* restrict parser, size_t i, size_t count, TB_ArchiveEntry* out_entry);
#endif // TB_OBJECT_H
+90
View File
@@ -0,0 +1,90 @@
#ifndef TB_X64_H
#define TB_X64_H
#include <stdint.h>
#include <stdbool.h>
typedef enum {
// uses xmm registers for the reg array
TB_X86_INSTR_XMMREG = (1u << 0u),
// r/m is a memory operand
TB_X86_INSTR_USE_MEMOP = (1u << 1u),
// r/m is a rip-relative address (TB_X86_INSTR_USE_MEMOP is always set when this is set)
TB_X86_INSTR_USE_RIPMEM = (1u << 2u),
// LOCK prefix is present
TB_X86_INSTR_LOCK = (1u << 3u),
// uses a signed immediate
TB_X86_INSTR_IMMEDIATE = (1u << 4u),
// absolute means it's using the 64bit immediate (cannot be applied while a memory operand is active)
TB_X86_INSTR_ABSOLUTE = (1u << 5u),
// set if the r/m can be found on the right hand side
TB_X86_INSTR_DIRECTION = (1u << 6u),
// uses the second data type because the instruction is weird like MOVSX or MOVZX
TB_X86_INSTR_TWO_DATA_TYPES = (1u << 7u)
} TB_X86_InstFlags;
typedef enum {
TB_X86_SEGMENT_DEFAULT = 0,
TB_X86_SEGMENT_ES, TB_X86_SEGMENT_CS,
TB_X86_SEGMENT_SS, TB_X86_SEGMENT_DS,
TB_X86_SEGMENT_GS, TB_X86_SEGMENT_FS,
} TB_X86_Segment;
typedef enum {
TB_X86_TYPE_NONE = 0,
TB_X86_TYPE_BYTE, // 1
TB_X86_TYPE_WORD, // 2
TB_X86_TYPE_DWORD, // 4
TB_X86_TYPE_QWORD, // 8
TB_X86_TYPE_PBYTE, // int8 x 16 = 16
TB_X86_TYPE_PWORD, // int16 x 8 = 16
TB_X86_TYPE_PDWORD, // int32 x 4 = 16
TB_X86_TYPE_PQWORD, // int64 x 2 = 16
TB_X86_TYPE_SSE_SS, // float32 x 1 = 4
TB_X86_TYPE_SSE_SD, // float64 x 1 = 8
TB_X86_TYPE_SSE_PS, // float32 x 4 = 16
TB_X86_TYPE_SSE_PD, // float64 x 2 = 16
TB_X86_TYPE_XMMWORD, // the generic idea of them
} TB_X86_DataType;
typedef struct {
int16_t type;
// registers (there's 4 max taking up 4bit slots each)
uint16_t regs;
uint8_t flags;
// bitpacking amirite
TB_X86_DataType data_type : 4;
TB_X86_DataType data_type2 : 4;
TB_X86_Segment segment : 4;
uint8_t length : 4;
// memory operand
// X86_INSTR_USE_MEMOP
int32_t disp;
// immediate operand
// imm for INSTR_IMMEDIATE
// abs for INSTR_ABSOLUTE
union {
int32_t imm;
uint64_t abs;
};
} TB_X86_Inst;
TB_X86_Inst tb_x86_disasm(size_t length, const uint8_t data[length]);
#endif /* TB_X64_H */