From 190f68d1f84a791e4ca244bdd2d486967eee4415 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Thu, 2 Jul 2020 13:41:44 -0700 Subject: [PATCH] Add code hints to OMF jump tables We now put a code hint on the JML instruction in each jump table entry. This is necessary to ensure that the target address is recognized as code, since a dynamic segment won't otherwise be referenced. Also, fiddle with the note/comment formatting some more. --- SourceGen/Res/Strings.xaml | 5 +-- SourceGen/Res/Strings.xaml.cs | 2 ++ SourceGen/Tools/Omf/Loader.cs | 62 ++++++++++++++++++++++++----------- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/SourceGen/Res/Strings.xaml b/SourceGen/Res/Strings.xaml index c133eca..cb97889 100644 --- a/SourceGen/Res/Strings.xaml +++ b/SourceGen/Res/Strings.xaml @@ -130,8 +130,9 @@ limitations under the License. Visualization ignored no files available No exported symbols found. - Segment {0:D2}: {3} Kind={1}, SegName='{2}' - Segment {0:D2}: {1} '{2}' + Segment {0:D2}: Kind={1}, Attrs={2}, Name='{3}' + Segment {0:D2}: {3} {1,-9} Name='{2}' + Seg{0:D2}: {1} '{2}' The file doesn't exist. File is empty Unable to load data file diff --git a/SourceGen/Res/Strings.xaml.cs b/SourceGen/Res/Strings.xaml.cs index 37bd598..4b80c0d 100644 --- a/SourceGen/Res/Strings.xaml.cs +++ b/SourceGen/Res/Strings.xaml.cs @@ -243,6 +243,8 @@ namespace SourceGen.Res { (string)Application.Current.FindResource("str_NoExportedSymbolsFound"); public static string OMF_SEG_COMMENT_FMT = (string)Application.Current.FindResource("str_OmfSegCommentFmt"); + public static string OMF_SEG_HDR_COMMENT_FMT = + (string)Application.Current.FindResource("str_OmfSegHdrCommentFmt"); public static string OMF_SEG_NOTE_FMT = (string)Application.Current.FindResource("str_OmfSegNoteFmt"); public static string OPEN_DATA_DOESNT_EXIST = diff --git a/SourceGen/Tools/Omf/Loader.cs b/SourceGen/Tools/Omf/Loader.cs index 41f45a8..f2d61b2 100644 --- a/SourceGen/Tools/Omf/Loader.cs +++ b/SourceGen/Tools/Omf/Loader.cs @@ -304,7 +304,7 @@ namespace SourceGen.Tools.Omf { } if (ent.Segment.Kind == OmfSegment.SegmentKind.JumpTable) { - if (!RelocJumpTable(ent, data, bufOffset)) { + if (!RelocJumpTable(ent, data, bufOffset, cs)) { // Could treat this as non-fatal, but it really ought to work. Debug.WriteLine("Jump Table reloc failed"); return false; @@ -320,13 +320,21 @@ namespace SourceGen.Tools.Omf { // can straddle multiple pages.) AddAddressEntries(proj, ent, bufOffset, cs); - // Add a note identifying the segment. - string segCmt = string.Format(Res.Strings.OMF_SEG_NOTE_FMT, - ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.SegName); - UndoableChange uc = UndoableChange.CreateNoteChange(bufOffset, null, + // Add a comment identifying the segment and its attributes. + string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT, + ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.Attrs, ent.Segment.SegName); + UndoableChange uc = UndoableChange.CreateLongCommentChange(bufOffset, null, new MultiLineComment(segCmt)); cs.Add(uc); + // Add a note identifying the segment. + string segNote = string.Format(Res.Strings.OMF_SEG_NOTE_FMT, + ent.Segment.SegNum, mFormatter.FormatAddress(ent.Address, true), + ent.Segment.SegName); + uc = UndoableChange.CreateNoteChange(bufOffset, null, + new MultiLineComment(segNote)); + cs.Add(uc); + bufOffset += ent.Segment.Length; } @@ -348,7 +356,7 @@ namespace SourceGen.Tools.Omf { if (ent == null) { continue; } - string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT, + string segCmt = string.Format(Res.Strings.OMF_SEG_HDR_COMMENT_FMT, ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.SegName, mFormatter.FormatAddress(ent.Address, true)); sb.AppendLine(segCmt); @@ -431,7 +439,8 @@ namespace SourceGen.Tools.Omf { /// Edits the data file, essentially putting the jump table entries into the /// "loaded" state. /// - private bool RelocJumpTable(SegmentMapEntry ent, byte[] data, int bufOffset) { + private bool RelocJumpTable(SegmentMapEntry ent, byte[] data, int bufOffset, + ChangeSet cs) { const int ENTRY_LEN = 14; byte[] srcData = ent.Segment.GetConstData(); @@ -445,6 +454,9 @@ namespace SourceGen.Tools.Omf { } } + TypedRangeSet newSet = new TypedRangeSet(); + TypedRangeSet undoSet = new TypedRangeSet(); + for (int i = 8; i + 4 <= ent.Segment.Length; i += ENTRY_LEN) { int userId = RawData.GetWord(data, bufOffset + i, 2, false); int fileNum = RawData.GetWord(data, bufOffset + i + 2, 2, false); @@ -473,21 +485,31 @@ namespace SourceGen.Tools.Omf { if (segNum < 0 || segNum >= mSegmentMap.Count || mSegmentMap[segNum] == null) { Debug.WriteLine("JumpTab: invalid SegNum=" + segNum); return false; - } else { - if (data[bufOffset + i + 10] != 0x22) { - Debug.WriteLine("JumpTab: did not find expected JSL at off=" + i); - return false; - } - - int addr = mSegmentMap[segNum].Address + segOff; - data[bufOffset + i + 10] = 0x5c; // JML - data[bufOffset + i + 11] = (byte)addr; - data[bufOffset + i + 12] = (byte)(addr >> 8); - data[bufOffset + i + 13] = (byte)(addr >> 16); - //Debug.WriteLine("JumpTab: off=" + i + " -> " + - // mFormatter.FormatAddress(addr, true)); } + if (data[bufOffset + i + 10] != 0x22) { + Debug.WriteLine("JumpTab: did not find expected JSL at off=" + i); + return false; + } + + int addr = mSegmentMap[segNum].Address + segOff; + int jmlOffset = bufOffset + i + 10; + data[jmlOffset] = 0x5c; // JML + data[jmlOffset + 1] = (byte)addr; + data[jmlOffset + 2] = (byte)(addr >> 8); + data[jmlOffset + 3] = (byte)(addr >> 16); + //Debug.WriteLine("JumpTab: off=" + i + " -> " + + // mFormatter.FormatAddress(addr, true)); + + // It seems to be fairly common for jump table entries to not be referenced + // from the program, which can leave whole dynamic segments unreferenced. Set + // a code hint on the JML instruction. + undoSet.Add(jmlOffset, (int)CodeAnalysis.TypeHint.NoHint); + newSet.Add(jmlOffset, (int)CodeAnalysis.TypeHint.Code); } + + UndoableChange uc = UndoableChange.CreateTypeHintChange(undoSet, newSet); + cs.Add(uc); + return true; }