diff --git a/src/torture/torture.c b/src/torture/torture.c index af4fb94e..11ca6bf9 100644 --- a/src/torture/torture.c +++ b/src/torture/torture.c @@ -305,6 +305,69 @@ t_undef_section(void) return result; } +internal T_Result +t_find_merged_pdata(void) +{ + Temp scratch = scratch_begin(0,0); + + T_Result result = T_Result_Fail; + + U8 foobar_payload[] = { + 0x40, 0x57, 0x48, 0x81, 0xEC, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x33, 0xC4, 0x48, 0x89, 0x84, 0x24, 0xF0, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x04, 0x24, 0x48, + 0x8B, 0xF8, 0x33, 0xC0, 0xB9, 0xEC, 0x01, 0x00, 0x00, 0xF3, 0xAA, 0xB8, 0x04, 0x00, 0x00, 0x00, + 0x48, 0x6B, 0xC0, 0x02, 0x8B, 0x04, 0x04, 0x48, 0x8B, 0x8C, 0x24, 0xF0, 0x01, 0x00, 0x00, 0x48, + 0x33, 0xCC, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x81, 0xC4, 0x00, 0x02, 0x00, 0x00, 0x5F, 0xC3, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0x48, 0x83, 0xEC, 0x28, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3 + }; + U8 xdata_payload[] = { + 0x19, 0x1B, 0x03, 0x00, 0x09, 0x01, 0x40, 0x00, 0x02, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF0, 0x01, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, 0x00, 0x00 + }; + PE_IntelPdata intel_pdata = {0}; + U8 text_payload[] = { 0xC3 }; + + String8 main_obj; + { + COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); + COFF_ObjSection *xdata = coff_obj_writer_push_section(obj_writer, str8_lit(".xdata"), COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_Align4Bytes, str8_array_fixed(xdata_payload)); + COFF_ObjSection *pdata = coff_obj_writer_push_section(obj_writer, str8_lit(".pdata"), COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_Align4Bytes, str8_struct(&intel_pdata)); + COFF_ObjSection *foobar = coff_obj_writer_push_section(obj_writer, str8_lit(".foobar"), COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_CntCode|COFF_SectionFlag_Align1Bytes, str8_array_fixed(foobar_payload)); + COFF_ObjSection *text = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_CntCode|COFF_SectionFlag_Align1Bytes, str8_array_fixed(text_payload)); + + COFF_ObjSymbol *foobar_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("foobar"), 0, foobar); + + coff_obj_writer_push_symbol_secdef(obj_writer, xdata, COFF_ComdatSelect_Null); + COFF_ObjSymbol *unwind_foobar = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("$unwind$foobar"), 0, xdata); + + coff_obj_writer_push_symbol_secdef(obj_writer, pdata, COFF_ComdatSelect_Null); + coff_obj_writer_push_symbol_static(obj_writer, str8_lit("$pdata$foobar"), 0, pdata); + + coff_obj_writer_section_push_reloc(obj_writer, pdata, OffsetOf(PE_IntelPdata, voff_unwind_info), unwind_foobar, COFF_Reloc_X64_Addr32Nb); + coff_obj_writer_section_push_reloc(obj_writer, pdata, OffsetOf(PE_IntelPdata, voff_first), foobar_symbol, COFF_Reloc_X64_Addr32Nb); + coff_obj_writer_section_push_reloc(obj_writer, pdata, OffsetOf(PE_IntelPdata, voff_one_past_last), foobar_symbol, COFF_Reloc_X64_Addr32Nb); + + coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text); + main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); + coff_obj_writer_release(&obj_writer); + } + + t_write_file(str8_lit("main.obj"), main_obj); + + int linker_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe main.obj /merge:.pdata=.rdata")); + if (linker_exit_code == 0) { + String8 exe = t_read_file(scratch.arena, str8_lit("a.exe")); + PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe); + if (dim_1u64(pe.data_dir_franges[PE_DataDirectoryIndex_EXCEPTIONS]) == 0xC) { + result = T_Result_Pass; + } + } + + scratch_end(scratch); + return result; +} + //////////////////////////////////////////////////////////////// internal void @@ -319,8 +382,9 @@ entry_point(CmdLine *cmdline) char *label; T_Result (*r)(void); } target_array[] = { - { "undef_section", t_undef_section }, - { "abs_vs_weak", t_abs_vs_weak }, + { "undef_section", t_undef_section }, + { "abs_vs_weak", t_abs_vs_weak }, + { "find_merged_pdata", t_find_merged_pdata }, }; //