From a5ba9e390cfdf382ac952f14021e2a8a1f20132b Mon Sep 17 00:00:00 2001 From: caheckman <48068198+caheckman@users.noreply.github.com> Date: Fri, 24 Feb 2023 17:32:26 -0500 Subject: [PATCH] GP-2717 Symbol attached to variable declarations --- .../ghidra/app/decompiler/ClangBreak.java | 6 ++ .../app/decompiler/ClangCommentToken.java | 3 + .../app/decompiler/ClangFieldToken.java | 3 +- .../app/decompiler/ClangFuncNameToken.java | 9 +- .../ghidra/app/decompiler/ClangFuncProto.java | 16 +--- .../ghidra/app/decompiler/ClangFunction.java | 12 +-- .../app/decompiler/ClangLabelToken.java | 5 +- .../ghidra/app/decompiler/ClangMarkup.java | 6 -- .../java/ghidra/app/decompiler/ClangNode.java | 60 ++++++++++--- .../ghidra/app/decompiler/ClangOpToken.java | 8 +- .../app/decompiler/ClangReturnType.java | 16 ++-- .../ghidra/app/decompiler/ClangStatement.java | 15 ++-- .../app/decompiler/ClangSyntaxToken.java | 20 ++--- .../ghidra/app/decompiler/ClangToken.java | 87 ++++++++++++++++--- .../app/decompiler/ClangTokenGroup.java | 19 +++- .../ghidra/app/decompiler/ClangTypeToken.java | 15 ++-- .../app/decompiler/ClangVariableDecl.java | 41 +++++---- .../app/decompiler/ClangVariableToken.java | 72 ++++++++++++++- .../actions/AbstractDecompilerAction.java | 73 +--------------- .../FindReferencesToHighSymbolAction.java | 4 +- .../decompile/actions/RenameGlobalAction.java | 8 +- .../decompile/actions/RenameLocalAction.java | 4 +- .../decompile/actions/RetypeGlobalAction.java | 4 +- .../decompile/actions/RetypeLocalAction.java | 4 +- .../plugin/core/decompile/HighSymbolTest.java | 13 +-- .../program/model/pcode/HighConstant.java | 3 +- .../model/pcode/HighFunctionDBUtil.java | 8 +- 27 files changed, 315 insertions(+), 219 deletions(-) diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangBreak.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangBreak.java index 60e1624db1..bd263abeef 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangBreak.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangBreak.java @@ -17,6 +17,9 @@ package ghidra.app.decompiler; import ghidra.program.model.pcode.*; +/** + * A line break in source code plus the indenting for the following line. + */ public class ClangBreak extends ClangToken { private int indent; // Number of characters of indent @@ -31,6 +34,9 @@ public class ClangBreak extends ClangToken { this.indent = indent; } + /** + * @return the number of indent levels following this line break + */ public int getIndent() { return indent; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangCommentToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangCommentToken.java index a930c9b4fc..7a6a1e2a63 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangCommentToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangCommentToken.java @@ -19,6 +19,9 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.pcode.*; +/** + * A token in source code representing (part of) a comment. + */ public class ClangCommentToken extends ClangToken { private Address srcaddr; // source address of the comment diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFieldToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFieldToken.java index 665d0b5a77..9ae3127742 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFieldToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFieldToken.java @@ -21,8 +21,7 @@ import ghidra.program.model.data.DataType; import ghidra.program.model.pcode.*; /** - * A C code token representing a structure field. - * + * A source code token representing a structure field. */ public class ClangFieldToken extends ClangToken { private DataType datatype; // Structure from which this field is a part diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncNameToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncNameToken.java index a067029c3f..3b6ab663b2 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncNameToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncNameToken.java @@ -19,10 +19,8 @@ import ghidra.program.model.address.Address; import ghidra.program.model.pcode.*; /** - * - * - * A C code token representing a function name - * It contains a link back to the pcode function object represented by the name + * A source code token representing a function name. + * It contains a link back to the p-code function object represented by the name */ public class ClangFuncNameToken extends ClangToken { private HighFunction hfunc; // Overall reference to function @@ -34,6 +32,9 @@ public class ClangFuncNameToken extends ClangToken { op = null; } + /** + * @return the HighFunction object associated with this name + */ public HighFunction getHighFunction() { return hfunc; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncProto.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncProto.java index 3579d4256c..f2bc52bcc2 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncProto.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFuncProto.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -14,20 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; - /** - * - * - * The C code syntax for a function prototype + * A grouping of source code tokens representing a function prototype */ public class ClangFuncProto extends ClangTokenGroup { - public ClangFuncProto(ClangNode par) { super(par); } + public ClangFuncProto(ClangNode par) { + super(par); + } } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFunction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFunction.java index e9188f0cc5..abe9a4e09c 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFunction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangFunction.java @@ -13,19 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jul 9, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ - package ghidra.app.decompiler; import ghidra.program.model.pcode.HighFunction; /** - * All the tokens making up one function in the display + * A grouping of source code tokens representing an entire function */ public class ClangFunction extends ClangTokenGroup { private final HighFunction hfunc; @@ -40,6 +33,9 @@ public class ClangFunction extends ClangTokenGroup { return this; } + /** + * @return the HighFunction object represented by this source code + */ public HighFunction getHighFunction() { return hfunc; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangLabelToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangLabelToken.java index bfddd2d921..e46de4f569 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangLabelToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangLabelToken.java @@ -19,8 +19,11 @@ import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.pcode.*; +/** + * A source code token representing a control-flow label. + */ public class ClangLabelToken extends ClangToken { - private Address blockaddr; // Address this is labelling + private Address blockaddr; // Address this is labeling public ClangLabelToken(ClangNode par) { super(par); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangMarkup.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangMarkup.java index 0f2438863d..536cfab391 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangMarkup.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangMarkup.java @@ -13,12 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 18, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import ghidra.program.model.pcode.*; diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangNode.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangNode.java index aa3b46fc94..a34602d08f 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangNode.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangNode.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -14,32 +13,67 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jul 7, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; -import ghidra.program.model.address.Address; - import java.awt.Color; import java.util.List; + +import ghidra.program.model.address.Address; + /** - * - * - * Generic tree interface + * A collection of source code text elements, with associated attributes, grouped in + * a tree structure. */ public interface ClangNode { + /** + * Get the immediate grouping (parent) containing this text element. If this is a + * complete document, null is returned. + * @return the parent grouping or null + */ public ClangNode Parent(); + + /** + * Get the smallest Program address associated with the code that this text represents + * @return the smallest Address + */ public Address getMinAddress(); + + /** + * Get the biggest Program address associated with the code that this text represents + * @return the biggest Address + */ public Address getMaxAddress(); + + /** + * Set a highlighting background color for all text elements + * @param c is the color to set + */ public void setHighlight(Color c); - public int numChildren(); + + /** + * Return the number of immediate groupings this text breaks up into + * @return the number of child groupings + */ + public int numChildren(); + + /** + * Get the i-th child grouping + * @param i is the index selecting the grouping + * @return the selected grouping + */ public ClangNode Child(int i); + + /** + * Get the text representing an entire function of which this is part. + * @return text for the whole function + */ public ClangFunction getClangFunction(); + + /** + * Flatten this text into a list of tokens (see ClangToken) + * @param list is the container that will contain the tokens + */ public void flatten(List list); } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangOpToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangOpToken.java index 43d17ab0d4..da205b2f08 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangOpToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangOpToken.java @@ -19,11 +19,9 @@ import ghidra.program.model.address.Address; import ghidra.program.model.pcode.*; /** - * - * - * Token representing an operation in C code text. This could be a keyword like - * "if" or "while" but could also be an operator like '+' or '*' - * The token may contain an id for the pcode object representing the operation + * A token representing a source code "operation". This could be a keyword like + * "if" or "while" but could also be an operator like '+' or '*'. + * The token may contain an id for the p-code object representing the operation. */ public class ClangOpToken extends ClangToken { private PcodeOp op; diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangReturnType.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangReturnType.java index 7c7546e573..b7400d5ed9 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangReturnType.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangReturnType.java @@ -13,12 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import ghidra.program.model.data.DataType; @@ -26,9 +20,7 @@ import ghidra.program.model.pcode.*; import ghidra.util.Msg; /** - * - * - * A group of C code tokens representing the return type of a function + * A grouping of source code tokens representing the "return type" of a function, * as at the beginning of a function prototype. */ public class ClangReturnType extends ClangTokenGroup { @@ -41,10 +33,16 @@ public class ClangReturnType extends ClangTokenGroup { datatype = null; } + /** + * @return the data-type represented by this text + */ public DataType getDataType() { return datatype; } + /** + * @return a Varnode representing the return value in the function's data-flow + */ public Varnode getVarnode() { return varnode; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangStatement.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangStatement.java index 555319dc10..50a7e29a3f 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangStatement.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangStatement.java @@ -13,21 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import ghidra.program.model.pcode.*; /** - * - * - * A C code statement. What typically appears between the ';' '{' and '}' characters. - * A statement must have a pcode operation associated with it. In the case of conditional + * A source code statement (as typically terminated by ';' in C) + * A statement must have a p-code operation associated with it. In the case of conditional * flow control operations, there are usually two lines associated with the statement one * containing the '{' and one containing '}'. The one containing the actual conditional branch * is considered a C statement, while the other one is just considered a blank line. @@ -43,6 +35,9 @@ public class ClangStatement extends ClangTokenGroup { op = null; } + /** + * @return the (final) p-code operation associated with the statement. + */ public PcodeOp getPcodeOp() { return op; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangSyntaxToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangSyntaxToken.java index 262e66435a..54fa5b431e 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangSyntaxToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangSyntaxToken.java @@ -13,21 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import ghidra.program.model.pcode.*; /** - * - * - * A C code token which is not an operation, variable, function name, or type. Like '(' or ',' - * A SyntaxToken may be or may include spacing + * A source code token which is not an operation, variable, function name, or type. Like '(' or ','. + * A SyntaxToken may be or may include spacing. As a special case, the token can be part of + * an enclosing pair of tokens, as with '(' and ')' or '{' and '}'. In this case, the token + * is either opening or closing and contains an id that matches it with its pair token. */ public class ClangSyntaxToken extends ClangToken { private int open, close; @@ -73,10 +67,16 @@ public class ClangSyntaxToken extends ClangToken { super.decode(decoder, pfactory); } + /** + * @return the pair id if this is an opening token, -1 otherwise + */ public int getOpen() { return open; } + /** + * @return the pair id if this is a closing token, -1 otherwise + */ public int getClose() { return close; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangToken.java index 23609af976..1018864087 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangToken.java @@ -13,12 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import static ghidra.program.model.pcode.AttributeId.*; @@ -32,10 +26,8 @@ import ghidra.program.model.address.Address; import ghidra.program.model.pcode.*; /** - * - * - * Class representing a C code language token - * May contain links back to pcode object + * Class representing a source code language token. + * A token has numerous display attributes and may link to the data-flow analysis */ public class ClangToken implements ClangNode { public final static int KEYWORD_COLOR = 0; // Constants must match Decompiler syntax_highlight @@ -85,10 +77,18 @@ public class ClangToken implements ClangNode { return parent; } + /** + * Get the element representing an entire line of text that contains this element + * @return the containing ClangLine + */ public ClangLine getLineParent() { return lineparent; } + /** + * Set (change) the line which this text element part of. + * @param line is the new ClangLine + */ public void setLineParent(ClangLine line) { lineparent = line; } @@ -126,38 +126,74 @@ public class ClangToken implements ClangNode { highlight = val; } + /** + * Get the background highlight color used to render this token, or null if not highlighted + * @return the Color or null + */ public Color getHighlight() { return highlight; } + /** + * Set whether or not additional "matching" highlighting is applied to this token. + * Currently this means a bounding box is drawn around the token. + * @param matchingToken is true to enable highlighting, false to disable + */ public void setMatchingToken(boolean matchingToken) { this.matchingToken = matchingToken; } + /** + * @return true if this token should be displayed with "matching" highlighting + */ public boolean isMatchingToken() { return matchingToken; } + /** + * @return true if this token represents a variable (in source code) + */ public boolean isVariableRef() { return false; } + /** + * Get the "syntax" type (color) associated with this token (keyword, type, etc) + * @return the color code + */ public int getSyntaxType() { return syntax_type; } + /** + * Set the "syntax" type (color) associated with this token + * @param syntax_type is the color code to set + */ void setSyntaxType(int syntax_type) { this.syntax_type = syntax_type; } + /** + * @return this token's display text as a string + */ public String getText() { return text; } + /** + * Set this token's display text. + * @param text is the string to set + */ void setText(String text) { this.text = text; } + /** + * Decode this token from the current position in an encoded stream + * @param decoder is the decoder for the stream + * @param pfactory is used to look up p-code objects associated with the token + * @throws DecoderException for problems decoding the stream + */ public void decode(Decoder decoder, PcodeFactory pfactory) throws DecoderException { syntax_type = DEFAULT_COLOR; for (;;) { @@ -181,6 +217,16 @@ public class ClangToken implements ClangNode { list.add(this); } + /** + * Decode one specialized token from the current position in an encoded stream. This + * serves as a factory for allocating the various objects derived from ClangToken + * @param node is the particular token type (already) decoded from the stream + * @param par is the text grouping which will contain the token + * @param decoder is the decoder for the stream + * @param pfactory is used to look up p-code objects associated with tokens + * @return the new ClangToken + * @throws DecoderException for problems decoding the stream + */ static public ClangToken buildToken(int node, ClangNode par, Decoder decoder, PcodeFactory pfactory) throws DecoderException { ClangToken token = null; @@ -218,6 +264,13 @@ public class ClangToken implements ClangNode { return token; } + /** + * Add a spacer token to the given text grouping + * @param par is the text grouping + * @param indent is the number of levels to indent + * @param indentStr is a string representing containg the number of spaces in one indent level + * @return the new spacer token + */ static public ClangToken buildSpacer(ClangNode par, int indent, String indentStr) { String spacing = new String(); for (int i = 0; i < indent; ++i) { @@ -237,9 +290,17 @@ public class ClangToken implements ClangNode { * @return HighVariable */ public HighVariable getHighVariable() { - if (Parent() instanceof ClangVariableDecl) { - return ((ClangVariableDecl) Parent()).getHighVariable(); - } + return null; + } + + /** + * Get the symbol associated with this token or null otherwise. + * This token may be directly associated with the symbol or a reference, in which + * case the symbol is looked up in the containing HighFunction + * @param highFunction is the function + * @return HighSymbol + */ + public HighSymbol getHighSymbol(HighFunction highFunction) { return null; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTokenGroup.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTokenGroup.java index 2fbf530c18..c796dd4e58 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTokenGroup.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTokenGroup.java @@ -25,7 +25,8 @@ import ghidra.program.model.address.Address; import ghidra.program.model.pcode.*; /** - * A node in a tree of C code tokens. + * A sequence of tokens that form a meaningful group in source code. This group may + * break up into subgroups and may be part of a larger group. */ public class ClangTokenGroup implements ClangNode, Iterable { private ClangNode parent; @@ -49,6 +50,10 @@ public class ClangTokenGroup implements ClangNode, Iterable { return maxaddress; } + /** + * Add additional text to this group + * @param obj is the additional text + */ public void AddTokenGroup(ClangNode obj) { Address minaddr = obj.getMinAddress(); Address maxaddr = obj.getMaxAddress(); @@ -106,6 +111,12 @@ public class ClangTokenGroup implements ClangNode, Iterable { } } + /** + * Decode this text from an encoded stream. + * @param decoder is the decoder for the stream + * @param pfactory is used to look up p-code attributes to associate with tokens + * @throws DecoderException for problems decoding the stream + */ public void decode(Decoder decoder, PcodeFactory pfactory) throws DecoderException { for (;;) { int elem = decoder.openElement(); @@ -145,7 +156,11 @@ public class ClangTokenGroup implements ClangNode, Iterable { } } - private boolean isLetterDigitOrUnderscore(char c) { + /** + * @param c is a character + * @return true if the given character is a letter, digit, or underscore + */ + private static boolean isLetterDigitOrUnderscore(char c) { return Character.isLetterOrDigit(c) || c == '_'; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTypeToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTypeToken.java index 515b03f444..dd26f16d4b 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTypeToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangTypeToken.java @@ -13,22 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import ghidra.program.model.data.DataType; import ghidra.program.model.pcode.*; /** - * - * - * A C code token representing a data type. This does not include qualifiers on the type - * like '*' (pointer to) or '[]' (array of). There should be no whitespace in the name + * A source code token representing a data-type. This does not include qualifiers on the data-type + * like '*' (pointer to) or '[]' (array of). There should be no whitespace in the name. */ public class ClangTypeToken extends ClangToken { private DataType datatype; @@ -46,6 +38,9 @@ public class ClangTypeToken extends ClangToken { return false; } + /** + * @return the data-type associated with this token + */ public DataType getDataType() { return datatype; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java index 99f55c2f49..3882094c47 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableDecl.java @@ -13,12 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * Created on Jun 12, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments - */ package ghidra.app.decompiler; import ghidra.program.model.data.DataType; @@ -26,40 +20,53 @@ import ghidra.program.model.pcode.*; import ghidra.util.Msg; /** - * - * - * A group of C code tokens forming a variable declaration. + * A grouping of source code tokens representing a variable declaration. * This can be for a one line declaration (as for local variables) or - * as part of a function prototype declaring a parameter + * as part of a function prototype declaring a parameter. */ public class ClangVariableDecl extends ClangTokenGroup { private DataType datatype; - private HighVariable typevar; + private HighSymbol symbol; public ClangVariableDecl(ClangNode par) { super(par); datatype = null; - typevar = null; + symbol = null; } + /** + * @return the data-type of the variable being declared + */ public DataType getDataType() { return datatype; } + /** + * @return the HighVariable (collection of Varnodes) associated with the variable + */ public HighVariable getHighVariable() { - return typevar; + if (symbol != null) { + return symbol.getHighVariable(); + } + return null; + } + + /** + * @return the symbol defined by this variable declaration + */ + public HighSymbol getHighSymbol() { + return symbol; } @Override public void decode(Decoder decoder, PcodeFactory pfactory) throws DecoderException { long symref = decoder.readUnsignedInteger(AttributeId.ATTRIB_SYMREF); super.decode(decoder, pfactory); - HighSymbol sym = pfactory.getSymbol(symref); - if (sym == null) { + symbol = pfactory.getSymbol(symref); + if (symbol == null) { Msg.error(this, "Invalid symbol reference: " + symref + " in " + Parent()); return; } - typevar = sym.getHighVariable(); - datatype = sym.getDataType(); + datatype = symbol.getDataType(); } } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableToken.java index 1025083088..bf28db8e4d 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/ClangVariableToken.java @@ -16,6 +16,7 @@ package ghidra.app.decompiler; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressFactory; import ghidra.program.model.pcode.*; /** @@ -76,7 +77,39 @@ public class ClangVariableToken extends ClangToken { } return inst.getHigh(); } - return super.getHighVariable(); + ClangNode parent = Parent(); + if (parent instanceof ClangVariableDecl) { + return ((ClangVariableDecl) parent).getHighVariable(); + } + return null; + } + + @Override + public HighSymbol getHighSymbol(HighFunction highFunction) { + Varnode inst = getVarnode(); + if (inst != null) { + HighVariable hvar = inst.getHigh(); + if (hvar != null) { + HighSymbol symbol = hvar.getSymbol(); + if (symbol != null) { + return symbol; + } + } + } + ClangNode parent = Parent(); + if (parent instanceof ClangVariableDecl) { + return ((ClangVariableDecl) parent).getHighSymbol(); + } + + if (highFunction == null) { + return null; + } + // Token may be from a variable reference, in which case we have to dig to find the actual symbol + Address storageAddress = getStorageAddress(highFunction.getAddressFactory()); + if (storageAddress == null) { + return null; + } + return findHighSymbol(storageAddress, highFunction); // Find symbol via the reference } @Override @@ -98,4 +131,41 @@ public class ClangVariableToken extends ClangToken { decoder.rewindAttributes(); super.decode(decoder, pfactory); } + + /** + * Get the storage address of the variable, if any. + * The variable may be directly referenced by this token, or indirectly referenced as a point. + * @param addrFactory is the factory used to construct the Address + * @return the storage Address or null if there is no variable attached + */ + private Address getStorageAddress(AddressFactory addrFactory) { + Address storageAddress = null; + if (varnode != null) { + storageAddress = varnode.getAddress(); + } + // op could be a PTRSUB, need to dig it out... + else { + storageAddress = HighFunctionDBUtil.getSpacebaseReferenceAddress(addrFactory, op); + } + return storageAddress; + } + + /** + * Find the HighSymbol the decompiler associates with a specific address. + * @param addr is the specific address + * @param highFunction is the decompiler results in which to search for the symbol + * @return the matching symbol or null if no symbol exists + */ + private static HighSymbol findHighSymbol(Address addr, HighFunction highFunction) { + HighSymbol highSymbol = null; + if (addr.isStackAddress()) { + LocalSymbolMap lsym = highFunction.getLocalSymbolMap(); + highSymbol = lsym.findLocal(addr, null); + } + else { + GlobalSymbolMap gsym = highFunction.getGlobalSymbolMap(); + highSymbol = gsym.getSymbol(addr); + } + return highSymbol; + } } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/AbstractDecompilerAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/AbstractDecompilerAction.java index f20ecf60c2..b8af322336 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/AbstractDecompilerAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/AbstractDecompilerAction.java @@ -75,77 +75,6 @@ public abstract class AbstractDecompilerAction extends DockingAction { }); } - /** - * Find the HighSymbol the decompiler associates with a specific address. - * @param addr is the specific address - * @param highFunction is the decompiler results in which to search for the symbol - * @return the matching symbol or null if no symbol exists - */ - private static HighSymbol findHighSymbol(Address addr, HighFunction highFunction) { - HighSymbol highSymbol = null; - if (addr.isStackAddress()) { - LocalSymbolMap lsym = highFunction.getLocalSymbolMap(); - highSymbol = lsym.findLocal(addr, null); - } - else { - GlobalSymbolMap gsym = highFunction.getGlobalSymbolMap(); - highSymbol = gsym.getSymbol(addr); - } - return highSymbol; - } - - /** - * Track down the HighSymbol associated with a particular token. The token may be directly attached to - * the symbol, or it may be a reference that needs to be looked up. - * @param token is the given token - * @param highFunction is the decompiler model of the function - * @return the associated HighSymbol or null if one can't be found - */ - public static HighSymbol findHighSymbolFromToken(ClangToken token, HighFunction highFunction) { - if (highFunction == null) { - return null; - } - HighVariable variable = token.getHighVariable(); - HighSymbol highSymbol = null; - if (variable == null) { - // Token may be from a variable reference, in which case we have to dig to find the actual symbol - Function function = highFunction.getFunction(); - if (function == null) { - return null; - } - Address storageAddress = getStorageAddress(token, function.getProgram()); - if (storageAddress == null) { - return null; - } - highSymbol = findHighSymbol(storageAddress, highFunction); - } - else { - highSymbol = variable.getSymbol(); - } - return highSymbol; - } - - /** - * Get the storage address of the variable attached to the given token, if any. - * The variable may be directly referenced by the token, or indirectly referenced as a point. - * @param tokenAtCursor is the given token - * @param program is the Program - * @return the storage Address or null if there is no variable attached - */ - private static Address getStorageAddress(ClangToken tokenAtCursor, Program program) { - Varnode vnode = tokenAtCursor.getVarnode(); - Address storageAddress = null; - if (vnode != null) { - storageAddress = vnode.getAddress(); - } - // op could be a PTRSUB, need to dig it out... - else if (tokenAtCursor instanceof ClangVariableToken) { - PcodeOp op = ((ClangVariableToken) tokenAtCursor).getPcodeOp(); - storageAddress = HighFunctionDBUtil.getSpacebaseReferenceAddress(program, op); - } - return storageAddress; - } - /** * Get the structure/union associated with a field token * @param tok is the token representing a field @@ -243,7 +172,7 @@ public abstract class AbstractDecompilerAction extends DockingAction { f = DecompilerUtils.getFunction(context.getProgram(), (ClangFuncNameToken) token); } else { - HighSymbol highSymbol = findHighSymbolFromToken(token, context.getHighFunction()); + HighSymbol highSymbol = token.getHighSymbol(context.getHighFunction()); if (highSymbol instanceof HighFunctionShellSymbol) { f = (Function) highSymbol.getSymbol().getObject(); } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java index 7717d7fa64..866fc659bb 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/FindReferencesToHighSymbolAction.java @@ -65,7 +65,7 @@ public class FindReferencesToHighSymbolAction extends AbstractDecompilerAction { if (token == null) { return false; } - HighSymbol highSymbol = findHighSymbolFromToken(token, context.getHighFunction()); + HighSymbol highSymbol = token.getHighSymbol(context.getHighFunction()); if (highSymbol == null || highSymbol.getStorage().isBadStorage() || !highSymbol.isGlobal()) { @@ -92,7 +92,7 @@ public class FindReferencesToHighSymbolAction extends AbstractDecompilerAction { } else { HighSymbol highSymbol = - findHighSymbolFromToken(context.getTokenAtCursor(), context.getHighFunction()); + context.getTokenAtCursor().getHighSymbol(context.getHighFunction()); location = new LabelFieldLocation(context.getProgram(), highSymbol.getStorage().getMinAddress(), highSymbol.getName()); } 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 b39094af4d..a15b02f290 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 @@ -27,9 +27,7 @@ import ghidra.app.util.HelpTopics; 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.pcode.*; import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.SymbolTable; import ghidra.util.*; @@ -62,7 +60,7 @@ public class RenameGlobalAction extends AbstractDecompilerAction { if (tokenAtCursor instanceof ClangFieldToken) { return false; } - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); if (highSymbol == null || highSymbol instanceof HighFunctionShellSymbol) { return false; } @@ -73,7 +71,7 @@ public class RenameGlobalAction extends AbstractDecompilerAction { protected void decompilerActionPerformed(DecompilerActionContext context) { PluginTool tool = context.getTool(); final ClangToken tokenAtCursor = context.getTokenAtCursor(); - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); Symbol symbol = null; if (highSymbol instanceof HighCodeSymbol) { symbol = ((HighCodeSymbol) highSymbol).getCodeSymbol(); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameLocalAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameLocalAction.java index b7a766fc75..ce19e1a7b7 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameLocalAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RenameLocalAction.java @@ -67,7 +67,7 @@ public class RenameLocalAction extends AbstractDecompilerAction { if (tokenAtCursor instanceof ClangFieldToken) { return false; } - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); if (highSymbol == null) { return false; } @@ -78,7 +78,7 @@ public class RenameLocalAction extends AbstractDecompilerAction { protected void decompilerActionPerformed(DecompilerActionContext context) { PluginTool tool = context.getTool(); final ClangToken tokenAtCursor = context.getTokenAtCursor(); - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); RenameVariableTask nameTask = new RenameVariableTask(tool, context.getProgram(), context.getComponentProvider(), tokenAtCursor, highSymbol, SourceType.USER_DEFINED); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeGlobalAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeGlobalAction.java index 08b7e9ed78..47180483df 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeGlobalAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeGlobalAction.java @@ -71,7 +71,7 @@ public class RetypeGlobalAction extends AbstractDecompilerAction { if (!tokenAtCursor.isVariableRef()) { return false; } - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); if (highSymbol == null) { return false; } @@ -85,7 +85,7 @@ public class RetypeGlobalAction extends AbstractDecompilerAction { ClangToken tokenAtCursor = context.getTokenAtCursor(); DataType dataType = null; - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); if (highSymbol == null) { return; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeLocalAction.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeLocalAction.java index eefe3ac2fb..8c7394c24a 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeLocalAction.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/RetypeLocalAction.java @@ -144,7 +144,7 @@ public class RetypeLocalAction extends AbstractDecompilerAction { if (!tokenAtCursor.isVariableRef()) { return false; } - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); if (highSymbol == null) { return false; } @@ -158,7 +158,7 @@ public class RetypeLocalAction extends AbstractDecompilerAction { ClangToken tokenAtCursor = context.getTokenAtCursor(); DataType dataType = null; - HighSymbol highSymbol = findHighSymbolFromToken(tokenAtCursor, context.getHighFunction()); + HighSymbol highSymbol = tokenAtCursor.getHighSymbol(context.getHighFunction()); if (highSymbol == null) { return; } diff --git a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/HighSymbolTest.java b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/HighSymbolTest.java index eef339ff2d..b3129dd2ea 100644 --- a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/HighSymbolTest.java +++ b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/plugin/core/decompile/HighSymbolTest.java @@ -32,6 +32,7 @@ import ghidra.app.plugin.core.decompile.actions.RenameVariableTask; import ghidra.framework.options.Options; import ghidra.program.database.symbol.CodeSymbol; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressFactory; import ghidra.program.model.data.DataType; import ghidra.program.model.data.Undefined; import ghidra.program.model.listing.*; @@ -82,9 +83,8 @@ public class HighSymbolTest extends AbstractDecompilerTest { } private void renameVariable(HighSymbol highSymbol, ClangToken tokenAtCursor, String newName) { - RenameVariableTask rename = - new RenameVariableTask(provider.getTool(), highSymbol.getProgram(), - provider, tokenAtCursor, highSymbol, SourceType.USER_DEFINED); + RenameVariableTask rename = new RenameVariableTask(provider.getTool(), + highSymbol.getProgram(), provider, tokenAtCursor, highSymbol, SourceType.USER_DEFINED); assertTrue(rename.isValid(newName)); modifyProgram(p -> { rename.commit(); @@ -93,8 +93,8 @@ public class HighSymbolTest extends AbstractDecompilerTest { } private void isolateVariable(HighSymbol highSymbol, ClangToken tokenAtCursor, String newName) { - IsolateVariableTask isolate = new IsolateVariableTask(provider.getTool(), program, - provider, tokenAtCursor, highSymbol, SourceType.USER_DEFINED); + IsolateVariableTask isolate = new IsolateVariableTask(provider.getTool(), program, provider, + tokenAtCursor, highSymbol, SourceType.USER_DEFINED); assertTrue(isolate.isValid(newName)); modifyProgram(p -> { isolate.commit(); @@ -223,7 +223,8 @@ public class HighSymbolTest extends AbstractDecompilerTest { assertTrue(token instanceof ClangVariableToken); assertNull(token.getHighVariable()); // No HighVariable associated with the token PcodeOp op = ((ClangVariableToken) token).getPcodeOp(); - Address addr = HighFunctionDBUtil.getSpacebaseReferenceAddress(provider.getProgram(), op); + AddressFactory addrFactory = provider.getProgram().getAddressFactory(); + Address addr = HighFunctionDBUtil.getSpacebaseReferenceAddress(addrFactory, op); HighFunction highFunction = getHighFunction(); LocalSymbolMap lsym = highFunction.getLocalSymbolMap(); HighSymbol highSymbol = lsym.findLocal(addr, null); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java index 94fa6c8090..aa994cd738 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighConstant.java @@ -111,7 +111,8 @@ public class HighConstant extends HighVariable { symbol = globalMap.populateSymbol(symref, null, -1); if (symbol == null) { PcodeOp op = ((VarnodeAST) represent).getLoneDescend(); - Address addr = HighFunctionDBUtil.getSpacebaseReferenceAddress(program, op); + Address addr = HighFunctionDBUtil + .getSpacebaseReferenceAddress(program.getAddressFactory(), op); if (addr != null) { Data data = program.getListing().getDataAt(addr); DataType dt = data == null ? DataType.DEFAULT : data.getDataType(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java index d7ea18c3ee..7b35995af1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java @@ -734,11 +734,11 @@ public class HighFunctionDBUtil { * Get the Address referred to by a spacebase reference. Address-of references are encoded in * the p-code syntax tree as: {@code vn = PTRSUB(, #const)}. This decodes the reference and * returns the Address - * @param program is the program containing the Address + * @param addrFactory is the factory used to construct the Address * @param op is the PTRSUB op encoding the reference * @return the recovered Address (or null if not correct form) */ - public static Address getSpacebaseReferenceAddress(Program program, PcodeOp op) { + public static Address getSpacebaseReferenceAddress(AddressFactory addrFactory, PcodeOp op) { Address storageAddress = null; if (op == null) { return storageAddress; @@ -747,13 +747,13 @@ public class HighFunctionDBUtil { Varnode vnode = op.getInput(0); Varnode cnode = op.getInput(1); if (vnode.isRegister()) { - AddressSpace stackspace = program.getAddressFactory().getStackSpace(); + AddressSpace stackspace = addrFactory.getStackSpace(); if (stackspace != null) { storageAddress = stackspace.getAddress(cnode.getOffset()); } } else { - AddressSpace space = program.getAddressFactory().getDefaultAddressSpace(); + AddressSpace space = addrFactory.getDefaultAddressSpace(); if (space instanceof SegmentedAddressSpace) { // Assume this is a "full" encoding of the offset int innersize = space.getPointerSize();