mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
test all LNCT encoding in the file table,
test line instruction encoder, test special opcode encoding
This commit is contained in:
+29
-27
@@ -2276,7 +2276,7 @@ dw_read_line_vm_header(Arena *arena,
|
|||||||
// compile unit name is always first in the file table
|
// compile unit name is always first in the file table
|
||||||
{
|
{
|
||||||
DW_LineFileNode *node = push_array(scratch.arena, DW_LineFileNode, 1);
|
DW_LineFileNode *node = push_array(scratch.arena, DW_LineFileNode, 1);
|
||||||
node->file.file_name = cu_name;
|
node->file.path = cu_name;
|
||||||
SLLQueuePush(file_list.first, file_list.last, node);
|
SLLQueuePush(file_list.first, file_list.last, node);
|
||||||
file_list.node_count += 1;
|
file_list.node_count += 1;
|
||||||
}
|
}
|
||||||
@@ -2288,10 +2288,10 @@ dw_read_line_vm_header(Arena *arena,
|
|||||||
if (first_byte == 0) { break; }
|
if (first_byte == 0) { break; }
|
||||||
|
|
||||||
DW_LineFile file = {0};
|
DW_LineFile file = {0};
|
||||||
TryRead(str8_deserial_read_cstr (data, cursor, &file.file_name), cursor, exit);
|
TryRead(str8_deserial_read_cstr (data, cursor, &file.path), cursor, exit);
|
||||||
TryRead(str8_deserial_read_uleb128(data, cursor, &file.dir_idx), cursor, exit);
|
TryRead(str8_deserial_read_uleb128(data, cursor, &file.dir_idx), cursor, exit);
|
||||||
TryRead(str8_deserial_read_uleb128(data, cursor, &file.modify_time), cursor, exit);
|
TryRead(str8_deserial_read_uleb128(data, cursor, &file.time_stamp), cursor, exit);
|
||||||
TryRead(str8_deserial_read_uleb128(data, cursor, &file.file_size), cursor, exit);
|
TryRead(str8_deserial_read_uleb128(data, cursor, &file.size), cursor, exit);
|
||||||
|
|
||||||
DW_LineFileNode *node = push_array(scratch.arena, DW_LineFileNode, 1);
|
DW_LineFileNode *node = push_array(scratch.arena, DW_LineFileNode, 1);
|
||||||
node->file = file;
|
node->file = file;
|
||||||
@@ -2309,10 +2309,10 @@ dw_read_line_vm_header(Arena *arena,
|
|||||||
file_table.v = push_array(arena, DW_LineFile, file_list.node_count);
|
file_table.v = push_array(arena, DW_LineFile, file_list.node_count);
|
||||||
for EachNode(n, DW_LineFileNode, file_list.first) {
|
for EachNode(n, DW_LineFileNode, file_list.first) {
|
||||||
DW_LineFile *dst = &file_table.v[file_table.count++];
|
DW_LineFile *dst = &file_table.v[file_table.count++];
|
||||||
dst->file_name = push_str8_copy(arena, n->file.file_name);
|
dst->path = push_str8_copy(arena, n->file.path);
|
||||||
dst->dir_idx = n->file.dir_idx;
|
dst->dir_idx = n->file.dir_idx;
|
||||||
dst->modify_time = n->file.modify_time;
|
dst->time_stamp = n->file.time_stamp;
|
||||||
dst->file_size = n->file.file_size;
|
dst->size = n->file.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// DWARF5
|
// DWARF5
|
||||||
@@ -2379,11 +2379,11 @@ dw_read_line_vm_header(Arena *arena,
|
|||||||
cursor += form_size;
|
cursor += form_size;
|
||||||
|
|
||||||
switch (lnct) {
|
switch (lnct) {
|
||||||
case DW_LNCT_Path: { file->file_name = dw_interp_string(input, format, cu_str_offsets, form); } break;
|
case DW_LNCT_Path: { file->path = dw_interp_string(input, format, cu_str_offsets, form); } break;
|
||||||
case DW_LNCT_DirectoryIndex: { file->dir_idx = dw_interp_const_u64(form); } break;
|
case DW_LNCT_DirectoryIndex: { file->dir_idx = dw_interp_const_u64(form); } break;
|
||||||
case DW_LNCT_TimeStamp: { file->modify_time = dw_interp_const_u64(form); } break;
|
case DW_LNCT_TimeStamp: { file->time_stamp = dw_interp_const_u64(form); } break;
|
||||||
case DW_LNCT_Size: { file->file_size = dw_interp_const_u64(form); } break;
|
case DW_LNCT_Size: { file->size = dw_interp_const_u64(form); } break;
|
||||||
case DW_LNCT_MD5: { file->md5_digest = dw_interp_const_u128(form); } break;
|
case DW_LNCT_MD5: { file->md5 = dw_interp_const_u128(form); } break;
|
||||||
case DW_LNCT_LLVM_Source: { file->source = dw_interp_string(input, format, cu_str_offsets, form); } break;
|
case DW_LNCT_LLVM_Source: { file->source = dw_interp_string(input, format, cu_str_offsets, form); } break;
|
||||||
default: {
|
default: {
|
||||||
Assert(!"unexpected LNTC encoding");
|
Assert(!"unexpected LNTC encoding");
|
||||||
@@ -2565,7 +2565,9 @@ dw_line_vm_step(DW_LineVM *vm)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_StdOpcode_FixedAdvancePc: {
|
case DW_StdOpcode_FixedAdvancePc: {
|
||||||
TryRead(str8_deserial_read_struct(vm->program, vm->cursor, &vm->operands[0].u64), vm->cursor, exit);
|
U16 fixed_advance = 0;
|
||||||
|
TryRead(str8_deserial_read_struct(vm->program, vm->cursor, &fixed_advance), vm->cursor, exit);
|
||||||
|
vm->operands[0].u64 = fixed_advance;
|
||||||
vm->state.address += vm->operands[0].u64;
|
vm->state.address += vm->operands[0].u64;
|
||||||
vm->state.op_index = 0;
|
vm->state.op_index = 0;
|
||||||
} break;
|
} break;
|
||||||
@@ -2590,7 +2592,7 @@ dw_line_vm_step(DW_LineVM *vm)
|
|||||||
vm->cursor += vm->ext_length;
|
vm->cursor += vm->ext_length;
|
||||||
|
|
||||||
U64 ext_cursor = 0;
|
U64 ext_cursor = 0;
|
||||||
TryRead(str8_deserial_read_struct(ext_data, ext_cursor, &vm->ext_opcode), vm->cursor, exit);
|
TryRead(str8_deserial_read_struct(ext_data, ext_cursor, &vm->ext_opcode), ext_cursor, exit);
|
||||||
|
|
||||||
switch (vm->ext_opcode) {
|
switch (vm->ext_opcode) {
|
||||||
case DW_ExtOpcode_EndSequence: {
|
case DW_ExtOpcode_EndSequence: {
|
||||||
@@ -2600,26 +2602,26 @@ dw_line_vm_step(DW_LineVM *vm)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_ExtOpcode_SetAddress: {
|
case DW_ExtOpcode_SetAddress: {
|
||||||
TryRead(str8_deserial_read(ext_data, ext_cursor, &vm->operands[0].u64, vm->header.address_size, vm->header.address_size), vm->cursor, exit);
|
TryRead(str8_deserial_read(ext_data, ext_cursor, &vm->operands[0].u64, vm->header.address_size, vm->header.address_size), ext_cursor, exit);
|
||||||
vm->state.address = vm->operands[0].u64;
|
vm->state.address = vm->operands[0].u64;
|
||||||
vm->state.op_index = 0;
|
vm->state.op_index = 0;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_ExtOpcode_DefineFile: {
|
case DW_ExtOpcode_DefineFile: {
|
||||||
TryRead(str8_deserial_read_cstr (ext_data, ext_cursor, &vm->operands[0].string), vm->cursor, exit); // file name
|
TryRead(str8_deserial_read_cstr (ext_data, ext_cursor, &vm->operands[0].string), ext_cursor, exit); // file name
|
||||||
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[1].u64), vm->cursor, exit); // dir index
|
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[1].u64), ext_cursor, exit); // dir index
|
||||||
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[2].u64), vm->cursor, exit); // modify time
|
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[2].u64), ext_cursor, exit); // modify time
|
||||||
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[3].u64), vm->cursor, exit); // file size
|
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[3].u64), ext_cursor, exit); // file size
|
||||||
|
|
||||||
if (vm->ext_file_ht == 0) {
|
if (vm->ext_file_ht == 0) {
|
||||||
vm->ext_file_ht = hash_table_init(vm->arena, 512);
|
vm->ext_file_ht = hash_table_init(vm->arena, 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
DW_LineFile *file = push_array(vm->arena, DW_LineFile, 1);
|
DW_LineFile *file = push_array(vm->arena, DW_LineFile, 1);
|
||||||
file->file_name = vm->operands[0].string;
|
file->path = vm->operands[0].string;
|
||||||
file->dir_idx = vm->operands[1].u64;
|
file->dir_idx = vm->operands[1].u64;
|
||||||
file->modify_time = vm->operands[2].u64;
|
file->time_stamp = vm->operands[2].u64;
|
||||||
file->file_size = vm->operands[3].u64;
|
file->size = vm->operands[3].u64;
|
||||||
|
|
||||||
if (hash_table_search_u64_raw(vm->ext_file_ht, vm->state.file_index) == 0) {
|
if (hash_table_search_u64_raw(vm->ext_file_ht, vm->state.file_index) == 0) {
|
||||||
vm->error = push_str8f(vm->arena, "file with index %I64d was already defined", vm->state.file_index);
|
vm->error = push_str8f(vm->arena, "file with index %I64d was already defined", vm->state.file_index);
|
||||||
@@ -2630,7 +2632,7 @@ dw_line_vm_step(DW_LineVM *vm)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DW_ExtOpcode_SetDiscriminator: {
|
case DW_ExtOpcode_SetDiscriminator: {
|
||||||
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[0].u64), vm->cursor, exit);
|
TryRead(str8_deserial_read_uleb128(ext_data, ext_cursor, &vm->operands[0].u64), ext_cursor, exit);
|
||||||
vm->state.discriminator = vm->operands[0].u64;
|
vm->state.discriminator = vm->operands[0].u64;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -2676,12 +2678,12 @@ dw_path_from_file(Arena *arena, String8Array dir_table, DW_LineFile *file)
|
|||||||
|
|
||||||
// find directory and file name associated with the file index
|
// find directory and file name associated with the file index
|
||||||
String8 dir = dir_table.v[file->dir_idx];
|
String8 dir = dir_table.v[file->dir_idx];
|
||||||
String8 file_name = file->file_name;
|
String8 path = file->path;
|
||||||
|
|
||||||
// infer path style if directory is empty use file name
|
// infer path style if directory is empty use file name
|
||||||
PathStyle style = path_style_from_str8(dir);
|
PathStyle style = path_style_from_str8(dir);
|
||||||
if (style == PathStyle_Null || style == PathStyle_Relative) {
|
if (style == PathStyle_Null || style == PathStyle_Relative) {
|
||||||
style = path_style_from_str8(file->file_name);
|
style = path_style_from_str8(file->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
String8List path_list = {0};
|
String8List path_list = {0};
|
||||||
@@ -2697,17 +2699,17 @@ dw_path_from_file(Arena *arena, String8Array dir_table, DW_LineFile *file)
|
|||||||
str8_list_concat_in_place(&path_list, &dir_list);
|
str8_list_concat_in_place(&path_list, &dir_list);
|
||||||
|
|
||||||
// push file name
|
// push file name
|
||||||
str8_list_push(scratch.arena, &path_list, file->file_name);
|
str8_list_push(scratch.arena, &path_list, file->path);
|
||||||
|
|
||||||
// resolve dots in the path
|
// resolve dots in the path
|
||||||
str8_path_list_resolve_dots_in_place(&path_list, style);
|
str8_path_list_resolve_dots_in_place(&path_list, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// join path
|
// join path
|
||||||
String8 path = str8_path_list_join_by_style(arena, &path_list, style);
|
String8 result = str8_path_list_join_by_style(arena, &path_list, style);
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return path;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DW_PubStringsTable
|
internal DW_PubStringsTable
|
||||||
|
|||||||
@@ -173,11 +173,11 @@ typedef struct DW_TagTree
|
|||||||
|
|
||||||
typedef struct DW_LineFile
|
typedef struct DW_LineFile
|
||||||
{
|
{
|
||||||
String8 file_name;
|
String8 path;
|
||||||
U64 dir_idx;
|
U64 dir_idx;
|
||||||
U64 modify_time;
|
U64 time_stamp;
|
||||||
U64 file_size;
|
U64 size;
|
||||||
U128 md5_digest;
|
U128 md5;
|
||||||
String8 source;
|
String8 source;
|
||||||
} DW_LineFile;
|
} DW_LineFile;
|
||||||
|
|
||||||
|
|||||||
+64
-25
@@ -117,6 +117,7 @@ dw_writer_begin(DW_Format format, DW_Version version, DW_CompUnitKind cu_kind, A
|
|||||||
writer->line.line_range = 14;
|
writer->line.line_range = 14;
|
||||||
writer->line.opcode_base = DW_StdOpcode_Count;
|
writer->line.opcode_base = DW_StdOpcode_Count;
|
||||||
writer->line.ln = 1;
|
writer->line.ln = 1;
|
||||||
|
Assert(writer->line.line_base < writer->line.line_range);
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -179,6 +180,10 @@ dw_serial_push_form(Arena *arena, String8List *srl, DW_Version version, DW_Forma
|
|||||||
case DW_Form_String: {
|
case DW_Form_String: {
|
||||||
str8_serial_push_cstr(arena, srl, form.reader.string);
|
str8_serial_push_cstr(arena, srl, form.reader.string);
|
||||||
} break;
|
} break;
|
||||||
|
case DW_Form_Block: {
|
||||||
|
dw_serial_push_uleb128(arena, srl, form.reader.block.size);
|
||||||
|
str8_serial_push_string(arena, srl, form.reader.block);
|
||||||
|
} break;
|
||||||
case DW_Form_Flag: {
|
case DW_Form_Flag: {
|
||||||
str8_serial_push_u8(arena, srl, form.reader.flag);
|
str8_serial_push_u8(arena, srl, form.reader.flag);
|
||||||
} break;
|
} break;
|
||||||
@@ -537,7 +542,9 @@ dw_data_from_line_insts(Arena *arena, U8 address_size, DW_LineInstList insts)
|
|||||||
} break;
|
} break;
|
||||||
case DW_StdOpcode_SetPrologueEnd: {} break;
|
case DW_StdOpcode_SetPrologueEnd: {} break;
|
||||||
case DW_StdOpcode_SetEpilogueBegin: {} break;
|
case DW_StdOpcode_SetEpilogueBegin: {} break;
|
||||||
case DW_StdOpcode_SetIsa: {} break;
|
case DW_StdOpcode_SetIsa: {
|
||||||
|
dw_serial_push_uleb128(arena, &srl, inst->set_isa);
|
||||||
|
} break;
|
||||||
case DW_StdOpcode_ExtendedOpcode: {
|
case DW_StdOpcode_ExtendedOpcode: {
|
||||||
// get ext size
|
// get ext size
|
||||||
U64 ext_size = 0;
|
U64 ext_size = 0;
|
||||||
@@ -562,7 +569,7 @@ dw_data_from_line_insts(Arena *arena, U8 address_size, DW_LineInstList insts)
|
|||||||
switch (inst->ext) {
|
switch (inst->ext) {
|
||||||
case DW_ExtOpcode_EndSequence: {} break;
|
case DW_ExtOpcode_EndSequence: {} break;
|
||||||
case DW_ExtOpcode_SetAddress: {
|
case DW_ExtOpcode_SetAddress: {
|
||||||
dw_serial_push_uleb128(arena, &srl, inst->set_address);
|
str8_serial_push_string(arena, &srl, str8_copy(arena, str8((U8 *)&inst->set_address, address_size)));
|
||||||
} break;
|
} break;
|
||||||
case DW_ExtOpcode_DefineFile: {
|
case DW_ExtOpcode_DefineFile: {
|
||||||
NotImplemented;
|
NotImplemented;
|
||||||
@@ -590,23 +597,29 @@ dw_writer_line_emit(DW_Writer *writer, DW_WriterFile *file, U64 ln, U64 col, U64
|
|||||||
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_file(file));
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_file(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)); }
|
||||||
|
|
||||||
Assert(addr <= max_S64);
|
Assert(addr <= max_S64);
|
||||||
S64 addr_delta = (S64)addr - (S64)writer->line.addr;
|
S64 addr_delta = (S64)addr - (S64)writer->line.addr;
|
||||||
S64 ln_delta = (S64)ln - (S64)writer->line.ln;
|
S64 ln_delta = (S64)ln - (S64)writer->line.ln;
|
||||||
S64 col_delta = (S64)col - (S64)writer->line.col;
|
|
||||||
|
|
||||||
if (col_delta == 0 && (ln_delta > 0 || addr_delta > 0) &&
|
S64 max_ln_delta = writer->line.line_range + writer->line.line_base;
|
||||||
writer->line.line_base <= ln_delta && ln_delta < writer->line.line_range+writer->line.line_base &&
|
S64 max_addr_delta = (max_U8 - writer->line.opcode_base - (ln_delta - writer->line.line_base)) / writer->line.line_range;
|
||||||
addr_delta < max_U8 - writer->line.opcode_base) {
|
if ((ln_delta != 0 || addr_delta != 0) &&
|
||||||
U8 opcode = (ln_delta - writer->line.line_base) + (writer->line.line_range * addr_delta) + writer->line.opcode_base;
|
writer->line.line_base <= ln_delta && ln_delta < max_ln_delta && // check line number window
|
||||||
|
0 <= addr_delta && addr_delta <= max_addr_delta) { // check address window
|
||||||
|
U8 opcode = (ln_delta - writer->line.line_base) + (addr_delta * writer->line.line_range) + writer->line.opcode_base;
|
||||||
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, (DW_LineInst){ .opcode = opcode });
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, (DW_LineInst){ .opcode = opcode });
|
||||||
} else {
|
} else {
|
||||||
if (addr_delta != 0) { dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(addr_delta)); }
|
if (addr_delta != 0) { dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(addr_delta)); }
|
||||||
if (ln_delta != 0) { dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(ln_delta)); }
|
if (ln_delta != 0) { dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(ln_delta)); }
|
||||||
if (col_delta != 0) { dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_column(col_delta)); }
|
if (addr_delta != 0 || ln_delta != 0 || col_delta != 0) {
|
||||||
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_copy());
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_copy());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update registers
|
||||||
writer->line.file = file;
|
writer->line.file = file;
|
||||||
writer->line.ln = ln;
|
writer->line.ln = ln;
|
||||||
writer->line.col = col;
|
writer->line.col = col;
|
||||||
@@ -619,6 +632,22 @@ 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));
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_address(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_set_discriminator(DW_Writer *writer, U64 d)
|
||||||
|
{
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_discriminator(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
dw_writer_line_end_sequence(DW_Writer *writer)
|
||||||
|
{
|
||||||
|
writer->line.file = 0;
|
||||||
|
writer->line.ln = 1;
|
||||||
|
writer->line.addr = 0;
|
||||||
|
writer->line.col = 0;
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_end_sequence());
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
dw_writer_line_set_prologue_end(DW_Writer *writer)
|
dw_writer_line_set_prologue_end(DW_Writer *writer)
|
||||||
{
|
{
|
||||||
@@ -642,7 +671,6 @@ dw_writer_new_file(DW_Writer *writer, String8 path)
|
|||||||
{
|
{
|
||||||
DW_WriterFile *file = push_array(writer->arena, DW_WriterFile, 1);
|
DW_WriterFile *file = push_array(writer->arena, DW_WriterFile, 1);
|
||||||
file->path = path;
|
file->path = path;
|
||||||
file->file_idx = writer->line.file_count;
|
|
||||||
|
|
||||||
SLLQueuePush(writer->line.first_file, writer->line.last_file, file);
|
SLLQueuePush(writer->line.first_file, writer->line.last_file, file);
|
||||||
writer->line.file_count += 1;
|
writer->line.file_count += 1;
|
||||||
@@ -936,7 +964,7 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
// line
|
// line
|
||||||
{
|
{
|
||||||
// push line table terminator
|
// push line table terminator
|
||||||
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_end_sequence());
|
dw_writer_line_end_sequence(writer);
|
||||||
|
|
||||||
// find comp dir in the compile unit tag
|
// find comp dir in the compile unit tag
|
||||||
String8 comp_dir = {0};
|
String8 comp_dir = {0};
|
||||||
@@ -945,7 +973,7 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
for EachNode(attrib, DW_WriterAttrib, writer->root->first_attrib) {
|
for EachNode(attrib, DW_WriterAttrib, writer->root->first_attrib) {
|
||||||
if (attrib->kind == DW_AttribKind_CompDir) {
|
if (attrib->kind == DW_AttribKind_CompDir) {
|
||||||
AssertAlways(attrib->form.writer.kind == DW_WriterFormKind_String);
|
AssertAlways(attrib->form.writer.kind == DW_WriterFormKind_String);
|
||||||
comp_dir = attrib->form.writer.string;
|
comp_dir = str8_chop_last_slash(attrib->form.writer.string);
|
||||||
} else if (attrib->kind == DW_AttribKind_Name) {
|
} else if (attrib->kind == DW_AttribKind_Name) {
|
||||||
AssertAlways(attrib->form.writer.kind == DW_WriterFormKind_String);
|
AssertAlways(attrib->form.writer.kind == DW_WriterFormKind_String);
|
||||||
comp_name = attrib->form.writer.string;
|
comp_name = attrib->form.writer.string;
|
||||||
@@ -964,31 +992,38 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
dw_serial_push_uleb128(writer->arena, srl, DW_LNCT_Path);
|
dw_serial_push_uleb128(writer->arena, srl, DW_LNCT_Path);
|
||||||
dw_serial_push_uleb128(writer->arena, srl, DW_Form_String);
|
dw_serial_push_uleb128(writer->arena, srl, DW_Form_String);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// dedup directories
|
// dedup directories
|
||||||
String8List dirs = {0};
|
String8List dirs = {0};
|
||||||
HashTable *dir_ht = hash_table_init(scratch.arena, writer->line.file_count + 1);
|
HashTable *dir_ht = hash_table_init(scratch.arena, writer->line.file_count + 1);
|
||||||
// first entry must be compile unit directory
|
// first entry must be compile unit directory
|
||||||
hash_table_push_string_u64(scratch.arena, dir_ht, comp_dir, dir_ht->count);
|
hash_table_push_string_u64(scratch.arena, dir_ht, comp_dir, dir_ht->count);
|
||||||
|
if (comp_dir.size == 2 && char_is_alpha(comp_dir.str[0]) && comp_dir.str[1] == ':') {
|
||||||
|
str8_list_pushf(scratch.arena, &dirs, "%S/", comp_dir);
|
||||||
|
} else {
|
||||||
str8_list_push(scratch.arena, &dirs, comp_dir);
|
str8_list_push(scratch.arena, &dirs, comp_dir);
|
||||||
|
}
|
||||||
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
||||||
String8 path = str8_chop_last_slash(file->path);
|
String8 path = str8_chop_last_slash(file->path);
|
||||||
|
if (path.size == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ( ! hash_table_search_string_u64(dir_ht, path, &file->dir_idx)) {
|
if ( ! hash_table_search_string_u64(dir_ht, path, &file->dir_idx)) {
|
||||||
|
// @dir_idx
|
||||||
file->dir_idx = hash_table_push_string_u64(scratch.arena, dir_ht, path, dir_ht->count)->v.value_u64;
|
file->dir_idx = hash_table_push_string_u64(scratch.arena, dir_ht, path, dir_ht->count)->v.value_u64;
|
||||||
|
if (path.size == 2 && char_is_alpha(path.str[0]) && path.str[1] == ':') {
|
||||||
|
str8_list_pushf(scratch.arena, &dirs, "%S/", path);
|
||||||
|
} else {
|
||||||
str8_list_push(scratch.arena, &dirs, path);
|
str8_list_push(scratch.arena, &dirs, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
// (15) directories_count
|
||||||
dw_serial_push_uleb128(writer->arena, srl, dir_ht->count);
|
dw_serial_push_uleb128(writer->arena, srl, dirs.node_count);
|
||||||
|
|
||||||
// (16) directories
|
// (16) directories
|
||||||
for (U64 i = 0; i < dir_ht->count; i += 1) {
|
for EachNode(dir_n, String8Node, dirs.first) {
|
||||||
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_n->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);
|
scratch_end(scratch);
|
||||||
@@ -1016,7 +1051,7 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
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->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->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 ( ! u128_match(file->md5, u128_zero())) { *(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; }
|
if (file->source.size != 0) { *(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_LLVM_Source) = DW_Form_String; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,11 +1092,15 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
U64 file_idx = 0;
|
||||||
for EachNode(file, DW_WriterFile, writer->line.first_file) {
|
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_udata = { .reader = { .kind = DW_Form_UData } };
|
||||||
static DW_WriterXForm null_form_string = { .reader = { .kind = DW_Form_String } };
|
static DW_WriterXForm null_form_string = { .reader = { .kind = DW_Form_String } };
|
||||||
static DW_WriterXForm null_form_block = { .reader = { .kind = DW_Form_Block } };
|
static DW_WriterXForm null_form_block = { .reader = { .kind = DW_Form_Block } };
|
||||||
|
|
||||||
|
// @file_idx
|
||||||
|
file->file_idx = file_idx++;
|
||||||
|
|
||||||
// path
|
// path
|
||||||
Assert(*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_Path) == DW_Form_String);
|
Assert(*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_Path) == DW_Form_String);
|
||||||
String8 file_name = str8_skip_last_slash(file->path);
|
String8 file_name = str8_skip_last_slash(file->path);
|
||||||
@@ -1095,8 +1134,8 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
|
|
||||||
// MD5
|
// MD5
|
||||||
if (*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_MD5) == DW_Form_Block) {
|
if (*(DW_FormKind *)hash_table_search_u64_raw(encs_ht, DW_LNCT_MD5) == DW_Form_Block) {
|
||||||
if (file->md5.size) {
|
if ( ! u128_match(file->md5, u128_zero())) {
|
||||||
DW_WriterXForm md5_form = { .reader = { .kind = DW_Form_Block, .block = file->md5 } };
|
DW_WriterXForm md5_form = { .reader = { .kind = DW_Form_Block, .block = str8_struct(&file->md5) } };
|
||||||
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, md5_form);
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, md5_form);
|
||||||
} else {
|
} else {
|
||||||
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, null_form_block);
|
dw_serial_push_form(writer->arena, srl, writer->version, writer->format, writer->address_size, 0, null_form_block);
|
||||||
@@ -1143,9 +1182,9 @@ dw_writer_emit(DW_Writer *writer)
|
|||||||
// (11) opcode_base
|
// (11) opcode_base
|
||||||
str8_serial_push_struct(writer->arena, srl, &writer->line.opcode_base);
|
str8_serial_push_struct(writer->arena, srl, &writer->line.opcode_base);
|
||||||
// (12) standard_opcode_lengths
|
// (12) standard_opcode_lengths
|
||||||
U8 *std_op_lens = push_array(writer->arena, U8, DW_StdOpcode_Count - 1);
|
U8 *std_op_lens = push_array(writer->arena, U8, writer->line.opcode_base - 1);
|
||||||
for (U64 i = 1; i < DW_StdOpcode_Count; i += 1) { std_op_lens[i-1] = dw_length_from_std_opcode(i); }
|
for (U64 i = 1; i < writer->line.opcode_base; i += 1) { std_op_lens[i-1] = dw_length_from_std_opcode(i); }
|
||||||
str8_serial_push_string(writer->arena, srl, str8(std_op_lens, DW_StdOpcode_Count - 1));
|
str8_serial_push_string(writer->arena, srl, str8(std_op_lens, writer->line.opcode_base - 1));
|
||||||
// directory table
|
// directory table
|
||||||
str8_list_concat_in_place(srl, &dir_table_srl);
|
str8_list_concat_in_place(srl, &dir_table_srl);
|
||||||
// file table
|
// file table
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ typedef struct DW_WriterFile
|
|||||||
String8 path;
|
String8 path;
|
||||||
U64 time_stamp;
|
U64 time_stamp;
|
||||||
U64 size;
|
U64 size;
|
||||||
String8 md5;
|
U128 md5;
|
||||||
String8 source;
|
String8 source;
|
||||||
// computed during line table emit step
|
// computed during line table emit step
|
||||||
U64 file_idx;
|
U64 file_idx;
|
||||||
@@ -308,7 +308,9 @@ internal DW_LineInstNode * dw_line_inst_list_push (Arena *arena, DW_LineInst
|
|||||||
|
|
||||||
internal void dw_writer_line_emit (DW_Writer *writer, DW_WriterFile *file, U64 ln, U64 col, U64 addr);
|
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_address (DW_Writer *writer, U64 address);
|
||||||
internal void dw_writer_line_set_prologue_end(DW_Writer *writer);
|
internal void dw_writer_line_set_discriminator(DW_Writer *writer, U64 d);
|
||||||
|
internal void dw_writer_line_end_sequence (DW_Writer *writer);
|
||||||
|
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_epilogue_begin (DW_Writer *writer);
|
||||||
internal void dw_writer_line_set_isa (DW_Writer *writer, U64 isa);
|
internal void dw_writer_line_set_isa (DW_Writer *writer, U64 isa);
|
||||||
internal DW_WriterFile * dw_writer_new_file (DW_Writer *writer, String8 path);
|
internal DW_WriterFile * dw_writer_new_file (DW_Writer *writer, String8 path);
|
||||||
|
|||||||
@@ -2564,7 +2564,7 @@ d2r_src_file_lookup_compar(void *raw_a, void *raw_b)
|
|||||||
String8 dir_path_b = b->vm->header.dir_table.v[file_b->dir_idx];
|
String8 dir_path_b = b->vm->header.dir_table.v[file_b->dir_idx];
|
||||||
int cmp = str8_compar(dir_path_a, dir_path_b, 0);
|
int cmp = str8_compar(dir_path_a, dir_path_b, 0);
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
cmp = str8_compar(file_a->file_name, file_b->file_name, 0);
|
cmp = str8_compar(file_a->path, file_b->path, 0);
|
||||||
}
|
}
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
@@ -2587,9 +2587,9 @@ d2r_hash_line_file(String8 dir_path, DW_LineFile *file)
|
|||||||
XXH3_state_t hasher = {0};
|
XXH3_state_t hasher = {0};
|
||||||
XXH3_64bits_reset(&hasher);
|
XXH3_64bits_reset(&hasher);
|
||||||
XXH3_64bits_update(&hasher, dir_path.str, dir_path.size);
|
XXH3_64bits_update(&hasher, dir_path.str, dir_path.size);
|
||||||
XXH3_64bits_update(&hasher, file->file_name.str, file->file_name.size);
|
XXH3_64bits_update(&hasher, file->path.str, file->path.size);
|
||||||
XXH3_64bits_update(&hasher, &file->modify_time, sizeof(file->modify_time));
|
XXH3_64bits_update(&hasher, &file->time_stamp, sizeof(file->time_stamp));
|
||||||
XXH3_64bits_update(&hasher, &file->md5_digest, sizeof(file->md5_digest));
|
XXH3_64bits_update(&hasher, &file->md5, sizeof(file->md5));
|
||||||
XXH64_hash_t hash = XXH3_64bits_digest(&hasher);
|
XXH64_hash_t hash = XXH3_64bits_digest(&hasher);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
@@ -2841,18 +2841,18 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
|||||||
{
|
{
|
||||||
String8List path_list = {0};
|
String8List path_list = {0};
|
||||||
str8_list_push_node(&path_list, &(String8Node){ .string = lookup->vm->header.dir_table.v[src->dir_idx] });
|
str8_list_push_node(&path_list, &(String8Node){ .string = lookup->vm->header.dir_table.v[src->dir_idx] });
|
||||||
str8_list_push_node(&path_list, &(String8Node){ .string = src->file_name });
|
str8_list_push_node(&path_list, &(String8Node){ .string = src->path });
|
||||||
path = str8_path_list_join_by_style(arena, &path_list, path_style);
|
path = str8_path_list_join_by_style(arena, &path_list, path_style);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill out source file
|
// fill out source file
|
||||||
dst->path = path;
|
dst->path = path;
|
||||||
if ( ! u128_match(src->md5_digest, u128_zero())) {
|
if ( ! u128_match(src->md5, u128_zero())) {
|
||||||
dst->checksum_kind = RDI_ChecksumKind_MD5;
|
dst->checksum_kind = RDI_ChecksumKind_MD5;
|
||||||
dst->checksum = str8_copy(arena, str8_struct(&src->md5_digest));
|
dst->checksum = str8_copy(arena, str8_struct(&src->md5));
|
||||||
} else if (src->modify_time != 0) {
|
} else if (src->time_stamp != 0) {
|
||||||
dst->checksum_kind = RDI_ChecksumKind_Timestamp;
|
dst->checksum_kind = RDI_ChecksumKind_Timestamp;
|
||||||
dst->checksum = str8_copy(arena, str8_struct(&src->modify_time));
|
dst->checksum = str8_copy(arena, str8_struct(&src->time_stamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup->src_file = dst;
|
lookup->src_file = dst;
|
||||||
@@ -2891,7 +2891,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
|
|||||||
(line_buffer_size >= D2R_LineBufferMax || line_buffer->file_index != vm->state.file_index))
|
(line_buffer_size >= D2R_LineBufferMax || line_buffer->file_index != vm->state.file_index))
|
||||||
&& line_buffer_size > 0) {
|
&& line_buffer_size > 0) {
|
||||||
// lookup source file
|
// lookup source file
|
||||||
DW_LineFile *file = &vm->header.file_table.v[vm->state.file_index];
|
DW_LineFile *file = &vm->header.file_table.v[line_buffer->file_index];
|
||||||
U64 hash = d2r_hash_line_file(vm->header.dir_table.v[file->dir_idx], file);
|
U64 hash = d2r_hash_line_file(vm->header.dir_table.v[file->dir_idx], file);
|
||||||
D2R_SrcFileLookup *lookup = lfht_search(src_file_lfht, hash, &(D2R_SrcFileLookup){ .file = file, .vm = vm }, d2r_src_file_lookup_is_equal, 0);
|
D2R_SrcFileLookup *lookup = lfht_search(src_file_lfht, hash, &(D2R_SrcFileLookup){ .file = file, .vm = vm }, d2r_src_file_lookup_is_equal, 0);
|
||||||
RDIM_SrcFile *src_file = lookup->src_file;
|
RDIM_SrcFile *src_file = lookup->src_file;
|
||||||
|
|||||||
+418
-78
@@ -34,7 +34,7 @@ t_dw_test_sleb128(U64 v, U64 expected_length)
|
|||||||
String8 e = dw_write_sleb128(scratch.arena, v0);
|
String8 e = dw_write_sleb128(scratch.arena, v0);
|
||||||
if (!(expected_length == e.size)) { goto exit; }
|
if (!(expected_length == e.size)) { goto exit; }
|
||||||
|
|
||||||
U64 v1;
|
S64 v1;
|
||||||
U64 bytes_read = str8_deserial_read_sleb128(e, 0, &v1);
|
U64 bytes_read = str8_deserial_read_sleb128(e, 0, &v1);
|
||||||
if (!(bytes_read == e.size)) { goto exit; }
|
if (!(bytes_read == e.size)) { goto exit; }
|
||||||
if (!(v0 == v1)) { goto exit; }
|
if (!(v0 == v1)) { goto exit; }
|
||||||
@@ -55,6 +55,8 @@ T_BeginTest(test_leb128)
|
|||||||
T_Ok(t_dw_test_sleb128(min_S64, 10));
|
T_Ok(t_dw_test_sleb128(min_S64, 10));
|
||||||
T_Ok(t_dw_test_sleb128(max_S64, 10));
|
T_Ok(t_dw_test_sleb128(max_S64, 10));
|
||||||
|
|
||||||
|
T_Ok(t_dw_test_uleb128(0xDEADBEEFCAFEBABE, 10));
|
||||||
|
|
||||||
for EachIndex(i, 64) {
|
for EachIndex(i, 64) {
|
||||||
T_Ok(t_dw_test_uleb128((1ull << i), 1 + (i / 7)));
|
T_Ok(t_dw_test_uleb128((1ull << i), 1 + (i / 7)));
|
||||||
}
|
}
|
||||||
@@ -102,45 +104,419 @@ exit:;
|
|||||||
return is_match;
|
return is_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DW_Writer *
|
internal DW_Input
|
||||||
dwt_make_writer(void)
|
dw_input_from_writer(Arena *arena, DW_Writer *writer)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
String8 comp_dir = t_make_file_path(scratch.arena, str8_lit(""));
|
OBJ *obj = obj_alloc(0, Arch_x64);
|
||||||
String8 comp_name = str8_lit("test_code.txt");
|
OBJ_Section *text_section = obj_push_section(obj, str8_lit(".text"), OBJ_SectionFlag_Read|OBJ_SectionFlag_Exec|OBJ_SectionFlag_Load);
|
||||||
String8 test_text = str8_lit("nop\nnop\nret\n");
|
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
|
||||||
String8 test_path = t_make_file_path(scratch.arena, comp_name);
|
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
|
||||||
t_write_file(comp_name, test_text);
|
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
|
||||||
|
str8_serial_push_u8(obj->arena, &text_section->data, 0xc3);
|
||||||
|
obj_push_symbol(obj, str8_lit("entry"), OBJ_SymbolScope_Global, OBJ_RefKind_Section, text_section);
|
||||||
|
|
||||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_Last, DW_CompUnitKind_Compile, Arch_x64);
|
dw_writer_emit_to_obj(writer, obj);
|
||||||
// line
|
String8 raw_coff = coff_from_obj(scratch.arena, obj);
|
||||||
{
|
|
||||||
DW_WriterFile *a_file = dw_writer_new_file(writer, test_path);
|
|
||||||
dw_writer_line_set_prologue_end(writer);
|
|
||||||
dw_writer_line_emit(writer, a_file, 1, 0, 0x140001000);
|
|
||||||
dw_writer_line_emit(writer, a_file, 2, 0, 0x140001001);
|
|
||||||
dw_writer_line_emit(writer, a_file, 3, 0, 0x140001002);
|
|
||||||
|
|
||||||
//DW_WriterFile *b_file = dw_writer_new_file(writer, str8_lit("~/devel/projects/b/b.c"));
|
t_write_file(str8_lit("dwarf.obj"), raw_coff);
|
||||||
//DW_WriterFile *a_file = dw_writer_new_file(writer, str8_lit("~/devel/projects/a.c"));
|
t_invoke(str8_lit("radlink"), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64);
|
||||||
//dw_writer_line_set_prologue_end(writer);
|
os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
|
||||||
//dw_writer_line_emit(writer, b_file, 10, 0, 0x140001000);
|
|
||||||
//dw_writer_line_emit(writer, b_file, 11, 0, 0x140001010);
|
String8 exe = t_read_file(arena, str8_lit("a.exe"));
|
||||||
//dw_writer_line_emit(writer, a_file, 1, 0, 0x140001016);
|
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe);
|
||||||
//dw_writer_line_emit(writer, a_file, 2, 0, 0x140001020);
|
COFF_SectionHeader *section_table = (COFF_SectionHeader *)(exe.str + pe.section_table_range.min);
|
||||||
}
|
String8 string_table = str8_substr(exe, pe.string_table_range);
|
||||||
// info
|
DW_Input input = dw_input_from_coff_section_table(arena, exe, string_table, pe.section_count, section_table);
|
||||||
{
|
|
||||||
|
obj_release(&obj);
|
||||||
|
scratch_end(scratch);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_BeginTest(dwarf_line_opcodes)
|
||||||
|
{
|
||||||
|
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||||
|
String8 comp_dir = str8_lit("c:/devel/");
|
||||||
|
String8 comp_name = str8_lit("test.c");
|
||||||
|
U64 address = 0xDEADBEEFCAFEBABE;
|
||||||
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, comp_dir);
|
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
|
||||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
|
||||||
|
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
|
||||||
|
dw_writer_tag_end(writer);
|
||||||
|
|
||||||
|
// test directory table and file table
|
||||||
|
DW_WriterFile *file2 = dw_writer_new_file(writer, str8_lit("d:/foobar/qwe.c"));
|
||||||
|
file2->time_stamp = 123;
|
||||||
|
file2->size = max_U64;
|
||||||
|
file2->md5 = *(U128 *)&((U8[sizeof(U128)]) { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, });
|
||||||
|
file2->source = str8_lit("a quick brown fox jumps over the lazy dog\n");
|
||||||
|
DW_WriterFile *file = dw_writer_new_file(writer, comp_name);
|
||||||
|
file->time_stamp = max_U64;
|
||||||
|
file->size = 314;
|
||||||
|
file->md5 = *(U128 *)&((U8[sizeof(U128)]) { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, });
|
||||||
|
file->source = str8_lit("int main() { return 057; }\n");
|
||||||
|
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_copy());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(7));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(-7));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(4));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-4));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_file(file));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_column(max_U64));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_column(0));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_negate_stmt());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_negate_stmt());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_basic_block());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_const_add_pc());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_fixed_advance_pc(max_U16));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_prologue_end());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_epilogue_begin());
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_set_isa(max_U64));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_address(address));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_discriminator(2));
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_end_sequence());
|
||||||
|
|
||||||
|
DW_Input input = dw_input_from_writer(scratch.arena, writer);
|
||||||
|
Rng1U64Array cu_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[DW_Section_Info].data);
|
||||||
|
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, (DW_ListUnitInput){0}, cu_ranges.v[0].min, 0);
|
||||||
|
DW_LineVM *line_vm = dw_line_vm_init(&input, &cu);
|
||||||
|
|
||||||
|
T_Ok(line_vm->header.dir_table.count == 2);
|
||||||
|
T_Ok(line_vm->header.file_table.count == 2);
|
||||||
|
|
||||||
|
T_Ok(str8_match(line_vm->header.dir_table.v[0], str8_lit("c:/devel"), 0));
|
||||||
|
T_Ok(str8_match(line_vm->header.dir_table.v[1], str8_lit("d:/foobar"), 0));
|
||||||
|
|
||||||
|
DW_LineFile *file_reader = &line_vm->header.file_table.v[0];
|
||||||
|
T_Ok(str8_match(file_reader->path, comp_name, 0));
|
||||||
|
T_Ok(file_reader->dir_idx == 0);
|
||||||
|
T_Ok(file_reader->time_stamp == file->time_stamp);
|
||||||
|
T_Ok(u128_match(file_reader->md5, file->md5));
|
||||||
|
T_Ok(str8_match(file_reader->source, file->source, 0));
|
||||||
|
|
||||||
|
DW_LineFile *file2_reader = &line_vm->header.file_table.v[1];
|
||||||
|
T_Ok(str8_match(file2_reader->path, str8_lit("qwe.c"), 0));
|
||||||
|
T_Ok(file2_reader->dir_idx == 1);
|
||||||
|
T_Ok(file2_reader->time_stamp == file2->time_stamp);
|
||||||
|
T_Ok(u128_match(file2_reader->md5, file2->md5));
|
||||||
|
T_Ok(str8_match(file2_reader->source, file2->source, 0));
|
||||||
|
|
||||||
|
T_Ok(line_vm->new_line == 0);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
|
||||||
|
T_Ok(line_vm->new_line == 1);
|
||||||
|
T_Ok(line_vm->state.discriminator == 0);
|
||||||
|
T_Ok(line_vm->state.basic_block == 0);
|
||||||
|
T_Ok(line_vm->state.prologue_end == 0);
|
||||||
|
T_Ok(line_vm->state.epilogue_begin == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
|
||||||
|
T_Ok(line_vm->state.address == 7);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
|
||||||
|
T_Ok(line_vm->state.address == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 5);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 1);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetFile);
|
||||||
|
T_Ok(line_vm->state.file_index == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetColumn);
|
||||||
|
T_Ok(line_vm->state.column == max_U64);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetColumn);
|
||||||
|
T_Ok(line_vm->state.column == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_NegateStmt);
|
||||||
|
T_Ok(line_vm->state.is_stmt == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_NegateStmt);
|
||||||
|
T_Ok(line_vm->state.is_stmt == 1);
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.basic_block == 0);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetBasicBlock);
|
||||||
|
T_Ok(line_vm->state.basic_block == 1);
|
||||||
|
|
||||||
|
{
|
||||||
|
U64 addr_before = line_vm->state.address;
|
||||||
|
U64 const_advance = (0xffu - line_vm->header.opcode_base) / line_vm->header.line_range;
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
T_Ok(line_vm->state.address == addr_before + const_advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.address == 0x11);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_FixedAdvancePc);
|
||||||
|
T_Ok(line_vm->state.address == max_U16 + 0x11);
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.prologue_end == 0);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetPrologueEnd);
|
||||||
|
T_Ok(line_vm->state.prologue_end == 1);
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.epilogue_begin == 0);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetEpilogueBegin);
|
||||||
|
T_Ok(line_vm->state.epilogue_begin == 1);
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.isa == 0);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetIsa);
|
||||||
|
T_Ok(line_vm->state.isa == max_U64);
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.address != address);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
|
||||||
|
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_SetAddress);
|
||||||
|
T_Ok(line_vm->state.address == address);
|
||||||
|
|
||||||
|
T_Ok(line_vm->state.discriminator == 0);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
|
||||||
|
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_SetDiscriminator);
|
||||||
|
T_Ok(line_vm->state.discriminator == 2);
|
||||||
|
|
||||||
|
T_Ok(!line_vm->state.end_sequence);
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
|
||||||
|
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence);
|
||||||
|
T_Ok(line_vm->state.end_sequence);
|
||||||
|
|
||||||
|
dw_writer_end(&writer);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(dwarf_line_emit)
|
||||||
|
{
|
||||||
|
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||||
|
String8 comp_dir = str8_lit("c:/devel/");
|
||||||
|
String8 comp_name = str8_lit("test.c");
|
||||||
|
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_CompDir, comp_dir);
|
||||||
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
|
||||||
|
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
|
||||||
|
dw_writer_tag_end(writer);
|
||||||
|
|
||||||
|
// test special opcode writer and reader
|
||||||
|
DW_WriterFile *file = dw_writer_new_file(writer, comp_name);
|
||||||
|
|
||||||
|
// init sequence
|
||||||
|
dw_writer_line_emit(writer, file, 10000, 0, 1000);
|
||||||
|
|
||||||
|
for EachIndex(i, abs_s64(writer->line.line_base) + 1) {
|
||||||
|
dw_writer_line_emit(writer, file, writer->line.ln-i, 0, writer->line.addr+1);
|
||||||
|
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(i));
|
||||||
|
writer->line.ln += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special opcode line window underflow, must emit three instructions to advance
|
||||||
|
dw_writer_line_emit(writer, file, (writer->line.ln + writer->line.line_base) - 1, 0, writer->line.addr + 1);
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-(writer->line.line_base - 1)));
|
||||||
|
|
||||||
|
for EachIndex(i, (writer->line.line_range + writer->line.line_base) + 1) {
|
||||||
|
dw_writer_line_emit(writer, file, writer->line.ln+i, 0, writer->line.addr+1);
|
||||||
|
|
||||||
|
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-i));
|
||||||
|
writer->line.ln -= i;
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_writer_line_end_sequence(writer);
|
||||||
|
dw_writer_line_emit(writer, file, 1000, 0, writer->line.addr+1);
|
||||||
|
|
||||||
|
// test address window
|
||||||
|
S64 c = writer->line.line_range + writer->line.line_base;
|
||||||
|
U64 line_addr_count = 0;
|
||||||
|
for (S64 i = 0; i < c; ++i) {
|
||||||
|
U64 ln_delta = i + writer->line.line_base;
|
||||||
|
S64 max_ln_delta = writer->line.line_range + writer->line.line_base;
|
||||||
|
S64 max_addr_delta = (max_U8 - writer->line.opcode_base - (ln_delta - writer->line.line_base)) / writer->line.line_range;
|
||||||
|
for EachIndex(k, max_addr_delta) {
|
||||||
|
dw_writer_line_emit(writer, file, writer->line.ln + i, 0, writer->line.addr + k);
|
||||||
|
line_addr_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DW_Input input = dw_input_from_writer(scratch.arena, writer);
|
||||||
|
Rng1U64Array cu_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[DW_Section_Info].data);
|
||||||
|
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, (DW_ListUnitInput){0}, cu_ranges.v[0].min, 0);
|
||||||
|
DW_LineVM *line_vm = dw_line_vm_init(&input, &cu);
|
||||||
|
|
||||||
|
// check init sequence
|
||||||
|
{
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_SetFile);
|
||||||
|
T_Ok(line_vm->state.file_index == 0);
|
||||||
|
T_Ok(line_vm->new_line == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
|
||||||
|
T_Ok(line_vm->state.address == 1000);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->new_line == 0);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == 1000);
|
||||||
|
T_Ok(line_vm->new_line == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
U64 pc = line_vm->state.address;
|
||||||
|
for EachIndex(i, abs_s64(writer->line.line_base) + 1) {
|
||||||
|
pc += 1;
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == 0x20 - i);
|
||||||
|
T_Ok(line_vm->state.line == 10000 - i);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(line_vm->new_line == 1);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// line window underflow check
|
||||||
|
{
|
||||||
|
pc += 1;
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 9994);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
|
||||||
|
T_Ok(line_vm->state.line == 9994);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
for EachIndex(i, writer->line.line_range + writer->line.line_base) {
|
||||||
|
pc += 1;
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == 0x20 + i);
|
||||||
|
T_Ok(line_vm->state.line == 10000 + i);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// line window overflow check
|
||||||
|
{
|
||||||
|
pc += 1;
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 10009);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(line_vm->state.line == 10009);
|
||||||
|
T_Ok(line_vm->new_line);
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(!line_vm->new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
|
||||||
|
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence);
|
||||||
|
T_Ok(line_vm->state.line == 10000);
|
||||||
|
T_Ok(line_vm->state.address == pc);
|
||||||
|
T_Ok(line_vm->new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
|
||||||
|
for EachIndex(i, line_addr_count/*first line is a noop*/-1) {
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->header.opcode_base < line_vm->opcode);
|
||||||
|
T_Ok(line_vm->new_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
T_Ok(dw_line_vm_step(line_vm));
|
||||||
|
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
|
||||||
|
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence);
|
||||||
|
T_Ok(line_vm->state.line == 1586);
|
||||||
|
T_Ok(line_vm->state.address == 1161);
|
||||||
|
T_Ok(line_vm->new_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(dwarf_writer)
|
||||||
|
{
|
||||||
|
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||||
|
// info
|
||||||
|
{
|
||||||
|
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_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);
|
||||||
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
|
|
||||||
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140001000);
|
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140001000);
|
||||||
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x140001003);
|
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x140001004);
|
||||||
{
|
{
|
||||||
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
|
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
|
||||||
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
|
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
|
||||||
@@ -183,7 +559,7 @@ dwt_make_writer(void)
|
|||||||
dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1);
|
dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1);
|
||||||
dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1);
|
dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1);
|
||||||
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140001000);
|
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140001000);
|
||||||
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x140001003);
|
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x140001004);
|
||||||
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("main"));
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("main"));
|
||||||
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, simple_struct_tag);
|
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, simple_struct_tag);
|
||||||
dw_writer_push_attrib_expression(writer, DW_AttribKind_FrameBase, &(DW_ExprEnc)DW_ExprEnc_Op(Reg7), 1);
|
dw_writer_push_attrib_expression(writer, DW_AttribKind_FrameBase, &(DW_ExprEnc)DW_ExprEnc_Op(Reg7), 1);
|
||||||
@@ -192,47 +568,12 @@ dwt_make_writer(void)
|
|||||||
dw_writer_tag_end(writer);
|
dw_writer_tag_end(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
DW_Input input = dw_input_from_writer(scratch.arena, writer);
|
||||||
DW_Input input;
|
|
||||||
{
|
|
||||||
OBJ *obj = obj_alloc(0, Arch_x64);
|
|
||||||
OBJ_Section *text_section = obj_push_section(obj, str8_lit(".text"), OBJ_SectionFlag_Read|OBJ_SectionFlag_Exec|OBJ_SectionFlag_Load);
|
|
||||||
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
|
|
||||||
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
|
|
||||||
str8_serial_push_u8(obj->arena, &text_section->data, 0xc3);
|
|
||||||
obj_push_symbol(obj, str8_lit("entry"), OBJ_SymbolScope_Global, OBJ_RefKind_Section, text_section);
|
|
||||||
|
|
||||||
dw_writer_emit_to_obj(writer, obj);
|
|
||||||
|
|
||||||
String8 raw_coff = coff_from_obj(scratch.arena, obj);
|
|
||||||
COFF_FileHeaderInfo obj_coff_header = coff_file_header_info_from_data(raw_coff);
|
|
||||||
String8 raw_sections = str8_substr(raw_coff, obj_coff_header.section_table_range);
|
|
||||||
U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader);
|
|
||||||
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str;
|
|
||||||
String8 string_table = str8_substr(raw_coff, obj_coff_header.string_table_range);
|
|
||||||
input = dw_input_from_coff_section_table(scratch.arena, raw_coff, string_table, section_count, section_table);
|
|
||||||
|
|
||||||
t_write_file(str8_lit("dwarf.obj"), raw_coff);
|
|
||||||
|
|
||||||
t_invoke(str8_lit("radlink"), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64);
|
|
||||||
|
|
||||||
obj_release(&obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input);
|
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input);
|
||||||
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, lu_input, 0, 1);
|
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, lu_input, 0, 1);
|
||||||
DW_TagTree tag_tree = dw_tag_tree_from_cu(scratch.arena, &input, &cu);
|
DW_TagTree tag_tree = dw_tag_tree_from_cu(scratch.arena, &input, &cu);
|
||||||
AssertAlways(dwt_tags_must_match(writer->root, tag_tree.root));
|
AssertAlways(dwt_tags_must_match(writer->root, tag_tree.root));
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
|
||||||
return writer;
|
|
||||||
}
|
|
||||||
|
|
||||||
T_BeginTest(dwarf_writer)
|
|
||||||
{
|
|
||||||
DW_Writer *writer = dwt_make_writer();
|
|
||||||
|
|
||||||
// validate the writer
|
// validate the writer
|
||||||
|
|
||||||
@@ -250,7 +591,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(comp_unit_tag->kind == DW_TagKind_CompileUnit);
|
T_Ok(comp_unit_tag->kind == DW_TagKind_CompileUnit);
|
||||||
T_Ok(comp_unit_tag->next == 0);
|
T_Ok(comp_unit_tag->next == 0);
|
||||||
T_Ok(comp_unit_tag->parent == 0);
|
T_Ok(comp_unit_tag->parent == 0);
|
||||||
T_Ok(comp_unit_tag->attrib_count == 3);
|
T_Ok(comp_unit_tag->attrib_count == 5);
|
||||||
T_Ok(comp_unit_tag->abbrev_id == 1);
|
T_Ok(comp_unit_tag->abbrev_id == 1);
|
||||||
T_Ok(comp_unit_tag->info_off == 0xc);
|
T_Ok(comp_unit_tag->info_off == 0xc);
|
||||||
|
|
||||||
@@ -278,7 +619,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(char_type_tag->parent == comp_unit_tag);
|
T_Ok(char_type_tag->parent == comp_unit_tag);
|
||||||
T_Ok(char_type_tag->attrib_count == 3);
|
T_Ok(char_type_tag->attrib_count == 3);
|
||||||
T_Ok(char_type_tag->abbrev_id == 2);
|
T_Ok(char_type_tag->abbrev_id == 2);
|
||||||
T_Ok(char_type_tag->info_off == 0x20);
|
T_Ok(char_type_tag->info_off == 0x30);
|
||||||
T_Ok(char_type_tag->first_attrib != char_type_tag->last_attrib);
|
T_Ok(char_type_tag->first_attrib != char_type_tag->last_attrib);
|
||||||
|
|
||||||
DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib;
|
DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib;
|
||||||
@@ -306,7 +647,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(const_type_tag->parent == comp_unit_tag);
|
T_Ok(const_type_tag->parent == comp_unit_tag);
|
||||||
T_Ok(const_type_tag->attrib_count == 1);
|
T_Ok(const_type_tag->attrib_count == 1);
|
||||||
T_Ok(const_type_tag->abbrev_id == 3);
|
T_Ok(const_type_tag->abbrev_id == 3);
|
||||||
T_Ok(const_type_tag->info_off == 0x28);
|
T_Ok(const_type_tag->info_off == 0x38);
|
||||||
T_Ok(const_type_tag->first_attrib && const_type_tag->first_attrib == const_type_tag->last_attrib);
|
T_Ok(const_type_tag->first_attrib && const_type_tag->first_attrib == const_type_tag->last_attrib);
|
||||||
|
|
||||||
DW_WriterAttrib *type_attrib = const_type_tag->first_attrib;
|
DW_WriterAttrib *type_attrib = const_type_tag->first_attrib;
|
||||||
@@ -322,7 +663,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(dup_char_type_tag->parent == comp_unit_tag);
|
T_Ok(dup_char_type_tag->parent == comp_unit_tag);
|
||||||
T_Ok(dup_char_type_tag->attrib_count == 3);
|
T_Ok(dup_char_type_tag->attrib_count == 3);
|
||||||
T_Ok(dup_char_type_tag->abbrev_id == 2);
|
T_Ok(dup_char_type_tag->abbrev_id == 2);
|
||||||
T_Ok(dup_char_type_tag->info_off == 0x2a);
|
T_Ok(dup_char_type_tag->info_off == 0x3a);
|
||||||
T_Ok(dup_char_type_tag->first_attrib != dup_char_type_tag->last_attrib);
|
T_Ok(dup_char_type_tag->first_attrib != dup_char_type_tag->last_attrib);
|
||||||
|
|
||||||
DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib;
|
DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib;
|
||||||
@@ -350,7 +691,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(simple_struct_tag->parent == comp_unit_tag);
|
T_Ok(simple_struct_tag->parent == comp_unit_tag);
|
||||||
T_Ok(simple_struct_tag->attrib_count == 2);
|
T_Ok(simple_struct_tag->attrib_count == 2);
|
||||||
T_Ok(simple_struct_tag->abbrev_id == 4);
|
T_Ok(simple_struct_tag->abbrev_id == 4);
|
||||||
T_Ok(simple_struct_tag->info_off == 0x32);
|
T_Ok(simple_struct_tag->info_off == 0x42);
|
||||||
|
|
||||||
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);
|
||||||
@@ -362,7 +703,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(m0_tag->kind == DW_TagKind_Member);
|
T_Ok(m0_tag->kind == DW_TagKind_Member);
|
||||||
T_Ok(m0_tag->parent == simple_struct_tag);
|
T_Ok(m0_tag->parent == simple_struct_tag);
|
||||||
T_Ok(m0_tag->attrib_count == 3);
|
T_Ok(m0_tag->attrib_count == 3);
|
||||||
T_Ok(m0_tag->info_off == 0x3b);
|
T_Ok(m0_tag->info_off == 0x4b);
|
||||||
T_Ok(m0_tag->abbrev_id == 5);
|
T_Ok(m0_tag->abbrev_id == 5);
|
||||||
|
|
||||||
DW_WriterAttrib *name = m0_tag->first_attrib;
|
DW_WriterAttrib *name = m0_tag->first_attrib;
|
||||||
@@ -373,7 +714,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
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->form.reader.kind == DW_Form_Ref1);
|
T_Ok(type->form.reader.kind == DW_Form_Ref1);
|
||||||
T_Ok(type->form.reader.ref == 0x20);
|
T_Ok(type->form.reader.ref == 0x30);
|
||||||
|
|
||||||
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);
|
||||||
@@ -387,7 +728,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(m1_tag->kind == DW_TagKind_Member);
|
T_Ok(m1_tag->kind == DW_TagKind_Member);
|
||||||
T_Ok(m1_tag->parent == simple_struct_tag);
|
T_Ok(m1_tag->parent == simple_struct_tag);
|
||||||
T_Ok(m1_tag->attrib_count == 4);
|
T_Ok(m1_tag->attrib_count == 4);
|
||||||
T_Ok(m1_tag->info_off == 0x41);
|
T_Ok(m1_tag->info_off == 0x51);
|
||||||
T_Ok(m1_tag->abbrev_id == 6);
|
T_Ok(m1_tag->abbrev_id == 6);
|
||||||
|
|
||||||
DW_WriterAttrib *name = m1_tag->first_attrib;
|
DW_WriterAttrib *name = m1_tag->first_attrib;
|
||||||
@@ -398,7 +739,7 @@ T_BeginTest(dwarf_writer)
|
|||||||
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->form.reader.kind == DW_Form_Ref1);
|
T_Ok(type->form.reader.kind == DW_Form_Ref1);
|
||||||
T_Ok(type->form.reader.ref == 0x20);
|
T_Ok(type->form.reader.ref == 0x30);
|
||||||
|
|
||||||
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);
|
||||||
@@ -433,13 +774,13 @@ T_BeginTest(dwarf_writer)
|
|||||||
T_Ok(low_pc->kind == DW_AttribKind_LowPc);
|
T_Ok(low_pc->kind == DW_AttribKind_LowPc);
|
||||||
T_Ok(low_pc->form.reader.kind == DW_Form_Addr);
|
T_Ok(low_pc->form.reader.kind == DW_Form_Addr);
|
||||||
T_Ok(low_pc->form.reader.addr.size == sizeof(U64));
|
T_Ok(low_pc->form.reader.addr.size == sizeof(U64));
|
||||||
T_Ok(*(U64 *)low_pc->form.reader.addr.str == 0x14012f2f0);
|
T_Ok(*(U64 *)low_pc->form.reader.addr.str == 0x140001000);
|
||||||
|
|
||||||
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->form.reader.kind == DW_Form_Addr);
|
T_Ok(high_pc->form.reader.kind == DW_Form_Addr);
|
||||||
T_Ok(high_pc->form.reader.addr.size == sizeof(U64));
|
T_Ok(high_pc->form.reader.addr.size == sizeof(U64));
|
||||||
T_Ok(*(U64 *)high_pc->form.reader.addr.str == 0x14012f405);
|
T_Ok(*(U64 *)high_pc->form.reader.addr.str == 0x140001004);
|
||||||
|
|
||||||
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);
|
||||||
@@ -651,4 +992,3 @@ T_EndTest;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef T_Group
|
#undef T_Group
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user