From 4312ee14fd389d4961a98e3e224b33aeb577a4d7 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 3 Mar 2026 16:24:54 -0800 Subject: [PATCH] first pass at (rdi -> loose rdim) path, used in (rdi * ... * rdi) -> rdi joining in radbin; plug in regular conversion path before voff -> line & breakpad paths in radbin, such that PDBs, DWARFs, RDIs, etc. can be used as input; fix up voff -> line path to plug into regular output systems; remove String8 union thing - three reasons: (a) it was only ever introduced for convenience in Linux layers, so let's just keep zero-terminated Linux nonsense in Linux land, (b) it was just alternate syntax for a cast, so let's just cast, (c) it was misleading - 'cstr' implies null-termination, which String8 of course doesn't guarantee. this led to some misuses, where .cstr was trusted to be zero-terminated, when that was not necessarily true (semaphore opening). --- src/base/base_strings.h | 6 +- src/demon/linux/demon_core_linux.c | 588 +++++++++--------- src/lib_rdi/rdi.h | 930 ++++++++++++++--------------- src/lib_rdi_make/rdi_make.c | 82 +-- src/lib_rdi_make/rdi_make.h | 5 + src/linker/lnk_debug_info.c | 4 +- src/msf/msf_parse.c | 3 +- src/os/core/linux/os_core_linux.c | 81 +-- src/radbin/radbin.c | 452 +++++++------- src/rdi_from_pdb/rdi_from_pdb.c | 1 - src/rdi_make/rdi_make_local.c | 230 +++++++ src/rdi_make/rdi_make_local.h | 1 + src/third_party/radsort/radsort.h | 2 +- src/third_party/stb/stb_sprintf.h | 30 +- src/torture/torture.h | 44 +- src/torture/torture_d2r.c | 524 ++++++++-------- src/torture/torture_dwarf.c | 322 +++++----- 17 files changed, 1797 insertions(+), 1508 deletions(-) diff --git a/src/base/base_strings.h b/src/base/base_strings.h index 9692eda4..8912d1e1 100644 --- a/src/base/base_strings.h +++ b/src/base/base_strings.h @@ -10,11 +10,7 @@ typedef struct String8 String8; struct String8 { - union - { - U8 *str; - char *cstr; - }; + U8 *str; U64 size; }; diff --git a/src/demon/linux/demon_core_linux.c b/src/demon/linux/demon_core_linux.c index 12104181..5ba475a8 100644 --- a/src/demon/linux/demon_core_linux.c +++ b/src/demon/linux/demon_core_linux.c @@ -106,21 +106,21 @@ dmn_lnx_exe_path_from_pid(Arena *arena, pid_t pid) { Temp scratch = scratch_begin(&arena, 1); - String8 exe_link_path = str8f(scratch.arena, "/proc/%d/exe", pid); - String8List parts = {0}; - int readlink_result = 0; + String8 exe_link_path = str8f(scratch.arena, "/proc/%d/exe", pid); + String8List parts = {0}; + int readlink_result = 0; for(S64 r = 0, cap = PATH_MAX; r < 4; cap *= 2, r += 1) { U8 *buffer = push_array(arena, U8, cap); - readlink_result = readlink(exe_link_path.cstr, (char *)buffer, cap); - + readlink_result = readlink((char *)exe_link_path.str, (char *)buffer, cap); + if(readlink_result < 0) { break; } - + str8_list_push(scratch.arena, &parts, str8(buffer, readlink_result)); - + if(readlink_result < cap) { break; @@ -136,32 +136,32 @@ internal String8 dmn_lnx_dl_path_from_pid(Arena *arena, pid_t pid, U64 auxv_base) { Temp scratch = scratch_begin(&arena, 1); - + String8 dl_path = {0}; - - int maps_fd = OS_LNX_RETRY_ON_EINTR(open(str8f(scratch.arena, "/proc/%d/maps", pid).cstr, O_RDONLY)); + + int maps_fd = OS_LNX_RETRY_ON_EINTR(open((char *)str8f(scratch.arena, "/proc/%d/maps", pid).str, O_RDONLY)); if(maps_fd != -1) { // read entire /proc/pid/maps U64 maps_size = dmn_lnx_size_from_fd(maps_fd, MB(1)); U8 *maps_ptr = push_array(scratch.arena, U8, maps_size); U64 read_size = dmn_lnx_read(maps_fd, r1u64(0, maps_size), maps_ptr); - - // split map file on lines + + // split map file on lines String8List lines = str8_split_by_string_chars(scratch.arena, str8(maps_ptr, maps_size), str8_lit("\n"), 0); - + // scan each line until a virtual mapping whose low part matches the DL base address is found for EachNode(n, String8Node, lines.first) { String8 line = n->string; - + // split the string while respecting escape sequences String8List parts = {0}; for EachIndex(cursor, line.size) { if(parts.node_count > 5) { break; } if(line.str[cursor] == ' ') { continue; } - + // scan forward to the closing delimiter U64 token_start = cursor; for(; cursor < line.size; cursor += 1) @@ -173,18 +173,18 @@ dmn_lnx_dl_path_from_pid(Arena *arena, pid_t pid, U64 auxv_base) } if(line.str[cursor] == ' ') { break; } } - + // push sub-string to the list str8_list_push(scratch.arena, &parts, str8_substr(line, r1u64(token_start, cursor))); } - + // was line parsed correctly? if(parts.node_count < 5) { Assert(0 && "failed to parse map line"); continue; } - + // parse map virtual range String8List vaddr_list = str8_split_by_string_chars(scratch.arena, parts.first->string, str8_lit("-"), 0); if(vaddr_list.node_count != 2) { Assert(0 && "failed to parse virtual range portion of map line"); continue; } - + // does the low part match DL base address? U64 lo_vaddr = u64_from_str8(vaddr_list.first->string, 16); if(lo_vaddr == auxv_base) @@ -194,11 +194,11 @@ dmn_lnx_dl_path_from_pid(Arena *arena, pid_t pid, U64 auxv_base) break; } } - + OS_LNX_RETRY_ON_EINTR(close(maps_fd)); } else { Assert(0 && "failed to open DL fd"); } - + scratch_end(scratch); Assert(dl_path.size); return dl_path; @@ -208,19 +208,19 @@ internal ELF_Hdr64 dmn_lnx_ehdr_from_pid(pid_t pid) { Temp scratch = scratch_begin(0, 0); - + ELF_Hdr64 exe = {0}; B32 is_read = 0; - - char *exe_path = push_str8f(scratch.arena, "/proc/%d/exe", pid).cstr; + + char *exe_path = (char *)str8f(scratch.arena, "/proc/%d/exe", pid).str; int exe_fd = OS_LNX_RETRY_ON_EINTR(open(exe_path, O_RDONLY)); - + if(exe_fd >= 0) { is_read = elf_read_ehdr(dmn_lnx_machine_op_mem_read, &exe_fd, 0, &exe); OS_LNX_RETRY_ON_EINTR(close(exe_fd)); } - + Assert(is_read); scratch_end(scratch); return exe; @@ -233,8 +233,8 @@ dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class) DMN_LNX_Auxv result = {0}; // rjf: open aux data - String8 auxv_path = push_str8f(scratch.arena, "/proc/%d/auxv", pid); - int auxv_fd = OS_LNX_RETRY_ON_EINTR(open(auxv_path.cstr, O_RDONLY)); + String8 auxv_path = str8f(scratch.arena, "/proc/%d/auxv", pid); + int auxv_fd = OS_LNX_RETRY_ON_EINTR(open((char *)auxv_path.str, O_RDONLY)); // rjf: scan aux data if(auxv_fd >= 0) @@ -245,18 +245,18 @@ dmn_lnx_auxv_from_pid(pid_t pid, ELF_Class elf_class) ELF_Auxv64 auxv = {0}; switch(elf_class) { - case ELF_Class_None:{}break; - case ELF_Class_32: - { - ELF_Auxv32 auxv32 = {0}; - if(read(auxv_fd, &auxv32, sizeof(auxv32)) != sizeof(auxv32)) { goto brkloop; } - auxv = elf_auxv64_from_auxv32(auxv32); - }break; - case ELF_Class_64: - { - if(read(auxv_fd, &auxv, sizeof(auxv)) != sizeof(auxv)) { goto brkloop; } - }break; - default:{NotImplemented;}break; + case ELF_Class_None:{}break; + case ELF_Class_32: + { + ELF_Auxv32 auxv32 = {0}; + if(read(auxv_fd, &auxv32, sizeof(auxv32)) != sizeof(auxv32)) { goto brkloop; } + auxv = elf_auxv64_from_auxv32(auxv32); + }break; + case ELF_Class_64: + { + if(read(auxv_fd, &auxv, sizeof(auxv)) != sizeof(auxv)) { goto brkloop; } + }break; + default:{NotImplemented;}break; } // rjf: fill result @@ -304,7 +304,7 @@ dmn_lnx_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 { Assert(0 && "unable to read a program header"); } - + if(phdr.p_type == ELF_PType_Load) { U64 min = rebase + phdr.p_vaddr; @@ -313,7 +313,7 @@ dmn_lnx_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 result.max = Max(result.max, max); } } - + return result; } @@ -326,10 +326,10 @@ dmn_lnx_dynamic_info_from_memory(int memory_fd, ELF_Class elf_class, U64 rebase, // rjf: read next dyn entry ELF_Dyn64 dyn = {0}; if(elf_read_dyn(dmn_lnx_machine_op_mem_read, &memory_fd, dynamic_cursor, elf_class, &dyn) != MachineOpResult_Ok) { Assert(0 && "unable to read dynamic"); } - + // rjf: break on zero if(dyn.tag == ELF_DynTag_Null) { break; } - + // extract reuiqred values out of dynamic section if(dyn.tag == ELF_DynTag_Strtab) { @@ -363,7 +363,7 @@ internal U64 dmn_lnx_find_dynamic_phdr(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum) { U64 result = max_U64; - + for(U64 ph_cursor = e_phaddr, ph_opl = (e_phaddr + e_phentsize * e_phnum); ph_cursor < ph_opl; ph_cursor += e_phentsize) { ELF_Phdr64 phdr = {0}; @@ -371,14 +371,14 @@ dmn_lnx_find_dynamic_phdr(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_ { Assert(0 && "unable to read a program header"); } - + if(phdr.p_type == ELF_PType_Dynamic) { result = rebase + phdr.p_vaddr; break; } } - + return result; } @@ -386,24 +386,24 @@ internal U64 dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase, B32 is_rebased) { Temp scratch = scratch_begin(0, 0); - + U64 rdebug_vaddr = 0; - + // load DL's header ELF_Hdr64 ehdr = {0}; if(elf_read_ehdr(dmn_lnx_machine_op_mem_read, &memory_fd, loader_vbase, &ehdr) != MachineOpResult_Ok) { Assert(0 && "failed to read interp's header"); goto exit; } - + U64 rebase = ehdr.e_type == ELF_Type_Dyn ? loader_vbase : 0; ELF_Class elf_class = ehdr.e_ident[ELF_Identifier_Class]; - + // find dynamic program header U64 phdr_vaddr = loader_vbase + ehdr.e_phoff; U64 dynamic_vaddr = dmn_lnx_find_dynamic_phdr(memory_fd, elf_class, rebase, phdr_vaddr, ehdr.e_phentsize, ehdr.e_phentsize); - + // extract necessary info out of dynamic program header U64 dynamic_info_rebase = is_rebased ? 0 : rebase; DMN_LNX_DynamicInfo dynamic_info = dmn_lnx_dynamic_info_from_memory(memory_fd, elf_class, dynamic_info_rebase, dynamic_vaddr); - + // extract symbol table count from available options U64 symbol_count = 0; if(dynamic_info.hash_vaddr) @@ -413,7 +413,7 @@ dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase, B32 is_rebased { hash_entry_size = 8; } - + U64 chain_count = 0; if(dmn_lnx_read(memory_fd, r1u64(dynamic_info.hash_vaddr, dynamic_info.hash_vaddr + hash_entry_size), &chain_count) == hash_entry_size) { @@ -429,7 +429,7 @@ dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase, B32 is_rebased // TODO: extract count from GNU_HASH NotImplemented; } - + // scan symbol table for the rendezvous symbol if(dynamic_info.symtab_vaddr && dynamic_info.symtab_entry_size && symbol_count) { @@ -441,16 +441,16 @@ dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase, B32 is_rebased Assert(0 && "failed to read symbol table"); break; } - + Temp temp = temp_begin(scratch.arena); - + String8 symbol_name = {0}; if(symbol.st_name < dynamic_info.strtab_size) { U64 cap = dynamic_info.strtab_size - symbol.st_name; symbol_name = dmn_lnx_read_string_capped(temp.arena, memory_fd, dynamic_info.strtab_vaddr + symbol.st_name, cap); } - + if(str8_match(symbol_name, str8_lit("_r_debug"), 0)) { ELF_SymType symbol_type = ELF_ST_TYPE(symbol.st_info); @@ -460,12 +460,12 @@ dmn_lnx_rdebug_vaddr_from_memory(int memory_fd, U64 loader_vbase, B32 is_rebased break; } } - + temp_end(temp); } } -exit:; + exit:; scratch_end(scratch); return rdebug_vaddr; } @@ -474,33 +474,33 @@ internal DMN_LNX_ProbeList dmn_lnx_read_probes(Arena *arena, int fd, U64 offset, U64 image_base) { Temp scratch = scratch_begin(&arena, 1); - + DMN_LNX_ProbeList probes = {0}; - + ELF_Hdr64 ehdr = {0}; if(elf_read_ehdr(dmn_lnx_machine_op_mem_read, &fd, offset, &ehdr) != MachineOpResult_Ok) { goto exit; } - + U64 strtab_shdr_offset = offset + ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize; ELF_Shdr64 strtab_shdr = {0}; if(elf_read_shdr(dmn_lnx_machine_op_mem_read, &fd, strtab_shdr_offset, ehdr.e_ident[ELF_Identifier_Class], &strtab_shdr) != MachineOpResult_Ok) { goto exit; } - + B32 found_probes = 0; B32 found_probes_base = 0; ELF_Shdr64 text_shdr = {0}; ELF_Shdr64 stapsdt_base_shdr = {0}; ELF_Shdr64 stapsdt_shdr = {0}; for(U64 shdr_off = offset + ehdr.e_shoff, shdr_opl = shdr_off + ehdr.e_shentsize * ehdr.e_shnum; - shdr_off < shdr_opl; - shdr_off += ehdr.e_shentsize) { + shdr_off < shdr_opl; + shdr_off += ehdr.e_shentsize) { ELF_Shdr64 shdr = {0}; if(elf_read_shdr(dmn_lnx_machine_op_mem_read, &fd, shdr_off, ehdr.e_ident[ELF_Identifier_Class], &shdr) != MachineOpResult_Ok) { goto exit; } - + if(shdr.sh_type == ELF_ShType_Note) { U64 name_offset = offset + strtab_shdr.sh_offset + shdr.sh_name; U64 name_cap = offset + strtab_shdr.sh_offset + strtab_shdr.sh_size; String8 name = dmn_lnx_read_string_capped(scratch.arena, fd, name_offset, name_cap); - + if(str8_match(name, str8_lit(".note.stapsdt"), 0)) { stapsdt_shdr = shdr; @@ -512,7 +512,7 @@ dmn_lnx_read_probes(Arena *arena, int fd, U64 offset, U64 image_base) U64 name_offset = offset + strtab_shdr.sh_offset + shdr.sh_name; U64 name_cap = offset + strtab_shdr.sh_offset + strtab_shdr.sh_size; String8 name = dmn_lnx_read_string_capped(scratch.arena, fd, name_offset, name_cap); - + if(str8_match(name, str8_lit(".stapsdt.base"), 0)) { stapsdt_base_shdr = shdr; @@ -522,76 +522,76 @@ dmn_lnx_read_probes(Arena *arena, int fd, U64 offset, U64 image_base) text_shdr = shdr; } } - + if(found_probes && found_probes_base) { break; } } - + if(!found_probes || !found_probes_base) { goto exit; } - + U64 probes_base = stapsdt_base_shdr.sh_addr; Rng1U64 note_range = shift_1u64(r1u64(stapsdt_shdr.sh_offset, stapsdt_shdr.sh_offset + stapsdt_shdr.sh_size), offset); void *raw_note = push_array(arena, U8, stapsdt_shdr.sh_size); U64 note_read_size = dmn_lnx_read(fd, note_range, raw_note); if(note_read_size != dim_1u64(note_range)) { goto exit; } - + Arch arch = arch_from_elf_machine(ehdr.e_machine); ELF_NoteList note = elf_parse_note(scratch.arena, str8(raw_note, dim_1u64(note_range)), ehdr.e_ident[ELF_Identifier_Class], ehdr.e_machine); - + for EachNode(n, ELF_NoteNode, note.first) { ELF_Note *note = &n->v; if(!str8_match(note->owner, str8_lit("stapsdt"), 0)) { continue; } if(note->type != ELF_NoteType_STapSdt) { continue; } - + DMN_LNX_Probe probe = {0}; { U64 cursor = 0; U64 addr_size = ehdr.e_ident[ELF_Identifier_Class] == ELF_Class_64 ? 8 : 4; - + U64 pc = 0; U64 pc_size = str8_deserial_read(note->desc, cursor, &pc, addr_size, addr_size); if (pc_size == 0) { goto exit; } cursor += pc_size; - + U64 base_addr = 0; U64 base_addr_size = str8_deserial_read(note->desc, cursor, &base_addr, addr_size, addr_size); if (base_addr_size == 0) { goto exit; } cursor += base_addr_size; - + U64 semaphore = 0; U64 semaphore_size = str8_deserial_read(note->desc, cursor, &semaphore, addr_size, addr_size); if (semaphore_size == 0) { goto exit; } cursor += semaphore_size; - + String8 provider = str8_cstring_capped(note->desc.str + cursor, note->desc.str + note->desc.size); cursor += provider.size + 1; if (cursor > note->desc.size) { goto exit; } - + String8 name = str8_cstring_capped(note->desc.str + cursor, note->desc.str + note->desc.size); cursor += name.size + 1; if (cursor > note->desc.size) { goto exit; } - + String8 args = str8_cstring_capped(note->desc.str + cursor, note->desc.str + note->desc.size); cursor += args.size + 1; if (cursor > note->desc.size) { goto exit; } - + U64 probe_rebase = image_base + (base_addr - probes_base); - + probe.provider = provider; probe.name = name; probe.args = stap_arg_array_from_string(arena, arch, args); probe.pc = pc + probe_rebase; probe.semaphore = semaphore ? semaphore + probe_rebase : 0; } - + DMN_LNX_ProbeNode *n = push_array(arena, DMN_LNX_ProbeNode, 1); n->v = probe; SLLQueuePush(probes.first, probes.last, n); probes.count += 1; } - -exit:; + + exit:; scratch_end(scratch); return probes; } @@ -627,28 +627,28 @@ internal DMN_LNX_Process * dmn_lnx_process_alloc(pid_t pid, DMN_LNX_ProcessState state, DMN_LNX_Process *parent_process, B32 debug_subprocesses, B32 is_cow) { Temp scratch = scratch_begin(0, 0); - + DMN_LNX_Process *process = &dmn_lnx_entity_alloc(DMN_LNX_EntityKind_Process)->process; process->pid = pid; - process->fd = OS_LNX_RETRY_ON_EINTR(open(str8f(scratch.arena, "/proc/%d/mem", pid).cstr, O_RDWR)); + process->fd = OS_LNX_RETRY_ON_EINTR(open((char *)str8f(scratch.arena, "/proc/%d/mem", pid).str, O_RDWR)); process->state = state; process->debug_subprocesses = debug_subprocesses; process->is_cow = is_cow; process->parent_process = parent_process; - + // update pending process tracker if(state != DMN_LNX_ProcessState_Normal) { dmn_lnx_state->process_pending_creation += 1; } - + // add process to the list DLLPushBack(dmn_lnx_state->first_process, dmn_lnx_state->last_process, process); dmn_lnx_state->process_count += 1; - + // push pid -> DMN_LNX_Process mapping hash_table_push_u64_raw(dmn_lnx_state->arena, dmn_lnx_state->pid_ht, pid, process); - + scratch_end(scratch); return process; } @@ -657,7 +657,7 @@ internal DMN_LNX_ProcessCtx * dmn_lnx_process_ctx_alloc(DMN_LNX_Process *process, B32 is_rebased) { DMN_LNX_ProcessCtx *ctx = &dmn_lnx_entity_alloc(DMN_LNX_EntityKind_ProcessCtx)->process_ctx; - + ELF_Hdr64 exe_ehdr = dmn_lnx_ehdr_from_pid(process->pid); DMN_LNX_Auxv auxv = dmn_lnx_auxv_from_pid(process->pid, exe_ehdr.e_ident[ELF_Identifier_Class]); Arch arch = arch_from_elf_machine(exe_ehdr.e_machine); @@ -666,14 +666,14 @@ dmn_lnx_process_ctx_alloc(DMN_LNX_Process *process, B32 is_rebased) U64 rebase = exe_ehdr.e_type == ELF_Type_Dyn ? base_vaddr : 0; Rng1U64 image_vrange = dmn_lnx_compute_image_vrange(process->fd, exe_ehdr.e_ident[ELF_Identifier_Class], rebase, auxv.phdr, auxv.phent, auxv.phnum); Arena *ctx_arena = arena_alloc(); - + ELF_Class dl_class; { ELF_Hdr64 ehdr = {0}; if(elf_read_ehdr(dmn_lnx_machine_op_mem_read, &process->fd, auxv.base, &ehdr) != MachineOpResult_Ok) { Assert(0 && "failed to read interp's header"); } dl_class = ehdr.e_ident[ELF_Identifier_Class]; } - + // query xsave layout U64 xcr0 = 0; U64 xsave_size = 0; @@ -691,22 +691,22 @@ dmn_lnx_process_ctx_alloc(DMN_LNX_Process *process, B32 is_rebased) } else { Assert(0 && "failed to get xstate"); } } - + // gather probes DMN_LNX_Probe **known_probes = push_array(ctx_arena, DMN_LNX_Probe *, DMN_LNX_ProbeType_Count); { Temp scratch = scratch_begin(0, 0); - + String8 dl_path = dmn_lnx_dl_path_from_pid(scratch.arena, process->pid, auxv.base); - int dl_fd = OS_LNX_RETRY_ON_EINTR(open(dl_path.cstr, O_RDONLY)); - + int dl_fd = OS_LNX_RETRY_ON_EINTR(open((char *)dl_path.str, O_RDONLY)); + DMN_LNX_ProbeList probes = {0}; if(dl_fd >= 0) { probes = dmn_lnx_read_probes(ctx_arena, dl_fd, 0, auxv.base); OS_LNX_RETRY_ON_EINTR(close(dl_fd)); } - + for EachNode(n, DMN_LNX_ProbeNode, probes.first) { DMN_LNX_Probe *p = &n->v; @@ -717,10 +717,10 @@ dmn_lnx_process_ctx_alloc(DMN_LNX_Process *process, B32 is_rebased) #undef X } } - + scratch_end(scratch); } - + ctx = &dmn_lnx_entity_alloc(DMN_LNX_EntityKind_ProcessCtx)->process_ctx; ctx->arena = arena_alloc(); ctx->arch = arch; @@ -731,13 +731,13 @@ dmn_lnx_process_ctx_alloc(DMN_LNX_Process *process, B32 is_rebased) ctx->xcr0 = xcr0; ctx->xsave_size = Max(xsave_size, sizeof(X64_XSave)); ctx->xsave_layout = xsave_layout; - + // create main module DMN_LNX_Module *main_module = dmn_lnx_module_alloc(ctx, process->fd, base_vaddr, auxv.execfn, 1, 1); - + // glibc has a shortcut mapping for the main module hash_table_push_u64_raw(ctx->arena, ctx->loaded_modules_ht, 0, main_module); - + return ctx; } @@ -756,7 +756,7 @@ dmn_lnx_thread_alloc(DMN_LNX_Process *process, DMN_LNX_ThreadState thread_state, U64 reg_block_size = regs_block_size_from_arch(process->ctx->arch); reg_block = push_array(process->ctx->arena, U8, reg_block_size); } - + DMN_LNX_Thread *thread = &dmn_lnx_entity_alloc(DMN_LNX_EntityKind_Thread)->thread; thread->tid = tid; thread->state = thread_state; @@ -766,20 +766,20 @@ dmn_lnx_thread_alloc(DMN_LNX_Process *process, DMN_LNX_ThreadState thread_state, { thread->is_reg_block_dirty = !dmn_lnx_thread_read_reg_block(thread); } - + // add thread to the list DLLPushBack(process->first_thread, process->last_thread, thread); process->thread_count += 1; - + // push tid -> thread mapping hash_table_push_u64_raw(dmn_lnx_state->arena, dmn_lnx_state->tid_ht, thread->tid, thread); - + // update global thread counter if(thread_state == DMN_LNX_ThreadState_PendingCreation) { dmn_lnx_state->threads_pending_creation += 1; } - + return thread; } @@ -788,16 +788,16 @@ dmn_lnx_module_alloc(DMN_LNX_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 { DMN_LNX_Module *module = hash_table_search_u64_raw(ctx->loaded_modules_ht, base_vaddr); if(module) { goto exit; } - + // parse out module's ELF header ELF_Hdr64 module_ehdr = {0}; if(elf_read_ehdr(dmn_lnx_machine_op_mem_read, &memory_fd, base_vaddr, &module_ehdr) != MachineOpResult_Ok) { goto exit; } - + // gather info about module U64 module_rebase = module_ehdr.e_type == ELF_Type_Dyn ? base_vaddr : 0; U64 module_phdr_vaddr = module_rebase + module_ehdr.e_phoff; Rng1U64 module_vrange = dmn_lnx_compute_image_vrange(memory_fd, module_ehdr.e_ident[ELF_Identifier_Class], module_rebase, module_phdr_vaddr, module_ehdr.e_phentsize, module_ehdr.e_phnum); - + // read TLS index and TLS offset U64 tls_index = max_U64; U64 tls_offset = max_U64; @@ -818,7 +818,7 @@ dmn_lnx_module_alloc(DMN_LNX_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 if(!dmn_lnx_read(memory_fd, tls_offset_range, &tls_offset)) { Assert(0 && "failed to read TLS offset"); } } } - + module = &dmn_lnx_entity_alloc(DMN_LNX_EntityKind_Module)->module; module->base_vaddr = base_vaddr; module->name_vaddr = name_vaddr; @@ -830,15 +830,15 @@ dmn_lnx_module_alloc(DMN_LNX_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 module->tls_index = tls_index; module->tls_offset = tls_offset; module->is_main = is_main; - + // add module to the list DLLPushBack(ctx->first_module, ctx->last_module, module); ctx->module_count += 1; - + // push base address -> module mapping hash_table_push_u64_raw(ctx->arena, ctx->loaded_modules_ht, base_vaddr, module); - -exit:; + + exit:; return module; } @@ -858,26 +858,26 @@ dmn_lnx_process_release(DMN_LNX_Process *process) AssertAlways(dmn_lnx_state->process_count > 0); DLLRemove(dmn_lnx_state->first_process, dmn_lnx_state->last_process, process); dmn_lnx_state->process_count -= 1; - + // update pending process tracker if(process->state != DMN_LNX_ProcessState_Normal) { Assert(dmn_lnx_state->process_pending_creation > 0); dmn_lnx_state->process_pending_creation -= 1; } - + // close memory handle if(OS_LNX_RETRY_ON_EINTR(close(process->fd)) < 0) { Assert(0 && "failed to close memory descriptor"); } - + // remove pid mapping hash_table_purge_u64(dmn_lnx_state->pid_ht, process->pid); - + // release the context if(process->ctx) { dmn_lnx_process_ctx_release(process->ctx); } - + // release process entity dmn_lnx_entity_release((DMN_LNX_Entity *)process); } @@ -887,7 +887,7 @@ dmn_lnx_process_ctx_release(DMN_LNX_ProcessCtx *ctx) { Assert(ctx->ref_count > 0); ctx->ref_count -= 1; - + if(ctx->ref_count == 0) { arena_release(ctx->arena); @@ -899,22 +899,22 @@ internal void dmn_lnx_thread_release(DMN_LNX_Thread *thread) { DMN_LNX_Process *process = thread->process; - + // purge tid mapping hash_table_purge_u64(dmn_lnx_state->tid_ht, thread->tid); - + // update global thread counter if(thread->state == DMN_LNX_ThreadState_PendingCreation) { AssertAlways(dmn_lnx_state->threads_pending_creation > 0); dmn_lnx_state->threads_pending_creation -= 1; } - + // remove thread from the list Assert(process->thread_count > 0); DLLRemove(process->first_thread, process->last_thread, thread); process->thread_count -= 1; - + // push reg block to the free list String8Node *reg_block_node; if(process->ctx->free_reg_block_nodes.node_count) @@ -927,7 +927,7 @@ dmn_lnx_thread_release(DMN_LNX_Thread *thread) } reg_block_node->string = str8(thread->reg_block, 0); str8_list_push_node(&process->ctx->free_reg_blocks, reg_block_node); - + dmn_lnx_entity_release((DMN_LNX_Entity *)thread); } @@ -938,10 +938,10 @@ dmn_lnx_module_release(DMN_LNX_ProcessCtx *ctx, DMN_LNX_Module *module) Assert(ctx->module_count > 0); DLLRemove(ctx->first_module, ctx->last_module, module); ctx->module_count -= 1; - + // purge base addr -> module mapping hash_table_purge_u64(ctx->loaded_modules_ht, module->base_vaddr); - + dmn_lnx_entity_release((DMN_LNX_Entity *)module); } @@ -958,14 +958,14 @@ dmn_lnx_process_ctx_clone(DMN_LNX_Process *new_owner, DMN_LNX_ProcessCtx *ctx) result->xcr0 = ctx->xcr0; result->xsave_size = ctx->xsave_size; result->xsave_layout = ctx->xsave_layout; - + // clone probes result->probes = push_array(result->arena, DMN_LNX_Probe *, DMN_LNX_ProbeType_Count); for EachIndex(probe_idx, DMN_LNX_ProbeType_Count) { DMN_LNX_Probe *dst = result->probes[probe_idx]; DMN_LNX_Probe *src = ctx->probes[probe_idx]; - + dst->provider = str8_copy(result->arena, src->provider); dst->name = str8_copy(result->arena, src->name); dst->args_string = str8_copy(result->arena, src->args_string); @@ -973,7 +973,7 @@ dmn_lnx_process_ctx_clone(DMN_LNX_Process *new_owner, DMN_LNX_ProcessCtx *ctx) dst->pc = src->pc; dst->semaphore = src->semaphore; } - + // clone probe traps for EachNode(src, DMN_ActiveTrap, ctx->first_probe_trap) { @@ -984,20 +984,20 @@ dmn_lnx_process_ctx_clone(DMN_LNX_Process *new_owner, DMN_LNX_ProcessCtx *ctx) dst_trap->id = src_trap->id; dst_trap->flags = src_trap->flags; dst_trap->size = src_trap->size; - + DMN_ActiveTrap *dst = push_array(result->arena, DMN_ActiveTrap, 1); dst->trap = dst_trap; dst->swap_bytes = str8_copy(result->arena, src->swap_bytes); - + SLLQueuePush(result->first_probe_trap, result->last_probe_trap, dst); } - + // clone modules for EachNode(module, DMN_LNX_Module, ctx->first_module) { dmn_lnx_module_clone(result, module); } - + return result; } @@ -1007,14 +1007,14 @@ dmn_lnx_module_clone(DMN_LNX_ProcessCtx *process_ctx, DMN_LNX_Module *module) DMN_LNX_Module *result = &dmn_lnx_entity_alloc(DMN_LNX_EntityKind_Module)->module; *result = *module; result->next = result->prev = 0; - + // clone base addr mapping hash_table_push_u64_raw(process_ctx->arena, process_ctx->loaded_modules_ht, result->base_vaddr, result); - + // push module to the list DLLPushBack(process_ctx->first_module, process_ctx->last_module, module); process_ctx->module_count += 1; - + return result; } @@ -1105,15 +1105,15 @@ dmn_lnx_process_trap_probes(DMN_LNX_Process *process) for EachIndex(i, DMN_LNX_ProbeType_Count) { if(process->ctx->probes[i] == 0) { continue; } - + DMN_Trap *trap = push_array(process->ctx->arena, DMN_Trap, 1); trap->process = dmn_lnx_handle_from_process(process); trap->vaddr = process->ctx->probes[i]->pc; trap->id = i; - + DMN_ActiveTrap *active_trap = dmn_set_trap(process->ctx->arena, trap); SLLQueuePush(process->ctx->first_probe_trap, process->ctx->last_probe_trap, active_trap); - + if(BUILD_DEBUG && process->ctx->arch == Arch_x64) { Assert(active_trap->swap_bytes.size == 1 && active_trap->swap_bytes.str[0] == 0x90); @@ -1157,9 +1157,9 @@ internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) { AssertAlways(thread->state == DMN_LNX_ThreadState_Stopped); - + B32 is_reg_block_read = 0; - + switch(thread->process->ctx->arch) { case Arch_Null: {} break; @@ -1173,7 +1173,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) OS_LNX_GprsX64 src; int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_len = sizeof(src), .iov_base = &src })); if(ptrace_result < 0) { goto exit; } - + dst->r15.u64 = src.r15; dst->r14.u64 = src.r14; dst->r13.u64 = src.r13; @@ -1206,7 +1206,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) // xsave { Temp scratch = scratch_begin(0, 0); - + X64_XSave *xsave = 0; X64_FXSave *fxsave = 0; @@ -1216,7 +1216,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) void *xsave_raw = push_array(scratch.arena, U8, process_ctx->xsave_size); int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_X86_XSTATE, &(struct iovec){ .iov_len = process_ctx->xsave_size, .iov_base = xsave_raw })); if(ptrace_result < 0) { goto exit; } - + xsave = xsave_raw; fxsave = &xsave->fxsave; } @@ -1227,7 +1227,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) fxsave = push_array(scratch.arena, X64_FXSave, 1); int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_FPREGSET, &(struct iovec){ .iov_len = sizeof(*fxsave), .iov_base = fxsave })); if(ptrace_result < 0) { goto exit; } - + fxsave = 0; } @@ -1235,7 +1235,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) if(fxsave) { X64_FXSave *src = fxsave; - + // copy x87 registers dst->fcw.u16 = src->fcw; dst->fsw.u16 = src->fsw; @@ -1249,7 +1249,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) { MemoryCopy(&dst->st0 + i, src->st_space + i, sizeof(REGS_Reg80)); } - + // SSE registers are always available in x64 { U128 *xmm_d = fxsave->xmm_space; @@ -1260,13 +1260,13 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) } } } - + // copy xsave registers if(xsave) { // compact register layout is not supported AssertAlways(xsave->header.xcomp_bv == 0); - + if(xsave->header.xstate_bv & X64_XStateComponentFlag_AVX) { AssertAlways(process_ctx->xsave_layout.avx_offset + 16*sizeof(REGS_Reg128) <= process_ctx->xsave_size); @@ -1277,7 +1277,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) MemoryCopy(&zmm_d[n].v[16], &avx_s[n], sizeof(REGS_Reg128)); } } - + if(xsave->header.xstate_bv & X64_XStateComponentFlag_OPMASK) { AssertAlways(process_ctx->xsave_layout.opmask_offset + sizeof(REGS_Reg64) * 8 <= process_ctx->xsave_size); @@ -1288,7 +1288,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(REGS_Reg64)); } } - + if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM_H) { AssertAlways(process_ctx->xsave_layout.zmm_h_offset + sizeof(REGS_Reg256) * 16 <= process_ctx->xsave_size); @@ -1299,7 +1299,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) MemoryCopy(&zmmh_d[n].v[32], &avx512h_s[n], sizeof(REGS_Reg256)); } } - + if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM) { AssertAlways(process_ctx->xsave_layout.zmm_offset + sizeof(REGS_Reg512) * 16 <= process_ctx->xsave_size); @@ -1310,7 +1310,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) MemoryCopy(&zmm_d[n], &avx512_s[n], sizeof(REGS_Reg512)); } } - + if(xsave->header.xstate_bv & X64_XStateComponentFlag_CETU) { AssertAlways(process_ctx->xsave_layout.cet_u_offset + sizeof(U64)*2 <= process_ctx->xsave_size); @@ -1338,7 +1338,7 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) } } } - + is_reg_block_read = 1; } break; case Arch_x86: @@ -1346,8 +1346,8 @@ dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread) case Arch_arm32: { NotImplemented; } break; default: { InvalidPath; } break; } - -exit:; + + exit:; return is_reg_block_read; } @@ -1355,9 +1355,9 @@ internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) { AssertAlways(thread->state == DMN_LNX_ThreadState_Stopped); - + B32 is_reg_block_written = 0; - + switch(thread->process->ctx->arch) { case Arch_Null: {} break; @@ -1403,7 +1403,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) // xsave { Temp scratch = scratch_begin(0, 0); - + X64_FXSave dst_fxsave = {0}; { dst_fxsave.fcw = src->fcw.u16; @@ -1414,14 +1414,14 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) dst_fxsave.fdp = src->fdp.u64; dst_fxsave.mxcsr = src->mxcsr.u32; dst_fxsave.mxcsr_mask = src->mxcsr_mask.u32; - + REGS_Reg128 *st_d = (REGS_Reg128 *)dst_fxsave.st_space; REGS_Reg80 *st_s = &src->st0; for EachIndex(n, 8) { MemoryCopy(&st_d[n], &st_s[n], sizeof(REGS_Reg80)); } - + REGS_Reg128 *xmm_d = (REGS_Reg128 *)dst_fxsave.xmm_space; REGS_Reg512 *xmm_s = &src->zmm0; for EachIndex(n, 16) @@ -1429,7 +1429,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) MemoryCopy(&xmm_d[n], &xmm_s[n], sizeof(REGS_Reg128)); } } - + if(x64_is_xsave_supported()) { U8 *xsave_raw = push_array(scratch.arena, U8, process_ctx->xsave_size); @@ -1437,7 +1437,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) dst->fxsave = dst_fxsave; dst->header.xstate_bv |= X64_XStateComponentFlag_FP; dst->header.xstate_bv |= X64_XStateComponentFlag_SSE; - + if(process_ctx->xsave_layout.avx_offset) { if(process_ctx->xsave_layout.avx_offset + sizeof(REGS_Reg128) * 16 <= process_ctx->xsave_size) @@ -1451,7 +1451,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) dst->header.xstate_bv |= X64_XStateComponentFlag_AVX; } } - + if(process_ctx->xsave_layout.opmask_offset) { if(process_ctx->xsave_layout.opmask_offset + sizeof(REGS_Reg64) * 8 <= process_ctx->xsave_size) @@ -1466,7 +1466,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) } else { Assert(0 && "invalid xsave size"); goto exit; } } - + if(process_ctx->xsave_layout.zmm_h_offset) { if(process_ctx->xsave_layout.zmm_h_offset + sizeof(REGS_Reg256) * 16 <= process_ctx->xsave_size) @@ -1481,7 +1481,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) } else { Assert(0 && "invalid xsave size"); goto exit; } } - + if(process_ctx->xsave_layout.zmm_offset) { if(process_ctx->xsave_layout.zmm_offset + sizeof(REGS_Reg512) * 16 <= process_ctx->xsave_size) @@ -1496,7 +1496,7 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) } else { Assert(0 && "invalid xsave size"); goto exit; } } - + if(process_ctx->xsave_layout.cet_u_offset) { if(process_ctx->xsave_layout.cet_u_offset + sizeof(REGS_Reg64) * 2 <= process_ctx->xsave_size) @@ -1508,20 +1508,20 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) } else { Assert(0 && "invalid xsave size"); goto exit; } } - + // xsave Assert(dst->header.xcomp_bv == 0); // must always be zero int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_SETREGSET, thread->tid, (void *)NT_X86_XSTATE, &(struct iovec){ .iov_base = dst, .iov_len = process_ctx->xsave_size })); if(ptrace_result < 0) { goto exit; } } - + scratch_end(scratch); } // debug registers { src->dr7.u64 |= (1 << 10); - + REGS_Reg64 *dr_s = &src->dr0; for EachIndex(n, 8) { @@ -1541,8 +1541,8 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread) case Arch_x86: { NotImplemented; }break; default: { InvalidPath; } break; } - -exit:; + + exit:; return is_reg_block_written; } @@ -1756,7 +1756,7 @@ dmn_lnx_push_event_exception(Arena *arena, DMN_EventList *events, DMN_LNX_Thread 1, // 31 SIGSYS 1, // 32 SIGUNUSED }; - + DMN_Event *e = dmn_event_list_push(arena, events); e->kind = DMN_EventKind_Exception; e->process = dmn_lnx_handle_from_process(thread->process); @@ -1764,7 +1764,7 @@ dmn_lnx_push_event_exception(Arena *arena, DMN_EventList *events, DMN_LNX_Thread e->instruction_pointer = dmn_lnx_thread_read_ip(thread); e->signo = signo; e->exception_repeated = signo < ArrayCount(is_repeatable) ? is_repeatable[signo] : 0; - + if(signo == SIGSEGV) { siginfo_t si = {0}; @@ -1801,19 +1801,19 @@ dmn_lnx_event_exit_thread(Arena *arena, DMN_EventList *events, pid_t tid, U64 ex { DMN_LNX_Thread *thread = dmn_lnx_thread_from_pid(tid); DMN_LNX_Process *process = thread->process; - + // store main thread's exit code if(thread->tid == thread->process->pid) { thread->process->main_thread_exit_code = exit_code; } - + // push exit event dmn_lnx_push_event_exit_thread(arena, events, thread, exit_code); - + // release entity dmn_lnx_thread_release(thread); - + // auto exit process on last thread if(process->thread_count == 0) { @@ -1825,7 +1825,7 @@ internal DMN_LNX_Process * dmn_lnx_event_create_process(Arena *arena, DMN_EventList *events, pid_t pid, DMN_LNX_Process *parent_process, DMN_LNX_CreateProcessFlags flags) { DMN_LNX_Process *process = dmn_lnx_process_alloc(pid, DMN_LNX_ProcessState_Normal, parent_process, !!(flags & DMN_LNX_CreateProcessFlag_DebugSubprocesses), !!(flags & DMN_LNX_CreateProcessFlag_Cow)); - + if(flags & DMN_LNX_CreateProcessFlag_ClonedMemory) { process->ctx = parent_process->ctx; @@ -1835,16 +1835,16 @@ dmn_lnx_event_create_process(Arena *arena, DMN_EventList *events, pid_t pid, DMN process->ctx = dmn_lnx_process_ctx_alloc(process, !!(flags & DMN_LNX_CreateProcessFlag_Rebased)); } process->ctx->ref_count += 1; - + // install probes in a process that does not have a cloned memory if(!(flags & DMN_LNX_CreateProcessFlag_ClonedMemory)) { dmn_lnx_process_trap_probes(process); } - + // create main thread dmn_lnx_thread_alloc(process, DMN_LNX_ThreadState_Stopped, pid); - + // push events dmn_lnx_push_event_create_process(arena, events, process); for EachNode(thread, DMN_LNX_Thread, process->first_thread) @@ -1856,7 +1856,7 @@ dmn_lnx_event_create_process(Arena *arena, DMN_EventList *events, pid_t pid, DMN dmn_lnx_push_event_load_module(arena, events, process->first_thread, module); } dmn_lnx_push_event_handshake_complete(arena, events, process); - + return process; } @@ -1865,16 +1865,16 @@ dmn_lnx_event_exit_process(Arena *arena, DMN_EventList *events, pid_t pid) { DMN_LNX_Process *process = dmn_lnx_process_from_pid(pid); AssertAlways(process->thread_count == 0); - + // push module events for EachNode(module, DMN_LNX_Module, process->ctx->first_module) { dmn_lnx_push_event_unload_module(arena, events, process, module); } - + // push process exit event dmn_lnx_push_event_exit_process(arena, events, process); - + // release process dmn_lnx_process_release(process); } @@ -1883,27 +1883,27 @@ internal void dmn_lnx_event_load_module(Arena *arena, DMN_EventList *events, DMN_LNX_Thread *thread, U64 name_space_id, U64 new_link_map_vaddr) { DMN_LNX_Process *process = thread->process; - + GNU_LinkMap64 map = {0}; for(U64 map_vaddr = new_link_map_vaddr; map_vaddr != 0; map_vaddr = map.next_vaddr) { // read out new link map item if(gnu_read_link_map(dmn_lnx_machine_op_mem_read, &process->fd, map_vaddr, process->ctx->dl_class, &map) != MachineOpResult_Ok) { break; } - + // was module already loaded? DMN_LNX_Module *module = hash_table_search_u64_raw(process->ctx->loaded_modules_ht, map.addr_vaddr); if(module) { continue; } - + // clone process ctx if(process->is_cow) { process->is_cow = 0; process->ctx = dmn_lnx_process_ctx_clone(process, process->ctx); } - + // alloc module module = dmn_lnx_module_alloc(process->ctx, process->fd, map.addr_vaddr, map.name_vaddr, name_space_id, 0); - + // push load module event dmn_lnx_push_event_load_module(arena, events, thread, module); } @@ -1913,15 +1913,15 @@ internal void dmn_lnx_event_unload_module(Arena *arena, DMN_EventList *events, DMN_LNX_Process *process, U64 rdebug_vaddr) { Temp scratch = scratch_begin(&arena, 1); - + DMN_LNX_ProcessCtx *ctx = process->ctx; - + // flag every module as inactive for EachNode(module, DMN_LNX_Module, ctx->first_module) { module->is_live = 0; } - + // mark live modules B32 is_64bit = ctx->dl_class == ELF_Class_64; GNU_RDebugInfoList rdebug_list = gnu_parse_rdebug(scratch.arena, is_64bit, rdebug_vaddr, dmn_lnx_machine_op_mem_read, &process->fd); @@ -1934,7 +1934,7 @@ dmn_lnx_event_unload_module(Arena *arena, DMN_EventList *events, DMN_LNX_Process module->is_live = 1; } } - + // collect unloaded modules DMN_LNX_ModulePtrList to_release = {0}; for EachNode(module, DMN_LNX_Module, ctx->first_module) @@ -1944,7 +1944,7 @@ dmn_lnx_event_unload_module(Arena *arena, DMN_EventList *events, DMN_LNX_Process dmn_lnx_module_ptr_list_push(scratch.arena, &to_release, module); } } - + // clone process context if(to_release.count > 0) { @@ -1954,14 +1954,14 @@ dmn_lnx_event_unload_module(Arena *arena, DMN_EventList *events, DMN_LNX_Process process->ctx = dmn_lnx_process_ctx_clone(process, process->ctx); } } - + // push events and clean up unloaded modules for EachNode(module_n, DMN_LNX_ModulePtrNode, to_release.first) { dmn_lnx_push_event_unload_module(arena, events, process, module_n->v); dmn_lnx_module_release(process->ctx, module_n->v); } - + scratch_end(scratch); } @@ -1971,7 +1971,7 @@ dmn_lnx_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us DMN_LNX_Thread *thread = dmn_lnx_thread_from_pid(tid); DMN_LNX_Process *process = thread->process; U64 ip = dmn_lnx_thread_read_ip(thread); - + // is this user trap? DMN_ActiveTrap *hit_user_trap = 0; { @@ -1988,7 +1988,7 @@ dmn_lnx_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us } } } - + // is this a probe trap? DMN_LNX_ProbeType probe_type = DMN_LNX_ProbeType_Null; if(hit_user_trap == 0) @@ -2002,22 +2002,22 @@ dmn_lnx_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us } } } - + if(probe_type == DMN_LNX_ProbeType_InitComplete) { B32 is_init_completed = 0; - + DMN_LNX_Probe *probe = process->ctx->probes[DMN_LNX_ProbeType_InitComplete]; U64 name_space_id = 0, rdebug_addr = 0; if(!stap_read_arg_u(probe->args.v[0], process->ctx->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { goto init_complete_exit; } if(!stap_read_arg_u(probe->args.v[1], process->ctx->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &rdebug_addr)) { goto init_complete_exit; } - + GNU_RDebugInfo64 rdebug = {0}; if(gnu_read_r_debug(dmn_lnx_machine_op_mem_read, &process->fd, rdebug_addr, process->ctx->arch, &rdebug) != MachineOpResult_Ok) { goto init_complete_exit; } if(rdebug.r_version < 1) { goto init_complete_exit; } - + dmn_lnx_event_load_module(arena, events, thread, name_space_id, rdebug.r_map); - + is_init_completed = 1; init_complete_exit:; AssertAlways(is_init_completed); @@ -2025,14 +2025,14 @@ dmn_lnx_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us else if(probe_type == DMN_LNX_ProbeType_RelocComplete) { B32 is_reloc_completed = 0; - + DMN_LNX_Probe *probe = process->ctx->probes[DMN_LNX_ProbeType_RelocComplete]; U64 name_space_id = 0, new_link_map_addr = 0; if(!stap_read_arg_u(probe->args.v[0], process->ctx->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { goto reloc_complete_exit; } if(!stap_read_arg_u(probe->args.v[2], process->ctx->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &new_link_map_addr)) { goto reloc_complete_exit; } - + dmn_lnx_event_load_module(arena, events, thread, name_space_id, new_link_map_addr); - + is_reloc_completed = 1; reloc_complete_exit:; AssertAlways(is_reloc_completed); @@ -2040,19 +2040,19 @@ dmn_lnx_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us else if(probe_type == DMN_LNX_ProbeType_UnmapComplete) { B32 is_unmap_completed = 0; - + DMN_LNX_Probe *probe = process->ctx->probes[DMN_LNX_ProbeType_UnmapComplete]; U64 name_space_id = 0, rdebug_vaddr = 0; if(!stap_read_arg_u(probe->args.v[0], process->ctx->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { goto unmap_complete_exit; } if(!stap_read_arg_u(probe->args.v[1], process->ctx->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &rdebug_vaddr)) { goto unmap_complete_exit; } - + dmn_lnx_event_unload_module(arena, events, process, rdebug_vaddr); - + is_unmap_completed = 1; unmap_complete_exit:; AssertAlways(is_unmap_completed); } - + if(probe_type == DMN_LNX_ProbeType_Null) { // rollback IP on user traps @@ -2061,7 +2061,7 @@ dmn_lnx_event_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *us U64 ip = dmn_lnx_thread_read_ip(thread); dmn_lnx_thread_write_ip(thread, ip - 1); } - + DMN_Event *e = dmn_event_list_push(arena, events); e->kind = DMN_EventKind_Breakpoint; e->process = dmn_lnx_handle_from_process(process); @@ -2074,7 +2074,7 @@ internal void dmn_lnx_event_data_breakpoint(Arena *arena, DMN_EventList *events, pid_t tid) { DMN_LNX_Thread *thread = dmn_lnx_thread_from_pid(tid); - + B32 is_valid = 1; U64 address = 0; switch(thread->process->ctx->arch) @@ -2110,7 +2110,7 @@ dmn_lnx_event_data_breakpoint(Arena *arena, DMN_EventList *events, pid_t tid) { NotImplemented; } break; default: { InvalidPath; } break; } - + if(is_valid) { dmn_lnx_push_event_breakpoint(arena, events, thread, address); @@ -2127,10 +2127,10 @@ internal void dmn_lnx_event_single_step(Arena *arena, DMN_EventList *events, pid_t tid) { DMN_LNX_Thread *thread = dmn_lnx_thread_from_pid(tid); - + // clear single step flag dmn_lnx_set_single_step_flag(thread, 0); - + // push event dmn_lnx_push_event_single_step(arena, events, thread); } @@ -2139,10 +2139,10 @@ internal void dmn_lnx_event_exception(Arena *arena, DMN_EventList *events, pid_t tid, U64 signo) { DMN_LNX_Thread *thread = dmn_lnx_thread_from_pid(tid); - + thread->pass_through_signal = 1; thread->pass_through_signo = signo; - + dmn_lnx_push_event_exception(arena, events, thread, signo); } @@ -2150,35 +2150,35 @@ internal DMN_LNX_Process * dmn_lnx_event_attach(Arena *arena, DMN_EventList *events, pid_t pid) { Temp scratch = scratch_begin(&arena, 1); - + // create process DMN_LNX_Process *process = dmn_lnx_event_create_process(arena, events, pid, 0, DMN_LNX_CreateProcessFlag_DebugSubprocesses|DMN_LNX_CreateProcessFlag_Rebased); - + // extract threads from /proc/pid/task { - String8 task_path = push_str8f(scratch.arena, "/proc/%d/task", pid); - DIR *task_dirp = opendir(task_path.cstr); + String8 task_path = str8f(scratch.arena, "/proc/%d/task", pid); + DIR *task_dirp = opendir((char *)task_path.str); if(task_dirp) { for(;;) { struct dirent *dirent = readdir(task_dirp); if(dirent == 0) { break; } - + String8 tid_str = str8_cstring_capped(dirent->d_name, dirent->d_name + NAME_MAX); if(str8_match(tid_str, str8_lit(".."), 0) || str8_match(tid_str, str8_lit("."), 0)) { continue; } U64 tid_64 = u64_from_str8(tid_str, 10); pid_t tid = (pid_t)tid_64; AssertAlways(tid == tid_64); - + if(tid == pid) { continue; } // main thread was created during create process sequence dmn_lnx_event_create_thread(arena, events, process, tid); } - + OS_LNX_RETRY_ON_EINTR(closedir(task_dirp)); } } - + // extract modules from r_debug { B32 is_64bit = process->ctx->dl_class == ELF_Class_64; @@ -2190,10 +2190,10 @@ dmn_lnx_event_attach(Arena *arena, DMN_EventList *events, pid_t pid) name_space_id += 1; } } - + // handshake complete dmn_lnx_push_event_handshake_complete(arena, events, process); - + scratch_end(scratch); return process; } @@ -2208,7 +2208,7 @@ dmn_init(void) { local_persist DMN_LNX_State state; dmn_lnx_state = &state; - + dmn_lnx_state->arena = arena_alloc(); dmn_lnx_state->access_mutex = mutex_alloc(); dmn_lnx_state->entities_arena = arena_alloc(.reserve_size = GB(32), .commit_size = KB(64), .flags = ArenaFlag_NoChain); @@ -2217,7 +2217,7 @@ dmn_init(void) dmn_lnx_state->pid_ht = hash_table_init(dmn_lnx_state->arena, 0x400); dmn_lnx_state->halter_mutex = mutex_alloc(); dmn_lnx_entity_alloc(DMN_LNX_EntityKind_Null); - + // find offsets of TLS index and TLS offset in the link_map struct // // TODO: assuming that target is using same libc version as debugger @@ -2271,7 +2271,7 @@ internal U32 dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params) { Temp scratch = scratch_begin(0, 0); - + // setup target command line U64 argc = params->cmd_line.node_count + 1; char **argv = push_array(scratch.arena, char *, argc); @@ -2279,43 +2279,45 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params) U64 idx = 0; for EachNode(n, String8Node, params->cmd_line.first) { - argv[idx++] = push_str8_copy(scratch.arena, n->string).cstr; + argv[idx] = (char *)str8_copy(scratch.arena, n->string).str; + idx += 1; } } - + // setup target environment U64 envc = os_lnx_state.default_env_count + params->env.node_count + 1; char **envp = push_array(scratch.arena, char *, envc); { // copy default environment MemoryCopyTyped(envp, os_lnx_state.default_env, os_lnx_state.default_env_count); - + // copy user environment U64 idx = os_lnx_state.default_env_count; for EachNode(n, String8Node, params->env.first) { - envp[idx++] = push_str8_copy(scratch.arena, n->string).cstr; + envp[idx] = (char *)str8_copy(scratch.arena, n->string).str; + idx += 1; } } - + // create zero-terminated work directory path - char *work_dir_path = push_str8_copy(scratch.arena, params->path).cstr; - + char *work_dir_path = (char *)str8_copy(scratch.arena, params->path).str; + // fork process pid_t pid = fork(); - + // child process if(pid == 0) { // wait for seize if(OS_LNX_RETRY_ON_EINTR(raise(SIGSTOP)) < 0) { goto child_exit; } - + // change work directory to tracee if(OS_LNX_RETRY_ON_EINTR(chdir(work_dir_path)) < 0) { goto child_exit; } - + // replace process with target program if(OS_LNX_RETRY_ON_EINTR(execve(argv[0], argv, envp)) < 0) { goto child_exit; } - + child_exit:; exit(0); } @@ -2393,7 +2395,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { Temp scratch = scratch_begin(&arena, 1); DMN_EventList events = {0}; - + mutex_take(dmn_lnx_state->halter_mutex); // wait for signals from the running threads @@ -2410,34 +2412,34 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) // skip hardware breakpoints DMN_Trap *trap = n->v+n_idx; if(trap->flags) { continue; } - + HashTable *active_trap_ht = hash_table_search_u64_raw(process_ht, trap->process.u64[0]); if(active_trap_ht == 0) { active_trap_ht = hash_table_init(scratch.arena, ctrls->traps.trap_count); hash_table_push_u64_raw(scratch.arena, process_ht, trap->process.u64[0], active_trap_ht); } - + // TODO: ctrl sends down duplicate traps DMN_ActiveTrap *is_set = hash_table_search_u64_raw(active_trap_ht, trap->vaddr); if(is_set) { continue; } - + // TODO: ctrl sends down traps for exited process DMN_LNX_Process *process = dmn_lnx_process_from_handle(trap->process); if(!process) { continue; } - + // trap instruction DMN_ActiveTrap *active_trap = dmn_set_trap(scratch.arena, trap); - + // add trap to the active list SLLQueuePush(active_trap_first, active_trap_last, active_trap); - + // add (address -> trap) hash_table_push_u64_raw(scratch.arena, active_trap_ht, trap->vaddr, active_trap); } } } - + // enable single stepping if(!dmn_handle_match(ctrls->single_step_thread, dmn_handle_zero())) { @@ -2451,7 +2453,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) Assert(0 && "invalid single_step_thread handle"); } } - + // schedule threads to run DMN_LNX_ThreadPtrList running_threads = {0}; { @@ -2470,12 +2472,12 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } } } - + for EachNode(thread, DMN_LNX_Thread, process->first_thread) { //- rjf: determine if this thread is frozen B32 is_frozen = 0; - + // rjf: not single-stepping? determine based on run controls freezing info if(dmn_handle_match(dmn_handle_zero(), ctrls->single_step_thread)) { @@ -2504,18 +2506,18 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { is_frozen = !dmn_handle_match(dmn_lnx_handle_from_thread(thread), ctrls->single_step_thread); } - + // resume thread if(!is_frozen) { AssertAlways(thread->state == DMN_LNX_ThreadState_Stopped); - + // write registers if(thread->is_reg_block_dirty) { thread->is_reg_block_dirty = !dmn_lnx_thread_write_reg_block(thread); } - + // pass signal to the child process void *sig_code = 0; if(thread->pass_through_signal) @@ -2526,7 +2528,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) sig_code = (void *)(uintptr_t)thread->pass_through_signo; } } - + // resume thread if(OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_CONT, thread->tid, 0, sig_code)) >= 0) { @@ -2555,14 +2557,14 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } } } - + // hash running threads tids HashTable *running_threads_ht = hash_table_init(scratch.arena, running_threads.count * 2); for EachNode(n, DMN_LNX_ThreadPtrNode, running_threads.first) { hash_table_push_u64_raw(scratch.arena, running_threads_ht, n->v->tid, n); } - + B32 is_halt_done = 0; DMN_LNX_ThreadPtrList stopped_threads = {0}; do @@ -2580,18 +2582,18 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } mutex_take(dmn_lnx_state->halter_mutex); } - + // unpack status int wifexited = WIFEXITED(status); int wifsignaled = WIFSIGNALED(status); int wifstopped = WIFSTOPPED(status); int wstopsig = WSTOPSIG(status); int event_code = (status >> 16); - + // intercept initing processes { DMN_LNX_Process *process = dmn_lnx_process_from_pid(wait_id); - + if(process && process->state != DMN_LNX_ProcessState_Normal) { switch(process->state) @@ -2646,7 +2648,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) else { Assert(0 && "unexpected signal"); } } break; } - + // shutdown process { if(OS_LNX_RETRY_ON_EINTR(kill(wait_id, SIGKILL)) >= 0) @@ -2659,12 +2661,12 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) dmn_lnx_process_release(process); } } - + wait_for_signal:; continue; } } - + if(wifstopped || wifsignaled || wifexited) { DMN_LNX_ThreadPtrNode *thread_n = hash_table_search_u64_raw(running_threads_ht, wait_id); @@ -2672,14 +2674,14 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { DMN_LNX_Thread *thread = thread_n->v; AssertAlways(thread->state == DMN_LNX_ThreadState_Running); - + // remove mapping hash_table_purge_u64(running_threads_ht, thread->tid); - + // move thread to the stopped list dmn_lnx_thread_ptr_list_remove(&running_threads, thread_n); dmn_lnx_thread_ptr_list_push_node(&stopped_threads, thread_n); - + // update thread state if(wifstopped && !wifsignaled && !wifexited) { @@ -2690,7 +2692,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) thread->state = DMN_LNX_ThreadState_Exited; } else { InvalidPath; } - + // stop all other threads if(stopped_threads.count == 1) { @@ -2701,13 +2703,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } } } - + // normal child exit via _exit or exit() if(wifexited) { dmn_lnx_event_exit_thread(arena, &events, wait_id, WEXITSTATUS(status)); } - + // exit because child did not handle a signal else if(wifsignaled) { @@ -2725,7 +2727,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) Assert(!thread->is_reg_block_dirty); } } - + if(wstopsig == SIGTRAP) { switch(event_code) @@ -2738,13 +2740,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { switch(siginfo.si_code) { - case SI_KERNEL: { dmn_lnx_event_breakpoint(arena, &events, active_trap_first, wait_id); } break; - case TRAP_BRKPT: { dmn_lnx_event_breakpoint(arena, &events, active_trap_first, wait_id); } break; - case TRAP_TRACE: { dmn_lnx_event_single_step(arena, &events, wait_id); } break; - case TRAP_HWBKPT: { dmn_lnx_event_data_breakpoint(arena, &events, wait_id); } break; - case TRAP_BRANCH: { NotImplemented; }break; - case TRAP_UNK: { NotImplemented; }break; - default: { InvalidPath; } break; + case SI_KERNEL: { dmn_lnx_event_breakpoint(arena, &events, active_trap_first, wait_id); } break; + case TRAP_BRKPT: { dmn_lnx_event_breakpoint(arena, &events, active_trap_first, wait_id); } break; + case TRAP_TRACE: { dmn_lnx_event_single_step(arena, &events, wait_id); } break; + case TRAP_HWBKPT: { dmn_lnx_event_data_breakpoint(arena, &events, wait_id); } break; + case TRAP_BRANCH: { NotImplemented; }break; + case TRAP_UNK: { NotImplemented; }break; + default: { InvalidPath; } break; } } else { Assert(0 && "failed to get signal info"); } }break; @@ -2765,12 +2767,12 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) // kernel stopped the parent just before scheduling the child to // give us a chance to prepare to trace it; next event for the child // will be a PTRACE_EVENT_STOP - + pid_t new_tid; if(OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETEVENTMSG, wait_id, 0, &new_tid)) >= 0) { DMN_LNX_Thread *thread = dmn_lnx_thread_from_pid(wait_id); - + // create a new partially inited thread dmn_lnx_thread_alloc(thread->process, DMN_LNX_ThreadState_PendingCreation, new_tid); } @@ -2842,39 +2844,39 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } else { Assert(0 && "unexpected stop code"); } } while(running_threads.count > 0 || dmn_lnx_state->process_pending_creation > 0 || dmn_lnx_state->threads_pending_creation > 0); - + // finalize halter state if(is_halt_done) { // push event dmn_lnx_event_halt(arena, &events); - + // reset state dmn_lnx_state->halter_tid = 0; dmn_lnx_state->halt_code = 0; dmn_lnx_state->halt_user_data = 0; dmn_lnx_state->is_halting = 0; } - + // restore original instruction bytes for EachNode(active_trap, DMN_ActiveTrap, active_trap_first) { // skip process that exited during the wait DMN_LNX_Process *process = dmn_lnx_process_from_handle(active_trap->trap->process); if(!process) { continue; } - + if(!dmn_process_write(active_trap->trap->process, r1u64(active_trap->trap->vaddr, active_trap->trap->vaddr + active_trap->swap_bytes.size), active_trap->swap_bytes.str)) { Assert(0 && "failed to restore original instruction bytes"); } } } - + if(events.count == 0 && dmn_lnx_state->process_count == 0) { dmn_lnx_push_event_not_attached(arena, &events); } - + mutex_drop(dmn_lnx_state->halter_mutex); scratch_end(scratch); return events; diff --git a/src/lib_rdi/rdi.h b/src/lib_rdi/rdi.h index d2b6f321..a7b8b476 100644 --- a/src/lib_rdi/rdi.h +++ b/src/lib_rdi/rdi.h @@ -75,428 +75,428 @@ union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];}; typedef RDI_U32 RDI_SectionKind; typedef enum RDI_SectionKindEnum { -RDI_SectionKind_NULL = 0x0000, -RDI_SectionKind_TopLevelInfo = 0x0001, -RDI_SectionKind_StringData = 0x0002, -RDI_SectionKind_StringTable = 0x0003, -RDI_SectionKind_IndexRuns = 0x0004, -RDI_SectionKind_BinarySections = 0x0005, -RDI_SectionKind_FilePathNodes = 0x0006, -RDI_SectionKind_SourceFiles = 0x0007, -RDI_SectionKind_LineTables = 0x0008, -RDI_SectionKind_LineInfoVOffs = 0x0009, -RDI_SectionKind_LineInfoLines = 0x000A, -RDI_SectionKind_LineInfoColumns = 0x000B, -RDI_SectionKind_SourceLineMaps = 0x000C, -RDI_SectionKind_SourceLineMapNumbers = 0x000D, -RDI_SectionKind_SourceLineMapRanges = 0x000E, -RDI_SectionKind_SourceLineMapVOffs = 0x000F, -RDI_SectionKind_Units = 0x0010, -RDI_SectionKind_UnitVMap = 0x0011, -RDI_SectionKind_TypeNodes = 0x0012, -RDI_SectionKind_UDTs = 0x0013, -RDI_SectionKind_Members = 0x0014, -RDI_SectionKind_EnumMembers = 0x0015, -RDI_SectionKind_GlobalVariables = 0x0016, -RDI_SectionKind_GlobalVMap = 0x0017, -RDI_SectionKind_ThreadVariables = 0x0018, -RDI_SectionKind_Constants = 0x0019, -RDI_SectionKind_Procedures = 0x001A, -RDI_SectionKind_Scopes = 0x001B, -RDI_SectionKind_ScopeVOffData = 0x001C, -RDI_SectionKind_ScopeVMap = 0x001D, -RDI_SectionKind_InlineSites = 0x001E, -RDI_SectionKind_Locals = 0x001F, -RDI_SectionKind_LocationBlocks = 0x0020, -RDI_SectionKind_LocationData = 0x0021, -RDI_SectionKind_ConstantValueData = 0x0022, -RDI_SectionKind_ConstantValueTable = 0x0023, -RDI_SectionKind_MD5Checksums = 0x0024, -RDI_SectionKind_SHA1Checksums = 0x0025, -RDI_SectionKind_SHA256Checksums = 0x0026, -RDI_SectionKind_Timestamps = 0x0027, -RDI_SectionKind_NameMaps = 0x0028, -RDI_SectionKind_NameMapBuckets = 0x0029, -RDI_SectionKind_NameMapNodes = 0x002A, -RDI_SectionKind_COUNT = 0x002B, + RDI_SectionKind_NULL = 0x0000, + RDI_SectionKind_TopLevelInfo = 0x0001, + RDI_SectionKind_StringData = 0x0002, + RDI_SectionKind_StringTable = 0x0003, + RDI_SectionKind_IndexRuns = 0x0004, + RDI_SectionKind_BinarySections = 0x0005, + RDI_SectionKind_FilePathNodes = 0x0006, + RDI_SectionKind_SourceFiles = 0x0007, + RDI_SectionKind_LineTables = 0x0008, + RDI_SectionKind_LineInfoVOffs = 0x0009, + RDI_SectionKind_LineInfoLines = 0x000A, + RDI_SectionKind_LineInfoColumns = 0x000B, + RDI_SectionKind_SourceLineMaps = 0x000C, + RDI_SectionKind_SourceLineMapNumbers = 0x000D, + RDI_SectionKind_SourceLineMapRanges = 0x000E, + RDI_SectionKind_SourceLineMapVOffs = 0x000F, + RDI_SectionKind_Units = 0x0010, + RDI_SectionKind_UnitVMap = 0x0011, + RDI_SectionKind_TypeNodes = 0x0012, + RDI_SectionKind_UDTs = 0x0013, + RDI_SectionKind_Members = 0x0014, + RDI_SectionKind_EnumMembers = 0x0015, + RDI_SectionKind_GlobalVariables = 0x0016, + RDI_SectionKind_GlobalVMap = 0x0017, + RDI_SectionKind_ThreadVariables = 0x0018, + RDI_SectionKind_Constants = 0x0019, + RDI_SectionKind_Procedures = 0x001A, + RDI_SectionKind_Scopes = 0x001B, + RDI_SectionKind_ScopeVOffData = 0x001C, + RDI_SectionKind_ScopeVMap = 0x001D, + RDI_SectionKind_InlineSites = 0x001E, + RDI_SectionKind_Locals = 0x001F, + RDI_SectionKind_LocationBlocks = 0x0020, + RDI_SectionKind_LocationData = 0x0021, + RDI_SectionKind_ConstantValueData = 0x0022, + RDI_SectionKind_ConstantValueTable = 0x0023, + RDI_SectionKind_MD5Checksums = 0x0024, + RDI_SectionKind_SHA1Checksums = 0x0025, + RDI_SectionKind_SHA256Checksums = 0x0026, + RDI_SectionKind_Timestamps = 0x0027, + RDI_SectionKind_NameMaps = 0x0028, + RDI_SectionKind_NameMapBuckets = 0x0029, + RDI_SectionKind_NameMapNodes = 0x002A, + RDI_SectionKind_COUNT = 0x002B, } RDI_SectionKindEnum; typedef RDI_U32 RDI_SectionEncoding; typedef enum RDI_SectionEncodingEnum { -RDI_SectionEncoding_Unpacked = 0, -RDI_SectionEncoding_LZB = 1, + RDI_SectionEncoding_Unpacked = 0, + RDI_SectionEncoding_LZB = 1, } RDI_SectionEncodingEnum; typedef RDI_U32 RDI_Arch; typedef enum RDI_ArchEnum { -RDI_Arch_NULL = 0, -RDI_Arch_X64 = 1, + RDI_Arch_NULL = 0, + RDI_Arch_X64 = 1, } RDI_ArchEnum; typedef RDI_U8 RDI_RegCode; typedef enum RDI_RegCodeEnum { -RDI_RegCode_nil, + RDI_RegCode_nil, } RDI_RegCodeEnum; typedef RDI_U8 RDI_RegCodeX64; typedef enum RDI_RegCodeX64Enum { -RDI_RegCodeX64_nil = 0, -RDI_RegCodeX64_rax = 1, -RDI_RegCodeX64_rcx = 2, -RDI_RegCodeX64_rdx = 3, -RDI_RegCodeX64_rbx = 4, -RDI_RegCodeX64_rsp = 5, -RDI_RegCodeX64_rbp = 6, -RDI_RegCodeX64_rsi = 7, -RDI_RegCodeX64_rdi = 8, -RDI_RegCodeX64_r8 = 9, -RDI_RegCodeX64_r9 = 10, -RDI_RegCodeX64_r10 = 11, -RDI_RegCodeX64_r11 = 12, -RDI_RegCodeX64_r12 = 13, -RDI_RegCodeX64_r13 = 14, -RDI_RegCodeX64_r14 = 15, -RDI_RegCodeX64_r15 = 16, -RDI_RegCodeX64_es = 17, -RDI_RegCodeX64_cs = 18, -RDI_RegCodeX64_ss = 19, -RDI_RegCodeX64_ds = 20, -RDI_RegCodeX64_fs = 21, -RDI_RegCodeX64_gs = 22, -RDI_RegCodeX64_rip = 23, -RDI_RegCodeX64_rflags = 24, -RDI_RegCodeX64_dr0 = 25, -RDI_RegCodeX64_dr1 = 26, -RDI_RegCodeX64_dr2 = 27, -RDI_RegCodeX64_dr3 = 28, -RDI_RegCodeX64_dr4 = 29, -RDI_RegCodeX64_dr5 = 30, -RDI_RegCodeX64_dr6 = 31, -RDI_RegCodeX64_dr7 = 32, -RDI_RegCodeX64_st0 = 33, -RDI_RegCodeX64_st1 = 34, -RDI_RegCodeX64_st2 = 35, -RDI_RegCodeX64_st3 = 36, -RDI_RegCodeX64_st4 = 37, -RDI_RegCodeX64_st5 = 38, -RDI_RegCodeX64_st6 = 39, -RDI_RegCodeX64_st7 = 40, -RDI_RegCodeX64_zmm0 = 41, -RDI_RegCodeX64_zmm1 = 42, -RDI_RegCodeX64_zmm2 = 43, -RDI_RegCodeX64_zmm3 = 44, -RDI_RegCodeX64_zmm4 = 45, -RDI_RegCodeX64_zmm5 = 46, -RDI_RegCodeX64_zmm6 = 47, -RDI_RegCodeX64_zmm7 = 48, -RDI_RegCodeX64_zmm8 = 49, -RDI_RegCodeX64_zmm9 = 50, -RDI_RegCodeX64_zmm10 = 51, -RDI_RegCodeX64_zmm11 = 52, -RDI_RegCodeX64_zmm12 = 53, -RDI_RegCodeX64_zmm13 = 54, -RDI_RegCodeX64_zmm14 = 55, -RDI_RegCodeX64_zmm15 = 56, -RDI_RegCodeX64_zmm16 = 57, -RDI_RegCodeX64_zmm17 = 58, -RDI_RegCodeX64_zmm18 = 59, -RDI_RegCodeX64_zmm19 = 60, -RDI_RegCodeX64_zmm20 = 61, -RDI_RegCodeX64_zmm21 = 62, -RDI_RegCodeX64_zmm22 = 63, -RDI_RegCodeX64_zmm23 = 64, -RDI_RegCodeX64_zmm24 = 65, -RDI_RegCodeX64_zmm25 = 66, -RDI_RegCodeX64_zmm26 = 67, -RDI_RegCodeX64_zmm27 = 68, -RDI_RegCodeX64_zmm28 = 69, -RDI_RegCodeX64_zmm29 = 70, -RDI_RegCodeX64_zmm30 = 71, -RDI_RegCodeX64_zmm31 = 72, -RDI_RegCodeX64_k0 = 73, -RDI_RegCodeX64_k1 = 74, -RDI_RegCodeX64_k2 = 75, -RDI_RegCodeX64_k3 = 76, -RDI_RegCodeX64_k4 = 77, -RDI_RegCodeX64_k5 = 78, -RDI_RegCodeX64_k6 = 79, -RDI_RegCodeX64_k7 = 80, -RDI_RegCodeX64_mxcsr = 81, -RDI_RegCodeX64_fsbase = 82, -RDI_RegCodeX64_gsbase = 83, -RDI_RegCodeX64_fcw = 84, -RDI_RegCodeX64_fsw = 85, -RDI_RegCodeX64_ftw = 86, -RDI_RegCodeX64_fop = 87, -RDI_RegCodeX64_fcs = 88, -RDI_RegCodeX64_fds = 89, -RDI_RegCodeX64_fip = 90, -RDI_RegCodeX64_fdp = 91, -RDI_RegCodeX64_mxcsr_mask = 92, -RDI_RegCodeX64_cetmsr = 93, -RDI_RegCodeX64_cetssp = 94, + RDI_RegCodeX64_nil = 0, + RDI_RegCodeX64_rax = 1, + RDI_RegCodeX64_rcx = 2, + RDI_RegCodeX64_rdx = 3, + RDI_RegCodeX64_rbx = 4, + RDI_RegCodeX64_rsp = 5, + RDI_RegCodeX64_rbp = 6, + RDI_RegCodeX64_rsi = 7, + RDI_RegCodeX64_rdi = 8, + RDI_RegCodeX64_r8 = 9, + RDI_RegCodeX64_r9 = 10, + RDI_RegCodeX64_r10 = 11, + RDI_RegCodeX64_r11 = 12, + RDI_RegCodeX64_r12 = 13, + RDI_RegCodeX64_r13 = 14, + RDI_RegCodeX64_r14 = 15, + RDI_RegCodeX64_r15 = 16, + RDI_RegCodeX64_es = 17, + RDI_RegCodeX64_cs = 18, + RDI_RegCodeX64_ss = 19, + RDI_RegCodeX64_ds = 20, + RDI_RegCodeX64_fs = 21, + RDI_RegCodeX64_gs = 22, + RDI_RegCodeX64_rip = 23, + RDI_RegCodeX64_rflags = 24, + RDI_RegCodeX64_dr0 = 25, + RDI_RegCodeX64_dr1 = 26, + RDI_RegCodeX64_dr2 = 27, + RDI_RegCodeX64_dr3 = 28, + RDI_RegCodeX64_dr4 = 29, + RDI_RegCodeX64_dr5 = 30, + RDI_RegCodeX64_dr6 = 31, + RDI_RegCodeX64_dr7 = 32, + RDI_RegCodeX64_st0 = 33, + RDI_RegCodeX64_st1 = 34, + RDI_RegCodeX64_st2 = 35, + RDI_RegCodeX64_st3 = 36, + RDI_RegCodeX64_st4 = 37, + RDI_RegCodeX64_st5 = 38, + RDI_RegCodeX64_st6 = 39, + RDI_RegCodeX64_st7 = 40, + RDI_RegCodeX64_zmm0 = 41, + RDI_RegCodeX64_zmm1 = 42, + RDI_RegCodeX64_zmm2 = 43, + RDI_RegCodeX64_zmm3 = 44, + RDI_RegCodeX64_zmm4 = 45, + RDI_RegCodeX64_zmm5 = 46, + RDI_RegCodeX64_zmm6 = 47, + RDI_RegCodeX64_zmm7 = 48, + RDI_RegCodeX64_zmm8 = 49, + RDI_RegCodeX64_zmm9 = 50, + RDI_RegCodeX64_zmm10 = 51, + RDI_RegCodeX64_zmm11 = 52, + RDI_RegCodeX64_zmm12 = 53, + RDI_RegCodeX64_zmm13 = 54, + RDI_RegCodeX64_zmm14 = 55, + RDI_RegCodeX64_zmm15 = 56, + RDI_RegCodeX64_zmm16 = 57, + RDI_RegCodeX64_zmm17 = 58, + RDI_RegCodeX64_zmm18 = 59, + RDI_RegCodeX64_zmm19 = 60, + RDI_RegCodeX64_zmm20 = 61, + RDI_RegCodeX64_zmm21 = 62, + RDI_RegCodeX64_zmm22 = 63, + RDI_RegCodeX64_zmm23 = 64, + RDI_RegCodeX64_zmm24 = 65, + RDI_RegCodeX64_zmm25 = 66, + RDI_RegCodeX64_zmm26 = 67, + RDI_RegCodeX64_zmm27 = 68, + RDI_RegCodeX64_zmm28 = 69, + RDI_RegCodeX64_zmm29 = 70, + RDI_RegCodeX64_zmm30 = 71, + RDI_RegCodeX64_zmm31 = 72, + RDI_RegCodeX64_k0 = 73, + RDI_RegCodeX64_k1 = 74, + RDI_RegCodeX64_k2 = 75, + RDI_RegCodeX64_k3 = 76, + RDI_RegCodeX64_k4 = 77, + RDI_RegCodeX64_k5 = 78, + RDI_RegCodeX64_k6 = 79, + RDI_RegCodeX64_k7 = 80, + RDI_RegCodeX64_mxcsr = 81, + RDI_RegCodeX64_fsbase = 82, + RDI_RegCodeX64_gsbase = 83, + RDI_RegCodeX64_fcw = 84, + RDI_RegCodeX64_fsw = 85, + RDI_RegCodeX64_ftw = 86, + RDI_RegCodeX64_fop = 87, + RDI_RegCodeX64_fcs = 88, + RDI_RegCodeX64_fds = 89, + RDI_RegCodeX64_fip = 90, + RDI_RegCodeX64_fdp = 91, + RDI_RegCodeX64_mxcsr_mask = 92, + RDI_RegCodeX64_cetmsr = 93, + RDI_RegCodeX64_cetssp = 94, } RDI_RegCodeX64Enum; typedef RDI_U32 RDI_BinarySectionFlags; typedef enum RDI_BinarySectionFlagsEnum { -RDI_BinarySectionFlag_Read = 1<<0, -RDI_BinarySectionFlag_Write = 1<<1, -RDI_BinarySectionFlag_Execute = 1<<2, + RDI_BinarySectionFlag_Read = 1<<0, + RDI_BinarySectionFlag_Write = 1<<1, + RDI_BinarySectionFlag_Execute = 1<<2, } RDI_BinarySectionFlagsEnum; typedef RDI_U32 RDI_ChecksumKind; typedef enum RDI_ChecksumKindEnum { -RDI_ChecksumKind_NULL = 0, -RDI_ChecksumKind_MD5 = 1, -RDI_ChecksumKind_SHA1 = 2, -RDI_ChecksumKind_SHA256 = 3, -RDI_ChecksumKind_Timestamp = 4, -RDI_ChecksumKind_COUNT = 5, + RDI_ChecksumKind_NULL = 0, + RDI_ChecksumKind_MD5 = 1, + RDI_ChecksumKind_SHA1 = 2, + RDI_ChecksumKind_SHA256 = 3, + RDI_ChecksumKind_Timestamp = 4, + RDI_ChecksumKind_COUNT = 5, } RDI_ChecksumKindEnum; typedef RDI_U32 RDI_Language; typedef enum RDI_LanguageEnum { -RDI_Language_NULL = 0, -RDI_Language_C = 1, -RDI_Language_CPlusPlus = 2, -RDI_Language_Masm = 3, -RDI_Language_COUNT = 4, + RDI_Language_NULL = 0, + RDI_Language_C = 1, + RDI_Language_CPlusPlus = 2, + RDI_Language_Masm = 3, + RDI_Language_COUNT = 4, } RDI_LanguageEnum; typedef RDI_U16 RDI_TypeKind; typedef enum RDI_TypeKindEnum { -RDI_TypeKind_NULL = 0x0000, -RDI_TypeKind_Void = 0x0001, -RDI_TypeKind_Handle = 0x0002, -RDI_TypeKind_HResult = 0x0003, -RDI_TypeKind_Char8 = 0x0004, -RDI_TypeKind_Char16 = 0x0005, -RDI_TypeKind_Char32 = 0x0006, -RDI_TypeKind_UChar8 = 0x0007, -RDI_TypeKind_UChar16 = 0x0008, -RDI_TypeKind_UChar32 = 0x0009, -RDI_TypeKind_U8 = 0x000A, -RDI_TypeKind_U16 = 0x000B, -RDI_TypeKind_U32 = 0x000C, -RDI_TypeKind_U64 = 0x000D, -RDI_TypeKind_U128 = 0x000E, -RDI_TypeKind_U256 = 0x000F, -RDI_TypeKind_U512 = 0x0010, -RDI_TypeKind_S8 = 0x0011, -RDI_TypeKind_S16 = 0x0012, -RDI_TypeKind_S32 = 0x0013, -RDI_TypeKind_S64 = 0x0014, -RDI_TypeKind_S128 = 0x0015, -RDI_TypeKind_S256 = 0x0016, -RDI_TypeKind_S512 = 0x0017, -RDI_TypeKind_Bool = 0x0018, -RDI_TypeKind_BF16 = 0x0019, -RDI_TypeKind_F16 = 0x001A, -RDI_TypeKind_F32 = 0x001B, -RDI_TypeKind_F32PP = 0x001C, -RDI_TypeKind_F48 = 0x001D, -RDI_TypeKind_F64 = 0x001E, -RDI_TypeKind_F80 = 0x001F, -RDI_TypeKind_F96 = 0x0020, -RDI_TypeKind_F128 = 0x0021, -RDI_TypeKind_ComplexF32 = 0x0022, -RDI_TypeKind_ComplexF64 = 0x0023, -RDI_TypeKind_ComplexF80 = 0x0024, -RDI_TypeKind_ComplexF128 = 0x0025, -RDI_TypeKind_Decimal32 = 0x0026, -RDI_TypeKind_Decimal64 = 0x0027, -RDI_TypeKind_Decimal128 = 0x0028, -RDI_TypeKind_Modifier = 0x1000, -RDI_TypeKind_Ptr = 0x1001, -RDI_TypeKind_LRef = 0x1002, -RDI_TypeKind_RRef = 0x1003, -RDI_TypeKind_Array = 0x1004, -RDI_TypeKind_Function = 0x1005, -RDI_TypeKind_Method = 0x1006, -RDI_TypeKind_MemberPtr = 0x1007, -RDI_TypeKind_Struct = 0x2000, -RDI_TypeKind_Class = 0x2001, -RDI_TypeKind_Union = 0x2002, -RDI_TypeKind_Enum = 0x2003, -RDI_TypeKind_Alias = 0x2004, -RDI_TypeKind_IncompleteStruct = 0x2005, -RDI_TypeKind_IncompleteUnion = 0x2006, -RDI_TypeKind_IncompleteClass = 0x2007, -RDI_TypeKind_IncompleteEnum = 0x2008, -RDI_TypeKind_Bitfield = 0xF000, -RDI_TypeKind_Variadic = 0xF001, -RDI_TypeKind_Count = 0xF002, -RDI_TypeKind_FirstBuiltIn = RDI_TypeKind_Void, -RDI_TypeKind_LastBuiltIn = RDI_TypeKind_Decimal128, -RDI_TypeKind_FirstConstructed = RDI_TypeKind_Modifier, -RDI_TypeKind_LastConstructed = RDI_TypeKind_MemberPtr, -RDI_TypeKind_FirstUserDefined = RDI_TypeKind_Struct, -RDI_TypeKind_LastRecord = RDI_TypeKind_Union, -RDI_TypeKind_FirstIncomplete = RDI_TypeKind_IncompleteStruct, -RDI_TypeKind_LastIncomplete = RDI_TypeKind_IncompleteEnum, -RDI_TypeKind_FirstRecord = RDI_TypeKind_Struct, -RDI_TypeKind_LastUserDefined = RDI_TypeKind_IncompleteEnum, + RDI_TypeKind_NULL = 0x0000, + RDI_TypeKind_Void = 0x0001, + RDI_TypeKind_Handle = 0x0002, + RDI_TypeKind_HResult = 0x0003, + RDI_TypeKind_Char8 = 0x0004, + RDI_TypeKind_Char16 = 0x0005, + RDI_TypeKind_Char32 = 0x0006, + RDI_TypeKind_UChar8 = 0x0007, + RDI_TypeKind_UChar16 = 0x0008, + RDI_TypeKind_UChar32 = 0x0009, + RDI_TypeKind_U8 = 0x000A, + RDI_TypeKind_U16 = 0x000B, + RDI_TypeKind_U32 = 0x000C, + RDI_TypeKind_U64 = 0x000D, + RDI_TypeKind_U128 = 0x000E, + RDI_TypeKind_U256 = 0x000F, + RDI_TypeKind_U512 = 0x0010, + RDI_TypeKind_S8 = 0x0011, + RDI_TypeKind_S16 = 0x0012, + RDI_TypeKind_S32 = 0x0013, + RDI_TypeKind_S64 = 0x0014, + RDI_TypeKind_S128 = 0x0015, + RDI_TypeKind_S256 = 0x0016, + RDI_TypeKind_S512 = 0x0017, + RDI_TypeKind_Bool = 0x0018, + RDI_TypeKind_BF16 = 0x0019, + RDI_TypeKind_F16 = 0x001A, + RDI_TypeKind_F32 = 0x001B, + RDI_TypeKind_F32PP = 0x001C, + RDI_TypeKind_F48 = 0x001D, + RDI_TypeKind_F64 = 0x001E, + RDI_TypeKind_F80 = 0x001F, + RDI_TypeKind_F96 = 0x0020, + RDI_TypeKind_F128 = 0x0021, + RDI_TypeKind_ComplexF32 = 0x0022, + RDI_TypeKind_ComplexF64 = 0x0023, + RDI_TypeKind_ComplexF80 = 0x0024, + RDI_TypeKind_ComplexF128 = 0x0025, + RDI_TypeKind_Decimal32 = 0x0026, + RDI_TypeKind_Decimal64 = 0x0027, + RDI_TypeKind_Decimal128 = 0x0028, + RDI_TypeKind_Modifier = 0x1000, + RDI_TypeKind_Ptr = 0x1001, + RDI_TypeKind_LRef = 0x1002, + RDI_TypeKind_RRef = 0x1003, + RDI_TypeKind_Array = 0x1004, + RDI_TypeKind_Function = 0x1005, + RDI_TypeKind_Method = 0x1006, + RDI_TypeKind_MemberPtr = 0x1007, + RDI_TypeKind_Struct = 0x2000, + RDI_TypeKind_Class = 0x2001, + RDI_TypeKind_Union = 0x2002, + RDI_TypeKind_Enum = 0x2003, + RDI_TypeKind_Alias = 0x2004, + RDI_TypeKind_IncompleteStruct = 0x2005, + RDI_TypeKind_IncompleteUnion = 0x2006, + RDI_TypeKind_IncompleteClass = 0x2007, + RDI_TypeKind_IncompleteEnum = 0x2008, + RDI_TypeKind_Bitfield = 0xF000, + RDI_TypeKind_Variadic = 0xF001, + RDI_TypeKind_Count = 0xF002, + RDI_TypeKind_FirstBuiltIn = RDI_TypeKind_Void, + RDI_TypeKind_LastBuiltIn = RDI_TypeKind_Decimal128, + RDI_TypeKind_FirstConstructed = RDI_TypeKind_Modifier, + RDI_TypeKind_LastConstructed = RDI_TypeKind_MemberPtr, + RDI_TypeKind_FirstUserDefined = RDI_TypeKind_Struct, + RDI_TypeKind_LastRecord = RDI_TypeKind_Union, + RDI_TypeKind_FirstIncomplete = RDI_TypeKind_IncompleteStruct, + RDI_TypeKind_LastIncomplete = RDI_TypeKind_IncompleteEnum, + RDI_TypeKind_FirstRecord = RDI_TypeKind_Struct, + RDI_TypeKind_LastUserDefined = RDI_TypeKind_IncompleteEnum, } RDI_TypeKindEnum; typedef RDI_U16 RDI_TypeModifierFlags; typedef enum RDI_TypeModifierFlagsEnum { -RDI_TypeModifierFlag_Const = 1<<0, -RDI_TypeModifierFlag_Volatile = 1<<1, -RDI_TypeModifierFlag_Restrict = 1<<2, + RDI_TypeModifierFlag_Const = 1<<0, + RDI_TypeModifierFlag_Volatile = 1<<1, + RDI_TypeModifierFlag_Restrict = 1<<2, } RDI_TypeModifierFlagsEnum; typedef RDI_U32 RDI_UDTFlags; typedef enum RDI_UDTFlagsEnum { -RDI_UDTFlag_EnumMembers = 1<<0, + RDI_UDTFlag_EnumMembers = 1<<0, } RDI_UDTFlagsEnum; typedef RDI_U16 RDI_MemberKind; typedef enum RDI_MemberKindEnum { -RDI_MemberKind_NULL = 0x0000, -RDI_MemberKind_DataField = 0x0001, -RDI_MemberKind_StaticData = 0x0002, -RDI_MemberKind_Method = 0x0100, -RDI_MemberKind_StaticMethod = 0x0101, -RDI_MemberKind_VirtualMethod = 0x0102, -RDI_MemberKind_VTablePtr = 0x0200, -RDI_MemberKind_Base = 0x0201, -RDI_MemberKind_VirtualBase = 0x0202, -RDI_MemberKind_NestedType = 0x0300, + RDI_MemberKind_NULL = 0x0000, + RDI_MemberKind_DataField = 0x0001, + RDI_MemberKind_StaticData = 0x0002, + RDI_MemberKind_Method = 0x0100, + RDI_MemberKind_StaticMethod = 0x0101, + RDI_MemberKind_VirtualMethod = 0x0102, + RDI_MemberKind_VTablePtr = 0x0200, + RDI_MemberKind_Base = 0x0201, + RDI_MemberKind_VirtualBase = 0x0202, + RDI_MemberKind_NestedType = 0x0300, } RDI_MemberKindEnum; typedef RDI_U32 RDI_LinkFlags; typedef enum RDI_LinkFlagsEnum { -RDI_LinkFlag_External = 1<<0, -RDI_LinkFlag_TypeScoped = 1<<1, -RDI_LinkFlag_ProcScoped = 1<<2, + RDI_LinkFlag_External = 1<<0, + RDI_LinkFlag_TypeScoped = 1<<1, + RDI_LinkFlag_ProcScoped = 1<<2, } RDI_LinkFlagsEnum; typedef RDI_U32 RDI_LocalKind; typedef enum RDI_LocalKindEnum { -RDI_LocalKind_NULL = 0x0, -RDI_LocalKind_Parameter = 0x1, -RDI_LocalKind_Variable = 0x2, + RDI_LocalKind_NULL = 0x0, + RDI_LocalKind_Parameter = 0x1, + RDI_LocalKind_Variable = 0x2, } RDI_LocalKindEnum; typedef RDI_U8 RDI_LocationKind; typedef enum RDI_LocationKindEnum { -RDI_LocationKind_NULL = 0x0, -RDI_LocationKind_AddrBytecodeStream = 0x1, -RDI_LocationKind_ValBytecodeStream = 0x2, -RDI_LocationKind_AddrRegPlusU16 = 0x3, -RDI_LocationKind_AddrAddrRegPlusU16 = 0x4, -RDI_LocationKind_ValReg = 0x5, + RDI_LocationKind_NULL = 0x0, + RDI_LocationKind_AddrBytecodeStream = 0x1, + RDI_LocationKind_ValBytecodeStream = 0x2, + RDI_LocationKind_AddrRegPlusU16 = 0x3, + RDI_LocationKind_AddrAddrRegPlusU16 = 0x4, + RDI_LocationKind_ValReg = 0x5, } RDI_LocationKindEnum; typedef RDI_U8 RDI_EvalOp; typedef enum RDI_EvalOpEnum { -RDI_EvalOp_Stop = 0, -RDI_EvalOp_Noop = 1, -RDI_EvalOp_Cond = 2, -RDI_EvalOp_Skip = 3, -RDI_EvalOp_MemRead = 4, -RDI_EvalOp_RegRead = 5, -RDI_EvalOp_RegReadDyn = 6, -RDI_EvalOp_FrameOff = 7, -RDI_EvalOp_ModuleOff = 8, -RDI_EvalOp_TLSOff = 9, -RDI_EvalOp_ObjectOff = 10, -RDI_EvalOp_CFA = 11, -RDI_EvalOp_ConstU8 = 12, -RDI_EvalOp_ConstU16 = 13, -RDI_EvalOp_ConstU32 = 14, -RDI_EvalOp_ConstU64 = 15, -RDI_EvalOp_ConstU128 = 16, -RDI_EvalOp_ConstString = 17, -RDI_EvalOp_Abs = 18, -RDI_EvalOp_Neg = 19, -RDI_EvalOp_Add = 20, -RDI_EvalOp_Sub = 21, -RDI_EvalOp_Mul = 22, -RDI_EvalOp_Div = 23, -RDI_EvalOp_Mod = 24, -RDI_EvalOp_LShift = 25, -RDI_EvalOp_RShift = 26, -RDI_EvalOp_BitAnd = 27, -RDI_EvalOp_BitOr = 28, -RDI_EvalOp_BitXor = 29, -RDI_EvalOp_BitNot = 30, -RDI_EvalOp_LogAnd = 31, -RDI_EvalOp_LogOr = 32, -RDI_EvalOp_LogNot = 33, -RDI_EvalOp_EqEq = 34, -RDI_EvalOp_NtEq = 35, -RDI_EvalOp_LsEq = 36, -RDI_EvalOp_GrEq = 37, -RDI_EvalOp_Less = 38, -RDI_EvalOp_Grtr = 39, -RDI_EvalOp_Trunc = 40, -RDI_EvalOp_TruncSigned = 41, -RDI_EvalOp_Convert = 42, -RDI_EvalOp_Pick = 43, -RDI_EvalOp_Pop = 44, -RDI_EvalOp_Insert = 45, -RDI_EvalOp_ValueRead = 46, -RDI_EvalOp_ByteSwap = 47, -RDI_EvalOp_CallSiteValue = 48, -RDI_EvalOp_PartialValue = 49, -RDI_EvalOp_PartialValueBit = 50, -RDI_EvalOp_Swap = 51, -RDI_EvalOp_PushCfa = 52, -RDI_EvalOp_COUNT = 53, + RDI_EvalOp_Stop = 0, + RDI_EvalOp_Noop = 1, + RDI_EvalOp_Cond = 2, + RDI_EvalOp_Skip = 3, + RDI_EvalOp_MemRead = 4, + RDI_EvalOp_RegRead = 5, + RDI_EvalOp_RegReadDyn = 6, + RDI_EvalOp_FrameOff = 7, + RDI_EvalOp_ModuleOff = 8, + RDI_EvalOp_TLSOff = 9, + RDI_EvalOp_ObjectOff = 10, + RDI_EvalOp_CFA = 11, + RDI_EvalOp_ConstU8 = 12, + RDI_EvalOp_ConstU16 = 13, + RDI_EvalOp_ConstU32 = 14, + RDI_EvalOp_ConstU64 = 15, + RDI_EvalOp_ConstU128 = 16, + RDI_EvalOp_ConstString = 17, + RDI_EvalOp_Abs = 18, + RDI_EvalOp_Neg = 19, + RDI_EvalOp_Add = 20, + RDI_EvalOp_Sub = 21, + RDI_EvalOp_Mul = 22, + RDI_EvalOp_Div = 23, + RDI_EvalOp_Mod = 24, + RDI_EvalOp_LShift = 25, + RDI_EvalOp_RShift = 26, + RDI_EvalOp_BitAnd = 27, + RDI_EvalOp_BitOr = 28, + RDI_EvalOp_BitXor = 29, + RDI_EvalOp_BitNot = 30, + RDI_EvalOp_LogAnd = 31, + RDI_EvalOp_LogOr = 32, + RDI_EvalOp_LogNot = 33, + RDI_EvalOp_EqEq = 34, + RDI_EvalOp_NtEq = 35, + RDI_EvalOp_LsEq = 36, + RDI_EvalOp_GrEq = 37, + RDI_EvalOp_Less = 38, + RDI_EvalOp_Grtr = 39, + RDI_EvalOp_Trunc = 40, + RDI_EvalOp_TruncSigned = 41, + RDI_EvalOp_Convert = 42, + RDI_EvalOp_Pick = 43, + RDI_EvalOp_Pop = 44, + RDI_EvalOp_Insert = 45, + RDI_EvalOp_ValueRead = 46, + RDI_EvalOp_ByteSwap = 47, + RDI_EvalOp_CallSiteValue = 48, + RDI_EvalOp_PartialValue = 49, + RDI_EvalOp_PartialValueBit = 50, + RDI_EvalOp_Swap = 51, + RDI_EvalOp_PushCfa = 52, + RDI_EvalOp_COUNT = 53, } RDI_EvalOpEnum; typedef RDI_U8 RDI_EvalTypeGroup; typedef enum RDI_EvalTypeGroupEnum { -RDI_EvalTypeGroup_Other = 0, -RDI_EvalTypeGroup_U = 1, -RDI_EvalTypeGroup_S = 2, -RDI_EvalTypeGroup_F32 = 3, -RDI_EvalTypeGroup_F64 = 4, -RDI_EvalTypeGroup_F80 = 5, -RDI_EvalTypeGroup_F128 = 6, -RDI_EvalTypeGroup_COUNT = 7, + RDI_EvalTypeGroup_Other = 0, + RDI_EvalTypeGroup_U = 1, + RDI_EvalTypeGroup_S = 2, + RDI_EvalTypeGroup_F32 = 3, + RDI_EvalTypeGroup_F64 = 4, + RDI_EvalTypeGroup_F80 = 5, + RDI_EvalTypeGroup_F128 = 6, + RDI_EvalTypeGroup_COUNT = 7, } RDI_EvalTypeGroupEnum; typedef RDI_U8 RDI_EvalConversionKind; typedef enum RDI_EvalConversionKindEnum { -RDI_EvalConversionKind_Noop = 0, -RDI_EvalConversionKind_Legal = 1, -RDI_EvalConversionKind_OtherToOther = 2, -RDI_EvalConversionKind_ToOther = 3, -RDI_EvalConversionKind_FromOther = 4, -RDI_EvalConversionKind_COUNT = 5, + RDI_EvalConversionKind_Noop = 0, + RDI_EvalConversionKind_Legal = 1, + RDI_EvalConversionKind_OtherToOther = 2, + RDI_EvalConversionKind_ToOther = 3, + RDI_EvalConversionKind_FromOther = 4, + RDI_EvalConversionKind_COUNT = 5, } RDI_EvalConversionKindEnum; typedef RDI_U32 RDI_NameMapKind; typedef enum RDI_NameMapKindEnum { -RDI_NameMapKind_NULL = 0, -RDI_NameMapKind_GlobalVariables = 1, -RDI_NameMapKind_ThreadVariables = 2, -RDI_NameMapKind_Constants = 3, -RDI_NameMapKind_Procedures = 4, -RDI_NameMapKind_Types = 5, -RDI_NameMapKind_LinkNameProcedures = 6, -RDI_NameMapKind_NormalSourcePaths = 7, -RDI_NameMapKind_COUNT = 8, + RDI_NameMapKind_NULL = 0, + RDI_NameMapKind_GlobalVariables = 1, + RDI_NameMapKind_ThreadVariables = 2, + RDI_NameMapKind_Constants = 3, + RDI_NameMapKind_Procedures = 4, + RDI_NameMapKind_Types = 5, + RDI_NameMapKind_LinkNameProcedures = 6, + RDI_NameMapKind_NormalSourcePaths = 7, + RDI_NameMapKind_COUNT = 8, } RDI_NameMapKindEnum; #define RDI_Header_XList \ @@ -1126,126 +1126,126 @@ typedef RDI_U32_Table RDI_U32_NameMapNodes; typedef struct RDI_Header RDI_Header; struct RDI_Header { -RDI_U64 magic; -RDI_U32 encoding_version; -RDI_U32 data_section_off; -RDI_U32 data_section_count; + RDI_U64 magic; + RDI_U32 encoding_version; + RDI_U32 data_section_off; + RDI_U32 data_section_count; }; typedef struct RDI_Section RDI_Section; struct RDI_Section { -RDI_SectionEncoding encoding; -RDI_U32 pad; -RDI_U64 off; -RDI_U64 encoded_size; -RDI_U64 unpacked_size; + RDI_SectionEncoding encoding; + RDI_U32 pad; + RDI_U64 off; + RDI_U64 encoded_size; + RDI_U64 unpacked_size; }; typedef struct RDI_VMapEntry RDI_VMapEntry; struct RDI_VMapEntry { -RDI_U64 voff; -RDI_U64 idx; + RDI_U64 voff; + RDI_U64 idx; }; typedef struct RDI_TopLevelInfo RDI_TopLevelInfo; struct RDI_TopLevelInfo { -RDI_Arch arch; -RDI_U32 exe_name_string_idx; -RDI_U64 exe_hash; -RDI_U64 voff_max; -RDI_GUID guid; -RDI_U32 producer_name_string_idx; + RDI_Arch arch; + RDI_U32 exe_name_string_idx; + RDI_U64 exe_hash; + RDI_U64 voff_max; + RDI_GUID guid; + RDI_U32 producer_name_string_idx; }; typedef struct RDI_BinarySection RDI_BinarySection; struct RDI_BinarySection { -RDI_U32 name_string_idx; -RDI_BinarySectionFlags flags; -RDI_U64 voff_first; -RDI_U64 voff_opl; -RDI_U64 foff_first; -RDI_U64 foff_opl; + RDI_U32 name_string_idx; + RDI_BinarySectionFlags flags; + RDI_U64 voff_first; + RDI_U64 voff_opl; + RDI_U64 foff_first; + RDI_U64 foff_opl; }; typedef struct RDI_FilePathNode RDI_FilePathNode; struct RDI_FilePathNode { -RDI_U32 name_string_idx; -RDI_U32 parent_path_node; -RDI_U32 first_child; -RDI_U32 next_sibling; -RDI_U32 source_file_idx; + RDI_U32 name_string_idx; + RDI_U32 parent_path_node; + RDI_U32 first_child; + RDI_U32 next_sibling; + RDI_U32 source_file_idx; }; typedef struct RDI_SourceFile RDI_SourceFile; struct RDI_SourceFile { -RDI_U32 file_path_node_idx; -RDI_U32 normal_full_path_string_idx; -RDI_U32 source_line_map_idx; -RDI_ChecksumKind checksum_kind; -RDI_U32 checksum_idx; + RDI_U32 file_path_node_idx; + RDI_U32 normal_full_path_string_idx; + RDI_U32 source_line_map_idx; + RDI_ChecksumKind checksum_kind; + RDI_U32 checksum_idx; }; typedef struct RDI_Unit RDI_Unit; struct RDI_Unit { -RDI_U32 unit_name_string_idx; -RDI_U32 compiler_name_string_idx; -RDI_U32 source_file_path_node; -RDI_U32 object_file_path_node; -RDI_U32 archive_file_path_node; -RDI_U32 build_path_node; -RDI_Language language; -RDI_U32 line_table_idx; + RDI_U32 unit_name_string_idx; + RDI_U32 compiler_name_string_idx; + RDI_U32 source_file_path_node; + RDI_U32 object_file_path_node; + RDI_U32 archive_file_path_node; + RDI_U32 build_path_node; + RDI_Language language; + RDI_U32 line_table_idx; }; typedef struct RDI_LineTable RDI_LineTable; struct RDI_LineTable { -RDI_U32 voffs_base_idx; -RDI_U32 lines_base_idx; -RDI_U32 cols_base_idx; -RDI_U32 lines_count; -RDI_U32 cols_count; + RDI_U32 voffs_base_idx; + RDI_U32 lines_base_idx; + RDI_U32 cols_base_idx; + RDI_U32 lines_count; + RDI_U32 cols_count; }; typedef struct RDI_Line RDI_Line; struct RDI_Line { -RDI_U32 file_idx; -RDI_U32 line_num; + RDI_U32 file_idx; + RDI_U32 line_num; }; typedef struct RDI_Column RDI_Column; struct RDI_Column { -RDI_U16 col_first; -RDI_U16 col_opl; + RDI_U16 col_first; + RDI_U16 col_opl; }; typedef struct RDI_SourceLineMap RDI_SourceLineMap; struct RDI_SourceLineMap { -RDI_U32 line_count; -RDI_U32 voff_count; -RDI_U32 line_map_nums_base_idx; -RDI_U32 line_map_range_base_idx; -RDI_U32 line_map_voff_base_idx; + RDI_U32 line_count; + RDI_U32 voff_count; + RDI_U32 line_map_nums_base_idx; + RDI_U32 line_map_range_base_idx; + RDI_U32 line_map_voff_base_idx; }; typedef struct RDI_TypeNode RDI_TypeNode; struct RDI_TypeNode { -RDI_TypeKind kind; -RDI_U16 flags; -RDI_U32 byte_size; - - union + RDI_TypeKind kind; + RDI_U16 flags; + RDI_U32 byte_size; + + union { // kind is 'built-in' struct @@ -1292,159 +1292,159 @@ RDI_U32 byte_size; typedef struct RDI_UDT RDI_UDT; struct RDI_UDT { -RDI_U32 self_type_idx; -RDI_UDTFlags flags; -RDI_U32 member_first; -RDI_U32 member_count; -RDI_U32 file_idx; -RDI_U32 line; -RDI_U32 col; + RDI_U32 self_type_idx; + RDI_UDTFlags flags; + RDI_U32 member_first; + RDI_U32 member_count; + RDI_U32 file_idx; + RDI_U32 line; + RDI_U32 col; }; typedef struct RDI_Member RDI_Member; struct RDI_Member { -RDI_MemberKind kind; -RDI_U16 pad; -RDI_U32 name_string_idx; -RDI_U32 type_idx; -RDI_U32 off; + RDI_MemberKind kind; + RDI_U16 pad; + RDI_U32 name_string_idx; + RDI_U32 type_idx; + RDI_U32 off; }; typedef struct RDI_EnumMember RDI_EnumMember; struct RDI_EnumMember { -RDI_U32 name_string_idx; -RDI_U32 pad; -RDI_U64 val; + RDI_U32 name_string_idx; + RDI_U32 pad; + RDI_U64 val; }; typedef struct RDI_GlobalVariable RDI_GlobalVariable; struct RDI_GlobalVariable { -RDI_U32 name_string_idx; -RDI_LinkFlags link_flags; -RDI_U64 voff; -RDI_U32 type_idx; -RDI_U32 container_idx; + RDI_U32 name_string_idx; + RDI_LinkFlags link_flags; + RDI_U64 voff; + RDI_U32 type_idx; + RDI_U32 container_idx; }; typedef struct RDI_ThreadVariable RDI_ThreadVariable; struct RDI_ThreadVariable { -RDI_U32 name_string_idx; -RDI_LinkFlags link_flags; -RDI_U32 tls_off; -RDI_U32 type_idx; -RDI_U32 container_idx; + RDI_U32 name_string_idx; + RDI_LinkFlags link_flags; + RDI_U32 tls_off; + RDI_U32 type_idx; + RDI_U32 container_idx; }; typedef struct RDI_Constant RDI_Constant; struct RDI_Constant { -RDI_U32 name_string_idx; -RDI_U32 type_idx; -RDI_U32 constant_value_idx; + RDI_U32 name_string_idx; + RDI_U32 type_idx; + RDI_U32 constant_value_idx; }; typedef struct RDI_Procedure RDI_Procedure; struct RDI_Procedure { -RDI_U32 name_string_idx; -RDI_U32 link_name_string_idx; -RDI_LinkFlags link_flags; -RDI_U32 type_idx; -RDI_U32 root_scope_idx; -RDI_U32 container_idx; -RDI_U32 frame_base_location_first; -RDI_U32 frame_base_location_opl; + RDI_U32 name_string_idx; + RDI_U32 link_name_string_idx; + RDI_LinkFlags link_flags; + RDI_U32 type_idx; + RDI_U32 root_scope_idx; + RDI_U32 container_idx; + RDI_U32 frame_base_location_first; + RDI_U32 frame_base_location_opl; }; typedef struct RDI_Scope RDI_Scope; struct RDI_Scope { -RDI_U32 proc_idx; -RDI_U32 parent_scope_idx; -RDI_U32 first_child_scope_idx; -RDI_U32 next_sibling_scope_idx; -RDI_U32 voff_range_first; -RDI_U32 voff_range_opl; -RDI_U32 local_first; -RDI_U32 local_count; -RDI_U32 inline_site_idx; + RDI_U32 proc_idx; + RDI_U32 parent_scope_idx; + RDI_U32 first_child_scope_idx; + RDI_U32 next_sibling_scope_idx; + RDI_U32 voff_range_first; + RDI_U32 voff_range_opl; + RDI_U32 local_first; + RDI_U32 local_count; + RDI_U32 inline_site_idx; }; typedef struct RDI_InlineSite RDI_InlineSite; struct RDI_InlineSite { -RDI_U32 name_string_idx; -RDI_U32 type_idx; -RDI_U32 owner_type_idx; -RDI_U32 line_table_idx; + RDI_U32 name_string_idx; + RDI_U32 type_idx; + RDI_U32 owner_type_idx; + RDI_U32 line_table_idx; }; typedef struct RDI_Local RDI_Local; struct RDI_Local { -RDI_LocalKind kind; -RDI_U32 name_string_idx; -RDI_U32 type_idx; -RDI_U32 pad; -RDI_U32 location_first; -RDI_U32 location_opl; + RDI_LocalKind kind; + RDI_U32 name_string_idx; + RDI_U32 type_idx; + RDI_U32 pad; + RDI_U32 location_first; + RDI_U32 location_opl; }; typedef struct RDI_LocationBlock RDI_LocationBlock; struct RDI_LocationBlock { -RDI_U32 scope_off_first; -RDI_U32 scope_off_opl; -RDI_U32 location_data_off; + RDI_U32 scope_off_first; + RDI_U32 scope_off_opl; + RDI_U32 location_data_off; }; typedef struct RDI_LocationBytecodeStream RDI_LocationBytecodeStream; struct RDI_LocationBytecodeStream { -RDI_LocationKind kind; + RDI_LocationKind kind; }; typedef struct RDI_LocationRegPlusU16 RDI_LocationRegPlusU16; struct RDI_LocationRegPlusU16 { -RDI_LocationKind kind; -RDI_RegCode reg_code; -RDI_U16 offset; + RDI_LocationKind kind; + RDI_RegCode reg_code; + RDI_U16 offset; }; typedef struct RDI_LocationReg RDI_LocationReg; struct RDI_LocationReg { -RDI_LocationKind kind; -RDI_RegCode reg_code; + RDI_LocationKind kind; + RDI_RegCode reg_code; }; typedef struct RDI_NameMap RDI_NameMap; struct RDI_NameMap { -RDI_U32 bucket_base_idx; -RDI_U32 node_base_idx; -RDI_U32 bucket_count; -RDI_U32 node_count; + RDI_U32 bucket_base_idx; + RDI_U32 node_base_idx; + RDI_U32 bucket_count; + RDI_U32 node_count; }; typedef struct RDI_NameMapBucket RDI_NameMapBucket; struct RDI_NameMapBucket { -RDI_U32 first_node; -RDI_U32 node_count; + RDI_U32 first_node; + RDI_U32 node_count; }; typedef struct RDI_NameMapNode RDI_NameMapNode; struct RDI_NameMapNode { -RDI_U32 string_idx; -RDI_U32 match_count; -RDI_U32 match_idx_or_idx_run_first; + RDI_U32 string_idx; + RDI_U32 match_count; + RDI_U32 match_idx_or_idx_run_first; }; typedef RDI_TopLevelInfo RDI_SectionElementType_TopLevelInfo; diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 23cd540b..6537fca1 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -5,51 +5,51 @@ //~ rjf: API Implementation Helper Macros #define RDIM_IdxedChunkListPush(arena, list, chunk_type, element_type, cap_value, result, ...) \ - element_type *result = 0; \ - do \ - { \ - chunk_type *n = list->last; \ - if(n == 0 || n->count >= n->cap) \ - { \ - n = rdim_push_array(arena, chunk_type, 1); \ - n->cap = cap_value; \ - n->base_idx = list->total_count; \ - __VA_ARGS__; \ - n->v = rdim_push_array_no_zero(arena, element_type, n->cap); \ - RDIM_SLLQueuePush(list->first, list->last, n); \ - list->chunk_count += 1; \ - } \ - result = &n->v[n->count]; \ - result->chunk = n; \ - n->count += 1; \ - list->total_count += 1; \ - }while(0) +element_type *result = 0; \ +do \ +{ \ +chunk_type *n = list->last; \ +if(n == 0 || n->count >= n->cap) \ +{ \ +n = rdim_push_array(arena, chunk_type, 1); \ +n->cap = cap_value; \ +n->base_idx = list->total_count; \ +__VA_ARGS__; \ +n->v = rdim_push_array_no_zero(arena, element_type, n->cap); \ +RDIM_SLLQueuePush(list->first, list->last, n); \ +list->chunk_count += 1; \ +} \ +result = &n->v[n->count]; \ +result->chunk = n; \ +n->count += 1; \ +list->total_count += 1; \ +}while(0) #define RDIM_IdxedChunkListElementGetIdx(ptr, result) \ - RDI_U64 idx = 0; \ - if(ptr != 0 && ptr->chunk != 0) \ - { \ - idx = ptr->chunk->base_idx + (ptr - ptr->chunk->v) + 1; \ - } +RDI_U64 idx = 0; \ +if(ptr != 0 && ptr->chunk != 0) \ +{ \ +idx = ptr->chunk->base_idx + (ptr - ptr->chunk->v) + 1; \ +} #define RDIM_IdxedChunkListConcatInPlace(chunk_type, dst, to_push, ...) \ - for(chunk_type *n = to_push->first; n != 0; n = n->next) \ - { \ - n->base_idx += dst->total_count; \ - } \ - if(dst->last != 0 && to_push->first != 0) \ - { \ - dst->last->next = to_push->first; \ - dst->last = to_push->last; \ - dst->chunk_count += to_push->chunk_count; \ - dst->total_count += to_push->total_count; \ - __VA_ARGS__; \ - } \ - else if(dst->first == 0) \ - { \ - rdim_memcpy_struct(dst, to_push); \ - } \ - rdim_memzero_struct(to_push); +for(chunk_type *n = to_push->first; n != 0; n = n->next) \ +{ \ +n->base_idx += dst->total_count; \ +} \ +if(dst->last != 0 && to_push->first != 0) \ +{ \ +dst->last->next = to_push->first; \ +dst->last = to_push->last; \ +dst->chunk_count += to_push->chunk_count; \ +dst->total_count += to_push->total_count; \ +__VA_ARGS__; \ +} \ +else if(dst->first == 0) \ +{ \ +rdim_memcpy_struct(dst, to_push); \ +} \ +rdim_memzero_struct(to_push); //////////////////////////////// //~ rjf: Basic Helpers diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 814ed301..70a82105 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1757,4 +1757,9 @@ RDI_PROC RDIM_SerializedSection rdim_serialized_section_make_unpacked(void *data RDI_PROC RDIM_SerializedSectionBundle rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results); RDI_PROC RDIM_String8List rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle); +//////////////////////////////// +//~ rjf: [Serializing] Parsed RDI -> Bake Results + +RDI_PROC RDIM_BakeResults *rdim_bake_results_from_rdi(RDIM_Arena *arena, RDI_Parsed *rdi); + #endif // RDI_MAKE_H diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index 91f3380d..5c9eea61 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -2432,7 +2432,7 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_lenient_task) } else { // replace uniuqe type name with hash udt_info.unique_name.str = udt_info.name.str + udt_info.name.size + 1; - udt_info.unique_name.size = raddbg_snprintf(udt_info.unique_name.cstr, udt_info.unique_name.size, "%llx", name_hash); + udt_info.unique_name.size = raddbg_snprintf((char *)udt_info.unique_name.str, udt_info.unique_name.size, "%llx", name_hash); // update leaf header U64 new_size = sizeof(CV_LeafKind) + @@ -2498,7 +2498,7 @@ THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_full_task) } // replace name with hash - udt_info.name.size = raddbg_snprintf(udt_info.name.cstr, udt_info.name.size, "%llx", name_hash); + udt_info.name.size = raddbg_snprintf((char *)udt_info.name.str, udt_info.name.size, "%llx", name_hash); // parse struct size CV_NumericParsed dummy; diff --git a/src/msf/msf_parse.c b/src/msf/msf_parse.c index 02912ab7..23f0df63 100644 --- a/src/msf/msf_parse.c +++ b/src/msf/msf_parse.c @@ -9,7 +9,7 @@ msf_raw_stream_table_from_data(Arena *arena, String8 msf_data) { Temp scratch = scratch_begin(&arena, 1); - MSF_RawStreamTable *result = 0; + MSF_RawStreamTable *result = push_array(arena, MSF_RawStreamTable, 1); //- determine msf type U32 index_size = 0; @@ -214,7 +214,6 @@ msf_raw_stream_table_from_data(Arena *arena, String8 msf_data) } if (got_streams) { - result = push_array(arena, MSF_RawStreamTable, 1); result->total_page_count = whole_file_page_count; result->index_size = index_size; result->page_size = page_size; diff --git a/src/os/core/linux/os_core_linux.c b/src/os/core/linux/os_core_linux.c index 672151e6..b1ea7097 100644 --- a/src/os/core/linux/os_core_linux.c +++ b/src/os/core/linux/os_core_linux.c @@ -159,7 +159,7 @@ os_get_process_start_time_unix(void) pid_t pid = getpid(); String8 path = push_str8f(scratch.arena, "/proc/%u", pid); struct stat st; - int err = stat(path.cstr, &st); + int err = stat((char *)path.str, &st); if(err == 0) { start_time = st.st_mtime; @@ -240,7 +240,7 @@ os_set_thread_name(String8 name) Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); pthread_t current_thread = pthread_self(); - pthread_setname_np(current_thread, name_copy.cstr); + pthread_setname_np(current_thread, (char *)name_copy.str); scratch_end(scratch); } @@ -285,7 +285,7 @@ os_file_open(OS_AccessFlags flags, String8 path) lnx_flags |= O_CREAT; } lnx_flags |= O_CLOEXEC; - int fd = open(path_copy.cstr, lnx_flags, 0755); + int fd = open((char *)path_copy.str, lnx_flags, 0755); OS_Handle handle = {0}; if(fd != -1) { @@ -400,7 +400,7 @@ os_delete_file_at_path(String8 path) Temp scratch = scratch_begin(0, 0); B32 result = 0; String8 path_copy = push_str8_copy(scratch.arena, path); - if(remove(path_copy.cstr) != -1) + if(remove((char *)path_copy.str) != -1) { result = 1; } @@ -447,8 +447,8 @@ os_move_file_path(String8 dst, String8 src) B32 good = 0; Temp scratch = scratch_begin(0, 0); { - char *src_cstr = push_str8_copy(scratch.arena, src).cstr; - char *dst_cstr = push_str8_copy(scratch.arena, dst).cstr; + char *src_cstr = (char *)str8_copy(scratch.arena, src).str; + char *dst_cstr = (char *)str8_copy(scratch.arena, dst).str; int rename_result = rename(src_cstr, dst_cstr); good = (rename_result != -1); } @@ -460,10 +460,10 @@ internal String8 os_full_path_from_path(Arena *arena, String8 path) { Temp scratch = scratch_begin(&arena, 1); - String8 path_copy = push_str8_copy(scratch.arena, path); + String8 path_copy = str8_copy(scratch.arena, path); char buffer[PATH_MAX] = {0}; - realpath(path_copy.cstr, buffer); - String8 result = push_str8_copy(arena, str8_cstring(buffer)); + realpath((char *)path_copy.str, buffer); + String8 result = str8_copy(arena, str8_cstring(buffer)); scratch_end(scratch); return result; } @@ -473,7 +473,7 @@ os_file_path_exists(String8 path) { Temp scratch = scratch_begin(0, 0); String8 path_copy = push_str8_copy(scratch.arena, path); - int access_result = access(path_copy.cstr, F_OK); + int access_result = access((char *)path_copy.str, F_OK); B32 result = 0; if(access_result == 0) { @@ -487,9 +487,9 @@ internal B32 os_folder_path_exists(String8 path) { Temp scratch = scratch_begin(0, 0); - B32 exists = 0; - String8 path_copy = push_str8_copy(scratch.arena, path); - DIR *handle = opendir(path_copy.cstr); + B32 exists = 0; + String8 path_copy = str8_copy(scratch.arena, path); + DIR *handle = opendir((char *)path_copy.str); if(handle) { closedir(handle); @@ -503,9 +503,9 @@ internal FileProperties os_properties_from_file_path(String8 path) { Temp scratch = scratch_begin(0, 0); - String8 path_copy = push_str8_copy(scratch.arena, path); + String8 path_copy = str8_copy(scratch.arena, path); struct stat f_stat = {0}; - int stat_result = stat(path_copy.cstr, &f_stat); + int stat_result = stat((char *)path_copy.str, &f_stat); FileProperties props = {0}; if(stat_result != -1) { @@ -564,7 +564,7 @@ os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags) OS_LNX_FileIter *iter = (OS_LNX_FileIter *)base_iter->memory; { String8 path_copy = push_str8_copy(arena, path); - iter->dir = opendir(path_copy.cstr); + iter->dir = opendir((char *)path_copy.str); iter->path = path_copy; } return base_iter; @@ -588,7 +588,7 @@ os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out) { Temp scratch = scratch_begin(&arena, 1); String8 full_path = push_str8f(scratch.arena, "%S/%s", lnx_iter->path, lnx_iter->dp->d_name); - stat_result = stat(full_path.cstr, &st); + stat_result = stat((char *)full_path.str, &st); scratch_end(scratch); } @@ -637,7 +637,7 @@ os_make_directory(String8 path) Temp scratch = scratch_begin(0, 0); B32 result = 0; String8 path_copy = push_str8_copy(scratch.arena, path); - if(mkdir(path_copy.cstr, 0755) != -1) + if(mkdir((char *)path_copy.str, 0755) != -1) { result = 1; } @@ -653,7 +653,7 @@ os_shared_memory_alloc(U64 size, String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); - int id = shm_open(name_copy.cstr, O_RDWR|O_CREAT, 0666); + int id = shm_open((char *)name_copy.str, O_RDWR|O_CREAT, 0666); ftruncate(id, size); OS_Handle result = {(U64)id}; scratch_end(scratch); @@ -665,7 +665,7 @@ os_shared_memory_open(String8 name) { Temp scratch = scratch_begin(0, 0); String8 name_copy = push_str8_copy(scratch.arena, name); - int id = shm_open(name_copy.cstr, O_RDWR, 0); + int id = shm_open((char *)name_copy.str, O_RDWR, 0); OS_Handle result = {(U64)id}; scratch_end(scratch); return result; @@ -802,9 +802,13 @@ os_process_launch(OS_ProcessLaunchParams *params) str8_list_push(scratch.arena, &l, params->cmd_line.first->string); String8 path_to_exe = str8_path_list_join_by_style(scratch.arena, &l, PathStyle_SystemAbsolute); - argv[0] = path_to_exe.cstr; + argv[0] = (char *)path_to_exe.str; U64 arg_idx = 1; - for EachNode(n, String8Node, params->cmd_line.first->next) { argv[arg_idx++] = n->string.cstr; } + for EachNode(n, String8Node, params->cmd_line.first->next) + { + argv[arg_idx] = (char *)n->string.str; + arg_idx += 1; + } } // package envp @@ -819,7 +823,8 @@ os_process_launch(OS_ProcessLaunchParams *params) U64 env_idx = 0; for EachNode(n, String8Node, params->cmd_line.first) { - envp[env_idx] = n->string.cstr; + envp[env_idx] = (char *)n->string.str; + env_idx += 1; } } @@ -1170,15 +1175,17 @@ os_cond_var_broadcast(CondVar cv) internal Semaphore os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) { + Temp scratch = scratch_begin(0, 0); Semaphore result = {0}; - if (name.size > 0) + if(name.size > 0) { for EachIndex(attempt_idx, 64) { - sem_t *s = sem_open(name.cstr, O_CREAT | O_EXCL, 0666, initial_count); + String8 name_copy = str8_copy(scratch.arena, name); + sem_t *s = sem_open((char *)name_copy.str, O_CREAT | O_EXCL, 0666, initial_count); if(s == SEM_FAILED) { - s = sem_open(name.cstr, 0); + s = sem_open((char *)name_copy.str, 0); } if(s != SEM_FAILED) { @@ -1197,6 +1204,7 @@ os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name) result.u64[0] = (U64)s; } } + scratch_end(scratch); return result; } @@ -1211,10 +1219,15 @@ internal Semaphore os_semaphore_open(String8 name) { Semaphore result = {0}; - sem_t *s = sem_open(name.cstr, 0); - if(s != SEM_FAILED) { - result.u64[0] = (U64)s; + Temp scratch = scratch_begin(0, 0); + String8 name_copy = str8_copy(scratch.arena, name); + sem_t *s = sem_open((char *)name_copy.str, 0); + if(s != SEM_FAILED) + { + result.u64[0] = (U64)s; + } + scratch_end(scratch); } return result; } @@ -1310,7 +1323,7 @@ internal OS_Handle os_library_open(String8 path) { Temp scratch = scratch_begin(0, 0); - char *path_cstr = push_str8_copy(scratch.arena, path).cstr; + char *path_cstr = (char *)str8_copy(scratch.arena, path).str; void *so = dlopen(path_cstr, RTLD_LAZY|RTLD_LOCAL); OS_Handle lib = { (U64)so }; scratch_end(scratch); @@ -1322,7 +1335,7 @@ os_library_load_proc(OS_Handle lib, String8 name) { Temp scratch = scratch_begin(0, 0); void *so = (void *)lib.u64; - char *name_cstr = push_str8_copy(scratch.arena, name).cstr; + char *name_cstr = (char *)str8_copy(scratch.arena, name).str; VoidProc *proc = (VoidProc *)dlsym(so, name_cstr); scratch_end(scratch); return proc; @@ -1485,15 +1498,15 @@ main(int argc, char **argv) os_lnx_state.arena = arena_alloc(); os_lnx_state.entity_arena = arena_alloc(); pthread_mutex_init(&os_lnx_state.entity_mutex, 0); - + // cache default environment { U64 env_count = 0; for(; __environ[env_count] != 0; env_count += 1) {} char **default_env = push_array(os_lnx_state.arena, char *, env_count+1); - for EachIndex(i, env_count) + for EachIndex(idx, env_count) { - default_env[i] = str8_copy(os_lnx_state.arena, str8_cstring(__environ[i])).cstr; + default_env[idx] = (char *)str8_copy(os_lnx_state.arena, str8_cstring(__environ[idx])).str; } default_env[env_count] = 0; os_lnx_state.default_env_count = env_count; diff --git a/src/radbin/radbin.c b/src/radbin/radbin.c index fd933399..3df719c1 100644 --- a/src/radbin/radbin.c +++ b/src/radbin/radbin.c @@ -341,7 +341,7 @@ rb_thread_entry_point(void *p) } scratch_end(scratch); } - + if(file_format == RB_FileFormat_COFF_OBJ || file_format == RB_FileFormat_COFF_BigOBJ) { Temp scratch = scratch_begin(&arena, 1); @@ -432,7 +432,7 @@ rb_thread_entry_point(void *p) {str8_lit_comp("rdi"), str8_lit_comp("RAD Debug Info (.rdi) Conversion")}, {str8_lit_comp("dump"), str8_lit_comp("Textual Dumping")}, {str8_lit_comp("breakpad"), str8_lit_comp("Breakpad Debug Info Conversion")}, - {str8_lit_comp("voff2line"), str8_lit_comp("Map virtual offset to a source line")}, + {str8_lit_comp("voff2line"), str8_lit_comp("Virtual Offset -> Line Mapping")}, }; OutputKind output_kind = OutputKind_Null; String8 output_path = cmd_line_string(cmdline, str8_lit("out")); @@ -535,8 +535,9 @@ rb_thread_entry_point(void *p) fprintf(stderr, "--breakpad Specifies that the utility should convert debug information\n"); fprintf(stderr, " data to the textual Breakpad format.\n\n"); - - fprintf(stderr, "--voff2line Specifies that the utility should map virtual offset to source line.\n\n"); + + fprintf(stderr, "--voff2line Specifies that the utility should map a virtual offset to a\n"); + fprintf(stderr, " line.\n\n"); fprintf(stderr, "--out: Specifies the path to which output data should be written. If\n"); fprintf(stderr, " not specified, the utility will choose a fallback. If dumping\n"); @@ -554,10 +555,11 @@ rb_thread_entry_point(void *p) }break; //////////////////////////// - //- rjf: RDI, Breakpad -> conversion based on inputs + //- rjf: RDI, Breakpad, Debug Info Operations -> conversion based on inputs // case OutputKind_RDI: case OutputKind_Breakpad: + case OutputKind_VOff2Line: { //- rjf: no inputs => help if(lane_idx() == 0 && cmdline->inputs.node_count == 0) switch(output_kind) @@ -592,6 +594,12 @@ rb_thread_entry_point(void *p) fprintf(stderr, "All input files specified on the command line will be dumped. The following\n"); fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n"); }break; + case OutputKind_VOff2Line: + { + fprintf(stderr, "ARGUMENTS\n\n"); + fprintf(stderr, "--voff: Specifies the virtual offset to map to a source line.\n"); + fprintf(stderr, "\n"); + }break; } //- rjf: unpack subset flags @@ -630,12 +638,24 @@ rb_thread_entry_point(void *p) { subset_flags = (RDIM_SubsetFlag_Units|RDIM_SubsetFlag_Procedures|RDIM_SubsetFlag_Scopes|RDIM_SubsetFlag_LineInfo|RDIM_SubsetFlag_InlineLineInfo); }break; + case OutputKind_VOff2Line: + { + subset_flags = (RDIM_SubsetFlag_Units|RDIM_SubsetFlag_LineInfo|RDIM_SubsetFlag_InlineLineInfo|RDIM_SubsetFlag_Procedures); + }break; } //- rjf: convert inputs to RDI info B32 convert_done = 0; RDIM_BakeParams pdb_bake_params = {0}; RDIM_BakeParams dwarf_bake_params = {0}; + typedef struct RDIM_BakeParamsNode RDIM_BakeParamsNode; + struct RDIM_BakeParamsNode + { + RDIM_BakeParamsNode *next; + RDIM_BakeParams v; + }; + RDIM_BakeParamsNode *first_rdi_bake_params = 0; + RDIM_BakeParamsNode *last_rdi_bake_params = 0; { //- rjf: PE inputs w/ DWARF, or ELF inputs => DWARF -> RDI conversion B32 pe_w_dwarf = (input_files_from_format_table[RB_FileFormat_PE].count != 0 && @@ -758,6 +778,43 @@ rb_thread_entry_point(void *p) } ProfScope("convert") pdb_bake_params = p2r_convert(arena, &convert_params); } + + //- rjf: RDI inputs => RDI joining + if(input_files_from_format_table[RB_FileFormat_RDI].count > 1) + { + convert_done = 1; + log_infof("RDIs specified; joining RDIs\n"); + + // rjf: produce bake params for each RDI + for EachNode(n, RB_FileNode, input_files_from_format_table[RB_FileFormat_RDI].first) + { + RB_File *f = n->v; + + // rjf: decompress RDI + RDI_Parsed *rdi = 0; + if(lane_idx() == 0) + { + rdi = push_array(arena, RDI_Parsed, 1); + RDI_ParseStatus rdi_status = rdi_parse(f->data.str, f->data.size, rdi); + U64 decompressed_size = rdi_decompressed_size_from_parsed(rdi); + if(decompressed_size > rdi->raw_data_size) + { + U8 *decompressed_data = push_array_no_zero(arena, U8, decompressed_size); + rdi_decompress_parsed(decompressed_data, decompressed_size, rdi); + rdi_status = rdi_parse(decompressed_data, decompressed_size, rdi); + } + } + lane_sync_u64(&rdi, 0); + + // rjf: RDI -> loose + RDIM_BakeParams rdi_loose = rdim_loose_from_rdi(arena, subset_flags, rdi); + + // rjf: add + RDIM_BakeParamsNode *n = push_array(arena, RDIM_BakeParamsNode, 1); + n->v = rdi_loose; + SLLQueuePush(first_rdi_bake_params, last_rdi_bake_params, n); + } + } } lane_sync(); @@ -768,6 +825,10 @@ rb_thread_entry_point(void *p) bake_params = push_array(arena, RDIM_BakeParams, 1); rdim_bake_params_concat_in_place(bake_params, &pdb_bake_params); rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params); + for EachNode(n, RDIM_BakeParamsNode, first_rdi_bake_params) + { + rdim_bake_params_concat_in_place(bake_params, &n->v); + } } lane_sync_u64(&bake_params, 0); @@ -779,24 +840,35 @@ rb_thread_entry_point(void *p) if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PE])->path); } if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_ELF64])->path); } if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_ELF32])->path); } + if(output_path__noext.size == 0) { output_path__noext = str8_chop_last_dot(rb_file_list_first(&input_files_from_format_table[RB_FileFormat_RDI])->path); } switch(output_kind) { default:{}break; case OutputKind_RDI: { - output_path = push_str8f(arena, "%S.rdi", output_path__noext); + output_path = str8f(arena, "%S.rdi", output_path__noext); }break; case OutputKind_Breakpad: { - output_path = push_str8f(arena, "%S.psym", output_path__noext); + output_path = str8f(arena, "%S.psym", output_path__noext); }break; } } + //- rjf: special case: only a single RDI file passed? all conversion is trivially done, just + // package up RDI data as serialized section bundle, and let the rest of the paths use it. + B32 noop_conversion = 0; + if(input_files.count == 1 && rb_file_list_first(&input_files)->format == RB_FileFormat_RDI) + { + noop_conversion = 1; + convert_done = 1; + log_infof("Single RDI specified; passing through (skipping conversion)"); + } + //- rjf: no viable input paths if(!convert_done && cmdline->inputs.node_count != 0) { - log_user_errorf("Could not load debug info from the specified inputs. You must provide either a valid PDB file or an executable image (PE, ELF) file with DWARF debug info."); + log_user_errorf("Could not load debug info from the specified inputs. You must provide a valid PDB file, an executable image (PE, ELF) file with DWARF debug info, or RDI file(s)."); } //- rjf: bake @@ -806,6 +878,41 @@ rb_thread_entry_point(void *p) bake_results = rdim_bake(arena, bake_params); } + //- rjf: serialize + RDIM_SerializedSectionBundle *serialized_section_bundle = 0; + ProfScope("serialize") if(lane_idx() == 0) + { + serialized_section_bundle = push_array(arena, RDIM_SerializedSectionBundle, 1); + serialized_section_bundle[0] = rdim_serialized_section_bundle_from_bake_results(&bake_results); + } + lane_sync_u64(&serialized_section_bundle, 0); + + //- rjf: special case: no-op conversion (single RDI file) + if(lane_idx() == 0 && noop_conversion) + { + RB_File *f = rb_file_list_first(&input_files); + RDI_Parsed rdi = {0}; + RDI_ParseStatus rdi_status = rdi_parse(f->data.str, f->data.size, &rdi); + U64 decompressed_size = rdi_decompressed_size_from_parsed(&rdi); + if(decompressed_size > rdi.raw_data_size) + { + U8 *decompressed_data = push_array_no_zero(arena, U8, decompressed_size); + rdi_decompress_parsed(decompressed_data, decompressed_size, &rdi); + rdi_status = rdi_parse(decompressed_data, decompressed_size, &rdi); + } + for EachIndex(idx, rdi.sections_count) + { + if(idx < RDI_SectionKind_COUNT) + { + serialized_section_bundle->sections[idx].data = rdi.raw_data + rdi.sections[idx].off; + serialized_section_bundle->sections[idx].encoded_size = rdi.sections[idx].encoded_size; + serialized_section_bundle->sections[idx].unpacked_size = rdi.sections[idx].unpacked_size; + serialized_section_bundle->sections[idx].encoding = rdi.sections[idx].encoding; + } + } + } + lane_sync(); + //- rjf: convert done => generate output if(convert_done) switch(output_kind) { @@ -814,15 +921,6 @@ rb_thread_entry_point(void *p) //- rjf: generate RDI blobs case OutputKind_RDI: { - // rjf: serialize - RDIM_SerializedSectionBundle *serialized_section_bundle = 0; - ProfScope("serialize") if(lane_idx() == 0) - { - serialized_section_bundle = push_array(arena, RDIM_SerializedSectionBundle, 1); - serialized_section_bundle[0] = rdim_serialized_section_bundle_from_bake_results(&bake_results); - } - lane_sync_u64(&serialized_section_bundle, 0); - // rjf: compress RDIM_SerializedSectionBundle serialized_section_bundle__compressed = serialized_section_bundle[0]; if(cmd_line_has_flag(cmdline, str8_lit("compress"))) ProfScope("compress") @@ -838,28 +936,36 @@ rb_thread_entry_point(void *p) //- rjf: generate breakpad text case OutputKind_Breakpad: { + //- rjf: flatten to RDI data + String8List rdi_blobs = rdim_file_blobs_from_section_bundle(arena, serialized_section_bundle); + String8 rdi_data = str8_list_join(arena, &rdi_blobs, 0); + RDI_Parsed rdi_ = {0}; + RDI_Parsed *rdi = &rdi_; + RDI_ParseStatus rdi_status = rdi_parse(rdi_data.str, rdi_data.size, rdi); + //- rjf: set up shared state typedef struct P2B_Shared P2B_Shared; struct P2B_Shared { String8List dump; - String8List *lane_chunk_file_dumps; - String8List *lane_chunk_func_dumps; + String8List *lane_file_dumps; + String8List *lane_func_dumps; }; - local_persist P2B_Shared *p2b_shared = 0; + P2B_Shared *p2b_shared = 0; if(lane_idx() == 0) { p2b_shared = push_array(arena, P2B_Shared, 1); - p2b_shared->lane_chunk_file_dumps = push_array(arena, String8List, lane_count()*bake_params->src_files.chunk_count); - p2b_shared->lane_chunk_func_dumps = push_array(arena, String8List, lane_count()*bake_params->procedures.chunk_count); + p2b_shared->lane_file_dumps = push_array(arena, String8List, lane_count()); + p2b_shared->lane_func_dumps = push_array(arena, String8List, lane_count()); } - lane_sync(); + lane_sync_u64(&p2b_shared, 0); //- rjf: dump MODULE record if(lane_idx() == 0) { // rjf: pick name to identify module - String8 module_name_string = bake_params->top_level_info.exe_name; + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + String8 module_name_string = str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx); if(module_name_string.size == 0 && input_files.first != 0) { module_name_string = input_files.first->v->path; @@ -867,9 +973,9 @@ rb_thread_entry_point(void *p) // rjf: pick string for unique code String8 unique_identifier_string = {0}; - if(unique_identifier_string.size == 0 && bake_params->top_level_info.exe_hash != 0) + if(unique_identifier_string.size == 0 && tli->exe_hash != 0) { - unique_identifier_string = str8f(arena, "%I64x", bake_params->top_level_info.exe_hash); + unique_identifier_string = str8f(arena, "%I64x", tli->exe_hash); } if(unique_identifier_string.size == 0) { @@ -906,86 +1012,74 @@ rb_thread_entry_point(void *p) //- rjf: dump FILE records ProfScope("dump FILE records") { - U64 chunk_idx = 0; - for EachNode(n, RDIM_SrcFileChunkNode, bake_params->src_files.first) + U64 count = 0; + RDI_SourceFile *v = rdi_table_from_name(rdi, SourceFiles, &count); + Rng1U64 range = lane_range(count); + for EachInRange(idx, range) { - Rng1U64 range = lane_range(n->count); - for EachInRange(idx, range) - { - U64 file_idx = rdim_idx_from_src_file(&n->v[idx]); - String8 src_path = n->v[idx].path; - str8_list_pushf(arena, &p2b_shared->lane_chunk_file_dumps[lane_idx()*bake_params->src_files.chunk_count + chunk_idx], "FILE %I64u %S\n", file_idx, src_path); - } - chunk_idx += 1; + String8List *out = &p2b_shared->lane_file_dumps[lane_idx()]; + Temp scratch = scratch_begin(&arena, 1); + String8 src_path = str8_from_rdi_path_node_idx(scratch.arena, rdi, PathStyle_Relative, v[idx].file_path_node_idx); + str8_list_pushf(arena, out, "FILE %I64u %S\n", idx, src_path); + scratch_end(scratch); } } //- rjf: dump FUNC records ProfScope("dump FUNC records") { - U64 chunk_idx = 0; - for EachNode(n, RDIM_SymbolChunkNode, bake_params->procedures.first) + U64 count = 0; + RDI_Procedure *v = rdi_table_from_name(rdi, Procedures, &count); + Rng1U64 range = lane_range(count); + for EachInRange(idx, range) { - String8List *out = &p2b_shared->lane_chunk_func_dumps[lane_idx()*bake_params->procedures.chunk_count + chunk_idx]; - Rng1U64 range = lane_range(n->count); - for EachInRange(idx, range) + // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. + String8List *out = &p2b_shared->lane_func_dumps[lane_idx()]; + RDI_Procedure *proc = &v[idx]; + RDI_Scope *root_scope = rdi_element_from_name_idx(rdi, Scopes, proc->root_scope_idx); + if(root_scope->voff_range_opl > root_scope->voff_range_first) { - // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. - RDIM_Symbol *proc = &n->v[idx]; - RDIM_Scope *root_scope = proc->root_scope; - if(root_scope != 0 && root_scope->voff_ranges.first != 0) + // rjf: dump function record + RDIM_Rng1U64 voff_range = { - // rjf: dump function record - RDIM_Rng1U64 voff_range = root_scope->voff_ranges.first->v; - str8_list_pushf(arena, out, "FUNC %I64x %I64x %I64x %S\n", voff_range.min, voff_range.max-voff_range.min, 0ull, proc->name); - - // rjf: dump function lines - U64 unit_idx = rdi_vmap_idx_from_voff(bake_results.unit_vmap.vmap.vmap, bake_results.unit_vmap.vmap.count, voff_range.min); - if(0 < unit_idx && unit_idx <= bake_results.units.units_count) + *rdi_element_from_name_idx(rdi, ScopeVOffData, root_scope->voff_range_first), + *rdi_element_from_name_idx(rdi, ScopeVOffData, root_scope->voff_range_opl - 1), + }; + str8_list_pushf(arena, out, "FUNC %I64x %I64x %I64x %S\n", voff_range.min, voff_range.max-voff_range.min, 0ull, str8_from_rdi_string_idx(rdi, proc->name_string_idx)); + + // rjf: dump function lines + U64 unit_vmap_count = 0; + RDI_VMapEntry *unit_vmap = rdi_table_from_name(rdi, UnitVMap, &unit_vmap_count); + RDI_Unit *unit = rdi_unit_from_voff(rdi, voff_range.min); + RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); + RDI_ParsedLineTable line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &line_info); + for(U64 voff = voff_range.min, last_voff = 0; + voff < voff_range.max && voff > last_voff;) + { + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); + if(line_info_idx < line_info.count) { - U32 line_table_idx = bake_results.units.units[unit_idx].line_table_idx; - if(0 < line_table_idx && line_table_idx <= bake_results.line_tables.line_tables_count) + RDI_Line *line = &line_info.lines[line_info_idx]; + U64 line_voff_min = line_info.voffs[line_info_idx]; + U64 line_voff_opl = line_info.voffs[line_info_idx+1]; + if(line->file_idx != 0) { - // rjf: unpack unit line info - RDI_LineTable *line_table = &bake_results.line_tables.line_tables[line_table_idx]; - RDI_ParsedLineTable line_info = - { - bake_results.line_tables.line_table_voffs + line_table->voffs_base_idx, - bake_results.line_tables.line_table_lines + line_table->lines_base_idx, - 0, - line_table->lines_count, - 0 - }; - for(U64 voff = voff_range.min, last_voff = 0; - voff < voff_range.max && voff > last_voff;) - { - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); - if(line_info_idx < line_info.count) - { - RDI_Line *line = &line_info.lines[line_info_idx]; - U64 line_voff_min = line_info.voffs[line_info_idx]; - U64 line_voff_opl = line_info.voffs[line_info_idx+1]; - if(line->file_idx != 0) - { - str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", - line_voff_min, - line_voff_opl-line_voff_min, - (U64)line->line_num, - (U64)line->file_idx); - } - last_voff = voff; - voff = line_voff_opl; - } - else - { - break; - } - } + str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", + line_voff_min, + line_voff_opl-line_voff_min, + (U64)line->line_num, + (U64)line->file_idx); } + last_voff = voff; + voff = line_voff_opl; + } + else + { + break; } } } - chunk_idx += 1; } } @@ -993,24 +1087,74 @@ rb_thread_entry_point(void *p) lane_sync(); if(lane_idx() == 0) { - for EachIndex(chunk_idx, bake_params->src_files.chunk_count) + for EachIndex(ln_idx, lane_count()) { - for EachIndex(ln_idx, lane_count()) - { - str8_list_concat_in_place(&p2b_shared->dump, &p2b_shared->lane_chunk_file_dumps[ln_idx*bake_params->src_files.chunk_count + chunk_idx]); - } + str8_list_concat_in_place(&p2b_shared->dump, &p2b_shared->lane_file_dumps[ln_idx]); } - for EachIndex(chunk_idx, bake_params->procedures.chunk_count) + for EachIndex(ln_idx, lane_count()) { - for EachIndex(ln_idx, lane_count()) - { - str8_list_concat_in_place(&p2b_shared->dump, &p2b_shared->lane_chunk_func_dumps[ln_idx*bake_params->procedures.chunk_count + chunk_idx]); - } + str8_list_concat_in_place(&p2b_shared->dump, &p2b_shared->lane_func_dumps[ln_idx]); } } lane_sync(); output_blobs = p2b_shared->dump; }break; + + //- rjf: generate voff -> line results + case OutputKind_VOff2Line: + { + //- rjf: unpack voff arg + U64 voff = 0; + { + String8 voff_str = cmd_line_string(cmdline, str8_lit("voff")); + try_u64_from_str8_c_rules(voff_str, &voff); + log_infof("User specified \"%S\" as virtual offset; parsed as 0x%I64x", voff_str, voff); + } + + //- rjf: flatten to RDI data + String8List rdi_blobs = rdim_file_blobs_from_section_bundle(arena, serialized_section_bundle); + String8 rdi_data = str8_list_join(arena, &rdi_blobs, 0); + RDI_Parsed rdi_ = {0}; + RDI_Parsed *rdi = &rdi_; + RDI_ParseStatus rdi_status = rdi_parse(rdi_data.str, rdi_data.size, rdi); + + //- rjf: voff -> line + RDI_Line line = rdi_line_from_voff(rdi, voff); + RDI_SourceFile *src_file = rdi_element_from_name_idx(rdi, SourceFiles, line.file_idx); + + //- rjf: dump line info + { + Temp scratch = scratch_begin(0, 0); + RDI_Scope *voff_scope = rdi_scope_from_voff(rdi, voff); + for(RDI_Scope *scope = voff_scope, *null_scope = rdi_element_from_name_idx(rdi, Scopes, 0); + scope != 0 && scope != null_scope; + scope = rdi_parent_from_scope(rdi, scope)) + { + RDI_InlineSite *inline_site = rdi_inline_site_from_scope(rdi, scope); + RDI_InlineSite *null_inline_site = rdi_element_from_name_idx(rdi, InlineSites, 0); + if(inline_site && inline_site != null_inline_site) + { + RDI_LineTable *inline_line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); + RDI_LineTable *null_inline_line_table = rdi_element_from_name_idx(rdi, LineTables, 0); + if(inline_line_table && inline_line_table != null_inline_line_table) + { + String8 inline_name = str8_from_rdi_string_idx(rdi, inline_site->name_string_idx); + RDI_Line inline_line = rdi_line_from_line_table_voff(rdi, inline_line_table, voff); + RDI_SourceFile *inline_src_file = rdi_element_from_name_idx(rdi, SourceFiles, inline_line.file_idx); + RDI_SourceFile *null_inline_src_file = rdi_element_from_name_idx(rdi, SourceFiles, 0); + if(inline_src_file && inline_src_file != null_inline_src_file) + { + String8 path = str8_from_rdi_path_node_idx(scratch.arena, rdi, PathStyle_SystemAbsolute, src_file->file_path_node_idx); + str8_list_pushf(arena, &output_blobs, "[inlined] %S %S:%u\n", inline_name, path, inline_line.line_num); + } + } + } + } + String8 path = str8_from_rdi_path_node_idx(scratch.arena, rdi, PathStyle_SystemAbsolute, src_file->file_path_node_idx); + str8_list_pushf(arena, &output_blobs, "%S:%u\n", path, line.line_num); + scratch_end(scratch); + } + }break; } }break; @@ -1058,7 +1202,7 @@ rb_thread_entry_point(void *p) #undef X fprintf(stderr, "\n"); } - + B32 verbose = cmd_line_has_flag(cmdline, str8_lit("verbose")); //- rjf: unpack dump subset flags @@ -1147,7 +1291,7 @@ rb_thread_entry_point(void *p) { elf = elf_bin_from_data(arena, f->data); arch = arch_from_elf_machine(elf.hdr.e_machine); - + for EachIndex(sect_idx, elf.hdr.e_shnum) { ELF_Shdr64 *shdr = &elf.shdrs.v[sect_idx]; @@ -1156,7 +1300,7 @@ rb_thread_entry_point(void *p) { eh_frame_hdr = str8_substr(f->data, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size)); eh_frame_hdr_vaddr = shdr->sh_addr; - + } else if(str8_match(name, str8_lit(".eh_frame"), 0)) { @@ -1268,7 +1412,7 @@ rb_thread_entry_point(void *p) } lane_sync(); } - + if(eh_dump_subset_flags) { if(lane_idx() == 0) @@ -1280,106 +1424,6 @@ rb_thread_entry_point(void *p) } } }break; - - case OutputKind_VOff2Line: - { - if(lane_idx() != 0) { break; } - - if(cmdline->inputs.node_count == 0) - { - fprintf(stderr, "ARGUMENTS\n\n"); - fprintf(stderr, "--voff:OFFSET Map specified virtual offset to a source line.\n"); - break; - } - - if(cmdline->inputs.node_count > 1) - { - fprintf(stderr, "ERROR: too many input files!\n"); - break; - } - - if(!cmd_line_has_argument(cmdline, str8_lit("voff"))) { - fprintf(stderr, "ERROR: missing -voff\n"); - break; - } - - String8 voff_str = cmd_line_string(cmdline, str8_lit("voff")); - if(voff_str.size == 0) - { - fprintf(stderr, "ERROR: missing argument for -voff\n"); - break; - } - - U64 voff = 0; - if(!try_u64_from_str8_c_rules(voff_str, &voff)) - { - fprintf(stderr, "ERROR: invalid argument for -voff\n"); - break; - } - - RB_File *f = input_files.first->v; - if(f->format != RB_FileFormat_RDI) - { - fprintf(stderr, "ERROR: input file must be RDI.\n"); - break; - } - - RDI_Parsed rdi = {0}; - RDI_ParseStatus rdi_parse_status = rdi_parse(f->data.str, f->data.size, &rdi); - if(rdi_parse_status != RDI_ParseStatus_Good) - { - fprintf(stderr, "ERROR: failed to parse RDI with code %d\n", rdi_parse_status); - break; - } - - RDI_Line line = rdi_line_from_voff(&rdi, voff); - if(line.file_idx == 0 || line.line_num == 0) - { - fprintf(stderr, "ERROR: failed to find mapping for virtual offset 0x%llx.\n", voff); - break; - } - - RDI_SourceFile *src_file = rdi_element_from_name_idx(&rdi, SourceFiles, line.file_idx); - if(src_file == 0) - { - fprintf(stderr, "ERROR: failed to find source file with index %u.\n", line.file_idx); - break; - } - - Temp scratch = scratch_begin(0, 0); - - // format inline site stack - { - RDI_Scope *voff_scope = rdi_scope_from_voff(&rdi, voff); - for(RDI_Scope *scope = voff_scope, *null_scope = rdi_element_from_name_idx(&rdi, Scopes, 0); scope != 0 && scope != null_scope; scope = rdi_parent_from_scope(&rdi, scope)) - { - RDI_InlineSite *inline_site = rdi_inline_site_from_scope(&rdi, scope); - RDI_InlineSite *null_inline_site = rdi_element_from_name_idx(&rdi, InlineSites, 0); - if(inline_site && inline_site != null_inline_site) - { - RDI_LineTable *inline_line_table = rdi_element_from_name_idx(&rdi, LineTables, inline_site->line_table_idx); - RDI_LineTable *null_inline_line_table = rdi_element_from_name_idx(&rdi, LineTables, 0); - if(inline_line_table && inline_line_table != null_inline_line_table) - { - String8 inline_name = str8_from_rdi_string_idx(&rdi, inline_site->name_string_idx); - RDI_Line inline_line = rdi_line_from_line_table_voff(&rdi, inline_line_table, voff); - RDI_SourceFile *inline_src_file = rdi_element_from_name_idx(&rdi, SourceFiles, inline_line.file_idx); - RDI_SourceFile *null_inline_src_file = rdi_element_from_name_idx(&rdi, SourceFiles, 0); - if(inline_src_file && inline_src_file != null_inline_src_file) - { - String8 path = str8_from_rdi_path_node_idx(scratch.arena, &rdi, PathStyle_SystemAbsolute, src_file->file_path_node_idx); - fprintf(stdout, "[inlined] %.*s %.*s:%u\n", str8_varg(inline_name), str8_varg(path), inline_line.line_num); - } - } - } - } - } - - String8 path = str8_from_rdi_path_node_idx(scratch.arena, &rdi, PathStyle_SystemAbsolute, src_file->file_path_node_idx); - fprintf(stdout, "%.*s:%u\n", str8_varg(path), line.line_num); - - scratch_end(scratch); - }break; } ////////////////////////////// diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 20504b8a..549a8fe4 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -1208,7 +1208,6 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params) lane_sync_u64(&units_first_inline_site_line_tables, 0); RDIM_Unit *units = all_units_ptr->first ? all_units_ptr->first->v : 0; U64 units_count = all_units_ptr->first ? all_units_ptr->first->count : 0; - Assert(units_count == comp_units->count); //- rjf: do per-lane work if(params->subset_flags & (RDIM_SubsetFlag_Units| diff --git a/src/rdi_make/rdi_make_local.c b/src/rdi_make/rdi_make_local.c index 9bf5e6e9..d4790190 100644 --- a/src/rdi_make/rdi_make_local.c +++ b/src/rdi_make/rdi_make_local.c @@ -46,6 +46,236 @@ rdim_make_top_level_info(String8 image_name, Arch arch, U64 exe_hash, RDIM_Binar return top_level_info; } +internal RDIM_BakeParams +rdim_loose_from_rdi(Arena *arena, RDIM_SubsetFlags subset_flags, RDI_Parsed *rdi) +{ + //- rjf: setup bake params + RDIM_BakeParams *bp = 0; + if(lane_idx() == 0) + { + bp = push_array(arena, RDIM_BakeParams, 1); + bp->subset_flags = subset_flags; + } + lane_sync_u64(&bp, 0); + + //- rjf: convert top level info + if(lane_idx() == 0) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + bp->top_level_info.arch = tli->arch; + bp->top_level_info.exe_name.str = rdi_string_from_idx(rdi, tli->exe_name_string_idx, &bp->top_level_info.exe_name.size); + bp->top_level_info.exe_hash = tli->exe_hash; + bp->top_level_info.voff_max = tli->voff_max; + bp->top_level_info.guid = tli->guid; + bp->top_level_info.producer_name.str = rdi_string_from_idx(rdi, tli->producer_name_string_idx, &bp->top_level_info.producer_name.size); + } + lane_sync(); + + //- rjf: convert binary sections + if(lane_idx() == 0) + { + U64 count = 0; + RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); + for EachIndex(idx, count) + { + RDIM_BinarySection *bsec = rdim_binary_section_list_push(arena, &bp->binary_sections); + bsec->name.str = rdi_string_from_idx(rdi, v[idx].name_string_idx, &bsec->name.size); + bsec->flags = v[idx].flags; + bsec->voff_first = v[idx].voff_first; + bsec->voff_opl = v[idx].voff_opl; + bsec->foff_first = v[idx].foff_first; + bsec->foff_opl = v[idx].foff_opl; + } + } + lane_sync(); + + //- rjf: bucket voff ranges by unit idx + RDIM_Rng1U64ChunkList *unit_ranges = 0; + if(lane_idx() == 0) + { + U64 units_count = 0; + rdi_table_from_name(rdi, Units, &units_count); + U64 unit_vmap_count = 0; + RDI_VMapEntry *unit_vmap = rdi_table_from_name(rdi, UnitVMap, &unit_vmap_count); + unit_ranges = push_array(arena, RDIM_Rng1U64ChunkList, units_count); + if(unit_vmap_count > 0) + { + for EachIndex(idx, unit_vmap_count-1) + { + RDIM_Rng1U64 rng = {unit_vmap[idx].voff, unit_vmap[idx+1].voff}; + rdim_rng1u64_chunk_list_push(arena, &unit_ranges[unit_vmap[idx].idx], 256, rng); + } + } + } + lane_sync_u64(&unit_ranges, 0); + + //- rjf: convert src files + RDIM_SrcFileChunkList *src_files = 0; + RDIM_SrcFile **src_file_from_idx_table = 0; + { + U64 src_file_count = 0; + RDI_SourceFile *src_file_v = rdi_table_from_name(rdi, SourceFiles, &src_file_count); + RDIM_SrcFileChunkList *lane_srcfiles = 0; + if(lane_idx() == 0) + { + src_files = push_array(arena, RDIM_SrcFileChunkList, 1); + src_file_from_idx_table = push_array(arena, RDIM_SrcFile *, src_file_count); + lane_srcfiles = push_array(arena, RDIM_SrcFileChunkList, lane_count()); + } + lane_sync_u64(&lane_srcfiles, 0); + { + Rng1U64 range = lane_range(src_file_count); + for EachInRange(idx, range) + { + RDI_SourceFile *src = &src_file_v[idx]; + RDIM_SrcFile *dst = rdim_src_file_chunk_list_push(arena, &lane_srcfiles[lane_idx()], dim_1u64(range)); + + // rjf: get checksum + String8 checksum = {0}; + switch(src->checksum_kind) + { + default:{}break; + case RDI_ChecksumKind_MD5: {checksum = str8(rdi_element_from_name_idx(rdi, MD5Checksums, src->checksum_idx)->u8, sizeof(RDI_MD5));}break; + case RDI_ChecksumKind_SHA1: {checksum = str8(rdi_element_from_name_idx(rdi, SHA1Checksums, src->checksum_idx)->u8, sizeof(RDI_SHA1));}break; + case RDI_ChecksumKind_SHA256: {checksum = str8(rdi_element_from_name_idx(rdi, SHA256Checksums, src->checksum_idx)->u8, sizeof(RDI_SHA256));}break; + case RDI_ChecksumKind_Timestamp:{checksum = str8((U8 *)rdi_element_from_name_idx(rdi, Timestamps, src->checksum_idx), sizeof(RDI_U64));}break; + } + + // rjf: fill basics + dst->path = str8_from_rdi_path_node_idx(arena, rdi, PathStyle_Relative, src->file_path_node_idx); + dst->checksum_kind = src->checksum_kind; + dst->checksum = checksum; + src_file_from_idx_table[idx] = dst; + } + } + lane_sync(); + if(lane_idx() == 0) + { + for EachIndex(lidx, lane_count()) + { + rdim_src_file_chunk_list_concat_in_place(src_files, &lane_srcfiles[lidx]); + } + } + } + lane_sync(); + + //- rjf: convert units + RDIM_UnitChunkList *units = 0; + RDIM_LineTableChunkList *line_tables = 0; + { + RDIM_UnitChunkList *lane_units = 0; + RDIM_LineTableChunkList *lane_linetables = 0; + if(lane_idx() == 0) + { + lane_units = push_array(arena, RDIM_UnitChunkList, lane_count()); + lane_linetables = push_array(arena, RDIM_LineTableChunkList, lane_count()); + units = push_array(arena, RDIM_UnitChunkList, 1); + line_tables = push_array(arena, RDIM_LineTableChunkList, 1); + } + lane_sync_u64(&lane_units, 0); + lane_sync_u64(&lane_linetables, 0); + lane_sync_u64(&units, 0); + lane_sync_u64(&line_tables, 0); + U64 count = 0; + RDI_Unit *v = rdi_table_from_name(rdi, Units, &count); + U64 unit_take_idx_ = 0; + U64 *unit_take_idx_ptr = &unit_take_idx_; + lane_sync_u64(&unit_take_idx_ptr, 0); + for(;;) + { + U64 unit_idx = ins_atomic_u64_inc_eval(unit_take_idx_ptr)-1; + if(unit_idx >= count) + { + break; + } + RDI_Unit *src = &v[unit_idx]; + + // rjf: convert flat top parts + RDIM_Unit *dst = rdim_unit_chunk_list_push(arena, &lane_units[lane_idx()], 64); + dst->unit_name = str8_from_rdi_string_idx(rdi, src->unit_name_string_idx); + dst->compiler_name = str8_from_rdi_string_idx(rdi, src->compiler_name_string_idx); + dst->source_file = str8_from_rdi_path_node_idx(arena, rdi, PathStyle_Relative, src->source_file_path_node); + dst->object_file = str8_from_rdi_path_node_idx(arena, rdi, PathStyle_Relative, src->object_file_path_node); + dst->archive_file = str8_from_rdi_path_node_idx(arena, rdi, PathStyle_Relative, src->archive_file_path_node); + dst->build_path = str8_from_rdi_path_node_idx(arena, rdi, PathStyle_Relative, src->build_path_node); + dst->language = src->language; + dst->voff_ranges = unit_ranges[unit_idx]; + + // rjf: convert line table + dst->line_table = rdim_line_table_chunk_list_push(arena, &lane_linetables[lane_idx()], 64); + { + RDI_LineTable *src_lt_unparsed = rdi_element_from_name_idx(rdi, LineTables, src->line_table_idx); + RDI_ParsedLineTable src_lt = {0}; + rdi_parsed_from_line_table(rdi, src_lt_unparsed, &src_lt); + RDIM_LineTable *dst_lt = dst->line_table; + { + RDIM_SrcFile *seq_src_file = 0; + U64 seq_start_idx = 0; + for(U64 line_idx = 0; line_idx <= src_lt.count; line_idx += 1) + { + // rjf: get next src file + RDIM_SrcFile *next_src_file = 0; + if(line_idx < src_lt.count) + { + next_src_file = src_file_from_idx_table[src_lt.lines[line_idx].file_idx]; + } + + // rjf: next file doesn't match current sequence? -> complete sequence + if(next_src_file != seq_src_file && seq_src_file != 0) + { + U64 seq_line_count = (line_idx - seq_start_idx); + U32 *seq_line_nums = push_array(arena, U32, seq_line_count); + for(U64 line_idx_2 = seq_start_idx; line_idx_2 < line_idx; line_idx_2 += 1) + { + seq_line_nums[line_idx_2] = src_lt.lines[line_idx_2].line_num; + } + rdim_line_table_push_sequence(arena, &lane_linetables[lane_idx()], dst_lt, seq_src_file, + src_lt.voffs + seq_start_idx, + seq_line_nums, + 0, // TODO(rjf): column support + seq_line_count); + } + + // rjf: start next sequence + if(next_src_file != seq_src_file) + { + seq_src_file = next_src_file; + seq_start_idx = line_idx; + } + } + } + } + } + lane_sync(); + if(lane_idx() == 0) + { + for EachIndex(l_idx, lane_count()) + { + rdim_unit_chunk_list_concat_in_place(units, &lane_units[l_idx]); + } + for EachIndex(l_idx, lane_count()) + { + rdim_line_table_chunk_list_concat_in_place(line_tables, &lane_linetables[l_idx]); + } + } + } + lane_sync(); + + // TODO(rjf): convert types + // TODO(rjf): convert udts + // TODO(rjf): convert locations + // TODO(rjf): convert global variables + // TODO(rjf): convert thread variables + // TODO(rjf): convert constants + // TODO(rjf): convert procedures + // TODO(rjf): convert scopes + // TODO(rjf): convert inline sites + // TODO(rjf): package & return + + RDIM_BakeParams result = bp[0]; + return result; +} + internal RDIM_BakeResults rdim_bake(Arena *arena, RDIM_BakeParams *params) { diff --git a/src/rdi_make/rdi_make_local.h b/src/rdi_make/rdi_make_local.h index b7ed9ed9..3e5d6f95 100644 --- a/src/rdi_make/rdi_make_local.h +++ b/src/rdi_make/rdi_make_local.h @@ -162,6 +162,7 @@ global RDIM_Shared *rdim_shared = 0; internal RDIM_DataModel rdim_data_model_from_os_arch(OperatingSystem os, RDI_Arch arch); internal RDIM_TopLevelInfo rdim_make_top_level_info(String8 image_name, Arch arch, U64 exe_hash, RDIM_BinarySectionList sections); +internal RDIM_BakeParams rdim_loose_from_rdi(Arena *arena, RDIM_SubsetFlags subset_flags, RDI_Parsed *rdi); internal RDIM_BakeResults rdim_bake(Arena *arena, RDIM_BakeParams *params); internal RDIM_SerializedSectionBundle rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in); diff --git a/src/third_party/radsort/radsort.h b/src/third_party/radsort/radsort.h index 90a971ba..752193e8 100644 --- a/src/third_party/radsort/radsort.h +++ b/src/third_party/radsort/radsort.h @@ -115,7 +115,7 @@ typedef struct RS_MAX_BUBBLE_BUF { char b[RS_SMALL_FLIP_TO_INSERTION_GT_SIZE]; } #if _MSC_VER # define radsort_break_ __debugbreak() #else -# define radsort_break_ ___builtin_trap() +# define radsort_break_ __builtin_trap() #endif #define radsort( start, len, is_before_func ) \ diff --git a/src/third_party/stb/stb_sprintf.h b/src/third_party/stb/stb_sprintf.h index 7614dfbf..9a5fe40d 100644 --- a/src/third_party/stb/stb_sprintf.h +++ b/src/third_party/stb/stb_sprintf.h @@ -631,17 +631,17 @@ cl = lg; \ dp = 0; cs = 0; }goto scopy; - + case 'm': case 'M': { stbsp__flush_cb(); - + static const U64 one_kib = 1ull * 1024; static const U64 one_mib = 1ull * 1024 * 1024; static const U64 one_gib = 1ull * 1024 * 1024 * 1024; static const U64 one_tib = 1ull * 1024 * 1024 * 1024 * 1024; - + U64 size; if(f[0] == 'M') { @@ -651,11 +651,11 @@ cl = lg; \ { size = va_arg(va, U32); } - + U64 lo = 0; U64 hi = 0; char *units = ""; - + if(size < one_kib) { hi = size; @@ -686,7 +686,7 @@ cl = lg; \ lo = ((size * 100) / one_tib) % 100; units = "TiB"; } - + // format high part if(hi > 0) { @@ -707,37 +707,37 @@ cl = lg; \ *bf = '0'; ++bf; } - + // format low part if(lo > 0) { *bf = '.'; ++bf; - + s = num; for(U64 n = lo; n > 0; n /= 10ull) { *s = (char)(n % 10ull) + '0'; ++s; } - + U64 lead_zero_count = 3 - (U64)(s-num); for(U64 i = 1; i < lead_zero_count; ++i) { *bf = '0'; ++bf; } - + for(S64 i = (S64)(s-num)-1; i >= 0; --i) { *bf = num[i]; ++bf; } } - + *bf = ' '; ++bf; - + // copy units for(U64 i = 0; units[i] != 0; ++i) { @@ -745,14 +745,14 @@ cl = lg; \ ++bf; } }break; - + case 'r': { stbsp__flush_cb(); Rng1U64 range = va_arg(va, Rng1U64); - bf += STB_SPRINTF_DECORATE(sprintf)(bf, "[0x%llx, 0x%llx)", range.min, range.max); + bf += STB_SPRINTF_DECORATE(sprintf)(bf, "[0x%llx, 0x%llx)", (unsigned long long)range.min, (unsigned long long)range.max); }break; - + // // NOTE(rjf): DEBUGGER PROJECT ADDITION ^^^ //- diff --git a/src/torture/torture.h b/src/torture/torture.h index 647c3471..a2e90725 100644 --- a/src/torture/torture.h +++ b/src/torture/torture.h @@ -40,39 +40,39 @@ extern U64 g_torture_test_count; extern T_Test g_torture_tests[0xffffff]; #define T_AddTest(name, l, ...) \ - T_RunResult t_##name(void); \ - __VA_ARGS__ void t_add_test_##name(void) \ - { \ - g_torture_tests[g_torture_test_count].group = T_Group; \ - g_torture_tests[g_torture_test_count].label = Stringify(name); \ - g_torture_tests[g_torture_test_count].r = &t_##name; \ - g_torture_tests[g_torture_test_count].decl_line = l; \ - g_torture_test_count += 1; \ - } +T_RunResult t_##name(void); \ +__VA_ARGS__ void t_add_test_##name(void) \ +{ \ +g_torture_tests[g_torture_test_count].group = T_Group; \ +g_torture_tests[g_torture_test_count].label = Stringify(name); \ +g_torture_tests[g_torture_test_count].r = &t_##name; \ +g_torture_tests[g_torture_test_count].decl_line = l; \ +g_torture_test_count += 1; \ +} #if COMPILER_MSVC #pragma section(".CRT$XCU", read) # define T_BeginTest_(name) \ - T_AddTest(name, __LINE__) \ - __declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \ - __pragma(comment(linker, "/include:" Stringify(r_##name))) +T_AddTest(name, __LINE__) \ +__declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \ +__pragma(comment(linker, "/include:" Stringify(r_##name))) #else # define T_BeginTest_(name) \ - T_AddTest(name, __LINE__, __attribute__((constructor))) +T_AddTest(name, __LINE__, __attribute__((constructor))) #endif #define T_BeginTest(name) \ - T_BeginTest_(name) \ - T_RunResult t_##name(void) { \ - Temp scratch = scratch_begin(0,0); \ - T_RunResult result = { .status = T_RunStatus_Fail }; +T_BeginTest_(name) \ +T_RunResult t_##name(void) { \ +Temp scratch = scratch_begin(0,0); \ +T_RunResult result = { .status = T_RunStatus_Fail }; #define T_EndTest \ - result.status = T_RunStatus_Pass; \ - exit__:; \ - scratch_end(scratch); \ - return result; \ - } +result.status = T_RunStatus_Pass; \ +exit__:; \ +scratch_end(scratch); \ +return result; \ +} #define T_Ok(c) do { if (!(c)) { result.fail_file = __FILE__; result.fail_line = __LINE__; result.fail_cond = Stringify(c); goto exit__; } } while(0) #define T_MatchLinef(out, ...) T_Ok(t_match_linef(out, __VA_ARGS__)) diff --git a/src/torture/torture_d2r.c b/src/torture/torture_d2r.c index 1255e1c1..e2464b35 100644 --- a/src/torture/torture_d2r.c +++ b/src/torture/torture_d2r.c @@ -7,7 +7,7 @@ internal RDI_Parsed * d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer) { Temp scratch = scratch_begin(&arena, 1); - + String8 raw_coff; { OBJ *obj = obj_alloc(0, Arch_x64); @@ -18,26 +18,26 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer) raw_coff = coff_from_obj(scratch.arena, obj); obj_release(&obj); } - + Assert(t_write_file(str8_lit("a.obj"), raw_coff)); t_invoke(t_radlink_path(), str8_lit("/subsystem:console /out:a.exe /entry:main /DEBUG:FULL /opt:noref /opt:noicf a.obj"), max_U64); Assert(g_last_exit_code == 0); String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); Assert(exe.size > 0); - + B32 was_pdb_deleted = os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb"))); Assert(was_pdb_deleted); - + t_invoke_(t_radbin_path(), str8_lit("-rdi a.exe -out:a.rdi"), max_U64, 0, 0); Assert(g_last_exit_code == 0); - + String8 raw_rdi = t_read_file(arena, str8_lit("a.rdi")); Assert(raw_rdi.size > 0); - + RDI_Parsed *rdi = push_array(arena, RDI_Parsed, 1); RDI_ParseStatus rdi_parse_status = rdi_parse(raw_rdi.str, raw_rdi.size, rdi); Assert(rdi_parse_status == RDI_ParseStatus_Good); - + scratch_end(scratch); return rdi; } @@ -47,10 +47,10 @@ d2rt_type_from_name(RDI_Parsed *rdi, RDI_ParsedNameMap *map, char *name) { String8 s = str8_cstring(name); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, map, s.str, s.size); - + U32 id_count = 0; U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - + if (id_count == 1) { return rdi_element_from_name_idx(rdi, TypeNodes, ids[0]); } @@ -63,104 +63,104 @@ T_BeginTest(d2r_types) { dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test"); - + #define DeclBaseType(tt, n, e, s) \ - DW_WriterTag *tt = dw_writer_tag_begin(writer, DW_TagKind_BaseType); \ - dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, s); \ - dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_##e); \ - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \ - dw_writer_tag_end(writer); - DeclBaseType(char_type, "char", SignedChar, 1); - DeclBaseType(unsigned_char_type, "unsigned char", UnsignedChar, 1); - DeclBaseType(char8_type, "char8_t", Utf, 1); - DeclBaseType(char16_type, "char16_t", Utf, 2); - DeclBaseType(char32_type, "char32_t", Utf, 4); - DeclBaseType(wchar_type, "wchar_t", Signed, 4); - DeclBaseType(bool_type, "_Bool", Boolean, 1); - DeclBaseType(short_type, "short", Signed, 2); - DeclBaseType(unsigned_short_type, "unsigned short", Unsigned, 2); - DeclBaseType(short_unsigned_int_type, "short unsigned int", Unsigned, 2); - DeclBaseType(short_int_type, "short int", Signed, 2); - DeclBaseType(unsigned_int_type, "unsigned int", Unsigned, 4); - DeclBaseType(int_type, "int", Signed, 4); - DeclBaseType(long_int_type, "long int", Signed, 8); - DeclBaseType(long_unsigned_int_type, "long unsigned int", Unsigned, 8); - DeclBaseType(long_long_int_type, "long long int", Signed, 8); - DeclBaseType(long_long_unsigned_int, "long long unsigned int", Unsigned, 8); - DeclBaseType(float_type, "float", Float, 4); - DeclBaseType(double_type, "double", Float, 8); - DeclBaseType(long_double_type, "long double", Float, 16); - DeclBaseType(int128_type, "__int128", Signed, 16); - DeclBaseType(uint128_type, "__int128 unsigned", Unsigned, 16); - DeclBaseType(float16_type, "_Float16", Float, 2); - DeclBaseType(bfloat16_type, "__bf16", Float, 2); - DeclBaseType(float80_type, "__float80", Float, 16); - DeclBaseType(float128_type, "_float128", Float, 16); - DeclBaseType(complex_float_type, "complex float", ComplexFloat, 8); - DeclBaseType(complex_doulbe_type, "complex double", ComplexFloat, 16); - DeclBaseType(complex_long_double_type, "complex long double", ComplexFloat, 32); - DeclBaseType(decimal32_type, "_Decimal32", DecimalFloat, 4); - DeclBaseType(decimal64_type, "_Decimal64", DecimalFloat, 8); - DeclBaseType(decimal128_type, "_Decimal128", DecimalFloat, 16); +DW_WriterTag *tt = dw_writer_tag_begin(writer, DW_TagKind_BaseType); \ +dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, s); \ +dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_##e); \ +dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \ +dw_writer_tag_end(writer); + DeclBaseType(char_type, "char", SignedChar, 1); + DeclBaseType(unsigned_char_type, "unsigned char", UnsignedChar, 1); + DeclBaseType(char8_type, "char8_t", Utf, 1); + DeclBaseType(char16_type, "char16_t", Utf, 2); + DeclBaseType(char32_type, "char32_t", Utf, 4); + DeclBaseType(wchar_type, "wchar_t", Signed, 4); + DeclBaseType(bool_type, "_Bool", Boolean, 1); + DeclBaseType(short_type, "short", Signed, 2); + DeclBaseType(unsigned_short_type, "unsigned short", Unsigned, 2); + DeclBaseType(short_unsigned_int_type, "short unsigned int", Unsigned, 2); + DeclBaseType(short_int_type, "short int", Signed, 2); + DeclBaseType(unsigned_int_type, "unsigned int", Unsigned, 4); + DeclBaseType(int_type, "int", Signed, 4); + DeclBaseType(long_int_type, "long int", Signed, 8); + DeclBaseType(long_unsigned_int_type, "long unsigned int", Unsigned, 8); + DeclBaseType(long_long_int_type, "long long int", Signed, 8); + DeclBaseType(long_long_unsigned_int, "long long unsigned int", Unsigned, 8); + DeclBaseType(float_type, "float", Float, 4); + DeclBaseType(double_type, "double", Float, 8); + DeclBaseType(long_double_type, "long double", Float, 16); + DeclBaseType(int128_type, "__int128", Signed, 16); + DeclBaseType(uint128_type, "__int128 unsigned", Unsigned, 16); + DeclBaseType(float16_type, "_Float16", Float, 2); + DeclBaseType(bfloat16_type, "__bf16", Float, 2); + DeclBaseType(float80_type, "__float80", Float, 16); + DeclBaseType(float128_type, "_float128", Float, 16); + DeclBaseType(complex_float_type, "complex float", ComplexFloat, 8); + DeclBaseType(complex_doulbe_type, "complex double", ComplexFloat, 16); + DeclBaseType(complex_long_double_type, "complex long double", ComplexFloat, 32); + DeclBaseType(decimal32_type, "_Decimal32", DecimalFloat, 4); + DeclBaseType(decimal64_type, "_Decimal64", DecimalFloat, 8); + DeclBaseType(decimal128_type, "_Decimal128", DecimalFloat, 16); #undef DeclBaseType - + #define DeclStdint(n, a) \ - do { \ - dw_writer_tag_begin(writer, DW_TagKind_Typedef); \ - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \ - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, a); \ - dw_writer_tag_end(writer); \ - } while (0) - DeclStdint("uint8_t", unsigned_char_type); - DeclStdint("uint16_t", unsigned_short_type); - DeclStdint("uint32_t", unsigned_int_type); - DeclStdint("uint64_t", long_unsigned_int_type); - DeclStdint("int8_t", char_type); - DeclStdint("int16_t", short_type); - DeclStdint("int32_t", int_type); - DeclStdint("int64_t", long_int_type); +do { \ +dw_writer_tag_begin(writer, DW_TagKind_Typedef); \ +dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \ +dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, a); \ +dw_writer_tag_end(writer); \ +} while (0) + DeclStdint("uint8_t", unsigned_char_type); + DeclStdint("uint16_t", unsigned_short_type); + DeclStdint("uint32_t", unsigned_int_type); + DeclStdint("uint64_t", long_unsigned_int_type); + DeclStdint("int8_t", char_type); + DeclStdint("int16_t", short_type); + DeclStdint("int32_t", int_type); + DeclStdint("int64_t", long_int_type); #undef DeclStdInt - // TODO: @native_vector_support - // - // typedef int __attribute__((vector_size(32))) int256 - // typedef unsigned int __attribute__((vector_size(32))) uint256 - // typedef int __attribute__((vector_size(64))) int512 - // typedef unsigned int __attribute__((vector_size(64))) uint512 - // + // TODO: @native_vector_support + // + // typedef int __attribute__((vector_size(32))) int256 + // typedef unsigned int __attribute__((vector_size(32))) uint256 + // typedef int __attribute__((vector_size(64))) int512 + // typedef unsigned int __attribute__((vector_size(64))) uint512 + // #if 0 - dw_writer_tag_begin(writer, DW_TagKind_ArrayType); - dw_writer_push_attrib_flag(writer, DW_AttribKind_GNU_Vector, 1); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, int_type); - dw_writer_tag_begin(writer, DW_TagKind_SubrangeType); - dw_writer_push_attrib_uint(writer, DW_AttribKind_UpperBound, 15); - dw_writer_tag_end(writer); - dw_writer_tag_end(writer); + dw_writer_tag_begin(writer, DW_TagKind_ArrayType); + dw_writer_push_attrib_flag(writer, DW_AttribKind_GNU_Vector, 1); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, int_type); + dw_writer_tag_begin(writer, DW_TagKind_SubrangeType); + dw_writer_push_attrib_uint(writer, DW_AttribKind_UpperBound, 15); + dw_writer_tag_end(writer); + dw_writer_tag_end(writer); #endif - + dw_writer_tag_end(writer); } - + RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer); RDI_NameMap *types_nm = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types); T_Ok(types_nm); - + RDI_ParsedNameMap types_map = {0}; rdi_parsed_from_name_map(rdi, types_nm, &types_map); - + #define TestBuiltinType(n, bs, r) \ - do { \ - RDI_TypeNode *alias = d2rt_type_from_name(rdi, &types_map, n); \ - T_Ok(alias); \ - T_Ok(alias->kind == RDI_TypeKind_Alias); \ - T_Ok(alias->flags == 0); \ - T_Ok(alias->byte_size == bs); \ - RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, alias->user_defined.direct_type_idx); \ - T_Ok(type); \ - T_Ok(type->kind == RDI_TypeKind_##r); \ - T_Ok(type->flags == 0); \ - T_Ok(type->byte_size == alias->byte_size); \ - T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(Stringify(r)), 0)); \ - } while (0) +do { \ +RDI_TypeNode *alias = d2rt_type_from_name(rdi, &types_map, n); \ +T_Ok(alias); \ +T_Ok(alias->kind == RDI_TypeKind_Alias); \ +T_Ok(alias->flags == 0); \ +T_Ok(alias->byte_size == bs); \ +RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, alias->user_defined.direct_type_idx); \ +T_Ok(type); \ +T_Ok(type->kind == RDI_TypeKind_##r); \ +T_Ok(type->flags == 0); \ +T_Ok(type->byte_size == alias->byte_size); \ +T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(Stringify(r)), 0)); \ +} while (0) TestBuiltinType("char", 1, Char8); TestBuiltinType("char8_t", 1, UChar8); TestBuiltinType("char16_t", 2, UChar16); @@ -193,21 +193,21 @@ T_BeginTest(d2r_types) TestBuiltinType("_Decimal64", 8, Decimal64); TestBuiltinType("_Decimal128", 16, Decimal128); #undef TestBuiltinType - + #define TestStdint(n, s, t) \ - do { \ - RDI_TypeNode *td = d2rt_type_from_name(rdi, &types_map, n); \ - T_Ok(td); \ - T_Ok(td->kind == RDI_TypeKind_Alias); \ - T_Ok(td->flags == 0); \ - T_Ok(td->byte_size == s); \ - RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, td->user_defined.direct_type_idx); \ - T_Ok(type); \ - T_Ok(type->kind == RDI_TypeKind_Alias); \ - T_Ok(type->flags == 0); \ - T_Ok(type->byte_size = td->byte_size); \ - T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(t), 0)); \ - } while (0) +do { \ +RDI_TypeNode *td = d2rt_type_from_name(rdi, &types_map, n); \ +T_Ok(td); \ +T_Ok(td->kind == RDI_TypeKind_Alias); \ +T_Ok(td->flags == 0); \ +T_Ok(td->byte_size == s); \ +RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, td->user_defined.direct_type_idx); \ +T_Ok(type); \ +T_Ok(type->kind == RDI_TypeKind_Alias); \ +T_Ok(type->flags == 0); \ +T_Ok(type->byte_size = td->byte_size); \ +T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(t), 0)); \ +} while (0) TestStdint("uint8_t", 1, "unsigned char"); TestStdint("uint16_t", 2, "unsigned short"); TestStdint("uint32_t", 4, "unsigned int"); @@ -217,7 +217,7 @@ T_BeginTest(d2r_types) TestStdint("int32_t", 4, "int"); TestStdint("int64_t", 8, "long int"); #undef TestStdint - + dw_writer_end(&writer); } T_EndTest; @@ -227,10 +227,10 @@ T_BeginTest(d2r_line_table) DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); String8 comp_dir = str8_lit("c:/DEVEL/"); String8 comp_name = str8_lit("test.c"); - + DW_WriterFile *foo_file = dw_writer_new_file(writer, str8_lit("/mnt/C/Devel/foo.c")); DW_WriterFile *comp_file = dw_writer_new_file(writer, str8f(scratch.arena, "%S%S", comp_dir, comp_name)); - + struct { DW_WriterFile *file; U64 ln; U64 line_size; U64 voff; } test_table[] = { @@ -243,7 +243,7 @@ T_BeginTest(d2r_line_table) { foo_file, 100, 1 }, { comp_file, max_U32 - 0x100, 10 }, }; - + U64 exe_base = coff_default_exe_base_from_machine(COFF_MachineType_X64); U64 voff = 0x1000; for EachElement(i, test_table) { @@ -251,25 +251,25 @@ T_BeginTest(d2r_line_table) dw_writer_line_emit(writer, test_table[i].file, test_table[i].ln, 0, exe_base + voff); voff += test_table[i].line_size; } - + // emit one past last line dw_writer_line_emit(writer, test_table[ArrayCount(test_table) - 1].file, test_table[ArrayCount(test_table) - 1].ln, 0, exe_base + voff); - + dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); - dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir); - dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name); - dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, exe_base); - dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, exe_base + voff); - dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); + dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); + dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir); + dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name); + dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, exe_base); + dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, exe_base + voff); + dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); dw_writer_tag_end(writer); - + d2r_rdi_from_dwarf_writer(scratch.arena, writer); - + for EachElement(i, test_table) { for EachIndex(k, test_table[i].line_size) { String8 cmd_line = str8f(scratch.arena, "-voff2line -voff:0x%llx a.rdi", test_table[i].voff + k); @@ -279,7 +279,7 @@ T_BeginTest(d2r_line_table) T_MatchLinef(&output, "%S:%llu", test_table[i].file->path, test_table[i].ln); } } - + dw_writer_end(&writer); } T_EndTest; @@ -287,35 +287,35 @@ T_EndTest; T_BeginTest(d2r_checksums) { DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); - + DW_WriterFile *foo_file = dw_writer_new_file(writer, str8_lit("/mnt/c/devel/foo.c")); DW_WriterFile *comp_file = dw_writer_new_file(writer, str8_lit("/home/main.c")); foo_file->md5 = *(U128 *)&(U8[16]){ 0x04, 0x70, 0xe9, 0x6b, 0xa3, 0x05, 0x2c, 0xc8, 0x2d, 0x70, 0xc5, 0xe9, 0x80, 0x8e, 0x8a, 0x4e, }; comp_file->md5 = *(U128 *)&(U8[16]){ 0x82, 0x3c, 0xc6, 0x02, 0x82, 0x9e, 0xf6, 0xce, 0x53, 0xff, 0x5a, 0x93, 0xb6, 0x6e, 0x59, 0x38 }; comp_file->time_stamp = 123; // convert must pick MD5 checksum over time stamp - + dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); - dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, str8_chop_last_slash(comp_file->path)); - dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_skip_last_slash(comp_file->path)); - dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); + dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); + dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, str8_chop_last_slash(comp_file->path)); + dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_skip_last_slash(comp_file->path)); + dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); dw_writer_tag_end(writer); - + RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer); U64 checksum_count = 0; RDI_MD5 *checksums = rdi_table_from_name(rdi, MD5Checksums, &checksum_count); T_Ok(checksum_count == writer->line.file_count + 1); - - RDI_SourceFile *foo_src_file = rdi_source_file_from_normal_path_cstr(rdi, foo_file->path.cstr); + + RDI_SourceFile *foo_src_file = rdi_source_file_from_normal_path_cstr(rdi, (char *)foo_file->path.str); T_Ok(foo_src_file); T_Ok(foo_src_file->checksum_kind == RDI_ChecksumKind_MD5); T_Ok(MemoryMatch(&foo_file->md5, &checksums[foo_src_file->checksum_idx], sizeof(U128))); - - RDI_SourceFile *comp_src_file = rdi_source_file_from_normal_path_cstr(rdi, comp_file->path.cstr); + + RDI_SourceFile *comp_src_file = rdi_source_file_from_normal_path_cstr(rdi, (char *)comp_file->path.str); T_Ok(comp_src_file); T_Ok(comp_src_file->checksum_kind == RDI_ChecksumKind_MD5); T_Ok(MemoryMatch(&comp_file->md5, &checksums[comp_src_file->checksum_idx], sizeof(U128))); - + dw_writer_end(&writer); } T_EndTest; @@ -324,7 +324,7 @@ T_EndTest; T_BeginTest(d2r_subprogram) { DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); - + U64 image_lo = coff_default_exe_base_from_machine(COFF_MachineType_X64); U64 image_hi = image_lo + 0x10000; U64 subprogram_lo = image_lo + 0x1000; @@ -332,111 +332,111 @@ T_BeginTest(d2r_subprogram) U64 subprogram_entry_addr = subprogram_lo + 5; String8 subprogram_link_name = str8_lit("@FOOBAR!"); String8 subprogram_name = str8_lit("foobar"); - + dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_string (writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); - dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, image_lo); - dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, image_hi); - - DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); - dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 1); - dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char"); - dw_writer_tag_end(writer); - - DW_WriterTag *char_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); - dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 8); - dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_type); - dw_writer_tag_end(writer); - - DW_WriterTag *int_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); - dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 4); - dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_Signed); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "int"); - dw_writer_tag_end(writer); - - DW_WriterTag *int_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); - dw_writer_push_attrib_uint(writer, DW_AttribKind_ByteSize, 8); - dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type); - dw_writer_tag_end(writer); - - dw_writer_tag_begin(writer, DW_TagKind_SubProgram); - dw_writer_push_attrib_enum (writer, DW_AttribKind_Accessibility, DW_AccessKind_Private); - dw_writer_push_attrib_enum (writer, DW_AttribKind_AddressClass, DW_AddrClassKind_None); - dw_writer_push_attrib_uint (writer, DW_AttribKind_Alignment, 32); - dw_writer_push_attrib_flag (writer, DW_AttribKind_Artificial, 1); - dw_writer_push_attrib_enum (writer, DW_AttribKind_CallingConvention, DW_CallingConventionKind_Program); - dw_writer_push_attrib_flag (writer, DW_AttribKind_Deleted, 1); - dw_writer_push_attrib_address(writer, DW_AttribKind_EntryPc, subprogram_entry_addr); - dw_writer_push_attrib_flag (writer, DW_AttribKind_Explicit, 1); - dw_writer_push_attrib_flag (writer, DW_AttribKind_External, 1); - dw_writer_push_attrib_exprv (writer, DW_AttribKind_FrameBase, DW_ExprEnc_Op(Reg7)); - dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, subprogram_hi); - dw_writer_push_attrib_enum (writer, DW_AttribKind_Inline, DW_Inl_DeclaredNotInlined); - dw_writer_push_attrib_string (writer, DW_AttribKind_LinkageName, subprogram_link_name); - dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, subprogram_lo); - dw_writer_push_attrib_flag (writer, DW_AttribKind_MainSubProgram, 1); - dw_writer_push_attrib_string (writer, DW_AttribKind_Name, subprogram_name); - dw_writer_push_attrib_flag (writer, DW_AttribKind_NoReturn, 1); - dw_writer_push_attrib_flag (writer, DW_AttribKind_Prototyped, 1); - dw_writer_push_attrib_flag (writer, DW_AttribKind_Pure, 1); - dw_writer_push_attrib_flag (writer, DW_AttribKind_Recursive, 1); - dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type); - dw_writer_push_attrib_enum (writer, DW_AttribKind_Visibility, DW_Vis_Local); - // TODO: DW_AttribKind_ObjectPointer - // TODO: DW_AttribKind_Ranges - // TODO: DW_AttribKind_StartScope - dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "a"); - dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type); - dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg2)); // rcx - dw_writer_tag_end(writer); - - dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "b"); - dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_ptr_type); - dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg5)); // rdi - dw_writer_tag_end(writer); - - dw_writer_tag_begin(writer, DW_TagKind_UnspecifiedParameters); - dw_writer_tag_end(writer); - dw_writer_tag_end(writer); - - // -------------------------------------------------------------------------------- - - DW_WriterTag *my_struct_type = dw_writer_tag_reserve(writer, DW_TagKind_StructureType); - - DW_WriterTag *const_my_struct_type = dw_writer_tag_begin(writer, DW_TagKind_ConstType); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_type); - dw_writer_tag_end(writer); - - DW_WriterTag *my_struct_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, const_my_struct_type); - dw_writer_tag_end(writer); - - dw_writer_tag_begin_reserved(writer, my_struct_type); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyStructure"); - dw_writer_push_attrib_uint (writer, DW_AttribKind_ByteSize, 0x100); - - dw_writer_tag_begin(writer, DW_TagKind_SubProgram); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyMethod"); - dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type); - - dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_ptr_type); - dw_writer_tag_end(writer); - dw_writer_tag_end(writer); - dw_writer_tag_end(writer); - - // -------------------------------------------------------------------------------- - + dw_writer_push_attrib_string (writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); + dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, image_lo); + dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, image_hi); + + DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); + dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 1); + dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char"); dw_writer_tag_end(writer); - + + DW_WriterTag *char_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); + dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 8); + dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_type); + dw_writer_tag_end(writer); + + DW_WriterTag *int_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); + dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 4); + dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_Signed); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "int"); + dw_writer_tag_end(writer); + + DW_WriterTag *int_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); + dw_writer_push_attrib_uint(writer, DW_AttribKind_ByteSize, 8); + dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type); + dw_writer_tag_end(writer); + + dw_writer_tag_begin(writer, DW_TagKind_SubProgram); + dw_writer_push_attrib_enum (writer, DW_AttribKind_Accessibility, DW_AccessKind_Private); + dw_writer_push_attrib_enum (writer, DW_AttribKind_AddressClass, DW_AddrClassKind_None); + dw_writer_push_attrib_uint (writer, DW_AttribKind_Alignment, 32); + dw_writer_push_attrib_flag (writer, DW_AttribKind_Artificial, 1); + dw_writer_push_attrib_enum (writer, DW_AttribKind_CallingConvention, DW_CallingConventionKind_Program); + dw_writer_push_attrib_flag (writer, DW_AttribKind_Deleted, 1); + dw_writer_push_attrib_address(writer, DW_AttribKind_EntryPc, subprogram_entry_addr); + dw_writer_push_attrib_flag (writer, DW_AttribKind_Explicit, 1); + dw_writer_push_attrib_flag (writer, DW_AttribKind_External, 1); + dw_writer_push_attrib_exprv (writer, DW_AttribKind_FrameBase, DW_ExprEnc_Op(Reg7)); + dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, subprogram_hi); + dw_writer_push_attrib_enum (writer, DW_AttribKind_Inline, DW_Inl_DeclaredNotInlined); + dw_writer_push_attrib_string (writer, DW_AttribKind_LinkageName, subprogram_link_name); + dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, subprogram_lo); + dw_writer_push_attrib_flag (writer, DW_AttribKind_MainSubProgram, 1); + dw_writer_push_attrib_string (writer, DW_AttribKind_Name, subprogram_name); + dw_writer_push_attrib_flag (writer, DW_AttribKind_NoReturn, 1); + dw_writer_push_attrib_flag (writer, DW_AttribKind_Prototyped, 1); + dw_writer_push_attrib_flag (writer, DW_AttribKind_Pure, 1); + dw_writer_push_attrib_flag (writer, DW_AttribKind_Recursive, 1); + dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type); + dw_writer_push_attrib_enum (writer, DW_AttribKind_Visibility, DW_Vis_Local); + // TODO: DW_AttribKind_ObjectPointer + // TODO: DW_AttribKind_Ranges + // TODO: DW_AttribKind_StartScope + dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "a"); + dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type); + dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg2)); // rcx + dw_writer_tag_end(writer); + + dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "b"); + dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_ptr_type); + dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg5)); // rdi + dw_writer_tag_end(writer); + + dw_writer_tag_begin(writer, DW_TagKind_UnspecifiedParameters); + dw_writer_tag_end(writer); + dw_writer_tag_end(writer); + + // -------------------------------------------------------------------------------- + + DW_WriterTag *my_struct_type = dw_writer_tag_reserve(writer, DW_TagKind_StructureType); + + DW_WriterTag *const_my_struct_type = dw_writer_tag_begin(writer, DW_TagKind_ConstType); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_type); + dw_writer_tag_end(writer); + + DW_WriterTag *my_struct_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, const_my_struct_type); + dw_writer_tag_end(writer); + + dw_writer_tag_begin_reserved(writer, my_struct_type); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyStructure"); + dw_writer_push_attrib_uint (writer, DW_AttribKind_ByteSize, 0x100); + + dw_writer_tag_begin(writer, DW_TagKind_SubProgram); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyMethod"); + dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type); + + dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_ptr_type); + dw_writer_tag_end(writer); + dw_writer_tag_end(writer); + dw_writer_tag_end(writer); + + // -------------------------------------------------------------------------------- + + dw_writer_tag_end(writer); + RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer); - RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, subprogram_name.cstr); + RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, (char *)subprogram_name.str); RDI_TypeNode *proc_type = rdi_element_from_name_idx(rdi, TypeNodes, proc->type_idx); String8 proc_string = rdi_string_from_type(scratch.arena, rdi, proc, proc_type); - + dw_writer_end(&writer); } T_EndTest; @@ -448,53 +448,53 @@ T_BeginTest(d2r_general) { dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test"); - // declare char type - DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); - dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1); - dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char"); - dw_writer_tag_end(writer); - // declare function - dw_writer_tag_begin(writer, DW_TagKind_SubProgram); - dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140173f9); - dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14017474b); - dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1); - dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "FooBar"); - // declare variable - dw_writer_tag_begin(writer, DW_TagKind_Variable); - dw_writer_push_attrib_exprv(writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg7)); - dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "TestLocal"); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); - dw_writer_tag_end(writer); - dw_writer_tag_end(writer); + // declare char type + DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); + dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1); + dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char"); + dw_writer_tag_end(writer); + // declare function + dw_writer_tag_begin(writer, DW_TagKind_SubProgram); + dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140173f9); + dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14017474b); + dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1); + dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "FooBar"); + // declare variable + dw_writer_tag_begin(writer, DW_TagKind_Variable); + dw_writer_push_attrib_exprv(writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg7)); + dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "TestLocal"); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); + dw_writer_tag_end(writer); + dw_writer_tag_end(writer); } - + RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer); - + RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, "FooBar"); T_Ok(proc); T_Ok(proc->link_flags == RDI_LinkFlag_External); String8 proc_name = str8_from_rdi_string_idx(rdi, proc->name_string_idx); T_Ok(str8_match(proc_name, str8_lit("FooBar"), 0)); - + RDI_Scope *root_scope = rdi_root_scope_from_procedure(rdi, proc); T_Ok(root_scope); T_Ok(root_scope->local_count == 1); - + RDI_Local *test_local = rdi_element_from_name_idx(rdi, Locals, root_scope->local_first + 0); T_Ok(test_local); T_Ok(test_local->kind == RDI_LocalKind_Variable); String8 test_local_name = str8_from_rdi_string_idx(rdi, test_local->name_string_idx); T_Ok(str8_match(test_local_name, str8_lit("TestLocal"), 0)); - + RDI_TypeNode *test_local_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local->type_idx); T_Ok(test_local_type); T_Ok(test_local_type->kind == RDI_TypeKind_Alias); T_Ok(test_local_type->flags == 0); String8 alias_name = str8_from_rdi_string_idx(rdi, test_local_type->user_defined.name_string_idx); T_Ok(str8_match(alias_name, str8_lit("char"), 0)); - + RDI_TypeNode *char_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local_type->user_defined.direct_type_idx); T_Ok(char_type); T_Ok(char_type->kind == RDI_TypeKind_Char8); @@ -502,7 +502,7 @@ T_BeginTest(d2r_general) T_Ok(char_type->byte_size == 1); String8 char_type_name = str8_from_rdi_string_idx(rdi, char_type->built_in.name_string_idx); T_Ok(str8_match(char_type_name, str8_lit("Char8"), 0)); - + dw_writer_end(&writer); } T_EndTest; diff --git a/src/torture/torture_dwarf.c b/src/torture/torture_dwarf.c index 98d92b25..728cbb58 100644 --- a/src/torture/torture_dwarf.c +++ b/src/torture/torture_dwarf.c @@ -8,18 +8,18 @@ t_dw_test_uleb128(U64 v, U64 expected_length) { Temp scratch = scratch_begin(0, 0); B32 is_ok = 0; - + U64 v0 = v; String8 e = dw_write_uleb128(scratch.arena, v0); if (!(expected_length == e.size)) { goto exit; } - + U64 v1; U64 bytes_read = str8_deserial_read_uleb128(e, 0, &v1); if (!(bytes_read == e.size)) { goto exit; } if (!(v0 == v1)) { goto exit; } - + is_ok = 1; -exit:; + exit:; scratch_end(scratch); return is_ok; } @@ -29,18 +29,18 @@ t_dw_test_sleb128(U64 v, U64 expected_length) { Temp scratch = scratch_begin(0,0); B32 is_ok = 0; - + U64 v0 = v; String8 e = dw_write_sleb128(scratch.arena, v0); if (!(expected_length == e.size)) { goto exit; } - + S64 v1; U64 bytes_read = str8_deserial_read_sleb128(e, 0, &v1); if (!(bytes_read == e.size)) { goto exit; } if (!(v0 == v1)) { goto exit; } - + is_ok = 1; -exit:; + exit:; scratch_end(scratch); return is_ok; } @@ -50,13 +50,13 @@ T_BeginTest(test_leb128) T_Ok(t_dw_test_uleb128(0, 1)); T_Ok(t_dw_test_sleb128(0, 1)); T_Ok(t_dw_test_sleb128(-1, 1)); - + T_Ok(t_dw_test_uleb128(max_U64, 10)); T_Ok(t_dw_test_sleb128(min_S64, 10)); T_Ok(t_dw_test_sleb128(max_S64, 10)); - + T_Ok(t_dw_test_uleb128(0xDEADBEEFCAFEBABE, 10)); - + for EachIndex(i, 64) { T_Ok(t_dw_test_uleb128((1ull << i), 1 + (i / 7))); } @@ -70,7 +70,7 @@ internal B32 dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag) { B32 is_match = 0; - + // match headers B32 writer_has_children = writer_tag->first_child != 0; if (writer_tag->kind != reader_tag->tag.kind) { goto exit; } @@ -78,7 +78,7 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag) if (writer_tag->attrib_count != reader_tag->tag.attribs.count) { goto exit; } if (writer_tag->info_off != reader_tag->tag.info_off) { goto exit; } if (writer_has_children != reader_tag->tag.has_children) { goto exit; } - + // match attribs DW_WriterAttrib *writer_attrib = writer_tag->first_attrib; DW_AttribNode *reader_attrib = reader_tag->tag.attribs.first; @@ -89,7 +89,7 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag) writer_attrib = writer_attrib->next; reader_attrib = reader_attrib->next; } - + // visit children DW_WriterTag *writer_child = writer_tag->first_child; DW_TagNode *reader_child = reader_tag->first_child; @@ -98,9 +98,9 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag) writer_child = writer_child->next; reader_child = reader_child->sibling; } - + is_match = 1; -exit:; + exit:; return is_match; } @@ -108,7 +108,7 @@ internal DW_Input dw_input_from_writer(Arena *arena, DW_Writer *writer) { Temp scratch = scratch_begin(&arena, 1); - + OBJ *obj = obj_alloc(0, Arch_x64); OBJ_Section *text_section = obj_push_section(obj, str8_lit(".text"), OBJ_SectionFlag_Read|OBJ_SectionFlag_Exec|OBJ_SectionFlag_Load); str8_serial_push_u8(obj->arena, &text_section->data, 0x90); @@ -116,20 +116,20 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer) str8_serial_push_u8(obj->arena, &text_section->data, 0x90); str8_serial_push_u8(obj->arena, &text_section->data, 0xc3); obj_push_symbol(obj, str8_lit("entry"), OBJ_SymbolScope_Global, OBJ_RefKind_Section, text_section); - + dw_writer_emit_to_obj(writer, obj); String8 raw_coff = coff_from_obj(scratch.arena, obj); - + t_write_file(str8_lit("dwarf.obj"), raw_coff); t_invoke(str8_lit("radlink"), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64); os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb"))); - + String8 exe = t_read_file(arena, str8_lit("a.exe")); PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); COFF_SectionHeader *section_table = (COFF_SectionHeader *)(exe.str + pe.section_table_range.min); String8 string_table = str8_substr(exe, pe.string_table_range); DW_Input input = dw_input_from_coff_section_table(arena, exe, string_table, pe.section_count, section_table); - + obj_release(&obj); scratch_end(scratch); return input; @@ -139,27 +139,27 @@ T_BeginTest(dwarf_32bit) { DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); + dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); dw_writer_tag_end(writer); - + DW_Input input = dw_input_from_writer(scratch.arena, writer); - + for EachElement(sec_idx, input.sec) { if (sec_idx == DW_Section_Abbrev) continue; Rng1U64Array unit_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[sec_idx].data); for EachIndex(range_idx, unit_ranges.count) { Rng1U64 range = unit_ranges.v[range_idx]; - + U32 first_four_bytes = 0; T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min, &first_four_bytes) == sizeof(first_four_bytes)); T_Ok(first_four_bytes + 4 == dim_1u64(range)); - + U32 unit_length = 0; T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min, &unit_length) == sizeof(U32)); T_Ok(unit_length + 4 == dim_1u64(range)); } } - + dw_writer_end(&writer); } T_EndTest; @@ -170,25 +170,25 @@ T_BeginTest(dwarf_64bit) dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); dw_writer_tag_end(writer); - + DW_Input input = dw_input_from_writer(scratch.arena, writer); - + for EachElement(sec_idx, input.sec) { if (sec_idx == DW_Section_Abbrev) continue; Rng1U64Array unit_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[sec_idx].data); for EachIndex(range_idx, unit_ranges.count) { Rng1U64 range = unit_ranges.v[range_idx]; - + U32 first_four_bytes = 0; T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min, &first_four_bytes) == sizeof(first_four_bytes)); T_Ok(first_four_bytes == max_U32); - + U64 unit_length = 0; T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min + sizeof(U32), &unit_length) == sizeof(U64)); T_Ok(unit_length + 12 == dim_1u64(range)); } } - + dw_writer_end(&writer); } T_EndTest; @@ -200,12 +200,12 @@ T_BeginTest(dwarf_line_opcodes) String8 comp_name = str8_lit("test.c"); U64 address = 0xDEADBEEFCAFEBABE; dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); - dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir); - dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name); - dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); + dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); + dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir); + dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name); + dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); dw_writer_tag_end(writer); - + // test directory table and file table DW_WriterFile *file2 = dw_writer_new_file(writer, str8_lit("d:/foobar/qwe.c")); file2->time_stamp = 123; @@ -217,7 +217,7 @@ T_BeginTest(dwarf_line_opcodes) file->size = 314; file->md5 = *(U128 *)&((U8[sizeof(U128)]) { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, }); file->source = str8_lit("int main() { return 057; }\n"); - + dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_copy()); dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(7)); dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(-7)); @@ -237,32 +237,32 @@ T_BeginTest(dwarf_line_opcodes) dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_address(address)); dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_discriminator(2)); dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_end_sequence()); - + DW_Input input = dw_input_from_writer(scratch.arena, writer); Rng1U64Array cu_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[DW_Section_Info].data); DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, (DW_ListUnitInput){0}, cu_ranges.v[0].min, 0); DW_LineVM *line_vm = dw_line_vm_init(&input, &cu); - + T_Ok(line_vm->header.dir_table.count == 2); T_Ok(line_vm->header.file_table.count == 2); - + T_Ok(str8_match(line_vm->header.dir_table.v[0], str8_lit("c:/devel"), 0)); T_Ok(str8_match(line_vm->header.dir_table.v[1], str8_lit("d:/foobar"), 0)); - + DW_LineFile *file_reader = &line_vm->header.file_table.v[0]; T_Ok(str8_match(file_reader->path, comp_name, 0)); T_Ok(file_reader->dir_idx == 0); T_Ok(file_reader->time_stamp == file->time_stamp); T_Ok(u128_match(file_reader->md5, file->md5)); T_Ok(str8_match(file_reader->source, file->source, 0)); - + DW_LineFile *file2_reader = &line_vm->header.file_table.v[1]; T_Ok(str8_match(file2_reader->path, str8_lit("qwe.c"), 0)); T_Ok(file2_reader->dir_idx == 1); T_Ok(file2_reader->time_stamp == file2->time_stamp); T_Ok(u128_match(file2_reader->md5, file2->md5)); T_Ok(str8_match(file2_reader->source, file2->source, 0)); - + T_Ok(line_vm->new_line == 0); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_Copy); @@ -271,48 +271,48 @@ T_BeginTest(dwarf_line_opcodes) T_Ok(line_vm->state.basic_block == 0); T_Ok(line_vm->state.prologue_end == 0); T_Ok(line_vm->state.epilogue_begin == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc); T_Ok(line_vm->state.address == 7); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc); T_Ok(line_vm->state.address == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 5); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 1); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetFile); T_Ok(line_vm->state.file_index == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetColumn); T_Ok(line_vm->state.column == max_U64); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetColumn); T_Ok(line_vm->state.column == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_NegateStmt); T_Ok(line_vm->state.is_stmt == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_NegateStmt); T_Ok(line_vm->state.is_stmt == 1); - + T_Ok(line_vm->state.basic_block == 0); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetBasicBlock); T_Ok(line_vm->state.basic_block == 1); - + { U64 addr_before = line_vm->state.address; U64 const_advance = (0xffu - line_vm->header.opcode_base) / line_vm->header.line_range; @@ -320,45 +320,45 @@ T_BeginTest(dwarf_line_opcodes) T_Ok(!line_vm->new_line); T_Ok(line_vm->state.address == addr_before + const_advance); } - + T_Ok(line_vm->state.address == 0x11); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_FixedAdvancePc); T_Ok(line_vm->state.address == max_U16 + 0x11); - + T_Ok(line_vm->state.prologue_end == 0); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetPrologueEnd); T_Ok(line_vm->state.prologue_end == 1); - + T_Ok(line_vm->state.epilogue_begin == 0); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetEpilogueBegin); T_Ok(line_vm->state.epilogue_begin == 1); - + T_Ok(line_vm->state.isa == 0); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetIsa); T_Ok(line_vm->state.isa == max_U64); - + T_Ok(line_vm->state.address != address); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode); T_Ok(line_vm->ext_opcode == DW_ExtOpcode_SetAddress); T_Ok(line_vm->state.address == address); - + T_Ok(line_vm->state.discriminator == 0); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode); T_Ok(line_vm->ext_opcode == DW_ExtOpcode_SetDiscriminator); T_Ok(line_vm->state.discriminator == 2); - + T_Ok(!line_vm->state.end_sequence); T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode); T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence); T_Ok(line_vm->state.end_sequence); - + dw_writer_end(&writer); } T_EndTest; @@ -369,39 +369,39 @@ T_BeginTest(dwarf_line_emit) String8 comp_dir = str8_lit("c:/devel/"); String8 comp_name = str8_lit("test.c"); dw_writer_tag_begin(writer, DW_TagKind_CompileUnit); - dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); - dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir); - dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name); - dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); + dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER")); + dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir); + dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name); + dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0); dw_writer_tag_end(writer); - + // test special opcode writer and reader DW_WriterFile *file = dw_writer_new_file(writer, comp_name); - + // init sequence dw_writer_line_emit(writer, file, 10000, 0, 1000); - + for EachIndex(i, abs_s64(writer->line.line_base) + 1) { dw_writer_line_emit(writer, file, writer->line.ln-i, 0, writer->line.addr+1); - + dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(i)); writer->line.ln += i; } - + // special opcode line window underflow, must emit three instructions to advance dw_writer_line_emit(writer, file, (writer->line.ln + writer->line.line_base) - 1, 0, writer->line.addr + 1); dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-(writer->line.line_base - 1))); - + for EachIndex(i, (writer->line.line_range + writer->line.line_base) + 1) { dw_writer_line_emit(writer, file, writer->line.ln+i, 0, writer->line.addr+1); - + dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-i)); writer->line.ln -= i; } - + dw_writer_line_end_sequence(writer); dw_writer_line_emit(writer, file, 1000, 0, writer->line.addr+1); - + // test address window S64 c = writer->line.line_range + writer->line.line_base; U64 line_addr_count = 0; @@ -414,40 +414,40 @@ T_BeginTest(dwarf_line_emit) line_addr_count += 1; } } - + DW_Input input = dw_input_from_writer(scratch.arena, writer); Rng1U64Array cu_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[DW_Section_Info].data); DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, (DW_ListUnitInput){0}, cu_ranges.v[0].min, 0); DW_LineVM *line_vm = dw_line_vm_init(&input, &cu); - + // check init sequence { T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_SetFile); T_Ok(line_vm->state.file_index == 0); T_Ok(line_vm->new_line == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc); T_Ok(line_vm->state.address == 1000); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->new_line == 0); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_Copy); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == 1000); T_Ok(line_vm->new_line == 1); } - + { U64 pc = line_vm->state.address; for EachIndex(i, abs_s64(writer->line.line_base) + 1) { pc += 1; - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == 0x20 - i); T_Ok(line_vm->state.line == 10000 - i); @@ -459,81 +459,81 @@ T_BeginTest(dwarf_line_emit) T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == pc); } - + // line window underflow check { pc += 1; - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 9994); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_Copy); T_Ok(line_vm->state.line == 9994); T_Ok(line_vm->state.address == pc); T_Ok(line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); } - + for EachIndex(i, writer->line.line_range + writer->line.line_base) { pc += 1; - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == 0x20 + i); T_Ok(line_vm->state.line == 10000 + i); T_Ok(line_vm->state.address == pc); T_Ok(line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); } - + // line window overflow check { pc += 1; - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 10009); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_Copy); T_Ok(line_vm->state.address == pc); T_Ok(line_vm->state.line == 10009); T_Ok(line_vm->new_line); - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine); T_Ok(line_vm->state.line == 10000); T_Ok(line_vm->state.address == pc); T_Ok(!line_vm->new_line); } - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode); T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence); @@ -541,19 +541,19 @@ T_BeginTest(dwarf_line_emit) T_Ok(line_vm->state.address == pc); T_Ok(line_vm->new_line); } - + { T_Ok(dw_line_vm_step(line_vm)); T_Ok(dw_line_vm_step(line_vm)); T_Ok(dw_line_vm_step(line_vm)); T_Ok(dw_line_vm_step(line_vm)); - + for EachIndex(i, line_addr_count/*first line is a noop*/-1) { T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->header.opcode_base < line_vm->opcode); T_Ok(line_vm->new_line); } - + T_Ok(dw_line_vm_step(line_vm)); T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode); T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence); @@ -581,18 +581,18 @@ T_BeginTest(dwarf_writer) dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("char")); dw_writer_tag_end(writer); - + dw_writer_tag_begin(writer, DW_TagKind_ConstType); dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); dw_writer_tag_end(writer); - + // test abbrev dedup DW_WriterTag *dup_char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType); dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1); dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar); dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("char")); dw_writer_tag_end(writer); - + // simple struct test DW_WriterTag *simple_struct_tag = dw_writer_tag_begin(writer, DW_TagKind_StructureType); dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("FooBar")); @@ -603,7 +603,7 @@ T_BeginTest(dwarf_writer) dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); dw_writer_push_attrib_sint(writer, DW_AttribKind_DataMemberLocation, 0); dw_writer_tag_end(writer); - + dw_writer_tag_begin(writer, DW_TagKind_Member); dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("m1")); dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type); @@ -612,7 +612,7 @@ T_BeginTest(dwarf_writer) dw_writer_tag_end(writer); } dw_writer_tag_end(writer); - + dw_writer_tag_begin(writer, DW_TagKind_SubProgram); dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1); dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1); @@ -625,15 +625,15 @@ T_BeginTest(dwarf_writer) } dw_writer_tag_end(writer); } - + DW_Input input = dw_input_from_writer(scratch.arena, writer); DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input); DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, lu_input, 0, 1); DW_TagTree tag_tree = dw_tag_tree_from_cu(scratch.arena, &input, &cu); AssertAlways(dwt_tags_must_match(writer->root, tag_tree.root)); - + // validate the writer - + T_Ok(writer->current == 0); T_Ok(writer->format == DW_Format_32Bit); T_Ok(writer->cu_kind == DW_CompUnitKind_Compile); @@ -642,7 +642,7 @@ T_BeginTest(dwarf_writer) T_Ok(writer->abbrev_base_info_off == 8); T_Ok(writer->fixups.count == 0); T_Ok(writer->abbrev_id_map->count == 7); - + DW_WriterTag *comp_unit_tag = writer->root; { T_Ok(comp_unit_tag->kind == DW_TagKind_CompileUnit); @@ -651,24 +651,24 @@ T_BeginTest(dwarf_writer) T_Ok(comp_unit_tag->attrib_count == 5); T_Ok(comp_unit_tag->abbrev_id == 1); T_Ok(comp_unit_tag->info_off == 0xc); - + DW_WriterAttrib *producer_attrib = comp_unit_tag->first_attrib; T_Ok(producer_attrib->kind == DW_AttribKind_Producer); T_Ok(producer_attrib->form.reader.kind == DW_Form_String); T_Ok(str8_match(producer_attrib->form.writer.string, str8_lit("RAD DWARF WRITER"), 0)); - + DW_WriterAttrib *language_attrib = producer_attrib->next; T_Ok(language_attrib->kind == DW_AttribKind_Language); T_Ok(language_attrib->form.reader.kind == DW_Form_Data1); T_Ok(language_attrib->form.reader.data.size == 1); T_Ok(*(U8 *)language_attrib->form.reader.data.str == DW_Language_C99); - + DW_WriterAttrib *use_utf8_attrib = language_attrib->next; T_Ok(use_utf8_attrib->kind == DW_AttribKind_UseUtf8); T_Ok(use_utf8_attrib->form.reader.kind == DW_Form_Flag); T_Ok(use_utf8_attrib->form.reader.flag == 1); } - + DW_WriterTag *char_type_tag = comp_unit_tag->first_child; { T_Ok(char_type_tag->kind == DW_TagKind_BaseType); @@ -678,25 +678,25 @@ T_BeginTest(dwarf_writer) T_Ok(char_type_tag->abbrev_id == 2); T_Ok(char_type_tag->info_off == 0x30); T_Ok(char_type_tag->first_attrib != char_type_tag->last_attrib); - + DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib; T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize); T_Ok(byte_size_attrib->form.reader.kind == DW_Form_Data1); T_Ok(byte_size_attrib->form.reader.data.size == 1); T_Ok(*(U8 *)byte_size_attrib->form.reader.data.str == 1); - + DW_WriterAttrib *encoding_attrib = byte_size_attrib->next; T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding); T_Ok(encoding_attrib->form.reader.kind == DW_Form_Data1); T_Ok(encoding_attrib->form.reader.data.size == 1); T_Ok(*(U8 *)encoding_attrib->form.reader.data.str == DW_ATE_SignedChar); - + DW_WriterAttrib *name_attrib = encoding_attrib->next; T_Ok(name_attrib->kind == DW_AttribKind_Name); T_Ok(name_attrib->form.reader.kind == DW_Form_String); T_Ok(str8_match(name_attrib->form.reader.string, str8_lit("char"), 0)); } - + DW_WriterTag *const_type_tag = char_type_tag->next; { T_Ok(const_type_tag->kind == DW_TagKind_ConstType); @@ -706,13 +706,13 @@ T_BeginTest(dwarf_writer) T_Ok(const_type_tag->abbrev_id == 3); T_Ok(const_type_tag->info_off == 0x38); T_Ok(const_type_tag->first_attrib && const_type_tag->first_attrib == const_type_tag->last_attrib); - + DW_WriterAttrib *type_attrib = const_type_tag->first_attrib; T_Ok(type_attrib->kind == DW_AttribKind_Type); T_Ok(type_attrib->form.writer.kind == DW_WriterFormKind_Ref); T_Ok(type_attrib->form.writer.ref == char_type_tag); } - + DW_WriterTag *dup_char_type_tag = const_type_tag->next; { T_Ok(dup_char_type_tag->kind == DW_TagKind_BaseType); @@ -722,25 +722,25 @@ T_BeginTest(dwarf_writer) T_Ok(dup_char_type_tag->abbrev_id == 2); T_Ok(dup_char_type_tag->info_off == 0x3a); T_Ok(dup_char_type_tag->first_attrib != dup_char_type_tag->last_attrib); - + DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib; T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize); T_Ok(byte_size_attrib->form.reader.kind == DW_Form_Data1); T_Ok(byte_size_attrib->form.reader.data.size == 1); T_Ok(*(U8 *)byte_size_attrib->form.reader.data.str == 1); - + DW_WriterAttrib *encoding_attrib = byte_size_attrib->next; T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding); T_Ok(encoding_attrib->form.reader.kind == DW_Form_Data1); T_Ok(encoding_attrib->form.reader.data.size == 1); T_Ok(*(U8 *)encoding_attrib->form.reader.data.str == DW_ATE_SignedChar); - + DW_WriterAttrib *name_attrib = encoding_attrib->next; T_Ok(name_attrib->kind == DW_AttribKind_Name); T_Ok(name_attrib->form.reader.kind == DW_Form_String); T_Ok(str8_match(name_attrib->form.reader.string, str8_lit("char"), 0)); } - + DW_WriterTag *simple_struct_tag = dup_char_type_tag->next; { T_Ok(simple_struct_tag->kind == DW_TagKind_StructureType); @@ -749,12 +749,12 @@ T_BeginTest(dwarf_writer) T_Ok(simple_struct_tag->attrib_count == 2); T_Ok(simple_struct_tag->abbrev_id == 4); T_Ok(simple_struct_tag->info_off == 0x42); - + DW_WriterAttrib *simple_struct_name = simple_struct_tag->first_attrib; T_Ok(simple_struct_name->kind == DW_AttribKind_Name); T_Ok(simple_struct_name->form.reader.kind == DW_Form_String); T_Ok(str8_match(simple_struct_name->form.reader.string, str8_lit("FooBar"), 0)); - + DW_WriterTag *m0_tag = simple_struct_tag->first_child; { T_Ok(m0_tag->kind == DW_TagKind_Member); @@ -762,24 +762,24 @@ T_BeginTest(dwarf_writer) T_Ok(m0_tag->attrib_count == 3); T_Ok(m0_tag->info_off == 0x4b); T_Ok(m0_tag->abbrev_id == 5); - + DW_WriterAttrib *name = m0_tag->first_attrib; T_Ok(name->kind == DW_AttribKind_Name); T_Ok(name->form.reader.kind == DW_Form_String); T_Ok(str8_match(name->form.reader.string, str8_lit("m0"), 0)); - + DW_WriterAttrib *type = name->next; T_Ok(type->kind == DW_AttribKind_Type); T_Ok(type->form.reader.kind == DW_Form_Ref1); T_Ok(type->form.reader.ref == 0x30); - + DW_WriterAttrib *data_loc = type->next; T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation); T_Ok(data_loc->form.reader.kind == DW_Form_Data1); T_Ok(data_loc->form.reader.data.size == 1); T_Ok(*(U8 *)data_loc->form.reader.data.str == 0); } - + DW_WriterTag *m1_tag = m0_tag->next; { T_Ok(m1_tag->kind == DW_TagKind_Member); @@ -787,30 +787,30 @@ T_BeginTest(dwarf_writer) T_Ok(m1_tag->attrib_count == 4); T_Ok(m1_tag->info_off == 0x51); T_Ok(m1_tag->abbrev_id == 6); - + DW_WriterAttrib *name = m1_tag->first_attrib; T_Ok(name->kind == DW_AttribKind_Name); T_Ok(name->form.reader.kind == DW_Form_String); T_Ok(str8_match(name->form.reader.string, str8_lit("m1"), 0)); - + DW_WriterAttrib *type = name->next; T_Ok(type->kind == DW_AttribKind_Type); T_Ok(type->form.reader.kind == DW_Form_Ref1); T_Ok(type->form.reader.ref == 0x30); - + DW_WriterAttrib *data_loc = type->next; T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation); T_Ok(data_loc->form.reader.kind == DW_Form_Data1); T_Ok(data_loc->form.reader.data.size == 1); T_Ok(*(U8 *)data_loc->form.reader.data.str == 10); - + DW_WriterAttrib *byte_size = data_loc->next; T_Ok(byte_size->kind == DW_AttribKind_ByteSize); T_Ok(byte_size->form.reader.kind == DW_Form_ImplicitConst); T_Ok(byte_size->form.reader.implicit_const == 123); } } - + DW_WriterTag *main_tag = simple_struct_tag->next; T_Ok(main_tag->next == 0); T_Ok(main_tag->kind == DW_TagKind_SubProgram); @@ -821,34 +821,34 @@ T_BeginTest(dwarf_writer) T_Ok(external->kind == DW_AttribKind_External); T_Ok(external->form.reader.kind == DW_Form_Flag); T_Ok(external->form.reader.flag); - + DW_WriterAttrib *prototyped = external->next; T_Ok(prototyped->kind == DW_AttribKind_Prototyped); T_Ok(prototyped->form.reader.kind == DW_Form_Flag); T_Ok(prototyped->form.reader.flag); - + DW_WriterAttrib *low_pc = prototyped->next; T_Ok(low_pc->kind == DW_AttribKind_LowPc); T_Ok(low_pc->form.reader.kind == DW_Form_Addr); T_Ok(low_pc->form.reader.addr.size == sizeof(U64)); T_Ok(*(U64 *)low_pc->form.reader.addr.str == 0x140001000); - + DW_WriterAttrib *high_pc = low_pc->next; T_Ok(high_pc->kind == DW_AttribKind_HighPc); T_Ok(high_pc->form.reader.kind == DW_Form_Addr); T_Ok(high_pc->form.reader.addr.size == sizeof(U64)); T_Ok(*(U64 *)high_pc->form.reader.addr.str == 0x140001004); - + DW_WriterAttrib *name = high_pc->next; T_Ok(name->kind == DW_AttribKind_Name); T_Ok(name->form.reader.kind == DW_Form_String); T_Ok(str8_match(name->form.reader.string, str8_lit("main"), 0)); - + DW_WriterAttrib *type = name->next; T_Ok(type->kind == DW_AttribKind_Type); T_Ok(type->form.reader.kind == DW_Form_Ref1); T_Ok(type->form.reader.ref == simple_struct_tag->info_off); - + DW_WriterAttrib *frame_base = type->next; T_Ok(frame_base->kind == DW_AttribKind_FrameBase); T_Ok(frame_base->form.reader.kind == DW_Form_ExprLoc); @@ -860,7 +860,7 @@ T_BeginTest(dwarf_writer) T_Ok(frame_base_expr.first->next == 0); T_Ok(frame_base_expr.first->prev == 0); } - + dw_writer_end(&writer); } T_EndTest; @@ -873,7 +873,7 @@ T_BeginTest(value_in_register) Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code); U64 value = 0xc0ffee; MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value)); - + // compile a simple program which reads the value from register 3 DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Reg3) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); @@ -882,7 +882,7 @@ T_BeginTest(value_in_register) // evaluate the program DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value); - + // validate eval result T_Ok(expr_eval == DW_ExprEvalResult_Ok); T_Ok(expr_value.type == DW_ExprValueType_U64); @@ -898,16 +898,16 @@ T_BeginTest(value_in_x_register) Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code); U64 value = 0xc0ffee; MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value)); - + // compile a simple program which reads the value from register 3 DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(RegX), DW_ExprEnc_ULEB128(DW_RegX64_FsBase) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + // evaluate the program DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value); - + // validate eval result T_Ok(expr_eval == DW_ExprEvalResult_Ok); T_Ok(expr_value.type == DW_ExprValueType_U64); @@ -922,11 +922,11 @@ T_BeginTest(address_of_value) DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Addr), DW_ExprEnc_U64(addr) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + // evaluate the program DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, 0, 0, &expr_value); - + // validate eval result T_Ok(expr_eval == DW_ExprEvalResult_Ok); T_Ok(expr_value.type == DW_ExprValueType_Addr); @@ -942,14 +942,14 @@ T_BeginTest(register_relative_variable) Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code); U64 value = 1; MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value)); - + DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(BReg11), DW_ExprEnc_SLEB128(44) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value); - + // validate eval result T_Ok(expr_eval == DW_ExprEvalResult_Ok); T_Ok(expr_value.type == DW_ExprValueType_Addr); @@ -962,11 +962,11 @@ T_BeginTest(frame_relative_variable) DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(FBReg), DW_ExprEnc_SLEB128(-50) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + U64 frame_base = 123; DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, frame_base, 0, 0, max_U64, expr, 0, 0, 0, 0, &expr_value); - + T_Ok(expr_eval == DW_ExprEvalResult_Ok); T_Ok(expr_value.type == DW_ExprValueType_Addr); T_Ok(expr_value.addr == frame_base -50); @@ -985,20 +985,20 @@ T_BeginTest(call_by_reference) U8 *memory = push_array(scratch.arena, U8, 128); U64 value = 0xc0ffee; MemoryCopy(memory + 32, &value, sizeof(value)); - + REGS_RegBlockX64 regs = {0}; REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, 58); // fsbase Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code); U64 memory_ptr = IntFromPtr(memory); MemoryCopy((U8 *)®s + reg_range.min, &memory_ptr, sizeof(memory_ptr)); - + DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(BRegX), DW_ExprEnc_ULEB128(58), DW_ExprEnc_SLEB128(32), DW_ExprEnc_Op(Deref) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + DW_ExprValue expr_value = { 0 }; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, t_machine_op_mem_read, 0, &expr_value); - + T_Ok(expr_value.type == DW_ExprValueType_Generic); T_Ok(expr_value.generic.size == sizeof(U64)); T_Ok(*(U64 *)expr_value.generic.str == value); @@ -1011,10 +1011,10 @@ T_BeginTest(plus_uconst) DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Addr), DW_ExprEnc_Addr(struct_addr), DW_ExprEnc_Op(PlusUConst), DW_ExprEnc_ULEB128(4) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, t_machine_op_mem_read, 0, &expr_value); - + T_Ok(expr_value.type == DW_ExprValueType_Addr); T_Ok(expr_value.addr == 0x123 + 4); } @@ -1037,11 +1037,11 @@ T_BeginTest(reg_split_spill) U64 value = 0xbbbb; MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value)); } - + DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Reg3), DW_ExprEnc_Op(Piece), DW_ExprEnc_ULEB128(4), DW_ExprEnc_Op(Reg10), DW_ExprEnc_Op(Piece), DW_ExprEnc_ULEB128(2) }; String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs)); DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data); - + DW_ExprValue expr_value; DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value); }