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

Apply relocation data to unformatted data

Works well for things like jump tables.  Seeing a bunch of these
scattered in a chunk of data is a decent signal that it's actually
code.

In a bold move, we now exclude PEA operands from auto-label gen when
they don't have relocation data.  This is very useful for things
like Int2Hex for which constants are typically pushed with PEA.

Reworked the "use reloc data" setting so it defaults to false and is
explicitly set to true when converting OMF.  This provides a minor
optimization since we now check the boolean and skip doing a lookup
in an empty table.
This commit is contained in:
Andy McFadden 2020-07-03 22:03:50 -07:00
parent a6700e9062
commit 0fa77cba75
4 changed files with 67 additions and 19 deletions

View File

@ -163,10 +163,11 @@ namespace SourceGen {
}
// Check for a relocation. It'll be at offset+1 because it's on the operand,
// not the opcode byte.
if (mAnalysisParams.UseRelocData && mProject.RelocList.TryGetValue(offset + 1,
out DisasmProject.RelocData reloc)) {
if (reloc.Value != attr.OperandAddress) {
// not the opcode byte. (Make sure to check the length, or an RTS followed
// by relocated data will freak out.)
if (mAnalysisParams.UseRelocData) {
if (attr.Length > 1 && mProject.RelocList.TryGetValue(offset + 1,
out DisasmProject.RelocData reloc)) {
// The relocation address differs from what the analyzer came up
// with. This may be because of incorrect assumptions about the
// bank (assuming B==K) or because the partial address refers to
@ -174,28 +175,33 @@ namespace SourceGen {
// address is different, attr.OperandOffset will also be different.
int relOperandOffset = mProject.AddrMap.AddressToOffset(offset,
reloc.Value);
if (relOperandOffset >= 0 && relOperandOffset != attr.OperandOffset) {
if (relOperandOffset >= 0) {
// Determined a different offset. Use that instead.
//Debug.WriteLine("REL +" + offset.ToString("x6") + " " +
// reloc.Value.ToString("x6") + " vs. " +
// attr.OperandAddress.ToString("x6"));
WeakSymbolRef.Part part = WeakSymbolRef.Part.Low;
if (reloc.Shift == -8) {
part = WeakSymbolRef.Part.High;
} else if (reloc.Shift == -16) {
part = WeakSymbolRef.Part.Bank;
}
WeakSymbolRef.Part part = ShiftToPart(reloc.Shift);
SetDataTarget(offset, attr.Length, relOperandOffset, part);
continue;
}
}
// No reloc for this instruction. If it's a relative branch we need
// to do the usual stuff, but if it's a PEA we want to treat it like
// an immediate value. The safest thing to do is blacklist PEA and
// let everything else proceed like it does without reloc data enabled.
OpDef op = mProject.CpuDef.GetOpDef(mProject.FileData[offset]);
if (op == OpDef.OpPEA_StackAbs) {
//Debug.WriteLine("NoPEA +" + offset.ToString("x6"));
continue;
}
}
int operandOffset = attr.OperandOffset;
if (operandOffset >= 0) {
// This is an offset reference: a branch or data access instruction whose
// target is inside the file. Create a FormatDescriptor for it, and
// generate a label at the target if one is not already present.
// This is an offset reference: a branch or data access instruction
// whose target is inside the file. Create a FormatDescriptor for it,
// and generate a label at the target if one is not already present.
SetDataTarget(offset, attr.Length, operandOffset, WeakSymbolRef.Part.Low);
}
@ -237,10 +243,43 @@ namespace SourceGen {
// There shouldn't be any data items inside other data items, so we
// can just skip forward.
offset += mAnattribs[offset].DataDescriptor.Length - 1;
} else if (mAnalysisParams.UseRelocData &&
!attr.IsInstruction && !attr.IsData && !attr.IsInlineData &&
mProject.RelocList.TryGetValue(offset,
out DisasmProject.RelocData reloc)) {
// Byte is unformatted, but there's relocation data here. If the full
// range of bytes is unformatted, create a symbolic reference.
bool allClear = true;
for (int i = 1; i < reloc.Width; i++) {
if (mAnattribs[offset + i].DataDescriptor != null) {
allClear = false;
break;
}
}
if (allClear) {
int operandOffset = mProject.AddrMap.AddressToOffset(offset, reloc.Value);
if (operandOffset >= 0) {
//Debug.WriteLine("DREL +" + offset.ToString("x6") + " val=" +
// reloc.Value.ToString("x6") +
// " opOff=" + operandOffset.ToString("x6"));
SetDataTarget(offset, reloc.Width, operandOffset,
ShiftToPart(reloc.Shift));
}
}
}
}
}
private static WeakSymbolRef.Part ShiftToPart(int shift) {
if (shift == -16) {
return WeakSymbolRef.Part.Bank;
} else if (shift == -8) {
return WeakSymbolRef.Part.High;
} else {
return WeakSymbolRef.Part.Low;
}
}
/// <summary>
/// Extracts the operand offset from a data item. Only useful for numeric/Address
/// and numeric/Symbol.

View File

@ -61,7 +61,7 @@ namespace SourceGen {
DefaultTextScanMode = TextScanMode.LowHighAscii;
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
SeekNearbyTargets = true;
UseRelocData = true;
UseRelocData = false;
SmartPlpHandling = true;
}
public AnalysisParameters(AnalysisParameters src) {

View File

@ -131,7 +131,7 @@ limitations under the License.
<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}: 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_OmfSegHdrCommentFmt">Segment {0:D2}: {3} {1,-9} Name='{2}', Length={4}</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>

View File

@ -299,6 +299,7 @@ namespace SourceGen.Tools.Omf {
ChangeSet cs = new ChangeSet(mSegmentMap.Count * 2);
AddHeaderComment(proj, cs);
UndoableChange uc;
// Load the segments, and add entries to the project.
int bufOffset = 0;
@ -327,7 +328,7 @@ namespace SourceGen.Tools.Omf {
// 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,
uc = UndoableChange.CreateLongCommentChange(bufOffset, null,
new MultiLineComment(segCmt));
cs.Add(uc);
@ -343,11 +344,19 @@ namespace SourceGen.Tools.Omf {
}
proj.PrepForNew(data, "new_proj");
proj.ApplyChanges(cs, false, out _);
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in mRelocData) {
proj.RelocList.Add(kvp.Key, kvp.Value);
}
// Enable "use reloc" in the analysis parameters.
ProjectProperties newProps = new ProjectProperties(proj.ProjectProps);
newProps.AnalysisParams.UseRelocData = true;
uc = UndoableChange.CreateProjectPropertiesChange(proj.ProjectProps, newProps);
cs.Add(uc);
Debug.WriteLine("Applying " + cs.Count + " changes");
proj.ApplyChanges(cs, false, out _);
mLoadedData = data;
mNewProject = proj;
return true;
@ -365,7 +374,7 @@ namespace SourceGen.Tools.Omf {
}
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));
mFormatter.FormatAddress(ent.Address, true), ent.Segment.Length);
sb.AppendLine(segCmt);
}