mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
simplified dwarf parsing checkpoint: pull out form value reading, line table header parsing
This commit is contained in:
+449
-145
@@ -239,11 +239,176 @@ dw2_abbrev_map_from_data(Arena *arena, String8 data, U64 off)
|
||||
return map;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Form Value Parsing
|
||||
|
||||
internal U64
|
||||
dw2_read_form_val(DW2_ParseCtx *ctx, String8 data, U64 off, DW_FormKind form_kind, U64 implicit_const, DW2_FormVal *out)
|
||||
{
|
||||
U64 start_off = off;
|
||||
DW2_FormVal val = {0};
|
||||
{
|
||||
U64 bytes_to_read = 0;
|
||||
switch(form_kind)
|
||||
{
|
||||
//- rjf: no-ops
|
||||
default:
|
||||
case DW_Form_Indirect:
|
||||
case DW_Form_Null:
|
||||
{}break;
|
||||
|
||||
//- rjf: 1-byte uint reads
|
||||
case DW_Form_Ref1:
|
||||
case DW_Form_Data1:
|
||||
case DW_Form_Flag:
|
||||
case DW_Form_Strx1:
|
||||
case DW_Form_Addrx1:
|
||||
bytes_to_read = 1; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 2-byte uint reads
|
||||
case DW_Form_Ref2:
|
||||
case DW_Form_Data2:
|
||||
case DW_Form_Strx2:
|
||||
case DW_Form_Addrx2:
|
||||
bytes_to_read = 2; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 3-byte uint reads
|
||||
case DW_Form_Strx3:
|
||||
case DW_Form_Addrx3:
|
||||
bytes_to_read = 3; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 4-byte uint reads
|
||||
case DW_Form_Data4:
|
||||
case DW_Form_Ref4:
|
||||
case DW_Form_RefSup4:
|
||||
case DW_Form_Strx4:
|
||||
case DW_Form_Addrx4:
|
||||
bytes_to_read = 4; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 8-byte uint reads
|
||||
case DW_Form_Data8:
|
||||
case DW_Form_Ref8:
|
||||
case DW_Form_RefSig8:
|
||||
case DW_Form_RefSup8:
|
||||
bytes_to_read = 8; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 16-byte uint reads
|
||||
case DW_Form_Data16:
|
||||
bytes_to_read = 16; goto read_fixed_uint;
|
||||
|
||||
//- rjf: address-sized reads
|
||||
case DW_Form_Addr:
|
||||
bytes_to_read = ctx->addr_size; goto read_fixed_uint;
|
||||
|
||||
//- rjf: format-defined-size reads
|
||||
case DW_Form_RefAddr:
|
||||
case DW_Form_SecOffset:
|
||||
case DW_Form_LineStrp:
|
||||
case DW_Form_Strp:
|
||||
case DW_Form_StrpSup:
|
||||
bytes_to_read = dw_size_from_format(ctx->format); goto read_fixed_uint;
|
||||
|
||||
//- rjf: fixed-size uint reads
|
||||
read_fixed_uint:
|
||||
{
|
||||
off += str8_deserial_read(data, off, &val.u128.u64[0], bytes_to_read, bytes_to_read);
|
||||
}break;
|
||||
|
||||
//- rjf: uleb128 reads
|
||||
case DW_Form_UData:
|
||||
case DW_Form_RefUData:
|
||||
case DW_Form_Strx:
|
||||
case DW_Form_Addrx:
|
||||
case DW_Form_LocListx:
|
||||
case DW_Form_RngListx:
|
||||
{
|
||||
off += str8_deserial_read_uleb128(data, off, &val.u128.u64[0]);
|
||||
}break;
|
||||
|
||||
//- rjf: sleb128 reads
|
||||
case DW_Form_SData:
|
||||
{
|
||||
off += str8_deserial_read_sleb128(data, off, &val.u128.u64[0]);
|
||||
}break;
|
||||
|
||||
//- rjf: fixed-size uint reads / skips
|
||||
case DW_Form_Block1: bytes_to_read = 1; goto read_fixed_uint_and_skip;
|
||||
case DW_Form_Block2: bytes_to_read = 2; goto read_fixed_uint_and_skip;
|
||||
case DW_Form_Block4: bytes_to_read = 4; goto read_fixed_uint_and_skip;
|
||||
read_fixed_uint_and_skip:
|
||||
{
|
||||
U64 size = 0;
|
||||
U64 og_read_off = off;
|
||||
off += str8_deserial_read(data, off, &size, bytes_to_read, bytes_to_read);
|
||||
val.u128.u64[0] = size;
|
||||
val.u128.u64[1] = og_read_off;
|
||||
off += size;
|
||||
}break;
|
||||
|
||||
//- rjf: uleb128 read & skip
|
||||
case DW_Form_Block:
|
||||
{
|
||||
U64 size = 0;
|
||||
U64 og_read_off = off;
|
||||
off += str8_deserial_read_uleb128(data, off, &size);
|
||||
val.u128.u64[0] = size;
|
||||
val.u128.u64[1] = og_read_off;
|
||||
off += size;
|
||||
}break;
|
||||
|
||||
//- rjf: strings
|
||||
case DW_Form_String:
|
||||
{
|
||||
String8 string = {0};
|
||||
U64 og_read_off = off;
|
||||
off += str8_deserial_read_cstr(data, off, &string);
|
||||
val.u128.u64[0] = og_read_off;
|
||||
val.u128.u64[1] = og_read_off + string.size - 1;
|
||||
}break;
|
||||
|
||||
//- rjf: implicit constants (no reading in .debug_info; value comes from .debug_abbrev)
|
||||
case DW_Form_ImplicitConst:
|
||||
{
|
||||
val.u128.u64[0] = implicit_const;
|
||||
}break;
|
||||
|
||||
//- rjf: exprloc
|
||||
case DW_Form_ExprLoc:
|
||||
{
|
||||
U64 size = 0;
|
||||
U64 og_read_off = off;
|
||||
U64 bytes_read = str8_deserial_read_uleb128(data, off, &size);
|
||||
val.u128.u64[0] = og_read_off + bytes_read;
|
||||
val.u128.u64[1] = size;
|
||||
off += bytes_read;
|
||||
}break;
|
||||
|
||||
//- rjf: flag present
|
||||
case DW_Form_FlagPresent:
|
||||
{
|
||||
val.u128.u64[0] = 1;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
*out = val;
|
||||
U64 bytes_read = (off - start_off);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
internal String8
|
||||
dw2_string_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal val)
|
||||
{
|
||||
String8 section_data = ctx->raw->sec[val.section_kind].data;
|
||||
Rng1U64 range = r1u64(val.u128.u64[0], val.u128.u64[1]);
|
||||
String8 string = str8_substr(section_data, range);
|
||||
return string;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tag Parsing
|
||||
|
||||
internal U64
|
||||
dw2_read_tag(Arena *arena, DW2_TagParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out)
|
||||
dw2_read_tag(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out)
|
||||
{
|
||||
U64 start_off = off;
|
||||
|
||||
@@ -272,7 +437,7 @@ dw2_read_tag(Arena *arena, DW2_TagParseCtx *ctx, String8 data, U64 off, DW2_Tag
|
||||
U8 has_children = 0;
|
||||
U64 attrib_abbrev_read_off = 0;
|
||||
{
|
||||
String8 abbrev_data = ctx->abbrev_data;
|
||||
String8 abbrev_data = ctx->raw->sec[DW_Section_Abbrev].data;
|
||||
U64 abbrev_read_off = abbrev_off;
|
||||
U64 id = 0;
|
||||
abbrev_read_off += str8_deserial_read_uleb128(abbrev_data, abbrev_read_off, &id);
|
||||
@@ -288,7 +453,7 @@ dw2_read_tag(Arena *arena, DW2_TagParseCtx *ctx, String8 data, U64 off, DW2_Tag
|
||||
DW2_AttribList attribs = {0};
|
||||
if(abbrev_id != 0)
|
||||
{
|
||||
String8 abbrev_data = ctx->abbrev_data;
|
||||
String8 abbrev_data = ctx->raw->sec[DW_Section_Abbrev].data;
|
||||
U64 abbrev_read_off = attrib_abbrev_read_off;
|
||||
for(;;)
|
||||
{
|
||||
@@ -312,150 +477,10 @@ dw2_read_tag(Arena *arena, DW2_TagParseCtx *ctx, String8 data, U64 off, DW2_Tag
|
||||
}
|
||||
|
||||
// rjf: read attribute's value from .debug_info
|
||||
DW2_AttribVal val = {0};
|
||||
DW2_FormVal val = {0};
|
||||
if(attrib_kind != 0)
|
||||
{
|
||||
U64 bytes_to_read = 0;
|
||||
switch(attrib_form_kind)
|
||||
{
|
||||
//- rjf: no-ops
|
||||
default:
|
||||
case DW_Form_Indirect:
|
||||
case DW_Form_Null:
|
||||
{}break;
|
||||
|
||||
//- rjf: 1-byte uint reads
|
||||
case DW_Form_Ref1:
|
||||
case DW_Form_Data1:
|
||||
case DW_Form_Flag:
|
||||
case DW_Form_Strx1:
|
||||
case DW_Form_Addrx1:
|
||||
bytes_to_read = 1; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 2-byte uint reads
|
||||
case DW_Form_Ref2:
|
||||
case DW_Form_Data2:
|
||||
case DW_Form_Strx2:
|
||||
case DW_Form_Addrx2:
|
||||
bytes_to_read = 2; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 3-byte uint reads
|
||||
case DW_Form_Strx3:
|
||||
case DW_Form_Addrx3:
|
||||
bytes_to_read = 3; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 4-byte uint reads
|
||||
case DW_Form_Data4:
|
||||
case DW_Form_Ref4:
|
||||
case DW_Form_RefSup4:
|
||||
case DW_Form_Strx4:
|
||||
case DW_Form_Addrx4:
|
||||
bytes_to_read = 4; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 8-byte uint reads
|
||||
case DW_Form_Data8:
|
||||
case DW_Form_Ref8:
|
||||
case DW_Form_RefSig8:
|
||||
case DW_Form_RefSup8:
|
||||
bytes_to_read = 8; goto read_fixed_uint;
|
||||
|
||||
//- rjf: 16-byte uint reads
|
||||
case DW_Form_Data16:
|
||||
bytes_to_read = 16; goto read_fixed_uint;
|
||||
|
||||
//- rjf: address-sized reads
|
||||
case DW_Form_Addr:
|
||||
bytes_to_read = ctx->addr_size; goto read_fixed_uint;
|
||||
|
||||
//- rjf: format-defined-size reads
|
||||
case DW_Form_RefAddr:
|
||||
case DW_Form_SecOffset:
|
||||
case DW_Form_LineStrp:
|
||||
case DW_Form_Strp:
|
||||
case DW_Form_StrpSup:
|
||||
bytes_to_read = dw_size_from_format(ctx->format); goto read_fixed_uint;
|
||||
|
||||
//- rjf: fixed-size uint reads
|
||||
read_fixed_uint:
|
||||
{
|
||||
off += str8_deserial_read(data, off, &val.u128.u64[0], bytes_to_read, bytes_to_read);
|
||||
}break;
|
||||
|
||||
//- rjf: uleb128 reads
|
||||
case DW_Form_UData:
|
||||
case DW_Form_RefUData:
|
||||
case DW_Form_Strx:
|
||||
case DW_Form_Addrx:
|
||||
case DW_Form_LocListx:
|
||||
case DW_Form_RngListx:
|
||||
{
|
||||
off += str8_deserial_read_uleb128(data, off, &val.u128.u64[0]);
|
||||
}break;
|
||||
|
||||
//- rjf: sleb128 reads
|
||||
case DW_Form_SData:
|
||||
{
|
||||
off += str8_deserial_read_sleb128(data, off, &val.u128.u64[0]);
|
||||
}break;
|
||||
|
||||
//- rjf: fixed-size uint reads / skips
|
||||
case DW_Form_Block1: bytes_to_read = 1; goto read_fixed_uint_and_skip;
|
||||
case DW_Form_Block2: bytes_to_read = 2; goto read_fixed_uint_and_skip;
|
||||
case DW_Form_Block4: bytes_to_read = 4; goto read_fixed_uint_and_skip;
|
||||
read_fixed_uint_and_skip:
|
||||
{
|
||||
U64 size = 0;
|
||||
U64 og_read_off = off;
|
||||
off += str8_deserial_read(data, off, &size, bytes_to_read, bytes_to_read);
|
||||
val.u128.u64[0] = size;
|
||||
val.u128.u64[1] = og_read_off;
|
||||
off += size;
|
||||
}break;
|
||||
|
||||
//- rjf: uleb128 read & skip
|
||||
case DW_Form_Block:
|
||||
{
|
||||
U64 size = 0;
|
||||
U64 og_read_off = off;
|
||||
off += str8_deserial_read_uleb128(data, off, &size);
|
||||
val.u128.u64[0] = size;
|
||||
val.u128.u64[1] = og_read_off;
|
||||
off += size;
|
||||
}break;
|
||||
|
||||
//- rjf: strings
|
||||
case DW_Form_String:
|
||||
{
|
||||
String8 string = {0};
|
||||
U64 og_read_off = off;
|
||||
off += str8_deserial_read_cstr(data, off, &string);
|
||||
val.u128.u64[0] = og_read_off;
|
||||
val.u128.u64[1] = og_read_off + string.size - 1;
|
||||
}break;
|
||||
|
||||
//- rjf: implicit constants (no reading in .debug_info; value comes from .debug_abbrev)
|
||||
case DW_Form_ImplicitConst:
|
||||
{
|
||||
val.u128.u64[0] = implicit_const;
|
||||
}break;
|
||||
|
||||
//- rjf: exprloc
|
||||
case DW_Form_ExprLoc:
|
||||
{
|
||||
U64 size = 0;
|
||||
U64 og_read_off = off;
|
||||
U64 bytes_read = str8_deserial_read_uleb128(data, off, &size);
|
||||
val.u128.u64[0] = og_read_off + bytes_read;
|
||||
val.u128.u64[1] = size;
|
||||
off += bytes_read;
|
||||
}break;
|
||||
|
||||
//- rjf: flag present
|
||||
case DW_Form_FlagPresent:
|
||||
{
|
||||
val.u128.u64[0] = 1;
|
||||
}break;
|
||||
}
|
||||
off += dw2_read_form_val(ctx, data, off, attrib_form_kind, implicit_const, &val);
|
||||
}
|
||||
|
||||
// rjf: push
|
||||
@@ -485,3 +510,282 @@ dw2_read_tag(Arena *arena, DW2_TagParseCtx *ctx, String8 data, U64 off, DW2_Tag
|
||||
U64 bytes_read = (off - start_off);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Line Table Parsing
|
||||
|
||||
internal U64
|
||||
dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_LineTableHeader *out)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
U64 start_off = 0;
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: read unit length
|
||||
//
|
||||
U64 unit_length = 0;
|
||||
DW_Format format = DW_Format_32Bit;
|
||||
off += dw2_read_initial_length(data, off, &unit_length, &format);
|
||||
U64 off_opl = off + unit_length;
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: read version
|
||||
//
|
||||
DW_Version version = DW_Version_Null;
|
||||
off += str8_deserial_read_struct(data, off, &version);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: read address / segment selector sizes
|
||||
//
|
||||
U8 addr_size = 0;
|
||||
U8 segment_selector_size = 0;
|
||||
switch(version)
|
||||
{
|
||||
// NOTE(rjf): pre-dwarf5: assume from context
|
||||
default:
|
||||
{
|
||||
addr_size = ctx->addr_size;
|
||||
}break;
|
||||
|
||||
// NOTE(rjf): @dwarf5 read address / segment selector sizes explicitly
|
||||
case DW_Version_5:
|
||||
{
|
||||
off += str8_deserial_read_struct(data, off, &addr_size);
|
||||
off += str8_deserial_read_struct(data, off, &segment_selector_size);
|
||||
}break;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: read all remaining flat header properties
|
||||
//
|
||||
U64 header_length = 0;
|
||||
U8 min_inst_length = 0;
|
||||
U8 max_ops_per_inst = 1;
|
||||
U8 default_is_stmt = 0;
|
||||
S8 line_base = 0;
|
||||
U8 line_range = 0;
|
||||
U8 opcode_base = 0;
|
||||
{
|
||||
off += dw2_read_fmt_u64(data, off, format, &header_length);
|
||||
off += str8_deserial_read_struct(data, off, &min_inst_length);
|
||||
off += str8_deserial_read_struct(data, off, &max_ops_per_inst);
|
||||
off += str8_deserial_read_struct(data, off, &default_is_stmt);
|
||||
off += str8_deserial_read_struct(data, off, &line_base);
|
||||
off += str8_deserial_read_struct(data, off, &line_range);
|
||||
off += str8_deserial_read_struct(data, off, &opcode_base);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: read opcode lengths
|
||||
//
|
||||
U64 opcode_lengths_count = (opcode_base > 0 ? opcode_base - 1 : 0);
|
||||
U8 *opcode_lengths = 0;
|
||||
if(opcode_lengths_count > 0)
|
||||
{
|
||||
opcode_lengths = str8_skip(data, off).str;
|
||||
off += sizeof(opcode_lengths[0]) * opcode_lengths_count;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: read directory / file tables
|
||||
//
|
||||
DW2_LineTableFileArray dirs = {0};
|
||||
DW2_LineTableFileArray files = {0};
|
||||
switch(version)
|
||||
{
|
||||
////////////////////////////
|
||||
//- rjf: pre-dwarf5: simple(r) well-defined format... still ulebs everywhere but oh well...
|
||||
// just wait until the next case...
|
||||
//
|
||||
default:
|
||||
{
|
||||
//- rjf: gather directories
|
||||
DW2_LineTableFileList dir_list = {0};
|
||||
{
|
||||
// rjf: push compile directory as first list element, always
|
||||
{
|
||||
DW2_LineTableFileNode *n = push_array(scratch.arena, DW2_LineTableFileNode, 1);
|
||||
SLLQueuePush(dir_list.first, dir_list.last, n);
|
||||
dir_list.count += 1;
|
||||
n->v.file_name = ctx->unit_dir;
|
||||
}
|
||||
|
||||
// rjf: gather additional directories
|
||||
for(;off < off_opl;)
|
||||
{
|
||||
String8 dir = {0};
|
||||
off += str8_deserial_read_cstr(data, off, &dir);
|
||||
if(dir.size != 0)
|
||||
{
|
||||
DW2_LineTableFileNode *n = push_array(scratch.arena, DW2_LineTableFileNode, 1);
|
||||
SLLQueuePush(dir_list.first, dir_list.last, n);
|
||||
dir_list.count += 1;
|
||||
n->v.file_name = dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: gather files
|
||||
DW2_LineTableFileList file_list = {0};
|
||||
{
|
||||
// rjf: push main compilation unit file as first list element, always
|
||||
{
|
||||
DW2_LineTableFileNode *n = push_array(scratch.arena, DW2_LineTableFileNode, 1);
|
||||
SLLQueuePush(file_list.first, file_list.last, n);
|
||||
file_list.count += 1;
|
||||
n->v.file_name = ctx->unit_file;
|
||||
}
|
||||
|
||||
// rjf: gather additional files
|
||||
for(;off < off_opl;)
|
||||
{
|
||||
String8 file_name = {0};
|
||||
U64 dir_idx = 0;
|
||||
U64 modify_time = 0;
|
||||
U64 file_size = 0;
|
||||
off += str8_deserial_read_cstr(data, off, &file_name);
|
||||
off += str8_deserial_read_uleb128(data, off, &dir_idx);
|
||||
off += str8_deserial_read_uleb128(data, off, &modify_time);
|
||||
off += str8_deserial_read_uleb128(data, off, &file_size);
|
||||
if(file_name.size != 0)
|
||||
{
|
||||
DW2_LineTableFileNode *n = push_array(scratch.arena, DW2_LineTableFileNode, 1);
|
||||
SLLQueuePush(file_list.first, file_list.last, n);
|
||||
file_list.count += 1;
|
||||
n->v.file_name = file_name;
|
||||
n->v.dir_idx = dir_idx;
|
||||
n->v.modify_time = modify_time;
|
||||
n->v.file_size = file_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: flatten
|
||||
{
|
||||
dirs.count = dir_list.count;
|
||||
dirs.v = push_array(arena, DW2_LineTableFile, dirs.count);
|
||||
files.count = file_list.count;
|
||||
files.v = push_array(arena, DW2_LineTableFile, files.count);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for EachNode(n, DW2_LineTableFileNode, dir_list.first)
|
||||
{
|
||||
MemoryCopyStruct(&dirs.v[idx], &n->v);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
U64 idx = 0;
|
||||
for EachNode(n, DW2_LineTableFileNode, file_list.first)
|
||||
{
|
||||
MemoryCopyStruct(&files.v[idx], &n->v);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: @dwarf5: another VM! d'oh. :(
|
||||
//
|
||||
case DW_Version_5:
|
||||
{
|
||||
//- rjf: read directory & file tables
|
||||
for(B32 files = 0, dirs = 1; files <= 1; files = 1, dirs = 0)
|
||||
{
|
||||
// rjf: read header
|
||||
U8 entry_formats_count = 0;
|
||||
off += str8_deserial_read_struct(data, off, &entry_formats_count);
|
||||
U64 *entry_formats = push_array(scratch.arena, U64, entry_formats_count*2);
|
||||
for EachIndex(idx, entry_formats_count)
|
||||
{
|
||||
off += str8_deserial_read_uleb128(data, off, &entry_formats[idx]);
|
||||
}
|
||||
U64 table_count = 0;
|
||||
off += str8_deserial_read_uleb128(data, off, &table_count);
|
||||
|
||||
// rjf: read all table entries
|
||||
DW2_LineTableFileArray table = {0};
|
||||
table.count = table_count;
|
||||
table.v = push_array(arena, DW2_LineTableFile, table.count);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for(;off < off_opl && idx < table.count; idx += 1)
|
||||
{
|
||||
DW2_LineTableFile *entry_out = &table.v[idx];
|
||||
for(U64 entry_format_idx = 0; entry_format_idx < entry_formats_count; entry_format_idx += 1)
|
||||
{
|
||||
DW_LNCT lnct = (DW_LNCT)entry_formats[entry_format_idx*2 + 0];
|
||||
DW_FormKind form_kind = (DW_FormKind)entry_formats[entry_format_idx*2 + 1];
|
||||
DW2_FormVal form_val = {0};
|
||||
off += dw2_read_form_val(ctx, data, off, form_kind, 0, &form_val);
|
||||
switch(lnct)
|
||||
{
|
||||
default:
|
||||
{
|
||||
log_infof("DWARF LNCT encoding not currently supported (0x%I64x).\n", (U64)lnct);
|
||||
}break;
|
||||
case DW_LNCT_Path:
|
||||
{
|
||||
entry_out->file_name = dw2_string_from_form_val(ctx, form_val);
|
||||
}break;
|
||||
case DW_LNCT_DirectoryIndex:
|
||||
{
|
||||
entry_out->dir_idx = form_val.u128.u64[0];
|
||||
}break;
|
||||
case DW_LNCT_TimeStamp:
|
||||
{
|
||||
entry_out->modify_time = form_val.u128.u64[0];
|
||||
}break;
|
||||
case DW_LNCT_Size:
|
||||
{
|
||||
entry_out->file_size = form_val.u128.u64[0];
|
||||
}break;
|
||||
case DW_LNCT_MD5:
|
||||
{
|
||||
entry_out->md5.u128 = form_val.u128;
|
||||
}break;
|
||||
case DW_LNCT_LLVM_Source:
|
||||
{
|
||||
entry_out->source = dw2_string_from_form_val(ctx, form_val);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}break;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: fill output
|
||||
//
|
||||
if(out)
|
||||
{
|
||||
out->unit_length = unit_length;
|
||||
out->format = format;
|
||||
out->version = version;
|
||||
out->addr_size = addr_size;
|
||||
out->segment_selector_size = segment_selector_size;
|
||||
out->header_length = header_length;
|
||||
out->min_inst_length = min_inst_length;
|
||||
out->max_ops_per_inst = max_ops_per_inst;
|
||||
out->default_is_stmt = default_is_stmt;
|
||||
out->line_base = line_base;
|
||||
out->line_range = line_range;
|
||||
out->opcode_base = opcode_base;
|
||||
out->opcode_lengths_count = opcode_lengths_count;
|
||||
out->opcode_lengths = opcode_lengths;
|
||||
out->dirs = dirs;
|
||||
out->files = files;
|
||||
}
|
||||
|
||||
U64 bytes_read = (off - start_off);
|
||||
scratch_end(scratch);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
@@ -37,23 +37,27 @@ struct DW2_AbbrevMap
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tag Parsing Context
|
||||
//~ rjf: Parsing Context Bundle
|
||||
|
||||
typedef struct DW2_TagParseCtx DW2_TagParseCtx;
|
||||
struct DW2_TagParseCtx
|
||||
typedef struct DW2_ParseCtx DW2_ParseCtx;
|
||||
struct DW2_ParseCtx
|
||||
{
|
||||
DW_Raw *raw;
|
||||
// NOTE(rjf): all subsequent fields optional - top-level code fills out whatever
|
||||
// it can from context.
|
||||
DW_Version version;
|
||||
DW_Format format;
|
||||
U64 addr_size;
|
||||
String8 abbrev_data;
|
||||
DW2_AbbrevMap *abbrev_map;
|
||||
String8 unit_dir;
|
||||
String8 unit_file;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tag Attributes
|
||||
|
||||
typedef struct DW2_AttribVal DW2_AttribVal;
|
||||
struct DW2_AttribVal
|
||||
typedef struct DW2_FormVal DW2_FormVal;
|
||||
struct DW2_FormVal
|
||||
{
|
||||
DW_SectionKind section_kind;
|
||||
U128 u128;
|
||||
@@ -64,7 +68,7 @@ struct DW2_Attrib
|
||||
{
|
||||
DW_AttribKind attrib_kind;
|
||||
DW_FormKind form_kind;
|
||||
DW2_AttribVal val;
|
||||
DW2_FormVal val;
|
||||
};
|
||||
|
||||
typedef struct DW2_AttribNode DW2_AttribNode;
|
||||
@@ -93,6 +97,63 @@ struct DW2_Tag
|
||||
DW2_AttribList attribs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Line Info
|
||||
|
||||
typedef struct DW2_LineTableFile DW2_LineTableFile;
|
||||
struct DW2_LineTableFile
|
||||
{
|
||||
String8 file_name;
|
||||
U64 dir_idx;
|
||||
U64 modify_time;
|
||||
U64 file_size;
|
||||
MD5 md5;
|
||||
String8 source;
|
||||
};
|
||||
|
||||
typedef struct DW2_LineTableFileNode DW2_LineTableFileNode;
|
||||
struct DW2_LineTableFileNode
|
||||
{
|
||||
DW2_LineTableFileNode *next;
|
||||
DW2_LineTableFile v;
|
||||
};
|
||||
|
||||
typedef struct DW2_LineTableFileList DW2_LineTableFileList;
|
||||
struct DW2_LineTableFileList
|
||||
{
|
||||
DW2_LineTableFileNode *first;
|
||||
DW2_LineTableFileNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct DW2_LineTableFileArray DW2_LineTableFileArray;
|
||||
struct DW2_LineTableFileArray
|
||||
{
|
||||
DW2_LineTableFile *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct DW2_LineTableHeader DW2_LineTableHeader;
|
||||
struct DW2_LineTableHeader
|
||||
{
|
||||
U64 unit_length;
|
||||
DW_Format format;
|
||||
DW_Version version;
|
||||
U8 addr_size;
|
||||
U8 segment_selector_size;
|
||||
U64 header_length;
|
||||
U8 min_inst_length;
|
||||
U8 max_ops_per_inst;
|
||||
U8 default_is_stmt;
|
||||
S8 line_base;
|
||||
U8 line_range;
|
||||
U8 opcode_base;
|
||||
U64 opcode_lengths_count;
|
||||
U8 *opcode_lengths;
|
||||
DW2_LineTableFileArray dirs;
|
||||
DW2_LineTableFileArray files;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Parsing Helpers
|
||||
|
||||
@@ -109,9 +170,20 @@ internal U64 dw2_read_unit_header(String8 data, U64 off, DW2_UnitHeader *out);
|
||||
|
||||
internal DW2_AbbrevMap dw2_abbrev_map_from_data(Arena *arena, String8 data, U64 off);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Form Value Parsing
|
||||
|
||||
internal U64 dw2_read_form_val(DW2_ParseCtx *ctx, String8 data, U64 off, DW_FormKind form_kind, U64 implicit_const, DW2_FormVal *out);
|
||||
internal String8 dw2_string_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal val);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tag Parsing
|
||||
|
||||
internal U64 dw2_read_tag(Arena *arena, DW2_TagParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out);
|
||||
internal U64 dw2_read_tag(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Line Table Parsing
|
||||
|
||||
internal U64 dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_LineTableHeader *out);
|
||||
|
||||
#endif // DWARF_PARSE_2_H
|
||||
|
||||
@@ -257,24 +257,24 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
lane_sync();
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: build per-unit tag parsing contexts
|
||||
//- rjf: build per-unit parsing contexts
|
||||
//
|
||||
DW2_TagParseCtx *unit_tag_parse_ctxs = 0;
|
||||
DW2_ParseCtx *unit_parse_ctxs = 0;
|
||||
{
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
unit_tag_parse_ctxs = push_array(scratch.arena, DW2_TagParseCtx, unit_count);
|
||||
unit_parse_ctxs = push_array(scratch.arena, DW2_ParseCtx, unit_count);
|
||||
}
|
||||
lane_sync_u64(&unit_tag_parse_ctxs, 0);
|
||||
lane_sync_u64(&unit_parse_ctxs, 0);
|
||||
Rng1U64 range = lane_range(unit_count);
|
||||
for EachInRange(unit_idx, range)
|
||||
{
|
||||
DW2_UnitHeader *hdr = &unit_headers[unit_idx];
|
||||
DW2_TagParseCtx *ctx = &unit_tag_parse_ctxs[unit_idx];
|
||||
DW2_ParseCtx *ctx = &unit_parse_ctxs[unit_idx];
|
||||
ctx->raw = raw;
|
||||
ctx->version = hdr->version;
|
||||
ctx->format = hdr->format;
|
||||
ctx->addr_size = hdr->addr_size;
|
||||
ctx->abbrev_data = raw->sec[DW_Section_Abbrev].data;
|
||||
ctx->abbrev_map = abbrev_map_from_unit_idx_table[unit_idx];
|
||||
}
|
||||
}
|
||||
@@ -293,7 +293,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
||||
Rng1U64 range = lane_range(unit_count);
|
||||
for EachInRange(unit_idx, range)
|
||||
{
|
||||
dw2_read_tag(scratch.arena, &unit_tag_parse_ctxs[unit_idx], raw->sec[DW_Section_Info].data, unit_info_tag_ranges[unit_idx].min, &unit_root_tags[unit_idx]);
|
||||
dw2_read_tag(scratch.arena, &unit_parse_ctxs[unit_idx], raw->sec[DW_Section_Info].data, unit_info_tag_ranges[unit_idx].min, &unit_root_tags[unit_idx]);
|
||||
}
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
Reference in New Issue
Block a user