mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-21 12:29:00 +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:
parent
a6700e9062
commit
0fa77cba75
@ -163,10 +163,11 @@ namespace SourceGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for a relocation. It'll be at offset+1 because it's on the operand,
|
// Check for a relocation. It'll be at offset+1 because it's on the operand,
|
||||||
// not the opcode byte.
|
// not the opcode byte. (Make sure to check the length, or an RTS followed
|
||||||
if (mAnalysisParams.UseRelocData && mProject.RelocList.TryGetValue(offset + 1,
|
// by relocated data will freak out.)
|
||||||
out DisasmProject.RelocData reloc)) {
|
if (mAnalysisParams.UseRelocData) {
|
||||||
if (reloc.Value != attr.OperandAddress) {
|
if (attr.Length > 1 && mProject.RelocList.TryGetValue(offset + 1,
|
||||||
|
out DisasmProject.RelocData reloc)) {
|
||||||
// The relocation address differs from what the analyzer came up
|
// The relocation address differs from what the analyzer came up
|
||||||
// with. This may be because of incorrect assumptions about the
|
// with. This may be because of incorrect assumptions about the
|
||||||
// bank (assuming B==K) or because the partial address refers to
|
// 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.
|
// address is different, attr.OperandOffset will also be different.
|
||||||
int relOperandOffset = mProject.AddrMap.AddressToOffset(offset,
|
int relOperandOffset = mProject.AddrMap.AddressToOffset(offset,
|
||||||
reloc.Value);
|
reloc.Value);
|
||||||
if (relOperandOffset >= 0 && relOperandOffset != attr.OperandOffset) {
|
if (relOperandOffset >= 0) {
|
||||||
// Determined a different offset. Use that instead.
|
// Determined a different offset. Use that instead.
|
||||||
//Debug.WriteLine("REL +" + offset.ToString("x6") + " " +
|
//Debug.WriteLine("REL +" + offset.ToString("x6") + " " +
|
||||||
// reloc.Value.ToString("x6") + " vs. " +
|
// reloc.Value.ToString("x6") + " vs. " +
|
||||||
// attr.OperandAddress.ToString("x6"));
|
// attr.OperandAddress.ToString("x6"));
|
||||||
WeakSymbolRef.Part part = WeakSymbolRef.Part.Low;
|
WeakSymbolRef.Part part = ShiftToPart(reloc.Shift);
|
||||||
if (reloc.Shift == -8) {
|
|
||||||
part = WeakSymbolRef.Part.High;
|
|
||||||
} else if (reloc.Shift == -16) {
|
|
||||||
part = WeakSymbolRef.Part.Bank;
|
|
||||||
}
|
|
||||||
SetDataTarget(offset, attr.Length, relOperandOffset, part);
|
SetDataTarget(offset, attr.Length, relOperandOffset, part);
|
||||||
continue;
|
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;
|
int operandOffset = attr.OperandOffset;
|
||||||
if (operandOffset >= 0) {
|
if (operandOffset >= 0) {
|
||||||
// This is an offset reference: a branch or data access instruction whose
|
// This is an offset reference: a branch or data access instruction
|
||||||
// target is inside the file. Create a FormatDescriptor for it, and
|
// whose target is inside the file. Create a FormatDescriptor for it,
|
||||||
// generate a label at the target if one is not already present.
|
// and generate a label at the target if one is not already present.
|
||||||
SetDataTarget(offset, attr.Length, operandOffset, WeakSymbolRef.Part.Low);
|
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
|
// There shouldn't be any data items inside other data items, so we
|
||||||
// can just skip forward.
|
// can just skip forward.
|
||||||
offset += mAnattribs[offset].DataDescriptor.Length - 1;
|
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>
|
/// <summary>
|
||||||
/// Extracts the operand offset from a data item. Only useful for numeric/Address
|
/// Extracts the operand offset from a data item. Only useful for numeric/Address
|
||||||
/// and numeric/Symbol.
|
/// and numeric/Symbol.
|
||||||
|
@ -61,7 +61,7 @@ namespace SourceGen {
|
|||||||
DefaultTextScanMode = TextScanMode.LowHighAscii;
|
DefaultTextScanMode = TextScanMode.LowHighAscii;
|
||||||
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
|
MinCharsForString = DataAnalysis.DEFAULT_MIN_STRING_LENGTH;
|
||||||
SeekNearbyTargets = true;
|
SeekNearbyTargets = true;
|
||||||
UseRelocData = true;
|
UseRelocData = false;
|
||||||
SmartPlpHandling = true;
|
SmartPlpHandling = true;
|
||||||
}
|
}
|
||||||
public AnalysisParameters(AnalysisParameters src) {
|
public AnalysisParameters(AnalysisParameters src) {
|
||||||
|
@ -131,7 +131,7 @@ limitations under the License.
|
|||||||
<system:String x:Key="str_NoFilesAvailable">no files available</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_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_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_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_OpenDataDoesntExist">The file doesn't exist.</system:String>
|
||||||
<system:String x:Key="str_OpenDataEmpty">File is empty</system:String>
|
<system:String x:Key="str_OpenDataEmpty">File is empty</system:String>
|
||||||
|
@ -299,6 +299,7 @@ namespace SourceGen.Tools.Omf {
|
|||||||
|
|
||||||
ChangeSet cs = new ChangeSet(mSegmentMap.Count * 2);
|
ChangeSet cs = new ChangeSet(mSegmentMap.Count * 2);
|
||||||
AddHeaderComment(proj, cs);
|
AddHeaderComment(proj, cs);
|
||||||
|
UndoableChange uc;
|
||||||
|
|
||||||
// Load the segments, and add entries to the project.
|
// Load the segments, and add entries to the project.
|
||||||
int bufOffset = 0;
|
int bufOffset = 0;
|
||||||
@ -327,7 +328,7 @@ namespace SourceGen.Tools.Omf {
|
|||||||
// Add a comment identifying the segment and its attributes.
|
// Add a comment identifying the segment and its attributes.
|
||||||
string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT,
|
string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT,
|
||||||
ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.Attrs, ent.Segment.SegName);
|
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));
|
new MultiLineComment(segCmt));
|
||||||
cs.Add(uc);
|
cs.Add(uc);
|
||||||
|
|
||||||
@ -343,11 +344,19 @@ namespace SourceGen.Tools.Omf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proj.PrepForNew(data, "new_proj");
|
proj.PrepForNew(data, "new_proj");
|
||||||
proj.ApplyChanges(cs, false, out _);
|
|
||||||
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in mRelocData) {
|
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in mRelocData) {
|
||||||
proj.RelocList.Add(kvp.Key, kvp.Value);
|
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;
|
mLoadedData = data;
|
||||||
mNewProject = proj;
|
mNewProject = proj;
|
||||||
return true;
|
return true;
|
||||||
@ -365,7 +374,7 @@ namespace SourceGen.Tools.Omf {
|
|||||||
}
|
}
|
||||||
string segCmt = string.Format(Res.Strings.OMF_SEG_HDR_COMMENT_FMT,
|
string segCmt = string.Format(Res.Strings.OMF_SEG_HDR_COMMENT_FMT,
|
||||||
ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.SegName,
|
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);
|
sb.AppendLine(segCmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user