mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-09-22 17:20:05 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd433c89ff | ||
|
|
d2ec1d6a3a | ||
|
|
f736533933 | ||
|
|
8d82accc26 | ||
|
|
f61688fff5 | ||
|
|
c88f715ac2 | ||
|
|
cac911fbf5 | ||
|
|
1261aa55b0 | ||
|
|
5fe3f56d33 | ||
|
|
0c497abba6 |
@@ -99,6 +99,76 @@ raddbg.cpp
|
||||
If everything worked correctly, there will be a `build` folder in the root
|
||||
level of the codebase, and it will contain a freshly-built `raddbg.exe`.
|
||||
|
||||
## Short-To-Medium-Term Roadmap
|
||||
|
||||
### The Initial Alpha Battle-Testing Phase
|
||||
|
||||
The first priority for the project is to ensure that the most crucial debugger
|
||||
components are functioning extremely reliably for local, x64, Windows
|
||||
debugging. This would include parts like debug info conversion, debug info
|
||||
loading, process control, stepping, evaluation (correct usage of both location
|
||||
info and type info), and a robust frontend which ensures the lower level parts
|
||||
are usable.
|
||||
|
||||
We feel that the debugger has already come a long way in all of these respects,
|
||||
but given the massive set of possible combinations of languages, build
|
||||
settings, toolchains, used language features, and patterns of generated code,
|
||||
there are still cases where the debugger has not been tested, and so there are
|
||||
still issues. So, we feel that the top priority is eliminating these issues,
|
||||
such that the debugging experience is rock solid.
|
||||
|
||||
Additionally, the debug info conversion process is not fast (nor wide) enough
|
||||
to support extremely large projects. This is for two reasons: (a) the
|
||||
PDB-to-RADDBG converter is an unoptimized reference implementation, and (b) the
|
||||
debugger learns of new modules (and thus which PDBs to load) in a
|
||||
serially-dependent way (this is necessarily the case for correct debugging
|
||||
results). We expect that the conversion process' performance can be massively
|
||||
improved, and also that some heuristics can be used to begin converting PDBs
|
||||
to RADDBGs before the debugger knows those PDBs are needed, thus ensuring the
|
||||
associated RADDBG files are ready instantaneously when the associated modules
|
||||
are finally loaded by the debugger. Improving this situation is a major part of
|
||||
this phase, as it will make the debugger much more usable for large projects.
|
||||
|
||||
### Local x64 Linux Debugging Phase
|
||||
|
||||
The next priority for the project is to take the rock solid x64 Windows
|
||||
debugging experience, and port all of the relevant pieces to support local x64
|
||||
Linux debugging also.
|
||||
|
||||
The debugger has been written to abstract over the parts that need to differ on
|
||||
either Linux or Windows, and this is mainly going to be a task in building out
|
||||
different backends for those abstraction layers.
|
||||
|
||||
The major parts of this phase are:
|
||||
|
||||
- Porting the `src/demon` layer to implement the Demon local process control
|
||||
abstraction API.
|
||||
- Porting the `src/unwind` layer to support x64 ELF unwinding (currently, there
|
||||
is only an x64 PE unwinding implementation).
|
||||
- Creating a DWARF-to-RADDBG converter (in the same way that we've built a PDB-
|
||||
to-RADDBG converter). A partial implementation of this is in
|
||||
`src/raddbg_convert/dwarf`.
|
||||
- Porting the `src/render` layer to implement all of the rendering features the
|
||||
frontend needs on a Linux-compatible API (the backend used on Windows is D3D11).
|
||||
- Porting the `src/font_provider` layer to a Linux-compatible font
|
||||
rasterization backend, like FreeType (the backend used on Windows is
|
||||
DirectWrite).
|
||||
- Porting the `src/os` layers to Linux. This includes core operating system
|
||||
abstraction (virtual memory allocation, threading and synchronization
|
||||
primitives, and so on), and graphical operating system abstraction (windows,
|
||||
input events, and so on).
|
||||
|
||||
Once the above list is complete, and once every part is rock solid, the Windows
|
||||
debugging experience we'll have worked diligently to create will also be
|
||||
available natively on Linux machines.
|
||||
|
||||
### And Beyond!
|
||||
|
||||
There are several directions we might take after these two major phases,
|
||||
like remote debugging, porting to different architectures, further improving
|
||||
the debugger's features (like improving the visualization engine), and so on.
|
||||
But for now, we're mostly focused on those first two phases.
|
||||
|
||||
## Top-Level Directory Descriptions
|
||||
|
||||
- `data`: Small binary files which are used when building, either to embed
|
||||
|
||||
@@ -81,6 +81,15 @@ commands =
|
||||
.save_dirty_files = true,
|
||||
.cursor_at_end = false,
|
||||
},
|
||||
.build_raddbg_dump =
|
||||
{
|
||||
.win = "build raddbg_dump",
|
||||
.linux = "",
|
||||
.out = "*compilation*",
|
||||
.footer_panel = true,
|
||||
.save_dirty_files = true,
|
||||
.cursor_at_end = false,
|
||||
},
|
||||
.build_mule_main =
|
||||
{
|
||||
.win = "build mule_main",
|
||||
|
||||
@@ -957,7 +957,9 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
}
|
||||
|
||||
// rjf: check if trap
|
||||
B32 is_trap = (!first_bp && exception->ExceptionCode == DEMON_W32_EXCEPTION_BREAKPOINT);
|
||||
B32 is_trap = (!first_bp &&
|
||||
(exception->ExceptionCode == DEMON_W32_EXCEPTION_BREAKPOINT ||
|
||||
exception->ExceptionCode == DEMON_W32_EXCEPTION_STACK_BUFFER_OVERRUN));
|
||||
|
||||
// rjf: check if this trap is currently registered
|
||||
B32 hit_user_trap = 0;
|
||||
@@ -979,7 +981,8 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
// TODO(rjf): x86/x64 specific check
|
||||
// TODO(rjf): do we need to check to make sure the instruction
|
||||
// pointer has not changed?
|
||||
hit_explicit_trap = (instruction_byte == 0xCC);
|
||||
hit_explicit_trap = (instruction_byte == 0xCC ||
|
||||
instruction_byte == 0xCD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,6 +1041,11 @@ demon_os_run(Arena *arena, DEMON_OS_RunCtrls *ctrls){
|
||||
e->kind = report_event_kind;
|
||||
}break;
|
||||
|
||||
case DEMON_W32_EXCEPTION_STACK_BUFFER_OVERRUN:
|
||||
{
|
||||
e->kind = DEMON_EventKind_Trap;
|
||||
}break;
|
||||
|
||||
case DEMON_W32_EXCEPTION_SINGLE_STEP:
|
||||
{
|
||||
e->kind = DEMON_EventKind_SingleStep;
|
||||
|
||||
@@ -2869,6 +2869,23 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread)
|
||||
{
|
||||
trap_addr = point->jump_dest_vaddr;
|
||||
flags &= ~CTRL_TrapFlag_SingleStepAfterHit;
|
||||
|
||||
// rjf: read instruction one layer deep after a jump and determine if
|
||||
// it is just jumping to an unconditional jump (e.g. a function
|
||||
// dispatch table) - if so, then just follow one more layer
|
||||
String8 dst_machine_code = {0};
|
||||
dst_machine_code.str = push_array_no_zero(scratch.arena, U8, max_instruction_size_from_arch(arch));
|
||||
dst_machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, r1u64(trap_addr, trap_addr+max_instruction_size_from_arch(arch)), dst_machine_code.str);
|
||||
if(dst_machine_code.size != 0)
|
||||
{
|
||||
DF_Inst inst = df_single_inst_from_machine_code(scratch.arena, arch, 0, dst_machine_code);
|
||||
if((inst.flags & DF_InstFlag_UnconditionalJump ||
|
||||
inst.flags & DF_InstFlag_Call) &&
|
||||
inst.rel_voff != 0)
|
||||
{
|
||||
trap_addr = (U64)(trap_addr + (S64)((S32)inst.rel_voff));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -4990,7 +4990,8 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
||||
}break;
|
||||
case CTRL_EventCause_InterruptedByTrap:
|
||||
{
|
||||
|
||||
icon = DF_IconKind_WarningBig;
|
||||
explanation = push_str8f(scratch.arena, "%S interrupted by trap - 0x%x", thread_display_string, stop_event.exception_code);
|
||||
}break;
|
||||
case CTRL_EventCause_InterruptedByHalt:
|
||||
{
|
||||
@@ -11534,7 +11535,10 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
||||
}
|
||||
|
||||
//- rjf: apply keybindings
|
||||
df_clear_bindings();
|
||||
if(src == DF_CfgSrc_User)
|
||||
{
|
||||
df_clear_bindings();
|
||||
}
|
||||
DF_CfgVal *keybindings = df_cfg_val_from_string(table, str8_lit("keybindings"));
|
||||
for(DF_CfgNode *keybinding_set = keybindings->first;
|
||||
keybinding_set != &df_g_nil_cfg_node;
|
||||
@@ -11649,7 +11653,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
||||
}
|
||||
|
||||
//- rjf: if config opened 0 windows, we need to do some sensible default
|
||||
if(windows->first == &df_g_nil_cfg_node)
|
||||
if(src == DF_CfgSrc_User && windows->first == &df_g_nil_cfg_node)
|
||||
{
|
||||
OS_Handle preferred_monitor = os_primary_monitor();
|
||||
Vec2F32 monitor_dim = os_dim_from_monitor(preferred_monitor);
|
||||
@@ -11660,7 +11664,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
||||
}
|
||||
|
||||
//- rjf: if config bound 0 keys, we need to do some sensible default
|
||||
if(df_gfx_state->key_map_total_count == 0)
|
||||
if(src == DF_CfgSrc_User && df_gfx_state->key_map_total_count == 0)
|
||||
{
|
||||
for(U64 idx = 0; idx < ArrayCount(df_g_default_binding_table); idx += 1)
|
||||
{
|
||||
|
||||
@@ -5153,7 +5153,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
|
||||
if(txti_buffer_is_ready) UI_Parent(container_box)
|
||||
{
|
||||
//- rjf: build fractional space
|
||||
container_box->view_off.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.x = container_box->view_off_target.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.y = container_box->view_off_target.y = code_line_height*mod_f32(view->scroll_pos.y.off, 1.f) + code_line_height*(view->scroll_pos.y.off < 0) - code_line_height*(view->scroll_pos.y.off == -1.f && view->scroll_pos.y.idx == 1);
|
||||
|
||||
//- rjf: build code slice
|
||||
@@ -6033,7 +6033,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
|
||||
if(has_disasm) UI_Parent(container_box)
|
||||
{
|
||||
//- rjf: build fractional space
|
||||
container_box->view_off.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.x = container_box->view_off_target.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.y = container_box->view_off_target.y = code_line_height*mod_f32(view->scroll_pos.y.off, 1.f) + code_line_height*(view->scroll_pos.y.off < 0) - code_line_height*(view->scroll_pos.y.off == -1.f && view->scroll_pos.y.idx == 1);
|
||||
|
||||
//- rjf: build code slice
|
||||
@@ -6967,7 +6967,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output)
|
||||
if(txti_buffer_is_ready) UI_Parent(container_box)
|
||||
{
|
||||
//- rjf: build fractional space
|
||||
container_box->view_off.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.x = container_box->view_off_target.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.y = container_box->view_off_target.y = code_line_height*mod_f32(view->scroll_pos.y.off, 1.f) + code_line_height*(view->scroll_pos.y.off < 0) - code_line_height*(view->scroll_pos.y.off == -1.f && view->scroll_pos.y.idx == 1);
|
||||
|
||||
//- rjf: build code slice
|
||||
@@ -7723,7 +7723,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
||||
UI_BoxFlag_AllowOverflowX|
|
||||
UI_BoxFlag_AllowOverflowY,
|
||||
"scrollable_box");
|
||||
scrollable_box->view_off.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
container_box->view_off.x = container_box->view_off_target.x = view->scroll_pos.x.idx + view->scroll_pos.x.off;
|
||||
scrollable_box->view_off.y = scrollable_box->view_off_target.y = floor_f32(row_height_px*mod_f32(view->scroll_pos.y.off, 1.f) + row_height_px*(view->scroll_pos.y.off < 0));
|
||||
}
|
||||
|
||||
|
||||
@@ -470,7 +470,7 @@ eval_leaf_type_from_name(RADDBG_Parsed *rdbg, String8 name)
|
||||
U32 *matches = raddbg_matches_from_map_node(rdbg, node, &match_count);
|
||||
if(match_count != 0)
|
||||
{
|
||||
U32 type_node_idx = matches[match_count-1];
|
||||
U32 type_node_idx = matches[0];
|
||||
if(type_node_idx < rdbg->type_node_count)
|
||||
{
|
||||
RADDBG_TypeNode *type_node = &rdbg->type_nodes[type_node_idx];
|
||||
|
||||
+49
-1
@@ -1317,7 +1317,53 @@ extended_type_coverage_eval_tests(void){
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): C Type Coverage
|
||||
//~ rjf: Templated Function Eval Tests
|
||||
|
||||
typedef struct TemplateArg TemplateArg;
|
||||
struct TemplateArg
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
float a;
|
||||
float b;
|
||||
float c;
|
||||
char *name;
|
||||
};
|
||||
|
||||
template<typename T> static T
|
||||
templated_factorial(T t)
|
||||
{
|
||||
T result = t;
|
||||
if(t > 1)
|
||||
{
|
||||
result *= templated_factorial<T>(t-1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T> static T
|
||||
compute_template_arg_info(T t)
|
||||
{
|
||||
int sum = t.x + t.y + t.z;
|
||||
int size = sizeof(t);
|
||||
float sum_f = t.a + t.b + t.c;
|
||||
OutputDebugStringA(t.name);
|
||||
return t;
|
||||
}
|
||||
|
||||
static void
|
||||
templated_function_eval_tests(void)
|
||||
{
|
||||
int int_factorial = templated_factorial<int>(10);
|
||||
float float_factorial = templated_factorial<float>(10);
|
||||
TemplateArg arg = {1, 2, 3, 4.f, 5.f, 6.f, "my template arg"};
|
||||
compute_template_arg_info(arg);
|
||||
int x = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): C Type Coverage
|
||||
|
||||
extern "C"{
|
||||
#include "mule_c.h"
|
||||
@@ -2343,6 +2389,8 @@ mule_main(int argc, char** argv){
|
||||
|
||||
extended_type_coverage_eval_tests();
|
||||
|
||||
templated_function_eval_tests();
|
||||
|
||||
c_type_coverage_eval_tests();
|
||||
|
||||
c_type_with_bitfield_usage();
|
||||
|
||||
+1
-1
@@ -422,7 +422,7 @@
|
||||
|
||||
#define RADDBG_VERSION_MAJOR 0
|
||||
#define RADDBG_VERSION_MINOR 9
|
||||
#define RADDBG_VERSION_PATCH 1
|
||||
#define RADDBG_VERSION_PATCH 3
|
||||
#define RADDBG_VERSION_STRING_LITERAL Stringify(RADDBG_VERSION_MAJOR) "." Stringify(RADDBG_VERSION_MINOR) "." Stringify(RADDBG_VERSION_PATCH)
|
||||
#if defined(NDEBUG)
|
||||
# define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ ""
|
||||
|
||||
@@ -2935,7 +2935,7 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\
|
||||
if (tpi != 0) ProfScope("parse tpi hash"){
|
||||
String8 hash_data = msf_data_from_stream(msf, tpi->hash_sn);
|
||||
String8 aux_data = msf_data_from_stream(msf, tpi->hash_sn_aux);
|
||||
tpi_hash = pdb_tpi_hash_from_data(arena, tpi, hash_data, aux_data);
|
||||
tpi_hash = pdb_tpi_hash_from_data(arena, strtbl, tpi, hash_data, aux_data);
|
||||
|
||||
PARSE_CHECK_ERROR(tpi_hash, "TPI hash table");
|
||||
}
|
||||
@@ -2954,7 +2954,7 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\
|
||||
if (ipi != 0) ProfScope("parse ipi hash"){
|
||||
String8 hash_data = msf_data_from_stream(msf, ipi->hash_sn);
|
||||
String8 aux_data = msf_data_from_stream(msf, ipi->hash_sn_aux);
|
||||
ipi_hash = pdb_tpi_hash_from_data(arena, ipi, hash_data, aux_data);
|
||||
ipi_hash = pdb_tpi_hash_from_data(arena, strtbl, ipi, hash_data, aux_data);
|
||||
|
||||
PARSE_CHECK_ERROR(tpi_hash, "IPI hash table");
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ pdb_tpi_from_data(Arena *arena, String8 data){
|
||||
}
|
||||
|
||||
static PDB_TpiHashParsed*
|
||||
pdb_tpi_hash_from_data(Arena *arena, PDB_TpiParsed *tpi, String8 data, String8 aux_data){
|
||||
pdb_tpi_hash_from_data(Arena *arena, PDB_Strtbl *strtbl, PDB_TpiParsed *tpi, String8 data, String8 aux_data){
|
||||
ProfBegin("pdb_tpi_hash_from_data");
|
||||
|
||||
PDB_TpiHashParsed *result = 0;
|
||||
@@ -335,7 +335,11 @@ pdb_tpi_hash_from_data(Arena *arena, PDB_TpiParsed *tpi, String8 data, String8 a
|
||||
block = push_array(arena, PDB_TpiHashBlock, 1);
|
||||
SLLStackPush(buckets[bucket_idx], block);
|
||||
}
|
||||
block->itypes[block->local_count] = itype;
|
||||
if(block->local_count != 0)
|
||||
{
|
||||
MemoryCopy(block->itypes+1, block->itypes, sizeof(CV_TypeId)*block->local_count);
|
||||
}
|
||||
block->itypes[0] = itype;
|
||||
block->local_count += 1;
|
||||
}
|
||||
|
||||
@@ -344,15 +348,85 @@ pdb_tpi_hash_from_data(Arena *arena, PDB_TpiParsed *tpi, String8 data, String8 a
|
||||
itype += 1;
|
||||
}
|
||||
|
||||
//- rjf: compute bucket mask
|
||||
U32 bucket_mask = 0;
|
||||
if(IsPow2OrZero(bucket_count))
|
||||
{
|
||||
bucket_mask = bucket_count-1;
|
||||
}
|
||||
|
||||
//- rjf: apply hash adjustments, to pull correct type IDs to the front of
|
||||
// the chains
|
||||
if(tpi->hash_adj_size != 0)
|
||||
{
|
||||
// NOTE(rjf): this table is laid out in the following format:
|
||||
//
|
||||
// pair_count: U32 -> # of name_index/type_index pairs
|
||||
// slot_count: U32 -> # of slots in this hash table
|
||||
// present_bit_array_count: U32 -> count for next array
|
||||
// present_bit_array: U32[present_bit_array_count] -> 1 bit per slot, "is present"
|
||||
// deleted_bit_array_count: U32 -> count for next array
|
||||
// deleted_bit_array: U32[deleted_bit_array_count] -> 1 bit per slot, "is deleted"
|
||||
// (U32, U32)[pair_count] -> array of name_index/type_index pairs
|
||||
//
|
||||
U8 *adjs = data.str + tpi->hash_adj_off;
|
||||
U8 *adjs_opl = adjs + tpi->hash_adj_size;
|
||||
U8 *adjs_cursor = adjs;
|
||||
U32 pair_count = *(U32 *)adjs_cursor;
|
||||
adjs_cursor += sizeof(U32);
|
||||
U32 slot_count = *(U32 *)adjs_cursor;
|
||||
adjs_cursor += sizeof(U32);
|
||||
U32 present_bit_array_count = *(U32 *)adjs_cursor; // skip present_bit_array
|
||||
adjs_cursor += sizeof(U32);
|
||||
adjs_cursor += present_bit_array_count*sizeof(U32);
|
||||
U32 deleted_bit_array_count = *(U32 *)adjs_cursor; // skip deleted_bit_array
|
||||
adjs_cursor += sizeof(U32);
|
||||
adjs_cursor += deleted_bit_array_count*sizeof(U32);
|
||||
U32 adjs_stride = sizeof(U32)*2;
|
||||
U32 pair_idx = 0;
|
||||
for(;adjs_cursor < adjs_opl && pair_idx < pair_count;
|
||||
adjs_cursor += adjs_stride, pair_idx += 1)
|
||||
{
|
||||
U32 name_off = ((U32 *)adjs_cursor)[0];
|
||||
CV_TypeId type_id = ((CV_TypeId *)adjs_cursor)[1];
|
||||
String8 string = pdb_strtbl_string_from_off(strtbl, name_off);
|
||||
U32 hash = pdb_string_hash1(string);
|
||||
U32 bucket_idx = ((bucket_mask != 0) ? hash&bucket_mask : hash%bucket_count);
|
||||
PDB_TpiHashBlock *prev_block = 0;
|
||||
for(PDB_TpiHashBlock *block = buckets[bucket_idx];
|
||||
block != 0;
|
||||
prev_block = block, block = block->next)
|
||||
{
|
||||
for(U32 local_idx = 0;
|
||||
local_idx < block->local_count && local_idx < ArrayCount(block->itypes);
|
||||
local_idx += 1)
|
||||
{
|
||||
if(block->itypes[local_idx] == type_id)
|
||||
{
|
||||
if(prev_block != 0)
|
||||
{
|
||||
prev_block->next = block->next;
|
||||
block->next = buckets[bucket_idx];
|
||||
buckets[bucket_idx] = block;
|
||||
}
|
||||
if(local_idx != 0)
|
||||
{
|
||||
Swap(CV_TypeId, block->itypes[0], block->itypes[local_idx]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill result
|
||||
result = push_array(arena, PDB_TpiHashParsed, 1);
|
||||
result->data = data;
|
||||
result->aux_data = aux_data;
|
||||
result->buckets = buckets;
|
||||
result->bucket_count = bucket_count;
|
||||
if (IsPow2OrZero(bucket_count)){
|
||||
result->bucket_mask = bucket_count - 1;
|
||||
}
|
||||
result->bucket_mask = bucket_mask;
|
||||
}
|
||||
|
||||
ProfEnd();
|
||||
|
||||
@@ -407,6 +407,7 @@ static PDB_Strtbl* pdb_strtbl_from_data(Arena *arena, String8 strtbl_da
|
||||
static PDB_DbiParsed* pdb_dbi_from_data(Arena *arena, String8 dbi_data);
|
||||
static PDB_TpiParsed* pdb_tpi_from_data(Arena *arena, String8 tpi_data);
|
||||
static PDB_TpiHashParsed* pdb_tpi_hash_from_data(Arena *arena,
|
||||
PDB_Strtbl *strtbl,
|
||||
PDB_TpiParsed *tpi,
|
||||
String8 tpi_hash_data,
|
||||
String8 tpi_hash_aux_data);
|
||||
|
||||
@@ -1,14 +1,49 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include <stdlib.h>
|
||||
// build with:
|
||||
// cl /Zi /nologo look_at_raddbg.c
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include "raddbg_format/raddbg_format.h"
|
||||
#include "raddbg_format/raddbg_format_parse.h"
|
||||
#include "raddbg_format/raddbg_format.c"
|
||||
#include "raddbg_format/raddbg_format_parse.c"
|
||||
|
||||
typedef struct Foo Foo;
|
||||
struct Foo
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
int main(int argument_count, char **arguments)
|
||||
{
|
||||
int *arr = malloc(sizeof(int)*1000);
|
||||
for(int i = 0; i < 1001; i += 1)
|
||||
Foo foo = {123, 456, 789};
|
||||
HANDLE file = CreateFileA(arguments[1], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
DWORD size_hi32 = 0;
|
||||
DWORD size_lo32 = GetFileSize(file, &size_hi32);
|
||||
HANDLE map = CreateFileMappingA(file, 0, PAGE_READONLY, 0, 0, 0);
|
||||
uint64_t data_size = (size_lo32 | ((uint64_t)size_hi32 << 32));
|
||||
uint8_t *data = (uint8_t *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, data_size);
|
||||
RADDBG_Parsed rdbg = {0};
|
||||
RADDBG_ParseStatus parse_status = raddbg_parse(data, data_size, &rdbg);
|
||||
uint64_t foo_count = 0;
|
||||
for(uint64_t idx = 0; idx < rdbg.type_node_count; idx += 1)
|
||||
{
|
||||
arr[i] = i;
|
||||
RADDBG_TypeNode *type_node = &rdbg.type_nodes[idx];
|
||||
if(RADDBG_TypeKind_FirstUserDefined <= type_node->kind && type_node->kind <= RADDBG_TypeKind_LastUserDefined)
|
||||
{
|
||||
uint64_t name_size = 0;
|
||||
uint8_t *name = raddbg_string_from_idx(&rdbg, type_node->user_defined.name_string_idx, &name_size);
|
||||
if(name_size == 3 && name[0] == 'f' && name[1] == 'o' && name[2] == 'o')
|
||||
{
|
||||
foo_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("%s -> %I64u foos\n", arguments[1], foo_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+4
-4
@@ -118,7 +118,7 @@ ui_nav_eat_action_node(UI_NavActionList *list, UI_NavActionNode *node)
|
||||
internal B32
|
||||
ui_nav_char_is_code_symbol(U8 c)
|
||||
{
|
||||
return (char_is_alpha(c) || char_is_digit(c, 10) || c == '_');
|
||||
return (char_is_alpha(c) || char_is_digit(c, 10) || c == '_');
|
||||
}
|
||||
|
||||
internal S64
|
||||
@@ -134,7 +134,7 @@ ui_nav_scanned_column_from_column(String8 string, S64 start_column, Side side)
|
||||
U8 byte = (col <= string.size) ? string.str[col-1] : 0;
|
||||
B32 is_non_space = !char_is_space(byte);
|
||||
B32 is_name = ui_nav_char_is_code_symbol(byte);
|
||||
|
||||
|
||||
if (((side == Side_Min) && (col == 1)) ||
|
||||
((side == Side_Max) && (col == string.size+1)) ||
|
||||
(found_non_space && !is_non_space) ||
|
||||
@@ -143,9 +143,9 @@ ui_nav_scanned_column_from_column(String8 string, S64 start_column, Side side)
|
||||
new_column = col + (!side && col != 1);
|
||||
break;
|
||||
} else if (!found_text && is_name) {
|
||||
found_text = 1;
|
||||
found_text = 1;
|
||||
} else if (!found_non_space && is_non_space ) {
|
||||
found_non_space = 1;
|
||||
found_non_space = 1;
|
||||
}
|
||||
}
|
||||
return new_column;
|
||||
|
||||
Reference in New Issue
Block a user