mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 15:42:23 -07:00
codeview c13 inlinee lines info parsing, lookup in inline site parsing path
This commit is contained in:
+316
-273
@@ -7,21 +7,44 @@
|
||||
#include "generated/codeview.meta.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Common Functions
|
||||
//~ CodeView Common Decoding Helper Functions
|
||||
|
||||
internal U64
|
||||
cv_hash_from_string(String8 string)
|
||||
{
|
||||
U64 result = 5381;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + string.str[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_hash_from_item_id(CV_ItemId item_id)
|
||||
{
|
||||
U64 result = cv_hash_from_string(str8_struct(&item_id));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CV_NumericParsed
|
||||
cv_numeric_from_data_range(U8 *first, U8 *opl){
|
||||
cv_numeric_from_data_range(U8 *first, U8 *opl)
|
||||
{
|
||||
CV_NumericParsed result = {0};
|
||||
if (first + 2 <= opl){
|
||||
if(first + 2 <= opl)
|
||||
{
|
||||
U16 x = *(U16*)first;
|
||||
if (x < 0x8000){
|
||||
if(x < 0x8000)
|
||||
{
|
||||
result.kind = CV_NumericKind_USHORT;
|
||||
result.val = first;
|
||||
result.encoded_size = 2;
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
U64 val_size = 0;
|
||||
switch (x){
|
||||
switch(x)
|
||||
{
|
||||
case CV_NumericKind_CHAR: val_size = 1; break;
|
||||
case CV_NumericKind_SHORT:
|
||||
case CV_NumericKind_USHORT: val_size = 2; break;
|
||||
@@ -46,21 +69,23 @@ cv_numeric_from_data_range(U8 *first, U8 *opl){
|
||||
case CV_NumericKind_UTF8STRING:val_size = 0; break; // TODO: ???
|
||||
case CV_NumericKind_FLOAT16: val_size = 2; break;
|
||||
}
|
||||
|
||||
if (first + 2 + val_size <= opl){
|
||||
if(first + 2 + val_size <= opl)
|
||||
{
|
||||
result.kind = x;
|
||||
result.val = (first + 2);
|
||||
result.encoded_size = 2 + val_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_numeric_fits_in_u64(CV_NumericParsed *num){
|
||||
cv_numeric_fits_in_u64(CV_NumericParsed *num)
|
||||
{
|
||||
B32 result = 0;
|
||||
switch (num->kind){
|
||||
switch(num->kind)
|
||||
{
|
||||
case CV_NumericKind_USHORT:
|
||||
case CV_NumericKind_ULONG:
|
||||
case CV_NumericKind_UQUADWORD:
|
||||
@@ -68,13 +93,15 @@ cv_numeric_fits_in_u64(CV_NumericParsed *num){
|
||||
result = 1;
|
||||
}break;
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_numeric_fits_in_s64(CV_NumericParsed *num){
|
||||
cv_numeric_fits_in_s64(CV_NumericParsed *num)
|
||||
{
|
||||
B32 result = 0;
|
||||
switch (num->kind){
|
||||
switch(num->kind)
|
||||
{
|
||||
case CV_NumericKind_CHAR:
|
||||
case CV_NumericKind_SHORT:
|
||||
case CV_NumericKind_LONG:
|
||||
@@ -83,91 +110,63 @@ cv_numeric_fits_in_s64(CV_NumericParsed *num){
|
||||
result = 1;
|
||||
}break;
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_numeric_fits_in_f64(CV_NumericParsed *num){
|
||||
cv_numeric_fits_in_f64(CV_NumericParsed *num)
|
||||
{
|
||||
B32 result = 0;
|
||||
switch (num->kind){
|
||||
switch(num->kind)
|
||||
{
|
||||
case CV_NumericKind_FLOAT32:
|
||||
case CV_NumericKind_FLOAT64:
|
||||
{
|
||||
result = 1;
|
||||
}break;
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_u64_from_numeric(CV_NumericParsed *num){
|
||||
cv_u64_from_numeric(CV_NumericParsed *num)
|
||||
{
|
||||
U64 result = 0;
|
||||
switch (num->kind){
|
||||
case CV_NumericKind_USHORT:
|
||||
{
|
||||
result = *(U16*)num->val;
|
||||
}break;
|
||||
|
||||
case CV_NumericKind_ULONG:
|
||||
{
|
||||
result = *(U32*)num->val;
|
||||
}break;
|
||||
|
||||
case CV_NumericKind_UQUADWORD:
|
||||
{
|
||||
result = *(U64*)num->val;
|
||||
}break;
|
||||
switch(num->kind)
|
||||
{
|
||||
case CV_NumericKind_USHORT: {result = *(U16*)num->val;}break;
|
||||
case CV_NumericKind_ULONG: {result = *(U32*)num->val;}break;
|
||||
case CV_NumericKind_UQUADWORD:{result = *(U64*)num->val;}break;
|
||||
}
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal S64
|
||||
cv_s64_from_numeric(CV_NumericParsed *num){
|
||||
cv_s64_from_numeric(CV_NumericParsed *num)
|
||||
{
|
||||
S64 result = 0;
|
||||
switch (num->kind){
|
||||
case CV_NumericKind_CHAR:
|
||||
{
|
||||
result = *(S8*)num->val;
|
||||
}break;
|
||||
|
||||
case CV_NumericKind_SHORT:
|
||||
{
|
||||
result = *(S16*)num->val;
|
||||
}break;
|
||||
|
||||
case CV_NumericKind_LONG:
|
||||
{
|
||||
result = *(S32*)num->val;
|
||||
}break;
|
||||
|
||||
case CV_NumericKind_QUADWORD:
|
||||
{
|
||||
result = *(S64*)num->val;
|
||||
}break;
|
||||
switch(num->kind)
|
||||
{
|
||||
case CV_NumericKind_CHAR: {result = *(S8*)num->val;}break;
|
||||
case CV_NumericKind_SHORT: {result = *(S16*)num->val;}break;
|
||||
case CV_NumericKind_LONG: {result = *(S32*)num->val;}break;
|
||||
case CV_NumericKind_QUADWORD: {result = *(S64*)num->val;}break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal F64
|
||||
cv_f64_from_numeric(CV_NumericParsed *num){
|
||||
cv_f64_from_numeric(CV_NumericParsed *num)
|
||||
{
|
||||
F64 result = 0;
|
||||
switch (num->kind){
|
||||
case CV_NumericKind_FLOAT32:
|
||||
{
|
||||
result = *(F32*)num->val;
|
||||
}break;
|
||||
|
||||
case CV_NumericKind_FLOAT64:
|
||||
{
|
||||
result = *(F64*)num->val;
|
||||
}break;
|
||||
switch(num->kind)
|
||||
{
|
||||
case CV_NumericKind_FLOAT32:{result = *(F32*)num->val;}break;
|
||||
case CV_NumericKind_FLOAT64:{result = *(F64*)num->val;}break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Inline Binary Annotation Helpers
|
||||
|
||||
internal U64
|
||||
cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value)
|
||||
{
|
||||
@@ -239,27 +238,27 @@ cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value)
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Sym Parser Functions
|
||||
//~ CodeView Parsing Functions
|
||||
|
||||
//- the first pass parser
|
||||
//- rjf: record range stream parsing
|
||||
|
||||
internal CV_RecRangeStream*
|
||||
cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){
|
||||
cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align)
|
||||
{
|
||||
Assert(1 <= sym_align && IsPow2OrZero(sym_align));
|
||||
|
||||
CV_RecRangeStream *result = push_array(arena, CV_RecRangeStream, 1);
|
||||
|
||||
U8 *data = sym_data.str;
|
||||
U64 cursor = 0;
|
||||
U64 cap = sym_data.size;
|
||||
for (;cursor + sizeof(CV_RecHeader) <= cap;){
|
||||
for(;cursor + sizeof(CV_RecHeader) <= cap;)
|
||||
{
|
||||
// setup a new chunk
|
||||
arena_push_align(arena, 64);
|
||||
CV_RecRangeChunk *cur_chunk = cv_rec_range_stream_push_chunk(arena, result);
|
||||
|
||||
CV_RecRangeChunk *cur_chunk = push_array_no_zero(arena, CV_RecRangeChunk, 1);
|
||||
SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk);
|
||||
U64 partial_count = 0;
|
||||
for (;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap;
|
||||
partial_count += 1){
|
||||
for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1)
|
||||
{
|
||||
// compute cap
|
||||
CV_RecHeader *hdr = (CV_RecHeader*)(data + cursor);
|
||||
U64 symbol_cap_unclamped = cursor + 2 + hdr->size;
|
||||
@@ -273,110 +272,110 @@ cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){
|
||||
U32 next_pos = AlignPow2(symbol_cap, sym_align);
|
||||
cursor = next_pos;
|
||||
}
|
||||
|
||||
result->total_count += partial_count;
|
||||
}
|
||||
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//- sym
|
||||
internal CV_RecRangeArray
|
||||
cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream)
|
||||
{
|
||||
U64 total_count = stream->total_count;
|
||||
CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count);
|
||||
U64 idx = 0;
|
||||
for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next)
|
||||
{
|
||||
U64 copy_count_raw = total_count - idx;
|
||||
U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE);
|
||||
MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange));
|
||||
idx += copy_count;
|
||||
}
|
||||
CV_RecRangeArray result = {0};
|
||||
result.ranges = ranges;
|
||||
result.count = total_count;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CV_SymParsed*
|
||||
cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align){
|
||||
//- rjf: sym stream parsing
|
||||
|
||||
internal CV_SymParsed *
|
||||
cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align)
|
||||
{
|
||||
Assert(1 <= sym_align && IsPow2OrZero(sym_align));
|
||||
ProfBegin("cv_sym_from_data");
|
||||
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
// gather up symbols
|
||||
//- rjf: gather symbols
|
||||
CV_RecRangeStream *stream = cv_rec_range_stream_from_data(scratch.arena, sym_data, sym_align);
|
||||
|
||||
// convert to result
|
||||
//- rjf: convert to result, fill basics
|
||||
CV_SymParsed *result = push_array(arena, CV_SymParsed, 1);
|
||||
result->data = sym_data;
|
||||
result->sym_align = sym_align;
|
||||
result->sym_ranges = cv_rec_range_array_from_stream(arena, stream);
|
||||
cv_sym_top_level_info_from_syms(arena, sym_data, &result->sym_ranges, &result->info);
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
ProfEnd();
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data,
|
||||
CV_RecRangeArray *ranges,
|
||||
CV_SymTopLevelInfo *info_out){
|
||||
MemoryZeroStruct(info_out);
|
||||
|
||||
CV_RecRange *range = ranges->ranges;
|
||||
CV_RecRange *opl = range + ranges->count;
|
||||
for (; range < opl; range += 1){
|
||||
U8 *first = sym_data.str + range->off + 2;
|
||||
U64 cap = range->hdr.size - 2;
|
||||
|
||||
switch (range->hdr.kind){
|
||||
case CV_SymKind_COMPILE:
|
||||
//- rjf: extract top-level-info
|
||||
{
|
||||
CV_RecRange *range = result->sym_ranges.ranges;
|
||||
CV_RecRange *opl = range + result->sym_ranges.count;
|
||||
for(;range < opl; range += 1)
|
||||
{
|
||||
U8 *first = sym_data.str + range->off + 2;
|
||||
U64 cap = range->hdr.size - 2;
|
||||
switch(range->hdr.kind)
|
||||
{
|
||||
if (sizeof(CV_SymCompile) <= cap){
|
||||
case CV_SymKind_COMPILE:
|
||||
if(sizeof(CV_SymCompile) <= cap)
|
||||
{
|
||||
CV_SymCompile *compile = (CV_SymCompile*)first;
|
||||
|
||||
String8 ver_str = str8_cstring_capped((char*)(compile + 1), (char *)(first + cap));
|
||||
|
||||
info_out->arch = compile->machine;
|
||||
info_out->language = CV_CompileFlags_ExtractLanguage(compile->flags);;
|
||||
info_out->compiler_name = ver_str;
|
||||
}
|
||||
}break;
|
||||
|
||||
case CV_SymKind_COMPILE2:
|
||||
{
|
||||
if (sizeof(CV_SymCompile2) <= cap){
|
||||
result->info.arch = compile->machine;
|
||||
result->info.language = CV_CompileFlags_ExtractLanguage(compile->flags);;
|
||||
result->info.compiler_name = ver_str;
|
||||
}break;
|
||||
case CV_SymKind_COMPILE2:
|
||||
if(sizeof(CV_SymCompile2) <= cap)
|
||||
{
|
||||
CV_SymCompile2 *compile2 = (CV_SymCompile2*)first;
|
||||
|
||||
String8 ver_str = str8_cstring_capped((char*)(compile2 + 1), (char*)(first + cap));
|
||||
String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u",
|
||||
str8_varg(ver_str),
|
||||
compile2->ver_major,
|
||||
compile2->ver_minor,
|
||||
compile2->ver_build);
|
||||
|
||||
info_out->arch = compile2->machine;
|
||||
info_out->language = CV_Compile2Flags_ExtractLanguage(compile2->flags);;
|
||||
info_out->compiler_name = compiler_name;
|
||||
}
|
||||
}break;
|
||||
|
||||
case CV_SymKind_COMPILE3:
|
||||
{
|
||||
if (sizeof(CV_SymCompile3) <= cap){
|
||||
result->info.arch = compile2->machine;
|
||||
result->info.language = CV_Compile2Flags_ExtractLanguage(compile2->flags);;
|
||||
result->info.compiler_name = compiler_name;
|
||||
}break;
|
||||
case CV_SymKind_COMPILE3:
|
||||
if(sizeof(CV_SymCompile3) <= cap)
|
||||
{
|
||||
CV_SymCompile3 *compile3 = (CV_SymCompile3*)first;
|
||||
|
||||
String8 ver_str = str8_cstring_capped((char*)(compile3 + 1), (char *)(first + cap));
|
||||
String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u",
|
||||
str8_varg(ver_str),
|
||||
compile3->ver_major,
|
||||
compile3->ver_minor,
|
||||
compile3->ver_build);
|
||||
|
||||
info_out->arch = compile3->machine;
|
||||
info_out->language = CV_Compile3Flags_ExtractLanguage(compile3->flags);;
|
||||
info_out->compiler_name = compiler_name;
|
||||
}
|
||||
}break;
|
||||
result->info.arch = compile3->machine;
|
||||
result->info.language = CV_Compile3Flags_ExtractLanguage(compile3->flags);;
|
||||
result->info.compiler_name = compiler_name;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return result;
|
||||
}
|
||||
|
||||
//- leaf
|
||||
//- rjf: leaf stream parsing
|
||||
|
||||
internal CV_LeafParsed*
|
||||
cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){
|
||||
ProfBegin("cv_leaf_from_data");
|
||||
|
||||
internal CV_LeafParsed *
|
||||
cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
// gather up symbols
|
||||
@@ -390,57 +389,31 @@ cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){
|
||||
result->leaf_ranges = cv_rec_range_array_from_stream(arena, stream);
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
ProfEnd();
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
//- range streams
|
||||
|
||||
internal CV_RecRangeChunk*
|
||||
cv_rec_range_stream_push_chunk(Arena *arena, CV_RecRangeStream *stream){
|
||||
CV_RecRangeChunk *result = push_array_no_zero(arena, CV_RecRangeChunk, 1);
|
||||
SLLQueuePush(stream->first_chunk, stream->last_chunk, result);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal CV_RecRangeArray
|
||||
cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream){
|
||||
U64 total_count = stream->total_count;
|
||||
CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count);
|
||||
U64 idx = 0;
|
||||
for (CV_RecRangeChunk *chunk = stream->first_chunk;
|
||||
chunk != 0;
|
||||
chunk = chunk->next){
|
||||
U64 copy_count_raw = total_count - idx;
|
||||
U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE);
|
||||
MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange));
|
||||
idx += copy_count;
|
||||
}
|
||||
CV_RecRangeArray result = {0};
|
||||
result.ranges = ranges;
|
||||
result.count = total_count;
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView C13 Parser Functions
|
||||
|
||||
internal CV_C13Parsed*
|
||||
cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections){
|
||||
ProfBegin("cv_c13_from_data");
|
||||
internal CV_C13Parsed *
|
||||
cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
// gather c13 data
|
||||
//////////////////////////////
|
||||
//- rjf: gather c13 sub-sections
|
||||
//
|
||||
CV_C13SubSectionNode *file_chksms = 0;
|
||||
CV_C13SubSectionNode *first = 0;
|
||||
CV_C13SubSectionNode *last = 0;
|
||||
U64 count = 0;
|
||||
{
|
||||
U32 cursor = 0;
|
||||
for (; cursor + sizeof(CV_C13_SubSectionHeader) <= c13_data.size;){
|
||||
for(; cursor + sizeof(CV_C13SubSectionHeader) <= c13_data.size;)
|
||||
{
|
||||
// read header
|
||||
CV_C13_SubSectionHeader *hdr = (CV_C13_SubSectionHeader*)(c13_data.str + cursor);
|
||||
CV_C13SubSectionHeader *hdr = (CV_C13SubSectionHeader*)(c13_data.str + cursor);
|
||||
|
||||
// get sub section info
|
||||
U32 sub_section_off = cursor + sizeof(*hdr);
|
||||
@@ -450,15 +423,16 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec
|
||||
U32 sub_section_size = after_sub_section_off - sub_section_off;
|
||||
|
||||
// emit sub section
|
||||
if (!(hdr->kind & CV_C13_SubSectionKind_IgnoreFlag)){
|
||||
if(!(hdr->kind & CV_C13SubSectionKind_IgnoreFlag))
|
||||
{
|
||||
CV_C13SubSectionNode *node = push_array(arena, CV_C13SubSectionNode, 1);
|
||||
SLLQueuePush(first, last, node);
|
||||
count += 1;
|
||||
node->kind = hdr->kind;
|
||||
node->off = sub_section_off;
|
||||
node->size = sub_section_size;
|
||||
|
||||
if (hdr->kind == CV_C13_SubSectionKind_FileChksms){
|
||||
if(hdr->kind == CV_C13SubSectionKind_FileChksms)
|
||||
{
|
||||
file_chksms = node;
|
||||
}
|
||||
}
|
||||
@@ -468,112 +442,181 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec
|
||||
}
|
||||
}
|
||||
|
||||
// parse each section
|
||||
for (CV_C13SubSectionNode *node = first;
|
||||
node != 0;
|
||||
node = node->next){
|
||||
//////////////////////////////
|
||||
//- rjf: parse each sub-section
|
||||
//
|
||||
U64 inlinee_lines_parsed_slots_count = 4096;
|
||||
CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots = push_array(arena, CV_C13InlineeLinesParsedNode *, inlinee_lines_parsed_slots_count);
|
||||
for(CV_C13SubSectionNode *node = first;
|
||||
node != 0;
|
||||
node = node->next)
|
||||
{
|
||||
U8 *first = c13_data.str + node->off;
|
||||
U32 cap = node->size;
|
||||
|
||||
switch (node->kind){
|
||||
case CV_C13_SubSectionKind_Lines:
|
||||
switch(node->kind)
|
||||
{
|
||||
default:{}break;
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: line info sub-section
|
||||
//
|
||||
case CV_C13SubSectionKind_Lines:
|
||||
if(sizeof(CV_C13SubSecLinesHeader) <= cap)
|
||||
{
|
||||
// read header
|
||||
if (sizeof(CV_C13_SubSecLinesHeader) <= cap){
|
||||
U32 read_off = 0;
|
||||
U64 read_off_opl = node->size;
|
||||
CV_C13_SubSecLinesHeader *hdr = (CV_C13_SubSecLinesHeader*)(first + read_off);
|
||||
U32 read_off = 0;
|
||||
U64 read_off_opl = node->size;
|
||||
CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off);
|
||||
read_off += sizeof(*hdr);
|
||||
|
||||
// extract top level info
|
||||
U32 sec_idx = hdr->sec;
|
||||
B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns);
|
||||
U64 secrel_off = hdr->sec_off;
|
||||
U64 secrel_opl = secrel_off + hdr->len;
|
||||
U64 sec_base_off = sections->sections[sec_idx - 1].voff;
|
||||
|
||||
// rjf: bad section index -> skip
|
||||
if(sec_idx < 1 || sections->count < sec_idx)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// read files
|
||||
for(;read_off+sizeof(CV_C13File) <= read_off_opl;)
|
||||
{
|
||||
// rjf: grab next file header
|
||||
CV_C13File *file = (CV_C13File*)(first + read_off);
|
||||
U32 file_off = file->file_off;
|
||||
U32 line_count_unclamped = file->num_lines;
|
||||
U32 block_size = file->block_size;
|
||||
|
||||
// file_name from file_off
|
||||
String8 file_name = {0};
|
||||
if(file_off + sizeof(CV_C13Checksum) <= file_chksms->size)
|
||||
{
|
||||
CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off);
|
||||
U32 name_off = checksum->name_off;
|
||||
file_name = pdb_strtbl_string_from_off(strtbl, name_off);
|
||||
}
|
||||
|
||||
// array layouts
|
||||
U32 line_item_size = sizeof(CV_C13Line);
|
||||
if (has_cols){
|
||||
line_item_size += sizeof(CV_C13Column);
|
||||
}
|
||||
|
||||
U32 line_array_off = read_off + sizeof(*file);
|
||||
U32 line_count_max = (read_off_opl - line_array_off) / line_item_size;
|
||||
U32 line_count = ClampTop(line_count_unclamped, line_count_max);
|
||||
|
||||
U32 col_array_off = line_array_off + line_count*sizeof(CV_C13Line);
|
||||
|
||||
// parse lines
|
||||
U64 *voffs = push_array_no_zero(arena, U64, line_count + 1);
|
||||
U32 *line_nums = push_array_no_zero(arena, U32, line_count);
|
||||
|
||||
{
|
||||
CV_C13Line *line_ptr = (CV_C13Line*)(first + line_array_off);
|
||||
CV_C13Line *line_opl = line_ptr + line_count;
|
||||
|
||||
// TODO(allen): check order correctness here
|
||||
|
||||
U32 i = 0;
|
||||
for (; line_ptr < line_opl; line_ptr += 1, i += 1){
|
||||
voffs[i] = line_ptr->off + secrel_off + sec_base_off;
|
||||
line_nums[i] = CV_C13LineFlags_ExtractLineNumber(line_ptr->flags);
|
||||
}
|
||||
voffs[i] = secrel_opl + sec_base_off;
|
||||
}
|
||||
|
||||
// emit parsed lines
|
||||
CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1);
|
||||
CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v;
|
||||
lines_parsed->sec_idx = sec_idx;
|
||||
lines_parsed->file_off = file_off;
|
||||
lines_parsed->secrel_base_off = secrel_off;
|
||||
lines_parsed->file_name = file_name;
|
||||
lines_parsed->voffs = voffs;
|
||||
lines_parsed->line_nums = line_nums;
|
||||
lines_parsed->line_count = line_count;
|
||||
SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node);
|
||||
|
||||
// rjf: advance
|
||||
read_off += sizeof(*file);
|
||||
read_off += line_item_size*line_count;
|
||||
}
|
||||
}break;
|
||||
|
||||
//////////////////////////
|
||||
//- rjf: inlinee line info sub-section
|
||||
//
|
||||
case CV_C13SubSectionKind_InlineeLines:
|
||||
if(sizeof(CV_C13InlineeLinesSig) <= cap)
|
||||
{
|
||||
// rjf: read sig
|
||||
U32 read_off = 0;
|
||||
U64 read_off_opl = node->size;
|
||||
CV_C13InlineeLinesSig *sig = (CV_C13InlineeLinesSig *)(first + read_off);
|
||||
read_off += sizeof(*sig);
|
||||
|
||||
// rjf: read source lines
|
||||
for(;read_off + sizeof(CV_C13InlineeSourceLineHeader) <= read_off_opl;)
|
||||
{
|
||||
// rjf: read next header
|
||||
CV_C13InlineeSourceLineHeader *hdr = (CV_C13InlineeSourceLineHeader *)(first + read_off);
|
||||
read_off += sizeof(*hdr);
|
||||
|
||||
// extract top level info
|
||||
U32 sec_idx = hdr->sec;
|
||||
B32 has_cols = !!(hdr->flags & CV_C13_SubSecLinesFlag_HasColumns);
|
||||
U64 secrel_off = hdr->sec_off;
|
||||
U64 secrel_opl = secrel_off + hdr->len;
|
||||
U64 sec_base_off = sections->sections[sec_idx - 1].voff;
|
||||
|
||||
// rjf: bad section index -> skip
|
||||
if(sec_idx < 1 || sections->count < sec_idx)
|
||||
// rjf: file_off -> file_name
|
||||
String8 file_name = {0};
|
||||
if(hdr->file_off + sizeof(CV_C13Checksum) <= file_chksms->size)
|
||||
{
|
||||
continue;
|
||||
CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off);
|
||||
U32 name_off = checksum->name_off;
|
||||
file_name = pdb_strtbl_string_from_off(strtbl, name_off);
|
||||
}
|
||||
|
||||
// read files
|
||||
for(;read_off+sizeof(CV_C13_File) <= read_off_opl;)
|
||||
// rjf: parse extra files
|
||||
U32 extra_file_count = 0;
|
||||
U32 *extra_files = 0;
|
||||
if(*sig == CV_C13InlineeLinesSig_EXTRA_FILES && read_off+sizeof(U32) <= read_off_opl)
|
||||
{
|
||||
// rjf: grab next file header
|
||||
CV_C13_File *file = (CV_C13_File*)(first + read_off);
|
||||
U32 file_off = file->file_off;
|
||||
U32 line_count_unclamped = file->num_lines;
|
||||
U32 block_size = file->block_size;
|
||||
|
||||
// file_name from file_off
|
||||
String8 file_name = {0};
|
||||
if (file_off + sizeof(CV_C13_Checksum) <= file_chksms->size){
|
||||
CV_C13_Checksum *checksum = (CV_C13_Checksum*)(c13_data.str + file_chksms->off + file_off);
|
||||
U32 name_off = checksum->name_off;
|
||||
file_name = pdb_strtbl_string_from_off(strtbl, name_off);
|
||||
}
|
||||
|
||||
// array layouts
|
||||
U32 line_item_size = sizeof(CV_C13_Line);
|
||||
if (has_cols){
|
||||
line_item_size += sizeof(CV_C13_Column);
|
||||
}
|
||||
|
||||
U32 line_array_off = read_off + sizeof(*file);
|
||||
U32 line_count_max = (read_off_opl - line_array_off) / line_item_size;
|
||||
U32 line_count = ClampTop(line_count_unclamped, line_count_max);
|
||||
|
||||
U32 col_array_off = line_array_off + line_count*sizeof(CV_C13_Line);
|
||||
|
||||
// parse lines
|
||||
U64 *voffs = push_array_no_zero(arena, U64, line_count + 1);
|
||||
U32 *line_nums = push_array_no_zero(arena, U32, line_count);
|
||||
|
||||
{
|
||||
CV_C13_Line *line_ptr = (CV_C13_Line*)(first + line_array_off);
|
||||
CV_C13_Line *line_opl = line_ptr + line_count;
|
||||
|
||||
// TODO(allen): check order correctness here
|
||||
|
||||
U32 i = 0;
|
||||
for (; line_ptr < line_opl; line_ptr += 1, i += 1){
|
||||
voffs[i] = line_ptr->off + secrel_off + sec_base_off;
|
||||
line_nums[i] = CV_C13_LineFlags_ExtractLineNumber(line_ptr->flags);
|
||||
}
|
||||
voffs[i] = secrel_opl + sec_base_off;
|
||||
}
|
||||
|
||||
// emit parsed lines
|
||||
CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1);
|
||||
CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v;
|
||||
lines_parsed->sec_idx = sec_idx;
|
||||
lines_parsed->file_off = file_off;
|
||||
lines_parsed->secrel_base_off = secrel_off;
|
||||
lines_parsed->file_name = file_name;
|
||||
lines_parsed->voffs = voffs;
|
||||
lines_parsed->line_nums = line_nums;
|
||||
lines_parsed->line_count = line_count;
|
||||
SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node);
|
||||
|
||||
// rjf: advance
|
||||
read_off += sizeof(*file);
|
||||
read_off += line_item_size*line_count;
|
||||
U32 *extra_file_count_ptr = (U32 *)(first + read_off);
|
||||
read_off += sizeof(*extra_file_count_ptr);
|
||||
U32 max_extra_file_count = (read_off_opl-read_off)/sizeof(U32);
|
||||
extra_file_count = Min(*extra_file_count_ptr, max_extra_file_count);
|
||||
extra_files = (U32 *)(first + read_off);
|
||||
read_off += sizeof(*extra_files)*extra_file_count;
|
||||
}
|
||||
|
||||
// rjf: push node for this inlinee lines parsed into this subsection's list
|
||||
CV_C13InlineeLinesParsedNode *n = push_array(arena, CV_C13InlineeLinesParsedNode, 1);
|
||||
SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n);
|
||||
n->v.inlinee = hdr->inlinee;
|
||||
n->v.file_name = file_name;
|
||||
n->v.first_source_ln = hdr->first_source_ln;
|
||||
n->v.extra_file_count = extra_file_count;
|
||||
n->v.extra_files = extra_files;
|
||||
|
||||
// rjf: push node into inlinee parse hash table
|
||||
U64 hash = cv_hash_from_item_id(hdr->inlinee);
|
||||
U64 slot_idx = hash%inlinee_lines_parsed_slots_count;
|
||||
SLLStackPush_N(inlinee_lines_parsed_slots[slot_idx], n, hash_next);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
// convert to result
|
||||
//////////////////////////////
|
||||
//- rjf: fill output
|
||||
//
|
||||
CV_C13Parsed *result = push_array(arena, CV_C13Parsed, 1);
|
||||
result->first_sub_section = first;
|
||||
result->last_sub_section = last;
|
||||
result->sub_section_count = count;
|
||||
result->file_chksms_sub_section = file_chksms;
|
||||
|
||||
result->inlinee_lines_parsed_slots = inlinee_lines_parsed_slots;
|
||||
result->inlinee_lines_parsed_slots_count = inlinee_lines_parsed_slots_count;
|
||||
ProfEnd();
|
||||
|
||||
return(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user