diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java index 71447e37b4..8b3224d38f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/graph/AddressBasedGraphDisplayListener.java @@ -20,6 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger; import docking.widgets.EventTrigger; import ghidra.app.events.*; +import ghidra.app.nav.NavigationUtils; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginEvent; import ghidra.framework.plugintool.PluginTool; @@ -158,9 +159,22 @@ public abstract class AddressBasedGraphDisplayListener if (symbols.isEmpty()) { return null; } - // there should only be one external symbol with the same name, so just assume the first one is good - return symbols.get(0).getAddress(); + // There should only be one external symbol with the same name. + // Since externals are not shown in the listing, we are going to do a hack and try + // and navigate to a "fake" function if one exists. A "fake" function in Ghidra is just + // an indirect pointer to the external function. If such a pointer exists, Ghidra marks + // up the location with the function signature. + Address symbolAddress = symbols.get(0).getAddress(); + if (symbolAddress.isExternalAddress()) { + Address[] externalLinkageAddresses = + NavigationUtils.getExternalLinkageAddresses(program, symbolAddress); + // If this is a "fake" function situation, then there should only be one address + if (externalLinkageAddresses.length == 1) { + symbolAddress = externalLinkageAddresses[0]; + } + } + return symbolAddress; } protected Address getAddress(AttributedVertex vertex) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/EditLabelAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/EditLabelAction.java index b7769d8499..c687aca691 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/EditLabelAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/EditLabelAction.java @@ -25,6 +25,7 @@ import ghidra.app.context.ListingActionContext; import ghidra.app.context.ListingContextAction; import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.SymbolType; import ghidra.program.util.LabelFieldLocation; import ghidra.program.util.OperandFieldLocation; @@ -64,6 +65,10 @@ class EditLabelAction extends ListingContextAction { if (symbol.isExternal()) { return false; } + if (symbol.getSymbolType() == SymbolType.FUNCTION) { + // let the rename function action handle this + return false; + } getPopupMenuData().setMenuItemName(EDIT_LABEL); return true; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameFunctionAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameFunctionAction.java index a978a5a314..60433152bb 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameFunctionAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameFunctionAction.java @@ -27,6 +27,8 @@ import ghidra.app.util.AddEditDialog; import ghidra.app.util.HelpTopics; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; +import ghidra.program.model.pcode.HighFunctionShellSymbol; +import ghidra.program.model.pcode.HighSymbol; import ghidra.util.HelpLocation; import ghidra.util.UndefinedFunction; @@ -39,26 +41,32 @@ public class RenameFunctionAction extends AbstractDecompilerAction { setPopupMenuData(new MenuData(new String[] { "Rename Function" }, "Decompile")); } - private Function getFunction(Program program, ClangToken tokenAtCursor) { + private Function getFunction(DecompilerActionContext context) { + Program program = context.getProgram(); + ClangToken tokenAtCursor = context.getTokenAtCursor(); + // try to look up the function that is at the current cursor location // If there isn't one, just use the function we are in. if (tokenAtCursor instanceof ClangFuncNameToken) { return DecompilerUtils.getFunction(program, (ClangFuncNameToken) tokenAtCursor); } + HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + if (highSymbol instanceof HighFunctionShellSymbol) { + return (Function) highSymbol.getSymbol().getObject(); + } return null; } @Override protected boolean isEnabledForDecompilerContext(DecompilerActionContext context) { - Function func = - getFunction(context.getProgram(), context.getTokenAtCursor()); + Function func = getFunction(context); return func != null && !(func instanceof UndefinedFunction); } @Override protected void decompilerActionPerformed(DecompilerActionContext context) { Program program = context.getProgram(); - Function function = getFunction(program, context.getTokenAtCursor()); + Function function = getFunction(context); AddEditDialog dialog = new AddEditDialog("Edit Function Name", context.getTool()); dialog.editLabel(function.getSymbol(), program); } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameGlobalAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameGlobalAction.java index 48a8747a6b..b39094af4d 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameGlobalAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameGlobalAction.java @@ -28,6 +28,7 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.pcode.HighCodeSymbol; +import ghidra.program.model.pcode.HighFunctionShellSymbol; import ghidra.program.model.pcode.HighSymbol; import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.SymbolTable; @@ -62,7 +63,7 @@ public class RenameGlobalAction extends AbstractDecompilerAction { return false; } HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); - if (highSymbol == null) { + if (highSymbol == null || highSymbol instanceof HighFunctionShellSymbol) { return false; } return highSymbol.isGlobal(); diff --git a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java index 856126f516..90bb1741ce 100644 --- a/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java +++ b/Ghidra/Features/GraphServices/src/main/java/ghidra/graph/visualization/DefaultGraphDisplay.java @@ -666,6 +666,9 @@ public class DefaultGraphDisplay implements GraphDisplay { satellite.getRenderContext().setVertexFillPaintFunction(Colors::getColor); satellite.scaleToLayout(); satellite.getRenderContext().setVertexLabelFunction(n -> null); + // always get the current predicate from the main view and test with it, + satellite.getRenderContext() + .setVertexIncludePredicate(v -> viewer.getRenderContext().getVertexIncludePredicate().test(v)); satellite.getComponent().setBorder(BorderFactory.createEtchedBorder()); parentViewer.getComponent().addComponentListener(new ComponentAdapter() { @Override @@ -873,7 +876,7 @@ public class DefaultGraphDisplay implements GraphDisplay { viewer.getRenderContext() .setVertexIncludePredicate( v -> v.getAttributeMap().values().stream().noneMatch(selected::contains)); - viewer.repaint(); + }); edgeFilters = AttributeFilters.builder() diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java index ecbf29f663..fcf9ae229f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighSymbol.java @@ -144,7 +144,7 @@ public class HighSymbol { */ public Symbol getSymbol() { if (id != 0) { - return function.getFunction().getProgram().getSymbolTable().getSymbol(id); + return getProgram().getSymbolTable().getSymbol(id); } return null; } diff --git a/Ghidra/Processors/ARM/data/languages/ARM.cspec b/Ghidra/Processors/ARM/data/languages/ARM.cspec index 19c8bb9b00..4137ca1d69 100644 --- a/Ghidra/Processors/ARM/data/languages/ARM.cspec +++ b/Ghidra/Processors/ARM/data/languages/ARM.cspec @@ -82,7 +82,7 @@ - + @@ -158,8 +158,7 @@ tmpptr = lr & 0xfffffffe; offset = *:1 (tmpptr + r0); - offset = offset * 2; - lr = lr + zext(offset); + lr = lr + 2 * zext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; @@ -177,8 +176,7 @@ tmpptr = lr & 0xfffffffe; offset = *:1 (tmpptr + r0); - offset = offset * 2; - lr = lr + sext(offset); + lr = lr + 2 * sext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; @@ -197,8 +195,7 @@ index = r0 * 2; offset = *:2 (tmpptr + index); - offset = offset * 2; - lr = lr + sext(offset); + lr = lr + 2 * sext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; @@ -217,8 +214,7 @@ index = r0 * 2; offset = *:2 (tmpptr + index); - offset = offset * 2; - lr = lr + zext(offset); + lr = lr + 2 * zext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; diff --git a/Ghidra/Processors/ARM/data/languages/ARM_v45.cspec b/Ghidra/Processors/ARM/data/languages/ARM_v45.cspec index db5ca37aae..5b6a05aaa1 100644 --- a/Ghidra/Processors/ARM/data/languages/ARM_v45.cspec +++ b/Ghidra/Processors/ARM/data/languages/ARM_v45.cspec @@ -59,6 +59,9 @@ + + + @@ -117,8 +120,7 @@ tmpptr = lr & 0xfffffffe; offset = *:1 (tmpptr + r0); - offset = offset * 2; - lr = lr + zext(offset); + lr = lr + 2 * zext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; @@ -136,8 +138,7 @@ tmpptr = lr & 0xfffffffe; offset = *:1 (tmpptr + r0); - offset = offset * 2; - lr = lr + sext(offset); + lr = lr + 2 * sext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; @@ -156,8 +157,7 @@ index = r0 * 2; offset = *:2 (tmpptr + index); - offset = offset * 2; - lr = lr + sext(offset); + lr = lr + 2 * sext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; @@ -176,8 +176,7 @@ index = r0 * 2; offset = *:2 (tmpptr + index); - offset = offset * 2; - lr = lr + zext(offset); + lr = lr + 2 * zext(offset); ISAModeSwitch = (lr & 1) != 0; TB = ISAModeSwitch; diff --git a/Ghidra/Processors/ARM/data/languages/ARM_win.cspec b/Ghidra/Processors/ARM/data/languages/ARM_win.cspec index 9e71ff4a04..f4e1dc2d1c 100644 --- a/Ghidra/Processors/ARM/data/languages/ARM_win.cspec +++ b/Ghidra/Processors/ARM/data/languages/ARM_win.cspec @@ -86,7 +86,7 @@ - +