diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/disasm.c | 147 | ||||
| -rw-r--r-- | src/events.c | 30 | ||||
| -rw-r--r-- | src/main.c | 2 | ||||
| -rw-r--r-- | src/parser.c | 27 | ||||
| -rw-r--r-- | src/pdb.c | 15 | ||||
| -rw-r--r-- | src/stack_walk.c | 2 | ||||
| -rw-r--r-- | src/utils.c | 193 |
7 files changed, 280 insertions, 136 deletions
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"); @@ -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"); @@ -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 */ |
