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)); }
public virtual bool resolve_index_hunks(IndexHunk index, List<List<Hunk>> segment_list, List<LibUnit> lib_units) { var units = index.units; var no = 0; bool found = false; foreach (var unit in units) { var unit_segments = new List<List<Hunk>>(); var lib_unit = new LibUnit { segments = unit_segments, name = unit.name, unit_no = no, index_unit = unit, }; lib_units.Add(lib_unit); no += 1; // try to find segment with start offset var hunk_offset = unit.hunk_begin_offset; found = false; foreach (var segment in segment_list) { int hunk_no = segment[0].hunk_no; uint lib_off = segment[0].hunk_lib_offset / 4; if (lib_off == hunk_offset) { // found segment int num_segs = unit.hunk_infos.Count; for (var i = 0; i < num_segs; ++i) { var info = unit.hunk_infos[i]; var seg = segment_list[hunk_no + i]; unit_segments.Add(seg); // renumber hunk seg[0].hunk_no = i; seg[0].Name = info.name; seg[0].index_hunk = info; } found = true; } } if (!found) { return false; } } return true; }