From 97fe9981fb7496e7cd075c0fa69c54dd8012e577 Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Thu, 26 Sep 2019 09:33:19 -0400 Subject: [PATCH] Check for extendable structure and pointer size --- .../CreateStructureVariableAction.java | 36 +++++++++++++++---- .../DecompilerStructureVariableAction.java | 5 +-- .../actions/FillOutStructureCmd.java | 17 ++------- .../ListingStructureVariableAction.java | 13 ++++--- 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CreateStructureVariableAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CreateStructureVariableAction.java index 41d8e606b2..c3b16a0344 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CreateStructureVariableAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/CreateStructureVariableAction.java @@ -56,6 +56,34 @@ public abstract class CreateStructureVariableAction extends DockingAction { return false; } + /** + * Check if a variable has a data-type that is suitable for being extended. + * If so return the structure data-type, otherwise return null. + * Modulo typedefs, the data-type of the variable must be exactly a + * "pointer to a structure". Not a "structure" itself, or a + * "pointer to a pointer to ... a structure". + * @param dt is the data-type of the variable to test + * @return the extendable structure data-type or null + */ + public static Structure getStructureForExtending(DataType dt) { + if (dt instanceof TypeDef) { + dt = ((TypeDef) dt).getBaseDataType(); + } + if (dt instanceof Pointer) { + dt = ((Pointer) dt).getDataType(); + } + else { + return null; + } + if (dt instanceof TypeDef) { + dt = ((TypeDef) dt).getBaseDataType(); + } + if (dt instanceof Structure) { + return (Structure) dt; + } + return null; + } + @Override public abstract boolean isEnabledForContext(ActionContext context); @@ -67,13 +95,9 @@ public abstract class CreateStructureVariableAction extends DockingAction { */ protected void adjustCreateStructureMenuText(DataType dt, boolean isThisParam) { - // rip off any multi-level pointers - while (dt instanceof Pointer) { - dt = ((Pointer) dt).getDataType(); - } - + dt = getStructureForExtending(dt); String menuString = "Auto Create Structure"; - if (dt instanceof Structure) { + if (dt != null) { if (isThisParam) { menuString = "Auto Fill in Class Structure"; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/DecompilerStructureVariableAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/DecompilerStructureVariableAction.java index 8a1fc7baa1..8652072f80 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/DecompilerStructureVariableAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/DecompilerStructureVariableAction.java @@ -45,7 +45,7 @@ public class DecompilerStructureVariableAction extends CreateStructureVariableAc return decompilerContext.checkActionEnablement(() -> { Function function = controller.getFunction(); - if (function instanceof UndefinedFunction) { + if (function == null || function instanceof UndefinedFunction) { return false; } @@ -58,13 +58,14 @@ public class DecompilerStructureVariableAction extends CreateStructureVariableAc if (tokenAtCursor == null) { return false; } + int maxPointerSize = controller.getProgram().getDefaultPointerSize(); HighVariable var = tokenAtCursor.getHighVariable(); if (var != null && !(var instanceof HighConstant)) { dt = var.getDataType(); isThisParam = testForAutoParameterThis(var, function); } - if (dt == null) { + if (dt == null || dt.getLength() > maxPointerSize) { return false; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java index b4c19049cb..d3f4711db0 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FillOutStructureCmd.java @@ -370,21 +370,8 @@ public class FillOutStructureCmd extends BackgroundCommand { */ private Structure createStructure(HighVariable var, Function f, boolean isThisParam) { - Structure structDT = null; - - DataType varDT = var.getDataType(); - if (varDT instanceof Structure) { - structDT = (StructureDataType) varDT; - } - else if (varDT instanceof Pointer) { - DataType dt = ((Pointer) varDT).getDataType(); - while (dt instanceof Pointer) { - dt = ((Pointer) dt).getDataType(); - } - if (dt instanceof Structure) { - structDT = (Structure) dt; - } - } + Structure structDT = + CreateStructureVariableAction.getStructureForExtending(var.getDataType()); if (structDT == null) { structDT = createNewStruct(var, (int) maxOffset, f, isThisParam); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ListingStructureVariableAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ListingStructureVariableAction.java index 999689081d..bc612bf2e6 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ListingStructureVariableAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/ListingStructureVariableAction.java @@ -15,6 +15,8 @@ */ package ghidra.app.plugin.core.decompile.actions; +import docking.ActionContext; +import docking.action.MenuData; import ghidra.app.context.ListingActionContext; import ghidra.app.decompiler.component.DecompilerController; import ghidra.app.plugin.core.function.FunctionPlugin; @@ -22,8 +24,6 @@ import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.*; import ghidra.program.util.*; -import docking.ActionContext; -import docking.action.MenuData; public class ListingStructureVariableAction extends CreateStructureVariableAction { @@ -55,16 +55,18 @@ public class ListingStructureVariableAction extends CreateStructureVariableActio VariableLocation varLoc = (VariableLocation) location; Variable variable = varLoc.getVariable(); if (variable instanceof Parameter) { - if (((Parameter) variable).getAutoParameterType() == AutoParameterType.THIS) + if (((Parameter) variable).getAutoParameterType() == AutoParameterType.THIS) { isThisParam = true; + } } dt = variable.getDataType(); } else if (location instanceof FunctionParameterFieldLocation) { FunctionParameterFieldLocation funcPFL = (FunctionParameterFieldLocation) location; Parameter parameter = funcPFL.getParameter(); - if (parameter.getAutoParameterType() == AutoParameterType.THIS) + if (parameter.getAutoParameterType() == AutoParameterType.THIS) { isThisParam = true; + } dt = parameter.getDataType(); } else if (location instanceof FunctionReturnTypeFieldLocation) { @@ -74,7 +76,8 @@ public class ListingStructureVariableAction extends CreateStructureVariableActio dt = func.getReturnType(); } - if (dt == null) { + int maxPointerSize = currentProgram.getDefaultPointerSize(); + if (dt == null || dt.getLength() > maxPointerSize) { return false; }