// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_PARSE_2_H #define DWARF_PARSE_2_H //////////////////////////////// //~ rjf: Unit Headers typedef struct DW2_UnitHeader DW2_UnitHeader; struct DW2_UnitHeader { DW_Version version; DW_Format format; U64 abbrev_off; U64 addr_size; DW_CompUnitKind kind; U64 dwo_id; }; //////////////////////////////// //~ rjf: Abbreviation Map (ID -> .debug_abbrev Offset) typedef struct DW2_AbbrevMapNode DW2_AbbrevMapNode; struct DW2_AbbrevMapNode { DW2_AbbrevMapNode *next; U64 id; U64 off; }; typedef struct DW2_AbbrevMap DW2_AbbrevMap; struct DW2_AbbrevMap { DW2_AbbrevMapNode **slots; U64 slots_count; }; //////////////////////////////// //~ rjf: Offset Tables (.debug_str_offsets, .debug_rnglists) typedef struct DW2_OffsetTable DW2_OffsetTable; struct DW2_OffsetTable { DW_Format format; DW_Version version; U8 addr_size; U8 segment_selector_size; U64 entry_size; U64 entries_count; void *entries; }; //////////////////////////////// //~ rjf: Parsing Context Bundle 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; DW_Ext ext; U64 addr_size; U64 unit_base_addr; U64 unit_base_info_off; DW2_AbbrevMap *abbrev_map; DW2_OffsetTable *rnglists_table; DW2_OffsetTable *str_offsets_table; DW2_OffsetTable *addr_table; DW2_OffsetTable *loclists_table; String8 unit_dir; String8 unit_file; }; //////////////////////////////// //~ rjf: Tag Attributes typedef struct DW2_FormVal DW2_FormVal; struct DW2_FormVal { DW_FormKind kind; U128 u128; String8 string; U64 addr; }; typedef struct DW2_Attrib DW2_Attrib; struct DW2_Attrib { DW_AttribKind attrib_kind; DW2_FormVal val; }; typedef struct DW2_AttribNode DW2_AttribNode; struct DW2_AttribNode { DW2_AttribNode *next; DW2_Attrib v; }; typedef struct DW2_AttribList DW2_AttribList; struct DW2_AttribList { DW2_AttribNode *first; DW2_AttribNode *last; U64 count; }; //////////////////////////////// //~ rjf: Tags typedef struct DW2_Tag DW2_Tag; struct DW2_Tag { DW_TagKind kind; B32 has_children; DW2_AttribList attribs; }; //////////////////////////////// //~ rjf: Line Info typedef U32 DW2_LineTableFileFlags; enum { DW2_LineTableFileFlag_HasMD5 = (1<<0), DW2_LineTableFileFlag_HasModifyTime = (1<<1), }; typedef struct DW2_LineTableFile DW2_LineTableFile; struct DW2_LineTableFile { String8 file_name; DW2_LineTableFileFlags flags; 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; U64 line_program_off; U64 total_unit_data_size; // NOTE(rjf): would be implied by `unit_length`, but DWARF makes that the size *past* the variable-width unit-length field itself }; typedef struct DW2_LineVMRegs DW2_LineVMRegs; struct DW2_LineVMRegs { U64 address; U64 vliw_op_index; U64 file_index; U64 line; U64 column; B32 is_stmt; B32 basic_block; B32 end_sequence; B32 prologue_end; B32 epilogue_begin; U64 isa; U64 discriminator; }; //////////////////////////////// //~ rjf: Location Lists typedef struct DW2_Loc DW2_Loc; struct DW2_Loc { Rng1U64 range; String8 expr; }; typedef struct DW2_LocNode DW2_LocNode; struct DW2_LocNode { DW2_LocNode *next; DW2_Loc v; }; typedef struct DW2_LocList DW2_LocList; struct DW2_LocList { DW2_LocNode *first; DW2_LocNode *last; U64 count; }; //////////////////////////////// //~ rjf: Globals global read_only DW2_Attrib dw2_attrib_nil = {0}; //////////////////////////////// //~ rjf: Basic Parsing Helpers internal U64 dw2_read_initial_length(String8 data, U64 off, U64 *out, DW_Format *fmt_out); internal U64 dw2_read_fmt_u64(String8 data, U64 off, DW_Format format, U64 *out); //////////////////////////////// //~ rjf: Unit Range Set Parsing (Top-Level .debug_info, .debug_aranges) internal Rng1U64Array dw2_unit_ranges_from_data(Arena *arena, String8 data); //////////////////////////////// //~ rjf: Unit Header Parsing internal U64 dw2_read_unit_header(String8 data, U64 off, DW2_UnitHeader *out); //////////////////////////////// //~ rjf: Abbreviation Map Parsing 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); //////////////////////////////// //~ rjf: Tag Parsing internal U64 dw2_read_tag(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_Tag *tag_out); internal DW2_Attrib *dw2_attrib_from_kind(DW2_Tag *tag, DW_AttribKind kind); internal U64 dw2_reference_info_off_from_form_val(DW2_ParseCtx *ctx, DW2_FormVal *v); //////////////////////////////// //~ rjf: Line Table Parsing internal U64 dw2_read_line_table_header(Arena *arena, DW2_ParseCtx *ctx, String8 data, U64 off, DW2_LineTableHeader *out); //////////////////////////////// //~ rjf: Offset Table Parsing (.debug_str_offsets, .debug_rnglists) internal U64 dw2_read_offset_table(String8 data, U64 off, DW2_OffsetTable *out); internal B32 dw2_try_offset_from_table_idx(DW2_OffsetTable *tbl, U64 idx, U64 *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); //////////////////////////////// //~ rjf: Location List Parsing (.debug_loclists) internal DW2_LocList dw2_loclist_from_form_val(Arena *arena, DW2_ParseCtx *ctx, DW_Raw *raw, DW2_FormVal form_val); #endif // DWARF_PARSE_2_H