// no constructor; use static members only public static void Convert(String input_file_name_1, String input_file_name_2, String output_file_name) { System.IO.Stream out_file; EndianBinaryWriter out_writer; ObjectFile obj_file_1, obj_file_2; Boolean second_input_file = (input_file_name_2 == "") ? false : true; // attempt to open output file for writing out_file = System.IO.File.Open(output_file_name, System.IO.FileMode.Create); out_writer = new EndianBinaryWriter(out_file, Endian.LittleEndian); // note: entrypoint accessible as obj_file_x.EntryPoint // note: section count accessible as obj_file_x.LoadableSectionCount // note: section contents accessible as obj_file_x.LoadableSections if (second_input_file) { // attempt to open input files as COFF or ELF openObjFile(input_file_name_1, out obj_file_1); openObjFile(input_file_name_2, out obj_file_2); // write header contents to output file writeRprcHeader(out_writer, obj_file_1.LoadableSectionCount + obj_file_2.LoadableSectionCount); // write entrypoint of both applications as "resource" sections to output file writeEntrypoint(out_writer, obj_file_1.EntryPoint); writeEntrypoint(out_writer, obj_file_2.EntryPoint); // write section contents to output file foreach (ObjectSection section in obj_file_1.LoadableSections) writeSection(out_writer, section, obj_file_1.secRead(section)); foreach (ObjectSection section in obj_file_2.LoadableSections) { writeSection(out_writer, section, obj_file_2.secRead(section)); // warn if section collides with another section from first application if (sectionOverlap(section, obj_file_1.LoadableSections)) Console.WriteLine("Warning: section in file " + input_file_name_2 + " starting at 0x" + section.loadAddr.ToString("x8") + " overlaps with one or more sections in file " + input_file_name_1 + "."); } // close input files obj_file_1.Close(); obj_file_2.Close(); } else { // attempt to open input file as COFF or ELF openObjFile(input_file_name_1, out obj_file_1); // write header contents to output file writeRprcHeader(out_writer, obj_file_1.LoadableSectionCount); // write entrypoint of first application as "resource" section to output file writeEntrypoint(out_writer, obj_file_1.EntryPoint); // write section contents to output file foreach (ObjectSection section in obj_file_1.LoadableSections) writeSection(out_writer, section, obj_file_1.secRead(section)); // close input file obj_file_1.Close(); } // close output file out_writer.Close(); }
private static void writeRprcHeader(EndianBinaryWriter writer, uint section_count) { // RPRC header contents: // char magic[4] = { 'R', 'P', 'R', 'C' }; // u32 version; // u32 header_len; // char header[...] = { header_len bytes of unformatted, textual header }; char[] magic = {'R', 'P', 'R', 'C'}; uint version = 1; // TODO: confirm with SDO // use text header to record section count uint length = 4; uint header = section_count; // TODO: add more text header contents? // write header to file writer.Write(magic); writer.Write(version); writer.Write(length); writer.Write(header); }
private static void writeSection(EndianBinaryWriter writer, ObjectSection section, byte[] contents) { // RPRC section contents: // u32 type; // u64 da; // u32 len; // u8 content[...] = { len bytes of binary data }; uint type = 1; // 1: TEXT, 2: DATA (TODO use both?) ulong addr = section.loadAddr; uint size = (uint)section.size; // write section to file writer.Write(type); writer.Write(addr); writer.Write(size); writer.Write(contents); }
private static void writeEntrypoint(EndianBinaryWriter writer, ulong entrypoint) { // RPRC section contents: // u32 type; // u64 da; // u32 len; // u8 content[...] = { len bytes of binary data }; // RPRC resource contents (inside section contents): // u32 type; // u64 da; // u32 len; // u32 reserved; // u8 name[48]; uint section_type = 0; // 0: RESOURCE ulong section_addr = entrypoint; uint section_size = 4 + 8 + 4 + 4 + 48; uint resource_type = 5; // 5: RSC_BOOTADDR ulong resource_addr = entrypoint; uint resource_size = 48; uint resource_rsvd = 0; char[] resource_name = newResourceName("Entrypoint"); // write section + resource to file writer.Write(section_type); writer.Write(section_addr); writer.Write(section_size); writer.Write(resource_type); writer.Write(resource_addr); writer.Write(resource_size); writer.Write(resource_rsvd); writer.Write(resource_name); }