1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-07-06 00:28:58 +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:
Andy McFadden 2020-07-02 17:10:05 -07:00
parent 190f68d1f8
commit 327ad4fbbc
7 changed files with 86 additions and 10 deletions

View File

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

View File

@ -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;
}

View File

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

View File

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

View File

@ -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);

View File

@ -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}"

View File

@ -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() {