GP-1100 fixing pinned symbols

This commit is contained in:
ghidragon 2023-03-22 11:11:52 -04:00
parent 6660f9663b
commit d694bb7d7b
3 changed files with 109 additions and 36 deletions

View File

@ -642,8 +642,8 @@ public class FunctionEditorModel {
try {
if (autoParamCount < oldAutoCount) {
if (oldParams.get(autoParamCount)
.getStorage()
.getAutoParameterType() != storage.getAutoParameterType()) {
.getStorage()
.getAutoParameterType() != storage.getAutoParameterType()) {
adjustSelectionForRowRemoved(i);
}
}
@ -1047,6 +1047,24 @@ public class FunctionEditorModel {
return true;
}
private FunctionSignature getFunctionSignature() {
FunctionDefinitionDataType funDt = new FunctionDefinitionDataType(name);
funDt.setReturnType(returnInfo.getFormalDataType());
List<ParameterDefinition> params = new ArrayList<>();
for (ParamInfo paramInfo : parameters) {
if (paramInfo.isAutoParameter()) {
continue;
}
String paramName = paramInfo.getName();
DataType paramDt = paramInfo.getFormalDataType();
params.add(new ParameterDefinitionImpl(paramName, paramDt, null));
}
funDt.setArguments(params.toArray(new ParameterDefinition[params.size()]));
funDt.setVarArgs(hasVarArgs);
return funDt;
}
Program getProgram() {
return program;
}
@ -1170,7 +1188,7 @@ public class FunctionEditorModel {
public void parseSignatureFieldText() throws ParseException, CancelledException {
FunctionSignatureParser parser =
new FunctionSignatureParser(program.getDataTypeManager(), dataTypeManagerService);
FunctionDefinitionDataType f = parser.parse(function.getSignature(), signatureFieldText);
FunctionDefinitionDataType f = parser.parse(getFunctionSignature(), signatureFieldText);
setFunctionData(f);
isInParsingMode = false;

View File

@ -16,7 +16,6 @@
package ghidra.app.util.parser;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.help.UnsupportedOperationException;
@ -98,7 +97,6 @@ public class FunctionSignatureParser {
*/
public FunctionDefinitionDataType parse(FunctionSignature originalSignature,
String signatureText) throws ParseException, CancelledException {
dtMap.clear();
nameMap.clear();
if (dtmService != null) {
@ -236,18 +234,18 @@ public class FunctionSignatureParser {
}
private String replaceDataTypeIfNeeded(String text, DataType dataType, String replacementName) {
String displayName = dataType.getDisplayName();
if (canParse(displayName)) {
String datatypeName = dataType.getName();
if (canParseType(datatypeName)) {
return text;
}
dtMap.put(replacementName, dataType);
return substitute(text, displayName, replacementName);
return substitute(text, datatypeName, replacementName);
}
private String replaceNameIfNeeded(String text, String name, String replacementName) {
if (canParse(name)) {
if (canParseName(name)) {
return text;
}
nameMap.put(replacementName, name);
@ -272,36 +270,11 @@ public class FunctionSignatureParser {
return dt;
}
// The following regex pattern attempts to isolate the parameter name from
// the beginning of a parameter specification. Since the name is optional,
// additional steps must be taken in code to ensure that the trailing word of
// a multi-word type-specified is not treated as a name (e.g., unsigned long).
//
// The regex pattern attempts to isolate the following fields:
//
// <type-specifier> [<array-specifier>|<pointer-specifier>]* [param-name]
// group-1 group-3 group-4
//
// Note: group-2 is an inner group to group-3 is not useful
//
private static final Pattern parameterNameCapturePattern =
Pattern.compile("(.+?)((\\[\\d*\\]|\\*\\d*)\\s*)*([^\\s\\[\\*]+)");
private DataType resolveDataType(String dataTypeName) throws CancelledException {
if (dtMap.containsKey(dataTypeName)) {
return dtMap.get(dataTypeName);
}
Matcher m = parameterNameCapturePattern.matcher(dataTypeName);
if (m.matches()) {
boolean hasPointerOrArraySpec = m.group(3) != null;
boolean hasName = (m.group(4) != null) && (m.group(4).length() != 0);
if (hasPointerOrArraySpec && hasName) {
// name after array/pointer spec - dataTypeName is not a valid datatype
return null;
}
}
DataType dataType = null;
try {
dataType = dataTypeParser.parse(dataTypeName);
@ -330,7 +303,7 @@ public class FunctionSignatureParser {
if (nameMap.containsKey(name)) {
return nameMap.get(name);
}
if (!canParse(name)) {
if (!canParseName(name)) {
throw new ParseException("Can't parse name: " + name);
}
return name;
@ -340,10 +313,14 @@ public class FunctionSignatureParser {
return text.replaceFirst(Pattern.quote(searchString), replacementString);
}
private boolean canParse(String text) {
private boolean canParseName(String text) {
return !StringUtils.containsAny(text, "()*[], ");
}
private boolean canParseType(String text) {
return !StringUtils.containsAny(text, "()<>,");
}
/**
* Provides a simple caching datatype manager service wrapper.<br>
* Implementation intended for use with {@link FunctionSignatureParser}

View File

@ -194,6 +194,75 @@ public class FunctionSignatureParserTest extends AbstractGhidraHeadedIntegration
assertEquals("char Bob(longlong a, uint b)", dt.getRepresentation(null, null, 0));
}
@Test
public void testReturnPointerToNoPointer() throws Exception {
FunctionSignature f = fun("char *", "Bob");
FunctionDefinitionDataType dt = parser.parse(f, "char Bob()");
assertEquals("char Bob(void)", dt.getRepresentation(null, null, 0));
}
@Test
public void testReturnPointerToSizedPointer() throws Exception {
FunctionSignature f = fun("char *", "Bob");
FunctionDefinitionDataType dt = parser.parse(f, "char *32 Bob()");
assertEquals("char * Bob(void)", dt.getRepresentation(null, null, 0));
assertEquals("char *", dt.getReturnType().getDisplayName());
}
@Test
public void testReturnPointerToPointerPointer() throws Exception {
FunctionSignature f = fun("char *", "Bob");
FunctionDefinitionDataType dt = parser.parse(f, "char * * Bob()");
assertEquals("char * * Bob(void)", dt.getRepresentation(null, null, 0));
}
@Test
public void testChangeReturnTypeToIncludeSizedPointer() throws Exception {
FunctionSignature f = fun("char", "Bob");
FunctionDefinitionDataType dt = parser.parse(f, "char *32 Bob(void)");
assertEquals("char * Bob(void)", dt.getRepresentation(null, null, 0));
assertEquals("char *32", dt.getReturnType().getName());
}
@Test
public void testParseFunctionNameWithSizedPointerReturnType() throws Exception {
FunctionSignature f = fun("char *32", "Bob");
FunctionDefinitionDataType dt = parser.parse(f, "char *32 Joe()");
assertEquals("char * Joe(void)", dt.getRepresentation(null, null, 0));
}
@Test
public void testParamPointerToSizedPointer() throws Exception {
FunctionSignature f = fun("int", "Bob", "char *", "p1");
FunctionDefinitionDataType dt = parser.parse(f, "int Bob(char *32 p1)");
assertEquals("int Bob(char * p1)", dt.getRepresentation(null, null, 0));
ParameterDefinition[] arguments = dt.getArguments();
assertEquals("char *32", arguments[0].getDataType().getName());
}
@Test
public void testParamPointerToPointerPointer() throws Exception {
FunctionSignature f = fun("int", "Bob", "char *", "p1");
FunctionDefinitionDataType dt = parser.parse(f, "int Bob(char * * p1)");
assertEquals("int Bob(char * * p1)", dt.getRepresentation(null, null, 0));
}
@Test
public void testChangeParamTypeToIncludeSizedPointer() throws Exception {
FunctionSignature f = fun("int", "Bob", "char", "p1");
FunctionDefinitionDataType dt = parser.parse(f, "int Bob(char *32 p1)");
assertEquals("int Bob(char * p1)", dt.getRepresentation(null, null, 0));
ParameterDefinition[] arguments = dt.getArguments();
assertEquals("char *32", arguments[0].getDataType().getName());
}
@Test
public void testParseParamNameWithSizedPointerDataType() throws Exception {
FunctionSignature f = fun("int", "Bob", "char *32", "p1");
FunctionDefinitionDataType dt = parser.parse(f, "int Bob(char *32 p2)");
assertEquals("int Bob(char * p2)", dt.getRepresentation(null, null, 0));
}
@Test
public void testSpacesNotAllowedInTypedFunctionName() {
FunctionSignature f = fun("int", "Bob", "int", "a");
@ -419,6 +488,15 @@ public class FunctionSignatureParserTest extends AbstractGhidraHeadedIntegration
if (name.equals("int")) {
return new IntegerDataType();
}
if (name.equals("char *")) {
return new PointerDataType(new CharDataType());
}
if (name.equals("char *32")) {
return new Pointer32DataType(new CharDataType());
}
if (name.equals("char * *32")) {
return new Pointer32DataType(new PointerDataType(new CharDataType()));
}
return new StructureDataType(name, 2);
}