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)); }
//$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; }