GP-2012_James_java_attribute_improvements

This commit is contained in:
James 2022-05-10 18:22:43 +00:00
parent f2510e4dc8
commit 7d8b222183
7 changed files with 266 additions and 7 deletions

View file

@ -720,6 +720,26 @@ public class JavaAnalyzer extends AbstractJavaAnalyzer implements AnalysisWorker
explicitParams.get(i), function.getProgram()); explicitParams.get(i), function.getProgram());
params.add(currentParam); params.add(currentParam);
} }
MethodParametersAttribute methodParamsAttr = methodInfo.getMethodParameters();
if (methodParamsAttr != null) {
MethodParameters[] methodParams = methodParamsAttr.getMethodParameters();
int indexAdjust = methodInfo.isStatic() ? 0 : 1;
if (methodParams.length == (params.size() - indexAdjust)) {
for (int i = 0; i < methodParams.length; ++i) {
int nameIndex = methodParams[i].getNameIndex();
if (nameIndex == 0) {
continue; // no name
}
String name = ((ConstantPoolUtf8Info) constantPool[nameIndex]).getString();
params.get(i + indexAdjust).setName(name, SourceType.ANALYSIS);
}
}
else {
Msg.warn(this, "methodParams/params size mismatch for " + function.getName());
Msg.warn(this,
"methodParams: " + methodParams.length + "; params: " + params.size());
}
}
function.replaceParameters(params, FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true, function.replaceParameters(params, FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS, true,
SourceType.ANALYSIS); SourceType.ANALYSIS);

View file

@ -223,9 +223,11 @@ public class MethodInfoJava implements StructConverter {
stringBuffer.append(", "); stringBuffer.append(", ");
} }
ConstantPoolUtf8Info parameterName = ConstantPoolUtf8Info parameterName =
(ConstantPoolUtf8Info) constantPool[localVariables[i].getNameIndex()]; (ConstantPoolUtf8Info) constantPool[localVariables[i]
.getNameIndex()];
ConstantPoolUtf8Info parameterDescriptor = ConstantPoolUtf8Info parameterDescriptor =
(ConstantPoolUtf8Info) constantPool[localVariables[i].getDescriptorIndex()]; (ConstantPoolUtf8Info) constantPool[localVariables[i]
.getDescriptorIndex()];
stringBuffer.append(DescriptorDecoder.getTypeNameFromDescriptor( stringBuffer.append(DescriptorDecoder.getTypeNameFromDescriptor(
parameterDescriptor.getString(), false, true)); parameterDescriptor.getString(), false, true));
@ -247,8 +249,8 @@ public class MethodInfoJava implements StructConverter {
int i = 0; int i = 0;
for (int k = 0; k < exceptionsAttribute.getNumberOfExceptions(); k++) { for (int k = 0; k < exceptionsAttribute.getNumberOfExceptions(); k++) {
ConstantPoolClassInfo exceptionClass = ConstantPoolClassInfo exceptionClass =
(ConstantPoolClassInfo) constantPool[exceptionsAttribute.getExceptionIndexTableEntry( (ConstantPoolClassInfo) constantPool[exceptionsAttribute
k)]; .getExceptionIndexTableEntry(k)];
ConstantPoolUtf8Info exceptionClassName = ConstantPoolUtf8Info exceptionClassName =
(ConstantPoolUtf8Info) constantPool[exceptionClass.getNameIndex()]; (ConstantPoolUtf8Info) constantPool[exceptionClass.getNameIndex()];
String className = exceptionClassName.getString(); String className = exceptionClassName.getString();
@ -306,6 +308,15 @@ public class MethodInfoJava implements StructConverter {
return null; return null;
} }
public MethodParametersAttribute getMethodParameters() {
for (AbstractAttributeInfo attributeInfo : attributes) {
if (attributeInfo instanceof MethodParametersAttribute) {
return (MethodParametersAttribute) attributeInfo;
}
}
return null;
}
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
String name = String name =

View file

@ -20,6 +20,7 @@ import java.io.IOException;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava; import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
import ghidra.javaclass.format.constantpool.ConstantPoolUtf8Info; import ghidra.javaclass.format.constantpool.ConstantPoolUtf8Info;
import ghidra.util.Msg;
public class AttributeFactory { public class AttributeFactory {
@ -61,6 +62,10 @@ public class AttributeFactory {
return new LocalVariableTableAttribute(reader, constantPool); return new LocalVariableTableAttribute(reader, constantPool);
case AttributesConstants.LocalVariableTypeTable: case AttributesConstants.LocalVariableTypeTable:
return new LocalVariableTypeTableAttribute(reader); return new LocalVariableTypeTableAttribute(reader);
case AttributesConstants.MethodParameters:
return new MethodParametersAttribute(reader);
case AttributesConstants.Module:
return new ModuleAttribute(reader);
case AttributesConstants.ModuleMainClass: case AttributesConstants.ModuleMainClass:
return new ModuleMainClassAttribute(reader); return new ModuleMainClassAttribute(reader);
case AttributesConstants.ModulePackages: case AttributesConstants.ModulePackages:
@ -87,10 +92,11 @@ public class AttributeFactory {
return new StackMapTableAttribute(reader); return new StackMapTableAttribute(reader);
case AttributesConstants.Synthetic: case AttributesConstants.Synthetic:
return new SyntheticAttribute(reader); return new SyntheticAttribute(reader);
case AttributesConstants.Module:
return new ModuleAttribute(reader);
default: default:
throw new RuntimeException("Unknown attribute type: " + utf8.getString()); Msg.warn(AttributeFactory.class, "Unknown attribute type: " + utf8.getString() +
" at index " + (reader.getPointerIndex() - 2));
return new UnsupportedAttributeInfo(reader);
} }
} }
} }

