mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 16:47:43 +08:00
GP-5996 - Version Tracking - Added option for apply function namespace
This commit is contained in:
+6
-6
@@ -261,27 +261,27 @@ public abstract class AbstractGhidraHeadlessIntegrationTest extends AbstractDock
|
||||
*
|
||||
* @param <T> the return type
|
||||
* @param <E> the exception type
|
||||
* @param p the program
|
||||
* @param dobj the program or other domain object
|
||||
* @param s the code to execute
|
||||
* @return the supplier's return value
|
||||
* @see #modifyProgram(Program, ExceptionalCallback)
|
||||
* @see #modifyProgram(Program, ExceptionalFunction)
|
||||
*/
|
||||
public static <T, E extends Exception> T tx(Program p, ExceptionalSupplier<T, E> s) {
|
||||
int txId = p.startTransaction("Test - Function in Transaction");
|
||||
public static <T, E extends Exception> T tx(DomainObject dobj, ExceptionalSupplier<T, E> s) {
|
||||
int txId = dobj.startTransaction("Test - Function in Transaction");
|
||||
boolean commit = true;
|
||||
try {
|
||||
T t = s.get();
|
||||
p.flushEvents();
|
||||
dobj.flushEvents();
|
||||
waitForSwing();
|
||||
return t;
|
||||
}
|
||||
catch (Exception e) {
|
||||
commit = false;
|
||||
failWithException("Exception modifying program '" + p.getName() + "'", e);
|
||||
failWithException("Exception modifying program '" + dobj.getName() + "'", e);
|
||||
}
|
||||
finally {
|
||||
p.endTransaction(txId, commit);
|
||||
dobj.endTransaction(txId, commit);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 57 KiB |
+44
-15
@@ -164,13 +164,18 @@
|
||||
<ul>
|
||||
<li><b>Do Not Apply</b> - Do not apply markup to the destination program</li>
|
||||
<li><b>Add</b> - Adds the function name from the source program to the one already
|
||||
at the address in the destination program.</li>
|
||||
at the address in the destination program. If the existing primary
|
||||
symbol is default, then no new label will not be added, but instead
|
||||
the existing label will be replaced with the source name.</li>
|
||||
<li><b>Add As Primary</b> - Adds the function name from the source program to
|
||||
the one already at the address in the destination program. Sets the
|
||||
primary label in the destination program to whatever label was the
|
||||
primary one in the source program.</li>
|
||||
<li><b>Replace Always</b> - Always apply markup to from the source
|
||||
program to the destination program.</li>
|
||||
primary one in the source program. </li>
|
||||
<li><b>Replace Always</b> - Always use the source symbol name to replace
|
||||
the destination symbol name. The one exception is that if the
|
||||
source symbol is a default symbol, then the destination symbol
|
||||
name will be removed instead of being replaced with the source
|
||||
symbol name.</li>
|
||||
<li><b>Replace Default Only</b> - Only apply markup from the
|
||||
source program to the destination program when the label
|
||||
in the destination program is a default label.</li>
|
||||
@@ -425,6 +430,40 @@
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD><b>Function Signature</b> : <br>
|
||||
Specifies the default action to take when applying the function
|
||||
signature of a match.
|
||||
</TD>
|
||||
|
||||
<TD nowrap><tt>Replace When Same Parameter Count</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
|
||||
<TR>
|
||||
<TD><b>Replace Namespace</b> : <br>
|
||||
Specifies whether to apply the source function's namespace when applying
|
||||
the function name.
|
||||
|
||||
<P>
|
||||
<B>Note: If the source uses the Global namespace, then the destination
|
||||
will not be updated when this option is on. The Global namespace is
|
||||
considered the default namesapce. The assumption is that if the
|
||||
destination program has a non-Global namespace, then the existing
|
||||
destination namespace is preferred over the Global namespace.
|
||||
</B>
|
||||
</P>
|
||||
</TD>
|
||||
|
||||
<TD nowrap><tt>False</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
|
||||
<TR>
|
||||
<TD><b>Inline</b> : <br>
|
||||
Specifies the action to take for applying the inline flag when
|
||||
@@ -497,17 +536,7 @@
|
||||
<TD nowrap><tt>False</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><b>Function Signature</b> : <br>
|
||||
Specifies the default action to take when applying the function
|
||||
signature of a match.
|
||||
</TD>
|
||||
|
||||
<TD nowrap><tt>Replace When Same Parameter Count</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
|
||||
<TR>
|
||||
<TD><b>Labels</b> : <br>
|
||||
Specifies the default action to take when applying the label of a match.
|
||||
|
||||
+25
-26
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -115,33 +115,37 @@ public class MarkupItemImpl implements VTMarkupItem {
|
||||
|
||||
@Override
|
||||
public VTMarkupType getMarkupType() {
|
||||
return markupItemStorage.getMarkupType();
|
||||
return markupType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VTMarkupItemStatus getStatus() {
|
||||
validateDestinationCache();
|
||||
VTMarkupItemStatus status = markupItemStorage.getStatus();
|
||||
if (status == UNAPPLIED) {
|
||||
if (!gettingStatus) {
|
||||
try {
|
||||
gettingStatus = true;
|
||||
boolean conflictsWithOtherMarkup = getMarkupType().conflictsWithOtherMarkup(
|
||||
this, getAssociation().getMarkupItems(TaskMonitor.DUMMY));
|
||||
if (conflictsWithOtherMarkup) {
|
||||
return CONFLICT;
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// Shouldn't happen, but ignore if it does.
|
||||
}
|
||||
finally {
|
||||
gettingStatus = false;
|
||||
if (status != UNAPPLIED) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!gettingStatus) {
|
||||
try {
|
||||
gettingStatus = true;
|
||||
VTAssociation association = getAssociation();
|
||||
Collection<VTMarkupItem> items = association.getMarkupItems(TaskMonitor.DUMMY);
|
||||
boolean conflicts = markupType.conflictsWithOtherMarkup(this, items);
|
||||
if (conflicts) {
|
||||
return CONFLICT;
|
||||
}
|
||||
}
|
||||
if (hasSameSourceDestinationValues()) {
|
||||
return SAME;
|
||||
catch (CancelledException e) {
|
||||
// Shouldn't happen, but ignore if it does.
|
||||
}
|
||||
finally {
|
||||
gettingStatus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSameSourceDestinationValues()) {
|
||||
return SAME;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -196,15 +200,10 @@ public class MarkupItemImpl implements VTMarkupItem {
|
||||
markupItemStorage.setApplyFailed("Can't apply without a valid destination");
|
||||
fireMarkupItemStatusChanged(oldStatus, FAILED_APPLY);
|
||||
throw new VersionTrackingApplyException(
|
||||
"Cannot apply a markup item without first " + "setting the destination address");
|
||||
"Cannot apply a markup item without first setting the destination address");
|
||||
}
|
||||
|
||||
if (!canApply()) {
|
||||
// TODO Should this throw an Exception instead?
|
||||
// VTMarkupType itemMarkupType = item.getMarkupType();
|
||||
// throw new VersionTrackingApplyException("Cannot apply " +
|
||||
// itemMarkupType.getDisplayName() + " at " + item.getDestinationAddress().toString() +
|
||||
// ".");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+250
-106
File diff suppressed because it is too large
Load Diff
+60
-37
@@ -1,13 +1,12 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -16,13 +15,19 @@
|
||||
*/
|
||||
package ghidra.feature.vt.api.markuptype;
|
||||
|
||||
import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.feature.vt.api.impl.MarkupItemImpl;
|
||||
import ghidra.feature.vt.api.main.*;
|
||||
import ghidra.feature.vt.api.stringable.FunctionSignatureStringable;
|
||||
import ghidra.feature.vt.api.util.Stringable;
|
||||
import ghidra.feature.vt.api.util.VersionTrackingApplyException;
|
||||
import ghidra.feature.vt.gui.util.*;
|
||||
import ghidra.feature.vt.gui.util.VTMatchApplyChoices.FunctionSignatureChoices;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.feature.vt.gui.util.VTMatchApplyChoices;
|
||||
import ghidra.feature.vt.gui.util.VTMatchApplyChoices.*;
|
||||
import ghidra.feature.vt.gui.util.VTOptionDefines;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -30,16 +35,12 @@ import ghidra.program.model.listing.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.util.SystemUtilities;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstractMarkupType {
|
||||
|
||||
//==================================================================================================
|
||||
// Factory Methods
|
||||
//==================================================================================================
|
||||
|
||||
public static final VTMarkupType INSTANCE = new FunctionSignatureMarkupType();
|
||||
|
||||
@Override
|
||||
public List<VTMarkupItem> createMarkupItems(VTAssociation association) {
|
||||
|
||||
@@ -67,6 +68,10 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
// End Factory Methods
|
||||
//==================================================================================================
|
||||
|
||||
public static final VTMarkupType INSTANCE = new FunctionSignatureMarkupType();
|
||||
|
||||
private ToolOptions unapplyOptions;
|
||||
|
||||
private FunctionSignatureMarkupType() {
|
||||
super("Function Signature");
|
||||
}
|
||||
@@ -106,8 +111,42 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
return;
|
||||
}
|
||||
|
||||
destinationSignatureStringable.applyFunctionSignature(destinationFunction,
|
||||
VT_UNAPPLY_MARKUP_OPTIONS, true);
|
||||
ToolOptions options = getUnapplyOptions();
|
||||
destinationSignatureStringable.applyFunctionSignature(destinationFunction, options, true);
|
||||
}
|
||||
|
||||
private ToolOptions getUnapplyOptions() {
|
||||
|
||||
if (unapplyOptions != null) {
|
||||
return unapplyOptions;
|
||||
}
|
||||
|
||||
unapplyOptions = new ToolOptions(VTController.VERSION_TRACKING_OPTIONS_NAME);
|
||||
|
||||
unapplyOptions.setEnum(FUNCTION_SIGNATURE, FunctionSignatureChoices.REPLACE);
|
||||
unapplyOptions.setEnum(CALLING_CONVENTION, CallingConventionChoices.NAME_MATCH);
|
||||
unapplyOptions.setEnum(INLINE, ReplaceChoices.REPLACE);
|
||||
unapplyOptions.setEnum(NO_RETURN, ReplaceChoices.REPLACE);
|
||||
unapplyOptions.setEnum(VAR_ARGS, ReplaceChoices.REPLACE);
|
||||
unapplyOptions.setEnum(CALL_FIXUP, ReplaceChoices.REPLACE);
|
||||
unapplyOptions.setEnum(FUNCTION_RETURN_TYPE, ParameterDataTypeChoices.REPLACE);
|
||||
unapplyOptions.setEnum(PARAMETER_DATA_TYPES, ParameterDataTypeChoices.REPLACE);
|
||||
unapplyOptions.setEnum(PARAMETER_NAMES, SourcePriorityChoices.REPLACE);
|
||||
unapplyOptions.setEnum(PARAMETER_COMMENTS, CommentChoices.OVERWRITE_EXISTING);
|
||||
|
||||
unapplyOptions.setEnum(FUNCTION_NAME, FunctionNameChoices.REPLACE_ALWAYS);
|
||||
unapplyOptions.setEnum(LABELS, LabelChoices.REPLACE_ALL);
|
||||
|
||||
unapplyOptions.setEnum(PLATE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
unapplyOptions.setEnum(PRE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
unapplyOptions.setEnum(END_OF_LINE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
unapplyOptions.setEnum(REPEATABLE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
unapplyOptions.setEnum(POST_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
|
||||
unapplyOptions.setEnum(DATA_MATCH_DATA_TYPE,
|
||||
ReplaceDataChoices.REPLACE_ALL_DATA);
|
||||
|
||||
return unapplyOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,24 +161,6 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
markupItem.getMarkupType().getDisplayName() + " since it is excluded.");
|
||||
}
|
||||
|
||||
ToolOptions adjustedOptions = markupOptions.copy();
|
||||
// switch (functionSignatureChoice) {
|
||||
// case REPLACE:
|
||||
// adjustedOptions.putEnum(VTOptionDefines.FUNCTION_SIGNATURE,
|
||||
// FunctionSignatureChoices.REPLACE);
|
||||
// break;
|
||||
// case WHEN_SAME_PARAMETER_COUNT:
|
||||
// adjustedOptions.putEnum(VTOptionDefines.FUNCTION_SIGNATURE,
|
||||
// FunctionSignatureChoices.WHEN_SAME_PARAMETER_COUNT);
|
||||
// break;
|
||||
// case WHEN_TAKING_SIGNATURE:
|
||||
// // Don't apply the names. The function signature will do it if needed.
|
||||
// return false;
|
||||
// default:
|
||||
// throw new IllegalArgumentException("Unsupported apply action: " + applyAction);
|
||||
//
|
||||
// }
|
||||
|
||||
Address destinationAddress = markupItem.getDestinationAddress();
|
||||
|
||||
if (destinationAddress == null) {
|
||||
@@ -147,7 +168,8 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
}
|
||||
|
||||
if (destinationAddress == Address.NO_ADDRESS) {
|
||||
throw new VersionTrackingApplyException("The destination address cannot be No Address!");
|
||||
throw new VersionTrackingApplyException(
|
||||
"The destination address cannot be No Address!");
|
||||
}
|
||||
|
||||
Program destinationProgram = getDestinationProgram(markupItem.getAssociation());
|
||||
@@ -166,11 +188,7 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
throw new VersionTrackingApplyException(
|
||||
"Couldn't find destination function to apply a name.");
|
||||
}
|
||||
if (sourceStringable.applyFunctionSignature(destinationFunction, adjustedOptions, false)) {
|
||||
// // If the function signature was applied, apply the names if necessary.
|
||||
// applyParameterNamesIfNeeded(markupItem, adjustedOptions);
|
||||
// // If the function signature was applied, apply the no return flag if necessary.
|
||||
// applyNoReturnIfNeeded(markupItem, adjustedOptions);
|
||||
if (sourceStringable.applyFunctionSignature(destinationFunction, markupOptions, false)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -223,8 +241,9 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
}
|
||||
Address entryAddress = function.getEntryPoint();
|
||||
Stringable value =
|
||||
isSource ? getSourceValue(association, address) : getCurrentDestinationValue(
|
||||
association, address);
|
||||
isSource ? getSourceValue(association, address)
|
||||
: getCurrentDestinationValue(
|
||||
association, address);
|
||||
String displayString = (value != null) ? value.getDisplayString() : null;
|
||||
return new FunctionReturnTypeFieldLocation(program, entryAddress, displayString);
|
||||
}
|
||||
@@ -284,6 +303,10 @@ public class FunctionSignatureMarkupType extends FunctionEntryPointBasedAbstract
|
||||
options.setEnum(VTOptionDefines.FUNCTION_SIGNATURE,
|
||||
FunctionSignatureChoices.REPLACE);
|
||||
break;
|
||||
case REPLACE_FIRST_ONLY:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
+2
-33
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package ghidra.feature.vt.api.markuptype;
|
||||
|
||||
import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -24,8 +22,6 @@ import ghidra.feature.vt.api.impl.MarkupItemImpl;
|
||||
import ghidra.feature.vt.api.main.*;
|
||||
import ghidra.feature.vt.api.util.Stringable;
|
||||
import ghidra.feature.vt.api.util.VersionTrackingApplyException;
|
||||
import ghidra.feature.vt.gui.plugin.VTController;
|
||||
import ghidra.feature.vt.gui.util.VTMatchApplyChoices.*;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -36,33 +32,6 @@ import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public abstract class VTMarkupType {
|
||||
|
||||
static final ToolOptions VT_UNAPPLY_MARKUP_OPTIONS =
|
||||
new ToolOptions(VTController.VERSION_TRACKING_OPTIONS_NAME);
|
||||
static {
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(FUNCTION_SIGNATURE, FunctionSignatureChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(CALLING_CONVENTION, CallingConventionChoices.NAME_MATCH);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(INLINE, ReplaceChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(NO_RETURN, ReplaceChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(VAR_ARGS, ReplaceChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(CALL_FIXUP, ReplaceChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(FUNCTION_RETURN_TYPE, ParameterDataTypeChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(PARAMETER_DATA_TYPES, ParameterDataTypeChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(PARAMETER_NAMES, SourcePriorityChoices.REPLACE);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(PARAMETER_COMMENTS, CommentChoices.OVERWRITE_EXISTING);
|
||||
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(FUNCTION_NAME, FunctionNameChoices.REPLACE_ALWAYS);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(LABELS, LabelChoices.REPLACE_ALL);
|
||||
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(PLATE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(PRE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(END_OF_LINE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(REPEATABLE_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(POST_COMMENT, CommentChoices.OVERWRITE_EXISTING);
|
||||
|
||||
VT_UNAPPLY_MARKUP_OPTIONS.setEnum(DATA_MATCH_DATA_TYPE,
|
||||
ReplaceDataChoices.REPLACE_ALL_DATA);
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
||||
public VTMarkupType(String name) {
|
||||
|
||||
+206
-61
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -17,6 +17,7 @@ package ghidra.feature.vt.api.stringable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import generic.json.Json;
|
||||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||
import ghidra.app.util.NamespaceUtils;
|
||||
import ghidra.feature.vt.api.util.Stringable;
|
||||
@@ -45,8 +46,10 @@ public class FunctionNameStringable extends Stringable {
|
||||
if (symbol == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.symbolName = symbol.getName();
|
||||
this.sourceType = symbol.getSource();
|
||||
|
||||
Namespace namespace = symbol.getParentNamespace();
|
||||
while (namespace != null) {
|
||||
if (namespace instanceof GlobalNamespace) {
|
||||
@@ -84,11 +87,11 @@ public class FunctionNameStringable extends Stringable {
|
||||
sourceType = SourceType.valueOf(sourceName);
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
getNamespaceInfo(tok);
|
||||
addNamespaceInfo(tok);
|
||||
}
|
||||
}
|
||||
|
||||
private void getNamespaceInfo(StringTokenizer tok) {
|
||||
private void addNamespaceInfo(StringTokenizer tok) {
|
||||
String name = tok.nextToken();
|
||||
int id = Integer.parseInt(tok.nextToken());
|
||||
SymbolType type = SymbolType.getSymbolType(id);
|
||||
@@ -97,64 +100,187 @@ public class FunctionNameStringable extends Stringable {
|
||||
namespaceInfos.add(new NamespaceInfo(name, type, nameSpaceSourceType));
|
||||
}
|
||||
|
||||
public void applyFunctionName(Program program, Function function)
|
||||
// Note: this is only meant to be called on the 'destination stringable'
|
||||
public void unapplyFunctionNameAndNamespace(Function targetFunction)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
Namespace ns = createAllNamespacesAndClasses(targetFunction, namespaceInfos);
|
||||
doApplyFunctionName(targetFunction, ns);
|
||||
}
|
||||
|
||||
// Note: this is only meant to be called on the 'source stringable'
|
||||
public void applyFunctionNameAndNamespace(Function targetFunction)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
// use this stringable's namespace info to create the equivalent namespace in the target
|
||||
Namespace ns = createAllNamespacesAndClasses(targetFunction, namespaceInfos);
|
||||
|
||||
if (ns instanceof GlobalNamespace) {
|
||||
Namespace targetNs = targetFunction.getParentNamespace();
|
||||
if (!(targetNs instanceof GlobalNamespace)) {
|
||||
// Assume for now that any non-global namespace in the target is preferred by the
|
||||
// user to the default global namespace. We can always add another option for this
|
||||
// behavior in the future. If we change this code, then update the help.
|
||||
ns = targetNs;
|
||||
}
|
||||
}
|
||||
|
||||
doApplyFunctionName(targetFunction, ns);
|
||||
}
|
||||
|
||||
// Note: this is only meant to be called on the 'source stringable'
|
||||
public void applyFunctionName(Function targetFunction)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
// apply only the name; keep the existing namespace
|
||||
Symbol s = targetFunction.getSymbol();
|
||||
Namespace ns = s.getParentNamespace();
|
||||
doApplyFunctionName(targetFunction, ns);
|
||||
}
|
||||
|
||||
private void doApplyFunctionName(Function targetFunction, Namespace namespace)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
Symbol s = targetFunction.getSymbol();
|
||||
Program targetProgram = targetFunction.getProgram();
|
||||
SymbolTable symbolTable = targetProgram.getSymbolTable();
|
||||
Address entryPoint = targetFunction.getEntryPoint();
|
||||
if (entryPoint.isMemoryAddress() && sourceType == SourceType.DEFAULT) {
|
||||
// Apply a default name by removing the current one.
|
||||
program.getSymbolTable().removeSymbolSpecial(function.getSymbol());
|
||||
symbolTable.removeSymbolSpecial(targetFunction.getSymbol());
|
||||
s.setNamespace(namespace);
|
||||
return;
|
||||
}
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Namespace namespace = program.getGlobalNamespace();
|
||||
for (NamespaceInfo info : namespaceInfos) {
|
||||
Namespace ns = symbolTable.getNamespace(info.name, namespace);
|
||||
if (ns != null) {
|
||||
if (function.isExternal() != ns.isExternal()) {
|
||||
throw new DuplicateNameException("Conflicting namespace: " + info.name);
|
||||
}
|
||||
if (info.symbolType == SymbolType.CLASS &&
|
||||
ns.getSymbol().getSymbolType() == SymbolType.NAMESPACE) {
|
||||
// Promote existing namespace to class
|
||||
ns = NamespaceUtils.convertNamespaceToClass(ns);
|
||||
}
|
||||
namespace = ns;
|
||||
}
|
||||
else {
|
||||
namespace = createNamespace(program, info, namespace);
|
||||
}
|
||||
}
|
||||
|
||||
Symbol s = function.getSymbol();
|
||||
s.setNameAndNamespace(symbolName, namespace, sourceType);
|
||||
}
|
||||
|
||||
public void addFunctionName(Program program, Function function, boolean isPrimary)
|
||||
private Namespace createAllNamespacesAndClasses(Function destFunction,
|
||||
List<NamespaceInfo> infos) throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
Program destProgram = destFunction.getProgram();
|
||||
SymbolTable symbolTable = destProgram.getSymbolTable();
|
||||
Namespace namespace = destProgram.getGlobalNamespace();
|
||||
for (NamespaceInfo info : infos) {
|
||||
Namespace ns = symbolTable.getNamespace(info.name, namespace);
|
||||
if (ns == null) {
|
||||
namespace = createNamespace(destProgram, info, namespace);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (destFunction.isExternal() != ns.isExternal()) {
|
||||
throw new DuplicateNameException("Conflicting namespace: " + info.name);
|
||||
}
|
||||
if (info.symbolType == SymbolType.CLASS &&
|
||||
ns.getSymbol().getSymbolType() == SymbolType.NAMESPACE) {
|
||||
// Promote existing namespace to class
|
||||
ns = NamespaceUtils.convertNamespaceToClass(ns);
|
||||
}
|
||||
namespace = ns;
|
||||
}
|
||||
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void addFunctionNameAndNamespace(Function sourceFunction,
|
||||
Function destFunction, boolean isPrimary)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
List<NamespaceInfo> infos = new ArrayList<>();
|
||||
Namespace namespace = sourceFunction.getParentNamespace();
|
||||
while (namespace != null) {
|
||||
if (namespace instanceof GlobalNamespace) {
|
||||
break;
|
||||
}
|
||||
infos.add(new NamespaceInfo(namespace));
|
||||
namespace = namespace.getParentNamespace();
|
||||
}
|
||||
Collections.reverse(infos);
|
||||
|
||||
doAddFunctionName(destFunction, infos, isPrimary);
|
||||
}
|
||||
|
||||
public void addFunctionName(Function destFunction, boolean isPrimary)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
doAddFunctionName(destFunction, List.of(), isPrimary);
|
||||
}
|
||||
|
||||
private void doAddFunctionName(Function destFunction, List<NamespaceInfo> namespaces,
|
||||
boolean isPrimary)
|
||||
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||
|
||||
Program destProgram = destFunction.getProgram();
|
||||
SymbolTable symbolTable = destProgram.getSymbolTable();
|
||||
Namespace namespace = createAllNamespaces(destProgram, namespaces);
|
||||
Symbol symbol = destFunction.getSymbol();
|
||||
if (symbol.getSource() == SourceType.DEFAULT) {
|
||||
// Special case: when the destination is default, replace the default symbol instead of
|
||||
// adding a new symbol.
|
||||
applyFunctionName(destFunction);
|
||||
return;
|
||||
}
|
||||
|
||||
Address entryPoint = destFunction.getEntryPoint();
|
||||
Symbol addedSymbol = symbolTable.createLabel(entryPoint, symbolName, namespace, sourceType);
|
||||
if (!isPrimary || addedSymbol == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Address address = addedSymbol.getAddress();
|
||||
String name = addedSymbol.getName();
|
||||
Namespace ns = addedSymbol.getParentNamespace();
|
||||
SetLabelPrimaryCmd cmd = new SetLabelPrimaryCmd(address, name, ns);
|
||||
cmd.applyTo(destProgram);
|
||||
}
|
||||
|
||||
public String getSymbolNamespace() {
|
||||
if (namespaceInfos.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
for (NamespaceInfo info : namespaceInfos) {
|
||||
buffy.append(info.name).append(Namespace.DELIMITER);
|
||||
}
|
||||
|
||||
int end = buffy.length();
|
||||
int n = Namespace.DELIMITER.length();
|
||||
buffy.delete(end - n, end);
|
||||
return buffy.toString();
|
||||
}
|
||||
|
||||
public String getSymbolName() {
|
||||
return getSymbolName(false);
|
||||
}
|
||||
|
||||
public String getSymbolName(boolean includeNamespace) {
|
||||
if (!includeNamespace) {
|
||||
return symbolName;
|
||||
}
|
||||
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
for (NamespaceInfo info : namespaceInfos) {
|
||||
buffy.append(info.name).append(Namespace.DELIMITER);
|
||||
}
|
||||
buffy.append(symbolName);
|
||||
return buffy.toString();
|
||||
}
|
||||
|
||||
public SourceType getSymbolSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
private Namespace createAllNamespaces(Program program, List<NamespaceInfo> namespaces)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Namespace namespace = program.getGlobalNamespace();
|
||||
for (NamespaceInfo info : namespaceInfos) {
|
||||
Namespace ns = symbolTable.getNamespace(info.name, namespace);
|
||||
namespace = ns != null ? ns : createNamespace(program, info, namespace);
|
||||
}
|
||||
Symbol functionSymbol = function.getSymbol();
|
||||
if (functionSymbol.getSource() == SourceType.DEFAULT) {
|
||||
function.getSymbol().setNameAndNamespace(symbolName, namespace, sourceType);
|
||||
}
|
||||
else {
|
||||
// Add a label.
|
||||
Symbol addedSymbol = symbolTable.createLabel(function.getEntryPoint(), symbolName,
|
||||
namespace, sourceType);
|
||||
if (isPrimary && addedSymbol != null) {
|
||||
SetLabelPrimaryCmd setLabelPrimaryCmd =
|
||||
new SetLabelPrimaryCmd(addedSymbol.getAddress(), addedSymbol.getName(),
|
||||
addedSymbol.getParentNamespace());
|
||||
setLabelPrimaryCmd.applyTo(program);
|
||||
}
|
||||
for (NamespaceInfo info : namespaces) {
|
||||
Namespace nextNs = symbolTable.getNamespace(info.name, namespace);
|
||||
namespace = nextNs != null ? nextNs : createNamespace(program, info, namespace);
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
||||
private Namespace createNamespace(Program program, NamespaceInfo info, Namespace namespace)
|
||||
@@ -209,33 +335,52 @@ public class FunctionNameStringable extends Stringable {
|
||||
return true;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
private static class NamespaceInfo {
|
||||
String name;
|
||||
SymbolType symbolType;
|
||||
SourceType sourceType;
|
||||
|
||||
public NamespaceInfo(Namespace namespace) {
|
||||
private String name;
|
||||
private SymbolType symbolType;
|
||||
private SourceType sourceType;
|
||||
|
||||
NamespaceInfo(Namespace namespace) {
|
||||
this.name = namespace.getName();
|
||||
this.symbolType = namespace.getSymbol().getSymbolType();
|
||||
this.sourceType = namespace.getSymbol().getSource();
|
||||
}
|
||||
|
||||
public NamespaceInfo(String name, SymbolType type, SourceType sourceType) {
|
||||
NamespaceInfo(String name, SymbolType type, SourceType sourceType) {
|
||||
this.name = name;
|
||||
this.symbolType = type;
|
||||
this.sourceType = sourceType;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return Json.toString(this);
|
||||
}
|
||||
|
||||
public String getSymbolName() {
|
||||
return symbolName;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, sourceType, symbolType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
NamespaceInfo other = (NamespaceInfo) obj;
|
||||
return Objects.equals(name, other.name) && sourceType == other.sourceType &&
|
||||
Objects.equals(symbolType, other.symbolType);
|
||||
}
|
||||
|
||||
public SourceType getSymbolSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
}
|
||||
|
||||
+20
-47
@@ -19,7 +19,6 @@ import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
@@ -59,6 +58,8 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
private static final String FUNCTION_SIGNATURE_TOOLTIP =
|
||||
"<html>The apply action for the <b>function signature</b> " +
|
||||
"when performing bulk apply operations</html>";
|
||||
private static final String USE_NAMESPACE_TOOLTIP =
|
||||
"<html>When true function namespaces will be applied when names are applied.";
|
||||
private static final String PLATE_COMMENT_TOOLTIP =
|
||||
"<html>The apply action for <b>plate comments</b> when performing bulk apply operations</html>";
|
||||
private static final String PRE_COMMENT_TOOLTIP =
|
||||
@@ -119,6 +120,7 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
private JLabel dataMatchDataTypeLabel;
|
||||
private JLabel functionNameLabel;
|
||||
private JLabel functionSignatureLabel;
|
||||
private JLabel useFunctionNamespaceLabel;
|
||||
private JLabel returnTypeLabel;
|
||||
private JLabel inlineLabel;
|
||||
private JLabel noReturnLabel;
|
||||
@@ -138,6 +140,7 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
private JComboBox<Enum<?>> dataMatchDataTypeComboBox;
|
||||
private JComboBox<Enum<?>> functionNameComboBox;
|
||||
private JComboBox<Enum<?>> functionSignatureComboBox;
|
||||
private JCheckBox useFunctionNamespaceCheckBox;
|
||||
private JComboBox<Enum<?>> returnTypeComboBox;
|
||||
private JComboBox<Enum<?>> callingConventionComboBox;
|
||||
private JComboBox<Enum<?>> inlineComboBox;
|
||||
@@ -160,8 +163,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
private JCheckBox ignoreExcludedCheckBox;
|
||||
private JCheckBox ignoreIncompleteCheckBox;
|
||||
|
||||
private ActionListener defaultActionListener;
|
||||
|
||||
private ToolOptions originalOptions;
|
||||
private PropertyChangeListener listener;
|
||||
private boolean unappliedChanges = false;
|
||||
@@ -206,7 +207,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
panel.add(createSeparator());
|
||||
panel.add(createIgnoreCheckBoxPanel());
|
||||
|
||||
// TODO More needs to be done with the layout here.
|
||||
panel.setBorder(BorderFactory.createTitledBorder("Apply Markup Options"));
|
||||
JScrollPane scrollPane = new JScrollPane(panel);
|
||||
|
||||
@@ -223,7 +223,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
|
||||
private Component createIgnoreCheckBoxPanel() {
|
||||
createIgnoreCheckBoxes();
|
||||
setupIgnoreMarkupItemsListeners();
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.add(ignoreExcludedCheckBox);
|
||||
@@ -239,16 +238,10 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
ignoreExcludedCheckBox.setToolTipText(IGNORE_EXCLUDED_TOOLTIP);
|
||||
}
|
||||
|
||||
private void setupIgnoreMarkupItemsListeners() {
|
||||
ignoreExcludedCheckBox.addActionListener(defaultActionListener);
|
||||
ignoreIncompleteCheckBox.addActionListener(defaultActionListener);
|
||||
}
|
||||
|
||||
private JPanel createFunctionSignatureSubPanel() {
|
||||
|
||||
createFunctionSignatureDetailLabels();
|
||||
createFunctionSignatureDetailChoices();
|
||||
setupFunctionSignatureDetailChoiceListeners();
|
||||
|
||||
JPanel outerPanel = new JPanel();
|
||||
outerPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
|
||||
@@ -325,19 +318,9 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
varArgsComboBox.setToolTipText(VAR_ARGS_TOOLTIP);
|
||||
}
|
||||
|
||||
private void setupFunctionSignatureDetailChoiceListeners() {
|
||||
returnTypeComboBox.addActionListener(defaultActionListener);
|
||||
inlineComboBox.addActionListener(defaultActionListener);
|
||||
noReturnComboBox.addActionListener(defaultActionListener);
|
||||
callingConventionComboBox.addActionListener(defaultActionListener);
|
||||
callFixupComboBox.addActionListener(defaultActionListener);
|
||||
varArgsComboBox.addActionListener(defaultActionListener);
|
||||
}
|
||||
|
||||
private JPanel createParametersSubPanel() {
|
||||
createParameterLabels();
|
||||
createParameterChoices();
|
||||
setupParameterChoiceListeners();
|
||||
|
||||
JPanel outerPanel = new JPanel();
|
||||
outerPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
|
||||
@@ -402,15 +385,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
PARAMETER_NAMES_REPLACE_IF_SAME_PRIORITY_TOOLTIP);
|
||||
}
|
||||
|
||||
private void setupParameterChoiceListeners() {
|
||||
parameterDataTypesComboBox.addActionListener(defaultActionListener);
|
||||
parameterNamesComboBox.addActionListener(defaultActionListener);
|
||||
userHighestPriorityRB.addActionListener(defaultActionListener);
|
||||
importHighestPriorityRB.addActionListener(defaultActionListener);
|
||||
replaceIfSameSourceCheckBox.addActionListener(defaultActionListener);
|
||||
parameterCommentsComboBox.addActionListener(defaultActionListener);
|
||||
}
|
||||
|
||||
private JPanel createPrioritySubPanel() {
|
||||
JPanel outerPanel = new JPanel();
|
||||
JPanel panel = new JPanel();
|
||||
@@ -436,7 +410,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
|
||||
createNonCommentMarkupLabels();
|
||||
createNonCommentMarkupChoices();
|
||||
setupNonCommentMarkupChoiceListeners();
|
||||
|
||||
JPanel outerPanel = new JPanel();
|
||||
outerPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
|
||||
@@ -452,6 +425,9 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
panel.add(functionSignatureLabel);
|
||||
panel.add(functionSignatureComboBox);
|
||||
|
||||
panel.add(useFunctionNamespaceLabel);
|
||||
panel.add(useFunctionNamespaceCheckBox);
|
||||
|
||||
outerPanel.add(panel);
|
||||
return outerPanel;
|
||||
}
|
||||
@@ -468,6 +444,9 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
|
||||
functionSignatureLabel = new GDLabel("Function Signature", SwingConstants.RIGHT);
|
||||
functionSignatureLabel.setToolTipText(FUNCTION_SIGNATURE_TOOLTIP);
|
||||
|
||||
useFunctionNamespaceLabel = new GDLabel("Replace Namespace", SwingConstants.RIGHT);
|
||||
useFunctionNamespaceLabel.setToolTipText(USE_NAMESPACE_TOOLTIP);
|
||||
}
|
||||
|
||||
private void createNonCommentMarkupChoices() {
|
||||
@@ -485,19 +464,13 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
functionSignatureComboBox = createComboBox(VTOptionDefines.FUNCTION_SIGNATURE,
|
||||
DEFAULT_OPTION_FOR_FUNCTION_SIGNATURE);
|
||||
functionSignatureComboBox.setToolTipText(FUNCTION_SIGNATURE_TOOLTIP);
|
||||
}
|
||||
|
||||
private void setupNonCommentMarkupChoiceListeners() {
|
||||
dataMatchDataTypeComboBox.addActionListener(defaultActionListener);
|
||||
labelsComboBox.addActionListener(defaultActionListener);
|
||||
functionNameComboBox.addActionListener(defaultActionListener);
|
||||
functionSignatureComboBox.addActionListener(defaultActionListener);
|
||||
useFunctionNamespaceCheckBox = createCheckBox("");
|
||||
}
|
||||
|
||||
private JPanel createCommentsSubPanel() {
|
||||
createCommentLabels();
|
||||
createCommentChoices();
|
||||
setupCommentChoiceListeners();
|
||||
|
||||
JPanel outerPanel = new JPanel();
|
||||
outerPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
|
||||
@@ -562,14 +535,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
postCommentsComboBox.setToolTipText(POST_COMMENT_TOOLTIP);
|
||||
}
|
||||
|
||||
private void setupCommentChoiceListeners() {
|
||||
plateCommentsComboBox.addActionListener(defaultActionListener);
|
||||
preCommentsComboBox.addActionListener(defaultActionListener);
|
||||
endOfLineCommentsComboBox.addActionListener(defaultActionListener);
|
||||
repeatableCommentsComboBox.addActionListener(defaultActionListener);
|
||||
postCommentsComboBox.addActionListener(defaultActionListener);
|
||||
}
|
||||
|
||||
private void updateOptions(ToolOptions options) {
|
||||
updateNonCommentMarkupOptions(options);
|
||||
updateCommentOptions(options);
|
||||
@@ -594,6 +559,9 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
FunctionSignatureChoices functionSignatureChoice =
|
||||
(FunctionSignatureChoices) functionSignatureComboBox.getSelectedItem();
|
||||
options.setEnum(FUNCTION_SIGNATURE, functionSignatureChoice);
|
||||
|
||||
boolean useNamespaces = useFunctionNamespaceCheckBox.isSelected();
|
||||
options.setBoolean(USE_NAMESPACE_FUNCTIONS, useNamespaces);
|
||||
}
|
||||
|
||||
private void updateCommentOptions(ToolOptions options) {
|
||||
@@ -704,6 +672,12 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
if (functionSignatureChoice != functionSignatureComboBox.getSelectedItem()) {
|
||||
functionSignatureComboBox.setSelectedItem(functionSignatureChoice);
|
||||
}
|
||||
|
||||
boolean useNamespace =
|
||||
options.getBoolean(USE_NAMESPACE_FUNCTIONS, DEFAULT_OPTION_FOR_NAMESPACE_FUNCTIONS);
|
||||
if (useFunctionNamespaceCheckBox.isSelected() != useNamespace) {
|
||||
useFunctionNamespaceCheckBox.setSelected(useNamespace);
|
||||
}
|
||||
}
|
||||
|
||||
private void setEditorCommentValues(ToolOptions options) {
|
||||
@@ -852,7 +826,6 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
|
||||
|
||||
// signals that there are unapplied changes
|
||||
private void changesMade(boolean changes) {
|
||||
// FIXME Is this ok? complete?
|
||||
if (listener != null) {
|
||||
listener.propertyChange(new PropertyChangeEvent(this, GhidraOptions.APPLY_ENABLED,
|
||||
unappliedChanges, changes));
|
||||
|
||||
+3
@@ -766,6 +766,9 @@ public class VTMatchTableProvider extends ComponentProviderAdapter
|
||||
"Markup items that are incomplete (for example, no destination address is specified) " +
|
||||
"should become ignored by applying a match.");
|
||||
|
||||
vtOptions.registerOption(USE_NAMESPACE_FUNCTIONS, DEFAULT_OPTION_FOR_NAMESPACE_FUNCTIONS,
|
||||
null, "Apply the non-Global source namespace to the destination function.");
|
||||
|
||||
vtOptions.getOptions(APPLY_MARKUP_OPTIONS_NAME)
|
||||
.registerOptionsEditor(() -> new ApplyMarkupPropertyEditor(controller));
|
||||
vtOptions.getOptions(DISPLAY_APPLY_MARKUP_OPTIONS)
|
||||
|
||||
+6
-1
@@ -68,6 +68,8 @@ public class VTOptionDefines {
|
||||
public static CommentChoices DEFAULT_OPTION_FOR_POST_COMMENTS =
|
||||
CommentChoices.APPEND_TO_EXISTING;
|
||||
|
||||
public static boolean DEFAULT_OPTION_FOR_NAMESPACE_FUNCTIONS = false;
|
||||
|
||||
public static final String FUNCTION_NAME = APPLY_MARKUP_OPTIONS_NAME + ".Function Name";
|
||||
public static final String FUNCTION_RETURN_TYPE = APPLY_MARKUP_OPTIONS_NAME +
|
||||
".Function Return Type";
|
||||
@@ -105,9 +107,12 @@ public class VTOptionDefines {
|
||||
public static final String IGNORE_EXCLUDED_MARKUP_ITEMS = APPLY_MARKUP_OPTIONS_NAME +
|
||||
".Set Excluded Markup Items To Ignored";
|
||||
|
||||
public final static String DISPLAY_APPLY_MARKUP_OPTIONS = APPLY_MARKUP_OPTIONS_NAME +
|
||||
public static final String DISPLAY_APPLY_MARKUP_OPTIONS = APPLY_MARKUP_OPTIONS_NAME +
|
||||
Options.DELIMITER + "Display Apply Markup Options";
|
||||
|
||||
public static final String USE_NAMESPACE_FUNCTIONS =
|
||||
APPLY_MARKUP_OPTIONS_NAME + ".Replace Namespace";
|
||||
|
||||
// Auto VT Options
|
||||
public static final String AUTO_VT_OPTIONS_NAME = "Auto Version Tracking Options";
|
||||
|
||||
|
||||
+1204
File diff suppressed because it is too large
Load Diff
+264
-191
File diff suppressed because it is too large
Load Diff
+46
-10
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -35,6 +35,7 @@ import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.test.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
@@ -55,6 +56,10 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
env = new TestEnv();
|
||||
setErrorGUIEnabled(false);
|
||||
|
||||
resetPrograms();
|
||||
}
|
||||
|
||||
protected void resetPrograms() throws Exception {
|
||||
sourceBuilder = new ClassicSampleX86ProgramBuilder("notepadSrc", true, this);
|
||||
sourceProgram = sourceBuilder.getProgram();
|
||||
|
||||
@@ -112,6 +117,8 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
*/
|
||||
protected abstract class TestDataProviderAndValidator {
|
||||
|
||||
protected ToolOptions options;
|
||||
|
||||
protected abstract Address getSourceMatchAddress();
|
||||
|
||||
protected abstract Address getDestinationMatchAddress();
|
||||
@@ -134,6 +141,11 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
* @return the Apply Markup Options for the validator to use.
|
||||
*/
|
||||
protected ToolOptions getOptions() {
|
||||
|
||||
if (options != null) {
|
||||
return options;
|
||||
}
|
||||
|
||||
ToolOptions applyOptions = new ToolOptions(VERSION_TRACKING_OPTIONS_NAME);
|
||||
|
||||
applyOptions.setEnum(FUNCTION_NAME, FunctionNameChoices.REPLACE_ALWAYS);
|
||||
@@ -165,10 +177,29 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
|
||||
applyOptions.setEnum(DATA_MATCH_DATA_TYPE,
|
||||
ReplaceDataChoices.REPLACE_UNDEFINED_DATA_ONLY);
|
||||
|
||||
options = applyOptions;
|
||||
return applyOptions;
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTestFindButCannotApplyMarkupItem_SameStatus(
|
||||
TestDataProviderAndValidator validator) throws Exception {
|
||||
|
||||
VTSessionDB session = createNewSession();
|
||||
VTMatch match = createMatchSetWithOneMatch(session, validator.getSourceMatchAddress(),
|
||||
validator.getDestinationMatchAddress());
|
||||
VTMarkupItem markupItem = validator.searchForMarkupItem(match);
|
||||
|
||||
List<VTMarkupItem> markupItems = new ArrayList<>();
|
||||
Address destinationApplyAddress = validator.getDestinationApplyAddress();
|
||||
markupItem.setDefaultDestinationAddress(destinationApplyAddress, TEST_ADDRESS_SOURCE);
|
||||
markupItems.add(markupItem);
|
||||
|
||||
VTMarkupItemStatus status = markupItem.getStatus();
|
||||
assertEquals(VTMarkupItemStatus.SAME, status);
|
||||
}
|
||||
|
||||
protected void doTestFindAndApplyMarkupItem(TestDataProviderAndValidator validator)
|
||||
throws Exception {
|
||||
|
||||
@@ -319,7 +350,10 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
// verify that calling apply still leaves us in an unapplied state
|
||||
//
|
||||
task = new ApplyMarkupItemTask(session, markupItems, validator.getOptions());
|
||||
|
||||
setErrorsExpected(true);
|
||||
runTask(session, task);
|
||||
setErrorsExpected(false);
|
||||
|
||||
assertEquals("The markup item status was not correctly set",
|
||||
VTMarkupItemStatus.FAILED_APPLY, markupItem.getStatus());
|
||||
@@ -354,9 +388,8 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
|
||||
protected static VTMatch createMatchSetWithOneMatch(VTSessionDB db, Address sourceAddress,
|
||||
Address destinationAddress) throws Exception {
|
||||
int testTransactionID = 0;
|
||||
try {
|
||||
testTransactionID = db.startTransaction("Test Match Set Setup");
|
||||
|
||||
return tx(db, () -> {
|
||||
VTMatchInfo matchInfo = createRandomMatch(sourceAddress, destinationAddress, db);
|
||||
VTMatchSet matchSet = db.createMatchSet(
|
||||
createProgramCorrelator(db.getSourceProgram(), db.getDestinationProgram()));
|
||||
@@ -368,19 +401,22 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
|
||||
association.getMarkupItems(TaskMonitor.DUMMY);
|
||||
|
||||
return addedMatch;
|
||||
}
|
||||
finally {
|
||||
db.endTransaction(testTransactionID, true);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void runTask(VTSession session, VtTask task) {
|
||||
protected void runTask(VTSession session, VtTask task) {
|
||||
int id = session.startTransaction("test");
|
||||
try {
|
||||
task.run(TaskMonitor.DUMMY);
|
||||
}
|
||||
finally {
|
||||
session.endTransaction(id, true);
|
||||
|
||||
if (task.hasErrors()) {
|
||||
String errorDetails = task.getErrorDetails();
|
||||
Msg.error(this, "Error applying task: " + errorDetails);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -96,6 +96,7 @@ public class VersionControlScreenShots extends GhidraScreenShotGenerator {
|
||||
|
||||
UndoActionDialog d = waitForDialogComponent(UndoActionDialog.class);
|
||||
captureDialog(d);
|
||||
|
||||
close(d);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user