1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-06 00:28:58 +00:00

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.
This commit is contained in:
Andy McFadden 2020-07-02 13:41:44 -07:00
parent 4d06bb24eb
commit 190f68d1f8
3 changed files with 47 additions and 22 deletions

View File

@ -130,8 +130,9 @@ limitations under the License.
<system:String x:Key="str_MsgVisualizationIgnored">Visualization ignored</system:String>
<system:String x:Key="str_NoFilesAvailable">no files available</system:String>
<system:String x:Key="str_NoExportedSymbolsFound">No exported symbols found.</system:String>
<system:String x:Key="str_OmfSegCommentFmt">Segment {0:D2}: {3} Kind={1}, SegName='{2}'</system:String>
<system:String x:Key="str_OmfSegNoteFmt">Segment {0:D2}: {1} '{2}'</system:String>
<system:String x:Key="str_OmfSegCommentFmt">Segment {0:D2}: Kind={1}, Attrs={2}, Name='{3}'</system:String>
<system:String x:Key="str_OmfSegHdrCommentFmt">Segment {0:D2}: {3} {1,-9} Name='{2}'</system:String>
<system:String x:Key="str_OmfSegNoteFmt">Seg{0:D2}: {1} '{2}'</system:String>
<system:String x:Key="str_OpenDataDoesntExist">The file doesn't exist.</system:String>
<system:String x:Key="str_OpenDataEmpty">File is empty</system:String>
<system:String x:Key="str_OpenDataFailCaption">Unable to load data file</system:String>

View File

@ -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 =

View File

@ -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.
/// </summary>
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;
}