View file

@ -39,6 +39,7 @@ public final class AttributesConstants {
"RuntimeInvisibleParameterAnnotations"; "RuntimeInvisibleParameterAnnotations";
public final static String AnnotationDefault = "AnnotationDefault"; public final static String AnnotationDefault = "AnnotationDefault";
public final static String BootstrapMethods = "BootstrapMethods"; public final static String BootstrapMethods = "BootstrapMethods";
public final static String MethodParameters = "MethodParameters";
public final static String Module = "Module"; public final static String Module = "Module";
public final static String ModulePackages = "ModulePackages"; public final static String ModulePackages = "ModulePackages";
public final static String ModuleMainClass = "ModuleMainClass"; public final static String ModuleMainClass = "ModuleMainClass";

View file

@ -0,0 +1,104 @@
/* ###
* 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.javaclass.format.attributes;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* This class stores information about a single method parameter
*/
public class MethodParameters implements StructConverter {
private final static int ACC_FINAL_INDEX = 0x10;
private final static int ACC_SYNTHETIC_INDEX = 0x1000;
private final static int ACC_MANDATED_INDEX = 0x8000;
private int name_index;
private int access_flags;
/**
* Creates a new {@code MethodParameters} object from the current index of {@code reader}
* and advances the index.
* @param reader source of bytes
* @throws IOException thrown if problem reading bytes
*/
public MethodParameters(BinaryReader reader) throws IOException {
name_index = Short.toUnsignedInt(reader.readNextShort());
access_flags = Short.toUnsignedInt(reader.readNextShort());
}
/**
* Returns the name index. If the index is 0, then this formal parameter
* does not have a name. Otherwise, the constant pool entry at the index
* is a {@code CONSTANT_Utf8_Info} structure encoding the name of the
* parameter.
* @return index or 0
*/
public int getNameIndex() {
return name_index;
}
/**
* Returns a integer whose bits are treated as flags to encode various properties
* of the parameter
* @return access flags
*/
public int getAcccessFlags() {
return access_flags;
}
/**
* Returns a {@code boolean} representing whether or not the parameter was declared
* {@code final}
* @return true if final
*/
public boolean isFinal() {
return (access_flags & ACC_FINAL_INDEX) != 0;
}
/**
* Returns a {@code boolean} representing whether or not the parameter is synthetic, i.e.,
* a compiler artifact rather than being explicitly or implicitly declared in the source.
* @return true if synthetic
*/
public boolean isSynthetic() {
return (access_flags & ACC_SYNTHETIC_INDEX) != 0;
}
/**
* Returns a {@code boolean} representing whether or not the parameter is mandated, i.e.,
* implicitly declared in source code and forced to be emitted by all compilers.
* @return true if synthetic
*/
public boolean isMandated() {
return (access_flags & ACC_MANDATED_INDEX) != 0;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType structure = new StructureDataType("method_parameters", 0);
structure.add(WORD, "name_index", null);
structure.add(WORD, "access_flags", null);
return structure;
}
}

View file

@ -0,0 +1,68 @@
/* ###
* 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.javaclass.format.attributes;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.util.exception.DuplicateNameException;
/**
* This attribute records info about the (formal) parameters of a method,
* such as parameter names.
*/
public class MethodParametersAttribute extends AbstractAttributeInfo {
private byte parameters_count;
private MethodParameters[] parameters;
/**
* Creates a {@code MethodParametersAttribute} object from the current index of
* {@code reader} and advances index.
* @param reader source of bytes
* @throws IOException if problem reading bytes
*/
protected MethodParametersAttribute(BinaryReader reader) throws IOException {
super(reader);
parameters_count = reader.readNextByte();
int size = Byte.toUnsignedInt(parameters_count);
parameters = new MethodParameters[size];
for (int i = 0; i < size; ++i) {
parameters[i] = new MethodParameters(reader);
}
}
/**
* Returns information about the parameters of the method
* @return parameter info
*/
public MethodParameters[] getMethodParameters() {
return parameters;
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType structure = getBaseStructure("MethodParameters_attribute");
structure.add(BYTE, "num_parameters", null);
for (int i = 0; i < parameters.length; ++i) {
structure.add(parameters[i].toDataType(), "parameter" + i, null);
}
return structure;
}
}

View file

@ -0,0 +1,49 @@
/* ###
* 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.javaclass.format.attributes;
import java.io.IOException;
import ghidra.app.util.bin.BinaryReader;
import ghidra.program.model.data.*;
import ghidra.util.exception.DuplicateNameException;
/**
* This class in an artificial attribute (i.e., not defined in the JVM specification)
* whose purpose is to consume attributes that are not (yet) supported by Ghidra
* so that class file parsing can proceed.
*/
public class UnsupportedAttributeInfo extends AbstractAttributeInfo {
/**
* Creates a {@code UnsupportedAttributeInfo} object from the current index of
* {@code reader} and advances the index.
* @param reader source of bytes
* @throws IOException thrown if problem reading bytes
*/
protected UnsupportedAttributeInfo(BinaryReader reader) throws IOException {
super(reader);
reader.setPointerIndex(reader.getPointerIndex() + getAttributeLength());
}
@Override
public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType structure = getBaseStructure("Unsupported_attribute");
structure.add(new ArrayDataType(BYTE, getAttributeLength(), BYTE.getLength()));
return structure;
}
}