mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
d2r2: .debug_aranges parsing / unit conversion; .debug_ranges parsing
This commit is contained in:
@@ -339,9 +339,9 @@ struct Rng1U64Node
|
|||||||
typedef struct Rng1U64List Rng1U64List;
|
typedef struct Rng1U64List Rng1U64List;
|
||||||
struct Rng1U64List
|
struct Rng1U64List
|
||||||
{
|
{
|
||||||
U64 count;
|
|
||||||
Rng1U64Node *first;
|
Rng1U64Node *first;
|
||||||
Rng1U64Node *last;
|
Rng1U64Node *last;
|
||||||
|
U64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Rng1U64Array Rng1U64Array;
|
typedef struct Rng1U64Array Rng1U64Array;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ typedef struct DW_Section
|
|||||||
{
|
{
|
||||||
String8 name;
|
String8 name;
|
||||||
String8 data;
|
String8 data;
|
||||||
B32 is_dwo;
|
B32 is_dwo;
|
||||||
} DW_Section;
|
} DW_Section;
|
||||||
|
|
||||||
typedef struct DW_Raw
|
typedef struct DW_Raw
|
||||||
|
|||||||
@@ -900,3 +900,65 @@ dw2_read_str_offsets_table(String8 data, U64 off, DW2_StrOffsetsTable *out)
|
|||||||
U64 bytes_read = (off - start_off);
|
U64 bytes_read = (off - start_off);
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Range List Parsing (.debug_rnglists)
|
||||||
|
|
||||||
|
internal Rng1U64List
|
||||||
|
dw2_rnglist_from_form_val(Arena *arena, DW2_ParseCtx *ctx, DW_Raw *raw, DW2_FormVal form_val)
|
||||||
|
{
|
||||||
|
Rng1U64List result = {0};
|
||||||
|
switch((DW_VersionEnum)ctx->version)
|
||||||
|
{
|
||||||
|
case DW_Version_Null:{}break;
|
||||||
|
|
||||||
|
//- rjf: pre-dwarf5
|
||||||
|
case DW_Version_1:
|
||||||
|
case DW_Version_2:
|
||||||
|
case DW_Version_3:
|
||||||
|
case DW_Version_4:
|
||||||
|
{
|
||||||
|
String8 data = raw->sec[DW_Section_Ranges].data;
|
||||||
|
U64 ranges_off = ranges_off = form_val.u128.u64[0];;
|
||||||
|
U64 base_addr = ctx->unit_base_addr;
|
||||||
|
U64 sentinel = (ctx->addr_size == 4 ? max_U32 : max_U64);
|
||||||
|
for(U64 off = ranges_off; off < data.size;)
|
||||||
|
{
|
||||||
|
U64 start_off = off;
|
||||||
|
U64 range_min = 0;
|
||||||
|
U64 range_opl = 0;
|
||||||
|
off += str8_deserial_read(data, off, &range_min, ctx->addr_size, ctx->addr_size);
|
||||||
|
off += str8_deserial_read(data, off, &range_opl, ctx->addr_size, ctx->addr_size);
|
||||||
|
//
|
||||||
|
// NOTE(rjf): interpreting tuples:
|
||||||
|
// [0, 0) -> ending range list
|
||||||
|
// [max_U32/U64, depending on addr size, X) -> set new base address to X
|
||||||
|
// [N, M) -> new [base + N, base + M) range
|
||||||
|
//
|
||||||
|
if(range_min == 0 && range_opl == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(range_min == sentinel)
|
||||||
|
{
|
||||||
|
base_addr = range_opl;
|
||||||
|
}
|
||||||
|
else if(off == start_off)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rng1u64_list_push(arena, &result, r1u64(base_addr + range_min, base_addr + range_opl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
//- rjf: @dwarf5
|
||||||
|
case DW_Version_5:
|
||||||
|
{
|
||||||
|
// TODO(rjf)
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ struct DW2_ParseCtx
|
|||||||
DW_Format format;
|
DW_Format format;
|
||||||
DW_Ext ext;
|
DW_Ext ext;
|
||||||
U64 addr_size;
|
U64 addr_size;
|
||||||
|
U64 unit_base_addr;
|
||||||
DW2_AbbrevMap *abbrev_map;
|
DW2_AbbrevMap *abbrev_map;
|
||||||
DW2_StrOffsetsTable *str_offsets_table;
|
DW2_StrOffsetsTable *str_offsets_table;
|
||||||
String8 unit_dir;
|
String8 unit_dir;
|
||||||
@@ -237,4 +238,9 @@ internal U64 dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8
|
|||||||
|
|
||||||
internal U64 dw2_read_str_offsets_table(String8 data, U64 off, DW2_StrOffsetsTable *out);
|
internal U64 dw2_read_str_offsets_table(String8 data, U64 off, DW2_StrOffsetsTable *out);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Range List Parsing (.debug_rnglists)
|
||||||
|
|
||||||
|
internal Rng1U64List dw2_rnglist_from_form_val(Arena *arena, DW2_ParseCtx *ctx, DW_Raw *raw, DW2_FormVal form_val);
|
||||||
|
|
||||||
#endif // DWARF_PARSE_2_H
|
#endif // DWARF_PARSE_2_H
|
||||||
|
|||||||
+9
-9
@@ -10,22 +10,22 @@
|
|||||||
typedef struct ELF_Shdr64Array ELF_Shdr64Array;
|
typedef struct ELF_Shdr64Array ELF_Shdr64Array;
|
||||||
struct ELF_Shdr64Array
|
struct ELF_Shdr64Array
|
||||||
{
|
{
|
||||||
U64 count;
|
U64 count;
|
||||||
ELF_Shdr64 *v;
|
ELF_Shdr64 *v;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ELF_Phdr64Array ELF_Phdr64Array;
|
typedef struct ELF_Phdr64Array ELF_Phdr64Array;
|
||||||
struct ELF_Phdr64Array
|
struct ELF_Phdr64Array
|
||||||
{
|
{
|
||||||
U64 count;
|
U64 count;
|
||||||
ELF_Phdr64 *v;
|
ELF_Phdr64 *v;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ELF_Bin ELF_Bin;
|
typedef struct ELF_Bin ELF_Bin;
|
||||||
struct ELF_Bin
|
struct ELF_Bin
|
||||||
{
|
{
|
||||||
ELF_Hdr64 hdr;
|
ELF_Hdr64 hdr;
|
||||||
Rng1U64 sh_name_range;
|
Rng1U64 sh_name_range;
|
||||||
ELF_Shdr64Array shdrs;
|
ELF_Shdr64Array shdrs;
|
||||||
ELF_Phdr64Array phdrs;
|
ELF_Phdr64Array phdrs;
|
||||||
};
|
};
|
||||||
@@ -34,30 +34,30 @@ typedef struct ELF_GnuDebugLink ELF_GnuDebugLink;
|
|||||||
struct ELF_GnuDebugLink
|
struct ELF_GnuDebugLink
|
||||||
{
|
{
|
||||||
String8 path;
|
String8 path;
|
||||||
U32 checksum;
|
U32 checksum;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ELF_Note ELF_Note;
|
typedef struct ELF_Note ELF_Note;
|
||||||
struct ELF_Note
|
struct ELF_Note
|
||||||
{
|
{
|
||||||
String8 owner;
|
String8 owner;
|
||||||
ELF_NoteType type;
|
ELF_NoteType type;
|
||||||
String8 desc;
|
String8 desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ELF_NoteNode ELF_NoteNode;
|
typedef struct ELF_NoteNode ELF_NoteNode;
|
||||||
struct ELF_NoteNode
|
struct ELF_NoteNode
|
||||||
{
|
{
|
||||||
ELF_Note v;
|
|
||||||
ELF_NoteNode *next;
|
ELF_NoteNode *next;
|
||||||
|
ELF_Note v;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ELF_NoteList ELF_NoteList;
|
typedef struct ELF_NoteList ELF_NoteList;
|
||||||
struct ELF_NoteList
|
struct ELF_NoteList
|
||||||
{
|
{
|
||||||
U64 count;
|
|
||||||
ELF_NoteNode *first;
|
ELF_NoteNode *first;
|
||||||
ELF_NoteNode *last;
|
ELF_NoteNode *last;
|
||||||
|
U64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
+5
-5
@@ -872,9 +872,9 @@ rb_thread_entry_point(void *p)
|
|||||||
convert_params_2.base_vaddr = elf_base_addr_from_bin(&bin);
|
convert_params_2.base_vaddr = elf_base_addr_from_bin(&bin);
|
||||||
convert_params_2.raw = dw_input_from_elf_bin(scratch.arena, dbg_data, &bin);
|
convert_params_2.raw = dw_input_from_elf_bin(scratch.arena, dbg_data, &bin);
|
||||||
convert_params_2.path_style = PathStyle_UnixAbsolute;
|
convert_params_2.path_style = PathStyle_UnixAbsolute;
|
||||||
convert_params_2.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, bin.shdrs);
|
convert_params_2.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, dbg_data, &bin, &bin.shdrs);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
} break;
|
}break;
|
||||||
}
|
}
|
||||||
convert_params_2.exe_name = exe_name;
|
convert_params_2.exe_name = exe_name;
|
||||||
convert_params_2.exe_data = exe_data;
|
convert_params_2.exe_data = exe_data;
|
||||||
@@ -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);
|
||||||
@@ -1404,7 +1404,7 @@ rb_thread_entry_point(void *p)
|
|||||||
PE_BinInfo pe = {0};
|
PE_BinInfo pe = {0};
|
||||||
ELF_Bin elf = {0};
|
ELF_Bin elf = {0};
|
||||||
COFF_FileHeaderInfo coff_obj = {0};
|
COFF_FileHeaderInfo coff_obj = {0};
|
||||||
DW_Raw dw = {0};
|
DW_Raw dw = {0};
|
||||||
U64 eh_frame_hdr_vaddr = 0;
|
U64 eh_frame_hdr_vaddr = 0;
|
||||||
U64 eh_frame_vaddr = 0;
|
U64 eh_frame_vaddr = 0;
|
||||||
String8 eh_frame_hdr = {0};
|
String8 eh_frame_hdr = {0};
|
||||||
|
|||||||
@@ -2753,7 +2753,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
|||||||
input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin);
|
input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin);
|
||||||
path_style = PathStyle_UnixAbsolute;
|
path_style = PathStyle_UnixAbsolute;
|
||||||
|
|
||||||
g_d2r_shared.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, bin.shdrs);
|
g_d2r_shared.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, params->dbg_data, &bin, &bin.shdrs);
|
||||||
} break;
|
} break;
|
||||||
default: { InvalidPath; } break;
|
default: { InvalidPath; } break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,47 +78,62 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: gather unit ranges from .debug_info
|
//- rjf: gather unit ranges from .debug_info, .debug_aranges
|
||||||
//
|
//
|
||||||
Rng1U64Array *unit_info_ranges = 0;
|
Rng1U64Array *unit_info_ranges = 0;
|
||||||
ProfScope("gather unit ranges from .debug_info") if(lane_idx() == 0)
|
Rng1U64Array *unit_arange_ranges = 0;
|
||||||
|
ProfScope("gather unit ranges from .debug_info, .debug_aranges") if(lane_idx() == 0)
|
||||||
{
|
{
|
||||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
struct
|
||||||
String8 data = raw->sec[DW_Section_Info].data;
|
|
||||||
Rng1U64List unit_info_ranges_list = {0};
|
|
||||||
for(U64 off = 0; off < data.size;)
|
|
||||||
{
|
{
|
||||||
U64 start_off = off;
|
String8 data;
|
||||||
|
Rng1U64Array **dst_array;
|
||||||
// rjf: read next unit info size
|
}
|
||||||
U64 unit_info_size = 0;
|
tasks[] =
|
||||||
U64 unit_info_size_size = dw2_read_initial_length(data, off, &unit_info_size, 0);
|
{
|
||||||
|
{raw->sec[DW_Section_Info].data, &unit_info_ranges},
|
||||||
// rjf: push
|
{raw->sec[DW_Section_ARanges].data, &unit_arange_ranges},
|
||||||
if(unit_info_size > 0)
|
};
|
||||||
|
for EachElement(task_idx, tasks)
|
||||||
|
{
|
||||||
|
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||||
|
String8 data = tasks[task_idx].data;
|
||||||
|
Rng1U64List unit_range_list = {0};
|
||||||
|
for(U64 off = 0; off < data.size;)
|
||||||
{
|
{
|
||||||
rng1u64_list_push(scratch2.arena, &unit_info_ranges_list, r1u64(off, off + unit_info_size_size + unit_info_size));
|
U64 start_off = off;
|
||||||
|
|
||||||
|
// rjf: read next unit size
|
||||||
|
U64 unit_size = 0;
|
||||||
|
U64 unit_size_size = dw2_read_initial_length(data, off, &unit_size, 0);
|
||||||
|
|
||||||
|
// rjf: push
|
||||||
|
if(unit_size > 0)
|
||||||
|
{
|
||||||
|
rng1u64_list_push(scratch2.arena, &unit_range_list, r1u64(off, off + unit_size_size + unit_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: advance
|
||||||
|
off += unit_size_size;
|
||||||
|
off += unit_size;
|
||||||
|
|
||||||
|
// rjf: break if no movement
|
||||||
|
if(off == start_off)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
tasks[task_idx].dst_array[0] = push_array(scratch.arena, Rng1U64Array, 1);
|
||||||
// rjf: advance
|
tasks[task_idx].dst_array[0][0] = rng1u64_array_from_list(scratch.arena, &unit_range_list);
|
||||||
off += unit_info_size_size;
|
scratch_end(scratch2);
|
||||||
off += unit_info_size;
|
|
||||||
|
|
||||||
// rjf: break if no movement
|
|
||||||
if(off == start_off)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unit_info_ranges = push_array(scratch.arena, Rng1U64Array, 1);
|
|
||||||
unit_info_ranges[0] = rng1u64_array_from_list(scratch.arena, &unit_info_ranges_list);
|
|
||||||
scratch_end(scratch2);
|
|
||||||
}
|
}
|
||||||
lane_sync_u64(&unit_info_ranges, 0);
|
lane_sync_u64(&unit_info_ranges, 0);
|
||||||
|
lane_sync_u64(&unit_arange_ranges, 0);
|
||||||
U64 unit_count = unit_info_ranges->count;
|
U64 unit_count = unit_info_ranges->count;
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: parse all unit headers
|
//- rjf: parse all .debug_info unit headers
|
||||||
//
|
//
|
||||||
DW2_UnitHeader *unit_headers = 0;
|
DW2_UnitHeader *unit_headers = 0;
|
||||||
Rng1U64 *unit_info_tag_ranges = 0;
|
Rng1U64 *unit_info_tag_ranges = 0;
|
||||||
@@ -145,6 +160,148 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
lane_sync();
|
lane_sync();
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: parse all units from .debug_aranges
|
||||||
|
//
|
||||||
|
U64 *arange_info_offs = 0;
|
||||||
|
RDIM_Rng1U64ChunkList *arange_voff_ranges = 0;
|
||||||
|
{
|
||||||
|
if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
arange_info_offs = push_array(scratch.arena, U64, unit_arange_ranges->count);
|
||||||
|
arange_voff_ranges = push_array(scratch.arena, RDIM_Rng1U64ChunkList, unit_arange_ranges->count);
|
||||||
|
}
|
||||||
|
lane_sync_u64(&arange_info_offs, 0);
|
||||||
|
lane_sync_u64(&arange_voff_ranges, 0);
|
||||||
|
U64 unit_take_idx_ = 0;
|
||||||
|
U64 *unit_take_idx_ptr = &unit_take_idx_;
|
||||||
|
lane_sync_u64(&unit_take_idx_ptr, 0);
|
||||||
|
String8 data = raw->sec[DW_Section_ARanges].data;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
// rjf: take unit
|
||||||
|
U64 unit_idx = ins_atomic_u64_inc_eval(unit_take_idx_ptr)-1;
|
||||||
|
if(unit_idx >= unit_arange_ranges->count)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: unpack
|
||||||
|
Rng1U64 arange_range = unit_arange_ranges->v[unit_idx];
|
||||||
|
U64 off = arange_range.min;
|
||||||
|
|
||||||
|
// rjf: read unit data size / format
|
||||||
|
U64 unit_size = 0;
|
||||||
|
DW_Format fmt = 0;
|
||||||
|
off += dw2_read_initial_length(data, off, &unit_size, &fmt);
|
||||||
|
U64 unit_opl = off + unit_size;
|
||||||
|
|
||||||
|
// rjf: read version
|
||||||
|
DW_Version version = 0;
|
||||||
|
U64 version_off = off;
|
||||||
|
off += str8_deserial_read_struct(data, off, &version);
|
||||||
|
|
||||||
|
// rjf: warn on non-version 2
|
||||||
|
if(version != DW_Version_2)
|
||||||
|
{
|
||||||
|
log_infof("[.debug_aranges@0x%I64x] DWARF version for unit #%I64d was expected to be 2, but it was read as %i.\n", version_off, unit_idx, (S32)version);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: read .debug_info off for this unit
|
||||||
|
U64 info_off = 0;
|
||||||
|
off += dw2_read_fmt_u64(data, off, fmt, &info_off);
|
||||||
|
|
||||||
|
// rjf: read address / segment selector size
|
||||||
|
U8 addr_size = 0;
|
||||||
|
U8 segment_selector_size = 0;
|
||||||
|
off += str8_deserial_read_struct(data, off, &addr_size);
|
||||||
|
off += str8_deserial_read_struct(data, off, &segment_selector_size);
|
||||||
|
|
||||||
|
// rjf: round up past padding
|
||||||
|
{
|
||||||
|
U64 tuple_size = addr_size*2 + segment_selector_size;
|
||||||
|
off += tuple_size - (off%tuple_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: parse ranges
|
||||||
|
RDIM_Rng1U64ChunkList voff_ranges = {0};
|
||||||
|
if(segment_selector_size != 0)
|
||||||
|
{
|
||||||
|
log_infof("[.debug_aranges@0x%I64x] Non-zero (%i) segment selector size parsed; this form of addressing is not currently supported in DWARF info.\n", off, (S32)segment_selector_size);
|
||||||
|
}
|
||||||
|
else for(;off < unit_opl;)
|
||||||
|
{
|
||||||
|
U64 start_off = off;
|
||||||
|
U64 base_addr = 0;
|
||||||
|
U64 range_size = 0;
|
||||||
|
off += str8_deserial_read(data, off, &base_addr, addr_size, addr_size);
|
||||||
|
off += str8_deserial_read(data, off, &range_size, addr_size, addr_size);
|
||||||
|
if(base_addr == 0 && range_size == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(base_addr < base_vaddr)
|
||||||
|
{
|
||||||
|
log_infof("[.debug_aranges@0x%I64x] Address (0x%I64x) parsed which was less than the image base address (0x%I64x). Skipping.\n", start_off, base_addr, base_vaddr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
U64 voff_first = (base_addr - base_vaddr);
|
||||||
|
U64 voff_opl = voff_first + range_size;
|
||||||
|
RDIM_Rng1U64 range = {voff_first, voff_opl};
|
||||||
|
rdim_rng1u64_chunk_list_push(scratch.arena, &voff_ranges, 256, range);
|
||||||
|
}
|
||||||
|
if(off == start_off)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: store
|
||||||
|
arange_info_offs[unit_idx] = info_off;
|
||||||
|
arange_voff_ranges[unit_idx] = voff_ranges;
|
||||||
|
}
|
||||||
|
lane_sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: produce info_off -> list(voff_range) map from aranges units;
|
||||||
|
// we must do this because technically we can't guarantee that unit_idxs
|
||||||
|
// inside of .debug_aranges are the same as unit_idxs inside of .debug_info,
|
||||||
|
// nor can we guarantee that they'd be in the same order, so we need to
|
||||||
|
// correllate via the encoded .debug_info offset from .debug_aranges.
|
||||||
|
//
|
||||||
|
// more excellence.
|
||||||
|
//
|
||||||
|
typedef struct D2R2_ARangeUnitNode D2R2_ARangeUnitNode;
|
||||||
|
struct D2R2_ARangeUnitNode
|
||||||
|
{
|
||||||
|
D2R2_ARangeUnitNode *next;
|
||||||
|
U64 info_off;
|
||||||
|
RDIM_Rng1U64ChunkList *ranges;
|
||||||
|
};
|
||||||
|
U64 arange_unit_from_info_off_map_slots_count = unit_arange_ranges->count;
|
||||||
|
D2R2_ARangeUnitNode **arange_unit_from_info_off_map_slots = 0;
|
||||||
|
{
|
||||||
|
if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
arange_unit_from_info_off_map_slots = push_array(scratch.arena, D2R2_ARangeUnitNode *, arange_unit_from_info_off_map_slots_count);
|
||||||
|
}
|
||||||
|
lane_sync_u64(&arange_unit_from_info_off_map_slots, 0);
|
||||||
|
for EachIndex(arange_unit_idx, unit_arange_ranges->count)
|
||||||
|
{
|
||||||
|
U64 info_off = arange_info_offs[arange_unit_idx];
|
||||||
|
RDIM_Rng1U64ChunkList *ranges = &arange_voff_ranges[arange_unit_idx];
|
||||||
|
U64 hash = u64_hash_from_str8(str8_struct(&info_off));
|
||||||
|
U64 slot_idx = hash%arange_unit_from_info_off_map_slots_count;
|
||||||
|
D2R2_ARangeUnitNode *n = push_array(scratch.arena, D2R2_ARangeUnitNode, 1);
|
||||||
|
SLLStackPush(arange_unit_from_info_off_map_slots[slot_idx], n);
|
||||||
|
n->info_off = info_off;
|
||||||
|
n->ranges = ranges;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lane_sync();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: build all abbreviation maps, build (unit -> abbrev map)
|
//- rjf: build all abbreviation maps, build (unit -> abbrev map)
|
||||||
//
|
//
|
||||||
@@ -389,6 +546,21 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
lane_sync();
|
lane_sync();
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: look up base addresses for each unit - equip to per-unit parsing contexts
|
||||||
|
//
|
||||||
|
{
|
||||||
|
Rng1U64 range = lane_range(unit_count);
|
||||||
|
for EachInRange(unit_idx, range)
|
||||||
|
{
|
||||||
|
DW2_Tag *unit_root_tag = &unit_root_tags__pre_str_offsets[unit_idx];
|
||||||
|
DW2_Attrib *low_pc_attrib = dw2_attrib_from_kind(unit_root_tag, DW_AttribKind_LowPc);
|
||||||
|
U64 low_pc = low_pc_attrib->val.u128.u64[0];
|
||||||
|
unit_parse_ctxs[unit_idx].unit_base_addr = low_pc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lane_sync();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: look up string offset tables for each unit (.debug_str_offsets);
|
//- rjf: look up string offset tables for each unit (.debug_str_offsets);
|
||||||
// equip to per-unit parsing contexts
|
// equip to per-unit parsing contexts
|
||||||
@@ -1836,7 +2008,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
{
|
{
|
||||||
if(dw_is_form_kind_ref(unit_parse_ctx->version, unit_parse_ctx->ext, lower_bound_attrib->val.kind))
|
if(dw_is_form_kind_ref(unit_parse_ctx->version, unit_parse_ctx->ext, lower_bound_attrib->val.kind))
|
||||||
{
|
{
|
||||||
log_infof("[.debug_info@%I64x] Array type lower bound is a variable; this is not currently supported.\n", start_off);
|
log_infof("[.debug_info@0x%I64x] Array type lower bound is a variable; this is not currently supported.\n", start_off);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1855,7 +2027,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
{
|
{
|
||||||
if(dw_is_form_kind_ref(unit_parse_ctx->version, unit_parse_ctx->ext, upper_bound_attrib->val.kind))
|
if(dw_is_form_kind_ref(unit_parse_ctx->version, unit_parse_ctx->ext, upper_bound_attrib->val.kind))
|
||||||
{
|
{
|
||||||
log_infof("[.debug_info@%I64x] Array type upper bound is a variable; this is not currently supported.\n", start_off);
|
log_infof("[.debug_info@0x%I64x] Array type upper bound is a variable; this is not currently supported.\n", start_off);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1993,6 +2165,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
DW2_Attrib *comp_dir_attrib = &dw2_attrib_nil;
|
DW2_Attrib *comp_dir_attrib = &dw2_attrib_nil;
|
||||||
DW2_Attrib *producer_attrib = &dw2_attrib_nil;
|
DW2_Attrib *producer_attrib = &dw2_attrib_nil;
|
||||||
DW2_Attrib *lang_attrib = &dw2_attrib_nil;
|
DW2_Attrib *lang_attrib = &dw2_attrib_nil;
|
||||||
|
DW2_Attrib *ranges_attrib = &dw2_attrib_nil;
|
||||||
|
DW2_Attrib *lopc_attrib = &dw2_attrib_nil;
|
||||||
|
DW2_Attrib *hipc_attrib = &dw2_attrib_nil;
|
||||||
for EachNode(n, DW2_AttribNode, unit_root_tag->attribs.first)
|
for EachNode(n, DW2_AttribNode, unit_root_tag->attribs.first)
|
||||||
{
|
{
|
||||||
switch(n->v.attrib_kind)
|
switch(n->v.attrib_kind)
|
||||||
@@ -2003,6 +2178,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
Case(comp_dir, CompDir);
|
Case(comp_dir, CompDir);
|
||||||
Case(producer, Producer);
|
Case(producer, Producer);
|
||||||
Case(lang, Language);
|
Case(lang, Language);
|
||||||
|
Case(ranges, Ranges);
|
||||||
|
Case(lopc, LowPc);
|
||||||
|
Case(hipc, HighPc);
|
||||||
#undef Case
|
#undef Case
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2034,6 +2212,46 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: get unit's ranges from .debug_aranges parse artifacts, if we have them
|
||||||
|
RDIM_Rng1U64ChunkList unit_voff_ranges = {0};
|
||||||
|
if(arange_unit_from_info_off_map_slots_count != 0)
|
||||||
|
{
|
||||||
|
U64 unit_info_off = unit_info_ranges->v[unit_idx].min;
|
||||||
|
U64 hash = u64_hash_from_str8(str8_struct(&unit_info_off));
|
||||||
|
U64 slot_idx = hash%arange_unit_from_info_off_map_slots_count;
|
||||||
|
for(D2R2_ARangeUnitNode *n = arange_unit_from_info_off_map_slots[slot_idx]; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->info_off == unit_info_off)
|
||||||
|
{
|
||||||
|
unit_voff_ranges = n->ranges[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: if we have no voff ranges from .debug_aranges, then we need to extract
|
||||||
|
// this info from the unit root rag instead (via ranges & low-pc/high-pc tags)
|
||||||
|
if(unit_voff_ranges.total_count == 0)
|
||||||
|
{
|
||||||
|
// rjf: gather ranges from a ranges attribute
|
||||||
|
if(ranges_attrib != &dw2_attrib_nil)
|
||||||
|
{
|
||||||
|
Rng1U64List ranges = dw2_rnglist_from_form_val(scratch.arena, unit_parse_ctx, raw, ranges_attrib->val);
|
||||||
|
for EachNode(n, Rng1U64Node, ranges.first)
|
||||||
|
{
|
||||||
|
rdim_rng1u64_chunk_list_push(arena, &unit_voff_ranges, 256, (RDIM_Rng1U64){n->v.min - base_vaddr, n->v.max - base_vaddr});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: gather contiguous range from low-pc / high-pc attribute
|
||||||
|
if(lopc_attrib != &dw2_attrib_nil && hipc_attrib != &dw2_attrib_nil)
|
||||||
|
{
|
||||||
|
U64 voff_base = lopc_attrib->val.u128.u64[0] - base_vaddr;
|
||||||
|
U64 voff_opl = hipc_attrib->val.u128.u64[0] - base_vaddr;
|
||||||
|
rdim_rng1u64_chunk_list_push(arena, &unit_voff_ranges, 256, (RDIM_Rng1U64){voff_base, voff_opl});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: fill top-level unit info
|
//- rjf: fill top-level unit info
|
||||||
{
|
{
|
||||||
dst_unit->unit_name = unit_name;
|
dst_unit->unit_name = unit_name;
|
||||||
@@ -2044,6 +2262,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
dst_unit->build_path = unit_comp_dir;
|
dst_unit->build_path = unit_comp_dir;
|
||||||
dst_unit->language = unit_lang;
|
dst_unit->language = unit_lang;
|
||||||
dst_unit->line_table = unit_line_tables[unit_idx];
|
dst_unit->line_table = unit_line_tables[unit_idx];
|
||||||
|
dst_unit->voff_ranges = unit_voff_ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: produce all unit symbols
|
//- rjf: produce all unit symbols
|
||||||
@@ -2119,7 +2338,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params)
|
|||||||
RDIM_BakeParams result = {0};
|
RDIM_BakeParams result = {0};
|
||||||
{
|
{
|
||||||
result.subset_flags = params->subset_flags;
|
result.subset_flags = params->subset_flags;
|
||||||
// TODO(rjf): result.top_level_info = *top_level_info;
|
result.top_level_info = top_level_info;
|
||||||
// TODO(rjf): result.binary_sections = *binary_sections;
|
// TODO(rjf): result.binary_sections = *binary_sections;
|
||||||
result.units = *all_units;
|
result.units = *all_units;
|
||||||
result.types = *all_types;
|
result.types = *all_types;
|
||||||
|
|||||||
@@ -2,8 +2,32 @@
|
|||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
internal RDIM_BinarySectionList
|
internal RDIM_BinarySectionList
|
||||||
e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs)
|
e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_Bin *bin, ELF_Shdr64Array *shdrs)
|
||||||
{
|
{
|
||||||
RDIM_BinarySectionList result = {0};
|
RDIM_BinarySectionList result = {0};
|
||||||
|
for EachIndex(idx, shdrs->count)
|
||||||
|
{
|
||||||
|
// rjf: unpack section
|
||||||
|
ELF_Shdr64 *src_section = &shdrs->v[idx];
|
||||||
|
String8 name = elf_name_from_shdr64(data, bin, src_section);
|
||||||
|
U64 voff_first = src_section->sh_addr;
|
||||||
|
U64 voff_opl = voff_first + src_section->sh_size;
|
||||||
|
U64 foff_first = src_section->sh_offset;
|
||||||
|
U64 foff_opl = foff_first + src_section->sh_size;
|
||||||
|
|
||||||
|
// rjf: map flags -> rdi
|
||||||
|
RDI_BinarySectionFlags flags = RDI_BinarySectionFlag_Read;
|
||||||
|
if(src_section->sh_flags & ELF_Shf_Write) { flags |= RDI_BinarySectionFlag_Write; }
|
||||||
|
if(src_section->sh_flags & ELF_Shf_ExecInstr) { flags |= RDI_BinarySectionFlag_Execute; }
|
||||||
|
|
||||||
|
// rjf: make rdi section
|
||||||
|
RDIM_BinarySection *dst_section = rdim_binary_section_list_push(arena, &result);
|
||||||
|
dst_section->name = name;
|
||||||
|
dst_section->flags = flags;
|
||||||
|
dst_section->voff_first = voff_first;
|
||||||
|
dst_section->voff_opl = voff_opl;
|
||||||
|
dst_section->foff_first = foff_first;
|
||||||
|
dst_section->foff_opl = foff_opl;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
#ifndef RDI_FROM_ELF_H
|
#ifndef RDI_FROM_ELF_H
|
||||||
#define RDI_FROM_ELF_H
|
#define RDI_FROM_ELF_H
|
||||||
|
|
||||||
internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs);
|
internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, String8 data, ELF_Bin *bin, ELF_Shdr64Array *shdrs);
|
||||||
|
|
||||||
#endif // RDI_FROM_ELF_H
|
#endif // RDI_FROM_ELF_H
|
||||||
|
|||||||
Reference in New Issue
Block a user