mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
Merge remote-tracking branch 'origin/GP-2717_TokenSymbolAccess'
(Closes #4670)
This commit is contained in:
commit
73e4c17f2a
27 changed files with 315 additions and 219 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.*;
|
||||
|
|
|
@ -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<ClangNode> list);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ClangNode> {
|
||||
private ClangNode parent;
|
||||
|
@ -49,6 +50,10 @@ public class ClangTokenGroup implements ClangNode, Iterable<ClangNode> {
|
|||
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<ClangNode> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<ClangNode> {
|
|||
}
|
||||
}
|
||||
|
||||
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 == '_';
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(<spacebase>, #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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue