//$TODO: move this to HunkFile public bool BuildUnit() { var force_unit = true; var in_hunk = false; string name = null; List<Hunk> segment = null; Unit unit = null; this.hunkFile.units = new List<Unit>(); var unit_no = 0; int hunk_no = 0; foreach (var e in this.hunkFile.hunks) { var hunk_type = e.HunkType; // optional unit as first entry if (hunk_type == HunkType.HUNK_UNIT) { unit = new Unit { name = e.Name, unit_no = unit_no, segments = new List<List<Hunk>>(), unit = e, }; ++unit_no; this.hunkFile.units.Add(unit); force_unit = false; hunk_no = 0; } else if (force_unit) throw new BadImageFormatException(string.Format("Expected name hunk in unit: {0} {1}/{1:X}.", e.HunkType, (int) hunk_type)); else if (!in_hunk) { // begin a named hunk if (hunk_type == HunkType.HUNK_NAME) { name = e.Name; // main hunk block } else if (unit_valid_main_hunks.Contains(hunk_type)) { segment = new List<Hunk> { e }; unit.segments.Add(segment); // give main block the NAME if (name != null) { e.Name = name; name = null; } e.hunk_no = hunk_no; hunk_no += 1; in_hunk = true; // broken hunk: ignore multi ENDs } else if (hunk_type == HunkType.HUNK_END) { } else throw new BadImageFormatException(string.Format("Expected main hunk in unit: {0} {1}/{1:X}.", e.HunkType, hunk_type)); } else { // a hunk is finished if (hunk_type == HunkType.HUNK_END) { in_hunk = false; // contents of hunk } else if (HunkLoader.unit_valid_extra_hunks.Contains(hunk_type)) { segment.Add(e); // unecpected hunk?! } else throw new BadImageFormatException(string.Format("Unexpected hunk in unit: {0} {1}/{1:X}", e.HunkType, hunk_type)); } } return true; }
public void hunktool_signature() { // # 48 UNIT //#3 CODE size 00000000 alloc size 00000028 file header @ 'romhunks' // 48 E7 00 3A 26 6F 00 14 20 6F 00 18 43 EF 00 1C // 45 FA 00 12 2C 79 00 00 00 00 4E AE 00 00 4C DF // 5C 00 4E 75 16 C0 4E 75 // ext ext // 00000000 _sprintf def // 00000016 _AbsExecBase absref32 // 0000001C _LVORawDoFmt relref16 // symbol symbol // 00000000 _sprintf // 00000024 stuffChar var unit = new Unit { segments = new List<List<Hunk>> { new List<Hunk> { new Hunk { HunkType = HunkType.HUNK_CODE, Data = MakeBytes( "48 E7 00 3A 26 6F 00 14 20 6F 00 18 43 EF 00 1C" + "45 FA 00 12 2C 79 00 00 00 00 4E AE 00 00 4C DF" + "5C 00 4E 75 16 C0 4E 75"), }, new ExtHunk { ext_def = new List<ExtObject> { new ExtObject { def = 0, type = ExtType.EXT_DEF, name = "_sprintf" } }, ext_ref = new List<ExtObject> { new ExtObject {type = ExtType.EXT_ABSREF32, name= "_AbsExecBase", refs = new List<uint> { 0x16 } }, new ExtObject {type = ExtType.EXT_RELREF16, name= "_LVORawDoFmt", refs = new List<uint> { 0x1C } } } } } } }; var file = new HunkFile { type = FileType.TYPE_UNIT, units = new List<Unit> { unit } }; var sw = new StringWriter(); var segs = new SignatureGenerator(new Dictionary<string, ValueObject>()); segs.Output = sw; segs.handle_hunk_file("foo.lib", file); var sGen = sw.ToString(); var sExp = "48E7003A266F0014206F001843EF001C45FA00122C79........4EAE....4CDF _sprintf" + nl; if (sExp != sGen) Debug.Print(sGen); Assert.AreEqual(sExp, sGen); }
public virtual void ParseIndex(Action<Hunk> h) { var hunk = new IndexHunk(); h(hunk); var index_size = this.read_long(); var total_size = index_size * 4; // First read string table var strtab_size = f.ReadBeInt16(); var strtab = f.ReadBytes(strtab_size); total_size -= strtab_size + 2; // Read units var units = new List<Unit>(); hunk.units = units; var unit_no = 0; while (total_size > 2) { // Read name of unit var name_offset = f.ReadBeInt16(); total_size -= 2; if (name_offset == 0) break; var unit = new Unit { unit_no = unit_no }; units.Add(unit); ++unit_no; // Generate unit name unit.name = this.get_index_name(strtab, name_offset); // hunks in unit var hunk_begin = f.ReadBeInt16(); var num_hunks = f.ReadBeInt16(); total_size -= 4; unit.hunk_begin_offset = hunk_begin; // For all hunks in unit var ihunks = new List<IHunk>(); unit.hunk_infos = ihunks; for (var a = 0; a < num_hunks; ++a) { var ihunk = new IHunk(); ihunks.Add(ihunk); // get hunk info name_offset = f.ReadBeInt16(); var hunk_size = f.ReadBeInt16(); var hunk_type = f.ReadBeInt16(); total_size -= 6; ihunk.name = this.get_index_name(strtab, name_offset); ihunk.size = hunk_size; ihunk.type = hunk_type & 16383; ihunk.memf = this.SetMemoryFlags(hunk_type & 49152, 14); // get references var num_refs = f.ReadBeInt16(); total_size -= 2; if (num_refs > 0) { var refs = new List<Reference>(); ihunk.refs = refs; for (var b = 0; b < num_refs; ++b) { var @ref = new Reference(); name_offset = f.ReadBeInt16(); total_size -= 2; var name = this.get_index_name(strtab, name_offset); if (name == "") { // 16 bit refs point to the previous zero byte before the string entry... name = this.get_index_name(strtab, name_offset + 1); @ref.bits = 16; } else { @ref.bits = 32; } @ref.name = name; refs.Add(@ref); // get definitions } } var num_defs = f.ReadBeInt16(); total_size -= 2; if (num_defs > 0) { var defs = new List<Definition>(); ihunk.defs = defs; for (var b = 0; b < num_defs; ++b) { name_offset = f.ReadBeInt16(); var def_value = f.ReadBeInt16(); var def_type_flags = f.ReadBeInt16(); var def_type = def_type_flags & 16383; var def_flags = def_type_flags & 49152; total_size -= 6; var name = this.get_index_name(strtab, name_offset); var d = new Definition { name = name, value = def_value, type = def_type }; d.memf = this.SetMemoryFlags(def_flags, 14); defs.Add(d); } } } } // Align hunk to long-word. if (total_size == 2) { f.ReadBeInt16(); } else if (total_size != 0) throw new BadImageFormatException(string.Format("{0} has invalid padding.", hunk.HunkType)); }