switched to TryRead helper macro for parsing abbrev table and compile units

This commit is contained in:
Nikita Smith
2026-02-05 17:43:19 -08:00
parent cd70b7e1ec
commit 4f30f64914
4 changed files with 811 additions and 1042 deletions
+2 -1
View File
@@ -12,6 +12,7 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h>
//////////////////////////////// ////////////////////////////////
//~ rjf: Third Party Includes //~ rjf: Third Party Includes
@@ -439,7 +440,7 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s
# define this_function_name __func__ # define this_function_name __func__
#endif #endif
#define TryRead(func, cursor, label) do { U64 size = (func); if (size == 0) { goto label; } cursor += size; } while (0) #define TryRead(func__, cursor__, label__) do { U64 size__ = (func__); if (size__ == 0) { Assert(0 && "failed read"); goto label__; } cursor__ += size__; } while (0)
//////////////////////////////// ////////////////////////////////
//~ rjf: Base Types //~ rjf: Base Types
+39 -37
View File
@@ -151,12 +151,13 @@ typedef enum DW_InlKindEnum
X(SetEpilogueBegin, 0x0B) \ X(SetEpilogueBegin, 0x0B) \
X(SetIsa, 0x0C) \ X(SetIsa, 0x0C) \
typedef enum DW_StdOpcode typedef U8 DW_StdOpcode;
typedef enum DW_StdOpcodeEnum
{ {
#define X(_N,_ID) DW_StdOpcode_##_N = _ID, #define X(_N,_ID) DW_StdOpcode_##_N = _ID,
DW_StdOpcode_XList DW_StdOpcode_XList
#undef X #undef X
} DW_StdOpcode; } DW_StdOpcodeEnum;
#define DW_ExtOpcode_XList \ #define DW_ExtOpcode_XList \
X(Undefined, 0x00) \ X(Undefined, 0x00) \
@@ -167,12 +168,13 @@ typedef enum DW_StdOpcode
X(UserLo, 0x80) \ X(UserLo, 0x80) \
X(UserHi, 0xff) X(UserHi, 0xff)
typedef enum DW_ExtOpcode typedef U8 DW_ExtOpcode;
typedef enum DW_ExtOpcodeEnum
{ {
#define X(_N,_ID) DW_ExtOpcode_##_N = _ID, #define X(_N,_ID) DW_ExtOpcode_##_N = _ID,
DW_ExtOpcode_XList DW_ExtOpcode_XList
#undef X #undef X
} DW_ExtOpcode; } DW_ExtOpcodeEnum;
#define DW_IDCaseKind_XList \ #define DW_IDCaseKind_XList \
X(CaseSensitive, 0x00) \ X(CaseSensitive, 0x00) \
@@ -1023,39 +1025,39 @@ typedef enum DW_FormEnum
X(GNU_Denominator, 0x2304) \ X(GNU_Denominator, 0x2304) \
X(GNU_Bias, 0x2305) X(GNU_Bias, 0x2305)
#define DW_AttribKind_ClassFlags_GNU_XList \ #define DW_AttribKind_ClassFlags_GNU_XList \
X(GNU_Vector, DW_AttribClass_Flag) \ X(GNU_Vector, DW_AttribClass_Flag) \
X(GNU_GuardedBy, DW_AttribClass_Undefined) \ X(GNU_GuardedBy, DW_AttribClass_Undefined) \
X(GNU_PtGuardedBy, DW_AttribClass_Undefined) \ X(GNU_PtGuardedBy, DW_AttribClass_Undefined) \
X(GNU_Guarded, DW_AttribClass_Undefined) \ X(GNU_Guarded, DW_AttribClass_Undefined) \
X(GNU_PtGuarded, DW_AttribClass_Undefined) \ X(GNU_PtGuarded, DW_AttribClass_Undefined) \
X(GNU_LocksExcluded, DW_AttribClass_Undefined) \ X(GNU_LocksExcluded, DW_AttribClass_Undefined) \
X(GNU_ExclusiveLocksRequired, DW_AttribClass_Undefined) \ X(GNU_ExclusiveLocksRequired, DW_AttribClass_Undefined) \
X(GNU_SharedLocksRequired, DW_AttribClass_Undefined) \ X(GNU_SharedLocksRequired, DW_AttribClass_Undefined) \
X(GNU_OdrSignature, DW_AttribClass_Undefined) \ X(GNU_OdrSignature, DW_AttribClass_Undefined) \
X(GNU_TemplateName, DW_AttribClass_Undefined) \ X(GNU_TemplateName, DW_AttribClass_Undefined) \
X(GNU_CallSiteValue, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteValue, DW_AttribClass_ExprLoc) \
X(GNU_CallSiteDataValue, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteDataValue, DW_AttribClass_ExprLoc) \
X(GNU_CallSiteTarget, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteTarget, DW_AttribClass_ExprLoc) \
X(GNU_CallSiteTargetClobbered, DW_AttribClass_ExprLoc) \ X(GNU_CallSiteTargetClobbered, DW_AttribClass_ExprLoc) \
X(GNU_TailCall, DW_AttribClass_Flag) \ X(GNU_TailCall, DW_AttribClass_Flag) \
X(GNU_AllTailCallsSites, DW_AttribClass_Flag) \ X(GNU_AllTailCallsSites, DW_AttribClass_Flag) \
X(GNU_AllCallSites, DW_AttribClass_Flag) \ X(GNU_AllCallSites, DW_AttribClass_Flag) \
X(GNU_AllSourceCallSites, DW_AttribClass_Flag) \ X(GNU_AllSourceCallSites, DW_AttribClass_Flag) \
X(GNU_Macros, DW_AttribClass_Flag) \ X(GNU_Macros, DW_AttribClass_Flag) \
X(GNU_Deleted, DW_AttribClass_Undefined) \ X(GNU_Deleted, DW_AttribClass_Undefined) \
X(GNU_DwoName, DW_AttribClass_String) \ X(GNU_DwoName, DW_AttribClass_String) \
X(GNU_DwoId, DW_AttribClass_Const) \ X(GNU_DwoId, DW_AttribClass_Const) \
X(GNU_RangesBase, DW_AttribClass_Undefined) \ X(GNU_RangesBase, DW_AttribClass_Undefined) \
X(GNU_AddrBase, DW_AttribClass_AddrPtr) \ X(GNU_AddrBase, DW_AttribClass_AddrPtr) \
X(GNU_PubNames, DW_AttribClass_Flag) \ X(GNU_PubNames, DW_AttribClass_Flag) \
X(GNU_PubTypes, DW_AttribClass_Undefined) \ X(GNU_PubTypes, DW_AttribClass_Undefined) \
X(GNU_Discriminator, DW_AttribClass_Const) \ X(GNU_Discriminator, DW_AttribClass_Const) \
X(GNU_LocViews, DW_AttribClass_Undefined) \ X(GNU_LocViews, DW_AttribClass_LocListPtr) \
X(GNU_EntryView, DW_AttribClass_Undefined) \ X(GNU_EntryView, DW_AttribClass_Undefined) \
X(GNU_DescriptiveType, DW_AttribClass_Undefined) \ X(GNU_DescriptiveType, DW_AttribClass_Undefined) \
X(GNU_Numerator, DW_AttribClass_Undefined) \ X(GNU_Numerator, DW_AttribClass_Undefined) \
X(GNU_Denominator, DW_AttribClass_Undefined) \ X(GNU_Denominator, DW_AttribClass_Undefined) \
X(GNU_Bias, DW_AttribClass_Undefined) X(GNU_Bias, DW_AttribClass_Undefined)
//- Attributes LLVM //- Attributes LLVM
+673 -905
View File
File diff suppressed because it is too large Load Diff
+72 -74
View File
@@ -175,7 +175,6 @@ typedef struct DW_CompUnit
Rng1U64 info_range; Rng1U64 info_range;
U64 first_tag_info_off; U64 first_tag_info_off;
DW_AbbrevTable abbrev_table; DW_AbbrevTable abbrev_table;
String8 abbrev_data;
DW_ListUnit *addr_lu; DW_ListUnit *addr_lu;
DW_ListUnit *str_offsets_lu; DW_ListUnit *str_offsets_lu;
DW_ListUnit *rnglists_lu; DW_ListUnit *rnglists_lu;
@@ -192,6 +191,8 @@ typedef struct DW_TagTree
U64 tag_count; U64 tag_count;
} DW_TagTree; } DW_TagTree;
////////////////////////////////
typedef struct DW_LineFile typedef struct DW_LineFile
{ {
String8 file_name; String8 file_name;
@@ -202,42 +203,43 @@ typedef struct DW_LineFile
String8 source; String8 source;
} DW_LineFile; } DW_LineFile;
typedef struct DW_LineVMFileNode typedef struct DW_LineFileNode
{ {
struct DW_LineVMFileNode *next; struct DW_LineFileNode *next;
DW_LineFile file; DW_LineFile file;
} DW_LineVMFileNode; } DW_LineFileNode;
typedef struct DW_LineVMFileList typedef struct DW_LineFileList
{ {
U64 node_count; U64 node_count;
DW_LineVMFileNode *first; DW_LineFileNode *first;
DW_LineVMFileNode *last; DW_LineFileNode *last;
} DW_LineVMFileList; } DW_LineFileList;
typedef struct DW_LineVMFileArray typedef struct DW_LineFileArray
{ {
U64 count; U64 count;
DW_LineFile *v; DW_LineFile *v;
} DW_LineVMFileArray; } DW_LineFileArray;
typedef struct DW_LineVMHeader typedef struct DW_LineVMHeader
{ {
Rng1U64 unit_range; U64 unit_length;
DW_Version version; DW_Version version;
U8 address_size; // Duplicates size from the compilation unit but is needed to support stripped exe that just have .debug_line and .debug_line_str. U8 address_size; // Duplicates size from the compilation unit but is needed to support stripped exe that just have .debug_line and .debug_line_str.
U8 segment_selector_size; U8 segment_selector_size;
U64 header_length; U64 header_length;
U8 min_inst_len; U8 min_inst_len;
U8 max_ops_for_inst; U8 max_ops_for_inst;
U8 default_is_stmt; U8 default_is_stmt;
S8 line_base; S8 line_base;
U8 line_range; U8 line_range;
U8 opcode_base; U8 opcode_base;
U64 num_opcode_lens; U64 num_opcode_lens;
U8 *opcode_lens; U8 *opcode_lens;
DW_LineVMFileArray dir_table; U64 line_program_off;
DW_LineVMFileArray file_table; String8Array dir_table;
DW_LineFileArray file_table;
} DW_LineVMHeader; } DW_LineVMHeader;
typedef struct DW_LineVMState typedef struct DW_LineVMState
@@ -248,10 +250,10 @@ typedef struct DW_LineVMState
// Line table doesn't contain full path to a file, instead // Line table doesn't contain full path to a file, instead
// DWARF encodes path as two indices. First index will point into a directory // DWARF encodes path as two indices. First index will point into a directory
// table, and second points into a file name table. // table, and second points into a file name table.
U32 file_index; U64 file_index;
U32 line; U64 line;
U32 column; U64 column;
B32 is_stmt; // Indicates that "address" points to place suitable for a breakpoint. B32 is_stmt; // Indicates that "address" points to place suitable for a breakpoint.
B32 basic_block; // Indicates that the "address" is inside a basic block. B32 basic_block; // Indicates that the "address" is inside a basic block.
@@ -267,35 +269,33 @@ typedef struct DW_LineVMState
B32 end_sequence; // Indicates that "address" points to the first instruction in the instruction block that follows. B32 end_sequence; // Indicates that "address" points to the first instruction in the instruction block that follows.
} DW_LineVMState; } DW_LineVMState;
typedef struct DW_Line typedef struct DW_LineVM
{ {
U64 file_index; Arena *arena;
U32 line; U64 cursor;
U32 column; String8 program;
U64 address; DW_LineVMHeader header;
} DW_Line; B32 new_line;
B32 new_seq;
typedef struct DW_LineNode B32 skip_opcode;
{ DW_LineVMState state;
struct DW_LineNode *next; U64 advance;
DW_Line v; U64 opcode_off;
} DW_LineNode; DW_StdOpcode opcode;
DW_ExtOpcode ext_opcode;
typedef struct DW_LineSeqNode U64 ext_length;
{ U64 line_advance;
struct DW_LineSeqNode *next; U64 addr_advance;
U64 count; HashTable *ext_file_ht;
DW_LineNode *first; struct {
DW_LineNode *last; union {
} DW_LineSeqNode; String8 string;
U64 u64;
typedef struct DW_LineTableParseResult S64 s64;
{ };
DW_LineVMHeader vm_header; } operands[4];
U64 seq_count; String8 error;
DW_LineSeqNode *first_seq; } DW_LineVM;
DW_LineSeqNode *last_seq;
} DW_LineTableParseResult;
//////////////////////////////// ////////////////////////////////
// .debug_pubnames and .debug_pubtypes // .debug_pubnames and .debug_pubtypes
@@ -460,15 +460,16 @@ internal U64 dw_addr_from_list_unit (DW_ListUnit *lu, U64 index);
// abbrev table // abbrev table
internal U64 dw_read_abbrev_tag (String8 data, U64 offset, DW_Abbrev *out_abbrev); internal U64 dw_read_abbrev_tag (String8 data, U64 offset, DW_Abbrev *out_abbrev);
internal U64 dw_read_abbrev_attrib(String8 data, U64 offset, DW_Abbrev *out_abbrev); internal U64 dw_read_abbrev_attrib(String8 data, U64 offset, DW_Abbrev *out_abbrev);
internal DW_AbbrevTable dw_make_abbrev_table(Arena *arena, String8 abbrev_data, U64 start_abbrev_off);
internal DW_AbbrevTable dw_read_abbrev_table(Arena *arena, String8 abbrev_data, U64 abbrev_base);
internal U64 dw_abbrev_offset_from_abbrev_id(DW_AbbrevTable table, U64 abbrev_id); internal U64 dw_abbrev_offset_from_abbrev_id(DW_AbbrevTable table, U64 abbrev_id);
// form and tag // form and tag
internal U64 dw_read_form(String8 data, U64 off, DW_Version version, DW_Format unit_format, U64 address_size, DW_FormKind form_kind, U64 implicit_const, DW_Form *form_out); internal B32 dw_read_form (String8 data, DW_Version version, DW_Format unit_format, U64 address_size, DW_FormKind form_kind, U64 implicit_const, DW_Form *form_out, U64 *bytes_read_out);
internal U64 dw_read_tag (Arena *arena, String8 tag_data, U64 tag_off, U64 tag_base, DW_AbbrevTable abbrev_table, String8 abbrev_data, DW_Version version, DW_Format unit_format, U64 address_size, DW_Tag *tag_out); internal U64 dw_read_tag (Arena *arena, DW_Input *input, DW_AbbrevTable abbrev_table, DW_Version version, DW_Format format, U64 address_size, Rng1U64 cu_info_range, U64 tag_info_off, DW_Tag *tag_out);
internal U64 dw_read_tag_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 info_off, DW_Tag *tag_out); internal U64 dw_read_tag_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 info_off, DW_Tag *tag_out);
// attrib interp // attrib interp
@@ -530,18 +531,15 @@ internal DW_TagTree dw_tag_tree_from_cu(Arena *arena, DW_Input *input, DW_Comp
internal HashTable * dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree); internal HashTable * dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree);
internal DW_TagNode * dw_tag_node_from_info_off(DW_CompUnit *cu, U64 info_off); internal DW_TagNode * dw_tag_node_from_info_off(DW_CompUnit *cu, U64 info_off);
// line info // line VM
internal U64 dw_read_line_file(String8 line_data, U64 line_off, DW_Input *input, DW_Version unit_version, DW_Format unit_format, DW_Ext ext, U64 address_size, DW_ListUnit *str_offsets, U64 enc_count, U64 *enc_arr, DW_LineFile *line_file_out); internal U64 dw_read_line_vm_header(Arena *arena, DW_Input *input, String8 cu_stmt_list, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out);
internal U64 dw_read_line_vm_header(Arena *arena, String8 line_data, U64 line_off, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out); internal DW_LineVM * dw_line_vm_init(DW_Input *input, DW_CompUnit *cu);
internal void dw_line_vm_reset(DW_LineVMState *state, B32 default_is_stmt); internal void dw_line_vm_release(DW_LineVM *vm);
internal void dw_line_vm_advance(DW_LineVMState *state, U64 advance, U64 min_inst_len, U64 max_ops_for_inst); internal void dw_line_vm_advance(DW_LineVM *vm, U64 advance);
internal DW_LineSeqNode * dw_push_line_seq(Arena* arena, DW_LineTableParseResult *parsed_tbl); internal B32 dw_line_vm_step(DW_LineVM *vm);
internal DW_LineNode * dw_push_line(Arena *arena, DW_LineTableParseResult *tbl, DW_LineVMState *vm_state, B32 start_of_sequence); internal DW_LineFile * dw_line_vm_find_file(DW_LineVM *vm, U64 file_idx);
internal String8 dw_path_from_file(Arena *arena, DW_LineVMHeader *vm, DW_LineFile *file); internal String8 dw_path_from_file(Arena *arena, String8Array dir_table, DW_LineFile *file);
internal String8 dw_path_from_file_idx(Arena *arena, DW_LineVMHeader *vm, U64 file_idx);
internal DW_LineTableParseResult dw_parsed_line_table_from_data(Arena *arena, String8 unit_data, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets);
// helper for .debug_pubtypes and .debug_pubnames // helper for .debug_pubtypes and .debug_pubnames