From f5ec462438196681bb0b37c8afa2d36c6df4eecf Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 28 Apr 2026 08:57:59 -0700 Subject: [PATCH] d2r2: .debug_aranges parsing / unit conversion; .debug_ranges parsing --- src/base/base_math.h | 2 +- src/dwarf/dwarf_parse.h | 2 +- src/dwarf/dwarf_parse_2.c | 62 ++++++ src/dwarf/dwarf_parse_2.h | 6 + src/elf/elf_parse.h | 18 +- src/radbin/radbin.c | 10 +- src/rdi_from_dwarf/rdi_from_dwarf.c | 2 +- src/rdi_from_dwarf/rdi_from_dwarf_2.c | 283 +++++++++++++++++++++++--- src/rdi_from_elf/rdi_from_elf.c | 26 ++- src/rdi_from_elf/rdi_from_elf.h | 2 +- 10 files changed, 362 insertions(+), 51 deletions(-) diff --git a/src/base/base_math.h b/src/base/base_math.h index b31c0699..43604127 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -339,9 +339,9 @@ struct Rng1U64Node typedef struct Rng1U64List Rng1U64List; struct Rng1U64List { - U64 count; Rng1U64Node *first; Rng1U64Node *last; + U64 count; }; typedef struct Rng1U64Array Rng1U64Array; diff --git a/src/dwarf/dwarf_parse.h b/src/dwarf/dwarf_parse.h index e83fd918..edd7c1f0 100644 --- a/src/dwarf/dwarf_parse.h +++ b/src/dwarf/dwarf_parse.h @@ -8,7 +8,7 @@ typedef struct DW_Section { String8 name; String8 data; - B32 is_dwo; + B32 is_dwo; } DW_Section; typedef struct DW_Raw diff --git a/src/dwarf/dwarf_parse_2.c b/src/dwarf/dwarf_parse_2.c index 7b406587..ea5572ef 100644 --- a/src/dwarf/dwarf_parse_2.c +++ b/src/dwarf/dwarf_parse_2.c @@ -900,3 +900,65 @@ dw2_read_str_offsets_table(String8 data, U64 off, DW2_StrOffsetsTable *out) U64 bytes_read = (off - start_off); 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; +} diff --git a/src/dwarf/dwarf_parse_2.h b/src/dwarf/dwarf_parse_2.h index e298101d..8b86ee68 100644 --- a/src/dwarf/dwarf_parse_2.h +++ b/src/dwarf/dwarf_parse_2.h @@ -62,6 +62,7 @@ struct DW2_ParseCtx DW_Format format; DW_Ext ext; U64 addr_size; + U64 unit_base_addr; DW2_AbbrevMap *abbrev_map; DW2_StrOffsetsTable *str_offsets_table; 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); +//////////////////////////////// +//~ 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 diff --git a/src/elf/elf_parse.h b/src/elf/elf_parse.h index f15708c8..191c7fea 100644 --- a/src/elf/elf_parse.h +++ b/src/elf/elf_parse.h @@ -10,22 +10,22 @@ typedef struct ELF_Shdr64Array ELF_Shdr64Array; struct ELF_Shdr64Array { - U64 count; + U64 count; ELF_Shdr64 *v; }; typedef struct ELF_Phdr64Array ELF_Phdr64Array; struct ELF_Phdr64Array { - U64 count; + U64 count; ELF_Phdr64 *v; }; typedef struct ELF_Bin ELF_Bin; struct ELF_Bin { - ELF_Hdr64 hdr; - Rng1U64 sh_name_range; + ELF_Hdr64 hdr; + Rng1U64 sh_name_range; ELF_Shdr64Array shdrs; ELF_Phdr64Array phdrs; }; @@ -34,30 +34,30 @@ typedef struct ELF_GnuDebugLink ELF_GnuDebugLink; struct ELF_GnuDebugLink { String8 path; - U32 checksum; + U32 checksum; }; typedef struct ELF_Note ELF_Note; struct ELF_Note { - String8 owner; + String8 owner; ELF_NoteType type; - String8 desc; + String8 desc; }; typedef struct ELF_NoteNode ELF_NoteNode; struct ELF_NoteNode { - ELF_Note v; ELF_NoteNode *next; + ELF_Note v; }; typedef struct ELF_NoteList ELF_NoteList; struct ELF_NoteList { - U64 count; ELF_NoteNode *first; ELF_NoteNode *last; + U64 count; }; //////////////////////////////// diff --git a/src/radbin/radbin.c b/src/radbin/radbin.c index 3c8ba34d..2f59204f 100644 --- a/src/radbin/radbin.c +++ b/src/radbin/radbin.c @@ -872,9 +872,9 @@ rb_thread_entry_point(void *p) 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.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); - } break; + }break; } convert_params_2.exe_name = exe_name; 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); 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_2); + // rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params); + rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params_2); for EachNode(n, RDIM_BakeParamsNode, first_rdi_bake_params) { rdim_bake_params_concat_in_place(bake_params, &n->v); @@ -1404,7 +1404,7 @@ rb_thread_entry_point(void *p) PE_BinInfo pe = {0}; ELF_Bin elf = {0}; COFF_FileHeaderInfo coff_obj = {0}; - DW_Raw dw = {0}; + DW_Raw dw = {0}; U64 eh_frame_hdr_vaddr = 0; U64 eh_frame_vaddr = 0; String8 eh_frame_hdr = {0}; diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index 875f6a9c..f171c50b 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -2753,7 +2753,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params) input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin); 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; default: { InvalidPath; } break; } diff --git a/src/rdi_from_dwarf/rdi_from_dwarf_2.c b/src/rdi_from_dwarf/rdi_from_dwarf_2.c index 153dddcf..20e890db 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf_2.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf_2.c @@ -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; - 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); - String8 data = raw->sec[DW_Section_Info].data; - Rng1U64List unit_info_ranges_list = {0}; - for(U64 off = 0; off < data.size;) + struct { - U64 start_off = off; - - // rjf: read next unit info size - U64 unit_info_size = 0; - U64 unit_info_size_size = dw2_read_initial_length(data, off, &unit_info_size, 0); - - // rjf: push - if(unit_info_size > 0) + String8 data; + Rng1U64Array **dst_array; + } + tasks[] = + { + {raw->sec[DW_Section_Info].data, &unit_info_ranges}, + {raw->sec[DW_Section_ARanges].data, &unit_arange_ranges}, + }; + 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; + } } - - // rjf: advance - off += unit_info_size_size; - off += unit_info_size; - - // rjf: break if no movement - if(off == start_off) - { - break; - } + tasks[task_idx].dst_array[0] = push_array(scratch.arena, Rng1U64Array, 1); + tasks[task_idx].dst_array[0][0] = rng1u64_array_from_list(scratch.arena, &unit_range_list); + scratch_end(scratch2); } - 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_arange_ranges, 0); U64 unit_count = unit_info_ranges->count; //////////////////////////// - //- rjf: parse all unit headers + //- rjf: parse all .debug_info unit headers // DW2_UnitHeader *unit_headers = 0; Rng1U64 *unit_info_tag_ranges = 0; @@ -145,6 +160,148 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) } 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) // @@ -389,6 +546,21 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) } 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); // 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)) { - 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 { @@ -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)) { - 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 { @@ -1993,6 +2165,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) DW2_Attrib *comp_dir_attrib = &dw2_attrib_nil; DW2_Attrib *producer_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) { switch(n->v.attrib_kind) @@ -2003,6 +2178,9 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) Case(comp_dir, CompDir); Case(producer, Producer); Case(lang, Language); + Case(ranges, Ranges); + Case(lopc, LowPc); + Case(hipc, HighPc); #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 { 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->language = unit_lang; dst_unit->line_table = unit_line_tables[unit_idx]; + dst_unit->voff_ranges = unit_voff_ranges; } //- rjf: produce all unit symbols @@ -2119,7 +2338,7 @@ d2r2_convert(Arena *arena, D2R2_ConvertParams *params) RDIM_BakeParams result = {0}; { 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; result.units = *all_units; result.types = *all_types; diff --git a/src/rdi_from_elf/rdi_from_elf.c b/src/rdi_from_elf/rdi_from_elf.c index ccbb1351..909a28a2 100644 --- a/src/rdi_from_elf/rdi_from_elf.c +++ b/src/rdi_from_elf/rdi_from_elf.c @@ -2,8 +2,32 @@ // Licensed under the MIT license (https://opensource.org/license/mit/) 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}; + 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; } diff --git a/src/rdi_from_elf/rdi_from_elf.h b/src/rdi_from_elf/rdi_from_elf.h index 3d979c8f..bdb8faf5 100644 --- a/src/rdi_from_elf/rdi_from_elf.h +++ b/src/rdi_from_elf/rdi_from_elf.h @@ -4,6 +4,6 @@ #ifndef 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