mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
d2r2: function type info; fix reg+off location info for signed offsets, function type deduplicating / construction / referencing, etc.
This commit is contained in:
+1
-1
@@ -1121,7 +1121,7 @@ typedef RDI_U64 RDI_Location;
|
|||||||
#define RDI_Location_RegOffShift 32
|
#define RDI_Location_RegOffShift 32
|
||||||
#define rdi_kind_from_location(l) ((((l) & RDI_Location_KindMask) >> RDI_Location_KindShift))
|
#define rdi_kind_from_location(l) ((((l) & RDI_Location_KindMask) >> RDI_Location_KindShift))
|
||||||
#define rdi_regcode_from_location(l) ((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_ValReg) ? (((l) & RDI_Location_RegCodeMask) >> RDI_Location_RegCodeShift) : 0)
|
#define rdi_regcode_from_location(l) ((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_ValReg) ? (((l) & RDI_Location_RegCodeMask) >> RDI_Location_RegCodeShift) : 0)
|
||||||
#define rdi_regoff_from_location(l) (RDI_S64)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)
|
#define rdi_regoff_from_location(l) (RDI_S64)(RDI_S32)(RDI_S16)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)
|
||||||
#define rdi_voff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ModuleOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
#define rdi_voff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ModuleOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
||||||
#define rdi_toff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_TLSOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
#define rdi_toff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_TLSOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
||||||
#define rdi_constant_data_off_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ConstantDataOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
#define rdi_constant_data_off_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ConstantDataOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)
|
||||||
|
|||||||
+2
-2
@@ -956,8 +956,8 @@ rb_thread_entry_point(void *p)
|
|||||||
{
|
{
|
||||||
bake_params = push_array(arena, RDIM_BakeParams, 1);
|
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, &pdb_bake_params);
|
||||||
rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params);
|
// rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params);
|
||||||
// rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params_2);
|
rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params_2);
|
||||||
for EachNode(n, RDIM_BakeParamsNode, first_rdi_bake_params)
|
for EachNode(n, RDIM_BakeParamsNode, first_rdi_bake_params)
|
||||||
{
|
{
|
||||||
rdim_bake_params_concat_in_place(bake_params, &n->v);
|
rdim_bake_params_concat_in_place(bake_params, &n->v);
|
||||||
|
|||||||
@@ -44,9 +44,9 @@
|
|||||||
// [x] container can also be a unit, so you can also go from procedure/global/tvar -> unit
|
// [x] container can also be a unit, so you can also go from procedure/global/tvar -> unit
|
||||||
// [x] *OR*, because we can guarantee that the units themselves will be sorted from lowest -> highest in all symbol tables, we can simply binary search the unit table (small) with a symbol's index to find its corresponding unit. that way, no need to duplicate e.g. namespaces and so on across units. and actually, we have to do this, because containers can be types, and those cannot be unit-locked.
|
// [x] *OR*, because we can guarantee that the units themselves will be sorted from lowest -> highest in all symbol tables, we can simply binary search the unit table (small) with a symbol's index to find its corresponding unit. that way, no need to duplicate e.g. namespaces and so on across units. and actually, we have to do this, because containers can be types, and those cannot be unit-locked.
|
||||||
//
|
//
|
||||||
// [ ] symbols only store their *partly-qualified name*, e.g. `x` for A::B::C::x
|
// [x] symbols only store their *partly-qualified name*, e.g. `x` for A::B::C::x
|
||||||
// [ ] default name maps look up *partly-qualified names*
|
// [x] default name maps look up *partly-qualified names*
|
||||||
// [ ] to match a *fully qualified name*, there needs to be a second kind of different lookup - instead of string-matching, we need to match against the *fully qualified names*. the maps must be built by hashing the *fully qualified name*, but redirecting to the symbol with the *partially qualified name*. this is to allow fully-qualified lookups, but avoid storing fully-qualified names.
|
// [x] to match a *fully qualified name*, there needs to be a second kind of different lookup - instead of string-matching, we need to match against the *fully qualified names*. the maps must be built by hashing the *fully qualified name*, but redirecting to the symbol with the *partially qualified name*. this is to allow fully-qualified lookups, but avoid storing fully-qualified names.
|
||||||
//
|
//
|
||||||
//- urgent fixes
|
//- urgent fixes
|
||||||
// [ ] (use msvc assert as an example) show fastfail exception info (code, name, etc.) - comes from ExceptionInformation @fastfail
|
// [ ] (use msvc assert as an example) show fastfail exception info (code, name, etc.) - comes from ExceptionInformation @fastfail
|
||||||
|
|||||||
+1
-1
@@ -1116,7 +1116,7 @@ RDI_LocationSetElementMemberTable:
|
|||||||
`#define RDI_Location_RegOffShift 32`;
|
`#define RDI_Location_RegOffShift 32`;
|
||||||
`#define rdi_kind_from_location(l) ((((l) & RDI_Location_KindMask) >> RDI_Location_KindShift))`;
|
`#define rdi_kind_from_location(l) ((((l) & RDI_Location_KindMask) >> RDI_Location_KindShift))`;
|
||||||
`#define rdi_regcode_from_location(l) ((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_ValReg) ? (((l) & RDI_Location_RegCodeMask) >> RDI_Location_RegCodeShift) : 0)`;
|
`#define rdi_regcode_from_location(l) ((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_ValReg) ? (((l) & RDI_Location_RegCodeMask) >> RDI_Location_RegCodeShift) : 0)`;
|
||||||
`#define rdi_regoff_from_location(l) (RDI_S64)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)`;
|
`#define rdi_regoff_from_location(l) (RDI_S64)(RDI_S32)(RDI_S16)((rdi_kind_from_location(l) == RDI_LocationKind_AddrRegPlusOff || rdi_kind_from_location(l) == RDI_LocationKind_AddrAddrRegPlusOff) ? (((l) & RDI_Location_RegOffMask) >> RDI_Location_RegOffShift) : 0)`;
|
||||||
`#define rdi_voff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ModuleOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
`#define rdi_voff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ModuleOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
||||||
`#define rdi_toff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_TLSOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
`#define rdi_toff_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_TLSOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
||||||
`#define rdi_constant_data_off_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ConstantDataOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
`#define rdi_constant_data_off_from_location(l) (rdi_kind_from_location(l) == RDI_LocationKind_ConstantDataOff ? (((l) & RDI_Location_OffMask) >> RDI_Location_OffShift) : 0)`;
|
||||||
|
|||||||
+1
-1
@@ -1073,7 +1073,7 @@ lane_sync(); if(flags & (1ull<<(kind))) ProfScope(rdi_name_title_from_dump_subse
|
|||||||
S64 reg_off = rdi_regoff_from_location(location);
|
S64 reg_off = rdi_regoff_from_location(location);
|
||||||
String8 reg_code_string = rdi_string_from_reg_code(scratch.arena, tli->arch, reg_code);
|
String8 reg_code_string = rdi_string_from_reg_code(scratch.arena, tli->arch, reg_code);
|
||||||
dumpf(" reg: %S\n", reg_code_string);
|
dumpf(" reg: %S\n", reg_code_string);
|
||||||
dumpf(" reg_off: 0x%I64x\n", reg_off);
|
dumpf(" reg_off: %I64d (0x%x)\n", reg_off, (U16)reg_off);
|
||||||
}break;
|
}break;
|
||||||
case RDI_LocationKind_ValReg:
|
case RDI_LocationKind_ValReg:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1377,6 +1377,10 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
DW2_Tag tag = {0};
|
DW2_Tag tag = {0};
|
||||||
t_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, t_off, &tag);
|
t_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, t_off, &tag);
|
||||||
|
|
||||||
|
// rjf: determine if tag should be skipped
|
||||||
|
B32 should_skip_tag = (tag.kind == DW_TagKind_LexicalBlock ||
|
||||||
|
tag.kind == DW_TagKind_Variable);
|
||||||
|
|
||||||
// rjf: record top-level info about this tag tree
|
// rjf: record top-level info about this tag tree
|
||||||
if(t_start_off == t->off && t == &start_task)
|
if(t_start_off == t->off && t == &start_task)
|
||||||
{
|
{
|
||||||
@@ -1388,6 +1392,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
tag.kind == DW_TagKind_StringType ||
|
tag.kind == DW_TagKind_StringType ||
|
||||||
tag.kind == DW_TagKind_StructureType ||
|
tag.kind == DW_TagKind_StructureType ||
|
||||||
tag.kind == DW_TagKind_SubroutineType ||
|
tag.kind == DW_TagKind_SubroutineType ||
|
||||||
|
tag.kind == DW_TagKind_SubProgram ||
|
||||||
tag.kind == DW_TagKind_Typedef ||
|
tag.kind == DW_TagKind_Typedef ||
|
||||||
tag.kind == DW_TagKind_UnionType ||
|
tag.kind == DW_TagKind_UnionType ||
|
||||||
tag.kind == DW_TagKind_PtrToMemberType ||
|
tag.kind == DW_TagKind_PtrToMemberType ||
|
||||||
@@ -1409,7 +1414,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rjf: is type -> combine tag's content into hash
|
// rjf: is type -> combine tag's content into hash
|
||||||
if(is_type_tag_tree)
|
if(!should_skip_tag && is_type_tag_tree)
|
||||||
{
|
{
|
||||||
// rjf: combine tag's kind
|
// rjf: combine tag's kind
|
||||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind));
|
hash = u64_hash_from_seed_str8(hash, str8_struct(&tag.kind));
|
||||||
@@ -1427,7 +1432,18 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
n->v.val.kind != DW_Form_Ref8 &&
|
n->v.val.kind != DW_Form_Ref8 &&
|
||||||
n->v.val.kind != DW_Form_RefUData &&
|
n->v.val.kind != DW_Form_RefUData &&
|
||||||
n->v.val.kind != DW_Form_RefSup4 &&
|
n->v.val.kind != DW_Form_RefSup4 &&
|
||||||
n->v.val.kind != DW_Form_RefSig8)
|
n->v.val.kind != DW_Form_RefSig8 &&
|
||||||
|
((tag.kind != DW_TagKind_SubProgram &&
|
||||||
|
tag.kind != DW_TagKind_FormalParameter) ||
|
||||||
|
(n->v.attrib_kind != DW_AttribKind_Name &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_DeclFile &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_DeclLine &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_Prototyped &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_External &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_FrameBase &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_Location &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_LowPc &&
|
||||||
|
n->v.attrib_kind != DW_AttribKind_HighPc)))
|
||||||
{
|
{
|
||||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.kind));
|
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.kind));
|
||||||
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.u128));
|
hash = u64_hash_from_seed_str8(hash, str8_struct(&n->v.val.u128));
|
||||||
@@ -1638,26 +1654,40 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
TypeDepChain *next;
|
TypeDepChain *next;
|
||||||
U64 type_idx;
|
U64 type_idx;
|
||||||
};
|
};
|
||||||
TypeDepChain **type_dep_chains = 0;
|
|
||||||
U64 *type_dep_chains_counts = 0;
|
U64 *type_dep_chains_counts = 0;
|
||||||
ProfScope("gather per-type dependency chains")
|
ProfScope("gather per-type dependency chains")
|
||||||
{
|
{
|
||||||
if(lane_idx() == 0)
|
if(lane_idx() == 0)
|
||||||
{
|
{
|
||||||
type_dep_chains = push_array(scratch.arena, TypeDepChain *, type_count);
|
|
||||||
type_dep_chains_counts = push_array(scratch.arena, U64, type_count);
|
type_dep_chains_counts = push_array(scratch.arena, U64, type_count);
|
||||||
}
|
}
|
||||||
lane_sync_u64(&type_dep_chains, 0);
|
|
||||||
lane_sync_u64(&type_dep_chains_counts, 0);
|
lane_sync_u64(&type_dep_chains_counts, 0);
|
||||||
Rng1U64 range = lane_range(type_count);
|
Rng1U64 range = lane_range(type_count);
|
||||||
for EachInRange(root_type_idx, range)
|
for EachInRange(root_type_idx, range)
|
||||||
{
|
{
|
||||||
for(U64 hash = type_tag_nodes[root_type_idx]->hash, next_hash = 0;
|
typedef struct TypeChainTask TypeChainTask;
|
||||||
hash != 0;
|
struct TypeChainTask
|
||||||
hash = next_hash)
|
{
|
||||||
|
TypeChainTask *next;
|
||||||
|
U64 hash;
|
||||||
|
};
|
||||||
|
TypeChainTask start_task = {0, type_tag_nodes[root_type_idx]->hash};
|
||||||
|
TypeChainTask *top_task = &start_task;
|
||||||
|
TypeChainTask *free_task = 0;
|
||||||
|
TypeChainTask *last_t = 0;
|
||||||
|
for(TypeChainTask *t = top_task; t != 0; (last_t = t, t = t->next))
|
||||||
{
|
{
|
||||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||||
|
|
||||||
|
// rjf: recycle old tasks
|
||||||
|
if(last_t != 0)
|
||||||
|
{
|
||||||
|
SLLStackPush(free_task, last_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: unpack task
|
||||||
|
U64 hash = t->hash;
|
||||||
|
|
||||||
// rjf: hash -> unique type tag node
|
// rjf: hash -> unique type tag node
|
||||||
UniqueTypeTagNode *type_tag_node = 0;
|
UniqueTypeTagNode *type_tag_node = 0;
|
||||||
{
|
{
|
||||||
@@ -1681,12 +1711,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
unit_idx = type_tag_node->unit_idx;
|
unit_idx = type_tag_node->unit_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: record this type in the dependency chain
|
// rjf: record this type in the dependency chain count
|
||||||
if(type_tag_node != 0)
|
if(type_tag_node != 0)
|
||||||
{
|
{
|
||||||
TypeDepChain *c = push_array(scratch.arena, TypeDepChain, 1);
|
|
||||||
c->type_idx = type_tag_node->order_idx;
|
|
||||||
SLLStackPush(type_dep_chains[root_type_idx], c);
|
|
||||||
type_dep_chains_counts[root_type_idx] += 1;
|
type_dep_chains_counts[root_type_idx] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1695,12 +1722,20 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
|
Rng1U64 unit_info_tag_range = unit_info_tag_ranges[unit_idx];
|
||||||
|
|
||||||
// rjf: parse this type's tag
|
// rjf: parse this type's tag
|
||||||
|
U64 read_off = info_off;
|
||||||
DW2_Tag tag = {0};
|
DW2_Tag tag = {0};
|
||||||
dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, info_off, &tag);
|
read_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, read_off, &tag);
|
||||||
|
|
||||||
// rjf: find direct type, if one exists
|
// rjf: find direct types from this type tag
|
||||||
U64 direct_type_info_off = 0;
|
typedef struct DirectTypeNode DirectTypeNode;
|
||||||
U64 direct_type_unit_idx = 0;
|
struct DirectTypeNode
|
||||||
|
{
|
||||||
|
DirectTypeNode *next;
|
||||||
|
U64 info_off;
|
||||||
|
U64 unit_idx;
|
||||||
|
};
|
||||||
|
DirectTypeNode *first_direct_type = 0;
|
||||||
|
DirectTypeNode *last_direct_type = 0;
|
||||||
switch(tag.kind)
|
switch(tag.kind)
|
||||||
{
|
{
|
||||||
default:{}break;
|
default:{}break;
|
||||||
@@ -1713,10 +1748,14 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
case DW_TagKind_ArrayType:
|
case DW_TagKind_ArrayType:
|
||||||
case DW_TagKind_SubrangeType:
|
case DW_TagKind_SubrangeType:
|
||||||
case DW_TagKind_Typedef:
|
case DW_TagKind_Typedef:
|
||||||
|
case DW_TagKind_SubProgram:
|
||||||
|
case DW_TagKind_SubroutineType:
|
||||||
|
{
|
||||||
|
// rjf: gather direct type
|
||||||
{
|
{
|
||||||
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type);
|
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&tag, DW_AttribKind_Type);
|
||||||
direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
U64 direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||||
direct_type_unit_idx = unit_idx;
|
U64 direct_type_unit_idx = unit_idx;
|
||||||
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
|
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
|
||||||
{
|
{
|
||||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||||
@@ -1726,10 +1765,71 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
direct_type_unit_idx = new_unit_num-1;
|
direct_type_unit_idx = new_unit_num-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DirectTypeNode *n = push_array(scratch2.arena, DirectTypeNode, 1);
|
||||||
|
n->info_off = direct_type_info_off;
|
||||||
|
n->unit_idx = direct_type_unit_idx;
|
||||||
|
SLLQueuePush(first_direct_type, last_direct_type, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: functions -> gather parameters
|
||||||
|
if(tag.has_children && (tag.kind == DW_TagKind_SubProgram || tag.kind == DW_TagKind_SubroutineType))
|
||||||
|
{
|
||||||
|
S64 depth = 1;
|
||||||
|
for(;depth > 0 && contains_1u64(unit_info_tag_range, read_off);)
|
||||||
|
{
|
||||||
|
U64 start_read_off = read_off;
|
||||||
|
|
||||||
|
// rjf: read child tag
|
||||||
|
DW2_Tag child_tag = {0};
|
||||||
|
read_off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, read_off, &child_tag);
|
||||||
|
|
||||||
|
// rjf: formal parameters -> gather direct types
|
||||||
|
if(child_tag.kind == DW_TagKind_FormalParameter)
|
||||||
|
{
|
||||||
|
DW2_Attrib *direct_type_attrib = dw2_attrib_from_kind(&child_tag, DW_AttribKind_Type);
|
||||||
|
U64 direct_type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||||
|
U64 direct_type_unit_idx = unit_idx;
|
||||||
|
if(!contains_1u64(unit_info_tag_range, direct_type_info_off))
|
||||||
|
{
|
||||||
|
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||||
|
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, direct_type_info_off);
|
||||||
|
if(0 < new_unit_num && new_unit_num <= unit_count)
|
||||||
|
{
|
||||||
|
direct_type_unit_idx = new_unit_num-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DirectTypeNode *n = push_array(scratch2.arena, DirectTypeNode, 1);
|
||||||
|
n->info_off = direct_type_info_off;
|
||||||
|
n->unit_idx = direct_type_unit_idx;
|
||||||
|
SLLQueuePush(first_direct_type, last_direct_type, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: tree navigations
|
||||||
|
if(tag.has_children)
|
||||||
|
{
|
||||||
|
depth += 1;
|
||||||
|
}
|
||||||
|
if(tag.kind == DW_TagKind_Null)
|
||||||
|
{
|
||||||
|
depth -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(read_off == start_read_off)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: look up hash for direct type
|
// rjf: for each dependency type, look up their hash, + spawn new tasks for them
|
||||||
|
for EachNode(n, DirectTypeNode, first_direct_type)
|
||||||
|
{
|
||||||
|
U64 direct_type_info_off = n->info_off;
|
||||||
|
U64 direct_type_unit_idx = n->unit_idx;
|
||||||
|
|
||||||
|
// rjf: direct type info offset -> hash
|
||||||
U64 direct_type_hash = 0;
|
U64 direct_type_hash = 0;
|
||||||
{
|
{
|
||||||
U64 off_hash = u64_hash_from_str8(str8_struct(&direct_type_info_off));
|
U64 off_hash = u64_hash_from_str8(str8_struct(&direct_type_info_off));
|
||||||
@@ -1744,8 +1844,19 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: iterate to direct type's hash
|
// rjf: spawn task
|
||||||
next_hash = direct_type_hash;
|
TypeChainTask *new_task = free_task;
|
||||||
|
if(new_task != 0)
|
||||||
|
{
|
||||||
|
SLLStackPop(free_task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_task = push_array(scratch.arena, TypeChainTask, 1);
|
||||||
|
}
|
||||||
|
new_task->hash = direct_type_hash;
|
||||||
|
t->next = new_task;
|
||||||
|
}
|
||||||
|
|
||||||
scratch_end(scratch2);
|
scratch_end(scratch2);
|
||||||
}
|
}
|
||||||
@@ -1940,9 +2051,116 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
dst_type->direct_type = direct_type;
|
dst_type->direct_type = direct_type;
|
||||||
dst_type->byte_size = (direct_type != 0 ? direct_type->byte_size : bitsize/8);
|
dst_type->byte_size = (direct_type != 0 ? direct_type->byte_size : bitsize/8);
|
||||||
}break;
|
}break;
|
||||||
|
case DW_TagKind_SubProgram:
|
||||||
case DW_TagKind_SubroutineType:
|
case DW_TagKind_SubroutineType:
|
||||||
{
|
{
|
||||||
|
// rjf: build type
|
||||||
|
dst_type = rdim_type_chunk_list_push(arena, &lane_types, lane_types_chunk_count);
|
||||||
|
dst_type->kind = RDI_TypeKind_Function;
|
||||||
|
dst_type->name = name;
|
||||||
|
dst_type->direct_type = direct_type;
|
||||||
|
dst_type->byte_size = arch_addr_size;
|
||||||
|
|
||||||
|
// rjf: gather all parameter types
|
||||||
|
typedef struct ParamNode ParamNode;
|
||||||
|
struct ParamNode
|
||||||
|
{
|
||||||
|
ParamNode *next;
|
||||||
|
U64 type_unit_idx;
|
||||||
|
U64 type_info_off;
|
||||||
|
};
|
||||||
|
ParamNode *first_param = 0;
|
||||||
|
ParamNode *last_param = 0;
|
||||||
|
U64 param_count = 0;
|
||||||
|
{
|
||||||
|
U64 tag_children_off = info_off + tag_info_size;
|
||||||
|
S64 depth = 1;
|
||||||
|
for(U64 off = tag_children_off; depth > 0 && contains_1u64(unit_info_tag_range, off);)
|
||||||
|
{
|
||||||
|
U64 start_off = off;
|
||||||
|
|
||||||
|
// rjf: read child tag
|
||||||
|
DW2_Tag child_tag = {0};
|
||||||
|
off += dw2_read_tag(scratch2.arena, unit_parse_ctx, raw->sec[DW_Section_Info].data, off, &child_tag);
|
||||||
|
|
||||||
|
// rjf: gather parameters
|
||||||
|
if(child_tag.kind == DW_TagKind_FormalParameter)
|
||||||
|
{
|
||||||
|
DW2_Attrib *type_attrib = dw2_attrib_from_kind(&child_tag, DW_AttribKind_Type);
|
||||||
|
ParamNode *n = push_array(scratch2.arena, ParamNode, 1);
|
||||||
|
n->type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &direct_type_attrib->val);
|
||||||
|
n->type_unit_idx = unit_idx;
|
||||||
|
SLLQueuePush(first_param, last_param, n);
|
||||||
|
if(!contains_1u64(unit_info_tag_range, n->type_info_off))
|
||||||
|
{
|
||||||
|
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||||
|
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, n->type_info_off);
|
||||||
|
n->type_unit_idx = (new_unit_num > 0 ? new_unit_num-1 : unit_idx);
|
||||||
|
}
|
||||||
|
param_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: navigate tree
|
||||||
|
if(child_tag.kind == DW_TagKind_Null)
|
||||||
|
{
|
||||||
|
depth -= 1;
|
||||||
|
}
|
||||||
|
if(child_tag.has_children)
|
||||||
|
{
|
||||||
|
depth += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(off == start_off)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: tighten parameter types
|
||||||
|
dst_type->count = (RDI_U32)param_count; // TODO(rjf): @u64_to_u32
|
||||||
|
dst_type->param_types = push_array(arena, RDIM_Type *, dst_type->count);
|
||||||
|
{
|
||||||
|
U64 param_idx = 0;
|
||||||
|
for(ParamNode *n = first_param; n != 0; n = n->next, param_idx += 1)
|
||||||
|
{
|
||||||
|
U64 param_type_info_off = n->type_info_off;
|
||||||
|
U64 param_type_unit_idx = n->type_unit_idx;
|
||||||
|
|
||||||
|
// rjf: map info_off/unit_idx -> hash
|
||||||
|
U64 param_type_hash = 0;
|
||||||
|
{
|
||||||
|
UnitTypeMap *direct_type_unit_type_map = &unit_type_maps[param_type_unit_idx];
|
||||||
|
U64 info_off_hash = u64_hash_from_str8(str8_struct(¶m_type_info_off));
|
||||||
|
U64 info_off_slot_idx = info_off_hash%direct_type_unit_type_map->slots_count;
|
||||||
|
for(UnitTypeNode *n = direct_type_unit_type_map->slots[info_off_slot_idx]; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->src_info_off == param_type_info_off)
|
||||||
|
{
|
||||||
|
param_type_hash = n->dst_hash;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: map hash -> type
|
||||||
|
RDIM_Type *param_type = 0;
|
||||||
|
{
|
||||||
|
U64 unique_type_tag_slot_idx = param_type_hash%unique_type_tag_slots_count;
|
||||||
|
for(UniqueTypeTagNode *n = unique_type_tag_slots[unique_type_tag_slot_idx]; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->hash == param_type_hash)
|
||||||
|
{
|
||||||
|
param_type = type_from_idx_map[n->order_idx];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: store
|
||||||
|
dst_type->param_types[param_idx] = param_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
case DW_TagKind_Typedef:
|
case DW_TagKind_Typedef:
|
||||||
{
|
{
|
||||||
@@ -2458,15 +2676,24 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
RDIM_Type *type = 0;
|
RDIM_Type *type = 0;
|
||||||
if(type_attrib != &dw2_attrib_nil)
|
if(type_attrib != &dw2_attrib_nil)
|
||||||
{
|
{
|
||||||
// rjf: attrib -> (info_off, unit_idx)
|
// rjf: functions need to get their type info from themselves; the type attrib
|
||||||
U64 type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val);
|
// only references the return type. so, in that case, we'll use the procedure's
|
||||||
|
// own info offset / unit index, rather than the type attribute's.
|
||||||
|
U64 type_info_off = start_off;
|
||||||
U64 type_unit_idx = unit_idx;
|
U64 type_unit_idx = unit_idx;
|
||||||
|
|
||||||
|
// rjf: attrib -> (info_off, unit_idx)
|
||||||
|
if(tag.kind != DW_TagKind_SubProgram)
|
||||||
|
{
|
||||||
|
type_info_off = dw2_reference_info_off_from_form_val(unit_parse_ctx, &type_attrib->val);
|
||||||
|
type_unit_idx = unit_idx;
|
||||||
if(!contains_1u64(unit_info_tag_range, type_info_off))
|
if(!contains_1u64(unit_info_tag_range, type_info_off))
|
||||||
{
|
{
|
||||||
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
Rng1U64Array unit_info_tag_ranges_array = {unit_info_tag_ranges, unit_count};
|
||||||
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, type_info_off);
|
U64 new_unit_num = rng1u64_array_num_from_value__binary_search(&unit_info_tag_ranges_array, type_info_off);
|
||||||
type_unit_idx = (new_unit_num > 0 ? new_unit_num-1 : unit_idx);
|
type_unit_idx = (new_unit_num > 0 ? new_unit_num-1 : unit_idx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rjf: (info_off, unit_idx) -> hash
|
// rjf: (info_off, unit_idx) -> hash
|
||||||
U64 type_hash = 0;
|
U64 type_hash = 0;
|
||||||
@@ -3137,6 +3364,93 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
{
|
{
|
||||||
loc.kind = val_stack_top && val_stack_top->v.is_addr ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream;
|
loc.kind = val_stack_top && val_stack_top->v.is_addr ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream;
|
||||||
loc.bytecode = dst_bytecode;
|
loc.bytecode = dst_bytecode;
|
||||||
|
|
||||||
|
// rjf: gather first few bytecodes for pattern matching
|
||||||
|
RDI_EvalOp beginning_ops[5] = {0};
|
||||||
|
RDIM_EvalBytecodeOp *beginning_nodes[5] = {0};
|
||||||
|
{
|
||||||
|
U64 idx = 0;
|
||||||
|
for EachNode(n, RDIM_EvalBytecodeOp, dst_bytecode.first_op)
|
||||||
|
{
|
||||||
|
if(idx >= ArrayCount(beginning_ops))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
beginning_ops[idx] = n->op;
|
||||||
|
beginning_nodes[idx] = n;
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: match simple register offsets
|
||||||
|
if(loc.kind == RDI_LocationKind_AddrBytecodeStream &&
|
||||||
|
beginning_ops[0] == RDI_EvalOp_RegRead &&
|
||||||
|
(beginning_ops[1] == RDI_EvalOp_ConstU8 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU16) &&
|
||||||
|
beginning_ops[2] == RDI_EvalOp_TruncSigned &&
|
||||||
|
beginning_ops[3] == RDI_EvalOp_Add &&
|
||||||
|
beginning_ops[4] == RDI_EvalOp_Stop)
|
||||||
|
{
|
||||||
|
U8 rdi_reg_code = (beginning_nodes[0]->p&0x0000FF)>>0;
|
||||||
|
U8 byte_size = (beginning_nodes[0]->p&0x00FF00)>>8;
|
||||||
|
U8 byte_off = (beginning_nodes[0]->p&0xFF0000)>>16;
|
||||||
|
if(byte_off == 0 && byte_size == unit_parse_ctx->addr_size)
|
||||||
|
{
|
||||||
|
loc.kind = RDI_LocationKind_AddrRegPlusOff;
|
||||||
|
loc.reg_code = rdi_reg_code;
|
||||||
|
loc.offset = beginning_nodes[1]->p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: match simple module offsets
|
||||||
|
if(beginning_ops[0] == RDI_EvalOp_ModuleOff && beginning_ops[1] == RDI_EvalOp_Stop)
|
||||||
|
{
|
||||||
|
U64 voff = beginning_nodes[0]->p;
|
||||||
|
loc.kind = RDI_LocationKind_ModuleOff;
|
||||||
|
loc.offset = voff;
|
||||||
|
}
|
||||||
|
else if(((beginning_ops[0] == RDI_EvalOp_ModuleOff &&
|
||||||
|
(beginning_ops[1] == RDI_EvalOp_ConstU8 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU16 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU32 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU64)) ||
|
||||||
|
(beginning_ops[1] == RDI_EvalOp_ModuleOff &&
|
||||||
|
(beginning_ops[0] == RDI_EvalOp_ConstU8 ||
|
||||||
|
beginning_ops[0] == RDI_EvalOp_ConstU16 ||
|
||||||
|
beginning_ops[0] == RDI_EvalOp_ConstU32 ||
|
||||||
|
beginning_ops[0] == RDI_EvalOp_ConstU64))) &&
|
||||||
|
beginning_ops[2] == RDI_EvalOp_Add &&
|
||||||
|
beginning_ops[3] == RDI_EvalOp_Stop)
|
||||||
|
{
|
||||||
|
U64 voff = beginning_nodes[0]->p + beginning_nodes[1]->p;
|
||||||
|
loc.kind = RDI_LocationKind_ModuleOff;
|
||||||
|
loc.offset = voff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: match simple TLS offsets
|
||||||
|
if(beginning_ops[0] == RDI_EvalOp_TLSOff && beginning_ops[1] == RDI_EvalOp_Stop)
|
||||||
|
{
|
||||||
|
U64 toff = beginning_nodes[0]->p;
|
||||||
|
loc.kind = RDI_LocationKind_TLSOff;
|
||||||
|
loc.offset = toff;
|
||||||
|
}
|
||||||
|
else if(((beginning_ops[0] == RDI_EvalOp_TLSOff &&
|
||||||
|
(beginning_ops[1] == RDI_EvalOp_ConstU8 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU16 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU32 ||
|
||||||
|
beginning_ops[1] == RDI_EvalOp_ConstU64)) ||
|
||||||
|
(beginning_ops[1] == RDI_EvalOp_TLSOff &&
|
||||||
|
(beginning_ops[0] == RDI_EvalOp_ConstU8 ||
|
||||||
|
beginning_ops[0] == RDI_EvalOp_ConstU16 ||
|
||||||
|
beginning_ops[0] == RDI_EvalOp_ConstU32 ||
|
||||||
|
beginning_ops[0] == RDI_EvalOp_ConstU64))) &&
|
||||||
|
beginning_ops[2] == RDI_EvalOp_Add &&
|
||||||
|
beginning_ops[3] == RDI_EvalOp_Stop)
|
||||||
|
{
|
||||||
|
U64 toff = beginning_nodes[0]->p + beginning_nodes[1]->p;
|
||||||
|
loc.kind = RDI_LocationKind_TLSOff;
|
||||||
|
loc.offset = toff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: collect
|
//- rjf: collect
|
||||||
@@ -3176,7 +3490,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
RDIM_Symbol *procedure = rdim_symbol_chunk_list_push(arena, &dst_unit->procedures, chunk_count);
|
RDIM_Symbol *procedure = rdim_symbol_chunk_list_push(arena, &dst_unit->procedures, chunk_count);
|
||||||
procedure->name = name;
|
procedure->name = name;
|
||||||
procedure->link_name = link_name;
|
procedure->link_name = link_name;
|
||||||
|
procedure->type = type;
|
||||||
procedure->root_scope = root_scope;
|
procedure->root_scope = root_scope;
|
||||||
|
procedure->location_cases = framebase_location_cases;
|
||||||
root_scope->symbol = procedure;
|
root_scope->symbol = procedure;
|
||||||
root_scope->voff_ranges = ranges;
|
root_scope->voff_ranges = ranges;
|
||||||
dst_unit->scopes.scope_voff_count += 2;
|
dst_unit->scopes.scope_voff_count += 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user