diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs
index 2d79ade..1b22267 100644
--- a/SourceGen/DisasmProject.cs
+++ b/SourceGen/DisasmProject.cs
@@ -119,6 +119,28 @@ namespace SourceGen {
///
public ProjectProperties ProjectProps { get; private set; }
+ ///
+ /// "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.
+ ///
+ [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 RelocList { get; set; }
+
#endregion // data to save & restore
diff --git a/SourceGen/ProjectFile.cs b/SourceGen/ProjectFile.cs
index a8a2116..d3c81ee 100644
--- a/SourceGen/ProjectFile.cs
+++ b/SourceGen/ProjectFile.cs
@@ -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 Visualizations { get; set; }
public List VisualizationAnimations { get; set; }
public Dictionary VisualizationSets { get; set; }
+ public Dictionary RelocList { get; set; }
///
/// 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(proj.RelocList.Count);
+ foreach (KeyValuePair 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();
+ foreach (KeyValuePair 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;
}
diff --git a/SourceGen/Res/Strings.xaml b/SourceGen/Res/Strings.xaml
index cb97889..fd4b84c 100644
--- a/SourceGen/Res/Strings.xaml
+++ b/SourceGen/Res/Strings.xaml
@@ -155,6 +155,7 @@ limitations under the License.
local variable table
note
operand format
+ reloc data
status flag override
type hint
user-defined label
diff --git a/SourceGen/Res/Strings.xaml.cs b/SourceGen/Res/Strings.xaml.cs
index 4b80c0d..cd5da68 100644
--- a/SourceGen/Res/Strings.xaml.cs
+++ b/SourceGen/Res/Strings.xaml.cs
@@ -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 =
diff --git a/SourceGen/Tools/Omf/Loader.cs b/SourceGen/Tools/Omf/Loader.cs
index f2d61b2..5efd9e2 100644
--- a/SourceGen/Tools/Omf/Loader.cs
+++ b/SourceGen/Tools/Omf/Loader.cs
@@ -48,11 +48,15 @@ namespace SourceGen.Tools.Omf {
}
private List mSegmentMap;
+ private Dictionary mRelocData =
+ new Dictionary();
+
///
/// Constructor.
///
/// OMF file to load.
+ /// Text formatter.
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.
///
+ ///
+ /// We don't use ent.Segment.Relocs, as that is expected to be empty.
+ ///
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);
diff --git a/SourceGen/Tools/Omf/WpfGui/OmfSegmentViewer.xaml b/SourceGen/Tools/Omf/WpfGui/OmfSegmentViewer.xaml
index e876528..ef31098 100644
--- a/SourceGen/Tools/Omf/WpfGui/OmfSegmentViewer.xaml
+++ b/SourceGen/Tools/Omf/WpfGui/OmfSegmentViewer.xaml
@@ -31,6 +31,7 @@ limitations under the License.
File offset {0}, length {1} ({2})
Records ({0}):
+ Relocation dictionary ({0}):
@@ -59,7 +60,7 @@ limitations under the License.
HeadersVisibility="Column"
CanUserReorderColumns="False"
CanUserSortColumns="False"
- SelectionMode="Single">
+ SelectionMode="Extended">
+ SelectionMode="Extended">
-
+ SelectionMode="Extended">