mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
WIP stripped PDB
This commit is contained in:
@@ -466,6 +466,23 @@ cv_make_pub32(Arena *arena, CV_Pub32Flags flags, U32 off, U16 isect, String8 nam
|
||||
return symbol;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_gproc(CV_Symbol symbol)
|
||||
{
|
||||
return symbol.kind == CV_SymKind_GPROC32 ||
|
||||
symbol.kind == CV_SymKind_GPROCMIPS ||
|
||||
symbol.kind == CV_SymKind_GPROCIA64 ||
|
||||
symbol.kind == CV_SymKind_GPROC32_ID ||
|
||||
symbol.kind == CV_SymKind_GPROCMIPS_ID ||
|
||||
symbol.kind == CV_SymKind_GPROCIA64_ID ||
|
||||
symbol.kind == CV_SymKind_GPROC16 ||
|
||||
symbol.kind == CV_SymKind_GPROC32_16t ||
|
||||
symbol.kind == CV_SymKind_GPROCMIPS_16t ||
|
||||
symbol.kind == CV_SymKind_GPROC32_ST ||
|
||||
symbol.kind == CV_SymKind_GPROCMIPS_ST ||
|
||||
symbol.kind == CV_SymKind_GPROCIA64_ST;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_lproc(CV_Symbol symbol)
|
||||
{
|
||||
|
||||
@@ -364,6 +364,7 @@ internal CV_Symbol cv_make_pub32(Arena *arena, CV_Pub32Flags flags, U32 off,
|
||||
internal U64 cv_read_symbol(String8 raw_data, U64 off, U64 align, CV_Symbol *symbol_out);
|
||||
internal CV_Symbol cv_symbol_from_string(String8 raw_data);
|
||||
|
||||
internal B32 cv_is_gproc(CV_Symbol symbol);
|
||||
internal B32 cv_is_lproc(CV_Symbol symbol);
|
||||
internal B32 cv_is_obj_info(CV_Symbol symbol);
|
||||
internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol);
|
||||
|
||||
+72
-1
@@ -2123,7 +2123,7 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
|
||||
}
|
||||
|
||||
ProfBegin("Build * Debug Directories *");
|
||||
if (config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null) {
|
||||
if (lnk_do_debug_info(config)) {
|
||||
String8 pdb_dir_obj = pe_make_debug_directory_pdb_obj(arena->v[0], config->machine, config->guid, config->age, config->time_stamp, config->pdb_alt_path);
|
||||
lnk_inputer_push_obj_linkgen(inputer, 0, str8_lit("* Debug Directory PDB *"), pdb_dir_obj);
|
||||
}
|
||||
@@ -5298,6 +5298,77 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
|
||||
lnk_timer_end(LNK_Timer_Pdb);
|
||||
}
|
||||
|
||||
//
|
||||
// stripped PDB
|
||||
//
|
||||
if (config->pdb_stripped_name.size != 0) {
|
||||
CV_DebugS *debug_s_arr = push_array(scratch.arena, CV_DebugS, cv.obj_count);
|
||||
for EachIndex(obj_idx, cv.obj_count) {
|
||||
|
||||
CV_DebugS *debug_s_dst = &debug_s_arr[obj_idx];
|
||||
CV_DebugS *debug_s_src = &cv.debug_s_arr[obj_idx];
|
||||
String8List *dst = &debug_s_dst->data_list[CV_C13SubSectionIdxKind_Symbols];
|
||||
String8List *src = &debug_s_src->data_list[CV_C13SubSectionIdxKind_Symbols];
|
||||
|
||||
U64 proc_count = 0;
|
||||
U64 proc_size = 0;
|
||||
U64 section = 0;
|
||||
for EachNode(n, String8Node, src->first) {
|
||||
for (U64 cursor = 0; cursor < n->string.size; ) {
|
||||
U64 c = cursor;
|
||||
CV_Symbol symbol = {0};
|
||||
TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor);
|
||||
if (symbol.kind == CV_SymKind_SKIP) { continue; }
|
||||
if (cv_is_lproc(symbol)) {
|
||||
proc_count += 1;
|
||||
proc_size += AlignPow2(symbol.data.size, CV_SymbolAlign);
|
||||
}
|
||||
}
|
||||
section += 1;
|
||||
}
|
||||
|
||||
if (proc_count) {
|
||||
U64 end_count = proc_count;
|
||||
U64 symbol_count = proc_count + end_count;
|
||||
U64 buffer_size = proc_size + sizeof(CV_SymbolHeader) * symbol_count;
|
||||
U8 *buffer = push_array(scratch.arena, U8, buffer_size);
|
||||
U64 buffer_cursor = 0;
|
||||
|
||||
for EachNode(n, String8Node, src->first) {
|
||||
for (U64 cursor = 0; cursor < n->string.size; ) {
|
||||
CV_Symbol symbol = {0};
|
||||
TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor);
|
||||
if (symbol.kind == CV_SymKind_SKIP) { continue; }
|
||||
if (cv_is_lproc(symbol)) {
|
||||
CV_SymProc32 *src_proc = (CV_SymProc32 *)symbol.data.str;
|
||||
src_proc->itype = 0;
|
||||
|
||||
CV_Symbol end_symbol = { .kind = CV_SymKind_END };
|
||||
|
||||
buffer_cursor += cv_write_symbol(buffer, buffer_cursor, buffer_size, &symbol, CV_SymbolAlign);
|
||||
buffer_cursor += cv_write_symbol(buffer, buffer_cursor, buffer_size, &end_symbol, CV_SymbolAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert(buffer_cursor == buffer_size);
|
||||
|
||||
str8_list_push(scratch.arena, dst, str8(buffer, buffer_size));
|
||||
}
|
||||
}
|
||||
|
||||
LNK_CodeViewInput stripped_cv = {0};
|
||||
stripped_cv.io_flags = config->io_flags;
|
||||
stripped_cv.is_stripped = 1;
|
||||
stripped_cv.obj_arr = cv.obj_arr;
|
||||
stripped_cv.obj_count = cv.obj_count;
|
||||
stripped_cv.count = cv.obj_count;
|
||||
stripped_cv.debug_s_arr = debug_s_arr;
|
||||
stripped_cv.symbol_input_ranges = push_array(scratch.arena, Rng1U64, tp->worker_count);
|
||||
|
||||
String8List pdb_data = lnk_build_pdb(tp, arena, image_ctx.image_data, config, symtab, &stripped_cv, (LNK_MergedTypes){0});
|
||||
lnk_write_data_list_to_file_path(config->pdb_stripped_name, str8f(scratch.arena, "%S.tmp", config->pdb_stripped_name), pdb_data);
|
||||
}
|
||||
|
||||
lnk_timer_end(LNK_Timer_Debug);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ global read_only LNK_CmdSwitch g_cmd_switch_map[] =
|
||||
{ LNK_CmdSwitch_Pdb, 0, "PDB", ":FILENAME", "File name of the output PDB." },
|
||||
{ LNK_CmdSwitch_PdbAltPath, 0, "PDBALTPATH", ":PATH", "Alternative output path for the PDB." },
|
||||
{ LNK_CmdSwitch_PdbPageSize, 0, "PDBPAGESIZE", ":#", "Page size must be power of two." },
|
||||
{ LNK_CmdSwitch_PdbStripped, 0, "PDBSTRIPPED", ":FILENAME", "Create a stripped PDB containing public symbols, a section map, and a list of object files." },
|
||||
{ LNK_CmdSwitch_Release, 1, "RELEASE", "", "Write image checksum." },
|
||||
{ LNK_CmdSwitch_Stack, 1, "STACK", ":RESERVE[,COMMIT]", "Set reserve and commit size for the stack." },
|
||||
{ LNK_CmdSwitch_SubSystem, 1, "SUBSYSTEM", ":{CONSOLE|NATIVE|WINDOWS}[,#[.##]]", "Set subsystem for the image." },
|
||||
@@ -1721,6 +1722,13 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
}
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_PdbStripped: {
|
||||
String8 file_name;
|
||||
if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, &file_name)) {
|
||||
config->pdb_stripped_name = str8_copy(config->arena, file_name);
|
||||
}
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Release: {
|
||||
if (value_strings.node_count == 0) {
|
||||
config->flags |= LNK_ConfigFlag_WriteImageChecksum;
|
||||
|
||||
@@ -50,8 +50,8 @@ typedef enum
|
||||
LNK_CmdSwitch_FailIfMismatch,
|
||||
LNK_CmdSwitch_FileAlign,
|
||||
LNK_CmdSwitch_Fixed,
|
||||
LNK_CmdSwitch_FunctionPadMin,
|
||||
LNK_CmdSwitch_Force,
|
||||
LNK_CmdSwitch_FunctionPadMin,
|
||||
LNK_CmdSwitch_Heap,
|
||||
LNK_CmdSwitch_HighEntropyVa,
|
||||
LNK_CmdSwitch_Ignore,
|
||||
@@ -79,6 +79,7 @@ typedef enum
|
||||
LNK_CmdSwitch_Pdb,
|
||||
LNK_CmdSwitch_PdbAltPath,
|
||||
LNK_CmdSwitch_PdbPageSize,
|
||||
LNK_CmdSwitch_PdbStripped,
|
||||
LNK_CmdSwitch_Release,
|
||||
LNK_CmdSwitch_Stack,
|
||||
LNK_CmdSwitch_SubSystem,
|
||||
@@ -312,6 +313,7 @@ typedef struct LNK_Config
|
||||
String8List raw_cmd_line;
|
||||
String8 pdb_name;
|
||||
String8 pdb_alt_path;
|
||||
String8 pdb_stripped_name;
|
||||
String8 mt_path;
|
||||
LNK_TypeNameHashMode pdb_hash_type_names;
|
||||
String8 pdb_hash_type_name_map;
|
||||
|
||||
+50
-38
@@ -2046,30 +2046,33 @@ lnk_write_debug_s_to_pdb_module(PDB_DbiModule *mod, CV_DebugS debug_s, String8No
|
||||
mod->c13_data_size = 0;
|
||||
mod->globrefs_size = 0;
|
||||
|
||||
// signature
|
||||
U64 sig_size = str8_buffer_write_u32(buf, buf_pos, CV_Signature_C13);
|
||||
mod->sym_data_size += sig_size;
|
||||
mod_cursor += sig_size;
|
||||
|
||||
// write symbols
|
||||
String8List symbols = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_Symbols);
|
||||
U64 scope_depth = 0;
|
||||
for EachNode(n, String8Node, symbols.first) {
|
||||
for (U64 cursor = 0; cursor + sizeof(CV_SymbolHeader) <= n->string.size; ) {
|
||||
CV_Symbol symbol = {0};
|
||||
TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor);
|
||||
if (symbol.kind == CV_SymKind_SKIP) { continue; }
|
||||
|
||||
if (cv_is_global_symbol(symbol.kind)) { continue; }
|
||||
else if (cv_is_typedef(symbol.kind) && scope_depth == 0) { continue; }
|
||||
else if (symbol.kind == 0x1176) { continue; }
|
||||
if (symbols.total_size) {
|
||||
// signature
|
||||
U64 sig_size = str8_buffer_write_u32(buf, buf_pos, CV_Signature_C13);
|
||||
mod->sym_data_size += sig_size;
|
||||
mod_cursor += sig_size;
|
||||
|
||||
if (cv_is_scope_symbol(symbol.kind)) { scope_depth += 1; }
|
||||
else if (cv_is_end_symbol(symbol.kind)) { scope_depth -= 1; }
|
||||
// write symbols
|
||||
U64 scope_depth = 0;
|
||||
for EachNode(n, String8Node, symbols.first) {
|
||||
for (U64 cursor = 0; cursor + sizeof(CV_SymbolHeader) <= n->string.size; ) {
|
||||
CV_Symbol symbol = {0};
|
||||
TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor);
|
||||
if (symbol.kind == CV_SymKind_SKIP) { continue; }
|
||||
|
||||
U64 symbol_size = cv_write_symbol_buf(buf, buf_pos, &symbol, PDB_SYMBOL_ALIGN);
|
||||
mod_cursor += symbol_size;
|
||||
mod->sym_data_size += symbol_size;
|
||||
if (cv_is_global_symbol(symbol.kind)) { continue; }
|
||||
else if (cv_is_typedef(symbol.kind) && scope_depth == 0) { continue; }
|
||||
else if (symbol.kind == 0x1176) { continue; }
|
||||
|
||||
if (cv_is_scope_symbol(symbol.kind)) { scope_depth += 1; }
|
||||
else if (cv_is_end_symbol(symbol.kind)) { scope_depth -= 1; }
|
||||
|
||||
U64 symbol_size = cv_write_symbol_buf(buf, buf_pos, &symbol, PDB_SYMBOL_ALIGN);
|
||||
mod_cursor += symbol_size;
|
||||
mod->sym_data_size += symbol_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2112,10 +2115,12 @@ lnk_write_debug_s_to_pdb_module(PDB_DbiModule *mod, CV_DebugS debug_s, String8No
|
||||
}
|
||||
|
||||
// write global refs
|
||||
String8List globrefs = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_GlobalRefs);
|
||||
mod->globrefs_size += str8_buffer_write_u32(buf, buf_pos, safe_cast_u32(globrefs.total_size));
|
||||
mod->globrefs_size += str8_buffer_write_string_list(buf, buf_pos, globrefs);
|
||||
mod_cursor += mod->globrefs_size;
|
||||
if (mod->sym_data_size) {
|
||||
String8List globrefs = cv_sub_section_from_debug_s(debug_s, CV_C13SubSectionKind_GlobalRefs);
|
||||
mod->globrefs_size += str8_buffer_write_u32(buf, buf_pos, safe_cast_u32(globrefs.total_size));
|
||||
mod->globrefs_size += str8_buffer_write_string_list(buf, buf_pos, globrefs);
|
||||
mod_cursor += mod->globrefs_size;
|
||||
}
|
||||
|
||||
return mod_cursor;
|
||||
}
|
||||
@@ -2153,6 +2158,9 @@ THREAD_POOL_TASK_FUNC(lnk_write_pdb_modules)
|
||||
|
||||
U64 obj_idx = obj_indices.v[i];
|
||||
PDB_DbiModule *mod = task->mod_arr[obj_idx];
|
||||
|
||||
if (mod->sn == MSF_INVALID_STREAM_NUMBER) { continue; }
|
||||
|
||||
CV_DebugS debug_s = task->cv->debug_s_arr[obj_idx];
|
||||
String8List mod_data = msf_data_from_sn(temp.arena, task->pdb->msf, mod->sn);
|
||||
|
||||
@@ -2162,10 +2170,12 @@ THREAD_POOL_TASK_FUNC(lnk_write_pdb_modules)
|
||||
lnk_write_debug_s_to_pdb_module(mod, debug_s, &buf, &pos);
|
||||
|
||||
// sub range symbol data pages and patch symbol tree offsets
|
||||
Rng1U64 sym_data_range = r1u64(sizeof(CV_Signature), mod->sym_data_size);
|
||||
String8List mod_symbols = str8_list_substr(temp.arena, mod_data, sym_data_range);
|
||||
Assert(mod_symbols.total_size == dim_1u64(sym_data_range));
|
||||
cv_patch_symbol_tree_offsets(mod_symbols, sizeof(CV_Signature), PDB_SYMBOL_ALIGN);
|
||||
if (mod->sym_data_size) {
|
||||
Rng1U64 sym_data_range = r1u64(sizeof(CV_Signature), mod->sym_data_size);
|
||||
String8List mod_symbols = str8_list_substr(temp.arena, mod_data, sym_data_range);
|
||||
Assert(mod_symbols.total_size == dim_1u64(sym_data_range));
|
||||
cv_patch_symbol_tree_offsets(mod_symbols, sizeof(CV_Signature), PDB_SYMBOL_ALIGN);
|
||||
}
|
||||
}
|
||||
|
||||
temp_end(temp);
|
||||
@@ -2204,11 +2214,14 @@ THREAD_POOL_TASK_FUNC(lnk_write_pdb_modules)
|
||||
for EachIndex(i, obj_indices.count) {
|
||||
Temp temp = temp_begin(scratch.arena);
|
||||
|
||||
U64 obj_idx = obj_indices.v[i];
|
||||
PDB_DbiModule *mod = task->mod_arr[obj_idx];
|
||||
String8List mod_data = msf_data_from_sn(temp.arena, task->pdb->msf, mod->sn);
|
||||
Rng1U64 c13_data_range = r1u64(mod->sym_data_size + mod->c11_data_size, mod->sym_data_size + mod->c11_data_size + mod->c13_data_size);
|
||||
String8List c13_data = str8_list_substr(temp.arena, mod_data, c13_data_range);
|
||||
U64 obj_idx = obj_indices.v[i];
|
||||
PDB_DbiModule *mod = task->mod_arr[obj_idx];
|
||||
|
||||
if (mod->sn == MSF_INVALID_STREAM_NUMBER) { continue; }
|
||||
|
||||
String8List mod_data = msf_data_from_sn(temp.arena, task->pdb->msf, mod->sn);
|
||||
Rng1U64 c13_data_range = r1u64(mod->sym_data_size + mod->c11_data_size, mod->sym_data_size + mod->c11_data_size + mod->c13_data_size);
|
||||
String8List c13_data = str8_list_substr(temp.arena, mod_data, c13_data_range);
|
||||
|
||||
CV_DebugS debug_s = task->cv->debug_s_arr[obj_idx];
|
||||
String8 string_table = cv_string_table_from_debug_s(debug_s);
|
||||
@@ -2359,9 +2372,11 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config
|
||||
.image_section_virt_ranges.v = push_array(scratch.arena, Rng1U64, task.image_section_table_count),
|
||||
.image_section_file_ranges.v = push_array(scratch.arena, Rng1U64, task.image_section_table_count),
|
||||
};
|
||||
|
||||
// set min type indices
|
||||
for EachElement(ti_source, cv_types.min_type_indices) { task.pdb->type_servers[ti_source]->ti_lo = cv_types.min_type_indices[ti_source]; }
|
||||
|
||||
// per worker obj indices
|
||||
{
|
||||
U64 objs_per_worker = CeilIntegerDiv(cv->obj_count, tp->worker_count);
|
||||
task.obj_indices = push_array(scratch.arena, U32Array, tp->worker_count);
|
||||
@@ -2372,10 +2387,7 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config
|
||||
}
|
||||
}
|
||||
|
||||
// move patched type data
|
||||
//
|
||||
// leaf data is stored in g_file_arena which has linker's life-time
|
||||
// and this way we skip redundant leaf copy to the type server to make things faster
|
||||
// push types
|
||||
pdb_type_server_push_parallel(tp, task.pdb->type_servers[CV_TypeIndexSource_IPI], cv_types.count[CV_TypeIndexSource_IPI], cv_types.v[CV_TypeIndexSource_IPI]);
|
||||
pdb_type_server_push_parallel(tp, task.pdb->type_servers[CV_TypeIndexSource_TPI], cv_types.count[CV_TypeIndexSource_TPI], cv_types.v[CV_TypeIndexSource_TPI]);
|
||||
|
||||
@@ -2453,7 +2465,7 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config
|
||||
}
|
||||
ProfEnd();
|
||||
|
||||
pdb_build(tp, tp_arena, task.pdb, task.string_ht, 0);
|
||||
pdb_build(tp, tp_arena, task.pdb, task.string_ht, 0, cv->is_stripped);
|
||||
|
||||
MSF_Error msf_err = msf_build(task.pdb->msf);
|
||||
if (msf_err != MSF_Error_OK) {
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct
|
||||
{
|
||||
LNK_IO_Flags io_flags;
|
||||
U64 obj_count;
|
||||
B32 is_stripped;
|
||||
|
||||
U64 count;
|
||||
LNK_Obj **obj_arr;
|
||||
|
||||
Reference in New Issue
Block a user