Skip to content

Commit d2db454

Browse files
check type server signature against signature in obj
1 parent 7adf08c commit d2db454

File tree

6 files changed

+198
-84
lines changed

6 files changed

+198
-84
lines changed

src/linker/codeview_ext/codeview.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,24 @@ typedef struct CV_UDTInfo
207207

208208
typedef struct CV_TypeServerInfo
209209
{
210-
String8 name;
211-
COFF_Guid sig;
212-
U32 age;
210+
String8 name;
211+
OS_Guid sig;
212+
U32 age;
213213
} CV_TypeServerInfo;
214214

215+
typedef struct CV_TypeServerInfoNode
216+
{
217+
struct CV_TypeServerInfoNode *next;
218+
CV_TypeServerInfo data;
219+
} CV_TypeServerInfoNode;
220+
221+
typedef struct CV_TypeServerInfoList
222+
{
223+
CV_TypeServerInfoNode *first;
224+
CV_TypeServerInfoNode *last;
225+
U64 count;
226+
} CV_TypeServerInfoList;
227+
215228
typedef struct CV_PrecompInfo
216229
{
217230
CV_TypeIndex start_index;

src/linker/lnk_debug_info.c

Lines changed: 113 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -275,28 +275,51 @@ lnk_do_debug_info_discard(CV_DebugS *debug_s_arr, CV_SymbolListArray *parsed_sym
275275
}
276276

277277
internal
278-
THREAD_POOL_TASK_FUNC(lnk_get_external_leaves_task)
278+
THREAD_POOL_TASK_FUNC(lnk_msf_parsed_from_data_task)
279279
{
280280
ProfBeginFunction();
281+
LNK_MsfParsedFromDataTask *task = raw_task;
282+
// TODO: pick Info, TPI and IPI to flattten to make sure we don't waste compute on throw-away streams
283+
task->msf_parse_arr[task_id] = msf_parsed_from_data(arena, task->data_arr.v[task_id]);
284+
ProfEnd();
285+
}
281286

282-
LNK_GetExternalLeavesTask *task = raw_task;
287+
internal MSF_Parsed **
288+
lnk_msf_parsed_from_data_parallel(TP_Arena *arena, TP_Context *tp, String8Array data_arr)
289+
{
290+
ProfBeginFunction();
291+
LNK_MsfParsedFromDataTask task = {0};
292+
task.data_arr = data_arr;
293+
task.msf_parse_arr = push_array_no_zero(arena->v[0], MSF_Parsed *, data_arr.count);
294+
tp_for_parallel(tp, arena, data_arr.count, lnk_msf_parsed_from_data_task, &task);
295+
ProfEnd();
296+
return task.msf_parse_arr;
297+
}
283298

284-
U64 ts_idx = task_id;
299+
internal
300+
THREAD_POOL_TASK_FUNC(lnk_get_external_leaves_task)
301+
{
302+
ProfBeginFunction();
303+
304+
U64 ts_idx = task_id;
305+
LNK_GetExternalLeavesTask *task = raw_task;
306+
MSF_Parsed *msf_parse = task->msf_parse_arr[ts_idx];
285307

286308
task->external_ti_ranges[ts_idx] = push_array_no_zero(arena, Rng1U64, CV_TypeIndexSource_COUNT);
287309
task->external_leaves[ts_idx] = push_array_no_zero(arena, CV_DebugT, CV_TypeIndexSource_COUNT);
288310
task->is_corrupted[ts_idx] = 1;
289311

290-
// TODO: pick TPI and IPI to flattten to make sure we don't waste compute on throw-away streams
291-
MSF_Parsed *msf_parse = msf_parsed_from_data(arena, task->msf_data_arr[ts_idx]);
292-
293312
if (msf_parse) {
313+
PDB_OpenTypeServerError tpi_error = PDB_OpenTypeServerError_UNKNOWN;
314+
PDB_OpenTypeServerError ipi_error = PDB_OpenTypeServerError_UNKNOWN;
315+
294316
PDB_TypeServerParse tpi_parse, ipi_parse;
295-
PDB_OpenTypeServerError tpi_error = pdb_type_server_parse_from_data(msf_parse->streams[PDB_FixedStream_Tpi], &tpi_parse);
296-
PDB_OpenTypeServerError ipi_error = pdb_type_server_parse_from_data(msf_parse->streams[PDB_FixedStream_Ipi], &ipi_parse);
317+
if (PDB_FixedStream_Tpi < msf_parse->stream_count && PDB_FixedStream_Ipi < msf_parse->stream_count) {
318+
tpi_error = pdb_type_server_parse_from_data(msf_parse->streams[PDB_FixedStream_Tpi], &tpi_parse);
319+
ipi_error = pdb_type_server_parse_from_data(msf_parse->streams[PDB_FixedStream_Ipi], &ipi_parse);
320+
}
297321

298-
if (tpi_error == PDB_OpenTypeServerError_OK &&
299-
ipi_error == PDB_OpenTypeServerError_OK) {
322+
if (tpi_error == PDB_OpenTypeServerError_OK && ipi_error == PDB_OpenTypeServerError_OK) {
300323
task->is_corrupted[ts_idx] = 0;
301324

302325
task->external_ti_ranges[ts_idx][CV_TypeIndexSource_NULL] = rng_1u64(0,0);
@@ -308,15 +331,12 @@ THREAD_POOL_TASK_FUNC(lnk_get_external_leaves_task)
308331
task->external_leaves[ts_idx][CV_TypeIndexSource_IPI] = cv_debug_t_from_data(arena, ipi_parse.leaf_data, PDB_LEAF_ALIGN);
309332
} else {
310333
if (tpi_error != PDB_OpenTypeServerError_OK) {
311-
lnk_error(LNK_Error_UnableToOpenTypeServer, "failed to open TPI in %S, reson %S", task->path_arr[ts_idx], pdb_string_from_open_type_server_error(tpi_error));
334+
lnk_error(LNK_Error_UnableToOpenTypeServer, "failed to open TPI in %S, reson %S", task->ts_info_arr[ts_idx].name, pdb_string_from_open_type_server_error(tpi_error));
312335
}
313336
if (ipi_error != PDB_OpenTypeServerError_OK) {
314-
lnk_error(LNK_Error_UnableToOpenTypeServer, "failed to open IPI in %S, reason %S", task->path_arr[ts_idx], pdb_string_from_open_type_server_error(ipi_error));
337+
lnk_error(LNK_Error_UnableToOpenTypeServer, "failed to open IPI in %S, reason %S", task->ts_info_arr[ts_idx].name, pdb_string_from_open_type_server_error(ipi_error));
315338
}
316339
}
317-
} else {
318-
MemoryZeroTyped(task->external_ti_ranges[ts_idx], CV_TypeIndexSource_COUNT);
319-
MemoryZeroTyped(task->external_leaves[ts_idx], CV_TypeIndexSource_COUNT);
320340
}
321341

322342
ProfEnd();
@@ -537,18 +557,20 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
537557
CV_DebugT *merged_debug_t_p_arr = lnk_merge_debug_t_and_debug_p(tp_arena->v[0], internal_count, internal_debug_t_arr, internal_debug_p_arr);
538558

539559
ProfBegin("Analyze & Read External Type Server Files");
540-
String8Array type_server_path_arr;
560+
String8Array ts_path_arr;
541561
Rng1U64 **external_ti_ranges;
542562
CV_DebugT **external_leaves;
543563
U64 *obj_to_ts_idx_arr = push_array_no_zero(tp_arena->v[0], U64, external_count);
544564
U64List *ts_to_obj_arr = push_array(tp_arena->v[0], U64List, external_count);
545565
{
546-
HashTable *type_server_path_ht = hash_table_init(scratch.arena, 256);
547-
HashTable *ignored_path_ht = hash_table_init(scratch.arena, 256);
548-
String8List type_server_path_list; MemoryZeroStruct(&type_server_path_list);
566+
HashTable *type_server_path_ht = hash_table_init(scratch.arena, 256);
567+
HashTable *ignored_path_ht = hash_table_init(scratch.arena, 256);
568+
CV_TypeServerInfoList ts_info_list = {0};
549569

550570
// push null
551-
str8_list_pushf(scratch.arena, &type_server_path_list, "");
571+
CV_TypeServerInfoNode *null_ts_info = push_array(scratch.arena, CV_TypeServerInfoNode, 1);
572+
SLLQueuePush(ts_info_list.first, ts_info_list.last, null_ts_info);
573+
++ts_info_list.count;
552574

553575
for (U64 obj_idx = 0; obj_idx < external_count; ++obj_idx) {
554576
// first leaf always type server
@@ -620,9 +642,20 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
620642
present->obj->path);
621643
}
622644
} else {
623-
U64 ts_idx = type_server_path_list.node_count;
645+
U64 ts_idx = ts_info_list.count;
646+
647+
// when we search matches on disk we store path on scratch,
648+
// make path copy in case we need it for error reporting
624649
path = push_str8_copy(tp_arena->v[0], path);
625-
str8_list_push(scratch.arena, &type_server_path_list, path);
650+
651+
// fill out type server info we read from obj
652+
CV_TypeServerInfoNode *ts_info_node = push_array(scratch.arena, CV_TypeServerInfoNode, 1);
653+
ts_info_node->data = ts;
654+
ts_info_node->data.name = path;
655+
656+
// push to type server info list
657+
SLLQueuePush(ts_info_list.first, ts_info_list.last, ts_info_node);
658+
ts_info_list.count += 1;
626659

627660
// wire obj to type server
628661
obj_to_ts_idx_arr[obj_idx] = ts_idx;
@@ -642,25 +675,69 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
642675
}
643676
}
644677

645-
// read type servers from disk in parallel
646-
type_server_path_arr = str8_array_from_list(tp_arena->v[0], &type_server_path_list);
678+
// type server info list -> array
679+
ts_path_arr.count = ts_info_list.count;
680+
ts_path_arr.v = push_array(tp_arena->v[0], String8, ts_info_list.count);
681+
CV_TypeServerInfo *ts_info_arr = push_array(scratch.arena, CV_TypeServerInfo, ts_info_list.count);
682+
{
683+
U64 idx = 0;
684+
for (CV_TypeServerInfoNode *n = ts_info_list.first; n != 0; n = n->next, ++idx) {
685+
ts_path_arr.v[idx] = n->data.name;
686+
ts_info_arr[idx] = n->data;
687+
}
688+
}
647689

690+
// read type servers from disk in parallel
648691
{
649692
ProfBegin("Read External Type Servers");
650-
String8Array msf_data_arr = os_data_from_file_path_parallel(tp, scratch.arena, type_server_path_arr);
693+
String8Array msf_data_arr = os_data_from_file_path_parallel(tp, scratch.arena, ts_path_arr);
694+
ProfEnd();
695+
696+
MSF_Parsed **msf_parse_arr = lnk_msf_parsed_from_data_parallel(tp_arena, tp, msf_data_arr);
697+
698+
ProfBegin("Error check type servers");
699+
for (U64 ts_idx = 0; ts_idx < msf_data_arr.count; ++ts_idx) {
700+
MSF_Parsed *msf_parse = msf_parse_arr[ts_idx];
701+
702+
B32 do_debug_info_discard = 0;
703+
704+
if (!msf_parse) {
705+
do_debug_info_discard = 1;
706+
} else {
707+
PDB_InfoParse info_parse = {0};
708+
pdb_info_parse_from_data(msf_parse->streams[PDB_FixedStream_Info], &info_parse);
709+
if (!MemoryMatchStruct(&info_parse.guid, &ts_info_arr[ts_idx].sig)) {
710+
Temp scratch = scratch_begin(0,0);
711+
String8 expected_sig_str = os_string_from_guid(scratch.arena, ts_info_arr[ts_idx].sig);
712+
String8 on_disk_sig_str = os_string_from_guid(scratch.arena, info_parse.guid);
713+
lnk_error(LNK_Warning_MismatchedTypeServerSignature, "%S: signature mismatch in type server read from disk, expected %S, got %S",
714+
ts_info_arr[ts_idx].name, expected_sig_str, on_disk_sig_str);
715+
scratch_end(scratch);
716+
717+
do_debug_info_discard = 1;
718+
}
719+
}
720+
721+
if (do_debug_info_discard) {
722+
U64List obj_idx_list = ts_to_obj_arr[ts_idx];
723+
for (U64Node *obj_idx_n = obj_idx_list.first; obj_idx_n != 0; obj_idx_n = obj_idx_n->next) {
724+
lnk_do_debug_info_discard(external_debug_s_arr, external_parsed_symbols, obj_idx_n->data);
725+
}
726+
}
727+
}
651728
ProfEnd();
652729

653-
ProfBeginDynamic("Open External Type Servers [Count %llu]", type_server_path_arr.count);
654-
LNK_GetExternalLeavesTask task;
655-
task.path_arr = type_server_path_arr.v;
656-
task.msf_data_arr = msf_data_arr.v;
657-
task.external_ti_ranges = push_array_no_zero(tp_arena->v[0], Rng1U64 *, msf_data_arr.count);
658-
task.external_leaves = push_array_no_zero(tp_arena->v[0], CV_DebugT *, msf_data_arr.count);
659-
task.is_corrupted = push_array_no_zero(scratch.arena, B8, msf_data_arr.count);
730+
ProfBeginDynamic("Open External Type Servers [Count %llu]", ts_path_arr.count);
731+
LNK_GetExternalLeavesTask task = {0};
732+
task.ts_info_arr = ts_info_arr;
733+
task.msf_parse_arr = msf_parse_arr;
734+
task.external_ti_ranges = push_array_no_zero(tp_arena->v[0], Rng1U64 *, msf_data_arr.count);
735+
task.external_leaves = push_array_no_zero(tp_arena->v[0], CV_DebugT *, msf_data_arr.count);
736+
task.is_corrupted = push_array_no_zero(scratch.arena, B8, msf_data_arr.count);
660737
tp_for_parallel(tp, tp_arena, msf_data_arr.count, lnk_get_external_leaves_task, &task);
661738
ProfEnd();
662739

663-
String8List unopen_type_server_list; MemoryZeroStruct(&unopen_type_server_list);
740+
String8List unopen_type_server_list = {0};
664741

665742
// discard debug info that depends on the missing type server
666743
for (U64 ts_idx = 1; ts_idx < msf_data_arr.count; ++ts_idx) {
@@ -676,7 +753,7 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
676753
for (U64 ts_idx = 1; ts_idx < msf_data_arr.count; ++ts_idx) {
677754
if (task.is_corrupted[ts_idx]) {
678755
U64List obj_idx_list = ts_to_obj_arr[ts_idx];
679-
str8_list_pushf(scratch.arena, &unopen_type_server_list, "\t%S\n", type_server_path_arr.v[ts_idx]);
756+
str8_list_pushf(scratch.arena, &unopen_type_server_list, "\t%S\n", ts_path_arr.v[ts_idx]);
680757
str8_list_pushf(scratch.arena, &unopen_type_server_list, "\t\tDependent obj(s):\n");
681758
for (U64Node *obj_idx_node = obj_idx_list.first; obj_idx_node != 0; obj_idx_node = obj_idx_node->next) {
682759
String8 obj_path = external_obj_arr[obj_idx_node->data].path;
@@ -704,8 +781,8 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
704781
cv.count = obj_count;
705782
cv.internal_count = internal_count;
706783
cv.external_count = external_count;
707-
cv.type_server_count = type_server_path_arr.count;
708-
cv.type_server_path_arr = type_server_path_arr.v;
784+
cv.type_server_count = ts_path_arr.count;
785+
cv.type_server_path_arr = ts_path_arr.v;
709786
cv.ts_to_obj_arr = ts_to_obj_arr;
710787
cv.obj_arr = sorted_obj_arr;
711788
cv.pch_arr = pch_arr;

src/linker/lnk_debug_info.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,17 @@ typedef struct
142142

143143
typedef struct
144144
{
145-
String8 *path_arr;
146-
String8 *msf_data_arr;
147-
Rng1U64 **external_ti_ranges;
148-
CV_DebugT **external_leaves;
149-
B8 *is_corrupted;
145+
String8Array data_arr;
146+
MSF_Parsed **msf_parse_arr;
147+
} LNK_MsfParsedFromDataTask;
148+
149+
typedef struct
150+
{
151+
CV_TypeServerInfo *ts_info_arr;
152+
MSF_Parsed **msf_parse_arr;
153+
Rng1U64 **external_ti_ranges;
154+
CV_DebugT **external_leaves;
155+
B8 *is_corrupted;
150156
} LNK_GetExternalLeavesTask;
151157

152158
////////////////////////////////

src/linker/lnk_error.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef enum
6060
LNK_Warning_InvalidNatvisFileExt,
6161
LNK_Warning_LargePages,
6262
LNK_Warning_LargePagesNotEnabled,
63+
LNK_Warning_MismatchedTypeServerSignature,
6364
LNK_Warning_MissingExternalTypeServer,
6465
LNK_Warning_MultipleDebugTAndDebugP,
6566
LNK_Warning_MultipleExternalTypeServers,

0 commit comments

Comments
 (0)