mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch
'origin/GP-5453-dragonmacher-decompiler-locations--SQUASHED' (Closes #7518)
This commit is contained in:
commit
4aa78ae6d0
25 changed files with 880 additions and 322 deletions
|
@ -36,6 +36,7 @@ import docking.widgets.fieldpanel.support.FieldLocation;
|
|||
import generic.Unique;
|
||||
import ghidra.app.decompiler.*;
|
||||
import ghidra.app.decompiler.component.*;
|
||||
import ghidra.app.decompiler.location.DefaultDecompilerLocation;
|
||||
import ghidra.app.plugin.assembler.*;
|
||||
import ghidra.app.plugin.assembler.sleigh.sem.*;
|
||||
import ghidra.app.plugin.core.analysis.*;
|
||||
|
@ -1610,10 +1611,14 @@ public class StackUnwinderTest extends AbstractGhidraHeadedDebuggerTest {
|
|||
FieldLocation fLoc = new FieldLocation(i, j, r, c);
|
||||
ClangToken token = clangField.getToken(fLoc);
|
||||
if (token != null && tokText.equals(token.getText())) {
|
||||
DecompilerLocation loc = token.getMinAddress() == null ? null
|
||||
: new DecompilerLocation(program, token.getMinAddress(),
|
||||
function.getEntryPoint(), results, token, i.intValue(),
|
||||
0);
|
||||
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
DecompilerLocationInfo info =
|
||||
new DecompilerLocationInfo(entryPoint, results, token,
|
||||
i.intValue(), 0);
|
||||
DefaultDecompilerLocation loc = token.getMinAddress() == null ? null
|
||||
: new DefaultDecompilerLocation(program,
|
||||
token.getMinAddress(), info);
|
||||
return new HoverLocation(loc, fLoc, field, token);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -110,7 +110,7 @@ public class VariableLocFieldFactory extends AbstractVariableFieldFactory {
|
|||
VariableProxy variableProxy = (VariableProxy) proxy;
|
||||
Variable sv = variableProxy.getObject();
|
||||
return new VariableLocFieldLocation(sv.getProgram(), variableProxy.getLocationAddress(),
|
||||
variableProxy.getObject(), col);
|
||||
sv, col);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.awt.event.*;
|
|||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
@ -873,6 +874,13 @@ public class ListingPanel extends JPanel implements FieldMouseListener, FieldLoc
|
|||
* @param view the set of address to include in the view.
|
||||
*/
|
||||
public void setView(AddressSetView view) {
|
||||
|
||||
AddressIndexMap currentMap = layoutModel.getAddressIndexMap();
|
||||
AddressSetView originalView = currentMap.getOriginalAddressSet();
|
||||
if (Objects.equals(originalView, view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
layoutModel.setAddressSet(view);
|
||||
updateProviders();
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -30,7 +30,7 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.util.datastruct.Duo.Side;
|
||||
|
||||
/**
|
||||
* This is a base class for actions in a {@link DecompilerDiffCodeComparisonPanel}
|
||||
* This is a base class for actions in a {@link DecompilerCodeComparisonPanel}
|
||||
*/
|
||||
public abstract class AbstractMatchedTokensAction extends DockingAction {
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -15,150 +15,43 @@
|
|||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
public class DecompilerLocation extends ProgramLocation {
|
||||
private Address functionEntryPoint;
|
||||
private DecompileResults results;
|
||||
private ClangToken token;
|
||||
private String tokenName;
|
||||
private int lineNumber;
|
||||
private int charPos;
|
||||
/**
|
||||
* Represents a location in the Decompiler. This interface allows the Decompiler to subclass more
|
||||
* general {@link ProgramLocation}s while adding more detailed Decompiler information.
|
||||
*/
|
||||
public interface DecompilerLocation {
|
||||
|
||||
public DecompilerLocation(Program program, Address address, Address functionEntryPoint,
|
||||
DecompileResults results, ClangToken token, int lineNumber, int charPos) {
|
||||
super(program, address);
|
||||
this.functionEntryPoint = functionEntryPoint;
|
||||
this.results = results;
|
||||
this.token = token;
|
||||
this.tokenName = token.getText();
|
||||
this.lineNumber = lineNumber;
|
||||
this.charPos = charPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor required for restoring a program location from XML.
|
||||
*/
|
||||
public DecompilerLocation() {
|
||||
}
|
||||
|
||||
public Address getFunctionEntryPoint() {
|
||||
return functionEntryPoint;
|
||||
}
|
||||
public Address getFunctionEntryPoint();
|
||||
|
||||
/**
|
||||
* Results from the decompilation
|
||||
*
|
||||
* @return C-AST, DFG, and CFG object. null if there are no results attached to this location
|
||||
*/
|
||||
public DecompileResults getDecompile() {
|
||||
return results;
|
||||
}
|
||||
public DecompileResults getDecompile();
|
||||
|
||||
/**
|
||||
* C text token at the current cursor location
|
||||
*
|
||||
* @return token at this location, could be null if there are no decompiler results
|
||||
*/
|
||||
public ClangToken getToken() {
|
||||
return token;
|
||||
}
|
||||
public ClangToken getToken();
|
||||
|
||||
public String getTokenName() {
|
||||
return tokenName;
|
||||
}
|
||||
/**
|
||||
* {@return the name of the token for the current location}
|
||||
*/
|
||||
public String getTokenName();
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + charPos;
|
||||
result =
|
||||
prime * result + ((functionEntryPoint == null) ? 0 : functionEntryPoint.hashCode());
|
||||
result = prime * result + lineNumber;
|
||||
result = prime * result + ((tokenName == null) ? 0 : tokenName.hashCode());
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* {@return the line number}
|
||||
*/
|
||||
public int getLineNumber();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DecompilerLocation other = (DecompilerLocation) obj;
|
||||
if (charPos != other.charPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lineNumber != other.lineNumber) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(functionEntryPoint, other.functionEntryPoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(tokenName, other.tokenName)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveState(SaveState saveState) {
|
||||
super.saveState(saveState);
|
||||
saveState.putString("_FUNCTION_ENTRY", functionEntryPoint.toString());
|
||||
saveState.putString("_TOKEN_TEXT", tokenName);
|
||||
saveState.putInt("_LINE_NUM", lineNumber);
|
||||
saveState.putInt("_CHAR_POS", charPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState(Program program1, SaveState obj) {
|
||||
super.restoreState(program1, obj);
|
||||
String addrStr = obj.getString("_FUNCTION_ENTRY", "0");
|
||||
functionEntryPoint = program1.parseAddress(addrStr)[0];
|
||||
tokenName = obj.getString("_TOKEN_TEXT", "");
|
||||
lineNumber = obj.getInt("_LINE_NUM", 0);
|
||||
charPos = obj.getInt("_CHAR_POS", 0);
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public int getCharPos() {
|
||||
return charPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(getClass().getSimpleName());
|
||||
buf.append('@');
|
||||
buf.append(addr.toString());
|
||||
buf.append(", line=");
|
||||
buf.append(lineNumber);
|
||||
buf.append(", character=");
|
||||
buf.append(charPos);
|
||||
buf.append(", token=");
|
||||
buf.append(tokenName);
|
||||
return buf.toString();
|
||||
}
|
||||
/**
|
||||
* {@return the character position}
|
||||
*/
|
||||
public int getCharPos();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
public class DecompilerLocationInfo {
|
||||
|
||||
private Address entryPoint;
|
||||
private DecompileResults results;
|
||||
private ClangToken token;
|
||||
private String tokenName;
|
||||
private int lineNumber;
|
||||
private int charPos;
|
||||
|
||||
public DecompilerLocationInfo(Address entryPoint, DecompileResults results,
|
||||
ClangToken token, int lineNumber, int charPos) {
|
||||
this.entryPoint = entryPoint;
|
||||
this.results = results;
|
||||
this.token = token;
|
||||
this.tokenName = token.getText();
|
||||
this.lineNumber = lineNumber;
|
||||
this.charPos = charPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor required for restoring a program location from XML.
|
||||
*/
|
||||
public DecompilerLocationInfo() {
|
||||
}
|
||||
|
||||
public Address getFunctionEntryPoint() {
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Results from the decompilation
|
||||
*
|
||||
* @return C-AST, DFG, and CFG object. null if there are no results attached to this location
|
||||
*/
|
||||
public DecompileResults getDecompile() {
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* C text token at the current cursor location
|
||||
*
|
||||
* @return token at this location, could be null if there are no decompiler results
|
||||
*/
|
||||
public ClangToken getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public String getTokenName() {
|
||||
return tokenName;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public int getCharPos() {
|
||||
return charPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + charPos;
|
||||
result =
|
||||
prime * result + ((entryPoint == null) ? 0 : entryPoint.hashCode());
|
||||
result = prime * result + lineNumber;
|
||||
result = prime * result + ((tokenName == null) ? 0 : tokenName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DecompilerLocationInfo other = (DecompilerLocationInfo) obj;
|
||||
if (charPos != other.charPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lineNumber != other.lineNumber) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(entryPoint, other.entryPoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(tokenName, other.tokenName)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void saveState(SaveState saveState) {
|
||||
saveState.putString("_FUNCTION_ENTRY", entryPoint.toString());
|
||||
saveState.putString("_TOKEN_TEXT", tokenName);
|
||||
saveState.putInt("_LINE_NUM", lineNumber);
|
||||
saveState.putInt("_CHAR_POS", charPos);
|
||||
}
|
||||
|
||||
public void restoreState(Program program1, SaveState obj) {
|
||||
String addrStr = obj.getString("_FUNCTION_ENTRY", "0");
|
||||
entryPoint = program1.parseAddress(addrStr)[0];
|
||||
tokenName = obj.getString("_TOKEN_TEXT", "");
|
||||
lineNumber = obj.getInt("_LINE_NUM", 0);
|
||||
charPos = obj.getInt("_CHAR_POS", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(getClass().getSimpleName());
|
||||
buf.append(", line=");
|
||||
buf.append(lineNumber);
|
||||
buf.append(", character=");
|
||||
buf.append(charPos);
|
||||
buf.append(", token=");
|
||||
buf.append(tokenName);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
|
@ -41,13 +41,14 @@ import generic.theme.GColor;
|
|||
import ghidra.app.decompiler.*;
|
||||
import ghidra.app.decompiler.component.hover.DecompilerHoverService;
|
||||
import ghidra.app.decompiler.component.margin.*;
|
||||
import ghidra.app.decompiler.location.*;
|
||||
import ghidra.app.plugin.core.decompile.DecompilerClipboardProvider;
|
||||
import ghidra.app.plugin.core.decompile.actions.DecompilerSearchLocation;
|
||||
import ghidra.app.util.viewer.util.ScrollpaneAlignedHorizontalLayout;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.pcode.*;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.util.*;
|
||||
|
@ -979,17 +980,103 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
|||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Address address = DecompilerUtils.getClosestAddress(getProgram(), token);
|
||||
if (address == null) {
|
||||
address = DecompilerUtils.findAddressBefore(layoutController.getFields(), token);
|
||||
}
|
||||
|
||||
Function function = decompileData.getFunction();
|
||||
if (address == null) {
|
||||
address = decompileData.getFunction().getEntryPoint();
|
||||
address = function.getEntryPoint();
|
||||
}
|
||||
|
||||
return new DecompilerLocation(decompileData.getProgram(), address,
|
||||
decompileData.getFunction().getEntryPoint(), decompileData.getDecompileResults(), token,
|
||||
location.getIndex().intValue(), location.col);
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
DecompileResults results = decompileData.getDecompileResults();
|
||||
int lineNumber = location.getIndex().intValue();
|
||||
int charPos = location.col;
|
||||
DecompilerLocationInfo info =
|
||||
new DecompilerLocationInfo(entryPoint, results, token, lineNumber, charPos);
|
||||
Program program = decompileData.getProgram();
|
||||
ProgramLocation signatureLocation = createFunctionSignatureLocation(token, address, info);
|
||||
if (signatureLocation != null) {
|
||||
return signatureLocation;
|
||||
}
|
||||
|
||||
return new DefaultDecompilerLocation(program, address, info);
|
||||
}
|
||||
|
||||
private ProgramLocation createFunctionSignatureLocation(ClangToken token, Address address,
|
||||
DecompilerLocationInfo info) {
|
||||
|
||||
Function function = decompileData.getFunction();
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
if (!entryPoint.equals(address)) {
|
||||
// Another address implies that we are not on the function signature
|
||||
return null;
|
||||
}
|
||||
|
||||
if (token instanceof ClangFuncNameToken ft) {
|
||||
// if the token address is the entry point of this function, then create a location that
|
||||
// will place the cursor on the function signature in the listing
|
||||
Program program = decompileData.getProgram();
|
||||
String functionName = ft.getText();
|
||||
return new FunctionNameDecompilerLocation(program, entryPoint, functionName, info);
|
||||
}
|
||||
else if (token instanceof ClangVariableToken cvt) {
|
||||
return createVariableDeclarationLocation(cvt, address, info);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ProgramLocation createVariableDeclarationLocation(ClangVariableToken cvt,
|
||||
Address address, DecompilerLocationInfo info) {
|
||||
|
||||
Function function = decompileData.getFunction();
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
Program program = decompileData.getProgram();
|
||||
Variable variable = getVariable(cvt);
|
||||
if (variable != null) {
|
||||
return new VariableDecompilerLocation(program, entryPoint, variable, info);
|
||||
}
|
||||
|
||||
HighVariable highVar = cvt.getHighVariable();
|
||||
if (highVar == null) {
|
||||
// decomp param that is not in the listing; put on signature
|
||||
return new FunctionNameDecompilerLocation(program, entryPoint, cvt.getText(), info);
|
||||
}
|
||||
|
||||
HighSymbol highSymbol = highVar.getSymbol();
|
||||
if (highSymbol.isParameter()) {
|
||||
// decomp param that is not in the listing; put on signature
|
||||
return new FunctionNameDecompilerLocation(program, entryPoint, cvt.getText(), info);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Variable getVariable(ClangVariableToken token) {
|
||||
|
||||
HighVariable highVar = token.getHighVariable();
|
||||
if (highVar == null) {
|
||||
return null;
|
||||
}
|
||||
HighSymbol highSymbol = highVar.getSymbol();
|
||||
Variable variable = HighFunctionDBUtil.getFunctionVariable(highSymbol);
|
||||
if (variable != null) {
|
||||
return variable;
|
||||
}
|
||||
|
||||
Function function = decompileData.getFunction();
|
||||
Symbol symbol = highSymbol.getSymbol();
|
||||
Variable[] locals = function.getLocalVariables();
|
||||
for (Variable local : locals) {
|
||||
Symbol localSymbol = local.getSymbol();
|
||||
if (symbol == localSymbol) {
|
||||
return local;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSearchResults(SearchLocation searchLocation) {
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.decompiler.location;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.app.decompiler.*;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
/**
|
||||
* The default location handed out when the user clicks inside of the Decompiler.
|
||||
*/
|
||||
public class DefaultDecompilerLocation extends ProgramLocation implements DecompilerLocation {
|
||||
|
||||
private DecompilerLocationInfo info;
|
||||
|
||||
public DefaultDecompilerLocation(Program program, Address address,
|
||||
DecompilerLocationInfo info) {
|
||||
super(program, address);
|
||||
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public DefaultDecompilerLocation() {
|
||||
// for restoring from xml
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getFunctionEntryPoint() {
|
||||
return info.getFunctionEntryPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecompileResults getDecompile() {
|
||||
return info.getDecompile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClangToken getToken() {
|
||||
return info.getToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenName() {
|
||||
return info.getTokenName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber() {
|
||||
return info.getLineNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharPos() {
|
||||
return info.getCharPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveState(SaveState ss) {
|
||||
super.saveState(ss);
|
||||
info.saveState(ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState(Program p, SaveState ss) {
|
||||
super.restoreState(p, ss);
|
||||
info.restoreState(p, ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = info.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DefaultDecompilerLocation other = (DefaultDecompilerLocation) obj;
|
||||
return Objects.equals(info, other.info);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.decompiler.location;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.app.decompiler.*;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.FunctionNameFieldLocation;
|
||||
|
||||
/**
|
||||
* A location created when a function name is clicked in the Decompiler.
|
||||
*/
|
||||
public class FunctionNameDecompilerLocation extends FunctionNameFieldLocation
|
||||
implements DecompilerLocation {
|
||||
|
||||
private DecompilerLocationInfo info;
|
||||
|
||||
public FunctionNameDecompilerLocation(Program program, Address address, String funcionName,
|
||||
DecompilerLocationInfo info) {
|
||||
super(program, address, funcionName);
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getFunctionEntryPoint() {
|
||||
return info.getFunctionEntryPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecompileResults getDecompile() {
|
||||
return info.getDecompile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClangToken getToken() {
|
||||
return info.getToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenName() {
|
||||
return info.getTokenName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber() {
|
||||
return info.getLineNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharPos() {
|
||||
return info.getCharPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveState(SaveState ss) {
|
||||
super.saveState(ss);
|
||||
info.saveState(ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState(Program p, SaveState ss) {
|
||||
super.restoreState(p, ss);
|
||||
info.restoreState(p, ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = info.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionNameDecompilerLocation other = (FunctionNameDecompilerLocation) obj;
|
||||
return Objects.equals(info, other.info);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.decompiler.location;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ghidra.app.decompiler.*;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.Variable;
|
||||
import ghidra.program.util.VariableLocFieldLocation;
|
||||
|
||||
/**
|
||||
* A location created when a function variable is clicked in the Decompiler.
|
||||
*/
|
||||
public class VariableDecompilerLocation extends VariableLocFieldLocation
|
||||
implements DecompilerLocation {
|
||||
|
||||
private DecompilerLocationInfo info;
|
||||
|
||||
public VariableDecompilerLocation(Program program, Address locationAddr, Variable var,
|
||||
DecompilerLocationInfo info) {
|
||||
super(program, locationAddr, var, 0);
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getFunctionEntryPoint() {
|
||||
return info.getFunctionEntryPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecompileResults getDecompile() {
|
||||
return info.getDecompile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClangToken getToken() {
|
||||
return info.getToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenName() {
|
||||
return info.getTokenName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineNumber() {
|
||||
return info.getLineNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharPos() {
|
||||
return info.getCharPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveState(SaveState ss) {
|
||||
super.saveState(ss);
|
||||
info.saveState(ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState(Program p, SaveState ss) {
|
||||
super.restoreState(p, ss);
|
||||
info.restoreState(p, ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = info.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VariableDecompilerLocation other = (VariableDecompilerLocation) obj;
|
||||
return Objects.equals(info, other.info);
|
||||
}
|
||||
}
|
|
@ -17,8 +17,7 @@ package ghidra.app.plugin.core.decompile;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -34,10 +33,11 @@ import ghidra.app.plugin.core.navigation.NextPrevAddressPlugin;
|
|||
import ghidra.app.services.GoToService;
|
||||
import ghidra.app.util.navigation.GoToServiceImpl;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Library;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.OperandFieldLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.test.ClassicSampleX86ProgramBuilder;
|
||||
|
||||
public class DecompilerNavigationTest extends AbstractDecompilerTest {
|
||||
|
@ -77,7 +77,7 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
|
|||
|
||||
private Program buildProgram() throws Exception {
|
||||
ClassicSampleX86ProgramBuilder builder =
|
||||
new ClassicSampleX86ProgramBuilder("notepad", false, this);
|
||||
new ClassicSampleX86ProgramBuilder("sample", false, this);
|
||||
|
||||
// need a default label at 01002cf0, so make up a reference
|
||||
builder.createMemoryReference("01002ce5", "01002cf0", RefType.FALL_THROUGH,
|
||||
|
@ -230,6 +230,111 @@ public class DecompilerNavigationTest extends AbstractDecompilerTest {
|
|||
assertCurrentAddress(f1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecompilerLocationEvent_VariableDeclaration() {
|
||||
|
||||
/*
|
||||
undefined4 FUN_010059a3(undefined4 param_1,undefined4 param_2,int param_3)
|
||||
|
||||
{
|
||||
int iVar1;
|
||||
int iVar2;
|
||||
int *piVar3;
|
||||
undefined4 uVar4;
|
||||
int iVar5;
|
||||
bool bVar6;
|
||||
int local_14;
|
||||
int local_10;
|
||||
undefined1 local_c [4];
|
||||
undefined4 local_8;
|
||||
*/
|
||||
|
||||
decompile("010059a3"); // FUN_010059a3
|
||||
|
||||
// 16: undefined4 local_8;
|
||||
int line = 16;
|
||||
int character = 13;
|
||||
assertToken("local_8", line, character);
|
||||
setDecompilerLocation(line, character);
|
||||
|
||||
assertLocationType(loc -> loc instanceof VariableLocFieldLocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecompilerLocationEvent_FunctionSignature_Parameter() {
|
||||
|
||||
/*
|
||||
undefined4 FUN_010059a3(undefined4 param_1,undefined4 param_2,int param_3)
|
||||
|
||||
{
|
||||
int iVar1;
|
||||
int iVar2;
|
||||
int *piVar3;
|
||||
undefined4 uVar4;
|
||||
int iVar5;
|
||||
bool bVar6;
|
||||
int local_14;
|
||||
int local_10;
|
||||
undefined1 local_c [4];
|
||||
undefined4 local_8;
|
||||
*/
|
||||
|
||||
decompile("010059a3"); // FUN_010059a3
|
||||
|
||||
// 4: undefined4 FUN_010059a3(undefined4 param_1
|
||||
int line = 4;
|
||||
int character = 36;
|
||||
assertToken("param_1", line, character);
|
||||
setDecompilerLocation(line, character);
|
||||
|
||||
assertLocationType(loc -> loc instanceof VariableLocFieldLocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecompilerLocationEvent_FunctionSignature_FunctionName() {
|
||||
|
||||
/*
|
||||
undefined4 FUN_010059a3(undefined4 param_1,undefined4 param_2,int param_3)
|
||||
|
||||
{
|
||||
int iVar1;
|
||||
int iVar2;
|
||||
int *piVar3;
|
||||
undefined4 uVar4;
|
||||
int iVar5;
|
||||
bool bVar6;
|
||||
int local_14;
|
||||
int local_10;
|
||||
undefined1 local_c [4];
|
||||
undefined4 local_8;
|
||||
*/
|
||||
|
||||
decompile("010059a3"); // FUN_010059a3
|
||||
|
||||
// 4: undefined4 FUN_010059a3(undefined4 param_1
|
||||
int line = 4;
|
||||
int character = 12;
|
||||
assertToken("FUN_010059a3", line, character);
|
||||
setDecompilerLocation(line, character);
|
||||
|
||||
assertLocationType(loc -> loc instanceof FunctionNameFieldLocation);
|
||||
}
|
||||
|
||||
private void assertLocationType(Predicate<ProgramLocation> predicate) {
|
||||
waitForSwing();
|
||||
|
||||
BooleanSupplier success = () -> {
|
||||
ProgramLocation loc = codeBrowser.getCurrentLocation();
|
||||
return predicate.test(loc);
|
||||
};
|
||||
|
||||
Supplier<String> failureMessage =
|
||||
() -> "Listing is not at the expected field location. Current location: " +
|
||||
codeBrowser.getCurrentLocation();
|
||||
|
||||
waitForCondition(success, failureMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertCurrentAddress(Address expected) {
|
||||
codeBrowser.updateNow();
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -19,12 +19,10 @@ import db.DBRecord;
|
|||
import ghidra.program.database.DBObjectCache;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
/**
|
||||
* Symbols that represent "classes"
|
||||
* Symbols that represent classes
|
||||
*/
|
||||
|
||||
public class ClassSymbol extends SymbolDB {
|
||||
|
||||
private GhidraClassDB ghidraClass;
|
||||
|
@ -42,17 +40,11 @@ public class ClassSymbol extends SymbolDB {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getSymbolType()
|
||||
*/
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
return SymbolType.CLASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getObject()
|
||||
*/
|
||||
@Override
|
||||
public Object getObject() {
|
||||
lock.acquire();
|
||||
|
@ -68,9 +60,6 @@ public class ClassSymbol extends SymbolDB {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isPrimary()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
return true;
|
||||
|
@ -82,17 +71,6 @@ public class ClassSymbol extends SymbolDB {
|
|||
return parentSymbol != null ? parentSymbol.isExternal() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getProgramLocation()
|
||||
*/
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isValidParent(ghidra.program.model.symbol.Namespace)
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
return super.isValidParent(parent) &&
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -32,7 +32,6 @@ import ghidra.program.util.ProgramLocation;
|
|||
* EXTERNAL:
|
||||
* String stringData - external memory address/label
|
||||
*/
|
||||
|
||||
public class CodeSymbol extends SymbolDB {
|
||||
|
||||
/**
|
||||
|
@ -58,9 +57,6 @@ public class CodeSymbol extends SymbolDB {
|
|||
super(mgr, cache, addr, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getSymbolType()
|
||||
*/
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
return SymbolType.LABEL;
|
||||
|
@ -124,9 +120,6 @@ public class CodeSymbol extends SymbolDB {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getObject()
|
||||
*/
|
||||
@Override
|
||||
public Object getObject() {
|
||||
lock.acquire();
|
||||
|
@ -155,9 +148,6 @@ public class CodeSymbol extends SymbolDB {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isPrimary()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
if (getSource() == SourceType.DEFAULT || isExternal()) {
|
||||
|
@ -166,9 +156,6 @@ public class CodeSymbol extends SymbolDB {
|
|||
return doCheckIsPrimary();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#setPrimary()
|
||||
*/
|
||||
@Override
|
||||
public boolean setPrimary() {
|
||||
lock.acquire();
|
||||
|
@ -205,17 +192,11 @@ public class CodeSymbol extends SymbolDB {
|
|||
doSetPrimary(primary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getProgramLocation()
|
||||
*/
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return new LabelFieldLocation(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isValidParent(ghidra.program.model.symbol.Namespace)
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
return super.isValidParent(parent) &&
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -57,9 +57,6 @@ public class FunctionSymbol extends SymbolDB {
|
|||
this.functionMgr = symbolMgr.getFunctionManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getSymbolType()
|
||||
*/
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
return SymbolType.FUNCTION;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -22,7 +22,6 @@ import ghidra.program.model.listing.CircularDependencyException;
|
|||
import ghidra.program.model.listing.Library;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramEvent;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
@ -33,7 +32,6 @@ import ghidra.util.exception.InvalidInputException;
|
|||
* Symbol data usage:
|
||||
* String stringData - associated program project file path
|
||||
*/
|
||||
|
||||
public class LibrarySymbol extends SymbolDB {
|
||||
|
||||
private LibraryDB library;
|
||||
|
@ -93,6 +91,7 @@ public class LibrarySymbol extends SymbolDB {
|
|||
.setObjChanged(ProgramEvent.EXTERNAL_PATH_CHANGED, getName(), oldPath, newPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
return SymbolType.LIBRARY;
|
||||
}
|
||||
|
@ -115,14 +114,6 @@ public class LibrarySymbol extends SymbolDB {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getProgramLocation()
|
||||
*/
|
||||
public ProgramLocation getProgramLocation() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
return super.isValidParent(parent) &&
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -19,15 +19,13 @@ import db.DBRecord;
|
|||
import ghidra.program.database.DBObjectCache;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
|
||||
/**
|
||||
* Symbol class for namespaces.
|
||||
*/
|
||||
|
||||
public class NamespaceSymbol extends SymbolDB {
|
||||
|
||||
NamespaceDB namespace;
|
||||
private NamespaceDB namespace;
|
||||
|
||||
/**
|
||||
* Construct a new namespace symbol
|
||||
|
@ -36,13 +34,11 @@ public class NamespaceSymbol extends SymbolDB {
|
|||
* @param addr the address for this symbol.
|
||||
* @param record the record for this symbol.
|
||||
*/
|
||||
NamespaceSymbol(SymbolManager mgr, DBObjectCache<SymbolDB> cache, Address addr, DBRecord record) {
|
||||
NamespaceSymbol(SymbolManager mgr, DBObjectCache<SymbolDB> cache, Address addr,
|
||||
DBRecord record) {
|
||||
super(mgr, cache, addr, record);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.database.symbol.SymbolDB#isPrimary()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
return true;
|
||||
|
@ -54,25 +50,11 @@ public class NamespaceSymbol extends SymbolDB {
|
|||
return parentSymbol != null ? parentSymbol.isExternal() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getSymbolType()
|
||||
*/
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
return SymbolType.NAMESPACE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getProgramLocation()
|
||||
*/
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getObject()
|
||||
*/
|
||||
@Override
|
||||
public Object getObject() {
|
||||
return getNamespace();
|
||||
|
@ -85,9 +67,6 @@ public class NamespaceSymbol extends SymbolDB {
|
|||
return namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isValidParent(ghidra.program.model.symbol.Namespace)
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
// TODO: Not sure what other constraints should be placed on namespace movement
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -100,9 +100,6 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
return variableStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getSymbolType()
|
||||
*/
|
||||
@Override
|
||||
public SymbolType getSymbolType() {
|
||||
return type;
|
||||
|
@ -115,18 +112,12 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
return isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.database.symbol.SymbolDB#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// TODO: not sure what constitutes equality since address will differ
|
||||
return obj == this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#delete()
|
||||
*/
|
||||
@Override
|
||||
public boolean delete() {
|
||||
lock.acquire();
|
||||
|
@ -146,9 +137,6 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getObject()
|
||||
*/
|
||||
@Override
|
||||
public Object getObject() {
|
||||
FunctionDB func = getFunction();
|
||||
|
@ -158,9 +146,6 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isPrimary()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
return false;
|
||||
|
@ -178,9 +163,6 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
getParentNamespace().getID());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#getProgramLocation()
|
||||
*/
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
Variable var = (Variable) getObject();
|
||||
|
@ -190,9 +172,6 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.program.model.symbol.Symbol#isValidParent(ghidra.program.model.symbol.Namespace)
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
// symbol is locked to single function and can't be moved
|
||||
|
@ -270,9 +249,8 @@ public class VariableSymbolDB extends SymbolDB {
|
|||
}
|
||||
|
||||
/**
|
||||
* Change the storage address and data-type associated with this
|
||||
* variable symbol.
|
||||
* @param newStorage
|
||||
* Change the storage address and data-type associated with this variable symbol.
|
||||
* @param newStorage the new storage
|
||||
* @param dt data-type
|
||||
*/
|
||||
public void setStorageAndDataType(VariableStorage newStorage, DataType dt) {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -18,7 +18,6 @@ package ghidra.program.model.address;
|
|||
import ghidra.program.model.listing.CircularDependencyException;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -140,11 +139,6 @@ public class GlobalSymbol implements Symbol {
|
|||
return new Reference[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String newName, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
|
|
@ -385,6 +385,44 @@ public class HighFunctionDBUtil {
|
|||
return res;
|
||||
}
|
||||
|
||||
private static Variable getLocalVariable(Function function, VariableStorage storage,
|
||||
Address pcAddr) {
|
||||
|
||||
if (storage.isHashStorage()) {
|
||||
|
||||
long hashVal = storage.getFirstVarnode().getOffset();
|
||||
for (Variable ul : function.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER)) {
|
||||
// Note: assumes there is only one hash method used for unique locals
|
||||
if (ul.getFirstStorageVarnode().getOffset() == hashVal) {
|
||||
return ul;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int firstUseOffset = 0;
|
||||
if (pcAddr != null) {
|
||||
firstUseOffset = (int) pcAddr.subtract(function.getEntryPoint());
|
||||
}
|
||||
|
||||
for (Variable otherVar : function.getLocalVariables()) {
|
||||
if (otherVar.getFirstUseOffset() != firstUseOffset) {
|
||||
// other than parameters we will have a hard time identifying
|
||||
// local variable conflicts due to differences in scope (i.e., first-use)
|
||||
continue;
|
||||
}
|
||||
|
||||
VariableStorage otherStorage = otherVar.getVariableStorage();
|
||||
if (otherStorage.intersects(storage)) {
|
||||
if (otherStorage.equals(storage)) {
|
||||
return otherVar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level routine for clearing any variables in the
|
||||
* database which conflict with this variable and return
|
||||
|
@ -477,6 +515,38 @@ public class HighFunctionDBUtil {
|
|||
return parameters[slot];
|
||||
}
|
||||
|
||||
public static Variable getFunctionVariable(HighSymbol highSymbol) {
|
||||
|
||||
HighFunction highFunction = highSymbol.getHighFunction();
|
||||
Function function = highFunction.getFunction();
|
||||
HighVariable highVar = highSymbol.getHighVariable();
|
||||
if (highSymbol.isParameter()) {
|
||||
|
||||
int slot = ((HighParam) highVar).getSlot();
|
||||
Parameter parameter = function.getParameter(slot);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
if (highSymbol.isGlobal()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
VariableStorage storage = highSymbol.getStorage();
|
||||
Address pcAddr = highSymbol.getPCAddress();
|
||||
Variable localVariable = getLocalVariable(function, storage, pcAddr);
|
||||
|
||||
if (!storage.isHashStorage() && highVar != null && highVar.requiresDynamicStorage()) {
|
||||
DynamicEntry entry = DynamicEntry.build(highVar.getRepresentative());
|
||||
storage = entry.getStorage();
|
||||
pcAddr = entry.getPCAdress(); // The address may change from original Varnode
|
||||
}
|
||||
|
||||
if (localVariable != null) {
|
||||
return localVariable;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename and/or retype the specified variable in the database. All parameters may be flushed
|
||||
* to the database if typed parameter inconsistency detected.
|
||||
|
|
|
@ -128,9 +128,14 @@ public interface Symbol {
|
|||
public Reference[] getReferences();
|
||||
|
||||
/**
|
||||
* @return a program location corresponding to this symbol
|
||||
* Returns a program location for this symbol; may be null. This allows implementations to
|
||||
* return a more specific program location than what is typically used by the system.
|
||||
*
|
||||
* @return the location
|
||||
*/
|
||||
public ProgramLocation getProgramLocation();
|
||||
public default ProgramLocation getProgramLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name this symbol.
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -38,7 +38,7 @@ public class FunctionLocation extends ProgramLocation {
|
|||
* @param functionAddr the function address
|
||||
* @param row the row in the field
|
||||
* @param col the display piece on the row
|
||||
* @param charOffset the character position within the display piece specifed by row,col
|
||||
* @param charOffset the character position within the display piece specified by row,col
|
||||
*/
|
||||
protected FunctionLocation(Program program, Address locationAddr, Address functionAddr, int row,
|
||||
int col, int charOffset) {
|
||||
|
@ -53,9 +53,6 @@ public class FunctionLocation extends ProgramLocation {
|
|||
protected FunctionLocation() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (super.equals(obj)) {
|
||||
|
|
|
@ -25,18 +25,16 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.program.model.symbol.*;
|
||||
|
||||
/**
|
||||
* The <CODE>LableFieldLocation</CODE> class contains specific location information
|
||||
* within the LABEL field of a CodeUnitLocation object.
|
||||
* This class contains specific location information within the label field of a
|
||||
* {@link CodeUnitLocation}
|
||||
*/
|
||||
public class LabelFieldLocation extends CodeUnitLocation {
|
||||
private SymbolPath symbolPath;
|
||||
|
||||
/**
|
||||
* Default constructor needed for restoring
|
||||
* a label field location from XML
|
||||
* Default constructor needed for restoring a label field location from XML
|
||||
*/
|
||||
public LabelFieldLocation() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,8 +43,9 @@ public class LabelFieldLocation extends CodeUnitLocation {
|
|||
* @param program the program of the location
|
||||
* @param addr address of the location; should not be null
|
||||
* @param componentPath array of indexes for each nested data component; the
|
||||
* index is the data component's index within its parent; may be null
|
||||
* index is the data component's index within its parent; may be null.
|
||||
* @param label the label String at this location.
|
||||
* @param namespace the namespace; may be null.
|
||||
* @param row the row in list of labels as displayed by the label field. Only used for
|
||||
* program location comparison purposes.
|
||||
* @param charOffset the column position within the label string for this location.
|
||||
|
@ -113,9 +112,6 @@ public class LabelFieldLocation extends CodeUnitLocation {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the label string at this location.
|
||||
*/
|
||||
public String getName() {
|
||||
return symbolPath.getName();
|
||||
}
|
||||
|
@ -143,9 +139,6 @@ public class LabelFieldLocation extends CodeUnitLocation {
|
|||
return symbolPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String representation of this location.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ", Label = " + symbolPath.getPath();
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -48,6 +48,7 @@ public class ProgramLocation implements Cloneable, Comparable<ProgramLocation> {
|
|||
private int row;
|
||||
private int col;
|
||||
private int charOffset;
|
||||
private boolean hasBeenRestored;
|
||||
|
||||
/**
|
||||
* Construct a new ProgramLocation.
|
||||
|
@ -237,24 +238,31 @@ public class ProgramLocation implements Cloneable, Comparable<ProgramLocation> {
|
|||
/**
|
||||
* Restore this program location using the given program and save state object.
|
||||
*
|
||||
* @param program1 program to restore from
|
||||
* @param newProgram program to restore from
|
||||
* @param obj the save state to restore from
|
||||
*/
|
||||
public void restoreState(Program program1, SaveState obj) {
|
||||
this.program = program1;
|
||||
public void restoreState(Program newProgram, SaveState obj) {
|
||||
|
||||
if (hasBeenRestored) {
|
||||
// ProgramLoations are intended to be immutable. Calling this repeatedly breaks that.
|
||||
Msg.debug(this, "restoreState() has been called multiple times");
|
||||
return;
|
||||
}
|
||||
hasBeenRestored = true;
|
||||
|
||||
program = newProgram;
|
||||
String addrStr = obj.getString("_ADDRESS", "0");
|
||||
String byteAddrStr = obj.getString("_BYTE_ADDR", addrStr);
|
||||
String refAddrStr = obj.getString("_REF_ADDRESS", null);
|
||||
componentPath = obj.getInts("_COMP_PATH", null);
|
||||
addr = ProgramUtilities.parseAddress(program1, addrStr);
|
||||
byteAddr = ProgramUtilities.parseAddress(program1, byteAddrStr);
|
||||
addr = ProgramUtilities.parseAddress(program, addrStr);
|
||||
byteAddr = ProgramUtilities.parseAddress(program, byteAddrStr);
|
||||
if (refAddrStr != null) {
|
||||
refAddr = ProgramUtilities.parseAddress(program1, refAddrStr);
|
||||
refAddr = ProgramUtilities.parseAddress(program, refAddrStr);
|
||||
}
|
||||
col = obj.getInt("_COLUMN", 0);
|
||||
row = obj.getInt("_ROW", 0);
|
||||
charOffset = obj.getInt("_CHAR_OFFSET", 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -271,18 +279,24 @@ public class ProgramLocation implements Cloneable, Comparable<ProgramLocation> {
|
|||
}
|
||||
|
||||
try {
|
||||
Class<?> locClass = Class.forName(className);
|
||||
ProgramLocation loc = (ProgramLocation) locClass.getConstructor().newInstance();
|
||||
Class<?> locationClass = Class.forName(className);
|
||||
if (locationClass.isInterface()) {
|
||||
// This check is needed due to a refactoring that has changed a class into an
|
||||
// interface. The class name may have been saved into the tool. Upon restoring we
|
||||
// may try to restore that class. If that class is now an interface, the restore
|
||||
// will not work.
|
||||
return null;
|
||||
}
|
||||
|
||||
ProgramLocation loc = (ProgramLocation) locationClass.getConstructor().newInstance();
|
||||
loc.restoreState(program, saveState);
|
||||
if (loc.getAddress() != null) {
|
||||
return loc;
|
||||
}
|
||||
// no address, it must be in a removed block; we can't use it
|
||||
}
|
||||
catch (RuntimeException e) { // state may not parse the address if it is no longer valid
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
// not sure why we are ignoring this--if you know, then please let everyone else know
|
||||
// this can happen for locations created by plugins that are no longer installed
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | NoSuchMethodException e) {
|
||||
Msg.showError(ProgramLocation.class, null, "Programming Error",
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
@ -68,6 +68,7 @@ public class VariableLocFieldLocation extends VariableLocation {
|
|||
|
||||
/**
|
||||
* Gets the location string. (For stack variables this is the offset as a string.)
|
||||
* @return the location string
|
||||
*/
|
||||
public String getLoc() {
|
||||
return loc;
|
||||
|
@ -83,19 +84,24 @@ public class VariableLocFieldLocation extends VariableLocation {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
if (this == obj) {
|
||||
return true;
|
||||
if (!super.equals(obj))
|
||||
}
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
VariableLocFieldLocation other = (VariableLocFieldLocation) obj;
|
||||
if (loc == null) {
|
||||
if (other.loc != null)
|
||||
if (other.loc != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!loc.equals(other.loc))
|
||||
else if (!loc.equals(other.loc)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.util.List;
|
|||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.CircularDependencyException;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -98,7 +97,7 @@ public class StubSymbol implements Symbol {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidParent(Namespace parent) {
|
||||
public boolean isValidParent(Namespace nsParent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -132,11 +131,6 @@ public class StubSymbol implements Symbol {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgramLocation getProgramLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String newName, SourceType source)
|
||||
throws DuplicateNameException, InvalidInputException {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue