mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-09 11:01:37 -07:00
symbol conversion passes in new converter
This commit is contained in:
@@ -408,6 +408,10 @@ rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r
|
||||
n->v = r;
|
||||
RDIM_SLLQueuePush(list->first, list->last, n);
|
||||
list->count += 1;
|
||||
if(list->count == 1 || r.min < list->min)
|
||||
{
|
||||
list->min = r.min;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: u64 -> ptr map
|
||||
@@ -532,7 +536,7 @@ rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list)
|
||||
{
|
||||
n = rdim_push_array(arena, RDIM_UnitChunkNode, 1);
|
||||
n->cap = 512;
|
||||
n->v = rdim_push_array_no_zero(arena, RDIM_Unit, n->cap);
|
||||
n->v = rdim_push_array(arena, RDIM_Unit, n->cap);
|
||||
RDIM_SLLQueuePush(list->first, list->last, n);
|
||||
list->chunk_count += 1;
|
||||
}
|
||||
@@ -556,7 +560,7 @@ rdim_unit_array_from_chunk_list(RDIM_Arena *arena, RDIM_UnitChunkList *list)
|
||||
{
|
||||
RDIM_UnitArray array = {0};
|
||||
array.count = list->total_count;
|
||||
array.v = rdim_push_array_no_zero(arena, RDIM_Unit, array.count);
|
||||
array.v = rdim_push_array(arena, RDIM_Unit, array.count);
|
||||
U64 idx = 0;
|
||||
for(RDIM_UnitChunkNode *n = list->first; n != 0; n = n->next)
|
||||
{
|
||||
@@ -577,7 +581,7 @@ rdim_type_chunk_list_push(RDIM_Arena *arena, RDIM_TypeChunkList *list, RDI_U64 c
|
||||
{
|
||||
n = rdim_push_array(arena, RDIM_TypeChunkNode, 1);
|
||||
n->cap = cap;
|
||||
n->v = rdim_push_array_no_zero(arena, RDIM_Type, n->cap);
|
||||
n->v = rdim_push_array(arena, RDIM_Type, n->cap);
|
||||
RDIM_SLLQueuePush(list->first, list->last, n);
|
||||
list->chunk_count += 1;
|
||||
}
|
||||
@@ -595,7 +599,7 @@ rdim_udt_chunk_list_push(RDIM_Arena *arena, RDIM_UDTChunkList *list, RDI_U64 cap
|
||||
{
|
||||
n = rdim_push_array(arena, RDIM_UDTChunkNode, 1);
|
||||
n->cap = cap;
|
||||
n->v = rdim_push_array_no_zero(arena, RDIM_UDT, n->cap);
|
||||
n->v = rdim_push_array(arena, RDIM_UDT, n->cap);
|
||||
RDIM_SLLQueuePush(list->first, list->last, n);
|
||||
list->chunk_count += 1;
|
||||
}
|
||||
@@ -717,7 +721,7 @@ rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U
|
||||
{
|
||||
n = rdim_push_array(arena, RDIM_SymbolChunkNode, 1);
|
||||
n->cap = cap;
|
||||
n->v = rdim_push_array_no_zero(arena, RDIM_Symbol, n->cap);
|
||||
n->v = rdim_push_array(arena, RDIM_Symbol, n->cap);
|
||||
RDIM_SLLQueuePush(list->first, list->last, n);
|
||||
list->chunk_count += 1;
|
||||
}
|
||||
@@ -738,7 +742,7 @@ rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64
|
||||
{
|
||||
n = rdim_push_array(arena, RDIM_ScopeChunkNode, 1);
|
||||
n->cap = cap;
|
||||
n->v = rdim_push_array_no_zero(arena, RDIM_Scope, n->cap);
|
||||
n->v = rdim_push_array(arena, RDIM_Scope, n->cap);
|
||||
RDIM_SLLQueuePush(list->first, list->last, n);
|
||||
list->chunk_count += 1;
|
||||
}
|
||||
@@ -748,6 +752,79 @@ rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64
|
||||
return result;
|
||||
}
|
||||
|
||||
RDI_PROC RDIM_Local *
|
||||
rdim_scope_push_local(RDIM_Arena *arena, RDIM_Scope *scope)
|
||||
{
|
||||
RDIM_Local *local = rdim_push_array(arena, RDIM_Local, 1);
|
||||
RDIM_SLLQueuePush(scope->first_local, scope->last_local, local);
|
||||
scope->local_count += 1;
|
||||
return local;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Location Info Building
|
||||
|
||||
//- rjf: individual locations
|
||||
|
||||
RDI_PROC RDIM_Location *
|
||||
rdim_push_location_addr_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode)
|
||||
{
|
||||
RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1);
|
||||
result->kind = RDI_LocationKind_AddrBytecodeStream;
|
||||
result->bytecode = *bytecode;
|
||||
return result;
|
||||
}
|
||||
|
||||
RDI_PROC RDIM_Location *
|
||||
rdim_push_location_val_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode)
|
||||
{
|
||||
RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1);
|
||||
result->kind = RDI_LocationKind_ValBytecodeStream;
|
||||
result->bytecode = *bytecode;
|
||||
return result;
|
||||
}
|
||||
|
||||
RDI_PROC RDIM_Location *
|
||||
rdim_push_location_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset)
|
||||
{
|
||||
RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1);
|
||||
result->kind = RDI_LocationKind_AddrRegisterPlusU16;
|
||||
result->register_code = reg_code;
|
||||
result->offset = offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
RDI_PROC RDIM_Location *
|
||||
rdim_push_location_addr_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset)
|
||||
{
|
||||
RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1);
|
||||
result->kind = RDI_LocationKind_AddrAddrRegisterPlusU16;
|
||||
result->register_code = reg_code;
|
||||
result->offset = offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
RDI_PROC RDIM_Location *
|
||||
rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg_code)
|
||||
{
|
||||
RDIM_Location *result = rdim_push_array(arena, RDIM_Location, 1);
|
||||
result->kind = RDI_LocationKind_ValRegister;
|
||||
result->register_code = reg_code;
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: location sets
|
||||
|
||||
RDI_PROC void
|
||||
rdim_location_set_push_case(RDIM_Arena *arena, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location)
|
||||
{
|
||||
RDIM_LocationCase *location_case = rdim_push_array(arena, RDIM_LocationCase, 1);
|
||||
SLLQueuePush(locset->first_location_case, locset->last_location_case, location_case);
|
||||
locset->location_case_count += 1;
|
||||
location_case->voff_range = voff_range;
|
||||
location_case->location = location;
|
||||
}
|
||||
|
||||
#if 0
|
||||
////////////////////////////////
|
||||
//~ rjf: Loose Debug Info Construction (Anything -> Loose) Functions
|
||||
|
||||
@@ -304,6 +304,7 @@ struct RDIM_Rng1U64List
|
||||
RDIM_Rng1U64Node *first;
|
||||
RDIM_Rng1U64Node *last;
|
||||
RDI_U64 count;
|
||||
RDI_U64 min;
|
||||
};
|
||||
|
||||
//- rjf: u64 -> pointer map
|
||||
@@ -627,8 +628,7 @@ typedef struct RDIM_LocationCase RDIM_LocationCase;
|
||||
struct RDIM_LocationCase
|
||||
{
|
||||
RDIM_LocationCase *next;
|
||||
RDI_U64 voff_first;
|
||||
RDI_U64 voff_opl;
|
||||
RDIM_Rng1U64 voff_range;
|
||||
RDIM_Location *location;
|
||||
};
|
||||
|
||||
@@ -695,7 +695,7 @@ struct RDIM_Local
|
||||
RDI_LocalKind kind;
|
||||
RDIM_String8 name;
|
||||
RDIM_Type *type;
|
||||
RDIM_LocationSet *locset;
|
||||
RDIM_LocationSet locset;
|
||||
};
|
||||
|
||||
typedef struct RDIM_Scope RDIM_Scope;
|
||||
@@ -706,7 +706,6 @@ struct RDIM_Scope
|
||||
RDIM_Scope *first_child;
|
||||
RDIM_Scope *last_child;
|
||||
RDIM_Scope *next_sibling;
|
||||
RDI_U64 voff_base;
|
||||
RDIM_Rng1U64List voff_ranges;
|
||||
RDIM_Local *first_local;
|
||||
RDIM_Local *last_local;
|
||||
@@ -1216,6 +1215,20 @@ RDI_PROC RDIM_Symbol *rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_Symbol
|
||||
//~ rjf: Scope Info Building
|
||||
|
||||
RDI_PROC RDIM_Scope *rdim_scope_chunk_list_push(RDIM_Arena *arena, RDIM_ScopeChunkList *list, RDI_U64 cap);
|
||||
RDI_PROC RDIM_Local *rdim_scope_push_local(RDIM_Arena *arena, RDIM_Scope *scope);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Location Info Building
|
||||
|
||||
//- rjf: individual locations
|
||||
RDI_PROC RDIM_Location *rdim_push_location_addr_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode);
|
||||
RDI_PROC RDIM_Location *rdim_push_location_val_bytecode_stream(RDIM_Arena *arena, RDIM_EvalBytecode *bytecode);
|
||||
RDI_PROC RDIM_Location *rdim_push_location_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset);
|
||||
RDI_PROC RDIM_Location *rdim_push_location_addr_addr_reg_plus_u16(RDIM_Arena *arena, RDI_U8 reg_code, RDI_U16 offset);
|
||||
RDI_PROC RDIM_Location *rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg_code);
|
||||
|
||||
//- rjf: location sets
|
||||
RDI_PROC void rdim_location_set_push_case(RDIM_Arena *arena, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location);
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
internal U64
|
||||
p2r_end_of_cplusplus_container_name(String8 str)
|
||||
{
|
||||
// NOTE: This finds the index one past the last "::" contained in str.
|
||||
// if no "::" is contained in str, then the returned index is 0.
|
||||
// The intent is that [0,clamp_bot(0,result - 2)) gives the
|
||||
// "container name" and [result,str.size) gives the leaf name.
|
||||
U64 result = 0;
|
||||
if(str.size >= 2)
|
||||
{
|
||||
for(U64 i = str.size; i >= 2; i -= 1)
|
||||
{
|
||||
if(str.str[i - 2] == ':' && str.str[i - 1] == ':')
|
||||
{
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line -> Conversion Parameters
|
||||
|
||||
@@ -374,6 +398,139 @@ rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type)
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Location Info Building Helpers
|
||||
|
||||
internal RDIM_Location *
|
||||
p2r_location_from_addr_reg_off(Arena *arena, RDI_Arch arch, RDI_RegisterCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 extra_indirection)
|
||||
{
|
||||
RDIM_Location *result = 0;
|
||||
if(0 <= offset && offset <= (S64)max_U16)
|
||||
{
|
||||
if(extra_indirection)
|
||||
{
|
||||
result = rdim_push_location_addr_addr_reg_plus_u16(arena, reg_code, (U16)offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = rdim_push_location_addr_reg_plus_u16(arena, reg_code, (U16)offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDIM_EvalBytecode bytecode = {0};
|
||||
U32 regread_param = RDI_EncodeRegReadParam(reg_code, reg_byte_size, reg_byte_pos);
|
||||
rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_RegRead, regread_param);
|
||||
rdim_bytecode_push_sconst(arena, &bytecode, offset);
|
||||
rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_Add, 0);
|
||||
if(extra_indirection)
|
||||
{
|
||||
U64 addr_size = rdi_addr_size_from_arch(arch);
|
||||
rdim_bytecode_push_op(arena, &bytecode, RDI_EvalOp_MemRead, addr_size);
|
||||
}
|
||||
result = rdim_push_location_addr_bytecode_stream(arena, &bytecode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CV_EncodedFramePtrReg
|
||||
p2r_cv_encoded_fp_reg_from_frameproc(CV_SymFrameproc *frameproc, B32 param_base)
|
||||
{
|
||||
CV_EncodedFramePtrReg result = 0;
|
||||
CV_FrameprocFlags flags = frameproc->flags;
|
||||
if(param_base)
|
||||
{
|
||||
result = CV_FrameprocFlags_ExtractParamBasePointer(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CV_FrameprocFlags_ExtractLocalBasePointer(flags);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal RDI_RegisterCode
|
||||
p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg)
|
||||
{
|
||||
RDI_RegisterCode result = 0;
|
||||
switch(arch)
|
||||
{
|
||||
case RDI_Arch_X86:
|
||||
{
|
||||
switch(encoded_reg)
|
||||
{
|
||||
case CV_EncodedFramePtrReg_StackPtr:
|
||||
{
|
||||
// TODO(allen): support CV_AllReg_VFRAME
|
||||
// TODO(allen): error
|
||||
}break;
|
||||
case CV_EncodedFramePtrReg_FramePtr:
|
||||
{
|
||||
result = RDI_RegisterCode_X86_ebp;
|
||||
}break;
|
||||
case CV_EncodedFramePtrReg_BasePtr:
|
||||
{
|
||||
result = RDI_RegisterCode_X86_ebx;
|
||||
}break;
|
||||
}
|
||||
}break;
|
||||
case RDI_Arch_X64:
|
||||
{
|
||||
switch(encoded_reg)
|
||||
{
|
||||
case CV_EncodedFramePtrReg_StackPtr:
|
||||
{
|
||||
result = RDI_RegisterCode_X64_rsp;
|
||||
}break;
|
||||
case CV_EncodedFramePtrReg_FramePtr:
|
||||
{
|
||||
result = RDI_RegisterCode_X64_rbp;
|
||||
}break;
|
||||
case CV_EncodedFramePtrReg_BasePtr:
|
||||
{
|
||||
result = RDI_RegisterCode_X64_r13;
|
||||
}break;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
p2r_location_over_lvar_addr_range(Arena *arena, RDIM_LocationSet *locset, RDIM_Location *location, CV_LvarAddrRange *range, COFF_SectionHeader *section, CV_LvarAddrGap *gaps, U64 gap_count)
|
||||
{
|
||||
//- rjf: extract range info
|
||||
U64 voff_first = 0;
|
||||
U64 voff_opl = 0;
|
||||
if(section != 0)
|
||||
{
|
||||
voff_first = section->voff + range->off;
|
||||
voff_opl = voff_first + range->len;
|
||||
}
|
||||
|
||||
//- rjf: emit ranges
|
||||
CV_LvarAddrGap *gap_ptr = gaps;
|
||||
U64 voff_cursor = voff_first;
|
||||
for(U64 i = 0; i < gap_count; i += 1, gap_ptr += 1)
|
||||
{
|
||||
U64 voff_gap_first = voff_first + gap_ptr->off;
|
||||
U64 voff_gap_opl = voff_gap_first + gap_ptr->len;
|
||||
if(voff_cursor < voff_gap_first)
|
||||
{
|
||||
RDIM_Rng1U64 voff_range = {voff_cursor, voff_gap_first};
|
||||
rdim_location_set_push_case(arena, locset, voff_range, location);
|
||||
}
|
||||
voff_cursor = voff_gap_opl;
|
||||
}
|
||||
|
||||
//- rjf: emit remaining range
|
||||
if(voff_cursor < voff_opl)
|
||||
{
|
||||
RDIM_Rng1U64 voff_range = {voff_cursor, voff_opl};
|
||||
rdim_location_set_push_case(arena, locset, voff_range, location);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
////////////////////////////////
|
||||
@@ -3670,9 +3827,9 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
{
|
||||
rec_range_count += sym->sym_ranges.count;
|
||||
}
|
||||
for(U64 i = 0; i < comp_unit_count; i += 1)
|
||||
for(U64 comp_unit_idx = 0; comp_unit_idx < comp_unit_count; comp_unit_idx += 1)
|
||||
{
|
||||
CV_SymParsed *unit_sym = sym_for_unit[i];
|
||||
CV_SymParsed *unit_sym = sym_for_unit[comp_unit_idx];
|
||||
rec_range_count += unit_sym->sym_ranges.count;
|
||||
}
|
||||
symbol_count_prediction = rec_range_count/8;
|
||||
@@ -3683,11 +3840,11 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: types pass 0: produce type forward resolution map
|
||||
//- rjf: types pass 1: produce type forward resolution map
|
||||
//
|
||||
U64 type_fwd_map_count = 0;
|
||||
CV_TypeId *type_fwd_map = 0;
|
||||
ProfScope("types pass 0: produce type forward resolution map")
|
||||
ProfScope("types pass 1: produce type forward resolution map")
|
||||
{
|
||||
CV_TypeId itype_first = tpi_leaf->itype_first;
|
||||
CV_TypeId itype_opl = tpi_leaf->itype_opl;
|
||||
@@ -3805,7 +3962,7 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: types pass 1: construct all root/stub types from TPI
|
||||
//- rjf: types pass 2: construct all root/stub types from TPI
|
||||
//
|
||||
// this does NOT gather the following information, which is done by
|
||||
// subsequent passes, as they all require full resolution of all itypes first
|
||||
@@ -3828,13 +3985,13 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
};
|
||||
P2R_TypeIdRevisitTask *first_itype_revisit_task = 0;
|
||||
P2R_TypeIdRevisitTask *last_itype_revisit_task = 0;
|
||||
CV_TypeId itype_first = tpi_leaf->itype_first;
|
||||
CV_TypeId itype_opl = tpi_leaf->itype_opl;
|
||||
RDIM_TypeArray itype_types = {0}; // root type for per-TPI-itype
|
||||
RDIM_TypeChunkList extra_types = {0}; // extra supplementary types we build, which do not have any itypes
|
||||
ProfScope("types pass 1: construct all root/stub types from TPI")
|
||||
ProfScope("types pass 2: construct all root/stub types from TPI")
|
||||
{
|
||||
RDI_U64 extra_types_chunk_cap = 1024;
|
||||
CV_TypeId itype_first = tpi_leaf->itype_first;
|
||||
CV_TypeId itype_opl = tpi_leaf->itype_opl;
|
||||
itype_types.count = (U64)(itype_opl-itype_first);
|
||||
itype_types.v = push_array(arena, RDIM_Type, itype_types.count);
|
||||
#define p2r_type_ptr_from_itype(itype) ((itype_first <= (itype) && (itype) < itype_opl) ? (&itype_types.v[(type_fwd_map[(itype)-itype_first] ? type_fwd_map[(itype)-itype_first] : (itype))-itype_first]) : 0)
|
||||
@@ -4211,7 +4368,7 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: types pass 2: attach cross-itype-relationship data to all types, build UDTs
|
||||
//- rjf: types pass 3: attach cross-itype-relationship data to all types, build UDTs
|
||||
//
|
||||
// given the root/stub types for all itypes, this pass takes care of the
|
||||
// following extra pieces of per-type information:
|
||||
@@ -4224,7 +4381,7 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
// - direct type forward resolution
|
||||
//
|
||||
RDIM_UDTChunkList udts = {0};
|
||||
ProfScope("types pass 2: attach cross-itype-relationship data to all types, build UDTs")
|
||||
ProfScope("types pass 3: attach cross-itype-relationship data to all types, build UDTs")
|
||||
{
|
||||
RDI_U64 udts_chunk_cap = 1024;
|
||||
CV_TypeId itype_first = tpi_leaf->itype_first;
|
||||
@@ -4927,11 +5084,711 @@ p2r_convert(Arena *arena, P2R_Params *params)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//- rjf: produce all symbols for all units
|
||||
//- rjf: produce symbols from all sym streams
|
||||
//
|
||||
ProfScope("produce all symbols for all units")
|
||||
ProfScope("produce symbols from all sym streams")
|
||||
{
|
||||
#define p2r_type_ptr_from_itype(itype) ((itype_first <= (itype) && (itype) < itype_opl) ? (&itype_types.v[(type_fwd_map[(itype)-itype_first] ? type_fwd_map[(itype)-itype_first] : (itype))-itype_first]) : 0)
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: produce array of all symbol streams
|
||||
//
|
||||
U64 syms_count = 1 + comp_unit_count;
|
||||
CV_SymParsed **syms = push_array(scratch.arena, CV_SymParsed *, syms_count);
|
||||
{
|
||||
syms[0] = sym;
|
||||
for(U64 comp_unit_idx = 0; comp_unit_idx < comp_unit_count; comp_unit_idx += 1)
|
||||
{
|
||||
syms[comp_unit_idx+1] = sym_for_unit[comp_unit_idx];
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: produce symbols
|
||||
//
|
||||
for(U64 sym_idx = 0; sym_idx < syms_count; sym_idx += 1)
|
||||
{
|
||||
CV_SymParsed *sym = syms[sym_idx];
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: set up outputs for this sym stream
|
||||
//
|
||||
RDIM_SymbolChunkList sym_procedures = {0};
|
||||
RDIM_SymbolChunkList sym_global_variables = {0};
|
||||
RDIM_SymbolChunkList sym_thread_variables = {0};
|
||||
RDIM_ScopeChunkList sym_scopes = {0};
|
||||
U64 sym_procedures_chunk_cap = 1024;
|
||||
U64 sym_global_variables_chunk_cap = 1024;
|
||||
U64 sym_thread_variables_chunk_cap = 1024;
|
||||
U64 sym_scopes_chunk_cap = 1024;
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: symbols pass 1: produce procedure frame info map (procedure -> frame info)
|
||||
//
|
||||
U64 procedure_frameprocs_count = 0;
|
||||
U64 procedure_frameprocs_cap = sym->sym_ranges.count;
|
||||
CV_SymFrameproc **procedure_frameprocs = push_array_no_zero(scratch.arena, CV_SymFrameproc *, procedure_frameprocs_cap);
|
||||
ProfScope("symbols pass 1: produce procedure frame info map (procedure -> frame info)")
|
||||
{
|
||||
U64 procedure_num = 0;
|
||||
CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges;
|
||||
CV_RecRange *rec_ranges_opl = rec_ranges_first + sym->sym_ranges.count;
|
||||
for(CV_RecRange *rec_range = rec_ranges_first;
|
||||
rec_range < rec_ranges_opl;
|
||||
rec_range += 1)
|
||||
{
|
||||
//- rjf: rec range -> symbol info range
|
||||
U64 sym_off_first = rec_range->off + 2;
|
||||
U64 sym_off_opl = rec_range->off + rec_range->hdr.size;
|
||||
|
||||
//- rjf: skip invalid ranges
|
||||
if(sym_off_opl > sym->data.size || sym_off_first > sym->data.size || sym_off_first > sym_off_opl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: unpack symbol info
|
||||
CV_SymKind kind = rec_range->hdr.kind;
|
||||
U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind);
|
||||
void *sym_header_struct_base = sym->data.str + sym_off_first;
|
||||
|
||||
//- rjf: skip bad sizes
|
||||
if(sym_off_first + sym_header_struct_size > sym_off_opl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: consume symbol based on kind
|
||||
switch(kind)
|
||||
{
|
||||
default:{}break;
|
||||
|
||||
//- rjf: FRAMEPROC
|
||||
case CV_SymKind_FRAMEPROC:
|
||||
{
|
||||
if(procedure_num == 0) { break; }
|
||||
if(procedure_num > procedure_frameprocs_cap) { break; }
|
||||
CV_SymFrameproc *frameproc = (CV_SymFrameproc*)sym_header_struct_base;
|
||||
procedure_frameprocs[procedure_num-1] = frameproc;
|
||||
procedure_frameprocs_count = Max(procedure_frameprocs_count, procedure_num);
|
||||
}break;
|
||||
|
||||
//- rjf: LPROC32/GPROC32
|
||||
case CV_SymKind_LPROC32:
|
||||
case CV_SymKind_GPROC32:
|
||||
{
|
||||
procedure_num += 1;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
U64 scratch_overkill = sizeof(procedure_frameprocs[0])*(procedure_frameprocs_cap-procedure_frameprocs_count);
|
||||
arena_put_back(scratch.arena, scratch_overkill);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: symbols pass 2: construct all symbols, given procedure frame info map
|
||||
//
|
||||
ProfScope("symbols pass 2: construct all symbols, given procedure frame info map")
|
||||
{
|
||||
RDIM_LocationSet *defrange_target = 0;
|
||||
B32 defrange_target_is_param = 0;
|
||||
U64 procedure_num = 0;
|
||||
CV_RecRange *rec_ranges_first = sym->sym_ranges.ranges;
|
||||
CV_RecRange *rec_ranges_opl = rec_ranges_first + sym->sym_ranges.count;
|
||||
typedef struct P2R_ScopeNode P2R_ScopeNode;
|
||||
struct P2R_ScopeNode
|
||||
{
|
||||
P2R_ScopeNode *next;
|
||||
RDIM_Scope *scope;
|
||||
};
|
||||
P2R_ScopeNode *top_scope_node = 0;
|
||||
P2R_ScopeNode *free_scope_node = 0;
|
||||
for(CV_RecRange *rec_range = rec_ranges_first;
|
||||
rec_range < rec_ranges_opl;
|
||||
rec_range += 1)
|
||||
{
|
||||
//- rjf: rec range -> symbol info range
|
||||
U64 sym_off_first = rec_range->off + 2;
|
||||
U64 sym_off_opl = rec_range->off + rec_range->hdr.size;
|
||||
|
||||
//- rjf: skip invalid ranges
|
||||
if(sym_off_opl > sym->data.size || sym_off_first > sym->data.size || sym_off_first > sym_off_opl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: unpack symbol info
|
||||
CV_SymKind kind = rec_range->hdr.kind;
|
||||
U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind);
|
||||
void *sym_header_struct_base = sym->data.str + sym_off_first;
|
||||
void *sym_data_opl = sym->data.str + sym_off_opl;
|
||||
|
||||
//- rjf: skip bad sizes
|
||||
if(sym_off_first + sym_header_struct_size > sym_off_opl)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//- rjf: consume symbol based on kind
|
||||
switch(kind)
|
||||
{
|
||||
default:{}break;
|
||||
|
||||
//- rjf: END
|
||||
case CV_SymKind_END:
|
||||
{
|
||||
P2R_ScopeNode *n = top_scope_node;
|
||||
SLLStackPop(top_scope_node);
|
||||
SLLStackPush(free_scope_node, n);
|
||||
defrange_target = 0;
|
||||
defrange_target_is_param = 0;
|
||||
}break;
|
||||
|
||||
//- rjf: BLOCK32
|
||||
case CV_SymKind_BLOCK32:
|
||||
{
|
||||
// rjf: unpack sym
|
||||
CV_SymBlock32 *block32 = (CV_SymBlock32 *)sym_header_struct_base;
|
||||
|
||||
// rjf: build scope, insert into current parent scope
|
||||
RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap);
|
||||
{
|
||||
if(top_scope_node == 0)
|
||||
{
|
||||
// TODO(rjf): log
|
||||
}
|
||||
if(top_scope_node != 0)
|
||||
{
|
||||
RDIM_Scope *top_scope = top_scope_node->scope;
|
||||
SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling);
|
||||
scope->parent_scope = top_scope;
|
||||
scope->symbol = top_scope->symbol;
|
||||
}
|
||||
COFF_SectionHeader *section = (0 < block32->sec && block32->sec <= coff_sections->count) ? &coff_sections->sections[block32->sec-1] : 0;
|
||||
if(section != 0)
|
||||
{
|
||||
U64 voff_first = section->voff + block32->off;
|
||||
U64 voff_last = voff_first + block32->len;
|
||||
RDIM_Rng1U64 voff_range = {voff_first, voff_last};
|
||||
rdim_rng1u64_list_push(arena, &scope->voff_ranges, voff_range);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: push this scope to scope stack
|
||||
{
|
||||
P2R_ScopeNode *node = free_scope_node;
|
||||
if(node != 0) { SLLStackPop(free_scope_node); }
|
||||
else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); }
|
||||
node->scope = scope;
|
||||
SLLStackPush(top_scope_node, node);
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: LDATA32/GDATA32
|
||||
case CV_SymKind_LDATA32:
|
||||
case CV_SymKind_GDATA32:
|
||||
{
|
||||
// rjf: unpack sym
|
||||
CV_SymData32 *data32 = (CV_SymData32 *)sym_header_struct_base;
|
||||
String8 name = str8_cstring_capped(data32+1, sym_data_opl);
|
||||
COFF_SectionHeader *section = (0 < data32->sec && data32->sec <= coff_sections->count) ? &coff_sections->sections[data32->sec-1] : 0;
|
||||
U64 voff = (section ? section->voff : 0) + data32->off;
|
||||
|
||||
// rjf: determine if this is an exact duplicate global
|
||||
//
|
||||
// PDB likes to have duplicates of these spread across different
|
||||
// symbol streams so we deduplicate across the entire translation
|
||||
// context.
|
||||
//
|
||||
B32 is_duplicate = 0;
|
||||
{
|
||||
// TODO(rjf): @important global symbol dedup
|
||||
}
|
||||
|
||||
// rjf: is not duplicate -> push new global
|
||||
if(!is_duplicate)
|
||||
{
|
||||
// rjf: unpack global variable's type
|
||||
RDIM_Type *type = p2r_type_ptr_from_itype(data32->itype);
|
||||
|
||||
// rjf: unpack global's container type
|
||||
RDIM_Type *container_type = 0;
|
||||
U64 container_name_opl = p2r_end_of_cplusplus_container_name(name);
|
||||
if(container_name_opl > 2)
|
||||
{
|
||||
String8 container_name = str8(name.str, container_name_opl - 2);
|
||||
// TODO(rjf): @important type name maps
|
||||
// container_type = p2r_type_from_name(ctx, container_name);
|
||||
}
|
||||
|
||||
// rjf: unpack global's container symbol
|
||||
RDIM_Symbol *container_symbol = 0;
|
||||
if(container_type == 0 && top_scope_node != 0)
|
||||
{
|
||||
container_symbol = top_scope_node->scope->symbol;
|
||||
}
|
||||
|
||||
// rjf: build symbol
|
||||
RDIM_Symbol *symbol = rdim_symbol_chunk_list_push(arena, &sym_global_variables, sym_global_variables_chunk_cap);
|
||||
symbol->kind = RDIM_SymbolKind_GlobalVariable;
|
||||
symbol->is_extern = (kind == CV_SymKind_GDATA32);
|
||||
symbol->name = name;
|
||||
symbol->type = type;
|
||||
symbol->offset = voff;
|
||||
symbol->container_symbol = container_symbol;
|
||||
symbol->container_type = container_type;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: LPROC32/GPROC32
|
||||
case CV_SymKind_LPROC32:
|
||||
case CV_SymKind_GPROC32:
|
||||
{
|
||||
// rjf: unpack sym
|
||||
CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base;
|
||||
String8 name = str8_cstring_capped(proc32+1, sym_data_opl);
|
||||
RDIM_Type *type = p2r_type_ptr_from_itype(proc32->itype);
|
||||
|
||||
// rjf: unpack proc's container type
|
||||
RDIM_Type *container_type = 0;
|
||||
U64 container_name_opl = p2r_end_of_cplusplus_container_name(name);
|
||||
if(container_name_opl > 2)
|
||||
{
|
||||
String8 container_name = str8(name.str, container_name_opl - 2);
|
||||
// TODO(rjf): @important type name maps
|
||||
// container_type = p2r_type_from_name(ctx, container_name);
|
||||
}
|
||||
|
||||
// rjf: unpack proc's container symbol
|
||||
RDIM_Symbol *container_symbol = 0;
|
||||
if(container_type == 0 && top_scope_node != 0)
|
||||
{
|
||||
container_symbol = top_scope_node->scope->symbol;
|
||||
}
|
||||
|
||||
// rjf: build procedure's root scope
|
||||
//
|
||||
// NOTE: even if there could be a containing scope at this point (which should be
|
||||
// illegal in C/C++ but not necessarily in another language) we would not use
|
||||
// it here because these scopes refer to the ranges of code that make up a
|
||||
// procedure *not* the namespaces, so a procedure's root scope always has
|
||||
// no parent.
|
||||
RDIM_Scope *procedure_root_scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap);
|
||||
{
|
||||
COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= coff_sections->count) ? &coff_sections->sections[proc32->sec-1] : 0;
|
||||
if(section != 0)
|
||||
{
|
||||
U64 voff_first = section->voff + proc32->off;
|
||||
U64 voff_last = voff_first + proc32->len;
|
||||
RDIM_Rng1U64 voff_range = {voff_first, voff_last};
|
||||
rdim_rng1u64_list_push(arena, &procedure_root_scope->voff_ranges, voff_range);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: root scope voff minimum range -> link name
|
||||
String8 link_name = {0};
|
||||
if(procedure_root_scope->voff_ranges.min != 0)
|
||||
{
|
||||
// TODO(rjf): @important link names
|
||||
}
|
||||
|
||||
// rjf: build procedure symbol
|
||||
RDIM_Symbol *procedure_symbol = rdim_symbol_chunk_list_push(arena, &sym_procedures, sym_procedures_chunk_cap);
|
||||
procedure_symbol->kind = RDIM_SymbolKind_Procedure;
|
||||
procedure_symbol->is_extern = (kind == CV_SymKind_GPROC32);
|
||||
procedure_symbol->name = name;
|
||||
procedure_symbol->link_name = link_name;
|
||||
procedure_symbol->type = type;
|
||||
procedure_symbol->container_symbol = container_symbol;
|
||||
procedure_symbol->container_type = container_type;
|
||||
|
||||
// rjf: fill root scope's symbol
|
||||
procedure_root_scope->symbol = procedure_symbol;
|
||||
|
||||
// rjf: push scope to scope stack
|
||||
{
|
||||
P2R_ScopeNode *node = free_scope_node;
|
||||
if(node != 0) { SLLStackPop(free_scope_node); }
|
||||
else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); }
|
||||
node->scope = procedure_root_scope;
|
||||
SLLStackPush(top_scope_node, node);
|
||||
}
|
||||
|
||||
// rjf: increment procedure counter
|
||||
procedure_num += 1;
|
||||
}break;
|
||||
|
||||
//- rjf: REGREL32
|
||||
case CV_SymKind_REGREL32:
|
||||
{
|
||||
// TODO(rjf): apparently some of the information here may end up being
|
||||
// redundant with "better" information from CV_SymKind_LOCAL record.
|
||||
// we don't currently handle this, but if those cases arise then it
|
||||
// will obviously be better to prefer the better information from both
|
||||
// records.
|
||||
|
||||
// rjf: no containing scope? -> malformed data; locals cannot be produced
|
||||
// outside of a containing scope
|
||||
if(top_scope_node == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymRegrel32 *regrel32 = (CV_SymRegrel32 *)sym_header_struct_base;
|
||||
String8 name = str8_cstring_capped(regrel32+1, sym_data_opl);
|
||||
RDIM_Type *type = p2r_type_ptr_from_itype(regrel32->itype);
|
||||
CV_Reg cv_reg = regrel32->reg;
|
||||
U32 var_off = regrel32->reg_off;
|
||||
|
||||
// rjf: determine if this is a parameter
|
||||
RDI_LocalKind local_kind = RDI_LocalKind_Variable;
|
||||
{
|
||||
B32 is_stack_reg = 0;
|
||||
switch(arch)
|
||||
{
|
||||
default:{}break;
|
||||
case RDI_Arch_X86:{is_stack_reg = (cv_reg == CV_Regx86_ESP);}break;
|
||||
case RDI_Arch_X64:{is_stack_reg = (cv_reg == CV_Regx64_RSP);}break;
|
||||
}
|
||||
if(is_stack_reg)
|
||||
{
|
||||
U32 frame_size = 0xFFFFFFFF;
|
||||
if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num < procedure_frameprocs_count)
|
||||
{
|
||||
CV_SymFrameproc *frameproc = procedure_frameprocs[procedure_num-1];
|
||||
frame_size = frameproc->frame_size;
|
||||
}
|
||||
if(var_off > frame_size)
|
||||
{
|
||||
local_kind = RDI_LocalKind_Parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: build local
|
||||
RDIM_Scope *scope = top_scope_node->scope;
|
||||
RDIM_Local *local = rdim_scope_push_local(arena, scope);
|
||||
local->kind = local_kind;
|
||||
local->name = name;
|
||||
local->type = type;
|
||||
|
||||
// rjf: add location info to local
|
||||
{
|
||||
// rjf: determine if we need an extra indirection to the value
|
||||
B32 extra_indirection_to_value = 0;
|
||||
switch(arch)
|
||||
{
|
||||
case RDI_Arch_X86:
|
||||
{
|
||||
extra_indirection_to_value = (local_kind == RDI_LocalKind_Parameter && (type->byte_size > 4 || !IsPow2OrZero(type->byte_size)));
|
||||
}break;
|
||||
case RDI_Arch_X64:
|
||||
{
|
||||
extra_indirection_to_value = (local_kind == RDI_LocalKind_Parameter && (type->byte_size > 8 || !IsPow2OrZero(type->byte_size)));
|
||||
}break;
|
||||
}
|
||||
|
||||
// rjf: get raddbg register code
|
||||
RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg);
|
||||
// TODO(rjf): real byte_size & byte_pos from cv_reg goes here
|
||||
U32 byte_size = 8;
|
||||
U32 byte_pos = 0;
|
||||
|
||||
// rjf: set location case
|
||||
RDIM_Location *loc = p2r_location_from_addr_reg_off(arena, arch, register_code, byte_size, byte_pos, (S64)(S32)var_off, extra_indirection_to_value);
|
||||
RDIM_Rng1U64 voff_range = {0, max_U64};
|
||||
rdim_location_set_push_case(arena, &local->locset, voff_range, loc);
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: LTHREAD32/GTHREAD32
|
||||
case CV_SymKind_LTHREAD32:
|
||||
case CV_SymKind_GTHREAD32:
|
||||
{
|
||||
// rjf: unpack sym
|
||||
CV_SymThread32 *thread32 = (CV_SymThread32 *)sym_header_struct_base;
|
||||
String8 name = str8_cstring_capped(thread32+1, sym_data_opl);
|
||||
U32 tls_off = thread32->tls_off;
|
||||
RDIM_Type *type = p2r_type_ptr_from_itype(thread32->itype);
|
||||
|
||||
// rjf: unpack thread variable's container type
|
||||
RDIM_Type *container_type = 0;
|
||||
U64 container_name_opl = p2r_end_of_cplusplus_container_name(name);
|
||||
if(container_name_opl > 2)
|
||||
{
|
||||
String8 container_name = str8(name.str, container_name_opl - 2);
|
||||
// TODO(rjf): @important type name maps
|
||||
// container_type = p2r_type_from_name(ctx, container_name);
|
||||
}
|
||||
|
||||
// rjf: unpack thread variable's container symbol
|
||||
RDIM_Symbol *container_symbol = 0;
|
||||
if(container_type == 0 && top_scope_node != 0)
|
||||
{
|
||||
container_symbol = top_scope_node->scope->symbol;
|
||||
}
|
||||
|
||||
// rjf: build symbol
|
||||
RDIM_Symbol *tvar = rdim_symbol_chunk_list_push(arena, &sym_thread_variables, sym_thread_variables_chunk_cap);
|
||||
tvar->kind = RDIM_SymbolKind_ThreadVariable;
|
||||
tvar->name = name;
|
||||
tvar->type = type;
|
||||
tvar->is_extern = (kind == CV_SymKind_GTHREAD32);
|
||||
tvar->offset = tls_off;
|
||||
tvar->container_type = container_type;
|
||||
tvar->container_symbol = container_symbol;
|
||||
}break;
|
||||
|
||||
//- rjf: LOCAL
|
||||
case CV_SymKind_LOCAL:
|
||||
{
|
||||
// rjf: no containing scope? -> malformed data; locals cannot be produced
|
||||
// outside of a containing scope
|
||||
if(top_scope_node == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymLocal *slocal = (CV_SymLocal *)sym_header_struct_base;
|
||||
String8 name = str8_cstring_capped(slocal+1, sym_data_opl);
|
||||
RDIM_Type *type = p2r_type_ptr_from_itype(slocal->itype);
|
||||
|
||||
// rjf: determine if this symbol encodes the beginning of a global modification
|
||||
B32 is_global_modification = 0;
|
||||
if((slocal->flags & CV_LocalFlag_Global) ||
|
||||
(slocal->flags & CV_LocalFlag_Static))
|
||||
{
|
||||
is_global_modification = 1;
|
||||
}
|
||||
|
||||
// rjf: is global modification -> emit global modification symbol
|
||||
if(is_global_modification)
|
||||
{
|
||||
// TODO(rjf): add global modification symbols
|
||||
defrange_target = 0;
|
||||
defrange_target_is_param = 0;
|
||||
}
|
||||
|
||||
// rjf: is not a global modification -> emit a local variable
|
||||
if(!is_global_modification)
|
||||
{
|
||||
// rjf: determine local kind
|
||||
RDI_LocalKind local_kind = RDI_LocalKind_Variable;
|
||||
if(slocal->flags & CV_LocalFlag_Param)
|
||||
{
|
||||
local_kind = RDI_LocalKind_Parameter;
|
||||
}
|
||||
|
||||
// rjf: build local
|
||||
RDIM_Scope *scope = top_scope_node->scope;
|
||||
RDIM_Local *local = rdim_scope_push_local(arena, scope);
|
||||
local->kind = local_kind;
|
||||
local->name = name;
|
||||
local->type = type;
|
||||
|
||||
// rjf: save defrange target, for subsequent defrange symbols
|
||||
defrange_target = &local->locset;
|
||||
defrange_target_is_param = (local_kind == RDI_LocalKind_Parameter);
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: DEFRANGE_REGISTESR
|
||||
case CV_SymKind_DEFRANGE_REGISTER:
|
||||
{
|
||||
// rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing
|
||||
// a local - break immediately
|
||||
if(defrange_target == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymDefrangeRegister *defrange_register = (CV_SymDefrangeRegister*)sym_header_struct_base;
|
||||
CV_Reg cv_reg = defrange_register->reg;
|
||||
CV_LvarAddrRange *range = &defrange_register->range;
|
||||
COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections->count) ? &coff_sections->sections[range->sec-1] : 0;
|
||||
CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register+1);
|
||||
U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps);
|
||||
RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg);
|
||||
|
||||
// rjf: build location
|
||||
RDIM_Location *location = rdim_push_location_val_reg(arena, register_code);
|
||||
|
||||
// rjf: emit locations over ranges
|
||||
p2r_location_over_lvar_addr_range(arena, defrange_target, location, range, range_section, gaps, gap_count);
|
||||
}break;
|
||||
|
||||
//- rjf: DEFRANGE_FRAMEPOINTER_REL
|
||||
case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL:
|
||||
{
|
||||
// rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing
|
||||
// a local - break immediately
|
||||
if(defrange_target == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: find current procedure's frameproc
|
||||
CV_SymFrameproc *frameproc = 0;
|
||||
if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num < procedure_frameprocs_count)
|
||||
{
|
||||
frameproc = procedure_frameprocs[procedure_num-1];
|
||||
}
|
||||
|
||||
// rjf: no current valid frameproc? -> somehow we got a to a framepointer-relative defrange
|
||||
// without having an actually active procedure - break
|
||||
if(frameproc == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymDefrangeFramepointerRel *defrange_fprel = (CV_SymDefrangeFramepointerRel*)sym_header_struct_base;
|
||||
CV_LvarAddrRange *range = &defrange_fprel->range;
|
||||
COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections->count) ? &coff_sections->sections[range->sec-1] : 0;
|
||||
CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_fprel + 1);
|
||||
U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps);
|
||||
|
||||
// rjf: select frame pointer register
|
||||
CV_EncodedFramePtrReg encoded_fp_reg = p2r_cv_encoded_fp_reg_from_frameproc(frameproc, defrange_target_is_param);
|
||||
RDI_RegisterCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(arch, encoded_fp_reg);
|
||||
|
||||
// rjf: build location
|
||||
B32 extra_indirection = 0;
|
||||
U32 byte_size = arch_addr_size;
|
||||
U32 byte_pos = 0;
|
||||
S64 var_off = (S64)defrange_fprel->off;
|
||||
RDIM_Location *location = p2r_location_from_addr_reg_off(arena, arch, fp_register_code, byte_size, byte_pos, var_off, extra_indirection);
|
||||
|
||||
// rjf: emit locations over ranges
|
||||
p2r_location_over_lvar_addr_range(arena, defrange_target, location, range, range_section, gaps, gap_count);
|
||||
}break;
|
||||
|
||||
//- rjf: DEFRANGE_SUBFIELD_REGISTER
|
||||
case CV_SymKind_DEFRANGE_SUBFIELD_REGISTER:
|
||||
{
|
||||
// rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing
|
||||
// a local - break immediately
|
||||
if(defrange_target == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymDefrangeSubfieldRegister *defrange_subfield_register = (CV_SymDefrangeSubfieldRegister*)sym_header_struct_base;
|
||||
CV_Reg cv_reg = defrange_subfield_register->reg;
|
||||
CV_LvarAddrRange *range = &defrange_subfield_register->range;
|
||||
COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections->count) ? &coff_sections->sections[range->sec-1] : 0;
|
||||
CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_subfield_register + 1);
|
||||
U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps);
|
||||
RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg);
|
||||
|
||||
// rjf: skip "subfield" location info - currently not supported
|
||||
if(defrange_subfield_register->field_offset != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: build location
|
||||
RDIM_Location *location = rdim_push_location_val_reg(arena, register_code);
|
||||
|
||||
// rjf: emit locations over ranges
|
||||
p2r_location_over_lvar_addr_range(arena, defrange_target, location, range, range_section, gaps, gap_count);
|
||||
}break;
|
||||
|
||||
//- rjf: DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
|
||||
case CV_SymKind_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
|
||||
{
|
||||
// rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing
|
||||
// a local - break immediately
|
||||
if(defrange_target == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: find current procedure's frameproc
|
||||
CV_SymFrameproc *frameproc = 0;
|
||||
if(procedure_num != 0 && procedure_frameprocs[procedure_num-1] != 0 && procedure_num < procedure_frameprocs_count)
|
||||
{
|
||||
frameproc = procedure_frameprocs[procedure_num-1];
|
||||
}
|
||||
|
||||
// rjf: no current valid frameproc? -> somehow we got a to a framepointer-relative defrange
|
||||
// without having an actually active procedure - break
|
||||
if(frameproc == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymDefrangeFramepointerRelFullScope *defrange_fprel_full_scope = (CV_SymDefrangeFramepointerRelFullScope*)sym_header_struct_base;
|
||||
CV_EncodedFramePtrReg encoded_fp_reg = p2r_cv_encoded_fp_reg_from_frameproc(frameproc, defrange_target_is_param);
|
||||
RDI_RegisterCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(arch, encoded_fp_reg);
|
||||
|
||||
// rjf: build location
|
||||
B32 extra_indirection = 0;
|
||||
U32 byte_size = arch_addr_size;
|
||||
U32 byte_pos = 0;
|
||||
S64 var_off = (S64)defrange_fprel_full_scope->off;
|
||||
RDIM_Location *location = p2r_location_from_addr_reg_off(arena, arch, fp_register_code, byte_size, byte_pos, var_off, extra_indirection);
|
||||
|
||||
// rjf: emit location over ranges
|
||||
RDIM_Rng1U64 voff_range = {0, max_U64};
|
||||
rdim_location_set_push_case(arena, defrange_target, voff_range, location);
|
||||
}break;
|
||||
|
||||
//- rjf: DEFRANGE_REGISTER_REL
|
||||
case CV_SymKind_DEFRANGE_REGISTER_REL:
|
||||
{
|
||||
// rjf: no defrange target? -> somehow we got to a defrange symbol without first seeing
|
||||
// a local - break immediately
|
||||
if(defrange_target == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymDefrangeRegisterRel *defrange_register_rel = (CV_SymDefrangeRegisterRel*)sym_header_struct_base;
|
||||
CV_Reg cv_reg = defrange_register_rel->reg;
|
||||
RDI_RegisterCode register_code = rdi_reg_code_from_cv_reg_code(arch, cv_reg);
|
||||
CV_LvarAddrRange *range = &defrange_register_rel->range;
|
||||
COFF_SectionHeader *range_section = (0 < range->sec && range->sec <= coff_sections->count) ? &coff_sections->sections[range->sec-1] : 0;
|
||||
CV_LvarAddrGap *gaps = (CV_LvarAddrGap*)(defrange_register_rel + 1);
|
||||
U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps);
|
||||
|
||||
// rjf: build location
|
||||
// TODO(rjf): offset & size from cv_reg code
|
||||
U32 byte_size = arch_addr_size;
|
||||
U32 byte_pos = 0;
|
||||
B32 extra_indirection_to_value = 0;
|
||||
S64 var_off = defrange_register_rel->reg_off;
|
||||
RDIM_Location *location = p2r_location_from_addr_reg_off(arena, arch, register_code, byte_size, byte_pos, var_off, extra_indirection_to_value);
|
||||
|
||||
// rjf: emit locations over ranges
|
||||
p2r_location_over_lvar_addr_range(arena, defrange_target, location, range, range_section, gaps, gap_count);
|
||||
}break;
|
||||
|
||||
//- rjf: FILESTATIC
|
||||
case CV_SymKind_FILESTATIC:
|
||||
{
|
||||
CV_SymFileStatic *file_static = (CV_SymFileStatic*)sym_header_struct_base;
|
||||
String8 name = str8_cstring_capped(file_static+1, sym_data_opl);
|
||||
RDIM_Type *type = p2r_type_ptr_from_itype(file_static->itype);
|
||||
// TODO(rjf): emit a global modifier symbol
|
||||
defrange_target = 0;
|
||||
defrange_target_is_param = 0;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#undef p2r_type_ptr_from_itype
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,30 @@ struct P2R_Params
|
||||
String8List errors;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Conversion Data Structure Types
|
||||
|
||||
//- rjf: link name map (voff -> string)
|
||||
|
||||
typedef struct P2R_LinkNameNode P2R_LinkNameNode;
|
||||
struct P2R_LinkNameNode
|
||||
{
|
||||
P2R_LinkNameNode *next;
|
||||
U64 voff;
|
||||
String8 name;
|
||||
};
|
||||
|
||||
typedef struct P2R_LinkNameMap P2R_LinkNameMap;
|
||||
struct P2R_LinkNameMap
|
||||
{
|
||||
P2R_LinkNameNode **buckets;
|
||||
U64 buckets_count;
|
||||
U64 bucket_collision_count;
|
||||
U64 link_name_count;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: PDB Type & Symbol Info Translation Helper Types
|
||||
|
||||
@@ -193,6 +217,7 @@ struct P2R_Ctx
|
||||
P2R_KnownGlobalSet known_globals;
|
||||
P2R_LinkNameMap link_names;
|
||||
};
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ Conversion Output Type
|
||||
@@ -206,6 +231,11 @@ struct P2R_Out
|
||||
String8List errors;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
internal U64 p2r_end_of_cplusplus_container_name(String8 str);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line -> Conversion Parameters
|
||||
|
||||
@@ -224,6 +254,15 @@ internal RDI_RegisterCode rdi_reg_code_from_cv_reg_code(RDI_Arch arch, CV_Reg re
|
||||
internal RDI_Language rdi_language_from_cv_language(CV_Language language);
|
||||
internal RDI_TypeKind rdi_type_kind_from_cv_basic_type(CV_BasicType basic_type);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Location Info Building Helpers
|
||||
|
||||
internal RDIM_Location *p2r_location_from_addr_reg_off(Arena *arena, RDI_Arch arch, RDI_RegisterCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 extra_indirection);
|
||||
internal CV_EncodedFramePtrReg p2r_cv_encoded_fp_reg_from_frameproc(CV_SymFrameproc *frameproc, B32 param_base);
|
||||
internal RDI_RegisterCode p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg);
|
||||
internal void p2r_location_over_lvar_addr_range(Arena *arena, RDIM_LocationSet *locset, RDIM_Location *location, CV_LvarAddrRange *range, COFF_SectionHeader *section, CV_LvarAddrGap *gaps, U64 gap_count);
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user