public RoutineInfo FindRoutine(int pc) { int start = 0, end = routines.Count; while (start < end) { int mid = (start + end) / 2; RoutineInfo ri = routines[mid]; if (pc >= ri.CodeStart && pc < ri.CodeStart + ri.CodeLength) { return(ri); } if (pc > ri.CodeStart) { start = mid + 1; } else { end = mid; } } return(null); }
public LineInfo?FindLine(int pc) { RoutineInfo rtn = FindRoutine(pc); if (rtn == null) { return(null); } ushort offset = (ushort)(pc - rtn.CodeStart); int idx = Array.BinarySearch(rtn.LineOffsets, offset); if (idx >= 0) { return(rtn.LineInfos[idx]); } idx = ~idx - 1; if (idx >= 0 && idx < rtn.LineInfos.Length) { return(rtn.LineInfos[idx]); } return(null); }
public int FindCodeAddress(string filename, int line) { for (int i = 0; i < routines.Count; i++) { RoutineInfo rtn = routines[i]; for (int j = 0; j < rtn.LineInfos.Length; j++) { if (rtn.LineInfos[j].File == filename && rtn.LineInfos[j].Line == line) { return(rtn.CodeStart + rtn.LineOffsets[j]); } } } return(-1); }
public DebugInfo(Stream fromStream) { using (BinaryReader br = new BinaryReader(fromStream)) { if (ReadWord(br) != 0xDEBF) throw new ArgumentException("Invalid debug file header"); if (ReadWord(br) != 0) throw new ArgumentException("Unrecognized debug file version"); ReadWord(br); // skip Inform version Dictionary<byte, string> filenames = new Dictionary<byte, string>(5); Dictionary<ushort, int> routineStarts = new Dictionary<ushort, int>(); int i, codeArea = 0; byte b; ushort w; string str; LineRef line; RoutineInfo routine = null; while (fromStream.Position < fromStream.Length) { byte type = br.ReadByte(); switch (type) { case 0: // EOF_DBR fromStream.Seek(0, SeekOrigin.End); break; case 1: // FILE_DBR b = br.ReadByte(); ReadString(br); // skip include name str = ReadString(br); filenames[b] = str; break; case 2: // CLASS_DBR ReadString(br); ReadLineRef(br); ReadLineRef(br); break; case 3: // OBJECT_DBR ReadWord(br); ReadString(br); ReadLineRef(br); ReadLineRef(br); break; case 4: // GLOBAL_DBR br.ReadByte(); ReadString(br); break; case 12: // ARRAY_DBR case 5: // ATTR_DBR case 6: // PROP_DBR case 7: // FAKE_ACTION_DBR case 8: // ACTION_DBR ReadWord(br); ReadString(br); break; case 9: // HEADER_DBR matchingHeader = br.ReadBytes(64); break; case 11: // ROUTINE_DBR routine = new RoutineInfo(); routines.Add(routine); w = ReadWord(br); line = ReadLineRef(br); if (line.IsValid) routine.DefinedAt = new LineInfo( filenames[line.FileNum], line.LineNum, line.Column); routine.CodeStart = ReadAddress(br); routineStarts[w] = routine.CodeStart; routine.Name = ReadString(br); while (ReadString(br) != "") { // skip local variable names } break; case 10: // LINEREF_DBR ReadWord(br); w = ReadWord(br); while (w-- > 0) { ReadLineRef(br); ReadWord(br); } break; case 14: // ROUTINE_END_DBR // assume routine is still set from earlier... ReadWord(br); // skip routine number ReadLineRef(br); // skip defn end i = ReadAddress(br); routine.CodeLength = i - routine.CodeStart; break; case 13: // MAP_DBR do { str = ReadString(br); if (str != "") { i = ReadAddress(br); if (str == "code area") codeArea = i; } } while (str != ""); break; } } // patch routine addresses foreach (RoutineInfo ri in routines) ri.CodeStart += codeArea; routines.Sort(delegate(RoutineInfo r1, RoutineInfo r2) { return r1.CodeStart - r2.CodeStart; }); } }
public DebugInfo(Stream fromStream) { using (BinaryReader br = new BinaryReader(fromStream)) { if (ReadWord(br) != 0xDEBF) { throw new ArgumentException("Invalid debug file header"); } if (ReadWord(br) != 0) { throw new ArgumentException("Unrecognized debug file version"); } ReadWord(br); // skip Inform version Dictionary <byte, string> filenames = new Dictionary <byte, string>(5); Dictionary <ushort, int> routineStarts = new Dictionary <ushort, int>(); int i, codeArea = 0; byte b; ushort w; string str; LineRef line; RoutineInfo routine = null; while (fromStream.Position < fromStream.Length) { byte type = br.ReadByte(); switch (type) { case 0: // EOF_DBR fromStream.Seek(0, SeekOrigin.End); break; case 1: // FILE_DBR b = br.ReadByte(); ReadString(br); // skip include name str = ReadString(br); filenames[b] = str; break; case 2: // CLASS_DBR ReadString(br); ReadLineRef(br); ReadLineRef(br); break; case 3: // OBJECT_DBR ReadWord(br); ReadString(br); ReadLineRef(br); ReadLineRef(br); break; case 4: // GLOBAL_DBR br.ReadByte(); ReadString(br); break; case 12: // ARRAY_DBR case 5: // ATTR_DBR case 6: // PROP_DBR case 7: // FAKE_ACTION_DBR case 8: // ACTION_DBR ReadWord(br); ReadString(br); break; case 9: // HEADER_DBR matchingHeader = br.ReadBytes(64); break; case 11: // ROUTINE_DBR routine = new RoutineInfo(); routines.Add(routine); w = ReadWord(br); line = ReadLineRef(br); if (line.IsValid) { routine.DefinedAt = new LineInfo( filenames[line.FileNum], line.LineNum, line.Column); } routine.CodeStart = ReadAddress(br); routineStarts[w] = routine.CodeStart; routine.Name = ReadString(br); while (ReadString(br) != "") { // skip local variable names } break; case 10: // LINEREF_DBR ReadWord(br); w = ReadWord(br); while (w-- > 0) { ReadLineRef(br); ReadWord(br); } break; case 14: // ROUTINE_END_DBR // assume routine is still set from earlier... ReadWord(br); // skip routine number ReadLineRef(br); // skip defn end i = ReadAddress(br); routine.CodeLength = i - routine.CodeStart; break; case 13: // MAP_DBR do { str = ReadString(br); if (str != "") { i = ReadAddress(br); if (str == "code area") { codeArea = i; } } } while (str != ""); break; } } // patch routine addresses foreach (RoutineInfo ri in routines) { ri.CodeStart += codeArea; } routines.Sort(delegate(RoutineInfo r1, RoutineInfo r2) { return(r1.CodeStart - r2.CodeStart); }); } }