mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-08 20:30:47 +00:00
Store reduced OMF relocation data in project file
A "cooked" form of the relocation data is added to the project, for use during data analysis. Also, changed the data grids in the segment viewer to allow multi- select, so users can copy & paste the contents.
This commit is contained in:
parent
190f68d1f8
commit
327ad4fbbc
@ -119,6 +119,28 @@ namespace SourceGen {
|
||||
/// </summary>
|
||||
public ProjectProperties ProjectProps { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// "Cooked" form of relocation data (e.g. OmfReloc). This does not contain the file
|
||||
/// offset, as that's expected to be used as the dictionary key.
|
||||
///
|
||||
/// Will be null unless the project was generated from a relocatable source.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RelocData {
|
||||
public byte Width; // width of area written by relocator
|
||||
public byte Shift; // amount to shift the value
|
||||
public int Value; // value used (unshifted, full width)
|
||||
|
||||
public RelocData() { } // for deserialization
|
||||
|
||||
public RelocData(byte width, byte shift, int value) {
|
||||
Width = width;
|
||||
Shift = shift;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
public Dictionary<int, RelocData> RelocList { get; set; }
|
||||
|
||||
#endregion // data to save & restore
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ namespace SourceGen {
|
||||
// ignore stuff that's in one side but not the other. However, if we're opening a
|
||||
// newer file in an older program, it's worth letting the user know that some stuff
|
||||
// may get lost as soon as they save the file.
|
||||
public const int CONTENT_VERSION = 3;
|
||||
public const int CONTENT_VERSION = 4;
|
||||
|
||||
private static readonly bool ADD_CRLF = true;
|
||||
|
||||
@ -417,6 +417,7 @@ namespace SourceGen {
|
||||
public List<SerVisualization> Visualizations { get; set; }
|
||||
public List<SerVisBitmapAnimation> VisualizationAnimations { get; set; }
|
||||
public Dictionary<string, SerVisualizationSet> VisualizationSets { get; set; }
|
||||
public Dictionary<string, DisasmProject.RelocData> RelocList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Serializes a DisasmProject into an augmented JSON string.
|
||||
@ -525,6 +526,15 @@ namespace SourceGen {
|
||||
|
||||
spf.ProjectProps = new SerProjectProperties(proj.ProjectProps);
|
||||
|
||||
if (proj.RelocList != null) {
|
||||
// The objects can serialize directly, but the Dictionary key can't be an int.
|
||||
spf.RelocList =
|
||||
new Dictionary<string, DisasmProject.RelocData>(proj.RelocList.Count);
|
||||
foreach (KeyValuePair<int, DisasmProject.RelocData> kvp in proj.RelocList) {
|
||||
spf.RelocList.Add(kvp.Key.ToString(), kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
JavaScriptSerializer ser = new JavaScriptSerializer();
|
||||
string cereal = ser.Serialize(spf);
|
||||
sb.Append(cereal);
|
||||
@ -832,6 +842,19 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
// Deserialize relocation data. This was added in v1.7.
|
||||
if (spf.RelocList != null) {
|
||||
proj.RelocList = new Dictionary<int, DisasmProject.RelocData>();
|
||||
foreach (KeyValuePair<string, DisasmProject.RelocData> kvp in spf.RelocList) {
|
||||
if (!ParseValidateKey(kvp.Key, spf.FileDataLength,
|
||||
Res.Strings.PROJECT_FIELD_RELOC_DATA, report, out int intKey)) {
|
||||
continue;
|
||||
}
|
||||
proj.RelocList.Add(intKey, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,7 @@ limitations under the License.
|
||||
<system:String x:Key="str_ProjectFieldLvTable">local variable table</system:String>
|
||||
<system:String x:Key="str_ProjectFieldNote">note</system:String>
|
||||
<system:String x:Key="str_ProjectFieldOperandFormat">operand format</system:String>
|
||||
<system:String x:Key="str_ProjectFieldRelocData">reloc data</system:String>
|
||||
<system:String x:Key="str_ProjectFieldStatusFlags">status flag override</system:String>
|
||||
<system:String x:Key="str_ProjectFieldTypeHint">type hint</system:String>
|
||||
<system:String x:Key="str_ProjectFieldUserLabel">user-defined label</system:String>
|
||||
|
@ -291,6 +291,8 @@ namespace SourceGen.Res {
|
||||
(string)Application.Current.FindResource("str_ProjectFieldNote");
|
||||
public static string PROJECT_FIELD_OPERAND_FORMAT =
|
||||
(string)Application.Current.FindResource("str_ProjectFieldOperandFormat");
|
||||
public static string PROJECT_FIELD_RELOC_DATA =
|
||||
(string)Application.Current.FindResource("str_ProjectFieldRelocData");
|
||||
public static string PROJECT_FIELD_STATUS_FLAGS =
|
||||
(string)Application.Current.FindResource("str_ProjectFieldStatusFlags");
|
||||
public static string PROJECT_FIELD_TYPE_HINT =
|
||||
|
@ -48,11 +48,15 @@ namespace SourceGen.Tools.Omf {
|
||||
}
|
||||
private List<SegmentMapEntry> mSegmentMap;
|
||||
|
||||
private Dictionary<int, DisasmProject.RelocData> mRelocData =
|
||||
new Dictionary<int, DisasmProject.RelocData>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="omfFile">OMF file to load.</param>
|
||||
/// <param name="formatter">Text formatter.</param>
|
||||
public Loader(OmfFile omfFile, Formatter formatter) {
|
||||
Debug.Assert(omfFile.OmfFileKind == OmfFile.FileKind.Load);
|
||||
|
||||
@ -83,7 +87,7 @@ namespace SourceGen.Tools.Omf {
|
||||
Debug.Assert(i == ent.Segment.SegNum);
|
||||
}
|
||||
|
||||
if (!GenerateOutput()) {
|
||||
if (!GenerateDataAndProject()) {
|
||||
mSegmentMap = null;
|
||||
return false;
|
||||
}
|
||||
@ -258,7 +262,7 @@ namespace SourceGen.Tools.Omf {
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool GenerateOutput() {
|
||||
private bool GenerateDataAndProject() {
|
||||
// Sum up the segment lengths to get the total project size.
|
||||
int totalLen = 0;
|
||||
foreach (SegmentMapEntry ent in mSegmentMap) {
|
||||
@ -339,7 +343,8 @@ namespace SourceGen.Tools.Omf {
|
||||
}
|
||||
|
||||
proj.PrepForNew(data, "new_proj");
|
||||
proj.ApplyChanges(cs, false, out RangeSet unused);
|
||||
proj.ApplyChanges(cs, false, out _);
|
||||
proj.RelocList = mRelocData;
|
||||
|
||||
mLoadedData = data;
|
||||
mNewProject = proj;
|
||||
@ -401,6 +406,10 @@ namespace SourceGen.Tools.Omf {
|
||||
}
|
||||
}
|
||||
|
||||
if (omfRel.Shift < -32 || omfRel.Shift > 32) {
|
||||
Debug.WriteLine("Invalid reloc shift " + omfRel.Shift);
|
||||
return false;
|
||||
}
|
||||
if (omfRel.Shift < 0) {
|
||||
relocAddr >>= -omfRel.Shift;
|
||||
} else if (omfRel.Shift > 0) {
|
||||
@ -430,6 +439,9 @@ namespace SourceGen.Tools.Omf {
|
||||
Debug.WriteLine("Invalid reloc width " + omfRel.Width);
|
||||
return false;
|
||||
}
|
||||
|
||||
mRelocData.Add(bufOffset + omfRel.Offset,
|
||||
new DisasmProject.RelocData((byte)omfRel.Width, (byte)omfRel.Shift, relocAddr));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -439,10 +451,17 @@ namespace SourceGen.Tools.Omf {
|
||||
/// Edits the data file, essentially putting the jump table entries into the
|
||||
/// "loaded" state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We don't use ent.Segment.Relocs, as that is expected to be empty.
|
||||
/// </remarks>
|
||||
private bool RelocJumpTable(SegmentMapEntry ent, byte[] data, int bufOffset,
|
||||
ChangeSet cs) {
|
||||
const int ENTRY_LEN = 14;
|
||||
|
||||
if (ent.Segment.Relocs.Count != 0) {
|
||||
Debug.WriteLine("WEIRD: jump table has reloc data?");
|
||||
}
|
||||
|
||||
byte[] srcData = ent.Segment.GetConstData();
|
||||
Array.Copy(srcData, 0, data, bufOffset, srcData.Length);
|
||||
|
||||
@ -458,7 +477,7 @@ namespace SourceGen.Tools.Omf {
|
||||
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 userId = RawData.GetWord(data, bufOffset + i, 2, false);
|
||||
int fileNum = RawData.GetWord(data, bufOffset + i + 2, 2, false);
|
||||
|
||||
if (fileNum == 0) {
|
||||
@ -476,7 +495,7 @@ namespace SourceGen.Tools.Omf {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: segment ends right after FileNum, so don't try to read further
|
||||
// Note: segment might end right after FileNum, so don't try to read further
|
||||
// until we've confirmed that FileNum != 0.
|
||||
|
||||
int segNum = RawData.GetWord(data, bufOffset + i + 4, 2, false);
|
||||
|
@ -31,6 +31,7 @@ limitations under the License.
|
||||
|
||||
<system:String x:Key="str_FileOffsetLenFmt">File offset {0}, length {1} ({2})</system:String>
|
||||
<system:String x:Key="str_RecordHeaderFmt">Records ({0}):</system:String>
|
||||
<system:String x:Key="str_RelocHeaderFmt">Relocation dictionary ({0}):</system:String>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid Margin="8">
|
||||
@ -59,7 +60,7 @@ limitations under the License.
|
||||
HeadersVisibility="Column"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserSortColumns="False"
|
||||
SelectionMode="Single">
|
||||
SelectionMode="Extended">
|
||||
<DataGrid.Resources>
|
||||
<!-- make the no-focus color the same as the in-focus color -->
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
|
||||
@ -86,7 +87,7 @@ limitations under the License.
|
||||
HeadersVisibility="Column"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserSortColumns="False"
|
||||
SelectionMode="Single">
|
||||
SelectionMode="Extended">
|
||||
<DataGrid.Resources>
|
||||
<!-- make the no-focus color the same as the in-focus color -->
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
|
||||
@ -101,7 +102,7 @@ limitations under the License.
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<TextBlock Grid.Row="5" Text="Relocation dictionary:" Margin="0,8,0,0"
|
||||
<TextBlock Grid.Row="5" Text="{Binding RelocHeaderStr, FallbackValue=Relocation dictionary:}" Margin="0,8,0,0"
|
||||
Visibility="{Binding HasRelocs, Converter={StaticResource BoolToVis}}"/>
|
||||
<DataGrid Name="relocList" Grid.Row="6" Height="145" Margin="0,8,0,0"
|
||||
Visibility="{Binding HasRelocs, Converter={StaticResource BoolToVis}}"
|
||||
@ -115,7 +116,7 @@ limitations under the License.
|
||||
HeadersVisibility="Column"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserSortColumns="False"
|
||||
SelectionMode="Single">
|
||||
SelectionMode="Extended">
|
||||
<DataGrid.Resources>
|
||||
<!-- make the no-focus color the same as the in-focus color -->
|
||||
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
|
||||
|
@ -48,6 +48,12 @@ namespace SourceGen.Tools.Omf.WpfGui {
|
||||
set { mRecordHeaderStr = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
private string mRelocHeaderStr;
|
||||
public string RelocHeaderStr {
|
||||
get { return mRelocHeaderStr; }
|
||||
set { mRelocHeaderStr = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
public class HeaderItem {
|
||||
public string Name { get; private set; }
|
||||
public string Value { get; private set; }
|
||||
@ -141,6 +147,8 @@ namespace SourceGen.Tools.Omf.WpfGui {
|
||||
|
||||
fmt = (string)FindResource("str_RecordHeaderFmt");
|
||||
RecordHeaderStr = string.Format(fmt, RecordItems.Count);
|
||||
fmt = (string)FindResource("str_RelocHeaderFmt");
|
||||
RelocHeaderStr = string.Format(fmt, RelocItems.Count);
|
||||
}
|
||||
|
||||
private void GenerateHeaderItems() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user