mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
checkpoint: basic line emission
This commit is contained in:
@@ -166,6 +166,7 @@ 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_Count,
|
||||||
} DW_StdOpcodeEnum;
|
} DW_StdOpcodeEnum;
|
||||||
|
|
||||||
#define DW_ExtOpcode_XList \
|
#define DW_ExtOpcode_XList \
|
||||||
|
|||||||
+587
-90
@@ -49,14 +49,6 @@ dw_size_from_uint(U64 v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
|
||||||
dw_lower_form(DW_WriterFormKind form_kind,
|
|
||||||
DW_WriterForm form,
|
|
||||||
DW_FormKind *form_kind_out,
|
|
||||||
DW_Form *form_out)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal DW_WriterFixupNode *
|
internal DW_WriterFixupNode *
|
||||||
dw_writer_fixup_list_push(Arena *arena, DW_WriterFixupList *list, DW_WriterFixup v)
|
dw_writer_fixup_list_push(Arena *arena, DW_WriterFixupList *list, DW_WriterFixup v)
|
||||||
{
|
{
|
||||||
@@ -118,11 +110,14 @@ dw_writer_begin(DW_Format format, DW_Version version, DW_CompUnitKind cu_kind, A
|
|||||||
writer->address_size = byte_size_from_arch(arch);
|
writer->address_size = byte_size_from_arch(arch);
|
||||||
writer->current = 0;
|
writer->current = 0;
|
||||||
writer->abbrev_id_map = hash_table_init(arena, 0x2000);
|
writer->abbrev_id_map = hash_table_init(arena, 0x2000);
|
||||||
|
writer->line.opcode_base = DW_StdOpcode_Count;
|
||||||
|
writer->line.line_base = -5;
|
||||||
|
writer->line.line_range = 14;
|
||||||
for EachElement(i, writer->sections) {
|
for EachElement(i, writer->sections) {
|
||||||
str8_serial_begin(arena, &writer->sections[i].srl);
|
str8_serial_begin(arena, &writer->sections[i].srl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write .debug_info header
|
// write info header
|
||||||
{
|
{
|
||||||
String8List *srl = &writer->sections[DW_Section_Info].srl;
|
String8List *srl = &writer->sections[DW_Section_Info].srl;
|
||||||
|
|
||||||
@@ -158,6 +153,137 @@ dw_writer_end(DW_Writer **writer_ptr)
|
|||||||
*writer_ptr = 0;
|
*writer_ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal U64
|
||||||
|
dw_serial_push_form(Arena *arena, String8List *srl, DW_Version version, DW_Format format, U8 address_size, DW_WriterFixupList *fixups, DW_WriterXForm form)
|
||||||
|
{
|
||||||
|
U64 start_off = srl->total_size;
|
||||||
|
switch (form.reader.kind) {
|
||||||
|
case DW_Form_Addr: {
|
||||||
|
str8_serial_push_string(arena, srl, form.reader.addr);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Block1:
|
||||||
|
case DW_Form_Block2:
|
||||||
|
case DW_Form_Block4: {
|
||||||
|
str8_serial_push_string(arena, srl, form.reader.block);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Data1:
|
||||||
|
case DW_Form_Data2:
|
||||||
|
case DW_Form_Data4:
|
||||||
|
case DW_Form_Data8: {
|
||||||
|
str8_serial_push_string(arena, srl, form.reader.data);
|
||||||
|
} break;
|
||||||
|
case DW_Form_String: {
|
||||||
|
str8_serial_push_cstr(arena, srl, form.reader.string);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Flag: {
|
||||||
|
str8_serial_push_u8(arena, srl, form.reader.flag);
|
||||||
|
} break;
|
||||||
|
case DW_Form_SData: {
|
||||||
|
dw_serial_push_sleb128(arena, srl, form.reader.sdata);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Strp: {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.sec_offset);
|
||||||
|
} break;
|
||||||
|
case DW_Form_UData: {
|
||||||
|
dw_serial_push_uleb128(arena, srl, form.reader.udata);
|
||||||
|
} break;
|
||||||
|
case DW_Form_RefAddr: {
|
||||||
|
if (version < DW_Version_3) {
|
||||||
|
Assert(address_size <= sizeof(form.reader.ref));
|
||||||
|
str8_serial_push_string(arena, srl, str8((U8 *)&form.reader.ref, address_size));
|
||||||
|
} else {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.ref);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case DW_Form_Ref1: {
|
||||||
|
str8_serial_push_u8(arena, srl, (U8)form.reader.ref);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Ref2: {
|
||||||
|
str8_serial_push_u16(arena, srl, (U16)form.reader.ref);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Ref4: {
|
||||||
|
str8_serial_push_u32(arena, srl, (U32)form.reader.ref);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Ref8: {
|
||||||
|
if (form.writer.ref->info_off == 0) {
|
||||||
|
// reserve 8 bytes
|
||||||
|
void *value = str8_serial_push_u64(arena, srl, 0);
|
||||||
|
|
||||||
|
// push fixup
|
||||||
|
dw_writer_fixup_list_push(arena, fixups, (DW_WriterFixup){ .ptr = value, .tag = form.writer.ref });
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case DW_Form_RefUData: {
|
||||||
|
dw_serial_push_uleb128(arena, srl, form.reader.ref);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Indirect: {
|
||||||
|
NotImplemented;
|
||||||
|
} break;
|
||||||
|
case DW_Form_SecOffset: {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.sec_offset);
|
||||||
|
} break;
|
||||||
|
case DW_Form_ExprLoc: {
|
||||||
|
dw_serial_push_uleb128(arena, srl, form.reader.exprloc.size);
|
||||||
|
str8_serial_push_string(arena, srl, form.reader.exprloc);
|
||||||
|
} break;
|
||||||
|
case DW_Form_FlagPresent: {
|
||||||
|
} break;
|
||||||
|
case DW_Form_RefSig8: {
|
||||||
|
NotImplemented;
|
||||||
|
} break;
|
||||||
|
case DW_Form_Strx:
|
||||||
|
case DW_Form_Addrx:
|
||||||
|
case DW_Form_RngListx:
|
||||||
|
case DW_Form_LocListx: {
|
||||||
|
dw_serial_push_uleb128(arena, srl, form.reader.xval);
|
||||||
|
} break;
|
||||||
|
case DW_Form_RefSup4: {
|
||||||
|
NotImplemented;
|
||||||
|
} break;
|
||||||
|
case DW_Form_StrpSup: {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.strp_sup);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Data16: {
|
||||||
|
str8_serial_push_string(arena, srl, form.reader.data);
|
||||||
|
} break;
|
||||||
|
case DW_Form_LineStrp: {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.sec_offset);
|
||||||
|
} break;
|
||||||
|
case DW_Form_ImplicitConst: {
|
||||||
|
// value is stored in the abbrev entry
|
||||||
|
} break;
|
||||||
|
case DW_Form_RefSup8: {
|
||||||
|
NotImplemented;
|
||||||
|
} break;
|
||||||
|
case DW_Form_Strx1:
|
||||||
|
case DW_Form_Addrx1: {
|
||||||
|
str8_serial_push_u8(arena, srl, (U8)form.reader.xval);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Strx2:
|
||||||
|
case DW_Form_Addrx2: {
|
||||||
|
str8_serial_push_u16(arena, srl, (U16)form.reader.xval);
|
||||||
|
} break;
|
||||||
|
case DW_Form_Strx3:
|
||||||
|
case DW_Form_Addrx3: {
|
||||||
|
str8_serial_push_string(arena, srl, str8((U8 *)&form.reader.xval, 3));
|
||||||
|
} break;
|
||||||
|
case DW_Form_Strx4:
|
||||||
|
case DW_Form_Addrx4: {
|
||||||
|
str8_serial_push_u32(arena, srl, (U32)form.reader.xval);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DW_Form_GNU_StrpAlt: {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.sec_offset);
|
||||||
|
} break;
|
||||||
|
case DW_Form_GNU_RefAlt: {
|
||||||
|
dw_serial_push_uint(arena, srl, format, form.reader.ref);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: InvalidPath; break;
|
||||||
|
}
|
||||||
|
return srl->total_size - start_off;
|
||||||
|
}
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
dw_make_abbrev_entry(Arena *arena, DW_WriterTag *tag)
|
dw_make_abbrev_entry(Arena *arena, DW_WriterTag *tag)
|
||||||
{
|
{
|
||||||
@@ -174,9 +300,9 @@ dw_make_abbrev_entry(Arena *arena, DW_WriterTag *tag)
|
|||||||
// attrib abbrev
|
// attrib abbrev
|
||||||
for EachNode(attrib, DW_WriterAttrib, tag->first_attrib) {
|
for EachNode(attrib, DW_WriterAttrib, tag->first_attrib) {
|
||||||
dw_serial_push_uleb128(scratch.arena, &srl, attrib->kind);
|
dw_serial_push_uleb128(scratch.arena, &srl, attrib->kind);
|
||||||
dw_serial_push_uleb128(scratch.arena, &srl, attrib->reader.form.kind);
|
dw_serial_push_uleb128(scratch.arena, &srl, attrib->form.reader.kind);
|
||||||
if (attrib->reader.form.kind == DW_Form_ImplicitConst) {
|
if (attrib->form.reader.kind == DW_Form_ImplicitConst) {
|
||||||
dw_serial_push_sleb128(scratch.arena, &srl, attrib->reader.form.implicit_const);
|
dw_serial_push_sleb128(scratch.arena, &srl, attrib->form.reader.implicit_const);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +377,7 @@ dw_writer_push_attrib(DW_Writer *writer, DW_AttribKind kind, DW_WriterForm form)
|
|||||||
|
|
||||||
DW_WriterAttrib *attrib = dw_writer_attrib_chunk_list_push(writer->arena, &writer->attrib_chunk_list, 512);
|
DW_WriterAttrib *attrib = dw_writer_attrib_chunk_list_push(writer->arena, &writer->attrib_chunk_list, 512);
|
||||||
attrib->kind = kind;
|
attrib->kind = kind;
|
||||||
attrib->writer.form = form;
|
attrib->form.writer = form;
|
||||||
SLLQueuePush(writer->current->first_attrib, writer->current->last_attrib, attrib);
|
SLLQueuePush(writer->current->first_attrib, writer->current->last_attrib, attrib);
|
||||||
writer->current->attrib_count += 1;
|
writer->current->attrib_count += 1;
|
||||||
return attrib;
|
return attrib;
|
||||||
@@ -358,68 +484,230 @@ dw_writer_push_attrib_implicit(DW_Writer *writer, DW_AttribKind kind, S64 implic
|
|||||||
return dw_writer_push_attrib(writer, kind, (DW_WriterForm){ .kind = DW_WriterFormKind_Implicit, .implicit = implicit });
|
return dw_writer_push_attrib(writer, kind, (DW_WriterForm){ .kind = DW_WriterFormKind_Implicit, .implicit = implicit });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_line_inst_list_push_node(DW_LineInstList *list, DW_LineInstNode *node)
|
||||||
|
{
|
||||||
|
SLLQueuePush(list->first, list->last, node);
|
||||||
|
list->count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DW_LineInstNode *
|
||||||
|
dw_line_inst_list_push(Arena *arena, DW_LineInstList *list, DW_LineInst v)
|
||||||
|
{
|
||||||
|
DW_LineInstNode *node = push_array(arena, DW_LineInstNode, 1);
|
||||||
|
node->v = v;
|
||||||
|
dw_line_inst_list_push_node(list, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
dw_data_from_line_insts(Arena *arena, U8 address_size, DW_LineInstList insts)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
String8List srl = {0};
|
||||||
|
str8_serial_begin(scratch.arena, &srl);
|
||||||
|
|
||||||
|
for EachNode(inst_n, DW_LineInstNode, insts.first) {
|
||||||
|
DW_LineInst *inst = &inst_n->v;
|
||||||
|
|
||||||
|
str8_serial_push_struct(scratch.arena, &srl, &inst->opcode);
|
||||||
|
switch (inst->opcode) {
|
||||||
|
case DW_StdOpcode_Copy: {} break;
|
||||||
|
case DW_StdOpcode_AdvancePc: {
|
||||||
|
dw_serial_push_uleb128(arena, &srl, inst->advance_pc);
|
||||||
|
} break;
|
||||||
|
case DW_StdOpcode_AdvanceLine: {
|
||||||
|
dw_serial_push_sleb128(arena, &srl, inst->advance_line);
|
||||||
|
} break;
|
||||||
|
case DW_StdOpcode_SetFile: {
|
||||||
|
dw_serial_push_uleb128(arena, &srl, inst->set_file->file_idx);
|
||||||
|
} break;
|
||||||
|
case DW_StdOpcode_SetColumn: {
|
||||||
|
dw_serial_push_uleb128(arena, &srl, inst->set_column);
|
||||||
|
} break;
|
||||||
|
case DW_StdOpcode_NegateStmt: {} break;
|
||||||
|
case DW_StdOpcode_SetBasicBlock: {} break;
|
||||||
|
case DW_StdOpcode_ConstAddPc: {} break;
|
||||||
|
case DW_StdOpcode_FixedAdvancePc: {
|
||||||
|
str8_serial_push_u16(arena, &srl, inst->fixed_advance_pc);
|
||||||
|
} break;
|
||||||
|
case DW_StdOpcode_SetPrologueEnd: {} break;
|
||||||
|
case DW_StdOpcode_SetEpilogueBegin: {} break;
|
||||||
|
case DW_StdOpcode_SetIsa: {} break;
|
||||||
|
case DW_StdOpcode_ExtendedOpcode: {
|
||||||
|
// get ext size
|
||||||
|
U64 ext_size = 0;
|
||||||
|
switch (inst->ext) {
|
||||||
|
case DW_ExtOpcode_EndSequence: { ext_size = 0; } break;
|
||||||
|
case DW_ExtOpcode_SetAddress: { ext_size = address_size; } break;
|
||||||
|
case DW_ExtOpcode_DefineFile: {
|
||||||
|
NotImplemented;
|
||||||
|
} break;
|
||||||
|
case DW_ExtOpcode_SetDiscriminator: {
|
||||||
|
ext_size = dw_size_from_uleb128(inst->set_discriminator);
|
||||||
|
} break;
|
||||||
|
default: { InvalidPath; } break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write ext header
|
||||||
|
dw_serial_push_uleb128(arena, &srl, ext_size);
|
||||||
|
str8_serial_push_struct(arena, &srl, &inst->ext);
|
||||||
|
|
||||||
|
// write ext operands
|
||||||
|
switch (inst->ext) {
|
||||||
|
case DW_ExtOpcode_EndSequence: {} break;
|
||||||
|
case DW_ExtOpcode_SetAddress: {
|
||||||
|
dw_serial_push_uleb128(arena, &srl, inst->set_address);
|
||||||
|
} break;
|
||||||
|
case DW_ExtOpcode_DefineFile: {
|
||||||
|
NotImplemented;
|
||||||
|
} break;
|
||||||
|
case DW_ExtOpcode_SetDiscriminator: {
|
||||||
|
dw_serial_push_uleb128(arena, &srl, inst->set_discriminator);
|
||||||
|
} break;
|
||||||
|
default: { InvalidPath; } break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
// special opcode
|
||||||
|
default: {} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 data = str8_serial_end(arena, &srl);
|
||||||
|
scratch_end(scratch);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_emit(DW_Writer *writer, DW_WriterFile *file, U64 ln, U64 col, U64 addr)
|
||||||
|
{
|
||||||
|
if (writer->line.last_file != file) {
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_file(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert(addr <= max_S64);
|
||||||
|
S64 addr_delta = (S64)addr - (S64)writer->line.addr;
|
||||||
|
if (addr_delta != 0) {
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(addr_delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
S64 ln_delta = (S64)ln - (S64)writer->line.ln;
|
||||||
|
if (ln_delta != 0) {
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(ln_delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
S64 col_delta = (S64)col - (S64)writer->line.col;
|
||||||
|
if (col_delta != 0) {
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_column(col_delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append row
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_copy());
|
||||||
|
|
||||||
|
writer->line.file = file;
|
||||||
|
writer->line.ln = ln;
|
||||||
|
writer->line.col = col;
|
||||||
|
writer->line.addr = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_set_address(DW_Writer *writer, U64 address)
|
||||||
|
{
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_address(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_set_prologue_end(DW_Writer *writer)
|
||||||
|
{
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_prologue_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_epilogue_begin(DW_Writer *writer)
|
||||||
|
{
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_epilogue_begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_set_isa(DW_Writer *writer, U64 isa)
|
||||||
|
{
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_isa(isa));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DW_WriterFile *
|
||||||
|
dw_writer_new_file(DW_Writer *writer, String8 path)
|
||||||
|
{
|
||||||
|
DW_WriterFile *file = push_array(writer->arena, DW_WriterFile, 1);
|
||||||
|
file->path = path;
|
||||||
|
file->file_idx = writer->line.file_count;
|
||||||
|
|
||||||
|
SLLQueuePush(writer->line.first_file, writer->line.last_file, file);
|
||||||
|
writer->line.file_count += 1;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
dw_lower_attrib_forms(DW_Writer *writer, DW_WriterTag *tag)
|
dw_lower_attrib_forms(DW_Writer *writer, DW_WriterTag *tag)
|
||||||
{
|
{
|
||||||
for EachNode(attrib, DW_WriterAttrib, tag->first_attrib) {
|
for EachNode(attrib, DW_WriterAttrib, tag->first_attrib) {
|
||||||
switch (attrib->writer.form.kind) {
|
switch (attrib->form.writer.kind) {
|
||||||
case DW_WriterFormKind_Null: {} break;
|
case DW_WriterFormKind_Null: {} break;
|
||||||
case DW_WriterFormKind_Flag: {
|
case DW_WriterFormKind_Flag: {
|
||||||
attrib->reader.form.kind = DW_Form_Flag;
|
attrib->form.reader.kind = DW_Form_Flag;
|
||||||
attrib->reader.form.flag = attrib->writer.form.flag;
|
attrib->form.reader.flag = attrib->form.writer.flag;
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_SInt: {
|
case DW_WriterFormKind_SInt: {
|
||||||
switch (dw_int_enc_from_sint(attrib->writer.form.sint)) {
|
switch (dw_int_enc_from_sint(attrib->form.writer.sint)) {
|
||||||
case DW_IntEnc_Null: attrib->reader.form.kind = 0; break;
|
case DW_IntEnc_Null: attrib->form.reader.kind = 0; break;
|
||||||
case DW_IntEnc_1Byte: {
|
case DW_IntEnc_1Byte: {
|
||||||
attrib->reader.form.kind = DW_Form_Data1;
|
attrib->form.reader.kind = DW_Form_Data1;
|
||||||
attrib->reader.form.data = str8((U8 *)&attrib->writer.form.sint, sizeof(S8));
|
attrib->form.reader.data = str8((U8 *)&attrib->form.writer.sint, sizeof(S8));
|
||||||
} break;
|
} break;
|
||||||
case DW_IntEnc_2Byte: {
|
case DW_IntEnc_2Byte: {
|
||||||
attrib->reader.form.kind = DW_Form_Data2;
|
attrib->form.reader.kind = DW_Form_Data2;
|
||||||
attrib->reader.form.data = str8((U8 *)&attrib->writer.form.sint, sizeof(S16));
|
attrib->form.reader.data = str8((U8 *)&attrib->form.writer.sint, sizeof(S16));
|
||||||
} break;
|
} break;
|
||||||
case DW_IntEnc_4Byte: {
|
case DW_IntEnc_4Byte: {
|
||||||
attrib->reader.form.kind = DW_Form_Data4;
|
attrib->form.reader.kind = DW_Form_Data4;
|
||||||
attrib->reader.form.data = str8((U8 *)&attrib->writer.form.sint, sizeof(U32));
|
attrib->form.reader.data = str8((U8 *)&attrib->form.writer.sint, sizeof(U32));
|
||||||
} break;
|
} break;
|
||||||
case DW_IntEnc_LEB128: {
|
case DW_IntEnc_LEB128: {
|
||||||
attrib->reader.form.kind = DW_Form_SData;
|
attrib->form.reader.kind = DW_Form_SData;
|
||||||
attrib->reader.form.sdata = attrib->writer.form.sint;
|
attrib->form.reader.sdata = attrib->form.writer.sint;
|
||||||
} break;
|
} break;
|
||||||
default: InvalidPath; break;
|
default: InvalidPath; break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_UInt: {
|
case DW_WriterFormKind_UInt: {
|
||||||
attrib->reader.form.kind = DW_Form_UData;
|
attrib->form.reader.kind = DW_Form_UData;
|
||||||
attrib->reader.form.udata = attrib->writer.form.uint;
|
attrib->form.reader.udata = attrib->form.writer.uint;
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_Address: {
|
case DW_WriterFormKind_Address: {
|
||||||
Assert(writer->address_size <= sizeof(attrib->writer.form.address));
|
Assert(writer->address_size <= sizeof(attrib->form.writer.address));
|
||||||
attrib->reader.form.kind = DW_Form_Addr;
|
attrib->form.reader.kind = DW_Form_Addr;
|
||||||
attrib->reader.form.addr = push_str8_copy(writer->arena, str8((U8 *)&attrib->writer.form.address, writer->address_size));
|
attrib->form.reader.addr = push_str8_copy(writer->arena, str8((U8 *)&attrib->form.writer.address, writer->address_size));
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_Ref: {
|
case DW_WriterFormKind_Ref: {
|
||||||
if (attrib->writer.form.ref->info_off == 0) {
|
if (attrib->form.writer.ref->info_off == 0) {
|
||||||
attrib->reader.form.kind = DW_Form_Ref8;
|
attrib->form.reader.kind = DW_Form_Ref8;
|
||||||
} else {
|
} else {
|
||||||
switch (dw_int_enc_from_uint(attrib->writer.form.ref->info_off)) {
|
switch (dw_int_enc_from_uint(attrib->form.writer.ref->info_off)) {
|
||||||
case DW_IntEnc_Null: break;
|
case DW_IntEnc_Null: break;
|
||||||
case DW_IntEnc_1Byte: {
|
case DW_IntEnc_1Byte: {
|
||||||
attrib->reader.form.kind = DW_Form_Ref1;
|
attrib->form.reader.kind = DW_Form_Ref1;
|
||||||
attrib->reader.form.ref = (U8)attrib->writer.form.ref->info_off;
|
attrib->form.reader.ref = (U8)attrib->form.writer.ref->info_off;
|
||||||
} break;
|
} break;
|
||||||
case DW_IntEnc_2Byte: {
|
case DW_IntEnc_2Byte: {
|
||||||
attrib->reader.form.kind = DW_Form_Ref2;
|
attrib->form.reader.kind = DW_Form_Ref2;
|
||||||
attrib->reader.form.ref = (U16)attrib->writer.form.ref->info_off;
|
attrib->form.reader.ref = (U16)attrib->form.writer.ref->info_off;
|
||||||
} break;
|
} break;
|
||||||
case DW_IntEnc_4Byte: {
|
case DW_IntEnc_4Byte: {
|
||||||
attrib->reader.form.kind = DW_Form_Ref4;
|
attrib->form.reader.kind = DW_Form_Ref4;
|
||||||
attrib->reader.form.ref = (U32)attrib->writer.form.ref->info_off;
|
attrib->form.reader.ref = (U32)attrib->form.writer.ref->info_off;
|
||||||
} break;
|
} break;
|
||||||
case DW_IntEnc_LEB128: {
|
case DW_IntEnc_LEB128: {
|
||||||
attrib->reader.form.kind = DW_Form_RefUData;
|
attrib->form.reader.kind = DW_Form_RefUData;
|
||||||
attrib->reader.form.ref = attrib->writer.form.ref->info_off;
|
attrib->form.reader.ref = attrib->form.writer.ref->info_off;
|
||||||
} break;
|
} break;
|
||||||
default: InvalidPath; break;
|
default: InvalidPath; break;
|
||||||
}
|
}
|
||||||
@@ -438,26 +726,26 @@ dw_lower_attrib_forms(DW_Writer *writer, DW_WriterTag *tag)
|
|||||||
NotImplemented;
|
NotImplemented;
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_Block: {
|
case DW_WriterFormKind_Block: {
|
||||||
attrib->reader.form.block = attrib->writer.form.block;
|
attrib->form.reader.block = attrib->form.writer.block;
|
||||||
switch (attrib->writer.form.block.size) {
|
switch (attrib->form.writer.block.size) {
|
||||||
case 0 : break;
|
case 0 : break;
|
||||||
case 1 : attrib->reader.form.kind = DW_Form_Block1; break;
|
case 1 : attrib->form.reader.kind = DW_Form_Block1; break;
|
||||||
case 2 : attrib->reader.form.kind = DW_Form_Block2; break;
|
case 2 : attrib->form.reader.kind = DW_Form_Block2; break;
|
||||||
case 4 : attrib->reader.form.kind = DW_Form_Block4; break;
|
case 4 : attrib->form.reader.kind = DW_Form_Block4; break;
|
||||||
default: attrib->reader.form.kind = DW_Form_Block; break;
|
default: attrib->form.reader.kind = DW_Form_Block; break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_String: {
|
case DW_WriterFormKind_String: {
|
||||||
attrib->reader.form.kind = DW_Form_String;
|
attrib->form.reader.kind = DW_Form_String;
|
||||||
attrib->reader.form.string = attrib->writer.form.string;
|
attrib->form.reader.string = attrib->form.writer.string;
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_ExprLoc: {
|
case DW_WriterFormKind_ExprLoc: {
|
||||||
attrib->reader.form.kind = DW_Form_ExprLoc;
|
attrib->form.reader.kind = DW_Form_ExprLoc;
|
||||||
attrib->reader.form.exprloc = attrib->writer.form.exprloc;
|
attrib->form.reader.exprloc = attrib->form.writer.exprloc;
|
||||||
} break;
|
} break;
|
||||||
case DW_WriterFormKind_Implicit: {
|
case DW_WriterFormKind_Implicit: {
|
||||||
attrib->reader.form.kind = DW_Form_ImplicitConst;
|
attrib->form.reader.kind = DW_Form_ImplicitConst;
|
||||||
attrib->reader.form.implicit_const = attrib->writer.form.implicit;
|
attrib->form.reader.implicit_const = attrib->form.writer.implicit;
|
||||||
} break;
|
} break;
|
||||||
default: { InvalidPath; } break;
|
default: { InvalidPath; } break;
|
||||||
}
|
}
|
||||||
@@ -500,74 +788,74 @@ dw_writer_emit_tag(DW_Writer *writer, DW_WriterTag *tag)
|
|||||||
{
|
{
|
||||||
String8List *debug_info = &writer->sections[DW_Section_Info].srl;
|
String8List *debug_info = &writer->sections[DW_Section_Info].srl;
|
||||||
for EachNode(attrib, DW_WriterAttrib, tag->first_attrib) {
|
for EachNode(attrib, DW_WriterAttrib, tag->first_attrib) {
|
||||||
switch (attrib->reader.form.kind) {
|
switch (attrib->form.reader.kind) {
|
||||||
case DW_Form_Addr: {
|
case DW_Form_Addr: {
|
||||||
str8_serial_push_string(writer->arena, debug_info, attrib->reader.form.addr);
|
str8_serial_push_string(writer->arena, debug_info, attrib->form.reader.addr);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Block1:
|
case DW_Form_Block1:
|
||||||
case DW_Form_Block2:
|
case DW_Form_Block2:
|
||||||
case DW_Form_Block4: {
|
case DW_Form_Block4: {
|
||||||
str8_serial_push_string(writer->arena, debug_info, attrib->reader.form.block);
|
str8_serial_push_string(writer->arena, debug_info, attrib->form.reader.block);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Data1:
|
case DW_Form_Data1:
|
||||||
case DW_Form_Data2:
|
case DW_Form_Data2:
|
||||||
case DW_Form_Data4:
|
case DW_Form_Data4:
|
||||||
case DW_Form_Data8: {
|
case DW_Form_Data8: {
|
||||||
str8_serial_push_string(writer->arena, debug_info, attrib->reader.form.data);
|
str8_serial_push_string(writer->arena, debug_info, attrib->form.reader.data);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_String: {
|
case DW_Form_String: {
|
||||||
str8_serial_push_cstr(writer->arena, debug_info, attrib->reader.form.string);
|
str8_serial_push_cstr(writer->arena, debug_info, attrib->form.reader.string);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Flag: {
|
case DW_Form_Flag: {
|
||||||
str8_serial_push_u8(writer->arena, debug_info, attrib->reader.form.flag);
|
str8_serial_push_u8(writer->arena, debug_info, attrib->form.reader.flag);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_SData: {
|
case DW_Form_SData: {
|
||||||
dw_serial_push_sleb128(writer->arena, debug_info, attrib->reader.form.sdata);
|
dw_serial_push_sleb128(writer->arena, debug_info, attrib->form.reader.sdata);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Strp: {
|
case DW_Form_Strp: {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.sec_offset);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.sec_offset);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_UData: {
|
case DW_Form_UData: {
|
||||||
dw_serial_push_uleb128(writer->arena, debug_info, attrib->reader.form.udata);
|
dw_serial_push_uleb128(writer->arena, debug_info, attrib->form.reader.udata);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_RefAddr: {
|
case DW_Form_RefAddr: {
|
||||||
if (writer->version < DW_Version_3) {
|
if (writer->version < DW_Version_3) {
|
||||||
Assert(writer->address_size <= sizeof(attrib->reader.form.ref));
|
Assert(writer->address_size <= sizeof(attrib->form.reader.ref));
|
||||||
str8_serial_push_string(writer->arena, debug_info, str8((U8 *)&attrib->reader.form.ref, writer->address_size));
|
str8_serial_push_string(writer->arena, debug_info, str8((U8 *)&attrib->form.reader.ref, writer->address_size));
|
||||||
} else {
|
} else {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.ref);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.ref);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Ref1: {
|
case DW_Form_Ref1: {
|
||||||
str8_serial_push_u8(writer->arena, debug_info, (U8)attrib->reader.form.ref);
|
str8_serial_push_u8(writer->arena, debug_info, (U8)attrib->form.reader.ref);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Ref2: {
|
case DW_Form_Ref2: {
|
||||||
str8_serial_push_u16(writer->arena, debug_info, (U16)attrib->reader.form.ref);
|
str8_serial_push_u16(writer->arena, debug_info, (U16)attrib->form.reader.ref);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Ref4: {
|
case DW_Form_Ref4: {
|
||||||
str8_serial_push_u32(writer->arena, debug_info, (U32)attrib->reader.form.ref);
|
str8_serial_push_u32(writer->arena, debug_info, (U32)attrib->form.reader.ref);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Ref8: {
|
case DW_Form_Ref8: {
|
||||||
if (attrib->writer.form.ref->info_off == 0) {
|
if (attrib->form.writer.ref->info_off == 0) {
|
||||||
// reserve 8 bytes
|
// reserve 8 bytes
|
||||||
void *value = str8_serial_push_u64(writer->arena, debug_info, 0);
|
void *value = str8_serial_push_u64(writer->arena, debug_info, 0);
|
||||||
|
|
||||||
// push fixup
|
// push fixup
|
||||||
dw_writer_fixup_list_push(writer->arena, &writer->fixups, (DW_WriterFixup){ .value = value, .attrib = attrib });
|
dw_writer_fixup_list_push(writer->arena, &writer->fixups, (DW_WriterFixup){ .tag = attrib->form.writer.ref, .ptr = value });
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_RefUData: {
|
case DW_Form_RefUData: {
|
||||||
dw_serial_push_uleb128(writer->arena, debug_info, attrib->reader.form.ref);
|
dw_serial_push_uleb128(writer->arena, debug_info, attrib->form.reader.ref);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Indirect: {
|
case DW_Form_Indirect: {
|
||||||
NotImplemented;
|
NotImplemented;
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_SecOffset: {
|
case DW_Form_SecOffset: {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.sec_offset);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.sec_offset);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_ExprLoc: {
|
case DW_Form_ExprLoc: {
|
||||||
dw_serial_push_uleb128(writer->arena, debug_info, attrib->reader.form.exprloc.size);
|
dw_serial_push_uleb128(writer->arena, debug_info, attrib->form.reader.exprloc.size);
|
||||||
str8_serial_push_string(writer->arena, debug_info, attrib->reader.form.exprloc);
|
str8_serial_push_string(writer->arena, debug_info, attrib->form.reader.exprloc);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_FlagPresent: {
|
case DW_Form_FlagPresent: {
|
||||||
} break;
|
} break;
|
||||||
@@ -578,19 +866,19 @@ dw_writer_emit_tag(DW_Writer *writer, DW_WriterTag *tag)
|
|||||||
case DW_Form_Addrx:
|
case DW_Form_Addrx:
|
||||||
case DW_Form_RngListx:
|
case DW_Form_RngListx:
|
||||||
case DW_Form_LocListx: {
|
case DW_Form_LocListx: {
|
||||||
dw_serial_push_uleb128(writer->arena, debug_info, attrib->reader.form.xval);
|
dw_serial_push_uleb128(writer->arena, debug_info, attrib->form.reader.xval);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_RefSup4: {
|
case DW_Form_RefSup4: {
|
||||||
NotImplemented;
|
NotImplemented;
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_StrpSup: {
|
case DW_Form_StrpSup: {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.strp_sup);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.strp_sup);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Data16: {
|
case DW_Form_Data16: {
|
||||||
str8_serial_push_string(writer->arena, debug_info, attrib->reader.form.data);
|
str8_serial_push_string(writer->arena, debug_info, attrib->form.reader.data);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_LineStrp: {
|
case DW_Form_LineStrp: {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.sec_offset);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.sec_offset);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_ImplicitConst: {
|
case DW_Form_ImplicitConst: {
|
||||||
// value is stored in the abbrev entry
|
// value is stored in the abbrev entry
|
||||||
@@ -600,26 +888,26 @@ dw_writer_emit_tag(DW_Writer *writer, DW_WriterTag *tag)
|
|||||||
} break;
|
} break;
|
||||||
case DW_Form_Strx1:
|
case DW_Form_Strx1:
|
||||||
case DW_Form_Addrx1: {
|
case DW_Form_Addrx1: {
|
||||||
str8_serial_push_u8(writer->arena, debug_info, (U8)attrib->reader.form.xval);
|
str8_serial_push_u8(writer->arena, debug_info, (U8)attrib->form.reader.xval);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Strx2:
|
case DW_Form_Strx2:
|
||||||
case DW_Form_Addrx2: {
|
case DW_Form_Addrx2: {
|
||||||
str8_serial_push_u16(writer->arena, debug_info, (U16)attrib->reader.form.xval);
|
str8_serial_push_u16(writer->arena, debug_info, (U16)attrib->form.reader.xval);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Strx3:
|
case DW_Form_Strx3:
|
||||||
case DW_Form_Addrx3: {
|
case DW_Form_Addrx3: {
|
||||||
str8_serial_push_string(writer->arena, debug_info, str8((U8 *)&attrib->reader.form.xval, 3));
|
str8_serial_push_string(writer->arena, debug_info, str8((U8 *)&attrib->form.reader.xval, 3));
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_Strx4:
|
case DW_Form_Strx4:
|
||||||
case DW_Form_Addrx4: {
|
case DW_Form_Addrx4: {
|
||||||
str8_serial_push_u32(writer->arena, debug_info, (U32)attrib->reader.form.xval);
|
str8_serial_push_u32(writer->arena, debug_info, (U32)attrib->form.reader.xval);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_Form_GNU_StrpAlt: {
|
case DW_Form_GNU_StrpAlt: {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.sec_offset);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.sec_offset);
|
||||||
} break;
|
} break;
|
||||||
case DW_Form_GNU_RefAlt: {
|
case DW_Form_GNU_RefAlt: {
|
||||||
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->reader.form.ref);
|
dw_serial_push_uint(writer->arena, debug_info, writer->format, attrib->form.reader.ref);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: InvalidPath; break;
|
default: InvalidPath; break;
|
||||||
@@ -641,11 +929,222 @@ dw_writer_emit_tag(DW_Writer *writer, DW_WriterTag *tag)
|
|||||||
internal void
|
internal void
|
||||||
dw_writer_emit(DW_Writer *writer)
|
dw_writer_emit(DW_Writer *writer)
|
||||||
{
|
{
|
||||||
|
// line
|
||||||
|
{
|
||||||
|
// push line table terminator
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_end_sequence());
|
||||||
|
|
||||||
|
// find comp dir in the compile unit tag
|
||||||
|
String8 comp_dir = {0};
|
||||||
|
String8 comp_name = {0};
|
||||||
|
Assert(writer->root->kind == DW_TagKind_CompileUnit);
|
||||||
|
for EachNode(attrib, DW_WriterAttrib, writer->root->first_attrib) {
|
||||||
|
if (attrib->kind == DW_AttribKind_CompDir) {
|
||||||
|
AssertAlways(attrib->form.writer.kind == DW_WriterFormKind_String);
|
||||||
|
comp_dir = attrib->form.writer.string;
|
||||||
|
} else if (attrib->kind == DW_AttribKind_Name) {
|
||||||
|
AssertAlways(attrib->form.writer.kind == DW_WriterFormKind_String);
|
||||||
|
comp_name = attrib->form.writer.string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String8List dir_table_srl = {0};
|
||||||
|
str8_serial_begin(writer->arena, &dir_table_srl);
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
String8List *srl = &dir_table_srl;
|
||||||
|
|
||||||
|
// (13) directory_entry_format_count
|
||||||
|
str8_serial_push_u8(writer->arena, srl, 1);
|
||||||
|
// (14) directory_entry_format
|
||||||
|
dw_serial_push_uleb128(writer->arena, srl, DW_LNCT_Path);
|
||||||
|
dw_serial_push_uleb128(writer->arena, srl, DW_Form_String);
|
||||||
|
|
||||||
|
// dedup directories
|
||||||
|
HashTable *dir_ht = hash_table_init(scratch.arena, writer->line.file_count + 1);
|
||||||
|
// first entry must be compile unit directory
|
||||||
|
hash_table_push_string_u64(scratch.arena, dir_ht, comp_dir, dir_ht->count);
|
||||||
|
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
||||||
|
String8 path = str8_chop_last_slash(file->path);
|
||||||
|
if ( ! hash_table_search_string_u64(dir_ht, path, &file->dir_idx)) {
|
||||||
|
file->dir_idx = hash_table_push_string_u64(scratch.arena, dir_ht, path, dir_ht->count)->v.value_u64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyValuePair *dirs_kv = key_value_pairs_from_hash_table(scratch.arena, dir_ht);
|
||||||
|
sort_key_value_pairs_as_string_sensitive(dirs_kv, dir_ht->count);
|
||||||
|
|
||||||
|
// (15) directories_count
|
||||||
|
dw_serial_push_uleb128(writer->arena, srl, dir_ht->count);
|
||||||
|
// (16) directories
|
||||||
|
for (U64 i = 1; i < dir_ht->count; i += 1) {
|
||||||
|
String8 dir = dirs_kv[i].key_string;
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, (DW_WriterXForm) { .reader = { .kind = DW_Form_String, .string = dir } });
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
String8List file_table_srl = {0};
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
String8List *srl = &file_table_srl;
|
||||||
|
|
||||||
|
struct { DW_LNCT lnct; DW_FormKind form_kind; } encs[] = {
|
||||||
|
{ DW_LNCT_Path, DW_Form_String },
|
||||||
|
{ DW_LNCT_DirectoryIndex, DW_Form_UData },
|
||||||
|
{ DW_LNCT_TimeStamp, DW_Form_Null }, // DW_Form_UData
|
||||||
|
{ DW_LNCT_Size, DW_Form_Null }, // DW_Form_UData
|
||||||
|
{ DW_LNCT_MD5, DW_Form_Null }, // DW_Form_Block
|
||||||
|
{ DW_LNCT_LLVM_Source, DW_Form_Null } // DW_Form_String
|
||||||
|
};
|
||||||
|
|
||||||
|
HashTable *encs_ht = hash_table_init(scratch.arena, ArrayCount(encs) * 2);
|
||||||
|
for EachElement(i, encs) { hash_table_push_u64_raw(scratch.arena, encs_ht, encs[i].lnct, &encs[i].form_kind); }
|
||||||
|
|
||||||
|
// enable encodings in use
|
||||||
|
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
||||||
|
if (file->time_stamp != 0) { *(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_TimeStamp ) = DW_Form_UData; }
|
||||||
|
if (file->size != 0) { *(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_Size ) = DW_Form_UData; }
|
||||||
|
if (file->md5.size != 0) { *(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_MD5 ) = DW_Form_Block; }
|
||||||
|
if (file->source.size != 0) { *(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_LLVM_Source) = DW_Form_String; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// count needed encodings
|
||||||
|
U64 enc_count = 0;
|
||||||
|
for EachElement(i, encs) { if (encs[i].form_kind != DW_Form_Null) { enc_count += 1; } }
|
||||||
|
|
||||||
|
// (17) file_name_entry_format_count
|
||||||
|
str8_serial_push_u16(writer->arena, srl, enc_count);
|
||||||
|
|
||||||
|
// (18) file_name_entry_format
|
||||||
|
for EachElement(i, encs) {
|
||||||
|
if (encs[i].form_kind == DW_Form_Null) { continue; }
|
||||||
|
dw_serial_push_uleb128(writer->arena, srl, encs[i].lnct );
|
||||||
|
dw_serial_push_uleb128(writer->arena, srl, encs[i].form_kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (19) file_names_count
|
||||||
|
dw_serial_push_uleb128(writer->arena, srl, writer->line.file_count);
|
||||||
|
|
||||||
|
// (20) file_names
|
||||||
|
if (comp_name.size) {
|
||||||
|
for (DW_WriterFile *n = writer->line.first_file, *p = 0; n != 0; p = n, n = n->next) {
|
||||||
|
String8 file_name = str8_skip_last_slash(n->path);
|
||||||
|
if (str8_match(file_name, comp_name, 0)) {
|
||||||
|
if (p == 0) {
|
||||||
|
// file is already first
|
||||||
|
} else {
|
||||||
|
// move compile unit file to be first entry in the table
|
||||||
|
p->next = n->next;
|
||||||
|
n->next = writer->line.first_file;
|
||||||
|
writer->line.first_file = n;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
||||||
|
static DW_WriterXForm null_form_udata = { .reader = { .kind = DW_Form_UData } };
|
||||||
|
static DW_WriterXForm null_form_string = { .reader = { .kind = DW_Form_String } };
|
||||||
|
static DW_WriterXForm null_form_block = { .reader = { .kind = DW_Form_Block } };
|
||||||
|
|
||||||
|
// path
|
||||||
|
Assert(*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_Path) == DW_Form_String);
|
||||||
|
DW_WriterXForm path_form = { .reader = { .kind = DW_Form_String, .string = file->path } };
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, path_form);
|
||||||
|
|
||||||
|
// directory index
|
||||||
|
Assert(*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_DirectoryIndex) == DW_Form_UData);
|
||||||
|
DW_WriterXForm dir_idx_form = { .reader = { .kind = DW_Form_UData, .udata = file->time_stamp } };
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, dir_idx_form);
|
||||||
|
|
||||||
|
// time stamp
|
||||||
|
if (*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_TimeStamp) == DW_Form_UData) {
|
||||||
|
if (file->time_stamp) {
|
||||||
|
DW_WriterXForm time_stamp_form = { .reader = { .kind = DW_Form_UData, .udata = file->time_stamp } };
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, time_stamp_form);
|
||||||
|
} else {
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, null_form_udata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// size
|
||||||
|
if (*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_Size) == DW_Form_UData) {
|
||||||
|
if (file->size) {
|
||||||
|
DW_WriterXForm size_form = { .reader = { .kind = DW_Form_UData, .udata = file->size } };
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, size_form);
|
||||||
|
} else {
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, null_form_udata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MD5
|
||||||
|
if (*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_MD5) == DW_Form_Block) {
|
||||||
|
if (file->md5.size) {
|
||||||
|
DW_WriterXForm md5_form = { .reader = { .kind = DW_Form_Block, .block = file->md5 } };
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, md5_form);
|
||||||
|
} else {
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, null_form_block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LLVM Source
|
||||||
|
if (*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_LLVM_Source) == DW_Form_String) {
|
||||||
|
if (file->source.size) {
|
||||||
|
DW_WriterXForm source_form = { .reader = { .kind = DW_Form_String, .string = file->source } };
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, source_form);
|
||||||
|
} else {
|
||||||
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, null_form_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
String8List *srl = &writer->sections[DW_Section_Line].srl;
|
||||||
|
// (1) unit_length
|
||||||
|
writer->sections[DW_Section_Line].length = dw_serial_push_length(writer->arena, srl, writer->format, 0);
|
||||||
|
// (2) version
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->version);
|
||||||
|
// (3) address_size
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->address_size);
|
||||||
|
// (4) segment_selector_size
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->segsel_size);
|
||||||
|
// (5) header_length
|
||||||
|
U64 header_size = srl->total_size + dir_table_srl.total_size + file_table_srl.total_size;
|
||||||
|
dw_serial_push_uint(writer->arena, srl, writer->format, header_size);
|
||||||
|
// (6) minimum_instruction_length
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.min_inst_len);
|
||||||
|
// (7) maximum_operations_per_instruction
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.max_ops_per_inst);
|
||||||
|
// (8) default_is_stmt
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.default_is_stmt);
|
||||||
|
// (9) line_base
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.line_base);
|
||||||
|
// (10) line_range
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.line_range);
|
||||||
|
// (11) opcode_base
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.opcode_base);
|
||||||
|
// (12) standard_opcode_lengths
|
||||||
|
str8_serial_push_struct(writer->arena, srl, &writer->line.std_op_lens);
|
||||||
|
// directory table
|
||||||
|
str8_list_concat_in_place(srl, &dir_table_srl);
|
||||||
|
// file table
|
||||||
|
str8_list_concat_in_place(srl, &file_table_srl);
|
||||||
|
// line program
|
||||||
|
String8 line_program_data = dw_data_from_line_insts(writer->arena, writer->address_size, writer->line.line_insts);
|
||||||
|
str8_serial_push_string(writer->arena, srl, line_program_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// info
|
||||||
|
{
|
||||||
dw_writer_emit_tag(writer, writer->root);
|
dw_writer_emit_tag(writer, writer->root);
|
||||||
|
|
||||||
// null terminate .debug_abbrev
|
// null terminate .debug_abbrev
|
||||||
dw_serial_push_uleb128(writer->arena, &writer->sections[DW_Section_Abbrev].srl, 0);
|
dw_serial_push_uleb128(writer->arena, &writer->sections[DW_Section_Abbrev].srl, 0);
|
||||||
dw_serial_push_uleb128(writer->arena, &writer->sections[DW_Section_Abbrev].srl, 0);
|
|
||||||
|
|
||||||
// fixup units lengths
|
// fixup units lengths
|
||||||
for EachElement(i, writer->sections) {
|
for EachElement(i, writer->sections) {
|
||||||
@@ -667,10 +1166,8 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
// fixup forward references in .debug_info
|
// fixup forward references in .debug_info
|
||||||
for EachNode(fixup_n, DW_WriterFixupNode, writer->fixups.first) {
|
for EachNode(fixup_n, DW_WriterFixupNode, writer->fixups.first) {
|
||||||
DW_WriterFixup *fixup = &fixup_n->v;
|
DW_WriterFixup *fixup = &fixup_n->v;
|
||||||
if (fixup->attrib->reader.form.kind == DW_Form_Ref8) {
|
Assert(fixup->tag->info_off != 0);
|
||||||
Assert(fixup->attrib->writer.form.ref->info_off != 0);
|
MemoryCopy(fixup->ptr, &fixup->tag->info_off, sizeof(U64));
|
||||||
MemoryCopy(fixup->value, &fixup->attrib->writer.form.ref->info_off, sizeof(U64));
|
|
||||||
fixup->attrib->reader.form.ref = fixup->attrib->writer.form.ref->info_off;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+149
-28
@@ -65,15 +65,16 @@ typedef struct DW_WriterForm
|
|||||||
};
|
};
|
||||||
} DW_WriterForm;
|
} DW_WriterForm;
|
||||||
|
|
||||||
|
typedef struct DW_WriterXForm
|
||||||
|
{
|
||||||
|
DW_WriterForm writer;
|
||||||
|
DW_Form reader;
|
||||||
|
} DW_WriterXForm;
|
||||||
|
|
||||||
typedef struct DW_WriterAttrib
|
typedef struct DW_WriterAttrib
|
||||||
{
|
{
|
||||||
DW_AttribKindEnum kind;
|
DW_AttribKindEnum kind;
|
||||||
struct {
|
DW_WriterXForm form;
|
||||||
DW_WriterForm form;
|
|
||||||
} writer;
|
|
||||||
struct {
|
|
||||||
DW_Form form;
|
|
||||||
} reader;
|
|
||||||
struct DW_WriterAttrib *next;
|
struct DW_WriterAttrib *next;
|
||||||
} DW_WriterAttrib;
|
} DW_WriterAttrib;
|
||||||
|
|
||||||
@@ -123,10 +124,58 @@ typedef struct DW_WriterAttribChunkList
|
|||||||
DW_WriterAttribChunk *last;
|
DW_WriterAttribChunk *last;
|
||||||
} DW_WriterAttribChunkList;
|
} DW_WriterAttribChunkList;
|
||||||
|
|
||||||
|
typedef struct DW_WriterLine
|
||||||
|
{
|
||||||
|
struct DW_WriterLine *next;
|
||||||
|
} DW_WriterLine;
|
||||||
|
|
||||||
|
typedef struct DW_WriterFile
|
||||||
|
{
|
||||||
|
struct DW_WriterFile *next;
|
||||||
|
String8 path;
|
||||||
|
U64 time_stamp;
|
||||||
|
U64 size;
|
||||||
|
String8 md5;
|
||||||
|
String8 source;
|
||||||
|
U64 file_idx;
|
||||||
|
U64 dir_idx;
|
||||||
|
} DW_WriterFile;
|
||||||
|
|
||||||
|
typedef struct DW_LineInst
|
||||||
|
{
|
||||||
|
DW_StdOpcode opcode;
|
||||||
|
union {
|
||||||
|
U64 advance_pc;
|
||||||
|
S64 advance_line;
|
||||||
|
DW_WriterFile *set_file;
|
||||||
|
U64 set_column;
|
||||||
|
U16 fixed_advance_pc;
|
||||||
|
U64 set_isa;
|
||||||
|
struct {
|
||||||
|
DW_ExtOpcode ext;
|
||||||
|
U64 set_address;
|
||||||
|
U64 set_discriminator;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} DW_LineInst;
|
||||||
|
|
||||||
|
typedef struct DW_LineInstNode
|
||||||
|
{
|
||||||
|
DW_LineInst v;
|
||||||
|
struct DW_LineInstNode *next;
|
||||||
|
} DW_LineInstNode;
|
||||||
|
|
||||||
|
typedef struct DW_LineInstList
|
||||||
|
{
|
||||||
|
U64 count;
|
||||||
|
DW_LineInstNode *first;
|
||||||
|
DW_LineInstNode *last;
|
||||||
|
} DW_LineInstList;
|
||||||
|
|
||||||
typedef struct DW_WriterFixup
|
typedef struct DW_WriterFixup
|
||||||
{
|
{
|
||||||
struct DW_WriterAttrib *attrib;
|
DW_WriterTag *tag;
|
||||||
U8 *value;
|
U8 *ptr;
|
||||||
} DW_WriterFixup;
|
} DW_WriterFixup;
|
||||||
|
|
||||||
typedef struct DW_WriterFixupNode
|
typedef struct DW_WriterFixupNode
|
||||||
@@ -151,38 +200,67 @@ typedef struct DW_WriterSection
|
|||||||
typedef struct DW_Writer
|
typedef struct DW_Writer
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
|
// Compile Unit
|
||||||
|
Arch arch;
|
||||||
|
DW_Version version;
|
||||||
|
DW_Format format;
|
||||||
|
DW_CompUnitKind cu_kind;
|
||||||
|
U8 address_size;
|
||||||
|
U8 segsel_size;
|
||||||
|
|
||||||
|
// Abbrev
|
||||||
|
U64 abbrev_base_info_off;
|
||||||
|
HashTable *abbrev_id_map;
|
||||||
|
|
||||||
|
// Info
|
||||||
DW_WriterTag *root;
|
DW_WriterTag *root;
|
||||||
DW_WriterTag *current;
|
DW_WriterTag *current;
|
||||||
Arch arch;
|
|
||||||
DW_Format format;
|
// Line
|
||||||
DW_Version version;
|
struct {
|
||||||
DW_CompUnitKind cu_kind;
|
U8 min_inst_len;
|
||||||
U64 address_size;
|
U8 max_ops_per_inst;
|
||||||
U64 abbrev_base_info_off;
|
U8 default_is_stmt;
|
||||||
|
S8 line_base;
|
||||||
|
U8 line_range;
|
||||||
|
U8 opcode_base;
|
||||||
|
U8 *std_op_lens;
|
||||||
|
DW_LineInstList line_insts;
|
||||||
|
|
||||||
|
DW_WriterFile *file;
|
||||||
|
U64 ln;
|
||||||
|
U64 col;
|
||||||
|
U64 addr;
|
||||||
|
|
||||||
|
U64 file_count;
|
||||||
|
DW_WriterFile *first_file;
|
||||||
|
DW_WriterFile *last_file;
|
||||||
|
} line;
|
||||||
|
|
||||||
|
// Emit
|
||||||
DW_WriterFixupList fixups;
|
DW_WriterFixupList fixups;
|
||||||
HashTable *abbrev_id_map;
|
|
||||||
DW_WriterSection sections[DW_Section_Count];
|
DW_WriterSection sections[DW_Section_Count];
|
||||||
DW_WriterAttribChunkList attrib_chunk_list;
|
DW_WriterAttribChunkList attrib_chunk_list;
|
||||||
DW_WriterTagChunkList tag_chunk_list;
|
DW_WriterTagChunkList tag_chunk_list;
|
||||||
} DW_Writer;
|
} DW_Writer;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
// Writer
|
||||||
internal DW_IntEnc dw_int_enc_from_sint(S64 v);
|
|
||||||
internal DW_IntEnc dw_int_enc_from_uint(U64 v);
|
|
||||||
|
|
||||||
internal U64 dw_size_from_sint(S64 v);
|
|
||||||
internal U64 dw_size_from_uint(U64 v);
|
|
||||||
|
|
||||||
internal void dw_serial_push_form(Arena *arena, String8List *srl, DW_Format format, DW_Version version, U8 address_size, DW_FormKind form_kind, DW_Form form);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
internal DW_Writer * dw_writer_begin(DW_Format format, DW_Version version, DW_CompUnitKind cu_kind, Arch arch);
|
internal DW_Writer * dw_writer_begin(DW_Format format, DW_Version version, DW_CompUnitKind cu_kind, Arch arch);
|
||||||
internal void dw_writer_end(DW_Writer **writer_ptr);
|
internal void dw_writer_end (DW_Writer **writer_ptr);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Form
|
||||||
|
|
||||||
|
internal U64 dw_serial_push_form(Arena *arena, String8List *srl, DW_Version version, DW_Format format, U8 address_size, DW_WriterFixupList *fixups, DW_WriterXForm form);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Info
|
||||||
|
|
||||||
internal DW_WriterTag * dw_writer_tag_begin(DW_Writer *writer, DW_TagKind kind);
|
internal DW_WriterTag * dw_writer_tag_begin(DW_Writer *writer, DW_TagKind kind);
|
||||||
internal void dw_writer_tag_end(DW_Writer *writer);
|
internal void dw_writer_tag_end (DW_Writer *writer);
|
||||||
|
|
||||||
internal DW_WriterAttrib * dw_writer_push_attrib (DW_Writer *writer, DW_AttribKind kind, DW_WriterForm form );
|
internal DW_WriterAttrib * dw_writer_push_attrib (DW_Writer *writer, DW_AttribKind kind, DW_WriterForm form );
|
||||||
internal DW_WriterAttrib * dw_writer_push_attrib_address (DW_Writer *writer, DW_AttribKind kind, U64 address );
|
internal DW_WriterAttrib * dw_writer_push_attrib_address (DW_Writer *writer, DW_AttribKind kind, U64 address );
|
||||||
@@ -201,13 +279,56 @@ internal DW_WriterAttrib * dw_writer_push_attrib_line_ptr (DW_Writer *writer,
|
|||||||
internal DW_WriterAttrib * dw_writer_push_attrib_mac_ptr (DW_Writer *writer, DW_AttribKind kind, void * mac_ptr );
|
internal DW_WriterAttrib * dw_writer_push_attrib_mac_ptr (DW_Writer *writer, DW_AttribKind kind, void * mac_ptr );
|
||||||
internal DW_WriterAttrib * dw_writer_push_attrib_rng_list_ptr(DW_Writer *writer, DW_AttribKind kind, void * rng_list_ptr);
|
internal DW_WriterAttrib * dw_writer_push_attrib_rng_list_ptr(DW_Writer *writer, DW_AttribKind kind, void * rng_list_ptr);
|
||||||
internal DW_WriterAttrib * dw_writer_push_attrib_implicit (DW_Writer *writer, DW_AttribKind kind, S64 implicit );
|
internal DW_WriterAttrib * dw_writer_push_attrib_implicit (DW_Writer *writer, DW_AttribKind kind, S64 implicit );
|
||||||
|
|
||||||
#define dw_writer_push_attrib_expressionv(w, k, ...) dw_writer_push_attrib_expression(w, k, (DW_ExprEnc[]){ __VA_ARGS__ }, ArrayCount(((DW_ExprEnc[]){ __VA_ARGS__ })) )
|
#define dw_writer_push_attrib_expressionv(w, k, ...) dw_writer_push_attrib_expression(w, k, (DW_ExprEnc[]){ __VA_ARGS__ }, ArrayCount(((DW_ExprEnc[]){ __VA_ARGS__ })) )
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Line
|
||||||
|
|
||||||
|
internal void dw_line_inst_list_push_node(DW_LineInstList *list, DW_LineInstNode *node);
|
||||||
|
internal DW_LineInstNode * dw_line_inst_list_push (Arena *arena, DW_LineInstList *list, DW_LineInst op);
|
||||||
|
|
||||||
|
// std opcodes
|
||||||
|
#define DW_LNS_copy() (DW_LineInst){ .opcode = DW_StdOpcode_Copy }
|
||||||
|
#define DW_LNS_advance_pc(d) (DW_LineInst){ .opcode = DW_StdOpcode_AdvancePc, .advance_pc = d }
|
||||||
|
#define DW_LNS_advance_line(s) (DW_LineInst){ .opcode = DW_StdOpcode_AdvanceLine, .advance_line = s }
|
||||||
|
#define DW_LNS_set_file(f) (DW_LineInst){ .opcode = DW_StdOpcode_SetFile, .set_file = f }
|
||||||
|
#define DW_LNS_set_column(c) (DW_LineInst){ .opcode = DW_StdOpcode_SetColumn, .set_column = c }
|
||||||
|
#define DW_LNS_negate_stmt() (DW_LineInst){ .opcode = DW_StdOpcode_NegateStmt }
|
||||||
|
#define DW_LNS_set_basic_block() (DW_LineInst){ .opcode = DW_StdOpcode_SetBasicBlock }
|
||||||
|
#define DW_LNS_const_add_pc(a) (DW_LineInst){ .opcode = DW_StdOpcode_ConstAddPc }
|
||||||
|
#define DW_LNS_fixed_advance_pc(a) (DW_LineInst){ .opcode = DW_StdOpcode_FixedAdvancePc, .fixed_advance_pc = a }
|
||||||
|
#define DW_LNS_set_prologue_end() (DW_LineInst){ .opcode = DW_StdOpcode_SetPrologueEnd }
|
||||||
|
#define DW_LNS_set_epilogue_begin() (DW_LineInst){ .opcode = DW_StdOpcode_SetEpilogueBegin }
|
||||||
|
#define DW_LNS_set_isa(i) (DW_LineInst){ .opcode = DW_StdOpcode_SetIsa, .set_isa = i }
|
||||||
|
|
||||||
|
// ext opcodes
|
||||||
|
#define DW_LNE_end_sequence() (DW_LineInst){ .opcode = DW_StdOpcode_ExtendedOpcode, .ext = DW_ExtOpcode_EndSequence }
|
||||||
|
#define DW_LNE_set_address(a) (DW_LineInst){ .opcode = DW_StdOpcode_ExtendedOpcode, .ext = DW_ExtOpcode_SetAddress, .set_address = a }
|
||||||
|
#define DW_LNE_set_discriminator(d) (DW_LineInst){ .opcode = DW_StdOpcode_ExtendedOpcode, .ext = DW_ExtOpcode_SetDiscriminator, .set_discriminator = d }
|
||||||
|
|
||||||
|
internal void dw_writer_line_emit (DW_Writer *writer, DW_WriterFile *file, U64 ln, U64 col, U64 addr);
|
||||||
|
internal void dw_writer_line_set_address (DW_Writer *writer, U64 address);
|
||||||
|
internal void dw_writer_line_set_prologue_end(DW_Writer *writer);
|
||||||
|
internal void dw_writer_line_epilogue_begin (DW_Writer *writer);
|
||||||
|
internal void dw_writer_line_set_isa (DW_Writer *writer, U64 isa);
|
||||||
|
internal DW_WriterFile * dw_writer_new_file (DW_Writer *writer, String8 path);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Emit
|
||||||
|
|
||||||
internal void dw_writer_emit(DW_Writer *writer);
|
internal void dw_writer_emit(DW_Writer *writer);
|
||||||
#ifdef OBJ_H
|
#ifdef OBJ_H
|
||||||
internal void dw_writer_emit_to_obj(DW_Writer *writer, OBJ *obj);
|
internal void dw_writer_emit_to_obj(DW_Writer *writer, OBJ *obj);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Format Helpers
|
||||||
|
|
||||||
|
internal DW_IntEnc dw_int_enc_from_sint(S64 v);
|
||||||
|
internal DW_IntEnc dw_int_enc_from_uint(U64 v);
|
||||||
|
|
||||||
|
internal U64 dw_size_from_sint(S64 v);
|
||||||
|
internal U64 dw_size_from_uint(U64 v);
|
||||||
|
|
||||||
#endif // DWARF_WRITER_H
|
#endif // DWARF_WRITER_H
|
||||||
|
|
||||||
|
|||||||
@@ -519,3 +519,12 @@ remove_duplicates_str8_list(Arena *arena, String8List list)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal String8 **
|
||||||
|
str8_from_key_value_pairs(Arena *arena, KeyValuePair *v, U64 count)
|
||||||
|
{
|
||||||
|
String8 **result = push_array(arena, String8 *, count);
|
||||||
|
for EachIndex(i, count) {
|
||||||
|
result[i] = &v[i].value_string;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -94,14 +94,16 @@ internal U32 * keys_from_hash_table_u32 (Arena *arena, HashTable
|
|||||||
internal U64 * keys_from_hash_table_u64 (Arena *arena, HashTable *ht);
|
internal U64 * keys_from_hash_table_u64 (Arena *arena, HashTable *ht);
|
||||||
internal String8 keys_from_hash_table_str8 (Arena *arena, HashTable *ht);
|
internal String8 keys_from_hash_table_str8 (Arena *arena, HashTable *ht);
|
||||||
internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht);
|
internal KeyValuePair * key_value_pairs_from_hash_table(Arena *arena, HashTable *ht);
|
||||||
|
|
||||||
internal void * keys_from_hash_table_raw (Arena *arena, HashTable *ht);
|
internal void * keys_from_hash_table_raw (Arena *arena, HashTable *ht);
|
||||||
internal void * values_from_hash_table_raw(Arena *arena, HashTable *ht);
|
|
||||||
|
internal U64 * values_from_hash_table_u64(Arena *arena, HashTable *ht);
|
||||||
|
|
||||||
internal void sort_key_value_pairs_as_u32 (KeyValuePair *pairs, U64 count);
|
internal void sort_key_value_pairs_as_u32 (KeyValuePair *pairs, U64 count);
|
||||||
internal void sort_key_value_pairs_as_u64 (KeyValuePair *pairs, U64 count);
|
internal void sort_key_value_pairs_as_u64 (KeyValuePair *pairs, U64 count);
|
||||||
internal void sort_key_value_pairs_as_string_sensitive(KeyValuePair *pairs, U64 count);
|
internal void sort_key_value_pairs_as_string_sensitive(KeyValuePair *pairs, U64 count);
|
||||||
|
|
||||||
|
internal String8 ** str8_from_key_value_pairs(Arena *arena, KeyValuePair *v, U64 count);
|
||||||
|
|
||||||
// --- Misc --------------------------------------------------------------------
|
// --- Misc --------------------------------------------------------------------
|
||||||
|
|
||||||
internal U64Array remove_duplicates_u64_array(Arena *arena, U64Array arr);
|
internal U64Array remove_duplicates_u64_array(Arena *arena, U64Array arr);
|
||||||
|
|||||||
@@ -154,6 +154,7 @@
|
|||||||
<AlternativeType Name="COFF_LibWriterMemberList"/>
|
<AlternativeType Name="COFF_LibWriterMemberList"/>
|
||||||
<AlternativeType Name="PE_BaseRelocBlockList"/>
|
<AlternativeType Name="PE_BaseRelocBlockList"/>
|
||||||
<AlternativeType Name="DW_Expr"/>
|
<AlternativeType Name="DW_Expr"/>
|
||||||
|
<AlternativeType Name="DW_LineInstList"/>
|
||||||
<DisplayString>{{ count={count} first={first} }} </DisplayString>
|
<DisplayString>{{ count={count} first={first} }} </DisplayString>
|
||||||
<Expand>
|
<Expand>
|
||||||
<Item Name="[count]">count</Item>
|
<Item Name="[count]">count</Item>
|
||||||
|
|||||||
+74
-62
@@ -82,8 +82,8 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag)
|
|||||||
DW_AttribNode *reader_attrib = reader_tag->tag.attribs.first;
|
DW_AttribNode *reader_attrib = reader_tag->tag.attribs.first;
|
||||||
while (writer_attrib) {
|
while (writer_attrib) {
|
||||||
if (writer_attrib->kind != reader_attrib->v.attrib_kind) { goto exit; }
|
if (writer_attrib->kind != reader_attrib->v.attrib_kind) { goto exit; }
|
||||||
if (writer_attrib->reader.form.kind != reader_attrib->v.form.kind) { goto exit; }
|
if (writer_attrib->form.reader.kind != reader_attrib->v.form.kind) { goto exit; }
|
||||||
if ( ! dw_form_match(writer_attrib->reader.form, reader_attrib->v.form)) { goto exit; }
|
if ( ! dw_form_match(writer_attrib->form.reader, reader_attrib->v.form)) { goto exit; }
|
||||||
writer_attrib = writer_attrib->next;
|
writer_attrib = writer_attrib->next;
|
||||||
reader_attrib = reader_attrib->next;
|
reader_attrib = reader_attrib->next;
|
||||||
}
|
}
|
||||||
@@ -107,11 +107,23 @@ dwt_make_writer(void)
|
|||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
|
||||||
// define debug info layout
|
|
||||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_Last, DW_CompUnitKind_Compile, Arch_x64);
|
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_Last, DW_CompUnitKind_Compile, Arch_x64);
|
||||||
|
// line
|
||||||
|
{
|
||||||
|
DW_WriterFile *b_file = dw_writer_new_file(writer, str8_lit("~/devel/projects/b/b.c"));
|
||||||
|
DW_WriterFile *a_file = dw_writer_new_file(writer, str8_lit("~/devel/projects/a.c"));
|
||||||
|
dw_writer_line_set_prologue_end(writer);
|
||||||
|
dw_writer_line_emit(writer, b_file, 10, 0, 0x140001000);
|
||||||
|
dw_writer_line_emit(writer, b_file, 11, 0, 0x140001010);
|
||||||
|
dw_writer_line_emit(writer, a_file, 1, 0, 0x140001016);
|
||||||
|
dw_writer_line_emit(writer, a_file, 2, 0, 0x140001020);
|
||||||
|
}
|
||||||
|
// info
|
||||||
{
|
{
|
||||||
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
|
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
|
||||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
|
||||||
|
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, str8_lit("~/devel/projects"));
|
||||||
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("a.c"));
|
||||||
dw_writer_push_attrib_enum(writer, DW_AttribKind_Language, DW_Language_C99);
|
dw_writer_push_attrib_enum(writer, DW_AttribKind_Language, DW_Language_C99);
|
||||||
dw_writer_push_attrib_flag(writer, DW_AttribKind_UseUtf8, 1);
|
dw_writer_push_attrib_flag(writer, DW_AttribKind_UseUtf8, 1);
|
||||||
{
|
{
|
||||||
@@ -223,19 +235,19 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *producer_attrib = comp_unit_tag->first_attrib;
|
DW_WriterAttrib *producer_attrib = comp_unit_tag->first_attrib;
|
||||||
T_Ok(producer_attrib->kind == DW_AttribKind_Producer);
|
T_Ok(producer_attrib->kind == DW_AttribKind_Producer);
|
||||||
T_Ok(producer_attrib->reader.form.kind == DW_Form_String);
|
T_Ok(producer_attrib->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(producer_attrib->writer.form.string, str8_lit("RAD DWARF WRITER"), 0));
|
T_Ok(str8_match(producer_attrib->form.writer.string, str8_lit("RAD DWARF WRITER"), 0));
|
||||||
|
|
||||||
DW_WriterAttrib *language_attrib = producer_attrib->next;
|
DW_WriterAttrib *language_attrib = producer_attrib->next;
|
||||||
T_Ok(language_attrib->kind == DW_AttribKind_Language);
|
T_Ok(language_attrib->kind == DW_AttribKind_Language);
|
||||||
T_Ok(language_attrib->reader.form.kind == DW_Form_Data1);
|
T_Ok(language_attrib->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(language_attrib->reader.form.data.size == 1);
|
T_Ok(language_attrib->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)language_attrib->reader.form.data.str == DW_Language_C99);
|
T_Ok(*(U8 *)language_attrib->form.reader.data.str == DW_Language_C99);
|
||||||
|
|
||||||
DW_WriterAttrib *use_utf8_attrib = language_attrib->next;
|
DW_WriterAttrib *use_utf8_attrib = language_attrib->next;
|
||||||
T_Ok(use_utf8_attrib->kind == DW_AttribKind_UseUtf8);
|
T_Ok(use_utf8_attrib->kind == DW_AttribKind_UseUtf8);
|
||||||
T_Ok(use_utf8_attrib->reader.form.kind == DW_Form_Flag);
|
T_Ok(use_utf8_attrib->form.reader.kind == DW_Form_Flag);
|
||||||
T_Ok(use_utf8_attrib->reader.form.flag == 1);
|
T_Ok(use_utf8_attrib->form.reader.flag == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DW_WriterTag *char_type_tag = comp_unit_tag->first_child;
|
DW_WriterTag *char_type_tag = comp_unit_tag->first_child;
|
||||||
@@ -250,20 +262,20 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib;
|
DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib;
|
||||||
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
|
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
|
||||||
T_Ok(byte_size_attrib->reader.form.kind == DW_Form_Data1);
|
T_Ok(byte_size_attrib->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(byte_size_attrib->reader.form.data.size == 1);
|
T_Ok(byte_size_attrib->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)byte_size_attrib->reader.form.data.str == 1);
|
T_Ok(*(U8 *)byte_size_attrib->form.reader.data.str == 1);
|
||||||
|
|
||||||
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
|
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
|
||||||
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
|
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
|
||||||
T_Ok(encoding_attrib->reader.form.kind == DW_Form_Data1);
|
T_Ok(encoding_attrib->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(encoding_attrib->reader.form.data.size == 1);
|
T_Ok(encoding_attrib->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)encoding_attrib->reader.form.data.str == DW_ATE_SignedChar);
|
T_Ok(*(U8 *)encoding_attrib->form.reader.data.str == DW_ATE_SignedChar);
|
||||||
|
|
||||||
DW_WriterAttrib *name_attrib = encoding_attrib->next;
|
DW_WriterAttrib *name_attrib = encoding_attrib->next;
|
||||||
T_Ok(name_attrib->kind == DW_AttribKind_Name);
|
T_Ok(name_attrib->kind == DW_AttribKind_Name);
|
||||||
T_Ok(name_attrib->reader.form.kind == DW_Form_String);
|
T_Ok(name_attrib->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(name_attrib->reader.form.string, str8_lit("char"), 0));
|
T_Ok(str8_match(name_attrib->form.reader.string, str8_lit("char"), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
DW_WriterTag *const_type_tag = char_type_tag->next;
|
DW_WriterTag *const_type_tag = char_type_tag->next;
|
||||||
@@ -278,8 +290,8 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *type_attrib = const_type_tag->first_attrib;
|
DW_WriterAttrib *type_attrib = const_type_tag->first_attrib;
|
||||||
T_Ok(type_attrib->kind == DW_AttribKind_Type);
|
T_Ok(type_attrib->kind == DW_AttribKind_Type);
|
||||||
T_Ok(type_attrib->writer.form.kind == DW_WriterFormKind_Ref);
|
T_Ok(type_attrib->form.writer.kind == DW_WriterFormKind_Ref);
|
||||||
T_Ok(type_attrib->writer.form.ref == char_type_tag);
|
T_Ok(type_attrib->form.writer.ref == char_type_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
DW_WriterTag *dup_char_type_tag = const_type_tag->next;
|
DW_WriterTag *dup_char_type_tag = const_type_tag->next;
|
||||||
@@ -294,20 +306,20 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib;
|
DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib;
|
||||||
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
|
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
|
||||||
T_Ok(byte_size_attrib->reader.form.kind == DW_Form_Data1);
|
T_Ok(byte_size_attrib->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(byte_size_attrib->reader.form.data.size == 1);
|
T_Ok(byte_size_attrib->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)byte_size_attrib->reader.form.data.str == 1);
|
T_Ok(*(U8 *)byte_size_attrib->form.reader.data.str == 1);
|
||||||
|
|
||||||
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
|
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
|
||||||
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
|
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
|
||||||
T_Ok(encoding_attrib->reader.form.kind == DW_Form_Data1);
|
T_Ok(encoding_attrib->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(encoding_attrib->reader.form.data.size == 1);
|
T_Ok(encoding_attrib->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)encoding_attrib->reader.form.data.str == DW_ATE_SignedChar);
|
T_Ok(*(U8 *)encoding_attrib->form.reader.data.str == DW_ATE_SignedChar);
|
||||||
|
|
||||||
DW_WriterAttrib *name_attrib = encoding_attrib->next;
|
DW_WriterAttrib *name_attrib = encoding_attrib->next;
|
||||||
T_Ok(name_attrib->kind == DW_AttribKind_Name);
|
T_Ok(name_attrib->kind == DW_AttribKind_Name);
|
||||||
T_Ok(name_attrib->reader.form.kind == DW_Form_String);
|
T_Ok(name_attrib->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(name_attrib->reader.form.string, str8_lit("char"), 0));
|
T_Ok(str8_match(name_attrib->form.reader.string, str8_lit("char"), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
DW_WriterTag *simple_struct_tag = dup_char_type_tag->next;
|
DW_WriterTag *simple_struct_tag = dup_char_type_tag->next;
|
||||||
@@ -321,8 +333,8 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *simple_struct_name = simple_struct_tag->first_attrib;
|
DW_WriterAttrib *simple_struct_name = simple_struct_tag->first_attrib;
|
||||||
T_Ok(simple_struct_name->kind == DW_AttribKind_Name);
|
T_Ok(simple_struct_name->kind == DW_AttribKind_Name);
|
||||||
T_Ok(simple_struct_name->reader.form.kind == DW_Form_String);
|
T_Ok(simple_struct_name->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(simple_struct_name->reader.form.string, str8_lit("FooBar"), 0));
|
T_Ok(str8_match(simple_struct_name->form.reader.string, str8_lit("FooBar"), 0));
|
||||||
|
|
||||||
DW_WriterTag *m0_tag = simple_struct_tag->first_child;
|
DW_WriterTag *m0_tag = simple_struct_tag->first_child;
|
||||||
{
|
{
|
||||||
@@ -334,19 +346,19 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *name = m0_tag->first_attrib;
|
DW_WriterAttrib *name = m0_tag->first_attrib;
|
||||||
T_Ok(name->kind == DW_AttribKind_Name);
|
T_Ok(name->kind == DW_AttribKind_Name);
|
||||||
T_Ok(name->reader.form.kind == DW_Form_String);
|
T_Ok(name->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(name->reader.form.string, str8_lit("m0"), 0));
|
T_Ok(str8_match(name->form.reader.string, str8_lit("m0"), 0));
|
||||||
|
|
||||||
DW_WriterAttrib *type = name->next;
|
DW_WriterAttrib *type = name->next;
|
||||||
T_Ok(type->kind == DW_AttribKind_Type);
|
T_Ok(type->kind == DW_AttribKind_Type);
|
||||||
T_Ok(type->reader.form.kind == DW_Form_Ref1);
|
T_Ok(type->form.reader.kind == DW_Form_Ref1);
|
||||||
T_Ok(type->reader.form.ref == 0x20);
|
T_Ok(type->form.reader.ref == 0x20);
|
||||||
|
|
||||||
DW_WriterAttrib *data_loc = type->next;
|
DW_WriterAttrib *data_loc = type->next;
|
||||||
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
|
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
|
||||||
T_Ok(data_loc->reader.form.kind == DW_Form_Data1);
|
T_Ok(data_loc->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(data_loc->reader.form.data.size == 1);
|
T_Ok(data_loc->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)data_loc->reader.form.data.str == 0);
|
T_Ok(*(U8 *)data_loc->form.reader.data.str == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DW_WriterTag *m1_tag = m0_tag->next;
|
DW_WriterTag *m1_tag = m0_tag->next;
|
||||||
@@ -359,24 +371,24 @@ T_BeginTest(dwarf_writer)
|
|||||||
|
|
||||||
DW_WriterAttrib *name = m1_tag->first_attrib;
|
DW_WriterAttrib *name = m1_tag->first_attrib;
|
||||||
T_Ok(name->kind == DW_AttribKind_Name);
|
T_Ok(name->kind == DW_AttribKind_Name);
|
||||||
T_Ok(name->reader.form.kind == DW_Form_String);
|
T_Ok(name->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(name->reader.form.string, str8_lit("m1"), 0));
|
T_Ok(str8_match(name->form.reader.string, str8_lit("m1"), 0));
|
||||||
|
|
||||||
DW_WriterAttrib *type = name->next;
|
DW_WriterAttrib *type = name->next;
|
||||||
T_Ok(type->kind == DW_AttribKind_Type);
|
T_Ok(type->kind == DW_AttribKind_Type);
|
||||||
T_Ok(type->reader.form.kind == DW_Form_Ref1);
|
T_Ok(type->form.reader.kind == DW_Form_Ref1);
|
||||||
T_Ok(type->reader.form.ref == 0x20);
|
T_Ok(type->form.reader.ref == 0x20);
|
||||||
|
|
||||||
DW_WriterAttrib *data_loc = type->next;
|
DW_WriterAttrib *data_loc = type->next;
|
||||||
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
|
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
|
||||||
T_Ok(data_loc->reader.form.kind == DW_Form_Data1);
|
T_Ok(data_loc->form.reader.kind == DW_Form_Data1);
|
||||||
T_Ok(data_loc->reader.form.data.size == 1);
|
T_Ok(data_loc->form.reader.data.size == 1);
|
||||||
T_Ok(*(U8 *)data_loc->reader.form.data.str == 10);
|
T_Ok(*(U8 *)data_loc->form.reader.data.str == 10);
|
||||||
|
|
||||||
DW_WriterAttrib *byte_size = data_loc->next;
|
DW_WriterAttrib *byte_size = data_loc->next;
|
||||||
T_Ok(byte_size->kind == DW_AttribKind_ByteSize);
|
T_Ok(byte_size->kind == DW_AttribKind_ByteSize);
|
||||||
T_Ok(byte_size->reader.form.kind == DW_Form_ImplicitConst);
|
T_Ok(byte_size->form.reader.kind == DW_Form_ImplicitConst);
|
||||||
T_Ok(byte_size->reader.form.implicit_const == 123);
|
T_Ok(byte_size->form.reader.implicit_const == 123);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,40 +400,40 @@ T_BeginTest(dwarf_writer)
|
|||||||
{
|
{
|
||||||
DW_WriterAttrib *external = main_tag->first_attrib;
|
DW_WriterAttrib *external = main_tag->first_attrib;
|
||||||
T_Ok(external->kind == DW_AttribKind_External);
|
T_Ok(external->kind == DW_AttribKind_External);
|
||||||
T_Ok(external->reader.form.kind == DW_Form_Flag);
|
T_Ok(external->form.reader.kind == DW_Form_Flag);
|
||||||
T_Ok(external->reader.form.flag);
|
T_Ok(external->form.reader.flag);
|
||||||
|
|
||||||
DW_WriterAttrib *prototyped = external->next;
|
DW_WriterAttrib *prototyped = external->next;
|
||||||
T_Ok(prototyped->kind == DW_AttribKind_Prototyped);
|
T_Ok(prototyped->kind == DW_AttribKind_Prototyped);
|
||||||
T_Ok(prototyped->reader.form.kind == DW_Form_Flag);
|
T_Ok(prototyped->form.reader.kind == DW_Form_Flag);
|
||||||
T_Ok(prototyped->reader.form.flag);
|
T_Ok(prototyped->form.reader.flag);
|
||||||
|
|
||||||
DW_WriterAttrib *low_pc = prototyped->next;
|
DW_WriterAttrib *low_pc = prototyped->next;
|
||||||
T_Ok(low_pc->kind == DW_AttribKind_LowPc);
|
T_Ok(low_pc->kind == DW_AttribKind_LowPc);
|
||||||
T_Ok(low_pc->reader.form.kind == DW_Form_Addr);
|
T_Ok(low_pc->form.reader.kind == DW_Form_Addr);
|
||||||
T_Ok(low_pc->reader.form.addr.size == sizeof(U64));
|
T_Ok(low_pc->form.reader.addr.size == sizeof(U64));
|
||||||
T_Ok(*(U64 *)low_pc->reader.form.addr.str == 0x14012f2f0);
|
T_Ok(*(U64 *)low_pc->form.reader.addr.str == 0x14012f2f0);
|
||||||
|
|
||||||
DW_WriterAttrib *high_pc = low_pc->next;
|
DW_WriterAttrib *high_pc = low_pc->next;
|
||||||
T_Ok(high_pc->kind == DW_AttribKind_HighPc);
|
T_Ok(high_pc->kind == DW_AttribKind_HighPc);
|
||||||
T_Ok(high_pc->reader.form.kind == DW_Form_Addr);
|
T_Ok(high_pc->form.reader.kind == DW_Form_Addr);
|
||||||
T_Ok(high_pc->reader.form.addr.size == sizeof(U64));
|
T_Ok(high_pc->form.reader.addr.size == sizeof(U64));
|
||||||
T_Ok(*(U64 *)high_pc->reader.form.addr.str == 0x14012f405);
|
T_Ok(*(U64 *)high_pc->form.reader.addr.str == 0x14012f405);
|
||||||
|
|
||||||
DW_WriterAttrib *name = high_pc->next;
|
DW_WriterAttrib *name = high_pc->next;
|
||||||
T_Ok(name->kind == DW_AttribKind_Name);
|
T_Ok(name->kind == DW_AttribKind_Name);
|
||||||
T_Ok(name->reader.form.kind == DW_Form_String);
|
T_Ok(name->form.reader.kind == DW_Form_String);
|
||||||
T_Ok(str8_match(name->reader.form.string, str8_lit("main"), 0));
|
T_Ok(str8_match(name->form.reader.string, str8_lit("main"), 0));
|
||||||
|
|
||||||
DW_WriterAttrib *type = name->next;
|
DW_WriterAttrib *type = name->next;
|
||||||
T_Ok(type->kind == DW_AttribKind_Type);
|
T_Ok(type->kind == DW_AttribKind_Type);
|
||||||
T_Ok(type->reader.form.kind == DW_Form_Ref1);
|
T_Ok(type->form.reader.kind == DW_Form_Ref1);
|
||||||
T_Ok(type->reader.form.ref == simple_struct_tag->info_off);
|
T_Ok(type->form.reader.ref == simple_struct_tag->info_off);
|
||||||
|
|
||||||
DW_WriterAttrib *frame_base = type->next;
|
DW_WriterAttrib *frame_base = type->next;
|
||||||
T_Ok(frame_base->kind == DW_AttribKind_FrameBase);
|
T_Ok(frame_base->kind == DW_AttribKind_FrameBase);
|
||||||
T_Ok(frame_base->reader.form.kind == DW_Form_ExprLoc);
|
T_Ok(frame_base->form.reader.kind == DW_Form_ExprLoc);
|
||||||
DW_Expr frame_base_expr = dw_expr_from_data(scratch.arena, writer->format, writer->address_size, frame_base->reader.form.exprloc);
|
DW_Expr frame_base_expr = dw_expr_from_data(scratch.arena, writer->format, writer->address_size, frame_base->form.reader.exprloc);
|
||||||
T_Ok(frame_base_expr.count == 1);
|
T_Ok(frame_base_expr.count == 1);
|
||||||
T_Ok(frame_base_expr.first->opcode == DW_ExprOp_Reg7);
|
T_Ok(frame_base_expr.first->opcode == DW_ExprOp_Reg7);
|
||||||
T_Ok(frame_base_expr.first->operands == 0);
|
T_Ok(frame_base_expr.first->operands == 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user