mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 06:48:41 +00:00
fallback on PCH signature when file path match fails
This commit is contained in:
committed by
Ryan Fleury
parent
6ca7f162aa
commit
c030488814
@@ -445,8 +445,8 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s
|
|||||||
# define this_function_name __func__
|
# define this_function_name __func__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TryRead(func__, cursor__, label__) do { U64 size__ = (func__); if (size__ == 0) { Assert(0 && "failed read"); goto label__; } cursor__ += size__; } while (0)
|
#define TryRead(func__, cursor__, label__) do { U64 size__ = (func__); if (size__ == 0) { goto label__; } cursor__ += size__; } while (0)
|
||||||
#define TryReadBreak(func__, cursor__) { U64 size__ = (func__); if (size__ == 0) { Assert(0 && "failed read"); break; } cursor__ += size__; }
|
#define TryReadBreak(func__, cursor__) { U64 size__ = (func__); if (size__ == 0) { break; } cursor__ += size__; }
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Base Types
|
//~ rjf: Base Types
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ internal U64
|
|||||||
cv_read_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out)
|
cv_read_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out)
|
||||||
{
|
{
|
||||||
// do we have enough bytes to read header?
|
// do we have enough bytes to read header?
|
||||||
Assert(raw_data.size >= sizeof(CV_LeafHeader));
|
if (raw_data.size < sizeof(CV_LeafHeader)) { return 0; }
|
||||||
|
|
||||||
U8 *leaf_ptr = raw_data.str + off;
|
U8 *leaf_ptr = raw_data.str + off;
|
||||||
|
|
||||||
@@ -92,17 +92,18 @@ cv_read_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out)
|
|||||||
CV_LeafHeader header = { .v = memory_read32(leaf_ptr) };
|
CV_LeafHeader header = { .v = memory_read32(leaf_ptr) };
|
||||||
|
|
||||||
// leaf size must have enough bytes for the kind enum
|
// leaf size must have enough bytes for the kind enum
|
||||||
Assert(header.size >= sizeof(CV_LeafKind));
|
if (header.size < sizeof(CV_LeafKind)) { return 0; }
|
||||||
|
|
||||||
// do we have enough bytes to read leaf data?
|
// do we have enough bytes to read leaf data?
|
||||||
Assert(sizeof(CV_LeafSize) + header.size <= raw_data.size);
|
if (sizeof(CV_LeafSize) + header.size > raw_data.size) { return 0; }
|
||||||
|
|
||||||
// fill out leaf
|
// fill out leaf
|
||||||
leaf_out->kind = header.kind;
|
leaf_out->kind = header.kind;
|
||||||
leaf_out->data = str8(leaf_ptr + sizeof(CV_LeafHeader), header.size - sizeof(CV_LeafKind));
|
leaf_out->data = str8(leaf_ptr + sizeof(CV_LeafHeader), header.size - sizeof(CV_LeafKind));
|
||||||
|
|
||||||
U64 leaf_size = AlignPow2(sizeof(CV_LeafHeader) + leaf_out->data.size, align);
|
U64 leaf_size = AlignPow2(sizeof(CV_LeafHeader) + leaf_out->data.size, align);
|
||||||
Assert(leaf_size <= raw_data.size);
|
if (leaf_size > raw_data.size) { return 0; }
|
||||||
|
|
||||||
return leaf_size;
|
return leaf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1161,10 +1162,9 @@ count_stop:
|
|||||||
|
|
||||||
ProfBegin("store leaf offsets");
|
ProfBegin("store leaf offsets");
|
||||||
debug_t.offsets = push_array_no_zero(arena, U32, debug_t.count);
|
debug_t.offsets = push_array_no_zero(arena, U32, debug_t.count);
|
||||||
for (U64 cursor = 0, idx = 0; cursor < data.size;) {
|
for (U64 cursor = 0, idx = 0; cursor < data.size && idx < debug_t.count; idx += 1) {
|
||||||
debug_t.offsets[idx++] = cursor;
|
debug_t.offsets[idx] = cursor;
|
||||||
CV_Leaf leaf;
|
TryRead(cv_read_leaf(data, cursor, align, &(CV_Leaf){0}), cursor, store_stop);
|
||||||
TryRead(cv_read_leaf(data, cursor, align, &leaf), cursor, store_stop);
|
|
||||||
}
|
}
|
||||||
store_stop:
|
store_stop:
|
||||||
|
|
||||||
|
|||||||
+52
-22
@@ -632,21 +632,6 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pre-build PCH obj hash map (obj_path, obj_idx)
|
|
||||||
String8 work_dir = get_current_path(scratch.arena);
|
|
||||||
HashMap debug_p_hm = {0};
|
|
||||||
for EachIndex(obj_idx, obj_count) {
|
|
||||||
LNK_Obj *obj = obj_arr[obj_idx];
|
|
||||||
if (obj->debug_p_sect_idx < obj->header.section_count_no_null) {
|
|
||||||
String8 obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, obj_arr[obj_idx]->path, work_dir);
|
|
||||||
if (hash_map_search_path_u64(&debug_p_hm, obj_path)) {
|
|
||||||
lnk_error_obj(LNK_Warning_DuplicateObjPath, obj_arr[obj_idx], "duplicate obj path %S", obj_path);
|
|
||||||
} else {
|
|
||||||
hash_map_push_path_u64(scratch.arena, &debug_p_hm, obj_path, obj_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfBegin("Apply RRT to Objs");
|
ProfBegin("Apply RRT to Objs");
|
||||||
|
|
||||||
// hash map (obj path, obj idx)
|
// hash map (obj path, obj idx)
|
||||||
@@ -698,6 +683,7 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
|
|||||||
input.debug_s_list_arr = lnk_collect_obj_sections(tp, tp_arena, obj_count, obj_arr, str8_lit(".debug$S"), 0);
|
input.debug_s_list_arr = lnk_collect_obj_sections(tp, tp_arena, obj_count, obj_arr, str8_lit(".debug$S"), 0);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
|
|
||||||
|
// profiler info
|
||||||
if (lnk_get_log_status(LNK_Log_Debug) || PROFILE_TELEMETRY) {
|
if (lnk_get_log_status(LNK_Log_Debug) || PROFILE_TELEMETRY) {
|
||||||
U64 total_debug_s_size = 0, total_debug_t_size = 0, total_debug_p_size = 0, total_debug_h_size = 0;
|
U64 total_debug_s_size = 0, total_debug_t_size = 0, total_debug_p_size = 0, total_debug_h_size = 0;
|
||||||
for EachIndex(obj_idx, obj_count) {
|
for EachIndex(obj_idx, obj_count) {
|
||||||
@@ -745,41 +731,48 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
|
|||||||
ProfBegin("Parse CodeView");
|
ProfBegin("Parse CodeView");
|
||||||
CV_DebugT *debug_p_arr;
|
CV_DebugT *debug_p_arr;
|
||||||
{
|
{
|
||||||
|
// parse .debug$S
|
||||||
input.debug_s_arr = push_array(tp_arena->v[0], CV_DebugS, input.obj_count);
|
input.debug_s_arr = push_array(tp_arena->v[0], CV_DebugS, input.obj_count);
|
||||||
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_s_task, &input, "Parse .debug$S");
|
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_s_task, &input, "Parse .debug$S");
|
||||||
|
|
||||||
|
// collect .debug$P and .debug$T
|
||||||
String8Array *raw_debug_p_arr = push_array(scratch.arena, String8Array, obj_count);
|
String8Array *raw_debug_p_arr = push_array(scratch.arena, String8Array, obj_count);
|
||||||
String8Array *raw_debug_t_arr = push_array(scratch.arena, String8Array, obj_count);
|
String8Array *raw_debug_t_arr = push_array(scratch.arena, String8Array, obj_count);
|
||||||
for EachIndex(obj_idx, obj_count) {
|
for EachIndex(obj_idx, obj_count) {
|
||||||
LNK_Obj *obj = obj_arr[obj_idx];
|
LNK_Obj *obj = obj_arr[obj_idx];
|
||||||
|
|
||||||
if (obj->debug_t_sect_idx < obj->header.section_count_no_null) {
|
if (obj->debug_t_sect_idx < obj->header.section_count_no_null) {
|
||||||
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx);
|
LNK_ObjSection debug_t_sect = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx);
|
||||||
raw_debug_t_arr[obj_idx].count = 1;
|
raw_debug_t_arr[obj_idx].count = 1;
|
||||||
raw_debug_t_arr[obj_idx].v = push_array(scratch.arena, String8, 1);
|
raw_debug_t_arr[obj_idx].v = push_array(scratch.arena, String8, 1);
|
||||||
raw_debug_t_arr[obj_idx].v[0] = str8_substr(obj->data, section.frange);
|
raw_debug_t_arr[obj_idx].v[0] = str8_substr(obj->data, debug_t_sect.frange);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->debug_p_sect_idx < obj->header.section_count_no_null) {
|
if (obj->debug_p_sect_idx < obj->header.section_count_no_null) {
|
||||||
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, obj->debug_p_sect_idx);
|
LNK_ObjSection debug_p_sect = lnk_obj_section_from_sect_idx(obj, obj->debug_p_sect_idx);
|
||||||
raw_debug_p_arr[obj_idx].count = 1;
|
raw_debug_p_arr[obj_idx].count = 1;
|
||||||
raw_debug_p_arr[obj_idx].v = push_array(scratch.arena, String8, 1);
|
raw_debug_p_arr[obj_idx].v = push_array(scratch.arena, String8, 1);
|
||||||
raw_debug_p_arr[obj_idx].v[0] = str8_substr(obj->data, section.frange);
|
raw_debug_p_arr[obj_idx].v[0] = str8_substr(obj->data, debug_p_sect.frange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LNK_ParseCvTypes parse_types = { .input = &input };
|
LNK_ParseCvTypes parse_types = { .input = &input };
|
||||||
|
|
||||||
|
// parse .debug$P
|
||||||
debug_p_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count);
|
debug_p_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count);
|
||||||
parse_types.raw_types = raw_debug_p_arr;
|
parse_types.raw_types = raw_debug_p_arr;
|
||||||
parse_types.out_types = debug_p_arr;
|
parse_types.out_types = debug_p_arr;
|
||||||
tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$P");
|
tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$P");
|
||||||
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$P");
|
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$P");
|
||||||
|
|
||||||
|
// parse .debug$T
|
||||||
input.debug_t_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count);
|
input.debug_t_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count);
|
||||||
parse_types.raw_types = raw_debug_t_arr;
|
parse_types.raw_types = raw_debug_t_arr;
|
||||||
parse_types.out_types = input.debug_t_arr;
|
parse_types.out_types = input.debug_t_arr;
|
||||||
tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$T");
|
tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$T");
|
||||||
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$T");
|
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$T");
|
||||||
|
|
||||||
|
// parse .debug$H
|
||||||
input.debug_h_arr = push_array(tp_arena->v[0], CV_DebugH, input.obj_count);
|
input.debug_h_arr = push_array(tp_arena->v[0], CV_DebugH, input.obj_count);
|
||||||
if (config->ghash) {
|
if (config->ghash) {
|
||||||
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_h_task, &input, "Parse .debug$H");
|
tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_h_task, &input, "Parse .debug$H");
|
||||||
@@ -961,6 +954,40 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
|
|||||||
|
|
||||||
ProfBegin("Set up PCH");
|
ProfBegin("Set up PCH");
|
||||||
{
|
{
|
||||||
|
// pre-build PCH obj hash map (obj_path, obj_idx)
|
||||||
|
HashMap debug_p_hm_path = {0};
|
||||||
|
HashMap debug_p_hm_sig = {0};
|
||||||
|
for EachIndex(i, input.debug_p_indices.count) {
|
||||||
|
U64 obj_idx = input.debug_p_indices.v[i];
|
||||||
|
LNK_Obj *obj = obj_arr[obj_idx];
|
||||||
|
|
||||||
|
// register PCH signature
|
||||||
|
CV_DebugT debug_p = input.debug_t_arr[obj_idx];
|
||||||
|
if (debug_p.count > 0) {
|
||||||
|
CV_Leaf lf = cv_debug_t_get_leaf(&debug_p, debug_p.count - 1);
|
||||||
|
if (lf.kind == CV_LeafKind_ENDPRECOMP && lf.data.size <= sizeof(CV_LeafEndPreComp)) {
|
||||||
|
CV_LeafEndPreComp *ender = str8_deserial_get_raw_ptr(lf.data, 0, sizeof(*ender));
|
||||||
|
if (ender->sig) {
|
||||||
|
U64 *extant_obj_idx = hash_map_search_u64_u64(&debug_p_hm_sig, ender->sig);
|
||||||
|
if (extant_obj_idx == 0) {
|
||||||
|
hash_map_push_u64_u64(scratch.arena, &debug_p_hm_sig, ender->sig, obj_idx);
|
||||||
|
} else {
|
||||||
|
LNK_Obj *extant_obj = obj_arr[*extant_obj_idx];
|
||||||
|
lnk_log(LNK_Log_Debug, "%S: PCH signature is already defined in %S", lnk_loc_from_obj(scratch.arena, obj), lnk_loc_from_obj(scratch.arena, extant_obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// register PCH path
|
||||||
|
String8 obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, obj_arr[obj_idx]->path, config->work_dir);
|
||||||
|
if (hash_map_search_path_u64(&debug_p_hm_path, obj_path)) {
|
||||||
|
lnk_error_obj(LNK_Warning_DuplicateObjPath, obj, "duplicate obj path %S", obj_path);
|
||||||
|
} else {
|
||||||
|
hash_map_push_path_u64(scratch.arena, &debug_p_hm_path, obj_path, obj_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for EachIndex(i, input.int_obj_indices.count) {
|
for EachIndex(i, input.int_obj_indices.count) {
|
||||||
U64 obj_idx = input.int_obj_indices.v[i];
|
U64 obj_idx = input.int_obj_indices.v[i];
|
||||||
CV_DebugT *debug_t = &input.debug_t_arr[obj_idx];
|
CV_DebugT *debug_t = &input.debug_t_arr[obj_idx];
|
||||||
@@ -970,15 +997,18 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
|
|||||||
|
|
||||||
// find PCH obj
|
// find PCH obj
|
||||||
CV_PrecompInfo precomp = cv_precomp_info_from_leaf(cv_debug_t_get_leaf(debug_t, 0));
|
CV_PrecompInfo precomp = cv_precomp_info_from_leaf(cv_debug_t_get_leaf(debug_t, 0));
|
||||||
String8 obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, precomp.obj_name, work_dir);
|
String8 obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, precomp.obj_name, config->work_dir);
|
||||||
U64 *debug_p_obj_idx_ptr = hash_map_search_path_u64(&debug_p_hm, obj_path);
|
U64 *debug_p_obj_idx_ptr = hash_map_search_path_u64(&debug_p_hm_path, obj_path);
|
||||||
|
if (debug_p_obj_idx_ptr == 0) {
|
||||||
|
debug_p_obj_idx_ptr = hash_map_search_u64_u64(&debug_p_hm_sig, precomp.sig);
|
||||||
|
}
|
||||||
|
|
||||||
// try alternative directory for the PCH
|
// try alternative directory for the PCH
|
||||||
if (debug_p_obj_idx_ptr == 0) {
|
if (debug_p_obj_idx_ptr == 0) {
|
||||||
String8 obj_name = str8_skip_last_slash(obj_path);
|
String8 obj_name = str8_skip_last_slash(obj_path);
|
||||||
for EachNode(alt_dir_n, String8Node, config->alt_pch_dirs.first) {
|
for EachNode(alt_dir_n, String8Node, config->alt_pch_dirs.first) {
|
||||||
String8 alt_obj_path = str8f(scratch.arena, "%S/%S", alt_dir_n->string, obj_name);
|
String8 alt_obj_path = str8f(scratch.arena, "%S/%S", alt_dir_n->string, obj_name);
|
||||||
debug_p_obj_idx_ptr = hash_map_search_path_u64(&debug_p_hm, alt_obj_path);
|
debug_p_obj_idx_ptr = hash_map_search_path_u64(&debug_p_hm_path, alt_obj_path);
|
||||||
if (debug_p_obj_idx_ptr) { break; }
|
if (debug_p_obj_idx_ptr) { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5073,6 +5073,193 @@ TEST(debug_p_sig_mismatch)
|
|||||||
T_Ok(found_error);
|
T_Ok(found_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(pch_sig_fallback)
|
||||||
|
{
|
||||||
|
String8 a_obj_file_path = t_make_file_path(arena, str8_lit("a.obj"));
|
||||||
|
String8 b_obj_file_path = t_make_file_path(arena, str8_lit("b.obj"));
|
||||||
|
U32 a_sig = 0xCAFEBABE;
|
||||||
|
U32 b_sig = 0xCAFEBABE;
|
||||||
|
|
||||||
|
String8 a_debug_s;
|
||||||
|
{
|
||||||
|
String8List srl;
|
||||||
|
str8_serial_begin(arena, &srl);
|
||||||
|
|
||||||
|
CV_Signature sig = CV_Signature_C13;
|
||||||
|
str8_serial_push_struct(arena, &srl, &sig);
|
||||||
|
|
||||||
|
CV_C13SubSectionHeader *ss_header = str8_serial_push_size(arena, &srl, sizeof(*ss_header));
|
||||||
|
U64 ss_start_off = srl.total_size;
|
||||||
|
|
||||||
|
CV_SymObjName obj_name = {0};
|
||||||
|
obj_name.sig = a_sig;
|
||||||
|
String8 obj_name_string = a_obj_file_path;
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_SymKind) + sizeof(obj_name) + obj_name_string.size + 1);
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_SymKind_OBJNAME);
|
||||||
|
str8_serial_push_struct(arena, &srl, &obj_name);
|
||||||
|
str8_serial_push_cstr(arena, &srl, obj_name_string);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_SymbolAlign);
|
||||||
|
|
||||||
|
String8 comp3_data = cv_make_comp3(arena,
|
||||||
|
0,
|
||||||
|
CV_Language_C,
|
||||||
|
CV_Arch_X64,
|
||||||
|
/* ver_fe_major */ 0,
|
||||||
|
/* ver_fe_minor */ 0,
|
||||||
|
/* ver_fe_build */ 0,
|
||||||
|
/* ver_feqfe */ 0,
|
||||||
|
/* ver_major */ 14,
|
||||||
|
/* ver_minor */ 36,
|
||||||
|
/* ver_build */ 32537,
|
||||||
|
/* ver_qfe */ 0,
|
||||||
|
str8_lit(BUILD_TITLE));
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_SymKind) + comp3_data.size);
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_SymKind_COMPILE3);
|
||||||
|
str8_serial_push_string(arena, &srl, comp3_data);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_SymbolAlign);
|
||||||
|
|
||||||
|
ss_header->kind = CV_C13SubSectionKind_Symbols;
|
||||||
|
ss_header->size = srl.total_size - ss_start_off;
|
||||||
|
str8_serial_push_align(arena, &srl, CV_C13SubSectionAlign);
|
||||||
|
|
||||||
|
a_debug_s = str8_serial_end(arena, &srl);
|
||||||
|
}
|
||||||
|
String8 a_debug_p;
|
||||||
|
{
|
||||||
|
String8List srl;
|
||||||
|
str8_serial_begin(arena, &srl);
|
||||||
|
|
||||||
|
// signature
|
||||||
|
CV_Signature sig = CV_Signature_C13;
|
||||||
|
str8_serial_push_struct(arena, &srl, &sig);
|
||||||
|
|
||||||
|
// duplicate in a.obj
|
||||||
|
CV_LeafPointer ptr = { .itype = CV_BasicType_VOID };
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_LeafKind) + sizeof(ptr));
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_LeafKind_POINTER);
|
||||||
|
str8_serial_push_struct(arena, &srl, &ptr);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_LeafAlign);
|
||||||
|
|
||||||
|
// unique procedure type
|
||||||
|
CV_LeafProcedure proc = { .ret_itype = 0x1000, .call_kind = CV_CallKind_NearPascal };
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_LeafKind) + sizeof(proc));
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_LeafKind_PROCEDURE);
|
||||||
|
str8_serial_push_struct(arena, &srl, &proc);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_LeafAlign);
|
||||||
|
|
||||||
|
// PCH ender
|
||||||
|
CV_LeafEndPreComp endprecomp = { .sig = a_sig };
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_LeafKind) + sizeof(endprecomp));
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_LeafKind_ENDPRECOMP);
|
||||||
|
str8_serial_push_struct(arena, &srl, &endprecomp);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_LeafAlign);
|
||||||
|
|
||||||
|
a_debug_p = str8_serial_end(arena, &srl);
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 b_debug_s;
|
||||||
|
{
|
||||||
|
String8List srl;
|
||||||
|
str8_serial_begin(arena, &srl);
|
||||||
|
|
||||||
|
CV_Signature sig = CV_Signature_C13;
|
||||||
|
str8_serial_push_struct(arena, &srl, &sig);
|
||||||
|
|
||||||
|
CV_C13SubSectionHeader *ss_header = str8_serial_push_size(arena, &srl, sizeof(*ss_header));
|
||||||
|
U64 ss_start_off = srl.total_size;
|
||||||
|
|
||||||
|
CV_SymObjName obj_name = {0};
|
||||||
|
obj_name.sig = b_sig;
|
||||||
|
String8 obj_name_string = a_obj_file_path;
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_SymKind) + sizeof(obj_name) + obj_name_string.size + 1);
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_SymKind_OBJNAME);
|
||||||
|
str8_serial_push_struct(arena, &srl, &obj_name);
|
||||||
|
str8_serial_push_cstr(arena, &srl, obj_name_string);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_SymbolAlign);
|
||||||
|
|
||||||
|
String8 comp3_data = cv_make_comp3(arena,
|
||||||
|
0,
|
||||||
|
CV_Language_C,
|
||||||
|
CV_Arch_X64,
|
||||||
|
/* ver_fe_major */ 0,
|
||||||
|
/* ver_fe_minor */ 0,
|
||||||
|
/* ver_fe_build */ 0,
|
||||||
|
/* ver_feqfe */ 0,
|
||||||
|
/* ver_major */ 14,
|
||||||
|
/* ver_minor */ 36,
|
||||||
|
/* ver_build */ 32537,
|
||||||
|
/* ver_qfe */ 0,
|
||||||
|
str8_lit(BUILD_TITLE));
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_SymKind) + comp3_data.size);
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_SymKind_COMPILE3);
|
||||||
|
str8_serial_push_string(arena, &srl, comp3_data);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_SymbolAlign);
|
||||||
|
|
||||||
|
ss_header->kind = CV_C13SubSectionKind_Symbols;
|
||||||
|
ss_header->size = srl.total_size - ss_start_off;
|
||||||
|
str8_serial_push_align(arena, &srl, CV_C13SubSectionAlign);
|
||||||
|
|
||||||
|
b_debug_s = str8_serial_end(arena, &srl);
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 b_debug_t;
|
||||||
|
{
|
||||||
|
String8List srl;
|
||||||
|
str8_serial_begin(arena, &srl);
|
||||||
|
|
||||||
|
CV_Signature sig = CV_Signature_C13;
|
||||||
|
str8_serial_push_struct(arena, &srl, &sig);
|
||||||
|
|
||||||
|
String8 corrupt_pch_path = str8_lit("corrupt-pch-file-path.obj");
|
||||||
|
|
||||||
|
CV_LeafPreComp precomp = { .start_index = CV_MinComplexTypeIndex, .count = 2, sig = b_sig };
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_LeafKind) + sizeof(precomp) + corrupt_pch_path.size + 1);
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_LeafKind_PRECOMP);
|
||||||
|
str8_serial_push_struct(arena, &srl, &precomp);
|
||||||
|
str8_serial_push_cstr(arena, &srl, corrupt_pch_path);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_LeafAlign);
|
||||||
|
|
||||||
|
CV_LeafPointer ptr = { .itype = CV_BasicType_VOID };
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_LeafKind) + sizeof(CV_LeafPointer));
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_LeafKind_POINTER);
|
||||||
|
str8_serial_push_struct(arena, &srl, &ptr);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_LeafAlign);
|
||||||
|
|
||||||
|
CV_LeafProcedure proc = { .ret_itype = 0x1000, .call_kind = CV_CallKind_NearC };
|
||||||
|
str8_serial_push_u16(arena, &srl, sizeof(CV_LeafKind) + sizeof(CV_LeafProcedure));
|
||||||
|
str8_serial_push_u16(arena, &srl, CV_LeafKind_PROCEDURE);
|
||||||
|
str8_serial_push_struct(arena, &srl, &proc);
|
||||||
|
str8_serial_push_align(arena, &srl, CV_LeafAlign);
|
||||||
|
|
||||||
|
b_debug_t = str8_serial_end(arena, &srl);
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 a_obj = t_coff_from_def_obj(arena, (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{ "debug_p", ".debug$P", a_debug_p, .flags = "r:data@1", .raw_flags = COFF_SectionFlag_MemDiscardable },
|
||||||
|
{ "debug_s", ".debug$S", a_debug_s, .flags = "r:data@1", .raw_flags = COFF_SectionFlag_MemDiscardable },
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String8 b_obj = t_coff_from_def_obj(arena, (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{ "debug_t", ".debug$T", b_debug_t, .flags = "r:data@1", .raw_flags = COFF_SectionFlag_MemDiscardable },
|
||||||
|
{ "debug_s", ".debug$S", b_debug_s, .flags = "r:data@1", .raw_flags = COFF_SectionFlag_MemDiscardable },
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
T_Ok(write_data_to_file_path(a_obj_file_path, a_obj));
|
||||||
|
T_Ok(write_data_to_file_path(b_obj_file_path, b_obj));
|
||||||
|
T_Ok(t_write_entry_obj());
|
||||||
|
|
||||||
|
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj");
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(debug_p_and_debug_t_in_obj)
|
TEST(debug_p_and_debug_t_in_obj)
|
||||||
{
|
{
|
||||||
U32 pch_sig = 0xCAFEBABE;
|
U32 pch_sig = 0xCAFEBABE;
|
||||||
|
|||||||
Reference in New Issue
Block a user