summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2026-07-09 00:58:20 +0200
committerladevieq <ladevie.quentin@gmail.com>2026-07-09 00:58:20 +0200
commit0379f7634200c35682adb53a6653d441849903ae (patch)
treeb927d39a662df77e0dc95dda109da1303d401e9b
parent3c091fe6eacd542a506a3f8adf1a8bd91e2e34b0 (diff)
Fixed compilation
Add disasm to compiled files Removed dependency to strsafe Detect SIB and displacement bytes correctly
-rw-r--r--build.bat2
-rw-r--r--include/stack_walk.h4
-rw-r--r--include/utils.h21
-rw-r--r--src/disasm.c147
-rw-r--r--src/events.c30
-rw-r--r--src/main.c2
-rw-r--r--src/parser.c27
-rw-r--r--src/pdb.c15
-rw-r--r--src/stack_walk.c2
-rw-r--r--src/utils.c193
10 files changed, 299 insertions, 144 deletions
diff --git a/build.bat b/build.bat
index 88a175b..cc27d15 100644
--- a/build.bat
+++ b/build.bat
@@ -35,7 +35,7 @@ if "%release%"=="0" (
set L_FLAGS=/DEBUG %L_FLAGS%
)
-set src=main utils events module parser pdb hashmap stack_walk
+set src=main utils events module parser pdb hashmap stack_walk disasm
:: DBG
:: Compile
diff --git a/include/stack_walk.h b/include/stack_walk.h
index 783cbb9..f6f0f5b 100644
--- a/include/stack_walk.h
+++ b/include/stack_walk.h
@@ -1,3 +1,7 @@
#pragma once
+#include "module.h"
+
extern void walk_stack(void* ctx);
+
+extern struct module* get_addr_module(u64 addr);
diff --git a/include/utils.h b/include/utils.h
index 738ba9f..9f04262 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -8,16 +8,23 @@
#define assert(x) (x)
#endif
-void print(const char* format, ...);
+#define TRUE 1
+#define FALSE 0
-u8 is_alpha(char c);
+extern void print(const char* format, ...);
-u8 is_decimal_digit(char c);
+extern u8 is_alpha(char c);
-u8 is_hexadecimal_digit(char c);
+extern u8 is_decimal_digit(char c);
-void u64toa(u64 number, char* str, u32 base);
+extern u8 is_hexadecimal_digit(char c);
-u64 atou64(const char* str, u32 len);
+extern size_t str_len(const char* str, size_t max_size);
-u8 read_memory(const void* addr, void* buffer, size_t size);
+extern void str_cat(char* out, const char* str, size_t c_str);
+
+extern void u64toa(u64 number, char* str, u32 base);
+
+extern u64 atou64(const char* str, u32 len);
+
+extern u8 read_memory(const void* addr, void* buffer, size_t size);
diff --git a/src/disasm.c b/src/disasm.c
index 62f3fab..2f59dfe 100644
--- a/src/disasm.c
+++ b/src/disasm.c
@@ -1,3 +1,8 @@
+#include <Windows.h>
+
+#include "disasm.h"
+#include "utils.h"
+
const u8 MAX_LEGACY_PREFIXES = 4U;
const u8 legacy_prefixes[] = {
// Operand-size override
@@ -108,7 +113,7 @@ struct opcode {
const struct opcode rep_f3_opcode_map[] = {
{ "PAUSE", { .src = None }, { .src = None }}, // 0x90
-}
+};
const struct opcode primary_opcode_map[256U] = {
{ "ADD", { .src = TYPE_E, .type = TYPE_BYTE }, { .src = ModRM_Reg, .type = TYPE_BYTE }},
@@ -516,6 +521,13 @@ const struct opcode group_11[2U] = {
{ "MOV", { .src = TYPE_E, .type = TYPE_v }, { .src = Imm, .type = TYPE_z }},
};
+const u8 mod_to_disp_size[4U] = {
+ 4U,
+ 1U,
+ 4U,
+ 0U,
+};
+
u8 is_legacy_prefix(u8 byte) {
for (u8 index = 0U; index < sizeof(legacy_prefixes); index++) {
if (byte == legacy_prefixes[index]) {
@@ -599,7 +611,7 @@ u64 get_immediate(u8** bytes, enum DATA_TYPE type, u8 operand_effective_size) {
return imm;
}
-u8 get_immediate_size(enum OPERAND_TYPE type, u8 operand_effective_size) {
+u8 get_immediate_size(enum DATA_TYPE type, u8 operand_effective_size) {
if (type == TYPE_BYTE) {
return 1U;
} else if (type == TYPE_WORD) {
@@ -617,16 +629,16 @@ u8 get_immediate_size(enum OPERAND_TYPE type, u8 operand_effective_size) {
}
#define MODRM_MOD(ModRM) (ModRM >> 6U)
-#define MODRM_REG(ModRM) (ModRM & 0b00111000) >> 0x3
+#define MODRM_REG(ModRM) ((ModRM & 0b00111000) >> 0x3)
#define MODRM_RM(ModRM) (ModRM & 0b00000111)
#define SIB_SCALE(SIB) (SIB >> 6U)
-#define SIB_INDEX(SIB) (SIB & 0b00111000) >> 0x3
+#define SIB_INDEX(SIB) ((SIB & 0b00111000) >> 0x3)
#define SIB_BASE(SIB) (SIB & 0b00000111)
-#define REXW(REX) (REX & 0b00001000) >> 3U
-#define REXR(REX) (REX & 0b00000100) >> 2U
-#define REXX(REX) (REX & 0b00000010) >> 1U
+#define REXW(REX) ((REX & 0b00001000) >> 3U)
+#define REXR(REX) ((REX & 0b00000100) >> 2U)
+#define REXX(REX) ((REX & 0b00000010) >> 1U)
#define REXB(REX) (REX & 0b00000001)
// void unassemble(CONTEXT* ctx, u32 count) {
@@ -679,24 +691,31 @@ void unassemble(u8* start, u64 size) {
op = &primary_opcode_map[op_byte];
}
- u8 has_displacement = FALSE;
+ u8 disp_bytes_count = 0U;
u8 has_src_SIB = FALSE;
u8 has_dst_SIB = FALSE;
if (op->src_operand.src & (TYPE_E | ModRM_Reg) || op->dst_operand.src & (TYPE_E | ModRM_Reg)) {
u8 Mod = MODRM_MOD(ModRM);
u8 RM = MODRM_RM(ModRM);
- if (Mod == 0b10 || Mod == 0b01) {
- has_displacement = TRUE;
+ // Table 1-14
+ // Displacement detection
+ if (Mod == 0b00 && RM == 0b101) {
+ disp_bytes_count = mod_to_disp_size[Mod];
+ } else if (Mod != 0b11) {
+ disp_bytes_count = mod_to_disp_size[Mod];
}
- if (Mod != 0b11 && RM == 0b100) { // This may not be the only way to has an SIB byte
+ // SIB detection
+ if (Mod != 0b11 && RM == 0b100) { // This may not be the only way to have an SIB byte
if (op->src_operand.src & (TYPE_E | ModRM_Reg)) {
has_src_SIB = TRUE;
}
if (op->dst_operand.src & (TYPE_E | ModRM_Reg)) {
has_dst_SIB = TRUE;
}
+ // NOTE: We probably can't have both operand needing an SIB byte
+ assert(!(has_src_SIB == has_dst_SIB == TRUE));
}
current_byte++;
@@ -704,14 +723,23 @@ void unassemble(u8* start, u64 size) {
// SIB
u8 SIB = *current_byte;
- if (has_SIB) {
+ if (has_src_SIB || has_dst_SIB) {
+ u8 Mod = MODRM_MOD(ModRM);
+ if (SIB_BASE(SIB)) {
+ disp_bytes_count = mod_to_disp_size[Mod];
+ }
current_byte++;
}
// Displacement bits
- if (has_displacement) {
- // Read displacement bits
- current_byte++;
+ u32 disp = 0U;
+ if (disp_bytes_count) {
+ if (disp_bytes_count == 1U) {
+ disp = *current_byte;
+ } else if (disp_bytes_count == 4U) {
+ disp = *((u32*)current_byte);
+ }
+ current_byte += disp_bytes_count;
}
u64 src_imm = 0U;
@@ -728,56 +756,67 @@ void unassemble(u8* start, u64 size) {
u8 inst_size = (u8)(current_byte - inst_start);
- for (u8 index = 0U; index < inst_size; index++) {
- print("%2xb ", inst_start[index]);
- }
- print("\t\t%s", op->name);
-
- if (op->src_operand.src == Imm) {
- print(" %u", src_imm);
- } else if (op->src_operand.src == ModRM_Reg) {
- u8 Reg = MODRM_REG(ModRM);
- print(" %s", ModRM_registers[Reg][3U]);
- } else if (op->src_operand.src == TYPE_E) {
- u8 Mod = MODRM_MOD(ModRM);
- u8 RM = MODRM_RM(ModRM);
- if (Mod == 0b11) {
- print(" %s", ModRM_registers[RM][3U]);
+ for (u8 index = 0U; index < 6U; index++) {
+ if (index < inst_size) {
+ print("%.2x ", inst_start[index]);
+ } else {
+ print(" ");
}
}
+ print("%s", op->name);
- if (has_src_SIB) {
- // Read SIB
- i32 scale_factors[4U] = {
- 1, 2, 4, 8,
+ // Src operand
+ {
+ if (op->src_operand.src == Imm) {
+ print(" %u", src_imm);
+ } else if (op->src_operand.src == ModRM_Reg) {
+ u8 Reg = MODRM_REG(ModRM);
+ print(" %s", ModRM_registers[Reg][3U]);
+ } else if (op->src_operand.src == TYPE_E) {
+ u8 Mod = MODRM_MOD(ModRM);
+ u8 RM = MODRM_RM(ModRM);
+ if (Mod == 0b11) {
+ print(" %s", ModRM_registers[RM][3U]);
+ }
}
- effective_address = scale_factors[SIB_SCALE(SIB)] * SIB_INDEX(SIB) + SIB_BASE(SIB) + off;
- }
- if (op->dst_operand.src == Imm) {
- print(" %xu", dst_imm);
+ if (has_src_SIB) {
+ // Read SIB
+ i32 scale_factors[4U] = {
+ 1, 2, 4, 8,
+ };
+ i32 off = 0; // displacement bytes
+ effective_address = scale_factors[SIB_SCALE(SIB)] * SIB_INDEX(SIB) + SIB_BASE(SIB) + off;
+ }
}
- if (has_dst_SIB) {
- // Read SIB
- i32 scale_factors[4U] = {
- 1, 2, 4, 8,
+ // Dst operand
+ {
+ if (op->dst_operand.src == Imm) {
+ print(" %x", dst_imm);
}
- u8 index = SIB_INDEX(SIB);
- if (index != 0b100) {
- print(" [%d * %s", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
- }
+ if (has_dst_SIB) {
+ // Read SIB
+ i32 scale_factors[4U] = {
+ 1, 2, 4, 8,
+ };
- u8 base = SIB_BASE(SIB);
- if (base != 0b101 && MODRM_MOD(ModRM) != 0U) {
- print(" + %s", SIB_base_registers[base]);
- }
+ u8 index = SIB_INDEX(SIB);
+ if (index != 0b100) {
+ print(" [%d * %s", scale_factors[SIB_SCALE(SIB)], SIB_index_registers[index]);
+ }
- if (has_displacement) {
- print("+ %d]", );
- } else {
- print("]");
+ u8 base = SIB_BASE(SIB);
+ if (base != 0b101 && MODRM_MOD(ModRM) != 0U) {
+ print(" + %s", SIB_base_registers[base]);
+ }
+
+ if (disp_bytes_count) {
+ print("+ %d]", disp);
+ } else {
+ print("]");
+ }
}
}
diff --git a/src/events.c b/src/events.c
index 7492597..a1dd6ce 100644
--- a/src/events.c
+++ b/src/events.c
@@ -6,6 +6,8 @@
u8 expect_single_step = FALSE;
extern DEBUG_EVENT dbg_event;
+extern u8* string_stack_base;
+extern u8* string_stack_current;
const char* dummy_name = "Function_dummy_name";
@@ -58,8 +60,8 @@ void load_symbols(const void* base_addr, struct module* module) {
return;
}
- print("Module Base Address %xu\n", base_addr);
- print("Module Size %xu\n", module->nt_header.OptionalHeader.SizeOfImage);
+ print("Module Base Address %x\n", base_addr);
+ print("Module Size %x\n", module->nt_header.OptionalHeader.SizeOfImage);
#ifndef HASHMAP
// Exception directory
@@ -135,13 +137,13 @@ void load_symbols(const void* base_addr, struct module* module) {
assert(string_stack_current - 16U * 4096U < string_stack_base);
void* name_address = (void*)((u64)module->base_addr + names_address[name_index]);
read_memory(name_address, name, 256U);
- StringCchLengthA((PCNZCH)name, STRSAFE_MAX_CCH, &length);
+ length = str_len((const char*)name, 256U);
break;
}
}
if (name_index == export_dir.NumberOfNames) {
- print("%u : Function has no name, function address %xu\n", i, addresses[i]);
+ print("%u : Function has no name, function address %x\n", i, addresses[i]);
continue;
}
@@ -156,7 +158,7 @@ void load_symbols(const void* base_addr, struct module* module) {
string_stack_current[length] = '\0';
module->functions_name[global_functions_index] = name;
string_stack_current += length + 1U;
- print("%u : Function name : %s, function address %xu\n", i, name, addresses[i]);
+ print("%u : Function name : %s, function address %x\n", i, name, addresses[i]);
break;
}
}
@@ -185,10 +187,10 @@ void load_symbols(const void* base_addr, struct module* module) {
if (export_dir_start < (void*)func_address && (void*)func_address < export_dir_end) {
print("%u : Fowarded function : %s\n", i, func_name);
} else if (name_index && name_index < export_dir.NumberOfNames) {
- print("%u : Function name : %s, function address %xu\n", i, func_name, addresses[i]);
+ print("%u : Function name : %s, function address %x\n", i, func_name, addresses[i]);
insert_elem(&module->symbols, addresses[i], 0U, name_address);
} else {
- print("%u : Function has no name, function address %xu\n", i, addresses[i]);
+ print("%u : Function has no name, function address %x\n", i, addresses[i]);
insert_elem(&module->symbols, addresses[i], 0U, (u64)dummy_name);
}
}
@@ -282,17 +284,17 @@ void load_symbols(const void* base_addr, struct module* module) {
// if (cur_code->op_info == 0U) {
// u16 size = *(u16*)&u_info->unwind_code[code_index + 1U];
// if (u_info->frame_register) {
- // print("sub rbp %xu\n", size);
+ // print("sub rbp %x\n", size);
// } else {
- // print("sub rsp %xu\n", size);
+ // print("sub rsp %x\n", size);
// }
// code_index++;
// } else {
// u32 size = *(u32*)&u_info->unwind_code[code_index + 1U];
// if (u_info->frame_register) {
- // print("sub rbp %xu\n", size);
+ // print("sub rbp %x\n", size);
// } else {
- // print("sub rsp %xu\n", size);
+ // print("sub rsp %x\n", size);
// }
// code_index += 2U;
// }
@@ -301,14 +303,14 @@ void load_symbols(const void* base_addr, struct module* module) {
// print("alloc small\n");
// u32 size = cur_code->op_info * 8U + 8U;
// if (u_info->frame_register) {
- // print("sub rbp %xu\n", size);
+ // print("sub rbp %x\n", size);
// } else {
- // print("sub rsp %xu\n", size);
+ // print("sub rsp %u\n", size);
// }
// break;
// case UWOP_SET_FPREG:
// print("set frame point reg\n");
- // print("mov rbp rsp - %xu\n", u_info->frame_register_offset * 16U);
+ // print("mov rbp rsp - %u\n", u_info->frame_register_offset * 16U);
// break;
// case UWOP_SAVE_NONVOL:
// print("save non volatile\n");
diff --git a/src/main.c b/src/main.c
index fbefb1d..3ec9631 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,4 @@
#include <Windows.h>
-#include <intrin.h>
-#include <strsafe.h>
#include "types.h"
diff --git a/src/parser.c b/src/parser.c
index 985543b..f6dd074 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,10 +1,9 @@
#include "parser.h"
-#include <Windows.h>
-
#include "utils.h"
#include "module.h"
#include "stack_walk.h"
+#include "disasm.h"
extern u8 expect_single_step;
extern DWORD continue_status;
@@ -243,19 +242,19 @@ void run(struct ast_node* root) {
if (((1ULL << index) & modules_list) == 0U) {
struct module* module = &modules[index];
print("Module Name : %s\n", module->name);
- print("Module Base : %xu\n", module->base_addr);
- print("Module Size : %xu\n\n", module->nt_header.OptionalHeader.SizeOfImage);
+ print("Module Base : %x\n", module->base_addr);
+ print("Module Size : %x\n\n", module->nt_header.OptionalHeader.SizeOfImage);
}
}
} else if (cur_node.token->type == TOKEN_PRINT_REG) {
- print("RIP : %xu\n", ctx.Rip);
- print("RCX : %xu\n", ctx.Rcx);
- print("RDX : %xu\n", ctx.Rdx);
- print("RBX : %xu\n", ctx.Rbx);
- print("RSP : %xu\n", ctx.Rsp);
- print("RBP : %xu\n", ctx.Rbp);
- print("RSI : %xu\n", ctx.Rsi);
- print("RDI : %xu\n", ctx.Rdi);
+ print("RIP : %.12x\n", ctx.Rip);
+ print("RCX : %.12x\n", ctx.Rcx);
+ print("RDX : %.12x\n", ctx.Rdx);
+ print("RBX : %.12x\n", ctx.Rbx);
+ print("RSP : %.12x\n", ctx.Rsp);
+ print("RBP : %.12x\n", ctx.Rbp);
+ print("RSI : %.12x\n", ctx.Rsi);
+ print("RDI : %.12x\n", ctx.Rdi);
process_commands = TRUE;
} else if (cur_node.token->type == TOKEN_STEP_INTO) {
ctx.EFlags |= 0x100; // TRAP_FLAG
@@ -279,7 +278,7 @@ void run(struct ast_node* root) {
if(read_memory((const void*)addr, (void*)buf, size)) {
for (u32 index = 0U; index < size; index += 8U) {
- print("%xb %xb %xb %xb %xb %xb %xb %xb\n", buf[index], buf[index + 1U], buf[index + 2U], buf[index + 3U], buf[index + 4U], buf[index + 5U], buf[index + 6U], buf[index + 7U]);
+ print("%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", buf[index], buf[index + 1U], buf[index + 2U], buf[index + 3U], buf[index + 4U], buf[index + 5U], buf[index + 6U], buf[index + 7U]);
}
print("\n");
} else {
@@ -309,7 +308,7 @@ void run(struct ast_node* root) {
u32 end = module->functions_end[sym_index];
unassemble((u8*)module->base_addr + start, end - start);
} else {
- print("No symbol found at address %xu\n", ctx.Rip);
+ print("No symbol found at address %x\n", ctx.Rip);
}
} else {
print("Command unknown\n");
diff --git a/src/pdb.c b/src/pdb.c
index 0d6617a..955e3be 100644
--- a/src/pdb.c
+++ b/src/pdb.c
@@ -1,6 +1,5 @@
#include "pdb.h"
-#include <strsafe.h>
#include "cvinfo.h"
#include "utils.h"
@@ -142,15 +141,14 @@ void open_pdb(const char* pdb_path, struct module* module) {
for (u32 module_index = 0U; byte_index < DBI_stream_header->mod_info_size; module_index++) {
modules_info[module_index] = (struct mod_info*)&DBI_block[byte_index];
modules_name[module_index] = &DBI_block[byte_index + sizeof(struct mod_info)];
- print("Module symbol stream index %xu\n", modules_info[module_index]->ModuleSymStream);
+ print("Module symbol stream index %x\n", modules_info[module_index]->ModuleSymStream);
print("Module name : %s\n", modules_name[module_index]);
size_t module_name_length = 0U;
- StringCchLengthA((STRSAFE_LPSTR)modules_name[module_index], STRSAFE_MAX_CCH, &module_name_length);
+ module_name_length = str_len((const char*)modules_name[module_index], 256U);
obj_files_name[module_index] = &DBI_block[byte_index + sizeof(struct mod_info) + module_name_length + 1U];
print("Obj file name : %s\n", obj_files_name[module_index]);
- size_t obj_file_name_length = 0U;
- StringCchLengthA((STRSAFE_LPSTR)obj_files_name[module_index], STRSAFE_MAX_CCH, &obj_file_name_length);
+ size_t obj_file_name_length = str_len((const char*)obj_files_name[module_index], 256U);
u32 module_info_size = sizeof(*modules_info[0U]) + (i32)module_name_length + 1 + (i32)obj_file_name_length + 1;
module_info_size = ((module_info_size + 3U) / 4U) * 4U;
@@ -185,9 +183,8 @@ void open_pdb(const char* pdb_path, struct module* module) {
print("PROC32 SYMBOL %s\n", proc->name);
// TODO: Add string management code
assert(string_stack_current - 16U * 4096U < string_stack_base);
- size_t length = 0U;
- StringCchLengthA((PCNZCH)proc->name, STRSAFE_MAX_CCH, &length);
- StringCchCopyA((LPSTR)string_stack_current, STRSAFE_MAX_CCH, (LPCSTR)proc->name);
+ size_t length = str_len((const char*)proc->name, 256U);
+ str_cat((char*)string_stack_current, (const char*)proc->name, length);
string_stack_current[length] = '\0';
u32 start_address = proc->off + module->nt_header.OptionalHeader.BaseOfCode;
#ifdef HASHMAP
@@ -226,7 +223,7 @@ void open_pdb(const char* pdb_path, struct module* module) {
buildinfo;
print("BUILDINFO SYMBOL\n");
} else {
- print("Unknown symbol kind %xu\n", rec->rectyp);
+ print("Unknown symbol kind %x\n", rec->rectyp);
}
cur_sym = (u8*)NextSym((SYMTYPE*)cur_sym);
}
diff --git a/src/stack_walk.c b/src/stack_walk.c
index 88a21db..cc030b2 100644
--- a/src/stack_walk.c
+++ b/src/stack_walk.c
@@ -165,7 +165,7 @@ void walk_stack(void* ctx) {
u32 sym_index = find_function(module, addr - (u64)module->base_addr);
if (sym_index == (u32)-1) {
#endif
- print("No symbol found at address %xu\n", addr);
+ print("No symbol found at address %x\n", addr);
addr = *(u64*)rsp;
continue;
diff --git a/src/utils.c b/src/utils.c
index 27dab87..729b74d 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,7 +1,6 @@
#include "utils.h"
#include <Windows.h>
-#include <strsafe.h>
u8 is_alpha(char c) {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
@@ -15,6 +14,31 @@ u8 is_hexadecimal_digit(char c) {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F');
}
+
+// TODO: Improve basic functions perfs
+// max_size: str allocated size
+size_t str_len(const char* str, size_t max_size) {
+ const char* c = str;
+ size_t count = 0U;
+ while (*c != '\0' && count < max_size) {
+ c++;
+ count++;
+ }
+ return count;
+}
+
+void str_cat(char* out, const char* str, size_t c_str) {
+ char* cur_out = out;
+ const char* cur_str = str;
+ u32 index = 0U;
+ while(index < c_str) {
+ *cur_out = *cur_str;
+ cur_out++;
+ cur_str++;
+ index++;
+ }
+}
+
void u64toa(u64 number, char* str, u32 base) {
static char codes[16U] = {
'0',
@@ -37,9 +61,8 @@ void u64toa(u64 number, char* str, u32 base) {
u32 remainder = 0U;
u32 size = 0U;
- if (number == 0) {
+ if (number == 0U) {
str[0U] = codes[0U];
- return;
}
for(; number != 0U; size++) {
@@ -95,74 +118,162 @@ void print(const char* format, ...) {
va_list args;
va_start(args, format);
char formatted_str[4096U] = { 0 };
- STRSAFE_LPSTR cur_char = formatted_str;
+ char* cur_char = formatted_str;
const char* cur_fmt = format;
while(*cur_fmt != '\0') {
if(*cur_fmt == '%') {
cur_fmt++;
- const char* num_start = cur_fmt;
- u8 num_len = 0U;
u64 fill_count = 0U;
- while (is_decimal_digit(*cur_fmt)) {
+
+ // padding length
+ if (*cur_fmt == '.') {
cur_fmt++;
- num_len++;
- }
- if (num_len > 0U) {
- fill_count = atou64(num_start, num_len);
+ const char* num_start = cur_fmt;
+ u8 num_len = 0U;
+
+ while (is_decimal_digit(*cur_fmt)) {
+ cur_fmt++;
+ num_len++;
+ }
+
+ if (num_len > 0U) {
+ fill_count = atou64(num_start, num_len);
+ }
}
+ // TODO: length modifiers
+
+ // conversion specifiers
if (*cur_fmt == 's') {
const char* str = va_arg(args, const char*);
if(str != NULL) {
- size_t length = 0U;
- StringCchLengthA(str, sizeof(formatted_str), &length);
+ size_t length = str_len(str, sizeof(formatted_str));
i64 relative_fill_count = fill_count - length;
- if (relative_fill_count > 0) {
+ if (relative_fill_count > 1) {
fill_chars((u8*)cur_char, ' ', (u32)relative_fill_count);
cur_char += relative_fill_count;
}
- StringCchCatA(cur_char, length + 1U, str);
+ str_cat(cur_char, str, length);
cur_char += length;
}
} else if(*cur_fmt == 'c') {
char c = va_arg(args, char);
if (fill_count > 1U) {
fill_chars((u8*)cur_char, ' ', (u32)fill_count - 1U);
- cur_char += fill_count - 1U;
+ cur_char += fill_count;
}
- StringCchCatA(cur_char, 1U, &c);
- cur_char += 1U;
- } else if (*cur_fmt == 'x' && is_alpha(cur_fmt[1])) {
- u32 base = 16U;
- cur_fmt++;
+ *cur_char = c;
+ cur_char++;
+ } else if (*cur_fmt == 'x') {
+ u64 number = va_arg(args, u64);
+ u32 str_len = 0;
- if(*cur_fmt == 'b') {
- u8 number = va_arg(args, u8);
- u64toa((u64)number, cur_char, base);
- size_t length = 0U;
- StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
- cur_char = formatted_str + length;
- } else if(*cur_fmt == 'u') {
- u64 number = va_arg(args, u64);
- u64toa(number, cur_char, base);
- size_t length = 0U;
- StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
- cur_char = formatted_str + length;
+ if (number > 0xfffffffffffffff) {
+ str_len = 16U;
+ } else if (number > 0xffffffffffffff) {
+ str_len = 15U;
+ } else if (number > 0xfffffffffffff) {
+ str_len = 14U;
+ } else if (number > 0xffffffffffff) {
+ str_len = 13U;
+ } else if (number > 0xfffffffffff) {
+ str_len = 12U;
+ } else if (number > 0xffffffffff) {
+ str_len = 11U;
+ } else if (number > 0xfffffffff) {
+ str_len = 10U;
+ } else if (number > 0xffffffff) {
+ str_len = 9U;
+ } else if (number > 0xfffffff) {
+ str_len = 8U;
+ } else if (number > 0xffffff) {
+ str_len = 7U;
+ } else if (number > 0xfffff) {
+ str_len = 6U;
+ } else if (number > 0xffff) {
+ str_len = 5U;
+ } else if (number > 0xfff) {
+ str_len = 4U;
+ } else if (number > 0xff) {
+ str_len = 3U;
+ } else if (number > 0xf) {
+ str_len = 2U;
}
+
+ i64 relative_fill_count = fill_count - str_len;
+ if (relative_fill_count > 1) {
+ fill_chars((u8*)cur_char, '0', (u32)relative_fill_count);
+ cur_char += fill_count;
+ }
+ u64toa(number, cur_char, 16U);
+
+ cur_char += str_len;
} else if(*cur_fmt == 'b') {
u8 number = va_arg(args, u8);
+ u32 str_len = 8U - __lzcnt(number);
+
+ i64 relative_fill_count = fill_count - str_len;
+ if (relative_fill_count > 1) {
+ fill_chars((u8*)cur_char, '0', (u32)relative_fill_count);
+ cur_char += fill_count;
+ }
+
u64toa((u64)number, cur_char, 10U);
- size_t length = 0U;
- StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
- cur_char = formatted_str + length;
+ cur_char += str_len;
} else if(*cur_fmt == 'u') {
u64 number = va_arg(args, u64);
+ u32 str_len = 1U;
+
+ if (number > 9999999999999999999U) {
+ str_len = 20U;
+ } else if (number > 999999999999999999U) {
+ str_len = 19U;
+ } else if (number > 99999999999999999U) {
+ str_len = 18U;
+ } else if (number > 9999999999999999U) {
+ str_len = 17U;
+ } else if (number > 999999999999999U) {
+ str_len = 16U;
+ } else if (number > 99999999999999U) {
+ str_len = 15U;
+ } else if (number > 9999999999999U) {
+ str_len = 14U;
+ } else if (number > 999999999999U) {
+ str_len = 13U;
+ } else if (number > 99999999999U) {
+ str_len = 12U;
+ } else if (number > 9999999999U) {
+ str_len = 11U;
+ } else if (number > 999999999U) {
+ str_len = 10U;
+ } else if (number > 99999999U) {
+ str_len = 9U;
+ } else if (number > 9999999U) {
+ str_len = 8U;
+ } else if (number > 999999U) {
+ str_len = 7U;
+ } else if (number > 99999U) {
+ str_len = 6U;
+ } else if (number > 9999U) {
+ str_len = 5U;
+ } else if (number > 999U) {
+ str_len = 4U;
+ } else if (number > 99U) {
+ str_len = 3U;
+ } else if (number > 9U) {
+ str_len = 2U;
+ }
+
+ i64 relative_fill_count = fill_count - str_len;
+ if (relative_fill_count > 1U) {
+ fill_chars((u8*)cur_char, '0', (u32)relative_fill_count);
+ cur_char += fill_count;
+ }
+
u64toa(number, cur_char, 10U);
- size_t length = 0U;
- StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
- cur_char = formatted_str + length;
+ cur_char += str_len;
}
} else {
*cur_char = *cur_fmt;
@@ -173,9 +284,7 @@ void print(const char* format, ...) {
va_end(args);
HANDLE standard_err = GetStdHandle(STD_ERROR_HANDLE);
- size_t length = 0U;
- StringCchLengthA(formatted_str, sizeof(formatted_str), &length);
- SUCCEEDED(WriteFile(standard_err, formatted_str, (DWORD)length, NULL, NULL));
+ SUCCEEDED(WriteFile(standard_err, formatted_str, (u32)(cur_char - formatted_str), NULL, NULL));
}
/* Read debugged process memory at address */