mirror of
https://github.com/fadden/6502bench.git
synced 2024-12-23 16:32:44 +00:00
Add offset to PlSymbol
It's useful for extension scripts to be able to get the file offset of symbols in non-addressable regions. One example of this is CHR ROM data for an NES cartridge. However, we were getting the offset by doing an address-to-offset mapping on the plugin side, which by definition doesn't work for non-addressable memory. So we now add the offset to PlSymbol objects for user labels and address region pre-labels. The NES visualizer has been updated to use the new field. Also, fixed a bogus complaint about bank overruns for non-addressable regions.
This commit is contained in:
parent
1258dd89cb
commit
6e9ff395d2
@ -81,6 +81,11 @@ namespace PluginCommon {
|
||||
/// </summary>
|
||||
public string Tag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Symbol offset, for user labels and pre-labels; -1 otherwise.
|
||||
/// </summary>
|
||||
public int Offset { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Nullary constructor, for deserialization.
|
||||
@ -92,14 +97,20 @@ namespace PluginCommon {
|
||||
/// </summary>
|
||||
/// <param name="label">Symbol label.</param>
|
||||
/// <param name="value">Symbol value.</param>
|
||||
/// <param name="width">Width, for platform/project symbols.</param>
|
||||
/// <param name="source">Symbol source.</param>
|
||||
/// <param name="type">Symbol type.</param>
|
||||
/// <param name="tag">Symbol group tag.</param>
|
||||
public PlSymbol(string label, int value, int width, Source source, Type type, string tag) {
|
||||
/// <param name="offset">Offset, for user labels and pre-labels; -1 otherwise.</param>
|
||||
public PlSymbol(string label, int value, int width, Source source, Type type, string tag,
|
||||
int offset) {
|
||||
Label = label;
|
||||
Value = value;
|
||||
Width = width;
|
||||
SymbolSource = source;
|
||||
SymbolType = type;
|
||||
Tag = tag;
|
||||
Offset = offset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -407,6 +407,10 @@ namespace SourceGen.AsmGen {
|
||||
if (attr.Length != instrBytes) {
|
||||
// This instruction has another instruction inside it. Throw out what we
|
||||
// computed and just output as bytes.
|
||||
// TODO: in some odd situations we can split something that doesn't need
|
||||
// to be split (see note at end of #107). Working around the problem at
|
||||
// this stage is a little awkward because I think we need to check for the
|
||||
// presence of labels on one or more later lines.
|
||||
gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
|
||||
} else if (isPcRelBankWrap && gen.Quirks.NoPcRelBankWrap) {
|
||||
// Some assemblers have trouble generating PC-relative operands that wrap
|
||||
|
@ -759,7 +759,7 @@ namespace SourceGen {
|
||||
IEnumerator<AddressMap.AddressChange> addrIter = AddrMap.AddressChangeIterator;
|
||||
while (addrIter.MoveNext()) {
|
||||
AddressMap.AddressChange change = addrIter.Current;
|
||||
if (!change.IsStart) {
|
||||
if (!change.IsStart || change.Address == Address.NON_ADDR) {
|
||||
continue;
|
||||
}
|
||||
AddressMap.AddressRegion region = change.Region;
|
||||
@ -1552,46 +1552,7 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
// Create a mapping from label (which must be unique) to file offset. This
|
||||
// is different from UserLabels (which only has user-created labels, and is
|
||||
// sorted by offset) and SymbolTable (which has constants and platform symbols,
|
||||
// and uses the address as the value rather than the offset).
|
||||
SortedList<string, int> labelList = new SortedList<string, int>(mFileData.Length,
|
||||
Asm65.Label.LABEL_COMPARER);
|
||||
for (int offset = 0; offset < mAnattribs.Length; offset++) {
|
||||
Anattrib attr = mAnattribs[offset];
|
||||
if (attr.Symbol != null) {
|
||||
try {
|
||||
labelList.Add(attr.Symbol.Label, offset);
|
||||
} catch (ArgumentException ex) {
|
||||
// Duplicate UserLabel entries are stripped when projects are loaded, but
|
||||
// it might be possible to cause this by hiding/unhiding a label (e.g.
|
||||
// using a code start tag to place it in the middle of an instruction).
|
||||
// Just ignore the duplicate.
|
||||
Debug.WriteLine("Xref ignoring duplicate label '" + attr.Symbol.Label +
|
||||
"': " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add all valid address region pre-labels. Duplicates of user labels will be
|
||||
// rejected. Note the references will appear on the line for the next file offset,
|
||||
// not the pre-label itself, because we need to associate it with a file offset.
|
||||
IEnumerator<AddressMap.AddressChange> addrIter = AddrMap.AddressChangeIterator;
|
||||
while (addrIter.MoveNext()) {
|
||||
AddressMap.AddressChange change = addrIter.Current;
|
||||
if (!change.IsStart) {
|
||||
continue;
|
||||
}
|
||||
if (change.Region.HasValidPreLabel) {
|
||||
try {
|
||||
labelList.Add(change.Region.PreLabel, change.Region.Offset);
|
||||
} catch (ArgumentException ex) {
|
||||
Debug.WriteLine("Xref ignoring pre-label duplicate '" +
|
||||
change.Region.PreLabel + "': " + ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
SortedList<string, int> labelList = CreateLabelToOffsetMap();
|
||||
|
||||
// No particular reason to do this here, but it's convenient.
|
||||
ByteCounts.Reset();
|
||||
@ -1802,6 +1763,54 @@ namespace SourceGen {
|
||||
return xset; // will be null if not found
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mapping from label (which must be unique) to file offset. This
|
||||
/// is different from UserLabels (which only has user-created labels, and is
|
||||
/// sorted by offset) and SymbolTable (which has constants and platform symbols,
|
||||
/// and uses the address as the value rather than the offset).
|
||||
///
|
||||
/// We use Anattribs to ensure that we only include visible labels.
|
||||
/// </summary>
|
||||
private SortedList<string, int> CreateLabelToOffsetMap() {
|
||||
SortedList<string, int> labelList = new SortedList<string, int>(mFileData.Length,
|
||||
Asm65.Label.LABEL_COMPARER);
|
||||
for (int offset = 0; offset < mAnattribs.Length; offset++) {
|
||||
Anattrib attr = mAnattribs[offset];
|
||||
if (attr.Symbol != null) {
|
||||
try {
|
||||
labelList.Add(attr.Symbol.Label, offset);
|
||||
} catch (ArgumentException ex) {
|
||||
// Duplicate UserLabel entries are stripped when projects are loaded, but
|
||||
// it might be possible to cause this by hiding/unhiding a label (e.g.
|
||||
// using a code start tag to place it in the middle of an instruction).
|
||||
// Just ignore the duplicate.
|
||||
Debug.WriteLine("Xref ignoring duplicate label '" + attr.Symbol.Label +
|
||||
"': " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add all valid address region pre-labels. Duplicates of user labels will be
|
||||
// rejected. Note the references will appear on the line for the next file offset,
|
||||
// not the pre-label itself, because we need to associate it with a file offset.
|
||||
IEnumerator<AddressMap.AddressChange> addrIter = AddrMap.AddressChangeIterator;
|
||||
while (addrIter.MoveNext()) {
|
||||
AddressMap.AddressChange change = addrIter.Current;
|
||||
if (!change.IsStart) {
|
||||
continue;
|
||||
}
|
||||
if (change.Region.HasValidPreLabel) {
|
||||
try {
|
||||
labelList.Add(change.Region.PreLabel, change.Region.Offset);
|
||||
} catch (ArgumentException ex) {
|
||||
Debug.WriteLine("Xref ignoring pre-label duplicate '" +
|
||||
change.Region.PreLabel + "': " + ex.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return labelList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces generic auto-labels with fancier versions generated from xrefs.
|
||||
/// </summary>
|
||||
|
@ -3177,7 +3177,7 @@ namespace SourceGen {
|
||||
public void GoToLabel(Symbol sym) {
|
||||
int offset = mProject.FindLabelOffsetByName(sym.Label);
|
||||
if (offset >= 0) {
|
||||
// TODO(someday): jump to correct line for address region pre-labels
|
||||
// TODO(someday): jump to symbol line, not arstart, for address region pre-labels
|
||||
GoToLocation(new NavStack.Location(offset, 0, NavStack.GoToMode.JumpToCodeData),
|
||||
true);
|
||||
} else {
|
||||
|
@ -115,8 +115,7 @@ namespace RuntimeData.Nintendo {
|
||||
|
||||
foreach (PlSymbol sym in plSyms) {
|
||||
if (sym.Label == CHR_ROM) {
|
||||
int addr = sym.Value;
|
||||
mChrRomOffset = mAddrTrans.AddressToOffset(0, addr);
|
||||
mChrRomOffset = sym.Offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -327,18 +327,51 @@ namespace SourceGen.Sandbox {
|
||||
/// <summary>
|
||||
/// Gathers a list of symbols from the project's symbol table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Remember that we need to set this up before code analysis runs, so many of the
|
||||
/// secondary data structures (like Anattribs) won't be available.
|
||||
/// </remarks>
|
||||
private List<PlSymbol> GeneratePlSymbolList() {
|
||||
List<PlSymbol> plSymbols = new List<PlSymbol>();
|
||||
SymbolTable symTab = mProject.SymbolTable;
|
||||
|
||||
// UserLabels maps offset to Symbol. Create the reverse mapping.
|
||||
Dictionary<Symbol, int> symbolOffsets =
|
||||
new Dictionary<Symbol, int>(mProject.UserLabels.Count);
|
||||
foreach (KeyValuePair<int, Symbol> kvp in mProject.UserLabels) {
|
||||
symbolOffsets[kvp.Value] = kvp.Key;
|
||||
}
|
||||
|
||||
// Add in the address region pre-labels.
|
||||
IEnumerator<AddressMap.AddressChange> addrIter = mProject.AddrMap.AddressChangeIterator;
|
||||
while (addrIter.MoveNext()) {
|
||||
AddressMap.AddressChange change = addrIter.Current;
|
||||
if (!change.IsStart) {
|
||||
continue;
|
||||
}
|
||||
if (change.Region.HasValidPreLabel) {
|
||||
Symbol newSym = new Symbol(change.Region.PreLabel,
|
||||
change.Region.PreLabelAddress, Symbol.Source.AddrPreLabel,
|
||||
Symbol.Type.ExternalAddr, Symbol.LabelAnnotation.None);
|
||||
symbolOffsets[newSym] = change.Region.Offset;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Symbol sym in symTab) {
|
||||
PlSymbol.Source plsSource;
|
||||
int symOff, offset = -1;
|
||||
switch (sym.SymbolSource) {
|
||||
case Symbol.Source.User:
|
||||
plsSource = PlSymbol.Source.User;
|
||||
if (symbolOffsets.TryGetValue(sym, out symOff)) {
|
||||
offset = symOff;
|
||||
}
|
||||
break;
|
||||
case Symbol.Source.AddrPreLabel:
|
||||
plsSource = PlSymbol.Source.AddrPreLabel;
|
||||
if (symbolOffsets.TryGetValue(sym, out symOff)) {
|
||||
offset = symOff;
|
||||
}
|
||||
break;
|
||||
case Symbol.Source.Project:
|
||||
plsSource = PlSymbol.Source.Project;
|
||||
@ -381,8 +414,8 @@ namespace SourceGen.Sandbox {
|
||||
tag = defSym.Tag;
|
||||
}
|
||||
|
||||
|
||||
plSymbols.Add(new PlSymbol(sym.Label, sym.Value, width, plsSource, plsType, tag));
|
||||
plSymbols.Add(new PlSymbol(sym.Label, sym.Value, width, plsSource, plsType, tag,
|
||||
offset));
|
||||
}
|
||||
|
||||
return plSymbols;
|
||||
|
Loading…
Reference in New Issue
Block a user