From b97f7ca3d847df65c20935f154c295d8fbb3ad54 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Thu, 11 Oct 2018 16:48:55 -0700 Subject: [PATCH] Fix add-label shortcut for adjusted operands When you edit the operand of an instruction that targets an in-file address, you're given the opportunity to specify a shortcut that applies the symbol to the instruction's target address in addition to or instead of defining a weak symbol reference on the instruction being edited. This didn't work right for operands with adjustments, e.g. the store instructions in self-modifying code. It put the label at the unadjusted offset, which does nothing useful. We now correctly back up to the start of the instruction or multi- byte data area. --- SourceGen/AppForms/EditOperand.cs | 6 ++++-- SourceGen/DataAnalysis.cs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/SourceGen/AppForms/EditOperand.cs b/SourceGen/AppForms/EditOperand.cs index 4f2a4de..7214b65 100644 --- a/SourceGen/AppForms/EditOperand.cs +++ b/SourceGen/AppForms/EditOperand.cs @@ -391,11 +391,13 @@ namespace SourceGen.AppForms { if (mAttr.OperandOffset >= 0) { // Operand target is inside the file. Does the target offset already have a label? - bool hasLabel = mProject.UserLabels.ContainsKey(mAttr.OperandOffset); + int targetOffset = + DataAnalysis.GetBaseOperandOffset(mProject, mAttr.OperandOffset); + bool hasLabel = mProject.UserLabels.ContainsKey(targetOffset); labelInsteadRadioButton.Enabled = operandAndLabelRadioButton.Enabled = !hasLabel; operandAndProjRadioButton.Enabled = false; - ShortcutArg = mAttr.OperandOffset; + ShortcutArg = targetOffset; } else if (mAttr.OperandAddress >= 0) { // Operand target is outside the file. labelInsteadRadioButton.Enabled = operandAndLabelRadioButton.Enabled = false; diff --git a/SourceGen/DataAnalysis.cs b/SourceGen/DataAnalysis.cs index d924803..71f43d7 100644 --- a/SourceGen/DataAnalysis.cs +++ b/SourceGen/DataAnalysis.cs @@ -229,6 +229,25 @@ namespace SourceGen { return operandOffset; } + /// + /// Returns the "base" operand offset. If the byte at the specified offset is not the + /// start of a code/data/inline-data item, walk backward until the start is found. + /// + /// Project reference. + /// Start offset. + /// + public static int GetBaseOperandOffset(DisasmProject proj, int offset) { + Debug.Assert(offset >= 0 && offset < proj.FileDataLength); + while (!proj.GetAnattrib(offset).IsStart) { + offset--; + + // Should not be possible to walk off the top of the list, since we're in + // the middle of something. + Debug.Assert(offset >= 0); + } + return offset; + } + /// /// Creates a FormatDescriptor in the Anattrib array at srcOffset that links to /// targetOffset, or a nearby label. If targetOffset doesn't have a useful label,