mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-02 01:10:26 +08:00
GT_2757 fixed java stream decompile bug
This commit is contained in:
+21
-11
@@ -44,30 +44,40 @@ public abstract class ConstantPool {
|
|||||||
public boolean hasThisPtr = false;
|
public boolean hasThisPtr = false;
|
||||||
public boolean isConstructor = false;
|
public boolean isConstructor = false;
|
||||||
|
|
||||||
public StringBuilder build(long ref,PcodeDataTypeManager dtmanage) {
|
public StringBuilder build(long ref, PcodeDataTypeManager dtmanage) {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("<cpoolrec");
|
buf.append("<cpoolrec");
|
||||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "ref", ref);
|
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "ref", ref);
|
||||||
if (tag == STRING_LITERAL)
|
if (tag == STRING_LITERAL) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "string");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "string");
|
||||||
else if (tag == CLASS_REFERENCE)
|
}
|
||||||
|
else if (tag == CLASS_REFERENCE) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "classref");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "classref");
|
||||||
else if (tag == POINTER_METHOD)
|
}
|
||||||
|
else if (tag == POINTER_METHOD) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "method");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "method");
|
||||||
else if (tag == POINTER_FIELD)
|
}
|
||||||
|
else if (tag == POINTER_FIELD) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "field");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "field");
|
||||||
else if (tag == ARRAY_LENGTH)
|
}
|
||||||
|
else if (tag == ARRAY_LENGTH) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "arraylength");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "arraylength");
|
||||||
else if (tag == INSTANCE_OF)
|
}
|
||||||
|
else if (tag == INSTANCE_OF) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "instanceof");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "instanceof");
|
||||||
else if (tag == CHECK_CAST)
|
}
|
||||||
|
else if (tag == CHECK_CAST) {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "checkcast");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "checkcast");
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
SpecXmlUtils.encodeStringAttribute(buf, "tag", "primitive");
|
SpecXmlUtils.encodeStringAttribute(buf, "tag", "primitive");
|
||||||
if (hasThisPtr)
|
}
|
||||||
|
if (hasThisPtr) {
|
||||||
SpecXmlUtils.encodeBooleanAttribute(buf, "hasthis", true);
|
SpecXmlUtils.encodeBooleanAttribute(buf, "hasthis", true);
|
||||||
if (isConstructor)
|
}
|
||||||
|
if (isConstructor) {
|
||||||
SpecXmlUtils.encodeBooleanAttribute(buf, "constructor", true);
|
SpecXmlUtils.encodeBooleanAttribute(buf, "constructor", true);
|
||||||
|
}
|
||||||
buf.append(">\n");
|
buf.append(">\n");
|
||||||
if (tag == PRIMITIVE) {
|
if (tag == PRIMITIVE) {
|
||||||
buf.append("<value>");
|
buf.append("<value>");
|
||||||
|
|||||||
@@ -100,14 +100,6 @@
|
|||||||
</pcode>
|
</pcode>
|
||||||
</callotherfixup>
|
</callotherfixup>
|
||||||
|
|
||||||
<callotherfixup targetop="lookupswitchCallOther">
|
|
||||||
<pcode dynamic="true">
|
|
||||||
<input name="default"/>
|
|
||||||
<input name="numPairs"/>
|
|
||||||
<input name ="padding"/>
|
|
||||||
</pcode>
|
|
||||||
</callotherfixup>
|
|
||||||
|
|
||||||
<callotherfixup targetop="multianewarrayCallOther">
|
<callotherfixup targetop="multianewarrayCallOther">
|
||||||
<pcode dynamic="true">
|
<pcode dynamic="true">
|
||||||
<input name="cpool_index_multianewarray"/>
|
<input name="cpool_index_multianewarray"/>
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ define pcodeop invokeinterfaceCallOther;
|
|||||||
define pcodeop invokespecialCallOther;
|
define pcodeop invokespecialCallOther;
|
||||||
define pcodeop invokestaticCallOther;
|
define pcodeop invokestaticCallOther;
|
||||||
define pcodeop invokevirtualCallOther;
|
define pcodeop invokevirtualCallOther;
|
||||||
define pcodeop lookupswitchCallOther;
|
|
||||||
define pcodeop multianewarrayCallOther;
|
define pcodeop multianewarrayCallOther;
|
||||||
define pcodeop putStaticCallOther;
|
define pcodeop putStaticCallOther;
|
||||||
define pcodeop putFieldCallOther;
|
define pcodeop putFieldCallOther;
|
||||||
@@ -418,8 +417,8 @@ Default:"default" addr is defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4
|
|||||||
|
|
||||||
:checkcast index is (in_table_switch=0 & in_lookup_switch=0 & op=0xc0); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
|
:checkcast index is (in_table_switch=0 & in_lookup_switch=0 & op=0xc0); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
|
||||||
{
|
{
|
||||||
_object: $(SIZE) = *:$(SIZE) SP;
|
#_object: $(SIZE) = *:$(SIZE) SP;
|
||||||
throwExceptionOp(_object);
|
#throwExceptionOp(_object);
|
||||||
|
|
||||||
#_res:1 = cpool(_object,index,$(CPOOL_CHECKCAST));
|
#_res:1 = cpool(_object,index,$(CPOOL_CHECKCAST));
|
||||||
#throwExceptionOp(_res);
|
#throwExceptionOp(_res);
|
||||||
@@ -428,9 +427,12 @@ Default:"default" addr is defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4
|
|||||||
#_ref: $(SIZE) = cpool(0:4,index,$(CPOOL_CHECKCAST));
|
#_ref: $(SIZE) = cpool(0:4,index,$(CPOOL_CHECKCAST));
|
||||||
#checkcastOp(_object,_ref);
|
#checkcastOp(_object,_ref);
|
||||||
|
|
||||||
#_object:$(SIZE) = 0;
|
_object:$(SIZE) = 0;
|
||||||
#pop(_object);
|
pop(_object);
|
||||||
#_res:1 = cpool(_object,index,$(CPOOL_INSTANCEOF));
|
_object = cpool(_object,index,$(CPOOL_CHECKCAST));
|
||||||
|
push(_object);
|
||||||
|
|
||||||
|
#_res:1 = cpool(_object,index,$(CPOOL_CHECKCAST));
|
||||||
#_result:$(SIZE) = zext(_res);
|
#_result:$(SIZE) = zext(_res);
|
||||||
#push(_result);
|
#push(_result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import ghidra.javaclass.format.attributes.CodeAttribute;
|
|||||||
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.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.program.model.data.PointerDataType;
|
||||||
import ghidra.program.model.lang.LanguageCompilerSpecPair;
|
import ghidra.program.model.lang.LanguageCompilerSpecPair;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
@@ -43,6 +44,8 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
|
|
||||||
private static final String JAVA_NAME = "Java Class File";
|
private static final String JAVA_NAME = "Java Class File";
|
||||||
private Register alignmentReg;
|
private Register alignmentReg;
|
||||||
|
public static final long CODE_OFFSET = 0x10000L;
|
||||||
|
public static final String CONSTANT_POOL = "constantPool";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
|
public Collection<LoadSpec> findSupportedLoadSpecs(ByteProvider provider) throws IOException {
|
||||||
@@ -61,23 +64,25 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
return loadSpecs;
|
return loadSpecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkClass(ByteProvider provider) {
|
private boolean checkClass(ByteProvider provider) throws IOException {
|
||||||
BinaryReader reader = new BinaryReader(provider, false);
|
BinaryReader reader = new BinaryReader(provider, false);
|
||||||
ClassFileJava classFile;
|
int magic = reader.peekNextInt();
|
||||||
|
//if it doesn't begin with the 0xCAFEBABE it's not a class file
|
||||||
|
if (magic != JavaClassConstants.MAGIC) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//attempt to parse the header, if successful count it as a class file.
|
||||||
try {
|
try {
|
||||||
classFile = new ClassFileJava(reader);
|
new ClassFileJava(reader);
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
return false;
|
return false;
|
||||||
} catch (RuntimeException re) {
|
}
|
||||||
|
catch (RuntimeException re) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int magic = classFile.getMagic();
|
|
||||||
if (magic == 0xCAFEBABE) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -117,7 +122,7 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
throws LockException, MemoryConflictException, AddressOverflowException,
|
throws LockException, MemoryConflictException, AddressOverflowException,
|
||||||
CancelledException, DuplicateNameException, IOException {
|
CancelledException, DuplicateNameException, IOException {
|
||||||
AddressFactory af = program.getAddressFactory();
|
AddressFactory af = program.getAddressFactory();
|
||||||
AddressSpace space = af.getAddressSpace("constantPool");
|
AddressSpace space = af.getAddressSpace(CONSTANT_POOL);
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
alignmentReg = program.getRegister("alignmentPad");
|
alignmentReg = program.getRegister("alignmentPad");
|
||||||
|
|
||||||
@@ -130,28 +135,27 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
memory.createInitializedBlock("_" + provider.getName() + "_", address,
|
memory.createInitializedBlock("_" + provider.getName() + "_", address,
|
||||||
provider.getInputStream(0), provider.length(), monitor, false);
|
provider.getInputStream(0), provider.length(), monitor, false);
|
||||||
|
|
||||||
createMethodLookupMemoryBlock( program, monitor );
|
createMethodLookupMemoryBlock(program, monitor);
|
||||||
createMethodMemoryBlocks(program, provider, classFile, monitor);
|
createMethodMemoryBlocks(program, provider, classFile, monitor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void createMethodLookupMemoryBlock(Program program, TaskMonitor monitor) {
|
private void createMethodLookupMemoryBlock(Program program, TaskMonitor monitor) {
|
||||||
Address address = toAddr( program, JavaClassUtil.LOOKUP_ADDRESS );
|
Address address = toAddr(program, JavaClassUtil.LOOKUP_ADDRESS);
|
||||||
MemoryBlock block = null;
|
MemoryBlock block = null;
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
try {
|
try {
|
||||||
block = memory.createInitializedBlock( "method_lookup", address, JavaClassUtil.METHOD_INDEX_SIZE, (byte) 0xff, monitor, false );
|
block = memory.createInitializedBlock("method_lookup", address,
|
||||||
|
JavaClassUtil.METHOD_INDEX_SIZE, (byte) 0xff, monitor, false);
|
||||||
}
|
}
|
||||||
catch (LockException | DuplicateNameException | MemoryConflictException
|
catch (LockException | DuplicateNameException | MemoryConflictException
|
||||||
| AddressOverflowException | CancelledException e) {
|
| AddressOverflowException | CancelledException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
block.setRead( true );
|
block.setRead(true);
|
||||||
block.setWrite( false );
|
block.setWrite(false);
|
||||||
block.setExecute( false );
|
block.setExecute(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,12 +168,11 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
monitor.setProgress(0);
|
monitor.setProgress(0);
|
||||||
monitor.setMaximum(methods.length);
|
monitor.setMaximum(methods.length);
|
||||||
|
|
||||||
long codeOffset = 0x10000;
|
Address start = toAddr(program, CODE_OFFSET);
|
||||||
Address start = toAddr(program, codeOffset);
|
|
||||||
try {
|
try {
|
||||||
//program.setImageBase(start, true);
|
//program.setImageBase(start, true);
|
||||||
//for (MethodInfoJava method : methods) {
|
//for (MethodInfoJava method : methods) {
|
||||||
for (int i = 0, max = methods.length; i < max; ++i){
|
for (int i = 0, max = methods.length; i < max; ++i) {
|
||||||
MethodInfoJava method = methods[i];
|
MethodInfoJava method = methods[i];
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
CodeAttribute code = method.getCodeAttribute();
|
CodeAttribute code = method.getCodeAttribute();
|
||||||
@@ -180,18 +183,19 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
long offset = code.getCodeOffset();
|
long offset = code.getCodeOffset();
|
||||||
|
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
short nameIndex = method.getNameIndex();
|
int nameIndex = method.getNameIndex();
|
||||||
short descriptorIndex = method.getDescriptorIndex();
|
int descriptorIndex = method.getDescriptorIndex();
|
||||||
ConstantPoolUtf8Info methodNameInfo = (ConstantPoolUtf8Info) constantPool[nameIndex];
|
ConstantPoolUtf8Info methodNameInfo =
|
||||||
|
(ConstantPoolUtf8Info) constantPool[nameIndex];
|
||||||
ConstantPoolUtf8Info methodDescriptorInfo =
|
ConstantPoolUtf8Info methodDescriptorInfo =
|
||||||
(ConstantPoolUtf8Info) constantPool[descriptorIndex];
|
(ConstantPoolUtf8Info) constantPool[descriptorIndex];
|
||||||
String methodName = methodNameInfo.getString() + methodDescriptorInfo.getString();
|
String methodName = methodNameInfo.getString() + methodDescriptorInfo.getString();
|
||||||
|
|
||||||
MemoryBlock memoryBlock =
|
MemoryBlock memoryBlock = memory.createInitializedBlock(methodName, start,
|
||||||
memory.createInitializedBlock(methodName, start,
|
|
||||||
provider.getInputStream(offset), length, monitor, false);
|
provider.getInputStream(offset), length, monitor, false);
|
||||||
Address methodIndexAddress = JavaClassUtil.toLookupAddress( program, i );
|
Address methodIndexAddress = JavaClassUtil.toLookupAddress(program, i);
|
||||||
program.getMemory( ).setInt( methodIndexAddress, (int) start.getOffset() );
|
program.getMemory().setInt(methodIndexAddress, (int) start.getOffset());
|
||||||
|
program.getListing().createData(methodIndexAddress, PointerDataType.dataType);
|
||||||
|
|
||||||
setAlignmentInfo(program,
|
setAlignmentInfo(program,
|
||||||
new AddressSet(memoryBlock.getStart(), memoryBlock.getEnd()));
|
new AddressSet(memoryBlock.getStart(), memoryBlock.getEnd()));
|
||||||
@@ -200,10 +204,9 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
start = start.add(1);
|
start = start.add(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (Exception e1) {
|
}
|
||||||
|
catch (Exception e1) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -214,8 +217,7 @@ public class JavaLoader extends AbstractLibrarySupportLoader {
|
|||||||
int alignmentValue = 3;
|
int alignmentValue = 3;
|
||||||
while (addressIterator.hasNext()) {
|
while (addressIterator.hasNext()) {
|
||||||
Address address = addressIterator.next();
|
Address address = addressIterator.next();
|
||||||
SetRegisterCmd cmd =
|
SetRegisterCmd cmd = new SetRegisterCmd(alignmentReg, address, address,
|
||||||
new SetRegisterCmd(alignmentReg, address, address,
|
|
||||||
BigInteger.valueOf(alignmentValue));
|
BigInteger.valueOf(alignmentValue));
|
||||||
cmd.applyTo(program);
|
cmd.applyTo(program);
|
||||||
if (alignmentValue == 0) {
|
if (alignmentValue == 0) {
|
||||||
|
|||||||
+144
-118
@@ -58,43 +58,68 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
dtManager = program.getDataTypeManager();
|
dtManager = program.getDataTypeManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillinMethod(int name_and_type_index, Record res,JavaInvocationType methodType) {
|
private void fillinMethod(int index, int name_and_type_index, Record res,
|
||||||
ConstantPoolNameAndTypeInfo methodNameAndType = (ConstantPoolNameAndTypeInfo) constantPool[name_and_type_index];
|
JavaInvocationType methodType) {
|
||||||
|
ConstantPoolNameAndTypeInfo methodNameAndType =
|
||||||
|
(ConstantPoolNameAndTypeInfo) constantPool[name_and_type_index];
|
||||||
int name_index = methodNameAndType.getNameIndex();
|
int name_index = methodNameAndType.getNameIndex();
|
||||||
res.tag = ConstantPool.POINTER_METHOD;
|
res.tag = ConstantPool.POINTER_METHOD;
|
||||||
res.token = ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
|
||||||
|
if (methodType.equals(JavaInvocationType.INVOKE_STATIC)) {
|
||||||
|
AbstractConstantPoolReferenceInfo poolRef =
|
||||||
|
(AbstractConstantPoolReferenceInfo) constantPool[index];
|
||||||
|
ConstantPoolClassInfo classInfo =
|
||||||
|
(ConstantPoolClassInfo) constantPool[poolRef.getClassIndex()];
|
||||||
|
int classNameIndex = classInfo.getNameIndex();
|
||||||
|
String fullyQualifiedName =
|
||||||
|
((ConstantPoolUtf8Info) constantPool[classNameIndex]).getString();
|
||||||
|
String className = getClassName(fullyQualifiedName);
|
||||||
|
res.token =
|
||||||
|
className + "." + ((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.token = ((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
|
}
|
||||||
|
|
||||||
int descriptor_index = methodNameAndType.getDescriptorIndex();
|
int descriptor_index = methodNameAndType.getDescriptorIndex();
|
||||||
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
||||||
String descriptor = descriptorInfo.getString();
|
String descriptor = descriptorInfo.getString();
|
||||||
FunctionDefinitionDataType funcDef = new FunctionDefinitionDataType(res.token);
|
|
||||||
res.type = new PointerDataType(funcDef);
|
String uniqueifier = Integer.toHexString(index);
|
||||||
DataType returnType = DescriptorDecoder.getReturnTypeOfMethodDescriptor(descriptor, dtManager);
|
FunctionDefinitionDataType funcDef =
|
||||||
|
new FunctionDefinitionDataType(uniqueifier + "_" + res.token);
|
||||||
|
DataType returnType =
|
||||||
|
DescriptorDecoder.getReturnTypeOfMethodDescriptor(descriptor, dtManager);
|
||||||
funcDef.setReturnType(returnType);
|
funcDef.setReturnType(returnType);
|
||||||
List<DataType> params = DescriptorDecoder.getDataTypeList(descriptor, dtManager);
|
List<DataType> params = DescriptorDecoder.getDataTypeList(descriptor, dtManager);
|
||||||
ParameterDefinitionImpl[] paramDefs;
|
ParameterDefinitionImpl[] paramDefs;
|
||||||
|
|
||||||
//invokestatic and invokedynamic don't have a this pointer on the stack
|
//invokestatic and invokedynamic don't have a this pointer on the stack
|
||||||
if (methodType.equals(JavaInvocationType.INVOKE_STATIC) || methodType.equals(JavaInvocationType.INVOKE_DYNAMIC)){
|
if (methodType.equals(JavaInvocationType.INVOKE_STATIC) ||
|
||||||
|
methodType.equals(JavaInvocationType.INVOKE_DYNAMIC)) {
|
||||||
paramDefs = new ParameterDefinitionImpl[params.size()];
|
paramDefs = new ParameterDefinitionImpl[params.size()];
|
||||||
for (int i = 0, max = params.size(); i < max; ++i){
|
for (int i = 0, max = params.size(); i < max; ++i) {
|
||||||
ParameterDefinitionImpl currentParam = new ParameterDefinitionImpl("", params.get(i), null);
|
ParameterDefinitionImpl currentParam =
|
||||||
paramDefs[i]= currentParam;
|
new ParameterDefinitionImpl("", params.get(i), null);
|
||||||
|
paramDefs[i] = currentParam;
|
||||||
}
|
}
|
||||||
res.hasThisPtr = false;
|
res.hasThisPtr = false;
|
||||||
}
|
}
|
||||||
//invokeinterface, invokespecial, and invokevirtual do have a this pointer
|
//invokeinterface, invokespecial, and invokevirtual do have a this pointer
|
||||||
else {
|
else {
|
||||||
paramDefs = new ParameterDefinitionImpl[params.size() + 1];
|
paramDefs = new ParameterDefinitionImpl[params.size() + 1];
|
||||||
ParameterDefinitionImpl thisParam = new ParameterDefinitionImpl("objectRef", new Pointer32DataType(DataType.VOID), null);
|
ParameterDefinitionImpl thisParam = new ParameterDefinitionImpl("objectRef",
|
||||||
|
new Pointer32DataType(DataType.VOID), null);
|
||||||
paramDefs[0] = thisParam;
|
paramDefs[0] = thisParam;
|
||||||
for (int i = 1, max = params.size(); i <= max; ++i){
|
for (int i = 1, max = params.size(); i <= max; ++i) {
|
||||||
ParameterDefinitionImpl currentParam = new ParameterDefinitionImpl("", params.get(i-1), null);
|
ParameterDefinitionImpl currentParam =
|
||||||
paramDefs[i]= currentParam;
|
new ParameterDefinitionImpl("", params.get(i - 1), null);
|
||||||
|
paramDefs[i] = currentParam;
|
||||||
}
|
}
|
||||||
res.hasThisPtr = true;
|
res.hasThisPtr = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
funcDef.setArguments(paramDefs);
|
funcDef.setArguments(paramDefs);
|
||||||
|
res.type = new PointerDataType(funcDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ref array does not include the first element passed to the cpool operator.
|
//ref array does not include the first element passed to the cpool operator.
|
||||||
@@ -109,38 +134,33 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
* type of the elements of the new array. We use the cpool operator to
|
* type of the elements of the new array. We use the cpool operator to
|
||||||
* look up the string token corresponding to the primitive type.
|
* look up the string token corresponding to the primitive type.
|
||||||
*/
|
*/
|
||||||
if (op.equals(CPOOL_NEWARRAY)){
|
if (op.equals(CPOOL_NEWARRAY)) {
|
||||||
res.tag = ConstantPool.POINTER_METHOD;
|
res.tag = ConstantPool.POINTER_METHOD;
|
||||||
res.token = ArrayMethods.getPrimitiveArrayToken((int)ref[0]);
|
res.token = ArrayMethods.getPrimitiveArrayToken((int) ref[0]);
|
||||||
DataType elementType = ArrayMethods.getArrayBaseType((int) ref[0], dtManager);
|
DataType elementType = ArrayMethods.getArrayBaseType((int) ref[0], dtManager);
|
||||||
res.type = dtManager.getPointer(elementType);
|
res.type = dtManager.getPointer(elementType);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
/*arraylength instruction does not reference the constant pool */
|
/*arraylength instruction does not reference the constant pool */
|
||||||
if (op.equals(CPOOL_ARRAYLENGTH)){
|
if (op.equals(CPOOL_ARRAYLENGTH)) {
|
||||||
res.tag = ConstantPool.ARRAY_LENGTH;
|
res.tag = ConstantPool.ARRAY_LENGTH;
|
||||||
res.token = "length";
|
res.token = "length";
|
||||||
res.type = new PointerDataType(DWordDataType.dataType);
|
res.type = IntegerDataType.dataType;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractConstantPoolInfoJava poolRef = constantPool[(int)ref[0]];
|
AbstractConstantPoolInfoJava poolRef = constantPool[(int) ref[0]];
|
||||||
short name_and_type_index;
|
int name_and_type_index;
|
||||||
ConstantPoolNameAndTypeInfo fieldNameAndType;
|
switch (op) {
|
||||||
short descriptor_index;
|
|
||||||
ConstantPoolUtf8Info descriptorInfo;
|
|
||||||
String descriptor;
|
|
||||||
StringBuilder sb = null;
|
|
||||||
String[] parts = null;
|
|
||||||
switch(op){
|
|
||||||
case CPOOL_ANEWARRAY:
|
case CPOOL_ANEWARRAY:
|
||||||
case CPOOL_NEW:
|
case CPOOL_NEW:
|
||||||
res.tag = ConstantPool.CLASS_REFERENCE;
|
res.tag = ConstantPool.CLASS_REFERENCE;
|
||||||
int name_index = ((ConstantPoolClassInfo)poolRef).getNameIndex();
|
int name_index = ((ConstantPoolClassInfo) poolRef).getNameIndex();
|
||||||
String fullyQualifiedName = ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
String fullyQualifiedName =
|
||||||
parts = fullyQualifiedName.split("/");
|
((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
res.token = parts[parts.length-1];
|
String[] parts = fullyQualifiedName.split("/");
|
||||||
sb = new StringBuilder();
|
res.token = parts[parts.length - 1];
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
for (String part : parts) {
|
for (String part : parts) {
|
||||||
sb.append(CategoryPath.DELIMITER_CHAR);
|
sb.append(CategoryPath.DELIMITER_CHAR);
|
||||||
sb.append(part);
|
sb.append(part);
|
||||||
@@ -148,11 +168,12 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
DataTypePath dataPath = new DataTypePath(sb.toString(), res.token);
|
DataTypePath dataPath = new DataTypePath(sb.toString(), res.token);
|
||||||
res.type = new PointerDataType(dtManager.getDataType(dataPath));
|
res.type = new PointerDataType(dtManager.getDataType(dataPath));
|
||||||
break;
|
break;
|
||||||
//TODO
|
|
||||||
case CPOOL_CHECKCAST:
|
case CPOOL_CHECKCAST:
|
||||||
|
setTypeNameInfo(poolRef, res);
|
||||||
res.tag = ConstantPool.CHECK_CAST;
|
res.tag = ConstantPool.CHECK_CAST;
|
||||||
res.token = "checkcast";
|
PointerDataType pointerType = (PointerDataType) res.type;
|
||||||
setTypeNameInfo(poolRef,res);
|
String typeName = pointerType.getDataType().getDisplayName();
|
||||||
|
res.token = "checkcast(" + typeName + ")";
|
||||||
break;
|
break;
|
||||||
case CPOOL_INSTANCEOF:
|
case CPOOL_INSTANCEOF:
|
||||||
res.tag = ConstantPool.INSTANCE_OF;
|
res.tag = ConstantPool.INSTANCE_OF;
|
||||||
@@ -161,76 +182,43 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
break;
|
break;
|
||||||
case CPOOL_GETFIELD:
|
case CPOOL_GETFIELD:
|
||||||
case CPOOL_PUTFIELD:
|
case CPOOL_PUTFIELD:
|
||||||
name_and_type_index = ((ConstantPoolFieldReferenceInfo)poolRef).getNameAndTypeIndex();
|
|
||||||
fieldNameAndType = (ConstantPoolNameAndTypeInfo)constantPool[name_and_type_index];
|
|
||||||
name_index = fieldNameAndType.getNameIndex();
|
|
||||||
res.tag = ConstantPool.POINTER_FIELD;
|
|
||||||
res.token = ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
|
||||||
descriptor_index = fieldNameAndType.getDescriptorIndex();
|
|
||||||
descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
|
||||||
descriptor = descriptorInfo.getString();
|
|
||||||
DataType type = DescriptorDecoder.getDataTypeOfDescriptor(descriptor, dtManager);
|
|
||||||
res.type = new PointerDataType(type);
|
|
||||||
break;
|
|
||||||
//for references to static fields, we want the class name to be part of the token
|
|
||||||
case CPOOL_GETSTATIC:
|
case CPOOL_GETSTATIC:
|
||||||
case CPOOL_PUTSTATIC:
|
case CPOOL_PUTSTATIC:
|
||||||
name_and_type_index = ((ConstantPoolFieldReferenceInfo)poolRef).getNameAndTypeIndex();
|
handlePutAndGetOps(poolRef, res, op);
|
||||||
int class_index = ((ConstantPoolFieldReferenceInfo)poolRef).getClassIndex();
|
|
||||||
fieldNameAndType = (ConstantPoolNameAndTypeInfo)constantPool[name_and_type_index];
|
|
||||||
name_index = fieldNameAndType.getNameIndex();
|
|
||||||
ConstantPoolClassInfo classInfo = (ConstantPoolClassInfo)constantPool[class_index];
|
|
||||||
int classNameIndex = classInfo.getNameIndex();
|
|
||||||
fullyQualifiedName = ((ConstantPoolUtf8Info)constantPool[classNameIndex]).getString();
|
|
||||||
res.tag = ConstantPool.POINTER_FIELD;
|
|
||||||
String className = getClassName(fullyQualifiedName);
|
|
||||||
res.token = className + "." + ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
|
||||||
descriptor_index = fieldNameAndType.getDescriptorIndex();
|
|
||||||
descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
|
||||||
descriptor = descriptorInfo.getString();
|
|
||||||
type = DescriptorDecoder.getDataTypeOfDescriptor(descriptor, dtManager);
|
|
||||||
res.type = new PointerDataType(type);
|
|
||||||
//res.type = type;
|
|
||||||
break;
|
break;
|
||||||
case CPOOL_INVOKEDYNAMIC:
|
case CPOOL_INVOKEDYNAMIC:
|
||||||
name_and_type_index = ((ConstantPoolInvokeDynamicInfo)poolRef).getNameAndTypeIndex();
|
name_and_type_index =
|
||||||
fillinMethod(name_and_type_index,res,JavaInvocationType.INVOKE_DYNAMIC);
|
((ConstantPoolInvokeDynamicInfo) poolRef).getNameAndTypeIndex();
|
||||||
|
|
||||||
|
fillinMethod((int) ref[0], name_and_type_index, res,
|
||||||
|
JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
break;
|
break;
|
||||||
case CPOOL_INVOKEINTERFACE:
|
case CPOOL_INVOKEINTERFACE:
|
||||||
name_and_type_index = ((ConstantPoolInterfaceMethodReferenceInfo)poolRef).getNameAndTypeIndex();
|
name_and_type_index =
|
||||||
fillinMethod(name_and_type_index,res,JavaInvocationType.INVOKE_INTERFACE);
|
((ConstantPoolInterfaceMethodReferenceInfo) poolRef).getNameAndTypeIndex();
|
||||||
|
fillinMethod((int) ref[0], name_and_type_index, res,
|
||||||
|
JavaInvocationType.INVOKE_INTERFACE);
|
||||||
break;
|
break;
|
||||||
case CPOOL_INVOKESPECIAL:
|
case CPOOL_INVOKESPECIAL:
|
||||||
if (poolRef instanceof ConstantPoolMethodReferenceInfo) {
|
AbstractConstantPoolReferenceInfo refInfo =
|
||||||
name_and_type_index = ((ConstantPoolMethodReferenceInfo)poolRef).getNameAndTypeIndex();
|
(AbstractConstantPoolReferenceInfo) poolRef;
|
||||||
}
|
name_and_type_index = refInfo.getNameAndTypeIndex();
|
||||||
else{
|
fillinMethod((int) ref[0], name_and_type_index, res,
|
||||||
name_and_type_index = ((ConstantPoolInterfaceMethodReferenceInfo)poolRef).getNameAndTypeIndex();
|
JavaInvocationType.INVOKE_SPECIAL);
|
||||||
}
|
|
||||||
fillinMethod(name_and_type_index,res,JavaInvocationType.INVOKE_SPECIAL);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CPOOL_INVOKESTATIC:
|
case CPOOL_INVOKESTATIC:
|
||||||
if (poolRef instanceof ConstantPoolMethodReferenceInfo) {
|
refInfo = (AbstractConstantPoolReferenceInfo) poolRef;
|
||||||
name_and_type_index = ((ConstantPoolMethodReferenceInfo)poolRef).getNameAndTypeIndex();
|
name_and_type_index = refInfo.getNameAndTypeIndex();
|
||||||
class_index = ((ConstantPoolMethodReferenceInfo)poolRef).getClassIndex();
|
fillinMethod((int) ref[0], name_and_type_index, res,
|
||||||
|
JavaInvocationType.INVOKE_STATIC);
|
||||||
}
|
|
||||||
else{
|
|
||||||
name_and_type_index = ((ConstantPoolInterfaceMethodReferenceInfo)poolRef).getNameAndTypeIndex();
|
|
||||||
class_index = ((ConstantPoolInterfaceMethodReferenceInfo)poolRef).getClassIndex();
|
|
||||||
}
|
|
||||||
classInfo = (ConstantPoolClassInfo)constantPool[class_index];
|
|
||||||
classNameIndex = classInfo.getNameIndex();
|
|
||||||
fullyQualifiedName = ((ConstantPoolUtf8Info)constantPool[classNameIndex]).getString();
|
|
||||||
className = getClassName(fullyQualifiedName);
|
|
||||||
fillinMethod(name_and_type_index,res,JavaInvocationType.INVOKE_STATIC);
|
|
||||||
res.token = className + "." + res.token;
|
|
||||||
break;
|
break;
|
||||||
case CPOOL_INVOKEVIRTUAL:
|
case CPOOL_INVOKEVIRTUAL:
|
||||||
name_and_type_index = ((ConstantPoolMethodReferenceInfo)poolRef).getNameAndTypeIndex();
|
name_and_type_index =
|
||||||
fillinMethod(name_and_type_index,res,JavaInvocationType.INVOKE_VIRTUAL);
|
((ConstantPoolMethodReferenceInfo) poolRef).getNameAndTypeIndex();
|
||||||
|
fillinMethod((int) ref[0], name_and_type_index, res,
|
||||||
|
JavaInvocationType.INVOKE_VIRTUAL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//in this case, the constant pool entry can be a reference to:
|
//in this case, the constant pool entry can be a reference to:
|
||||||
//int, float, string literal, or a symbolic reference to a class,
|
//int, float, string literal, or a symbolic reference to a class,
|
||||||
//method type, or method handle
|
//method type, or method handle
|
||||||
@@ -238,38 +226,40 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
if (poolRef instanceof ConstantPoolIntegerInfo) {
|
if (poolRef instanceof ConstantPoolIntegerInfo) {
|
||||||
res.tag = ConstantPool.PRIMITIVE;
|
res.tag = ConstantPool.PRIMITIVE;
|
||||||
res.token = "int";
|
res.token = "int";
|
||||||
res.value = ((ConstantPoolIntegerInfo)poolRef).getValue();
|
res.value = ((ConstantPoolIntegerInfo) poolRef).getValue();
|
||||||
res.type = IntegerDataType.dataType;
|
res.type = IntegerDataType.dataType;
|
||||||
}
|
}
|
||||||
else if (poolRef instanceof ConstantPoolFloatInfo) {
|
else if (poolRef instanceof ConstantPoolFloatInfo) {
|
||||||
res.tag = ConstantPool.PRIMITIVE;
|
res.tag = ConstantPool.PRIMITIVE;
|
||||||
res.token = "float";
|
res.token = "float";
|
||||||
res.value = ((ConstantPoolFloatInfo)poolRef).getRawBytes() & 0xffffffffL;
|
res.value = ((ConstantPoolFloatInfo) poolRef).getRawBytes() & 0xffffffffL;
|
||||||
res.type = FloatDataType.dataType;
|
res.type = FloatDataType.dataType;
|
||||||
}
|
}
|
||||||
else if (poolRef instanceof ConstantPoolStringInfo) {
|
else if (poolRef instanceof ConstantPoolStringInfo) {
|
||||||
int string_index = ((ConstantPoolStringInfo)poolRef).getStringIndex();
|
int string_index = ((ConstantPoolStringInfo) poolRef).getStringIndex();
|
||||||
res.tag = ConstantPool.STRING_LITERAL;
|
res.tag = ConstantPool.STRING_LITERAL;
|
||||||
res.byteData = ((ConstantPoolUtf8Info) constantPool[string_index]).getBytes();
|
res.byteData = ((ConstantPoolUtf8Info) constantPool[string_index]).getBytes();
|
||||||
res.type = DescriptorDecoder.getReferenceTypeOfDescriptor("java/lang/String", dtManager, false);
|
res.type = DescriptorDecoder.getReferenceTypeOfDescriptor("java/lang/String",
|
||||||
|
dtManager, false);
|
||||||
}
|
}
|
||||||
else if (poolRef instanceof ConstantPoolClassInfo){
|
else if (poolRef instanceof ConstantPoolClassInfo) {
|
||||||
res.tag = ConstantPool.CLASS_REFERENCE;
|
res.tag = ConstantPool.CLASS_REFERENCE;
|
||||||
name_index = ((ConstantPoolClassInfo)poolRef).getNameIndex();
|
name_index = ((ConstantPoolClassInfo) poolRef).getNameIndex();
|
||||||
fullyQualifiedName = ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
fullyQualifiedName =
|
||||||
className = getClassName(fullyQualifiedName);
|
((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
|
String className = getClassName(fullyQualifiedName);
|
||||||
res.token = className + ".class";
|
res.token = className + ".class";
|
||||||
res.type = DescriptorDecoder.getReferenceTypeOfDescriptor(fullyQualifiedName, dtManager, false);
|
res.type = DescriptorDecoder.getReferenceTypeOfDescriptor(fullyQualifiedName,
|
||||||
|
dtManager, false);
|
||||||
}
|
}
|
||||||
//standard java compilers don't seem to emit the following two
|
else if (poolRef instanceof ConstantPoolMethodTypeInfo) {
|
||||||
else if (poolRef instanceof ConstantPoolMethodTypeInfo){
|
|
||||||
res.tag = ConstantPool.POINTER_METHOD;
|
res.tag = ConstantPool.POINTER_METHOD;
|
||||||
name_index = ((ConstantPoolMethodTypeInfo)poolRef).getDescriptorIndex();
|
name_index = ((ConstantPoolMethodTypeInfo) poolRef).getDescriptorIndex();
|
||||||
res.token = ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
res.token = ((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
res.type = dtManager.getPointer(DWordDataType.dataType);
|
res.type = dtManager.getPointer(DWordDataType.dataType);
|
||||||
}
|
}
|
||||||
//TODO set the token?
|
//TODO set the token?
|
||||||
else if (poolRef instanceof ConstantPoolMethodHandleInfo){
|
else if (poolRef instanceof ConstantPoolMethodHandleInfo) {
|
||||||
res.tag = ConstantPool.POINTER_METHOD;
|
res.tag = ConstantPool.POINTER_METHOD;
|
||||||
res.type = dtManager.getPointer(DWordDataType.dataType);
|
res.type = dtManager.getPointer(DWordDataType.dataType);
|
||||||
}
|
}
|
||||||
@@ -280,35 +270,71 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
if (poolRef instanceof ConstantPoolLongInfo) {
|
if (poolRef instanceof ConstantPoolLongInfo) {
|
||||||
res.tag = ConstantPool.PRIMITIVE;
|
res.tag = ConstantPool.PRIMITIVE;
|
||||||
res.token = "long";
|
res.token = "long";
|
||||||
res.value = ((ConstantPoolLongInfo)poolRef).getValue();
|
res.value = ((ConstantPoolLongInfo) poolRef).getValue();
|
||||||
res.type = LongDataType.dataType;
|
res.type = LongDataType.dataType;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res.tag = ConstantPool.PRIMITIVE;
|
res.tag = ConstantPool.PRIMITIVE;
|
||||||
res.token = "double";
|
res.token = "double";
|
||||||
res.value = ((ConstantPoolDoubleInfo)poolRef).getRawBytes();
|
res.value = ((ConstantPoolDoubleInfo) poolRef).getRawBytes();
|
||||||
res.type = DoubleDataType.dataType;
|
res.type = DoubleDataType.dataType;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CPOOL_MULTIANEWARRAY:
|
case CPOOL_MULTIANEWARRAY:
|
||||||
res.tag = ConstantPool.POINTER_METHOD;
|
res.tag = ConstantPool.CLASS_REFERENCE;
|
||||||
res.type = new PointerDataType(DataType.VOID);
|
res.type = new PointerDataType(DataType.VOID);
|
||||||
int nameIndex = ((ConstantPoolClassInfo) poolRef).getNameIndex();
|
int nameIndex = ((ConstantPoolClassInfo) poolRef).getNameIndex();
|
||||||
ConstantPoolUtf8Info utf8Info = (ConstantPoolUtf8Info) constantPool[nameIndex];
|
ConstantPoolUtf8Info utf8Info = (ConstantPoolUtf8Info) constantPool[nameIndex];
|
||||||
String classNameWithSemicolon = utf8Info.getString();
|
String classNameWithSemicolon = utf8Info.getString();
|
||||||
res.token = DescriptorDecoder.getTypeNameFromDescriptor(classNameWithSemicolon, false, false);
|
res.token = DescriptorDecoder.getTypeNameFromDescriptor(classNameWithSemicolon,
|
||||||
|
false, false);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handlePutAndGetOps(AbstractConstantPoolInfoJava poolRef, Record res, String op) {
|
||||||
|
|
||||||
|
int name_and_type_index = ((ConstantPoolFieldReferenceInfo) poolRef).getNameAndTypeIndex();
|
||||||
|
ConstantPoolNameAndTypeInfo fieldNameAndType =
|
||||||
|
(ConstantPoolNameAndTypeInfo) constantPool[name_and_type_index];
|
||||||
|
int name_index = fieldNameAndType.getNameIndex();
|
||||||
|
switch (op) {
|
||||||
|
case CPOOL_GETFIELD:
|
||||||
|
case CPOOL_PUTFIELD:
|
||||||
|
res.token = ((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
|
break;
|
||||||
|
case CPOOL_GETSTATIC:
|
||||||
|
case CPOOL_PUTSTATIC:
|
||||||
|
int class_index = ((ConstantPoolFieldReferenceInfo) poolRef).getClassIndex();
|
||||||
|
ConstantPoolClassInfo classInfo = (ConstantPoolClassInfo) constantPool[class_index];
|
||||||
|
int classNameIndex = classInfo.getNameIndex();
|
||||||
|
String fullyQualifiedName =
|
||||||
|
((ConstantPoolUtf8Info) constantPool[classNameIndex]).getString();
|
||||||
|
String className = getClassName(fullyQualifiedName);
|
||||||
|
res.token =
|
||||||
|
className + "." + ((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid op: " + op);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.tag = ConstantPool.POINTER_FIELD;
|
||||||
|
|
||||||
|
int descriptor_index = fieldNameAndType.getDescriptorIndex();
|
||||||
|
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
||||||
|
String descriptor = descriptorInfo.getString();
|
||||||
|
DataType type = DescriptorDecoder.getDataTypeOfDescriptor(descriptor, dtManager);
|
||||||
|
res.type = new PointerDataType(type);
|
||||||
|
}
|
||||||
|
|
||||||
private void setTypeNameInfo(AbstractConstantPoolInfoJava poolRef, Record res) {
|
private void setTypeNameInfo(AbstractConstantPoolInfoJava poolRef, Record res) {
|
||||||
int name_index = ((ConstantPoolClassInfo)poolRef).getNameIndex();
|
int name_index = ((ConstantPoolClassInfo) poolRef).getNameIndex();
|
||||||
String fullyQualifiedName = ((ConstantPoolUtf8Info)constantPool[name_index]).getString();
|
String fullyQualifiedName = ((ConstantPoolUtf8Info) constantPool[name_index]).getString();
|
||||||
String[] parts = null;
|
String[] parts = null;
|
||||||
StringBuilder sb = null;
|
StringBuilder sb = null;
|
||||||
if (fullyQualifiedName.startsWith("[")){
|
if (fullyQualifiedName.startsWith("[")) {
|
||||||
//TODO: how to get instanceof X to display, where X is an array type?
|
//TODO: how to get instanceof X to display, where X is an array type?
|
||||||
//need to decide how to handle multidimensional arrays
|
//need to decide how to handle multidimensional arrays
|
||||||
//remove the brackets
|
//remove the brackets
|
||||||
@@ -328,17 +354,17 @@ public class ConstantPoolJava extends ConstantPool {
|
|||||||
sb.append(part);
|
sb.append(part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataTypePath dataPath = new DataTypePath(sb.toString(), parts[parts.length-1]);
|
DataTypePath dataPath = new DataTypePath(sb.toString(), parts[parts.length - 1]);
|
||||||
res.type = new PointerDataType(dtManager.getDataType(dataPath));
|
res.type = new PointerDataType(dtManager.getDataType(dataPath));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getClassName(String fullyQualifiedName){
|
private String getClassName(String fullyQualifiedName) {
|
||||||
int lastSlash = fullyQualifiedName.lastIndexOf("/");
|
int lastSlash = fullyQualifiedName.lastIndexOf("/");
|
||||||
return fullyQualifiedName.substring(lastSlash+1, fullyQualifiedName.length());
|
return fullyQualifiedName.substring(lastSlash + 1, fullyQualifiedName.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractConstantPoolInfoJava[] getConstantPool(){
|
public AbstractConstantPoolInfoJava[] getConstantPool() {
|
||||||
return constantPool;
|
return constantPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ public class InjectInvokeDynamic extends InjectPayloadJava {
|
|||||||
InjectContext injectContext = getInjectContext(program, context);
|
InjectContext injectContext = getInjectContext(program, context);
|
||||||
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
AbstractConstantPoolInfoJava[] constantPool = getConstantPool(program);
|
||||||
int constantPoolIndex = (int) injectContext.inputlist.get(0).getOffset();
|
int constantPoolIndex = (int) injectContext.inputlist.get(0).getOffset();
|
||||||
String pcodeText = InvokeMethods.getPcodeForInvoke(constantPoolIndex, constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
String pcodeText = InvokeMethods.getPcodeForInvokeDynamic(constantPoolIndex, constantPool);
|
||||||
return pcodeText;
|
return pcodeText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* 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.util.pcodeInject;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
|
||||||
import ghidra.program.model.lang.InjectContext;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
|
|
||||||
public class InjectLookupSwitch extends InjectPayloadJava {
|
|
||||||
|
|
||||||
public InjectLookupSwitch(String sourceName, SleighLanguage language) {
|
|
||||||
super(sourceName, language);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPcodeText(Program program, String context) {
|
|
||||||
InjectContext injectContext = getInjectContext(program, context);
|
|
||||||
String pcodeText = null;
|
|
||||||
try {
|
|
||||||
pcodeText = SwitchMethods.getPcodeForLookupSwitch(injectContext, program);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
pcodeText = "SP = SP;\n";
|
|
||||||
}
|
|
||||||
return pcodeText;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+82
-25
@@ -38,7 +38,7 @@ public class InvokeMethods {
|
|||||||
static final String PARAM_SPACE = "parameterSpace";
|
static final String PARAM_SPACE = "parameterSpace";
|
||||||
|
|
||||||
//private constructor to enforce noninstantiability
|
//private constructor to enforce noninstantiability
|
||||||
private InvokeMethods(){
|
private InvokeMethods() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,24 +50,28 @@ public class InvokeMethods {
|
|||||||
* @param type - the JavaInvocationType of the invocation
|
* @param type - the JavaInvocationType of the invocation
|
||||||
* @return - the pcode as a string
|
* @return - the pcode as a string
|
||||||
*/
|
*/
|
||||||
|
public static String getPcodeForInvoke(int offset, AbstractConstantPoolInfoJava[] constantPool,
|
||||||
public static String getPcodeForInvoke(int offset, AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type) {
|
JavaInvocationType type) {
|
||||||
|
|
||||||
StringBuilder pCode = new StringBuilder();
|
StringBuilder pCode = new StringBuilder();
|
||||||
String descriptor = DescriptorDecoder.getDescriptorForInvoke(offset, constantPool, type);
|
String descriptor = DescriptorDecoder.getDescriptorForInvoke(offset, constantPool, type);
|
||||||
List<JavaComputationalCategory> categories = DescriptorDecoder.getParameterCategories(descriptor);
|
List<JavaComputationalCategory> categories =
|
||||||
boolean includeThisPointer = type.equals(JavaInvocationType.INVOKE_VIRTUAL) || type.equals(JavaInvocationType.INVOKE_SPECIAL) || type.equals(JavaInvocationType.INVOKE_INTERFACE);
|
DescriptorDecoder.getParameterCategories(descriptor);
|
||||||
|
boolean includeThisPointer = type.equals(JavaInvocationType.INVOKE_VIRTUAL) ||
|
||||||
|
type.equals(JavaInvocationType.INVOKE_SPECIAL) ||
|
||||||
|
type.equals(JavaInvocationType.INVOKE_INTERFACE);
|
||||||
|
|
||||||
int stackPurge = DescriptorDecoder.getStackPurge(descriptor);
|
int stackPurge = DescriptorDecoder.getStackPurge(descriptor);
|
||||||
if (includeThisPointer){
|
if (includeThisPointer) {
|
||||||
stackPurge += 4;
|
stackPurge += 4;
|
||||||
}
|
}
|
||||||
emitPcodeToMoveParams(pCode, categories, includeThisPointer, stackPurge);
|
emitPcodeToMoveParams(pCode, categories, includeThisPointer, stackPurge);
|
||||||
emitPcodeToResolveMethodReference(pCode, offset, constantPool, type);
|
emitPcodeToResolveMethodReference(pCode, offset, constantPool, type);
|
||||||
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
||||||
|
|
||||||
JavaComputationalCategory retType = DescriptorDecoder.getReturnCategoryOfMethodDescriptor(descriptor);
|
JavaComputationalCategory retType =
|
||||||
switch (retType){
|
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(descriptor);
|
||||||
|
switch (retType) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
||||||
break;
|
break;
|
||||||
@@ -80,6 +84,42 @@ public class InvokeMethods {
|
|||||||
return pCode.toString();
|
return pCode.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits the pcode for an invoke instruction.
|
||||||
|
* @param offset - the index of the constant pool element containing a symbolic reference
|
||||||
|
* to a method or a call site specifier.
|
||||||
|
* @param constantPool - the constant pool
|
||||||
|
* @return - the pcode as a string
|
||||||
|
*/
|
||||||
|
public static String getPcodeForInvokeDynamic(int offset,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool) {
|
||||||
|
StringBuilder pCode = new StringBuilder();
|
||||||
|
String invokeDynamicDescriptor = DescriptorDecoder.getDescriptorForInvoke(offset,
|
||||||
|
constantPool, JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
|
List<JavaComputationalCategory> categories =
|
||||||
|
DescriptorDecoder.getParameterCategories(invokeDynamicDescriptor);
|
||||||
|
|
||||||
|
int stackPurge = DescriptorDecoder.getStackPurge(invokeDynamicDescriptor);
|
||||||
|
|
||||||
|
emitPcodeToMoveParams(pCode, categories, false, stackPurge);
|
||||||
|
emitPcodeToResolveMethodReference(pCode, offset, constantPool,
|
||||||
|
JavaInvocationType.INVOKE_DYNAMIC);
|
||||||
|
PcodeTextEmitter.emitIndirectCall(pCode, CALL_TARGET);
|
||||||
|
|
||||||
|
JavaComputationalCategory retType =
|
||||||
|
DescriptorDecoder.getReturnCategoryOfMethodDescriptor(invokeDynamicDescriptor);
|
||||||
|
switch (retType) {
|
||||||
|
case CAT_1:
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, CAT_1_RETURN);
|
||||||
|
break;
|
||||||
|
case CAT_2:
|
||||||
|
PcodeTextEmitter.emitPushCat2Value(pCode, CAT_2_RETURN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return pCode.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits pcode to move the parameters from the stack to the space parameterSpace
|
* Emits pcode to move the parameters from the stack to the space parameterSpace
|
||||||
@@ -89,21 +129,26 @@ public class InvokeMethods {
|
|||||||
* @param categories - the list of computational categories on the top of the stack
|
* @param categories - the list of computational categories on the top of the stack
|
||||||
* @param includeThisPointer - true if the first element on the stack is an implicit this parameter
|
* @param includeThisPointer - true if the first element on the stack is an implicit this parameter
|
||||||
*/
|
*/
|
||||||
static void emitPcodeToMoveParams(StringBuilder pCode, List<JavaComputationalCategory> categories, boolean includeThisPointer, int totalSize){
|
static void emitPcodeToMoveParams(StringBuilder pCode,
|
||||||
|
List<JavaComputationalCategory> categories, boolean includeThisPointer, int totalSize) {
|
||||||
|
|
||||||
//pop the parameters off of the stack
|
//pop the parameters off of the stack
|
||||||
for (int i = categories.size() - 1; i >= 0; --i){
|
for (int i = categories.size() - 1; i >= 0; --i) {
|
||||||
switch (categories.get(i)){
|
switch (categories.get(i)) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
||||||
totalSize -= 4;
|
totalSize -= 4;
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4, Integer.toString(totalSize) + ":4", PARAMETER + Integer.toString(i));
|
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||||
|
Integer.toString(totalSize) + ":4", PARAMETER + Integer.toString(i));
|
||||||
break;
|
break;
|
||||||
case CAT_2:
|
case CAT_2:
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER + Integer.toString(i));
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4, Integer.toString(totalSize-8) + ":4", PARAMETER + Integer.toString(i));
|
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||||
|
Integer.toString(totalSize - 8) + ":4", PARAMETER + Integer.toString(i));
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER_PART2 + Integer.toString(i));
|
PcodeTextEmitter.emitPopCat1Value(pCode, PARAMETER_PART2 + Integer.toString(i));
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4, Integer.toString(totalSize-4) + ":4", PARAMETER_PART2 + Integer.toString(i));
|
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||||
|
Integer.toString(totalSize - 4) + ":4",
|
||||||
|
PARAMETER_PART2 + Integer.toString(i));
|
||||||
totalSize -= 8;
|
totalSize -= 8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -111,15 +156,15 @@ public class InvokeMethods {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//pop off the this pointer if there is one
|
//pop off the this pointer if there is one
|
||||||
if (includeThisPointer){
|
if (includeThisPointer) {
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, THIS);
|
PcodeTextEmitter.emitPopCat1Value(pCode, THIS);
|
||||||
totalSize -= 4;
|
totalSize -= 4;
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4, Integer.toString(totalSize) + ":4", THIS);
|
PcodeTextEmitter.emitWriteToMemory(pCode, PARAM_SPACE, 4,
|
||||||
|
Integer.toString(totalSize) + ":4", THIS);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits pcode to assign the result of a cpool op to the call_target register for an invocation.
|
* Emits pcode to assign the result of a cpool op to the call_target register for an invocation.
|
||||||
* @param pCode - the pcode buffer
|
* @param pCode - the pcode buffer
|
||||||
@@ -127,25 +172,37 @@ public class InvokeMethods {
|
|||||||
* @param constantPool - the constant pool
|
* @param constantPool - the constant pool
|
||||||
* @param type - the type of the invocation
|
* @param type - the type of the invocation
|
||||||
*/
|
*/
|
||||||
static void emitPcodeToResolveMethodReference(StringBuilder pCode, int offset, AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type){
|
static void emitPcodeToResolveMethodReference(StringBuilder pCode, int offset,
|
||||||
switch (type){
|
AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type) {
|
||||||
|
switch (type) {
|
||||||
case INVOKE_DYNAMIC:
|
case INVOKE_DYNAMIC:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET, ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset), ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||||
|
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
||||||
|
ConstantPoolJava.CPOOL_INVOKEDYNAMIC);
|
||||||
break;
|
break;
|
||||||
case INVOKE_INTERFACE:
|
case INVOKE_INTERFACE:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET, ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset), ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||||
|
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||||
|
ConstantPoolJava.CPOOL_INVOKEINTERFACE);
|
||||||
break;
|
break;
|
||||||
case INVOKE_SPECIAL:
|
case INVOKE_SPECIAL:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET, ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset), ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||||
|
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||||
|
ConstantPoolJava.CPOOL_INVOKESPECIAL);
|
||||||
break;
|
break;
|
||||||
case INVOKE_STATIC:
|
case INVOKE_STATIC:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET, ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset), ConstantPoolJava.CPOOL_INVOKESTATIC);
|
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||||
|
ConstantPoolJava.CPOOL_OP, STATIC_OFFSET, Integer.toString(offset),
|
||||||
|
ConstantPoolJava.CPOOL_INVOKESTATIC);
|
||||||
break;
|
break;
|
||||||
case INVOKE_VIRTUAL:
|
case INVOKE_VIRTUAL:
|
||||||
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET, ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset), ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
PcodeTextEmitter.emitAssignRegisterFromPcodeOpCall(pCode, CALL_TARGET,
|
||||||
|
ConstantPoolJava.CPOOL_OP, THIS, Integer.toString(offset),
|
||||||
|
ConstantPoolJava.CPOOL_INVOKEVIRTUAL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unimplemented JavaMethodType: " + type.toString());
|
throw new IllegalArgumentException(
|
||||||
|
"Unimplemented JavaMethodType: " + type.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-17
@@ -79,17 +79,6 @@ import ghidra.program.model.listing.Program;
|
|||||||
* (Use/add to PcodeTextEmitter.java to actually emit pcode text)
|
* (Use/add to PcodeTextEmitter.java to actually emit pcode text)
|
||||||
* See ConstantPoolJava.java for examples of the use of the CPOOL pcode op.
|
* See ConstantPoolJava.java for examples of the use of the CPOOL pcode op.
|
||||||
*
|
*
|
||||||
* TODO:
|
|
||||||
* 1) For the lookupswitch op, the disassembly is correct but the decompilation is not.
|
|
||||||
* There are several possible ways of modeling the instruction in pcode - either using
|
|
||||||
* injection (SwitchMethods.java) or pcode (JVM.slaspec). In all cases, there seems to
|
|
||||||
* be an issue with getting the decompiler to follow pointers to the various switch clauses.
|
|
||||||
* The file LookupSwitchHex.java in the resource directory contains a class file with
|
|
||||||
* 4 methods with switch statements. Currently the first method is modeled using a
|
|
||||||
* pcode loop and the last three are modeled using pcode injection (which is possible because
|
|
||||||
* there are actually 4 separate lookupswitch instructions, the only difference is the amount
|
|
||||||
* of padding bytes).
|
|
||||||
*
|
|
||||||
* possible improvements:
|
* possible improvements:
|
||||||
*
|
*
|
||||||
* 2) incorporate exceptions.
|
* 2) incorporate exceptions.
|
||||||
@@ -121,7 +110,6 @@ public class PcodeInjectLibraryJava extends PcodeInjectLibrary {
|
|||||||
public static final String LDC = "ldcCallOther";
|
public static final String LDC = "ldcCallOther";
|
||||||
public static final String LDC2_W = "ldc2_wCallOther";
|
public static final String LDC2_W = "ldc2_wCallOther";
|
||||||
public static final String LDC_W = "ldc_wCallOther";
|
public static final String LDC_W = "ldc_wCallOther";
|
||||||
public static final String LOOKUP_SWITCH = "lookupswitchCallOther";
|
|
||||||
public static final String MULTIANEWARRAY = "multianewarrayCallOther";
|
public static final String MULTIANEWARRAY = "multianewarrayCallOther";
|
||||||
|
|
||||||
public static final String PUTFIELD = "putFieldCallOther";
|
public static final String PUTFIELD = "putFieldCallOther";
|
||||||
@@ -149,7 +137,6 @@ public class PcodeInjectLibraryJava extends PcodeInjectLibrary {
|
|||||||
implementedOps.add(LDC);
|
implementedOps.add(LDC);
|
||||||
implementedOps.add(LDC2_W);
|
implementedOps.add(LDC2_W);
|
||||||
implementedOps.add(LDC_W);
|
implementedOps.add(LDC_W);
|
||||||
implementedOps.add(LOOKUP_SWITCH);
|
|
||||||
implementedOps.add(MULTIANEWARRAY);
|
implementedOps.add(MULTIANEWARRAY);
|
||||||
implementedOps.add(PUTFIELD);
|
implementedOps.add(PUTFIELD);
|
||||||
implementedOps.add(PUTSTATIC);
|
implementedOps.add(PUTSTATIC);
|
||||||
@@ -170,8 +157,9 @@ public class PcodeInjectLibraryJava extends PcodeInjectLibrary {
|
|||||||
@Override
|
@Override
|
||||||
protected InjectPayloadSleigh allocateInject(String sourceName, String name, int tp) {
|
protected InjectPayloadSleigh allocateInject(String sourceName, String name, int tp) {
|
||||||
InjectPayloadJava payload = null;
|
InjectPayloadJava payload = null;
|
||||||
if (tp != InjectPayload.CALLOTHERFIXUP_TYPE)
|
if (tp != InjectPayload.CALLOTHERFIXUP_TYPE) {
|
||||||
return super.allocateInject(sourceName, name, tp);
|
return super.allocateInject(sourceName, name, tp);
|
||||||
|
}
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case GETFIELD:
|
case GETFIELD:
|
||||||
payload = new InjectGetField(sourceName, language);
|
payload = new InjectGetField(sourceName, language);
|
||||||
@@ -199,9 +187,6 @@ public class PcodeInjectLibraryJava extends PcodeInjectLibrary {
|
|||||||
case LDC_W:
|
case LDC_W:
|
||||||
payload = new InjectLdc(sourceName, language);
|
payload = new InjectLdc(sourceName, language);
|
||||||
break;
|
break;
|
||||||
case LOOKUP_SWITCH:
|
|
||||||
payload = new InjectLookupSwitch(sourceName, language);
|
|
||||||
break;
|
|
||||||
case MULTIANEWARRAY:
|
case MULTIANEWARRAY:
|
||||||
payload = new InjectMultiANewArray(sourceName, language);
|
payload = new InjectMultiANewArray(sourceName, language);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+78
-31
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.util.pcodeInject;
|
package ghidra.app.util.pcodeInject;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* This is a utility class containing methods to emit pcode for decompile callbacks occurring during analysis of
|
* This is a utility class containing methods to emit pcode for decompile callbacks occurring during analysis of
|
||||||
@@ -30,7 +29,7 @@ public class PcodeTextEmitter {
|
|||||||
static final String RAM = "ram";
|
static final String RAM = "ram";
|
||||||
|
|
||||||
//private constructor to enforce noninstantiability
|
//private constructor to enforce noninstantiability
|
||||||
private PcodeTextEmitter(){
|
private PcodeTextEmitter() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ public class PcodeTextEmitter {
|
|||||||
* @param pCode - StringBuilder to hold pcode.
|
* @param pCode - StringBuilder to hold pcode.
|
||||||
* @param valueName - name of varnode to push.
|
* @param valueName - name of varnode to push.
|
||||||
*/
|
*/
|
||||||
public static void emitPushCat1Value(StringBuilder pCode, String valueName){
|
public static void emitPushCat1Value(StringBuilder pCode, String valueName) {
|
||||||
pCode.append("SP = SP - 4;\n*:4 SP = ");
|
pCode.append("SP = SP - 4;\n*:4 SP = ");
|
||||||
pCode.append(valueName);
|
pCode.append(valueName);
|
||||||
pCode.append(";\n");
|
pCode.append(";\n");
|
||||||
@@ -50,7 +49,7 @@ public class PcodeTextEmitter {
|
|||||||
* @param pCode - StringBuilder to hold pcode.
|
* @param pCode - StringBuilder to hold pcode.
|
||||||
* @param valueName - name of varnode to push.
|
* @param valueName - name of varnode to push.
|
||||||
*/
|
*/
|
||||||
public static void emitPushCat2Value(StringBuilder pCode, String valueName){
|
public static void emitPushCat2Value(StringBuilder pCode, String valueName) {
|
||||||
pCode.append("SP = SP - 8;\n*:8 SP = ");
|
pCode.append("SP = SP - 8;\n*:8 SP = ");
|
||||||
pCode.append(valueName);
|
pCode.append(valueName);
|
||||||
pCode.append(";\n");
|
pCode.append(";\n");
|
||||||
@@ -61,7 +60,7 @@ public class PcodeTextEmitter {
|
|||||||
* @param pCode - StringBuilder to hold pcode.
|
* @param pCode - StringBuilder to hold pcode.
|
||||||
* @param destName - name of destination varnode.
|
* @param destName - name of destination varnode.
|
||||||
*/
|
*/
|
||||||
public static void emitPopCat2Value(StringBuilder pCode, String destName){
|
public static void emitPopCat2Value(StringBuilder pCode, String destName) {
|
||||||
pCode.append(destName);
|
pCode.append(destName);
|
||||||
pCode.append(":8 = *:8 SP;\nSP = SP + 8;\n");
|
pCode.append(":8 = *:8 SP;\nSP = SP + 8;\n");
|
||||||
}
|
}
|
||||||
@@ -71,7 +70,7 @@ public class PcodeTextEmitter {
|
|||||||
* @param pCode - StringBuilder to hold pcode.
|
* @param pCode - StringBuilder to hold pcode.
|
||||||
* @param destName - name of destination varnode.
|
* @param destName - name of destination varnode.
|
||||||
*/
|
*/
|
||||||
public static void emitPopCat1Value(StringBuilder pCode, String destName){
|
public static void emitPopCat1Value(StringBuilder pCode, String destName) {
|
||||||
pCode.append(destName);
|
pCode.append(destName);
|
||||||
pCode.append(":4 = *:4 SP;\nSP = SP + 4;\n");
|
pCode.append(":4 = *:4 SP;\nSP = SP + 4;\n");
|
||||||
}
|
}
|
||||||
@@ -83,56 +82,55 @@ public class PcodeTextEmitter {
|
|||||||
* @param pcodeop - name of pcodeop
|
* @param pcodeop - name of pcodeop
|
||||||
* @param args - zero or more arguments for the pcodeop
|
* @param args - zero or more arguments for the pcodeop
|
||||||
*/
|
*/
|
||||||
public static void emitAssignVarnodeFromPcodeOpCall(StringBuilder pCode, String varnodeName, int size, String pcodeop, String... args){
|
public static void emitAssignVarnodeFromPcodeOpCall(StringBuilder pCode, String varnodeName,
|
||||||
|
int size, String pcodeop, String... args) {
|
||||||
pCode.append(varnodeName);
|
pCode.append(varnodeName);
|
||||||
pCode.append(":");
|
pCode.append(":");
|
||||||
pCode.append(Integer.toString(size));
|
pCode.append(Integer.toString(size));
|
||||||
pCode.append(" = ");
|
pCode.append(" = ");
|
||||||
pCode.append(pcodeop);
|
pCode.append(pcodeop);
|
||||||
pCode.append("(");
|
pCode.append("(");
|
||||||
for (int i = 0, numArgs = args.length; i < numArgs; ++i){
|
for (int i = 0, numArgs = args.length; i < numArgs; ++i) {
|
||||||
pCode.append(args[i]);
|
pCode.append(args[i]);
|
||||||
if (i < numArgs - 1){
|
if (i < numArgs - 1) {
|
||||||
pCode.append(",");
|
pCode.append(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pCode.append(");\n");
|
pCode.append(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits pcode to call a void black-box pcodeop
|
* Emits pcode to call a void black-box pcodeop
|
||||||
* @param pCode StringBuilder to hold the pcode
|
* @param pCode StringBuilder to hold the pcode
|
||||||
* @param pcodeop - name of pcodeop
|
* @param pcodeop - name of pcodeop
|
||||||
* @param args - zero or more arguments for the pcodeop
|
* @param args - zero or more arguments for the pcodeop
|
||||||
*/
|
*/
|
||||||
public static void emitVoidPcodeOpCall(StringBuilder pCode, String pcodeop, String... args){
|
public static void emitVoidPcodeOpCall(StringBuilder pCode, String pcodeop, String... args) {
|
||||||
pCode.append(pcodeop);
|
pCode.append(pcodeop);
|
||||||
pCode.append("(");
|
pCode.append("(");
|
||||||
for (int i = 0, numArgs = args.length; i < numArgs; ++i){
|
for (int i = 0, numArgs = args.length; i < numArgs; ++i) {
|
||||||
pCode.append(args[i]);
|
pCode.append(args[i]);
|
||||||
if (i < numArgs - 1){
|
if (i < numArgs - 1) {
|
||||||
pCode.append(",");
|
pCode.append(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pCode.append(");\n");
|
pCode.append(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the pcode to assign an integer constant to a register
|
* Appends the pcode to assign an integer constant to a register
|
||||||
* @param pCode
|
* @param pCode
|
||||||
* @param constantPool
|
* @param constantPool
|
||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
public static void emitAssignConstantToRegister(StringBuilder pCode, String register, int constant){
|
public static void emitAssignConstantToRegister(StringBuilder pCode, String register,
|
||||||
|
int constant) {
|
||||||
pCode.append(register);
|
pCode.append(register);
|
||||||
pCode.append(" = 0x");
|
pCode.append(" = 0x");
|
||||||
pCode.append(Integer.toHexString(constant));
|
pCode.append(Integer.toHexString(constant));
|
||||||
pCode.append(";\n");
|
pCode.append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the pcode to assign a register to the result of a pcode op call with arguments args
|
* Appends the pcode to assign a register to the result of a pcode op call with arguments args
|
||||||
* @param pCode
|
* @param pCode
|
||||||
@@ -140,14 +138,15 @@ public class PcodeTextEmitter {
|
|||||||
* @param pcodeop
|
* @param pcodeop
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void emitAssignRegisterFromPcodeOpCall(StringBuilder pCode, String register, String pcodeop, String... args){
|
public static void emitAssignRegisterFromPcodeOpCall(StringBuilder pCode, String register,
|
||||||
|
String pcodeop, String... args) {
|
||||||
pCode.append(register);
|
pCode.append(register);
|
||||||
pCode.append(" = ");
|
pCode.append(" = ");
|
||||||
pCode.append(pcodeop);
|
pCode.append(pcodeop);
|
||||||
pCode.append("(");
|
pCode.append("(");
|
||||||
for (int i = 0, numArgs = args.length; i < numArgs; ++i){
|
for (int i = 0, numArgs = args.length; i < numArgs; ++i) {
|
||||||
pCode.append(args[i]);
|
pCode.append(args[i]);
|
||||||
if (i < numArgs - 1){
|
if (i < numArgs - 1) {
|
||||||
pCode.append(",");
|
pCode.append(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,13 +158,22 @@ public class PcodeTextEmitter {
|
|||||||
* @param pCode
|
* @param pCode
|
||||||
* @param caseName
|
* @param caseName
|
||||||
*/
|
*/
|
||||||
public static void emitLabelDefinition(StringBuilder pCode, String caseName){
|
public static void emitLabelDefinition(StringBuilder pCode, String caseName) {
|
||||||
pCode.append("<");
|
pCode.append("<");
|
||||||
pCode.append(caseName);
|
pCode.append(caseName);
|
||||||
pCode.append(">\n");
|
pCode.append(">\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void emitWriteToMemory(StringBuilder pCode, String space, int size, String offset, String value){
|
/**
|
||||||
|
* Appends the pcode to write to a value at an offset of a memory space
|
||||||
|
* @param pCode buffer to append pcode
|
||||||
|
* @param space name of space
|
||||||
|
* @param size size of write
|
||||||
|
* @param offset offset in space
|
||||||
|
* @param value value to write
|
||||||
|
*/
|
||||||
|
public static void emitWriteToMemory(StringBuilder pCode, String space, int size, String offset,
|
||||||
|
String value) {
|
||||||
pCode.append("*[");
|
pCode.append("*[");
|
||||||
pCode.append(space);
|
pCode.append(space);
|
||||||
pCode.append("]:");
|
pCode.append("]:");
|
||||||
@@ -177,19 +185,25 @@ public class PcodeTextEmitter {
|
|||||||
pCode.append(";\n");
|
pCode.append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void emitIndirectCall(StringBuilder pCode, String target){
|
/**
|
||||||
|
* Appends the pcode to emit an indirect call
|
||||||
|
* @param pCode buffer to append to
|
||||||
|
* @param target varnode to call indirectly
|
||||||
|
*/
|
||||||
|
public static void emitIndirectCall(StringBuilder pCode, String target) {
|
||||||
pCode.append("call [");
|
pCode.append("call [");
|
||||||
pCode.append(target);
|
pCode.append(target);
|
||||||
pCode.append("];\n");
|
pCode.append("];\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void emitAddToStackPointer(StringBuilder pCode, int amount){
|
/**
|
||||||
pCode.append("SP = SP + ");
|
* Appends the pcode to sign-extend the value src into dest
|
||||||
pCode.append(Integer.toString(amount));
|
* @param pCode buffer to append to
|
||||||
pCode.append(";\n");
|
* @param dest target varnode
|
||||||
}
|
* @param size size of target varnode
|
||||||
|
* @param src size of source varnode
|
||||||
public static void emitSignExtension(StringBuilder pCode, String dest, int size, String src){
|
*/
|
||||||
|
public static void emitSignExtension(StringBuilder pCode, String dest, int size, String src) {
|
||||||
pCode.append(dest);
|
pCode.append(dest);
|
||||||
pCode.append(":");
|
pCode.append(":");
|
||||||
pCode.append(Integer.toString(size));
|
pCode.append(Integer.toString(size));
|
||||||
@@ -198,7 +212,14 @@ public class PcodeTextEmitter {
|
|||||||
pCode.append(");\n");
|
pCode.append(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void emitZeroExtension(StringBuilder pCode, String dest, int size, String src){
|
/**
|
||||||
|
* Appends the pcode to zero-extend the value src into dest
|
||||||
|
* @param pCode buffer to append to
|
||||||
|
* @param dest target varnode
|
||||||
|
* @param size size of target varnode
|
||||||
|
* @param src size of source varnode
|
||||||
|
*/
|
||||||
|
public static void emitZeroExtension(StringBuilder pCode, String dest, int size, String src) {
|
||||||
pCode.append(dest);
|
pCode.append(dest);
|
||||||
pCode.append(":");
|
pCode.append(":");
|
||||||
pCode.append(Integer.toString(size));
|
pCode.append(Integer.toString(size));
|
||||||
@@ -207,7 +228,14 @@ public class PcodeTextEmitter {
|
|||||||
pCode.append(");\n");
|
pCode.append(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void emitTruncate(StringBuilder pCode, String dest, int size, String src){
|
/**
|
||||||
|
* Appends the pcode truncate src into dest
|
||||||
|
* @param pCode buffer to append to
|
||||||
|
* @param dest target varnode
|
||||||
|
* @param size size of target varnode
|
||||||
|
* @param src size of source varnode
|
||||||
|
*/
|
||||||
|
public static void emitTruncate(StringBuilder pCode, String dest, int size, String src) {
|
||||||
pCode.append(dest);
|
pCode.append(dest);
|
||||||
pCode.append(" = ");
|
pCode.append(" = ");
|
||||||
pCode.append(src);
|
pCode.append(src);
|
||||||
@@ -216,5 +244,24 @@ public class PcodeTextEmitter {
|
|||||||
pCode.append(";\n");
|
pCode.append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the pcode to assign a varnode from a dereference of another varnode
|
||||||
|
* @param pCode buffer to append to
|
||||||
|
* @param lhs target varnode
|
||||||
|
* @param size size of pointed-to value
|
||||||
|
* @param rhs varnode to dereference
|
||||||
|
*/
|
||||||
|
public static void emitAssignVarnodeFromDereference(StringBuilder pCode, String lhs, int size,
|
||||||
|
String rhs) {
|
||||||
|
pCode.append(lhs);
|
||||||
|
pCode.append(":");
|
||||||
|
pCode.append(Integer.toString(size));
|
||||||
|
pCode.append(" = ");
|
||||||
|
pCode.append("*:");
|
||||||
|
pCode.append(Integer.toString(size));
|
||||||
|
pCode.append(" ");
|
||||||
|
pCode.append(rhs);
|
||||||
|
pCode.append(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+159
-87
@@ -16,10 +16,7 @@
|
|||||||
package ghidra.app.util.pcodeInject;
|
package ghidra.app.util.pcodeInject;
|
||||||
|
|
||||||
import ghidra.javaclass.format.DescriptorDecoder;
|
import ghidra.javaclass.format.DescriptorDecoder;
|
||||||
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
|
import ghidra.javaclass.format.constantpool.*;
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolFieldReferenceInfo;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolNameAndTypeInfo;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolUtf8Info;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -37,14 +34,15 @@ import ghidra.javaclass.format.constantpool.ConstantPoolUtf8Info;
|
|||||||
public class ReferenceMethods {
|
public class ReferenceMethods {
|
||||||
|
|
||||||
static final String VALUE = "value";
|
static final String VALUE = "value";
|
||||||
static final String TEMP = "temp";
|
static final String TEMP_1 = "temp_1";
|
||||||
|
static final String TEMP_2 = "temp_2";
|
||||||
static final String NEW_VALUE = "newValue";
|
static final String NEW_VALUE = "newValue";
|
||||||
static final String OBJECT_REF = "objectRef";
|
static final String OBJECT_REF = "objectRef";
|
||||||
static final String FIELD_OFFSET = "fieldOffset";
|
static final String FIELD_OFFSET = "fieldOffset";
|
||||||
static final String STATIC_OFFSET = "staticOffset";
|
static final String STATIC_OFFSET = "staticOffset";
|
||||||
|
|
||||||
//private constructor to enforce noninstantiability
|
//private constructor to enforce noninstantiability
|
||||||
private ReferenceMethods(){
|
private ReferenceMethods() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,43 +52,62 @@ public class ReferenceMethods {
|
|||||||
* @param constantPool - the constant pool of the class file
|
* @param constantPool - the constant pool of the class file
|
||||||
* @return - the pcode string
|
* @return - the pcode string
|
||||||
*/
|
*/
|
||||||
public static String getPcodeForGetStatic(int index, AbstractConstantPoolInfoJava[] constantPool) {
|
public static String getPcodeForGetStatic(int index,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool) {
|
||||||
StringBuilder pCode = new StringBuilder();
|
StringBuilder pCode = new StringBuilder();
|
||||||
//determine the computational category and push a value of the correct size onto the operand stack
|
//determine the computational category and push a value of the correct size onto the operand stack
|
||||||
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
||||||
|
|
||||||
switch (descriptor.charAt(0)){
|
switch (descriptor.charAt(0)) {
|
||||||
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 1, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_GETSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 1,
|
||||||
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETSTATIC);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 1, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 1, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_GETSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 1,
|
||||||
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETSTATIC);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 1, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 2, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_GETSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 2,
|
||||||
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETSTATIC);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 2, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 2, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_GETSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 2,
|
||||||
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETSTATIC);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 2, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
||||||
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
||||||
case DescriptorDecoder.BASE_TYPE_INT: //int
|
case DescriptorDecoder.BASE_TYPE_INT: //int
|
||||||
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, VALUE, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_GETSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 4,
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_GETSTATIC);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, VALUE, 4, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
||||||
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, VALUE, 8, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_GETSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 8,
|
||||||
PcodeTextEmitter.emitPushCat2Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_GETSTATIC);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, VALUE, 8, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitPushCat2Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
||||||
@@ -104,48 +121,67 @@ public class ReferenceMethods {
|
|||||||
* @param constantPool - the constant pool of the class file
|
* @param constantPool - the constant pool of the class file
|
||||||
* @return - the pcode string
|
* @return - the pcode string
|
||||||
*/
|
*/
|
||||||
public static String getPcodeForPutStatic(int index, AbstractConstantPoolInfoJava[] constantPool){
|
public static String getPcodeForPutStatic(int index,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool) {
|
||||||
StringBuilder pCode = new StringBuilder();
|
StringBuilder pCode = new StringBuilder();
|
||||||
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
||||||
|
|
||||||
switch (descriptor.charAt(0)){
|
switch (descriptor.charAt(0)) {
|
||||||
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_PUTSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 1, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, STATIC_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTSTATIC);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 1, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, STATIC_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_PUTSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 1, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, STATIC_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTSTATIC);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 1, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, STATIC_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_PUTSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 2, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, STATIC_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTSTATIC);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 2, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, STATIC_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_PUTSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 2, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, STATIC_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTSTATIC);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 2, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, STATIC_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
||||||
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
||||||
case DescriptorDecoder.BASE_TYPE_INT: //int
|
case DescriptorDecoder.BASE_TYPE_INT: //int
|
||||||
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_PUTSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 4, STATIC_OFFSET, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_PUTSTATIC);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 4, STATIC_OFFSET,
|
||||||
|
NEW_VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
||||||
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
||||||
PcodeTextEmitter.emitPopCat2Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat2Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4, ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index), ConstantPoolJava.CPOOL_PUTSTATIC);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, STATIC_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 8, STATIC_OFFSET, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, "0", Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_PUTSTATIC);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 8, STATIC_OFFSET,
|
||||||
|
NEW_VALUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
||||||
@@ -159,49 +195,68 @@ public class ReferenceMethods {
|
|||||||
* @param constantPool
|
* @param constantPool
|
||||||
* @return - the pcode string
|
* @return - the pcode string
|
||||||
*/
|
*/
|
||||||
public static String getPcodeForGetField(int index, AbstractConstantPoolInfoJava[] constantPool) {
|
public static String getPcodeForGetField(int index,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool) {
|
||||||
StringBuilder pCode = new StringBuilder();
|
StringBuilder pCode = new StringBuilder();
|
||||||
|
|
||||||
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
||||||
|
|
||||||
switch (descriptor.charAt(0)){
|
switch (descriptor.charAt(0)) {
|
||||||
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 1, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_GETFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 1,
|
||||||
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETFIELD);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 1, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 1, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_GETFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 1,
|
||||||
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETFIELD);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 1, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 2, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_GETFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 2,
|
||||||
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETFIELD);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 2, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitZeroExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP, 2, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_GETFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 2,
|
||||||
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_GETFIELD);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, TEMP_2, 2, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitSignExtension(pCode, VALUE, 4, TEMP_2);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
||||||
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
||||||
case DescriptorDecoder.BASE_TYPE_INT: //int
|
case DescriptorDecoder.BASE_TYPE_INT: //int
|
||||||
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, VALUE, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_GETFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 4,
|
||||||
PcodeTextEmitter.emitPushCat1Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_GETFIELD);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, VALUE, 4, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitPushCat1Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
||||||
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, VALUE, 8, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_GETFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, TEMP_1, 8,
|
||||||
PcodeTextEmitter.emitPushCat2Value(pCode,VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_GETFIELD);
|
||||||
|
PcodeTextEmitter.emitAssignVarnodeFromDereference(pCode, VALUE, 8, TEMP_1);
|
||||||
|
PcodeTextEmitter.emitPushCat2Value(pCode, VALUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
||||||
@@ -215,41 +270,53 @@ public class ReferenceMethods {
|
|||||||
* @param constantPool - the constant pool
|
* @param constantPool - the constant pool
|
||||||
* @return - the pcode
|
* @return - the pcode
|
||||||
*/
|
*/
|
||||||
public static String getPcodeForPutField(int index, AbstractConstantPoolInfoJava[] constantPool) {
|
public static String getPcodeForPutField(int index,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool) {
|
||||||
StringBuilder pCode = new StringBuilder();
|
StringBuilder pCode = new StringBuilder();
|
||||||
|
|
||||||
//determine the computational category and push a value of the correct size onto the operand stack
|
//determine the computational category and push a value of the correct size onto the operand stack
|
||||||
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
String descriptor = getDescriptorForFieldRef(constantPool, index);
|
||||||
|
|
||||||
|
switch (descriptor.charAt(0)) {
|
||||||
switch (descriptor.charAt(0)){
|
|
||||||
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
case DescriptorDecoder.BASE_TYPE_BYTE: //signed byte
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_PUTFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 1, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, FIELD_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTFIELD);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 1, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, FIELD_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
case DescriptorDecoder.BASE_TYPE_BOOLEAN: //boolean
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_PUTFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 1, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, FIELD_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTFIELD);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 1, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 1, FIELD_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
case DescriptorDecoder.BASE_TYPE_CHAR: //char
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_PUTFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 2, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, FIELD_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTFIELD);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 2, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, FIELD_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
case DescriptorDecoder.BASE_TYPE_SHORT: //signed short
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_PUTFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitTruncate(pCode, TEMP, 2, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, FIELD_OFFSET, TEMP);
|
ConstantPoolJava.CPOOL_PUTFIELD);
|
||||||
|
PcodeTextEmitter.emitTruncate(pCode, TEMP_1, 2, NEW_VALUE);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 2, FIELD_OFFSET,
|
||||||
|
TEMP_1);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
case DescriptorDecoder.BASE_TYPE_ARRAY: //array dimension
|
||||||
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
case DescriptorDecoder.BASE_TYPE_FLOAT: //float
|
||||||
@@ -257,22 +324,27 @@ public class ReferenceMethods {
|
|||||||
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
case DescriptorDecoder.BASE_TYPE_REFERENCE: //object reference
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat1Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_PUTFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 4, FIELD_OFFSET, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_PUTFIELD);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 4, FIELD_OFFSET,
|
||||||
|
NEW_VALUE);
|
||||||
break;
|
break;
|
||||||
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
case DescriptorDecoder.BASE_TYPE_DOUBLE: //double
|
||||||
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
case DescriptorDecoder.BASE_TYPE_LONG: //long
|
||||||
PcodeTextEmitter.emitPopCat2Value(pCode, NEW_VALUE);
|
PcodeTextEmitter.emitPopCat2Value(pCode, NEW_VALUE);
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
PcodeTextEmitter.emitPopCat1Value(pCode, OBJECT_REF);
|
||||||
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4, ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index), ConstantPoolJava.CPOOL_PUTFIELD);
|
PcodeTextEmitter.emitAssignVarnodeFromPcodeOpCall(pCode, FIELD_OFFSET, 4,
|
||||||
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 8, FIELD_OFFSET, NEW_VALUE);
|
ConstantPoolJava.CPOOL_OP, OBJECT_REF, Integer.toString(index),
|
||||||
|
ConstantPoolJava.CPOOL_PUTFIELD);
|
||||||
|
PcodeTextEmitter.emitWriteToMemory(pCode, PcodeTextEmitter.RAM, 8, FIELD_OFFSET,
|
||||||
|
NEW_VALUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
|
||||||
}
|
}
|
||||||
return pCode.toString();
|
return pCode.toString();
|
||||||
|
|
||||||
|
|
||||||
/*JavaComputationalCategory category = DescriptorDecoder.getComputationalCategoryOfDescriptor(descriptor);
|
/*JavaComputationalCategory category = DescriptorDecoder.getComputationalCategoryOfDescriptor(descriptor);
|
||||||
switch (category){
|
switch (category){
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
@@ -295,21 +367,21 @@ public class ReferenceMethods {
|
|||||||
return pCode.toString();*/
|
return pCode.toString();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the descriptor of a field reference in the constant pool
|
* Returns the descriptor of a field reference in the constant pool
|
||||||
* @param constantPool
|
* @param constantPool
|
||||||
* @param index
|
* @param index
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static String getDescriptorForFieldRef(AbstractConstantPoolInfoJava[] constantPool, int index){
|
static String getDescriptorForFieldRef(AbstractConstantPoolInfoJava[] constantPool, int index) {
|
||||||
ConstantPoolFieldReferenceInfo fieldRef = (ConstantPoolFieldReferenceInfo) constantPool[index];
|
ConstantPoolFieldReferenceInfo fieldRef =
|
||||||
|
(ConstantPoolFieldReferenceInfo) constantPool[index];
|
||||||
int nameAndTypeIndex = fieldRef.getNameAndTypeIndex();
|
int nameAndTypeIndex = fieldRef.getNameAndTypeIndex();
|
||||||
ConstantPoolNameAndTypeInfo nameAndTypeInfo = (ConstantPoolNameAndTypeInfo) constantPool[nameAndTypeIndex];
|
ConstantPoolNameAndTypeInfo nameAndTypeInfo =
|
||||||
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info) constantPool[nameAndTypeInfo.getDescriptorIndex()];
|
(ConstantPoolNameAndTypeInfo) constantPool[nameAndTypeIndex];
|
||||||
|
ConstantPoolUtf8Info descriptorInfo =
|
||||||
|
(ConstantPoolUtf8Info) constantPool[nameAndTypeInfo.getDescriptorIndex()];
|
||||||
return descriptorInfo.getString();
|
return descriptorInfo.getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* 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.util.pcodeInject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This is a utility class for generating pcode for the lookupswitch operation.
|
|
||||||
*
|
|
||||||
* This class is evolving and may eventually be replaced.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import ghidra.app.util.bin.ByteProvider;
|
|
||||||
import ghidra.app.util.bin.MemoryByteProvider;
|
|
||||||
import ghidra.program.model.lang.InjectContext;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
|
|
||||||
public class SwitchMethods {
|
|
||||||
|
|
||||||
static final String KEY = "key";
|
|
||||||
static final String SWITCH_TARGET = "switch_target";
|
|
||||||
|
|
||||||
public static String getPcodeForLookupSwitch(InjectContext injectContext, Program program) throws IOException {
|
|
||||||
StringBuilder pCode = new StringBuilder();
|
|
||||||
|
|
||||||
int defaultAddr = (int) injectContext.inputlist.get(0).getOffset();
|
|
||||||
int numPairs = (int) injectContext.inputlist.get(1).getOffset();
|
|
||||||
int padding = (int) injectContext.inputlist.get(2).getOffset();
|
|
||||||
|
|
||||||
PcodeTextEmitter.emitPopCat1Value(pCode, KEY);
|
|
||||||
|
|
||||||
int target = (int) (injectContext.baseAddr.getOffset() + defaultAddr);
|
|
||||||
PcodeTextEmitter.emitAssignConstantToRegister(pCode, SWITCH_TARGET, target);
|
|
||||||
ByteProvider provider = new MemoryByteProvider(program.getMemory(),injectContext.baseAddr);
|
|
||||||
byte[] bytes = provider.readBytes(1 + padding + 8, 8 * numPairs);
|
|
||||||
for (int i = 0, length = bytes.length ; i < length; i += 8){
|
|
||||||
int match = ((bytes[i] << 24) & 0xff000000) | ((bytes[i+1] << 16) & 0xff0000) | ((bytes[i+2] <<8) & 0xff00) | (bytes[i+3] & 0xff);
|
|
||||||
int offset = ((bytes[i+4] << 24) & 0xff000000) | ((bytes[i+5] << 16) & 0xff0000) | ((bytes[i+6] <<8) & 0xff00) | (bytes[i+7] & 0xff);
|
|
||||||
target = (int) (injectContext.baseAddr.getOffset() + offset);
|
|
||||||
pCode.append("if (key != " + match +") goto <test"+i+">;\n");
|
|
||||||
pCode.append(SWITCH_TARGET);
|
|
||||||
pCode.append(" = inst_start + " +offset+ ";\n");
|
|
||||||
//uncomment this to have the decompiler display multiple switch(address) statements
|
|
||||||
//pCode.append("goto [switch_target];\n");
|
|
||||||
PcodeTextEmitter.emitLabelDefinition(pCode, "test"+i);
|
|
||||||
}
|
|
||||||
pCode.append("SP=SP;\n");
|
|
||||||
provider.close();
|
|
||||||
return pCode.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+256
-312
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,23 +15,33 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.flags;
|
package ghidra.javaclass.flags;
|
||||||
|
|
||||||
public final class ClassFileFlags {
|
public enum ClassFileFlags {
|
||||||
|
|
||||||
/** Declared public; may be accessed from outside its package. */
|
/** Declared public; may be accessed from outside its package. */
|
||||||
public final static short ACC_PUBLIC = 0x0001;
|
ACC_PUBLIC(0x0001),
|
||||||
/** Declared final; no subclasses allowed. */
|
/** Declared final; no subclasses allowed. */
|
||||||
public final static short ACC_FINAL = 0x0010;
|
ACC_FINAL(0x0010),
|
||||||
/** Treat superclass methods specially when invoked by the invokespecial instruction. */
|
/** Treat superclass methods specially when invoked by the invokespecial instruction. */
|
||||||
public final static short ACC_SUPER = 0x0020;
|
ACC_SUPER(0x0020),
|
||||||
/** Is an interface, not a class. */
|
/** Is an interface, not a class. */
|
||||||
public final static short ACC_INTERFACE = 0x0200;
|
ACC_INTERFACE(0x0200),
|
||||||
/** Declared abstract; must not be instantiated. */
|
/** Declared abstract; must not be instantiated. */
|
||||||
public final static short ACC_ABSTRACT = 0x0400;
|
ACC_ABSTRACT(0x0400),
|
||||||
/** Declared synthetic; not present in the source code. */
|
/** Declared synthetic; not present in the source code. */
|
||||||
public final static short ACC_SYNTHETIC = 0x1000;
|
ACC_SYNTHETIC(0x1000),
|
||||||
/** Declared as an annotation type. */
|
/** Declared as an annotation type. */
|
||||||
public final static short ACC_ANNOTATION = 0x2000;
|
ACC_ANNOTATION(0x2000),
|
||||||
/** Declared as an enum type. */
|
/** Declared as an enum type. */
|
||||||
public final static short ACC_ENUM = 0x4000;
|
ACC_ENUM(0x4000);
|
||||||
|
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
private ClassFileFlags(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-12
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,25 +15,33 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.flags;
|
package ghidra.javaclass.flags;
|
||||||
|
|
||||||
final class FieldInfoAccessFlags {
|
public enum FieldInfoAccessFlags {
|
||||||
|
|
||||||
/** Declared public; may be accessed from outside its package. */
|
/** Declared public; may be accessed from outside its package. */
|
||||||
public final short ACC_PUBLIC = 0x0001;
|
ACC_PUBLIC(0x0001),
|
||||||
/** Declared private; usable only within the defining class. */
|
/** Declared private; usable only within the defining class. */
|
||||||
public final short ACC_PRIVATE = 0x0002;
|
ACC_PRIVATE(0x0002),
|
||||||
/** Declared protected; may be accessed within subclasses. */
|
/** Declared protected; may be accessed within subclasses. */
|
||||||
public final short ACC_PROTECTED = 0x0004;
|
ACC_PROTECTED(0x0004),
|
||||||
/** Declared static. */
|
/** Declared static. */
|
||||||
public final short ACC_STATIC = 0x0008;
|
ACC_STATIC(0x0008),
|
||||||
/** Declared final; never directly assigned to after object construction (JLS ?17.5). */
|
/** Declared final; never directly assigned to after object construction (JLS ?17.5). */
|
||||||
public final short ACC_FINAL = 0x0010;
|
ACC_FINAL(0x0010),
|
||||||
/** Declared volatile; cannot be cached. */
|
/** Declared volatile; cannot be cached. */
|
||||||
public final short ACC_VOLATILE = 0x0040;
|
ACC_VOLATILE(0x00400),
|
||||||
/** Declared transient; not written or read by a persistent object manager. */
|
/** Declared transient; not written or read by a persistent object manager. */
|
||||||
public final short ACC_TRANSIENT = 0x0080;
|
ACC_TRANSIENT(0x0080),
|
||||||
/** Declared synthetic; not present in the source code. */
|
/** Declared synthetic; not present in the source code. */
|
||||||
public final short ACC_SYNTHETIC = 0x1000;
|
ACC_SYNTHETIC(0x1000),
|
||||||
/** Declared as an element of an enum. */
|
/** Declared as an element of an enum. */
|
||||||
public final short ACC_ENUM = 0x4000;
|
ACC_ENUM(0x4000);
|
||||||
|
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
private FieldInfoAccessFlags(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+64
-14
@@ -15,31 +15,81 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.flags;
|
package ghidra.javaclass.flags;
|
||||||
|
|
||||||
public final class MethodsInfoAccessFlags {
|
public enum MethodsInfoAccessFlags {
|
||||||
|
|
||||||
/** Declared public; may be accessed from outside its package. */
|
/** Declared public; may be accessed from outside its package. */
|
||||||
public final static short ACC_PUBLIC = 0x0001;
|
ACC_PUBLIC(0x0001),
|
||||||
/** Declared private; accessible only within the defining class. */
|
/** Declared private; accessible only within the defining class. */
|
||||||
public final static short ACC_PRIVATE = 0x0002;
|
ACC_PRIVATE(0x0002),
|
||||||
/** Declared protected; may be accessed within subclasses. */
|
/** Declared protected; may be accessed within subclasses. */
|
||||||
public final static short ACC_PROTECTED = 0x0004;
|
ACC_PROTECTED(0x0004),
|
||||||
/** Declared static. */
|
/** Declared static. */
|
||||||
public final static short ACC_STATIC = 0x0008;
|
ACC_STATIC(0x0008),
|
||||||
/** Declared final; must not be overridden (5.4.5). */
|
/** Declared final; must not be overridden (5.4.5). */
|
||||||
public final static short ACC_FINAL = 0x0010;
|
ACC_FINAL(0x0010),
|
||||||
/** Declared synchronized; invocation is wrapped by a monitor use. */
|
/** Declared synchronized; invocation is wrapped by a monitor use. */
|
||||||
public final static short ACC_SYNCHRONIZED = 0x0020;
|
ACC_SYNCHRONIZED(0x0020),
|
||||||
/** A bridge method, generated by the compiler. */
|
/** A bridge method, generated by the compiler. */
|
||||||
public final static short ACC_BRIDGE = 0x0040;
|
ACC_BRIDGE(0x0040),
|
||||||
/** Declared with variable number of arguments. */
|
/** Declared with variable number of arguments. */
|
||||||
public final static short ACC_VARARGS = 0x0080;
|
ACC_VARARGS(0x0080),
|
||||||
/** Declared native; implemented in a language other than Java. */
|
/** Declared native; implemented in a language other than Java. */
|
||||||
public final static short ACC_NATIVE = 0x0100;
|
ACC_NATIVE(0x0100),
|
||||||
/** Declared abstract; no implementation is provided. */
|
/** Declared abstract; no implementation is provided. */
|
||||||
public final static short ACC_ABSTRACT = 0x0400;
|
ACC_ABSTRACT(0x0400),
|
||||||
/** Declared strictfp; floating-point mode is FP-strict. */
|
/** Declared strictfp; floating-point mode is FP-strict. */
|
||||||
public final static short ACC_STRICT = 0x0800;
|
ACC_STRICT(0x0800),
|
||||||
/** Declared synthetic; not present in the source code. */
|
/** Declared synthetic; not present in the source code. */
|
||||||
public final static short ACC_SYNTHETIC = 0x1000;
|
ACC_SYNTHETIC(0x1000);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private MethodsInfoAccessFlags(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a text representation for a given set of access flags.
|
||||||
|
* Here are some examples:
|
||||||
|
* <DL>
|
||||||
|
* <DD><CODE>"public static final"</CODE>,</DD>
|
||||||
|
* <DD><CODE>"package private"</CODE>, or</DD>
|
||||||
|
* <DD><CODE>"protected transient"</CODE>.</DD>
|
||||||
|
* </DL>
|
||||||
|
* Note: only access flags that map to Java modifier keywords are returned.
|
||||||
|
* @param access the mask of flags denoting access permission.
|
||||||
|
* @return a text representation of the access flags.
|
||||||
|
*/
|
||||||
|
public static String toString(int access) {
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
if ((access & ACC_PUBLIC.value) == ACC_PUBLIC.value) {
|
||||||
|
stringBuffer.append("public ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_PRIVATE.value) == ACC_PRIVATE.value) {
|
||||||
|
stringBuffer.append("private ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_PROTECTED.value) == ACC_PROTECTED.value) {
|
||||||
|
stringBuffer.append("protected ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_STATIC.value) == ACC_STATIC.value) {
|
||||||
|
stringBuffer.append("static ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_FINAL.value) == ACC_FINAL.value) {
|
||||||
|
stringBuffer.append("final ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_SYNCHRONIZED.value) == ACC_SYNCHRONIZED.value) {
|
||||||
|
stringBuffer.append("synchronized ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_NATIVE.value) == ACC_NATIVE.value) {
|
||||||
|
stringBuffer.append("native ");
|
||||||
|
}
|
||||||
|
if ((access & ACC_ABSTRACT.value) == ACC_ABSTRACT.value) {
|
||||||
|
stringBuffer.append("abstract ");
|
||||||
|
}
|
||||||
|
return stringBuffer.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,165 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility class defining access flags and access utility methods.
|
|
||||||
* Access flags are as defined by the Java Virtual Machine Specification
|
|
||||||
* Second Edition, tables 4.1, 4.4, 4.5 and 4.7.
|
|
||||||
*/
|
|
||||||
public abstract class AccessFlagsJava {
|
|
||||||
|
|
||||||
/** Declared public, may be accessed from outside its package. */
|
|
||||||
public static final int PUBLIC = 0x0001;
|
|
||||||
|
|
||||||
/** Declared private, usable only within the defining class. */
|
|
||||||
public static final int PRIVATE = 0x0002;
|
|
||||||
|
|
||||||
/** Declared protected, may be accessed within subclasses. */
|
|
||||||
public static final int PROTECTED = 0x0004;
|
|
||||||
|
|
||||||
/** Declared static. */
|
|
||||||
public static final int STATIC = 0x0008;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declared final. For classes this means no subclassing allowed.
|
|
||||||
* For fields it means no further assignment allowed after initialization.
|
|
||||||
* For methods it means that the method cannot be overridden.
|
|
||||||
*/
|
|
||||||
public static final int FINAL = 0x0010;
|
|
||||||
|
|
||||||
/** Declared synchronized; invocation is wrapped in a monitor lock. */
|
|
||||||
public static final int SYNCHRONIZED = 0x0020;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Treat superclass methods specially when invoked by the
|
|
||||||
* <i>invokespecial</i> instruction. This access only applies to
|
|
||||||
* classes, and shares the same value as SYNCHRONIZED.
|
|
||||||
*/
|
|
||||||
public static final int SUPER = 0x0020;
|
|
||||||
|
|
||||||
/** Declared volatile; cannot be cached. */
|
|
||||||
public static final int VOLATILE = 0x0040;
|
|
||||||
|
|
||||||
/** A bridge method, generated by the compiler. */
|
|
||||||
public static final int BRIDGE = 0x0040;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declared transient; not written or read by a persistent object
|
|
||||||
* manager
|
|
||||||
*/
|
|
||||||
public static final int TRANSIENT = 0x0080;
|
|
||||||
|
|
||||||
/** Declared with a variable number of arguments. */
|
|
||||||
public static final int VARARGS = 0x0080;
|
|
||||||
|
|
||||||
/** Declared native; implemented in a language other than Java. */
|
|
||||||
public static final int NATIVE = 0x0100;
|
|
||||||
|
|
||||||
/** Is an interface, not a class. */
|
|
||||||
public static final int INTERFACE = 0x0200;
|
|
||||||
|
|
||||||
/** Declared abstract; must not be instantiated. */
|
|
||||||
public static final int ABSTRACT = 0x0400;
|
|
||||||
|
|
||||||
/** Declared strictfp; floating point mode is FP-strict. */
|
|
||||||
public static final int STRICT = 0x0800;
|
|
||||||
|
|
||||||
/** Declared synthetic, not present in the source file. */
|
|
||||||
public static final int SYNTHETIC = 0x1000;
|
|
||||||
|
|
||||||
/** Declared as an annotation type. */
|
|
||||||
public static final int ANNOTATION = 0x2000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For classes, declared as an enum type. For fields, declared as
|
|
||||||
* an element of an enum.
|
|
||||||
*/
|
|
||||||
public static final int ENUM = 0x4000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a text representation for a given set of access flags.
|
|
||||||
* Here are some examples:
|
|
||||||
* <DL>
|
|
||||||
* <DD><CODE>"public static final"</CODE>,</DD>
|
|
||||||
* <DD><CODE>"package private"</CODE>, or</DD>
|
|
||||||
* <DD><CODE>"protected transient"</CODE>.</DD>
|
|
||||||
* </DL>
|
|
||||||
* Note: only access flags that map to Java modifier keywords are returned.
|
|
||||||
* @param access the mask of flags denoting access permission.
|
|
||||||
* @return a text representation of the access flags.
|
|
||||||
*/
|
|
||||||
public static String toString( int access, boolean isClass ) {
|
|
||||||
StringBuffer stringBuffer = new StringBuffer();
|
|
||||||
if ( ( access & PUBLIC ) == PUBLIC ) {
|
|
||||||
stringBuffer.append( "public " );
|
|
||||||
}
|
|
||||||
if ( ( access & PRIVATE ) == PRIVATE ) {
|
|
||||||
stringBuffer.append( "private " );
|
|
||||||
}
|
|
||||||
if ( ( access & PROTECTED ) == PROTECTED ) {
|
|
||||||
stringBuffer.append( "protected " );
|
|
||||||
}
|
|
||||||
if ( ( access & STATIC ) == STATIC ) {
|
|
||||||
stringBuffer.append( "static " );
|
|
||||||
}
|
|
||||||
if ( ( access & FINAL ) == FINAL ) {
|
|
||||||
stringBuffer.append( "final " );
|
|
||||||
}
|
|
||||||
if ( !isClass && ( access & SYNCHRONIZED ) == SYNCHRONIZED ) {
|
|
||||||
stringBuffer.append( "synchronized " );
|
|
||||||
}
|
|
||||||
if ( ( access & VOLATILE ) == VOLATILE ) {
|
|
||||||
stringBuffer.append( "volatile ");
|
|
||||||
}
|
|
||||||
if ( ( access & TRANSIENT ) == TRANSIENT ) {
|
|
||||||
stringBuffer.append( "transient " );
|
|
||||||
}
|
|
||||||
if ( ( access & NATIVE) == NATIVE ) {
|
|
||||||
stringBuffer.append( "native " );
|
|
||||||
}
|
|
||||||
if ( ( access & ABSTRACT ) == ABSTRACT && ( access & INTERFACE ) == 0) {//interfaces are always abstract, so drop the abstract keyword
|
|
||||||
stringBuffer.append( "abstract " );
|
|
||||||
}
|
|
||||||
// trim trailing space
|
|
||||||
return stringBuffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isStatic( int access ) {
|
|
||||||
return ( ( access & STATIC ) == STATIC );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final boolean isPublic( int access ) {
|
|
||||||
return ( ( access & PUBLIC ) == PUBLIC );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final boolean isProtected( int access ) {
|
|
||||||
return ( ( access & PROTECTED ) == PROTECTED );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final boolean isPackagePrivate( int access ) {
|
|
||||||
return ( ( access & ( PUBLIC | PRIVATE | PROTECTED ) ) == 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final boolean isPrivate( int access ) {
|
|
||||||
return ( ( access & PRIVATE ) == PRIVATE );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final boolean isInterface( int access ) {
|
|
||||||
return ( ( access & INTERFACE ) == INTERFACE );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -15,22 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format;
|
package ghidra.javaclass.format;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.javaclass.format.attributes.AbstractAttributeInfo;
|
import ghidra.javaclass.format.attributes.AbstractAttributeInfo;
|
||||||
import ghidra.javaclass.format.attributes.AttributeFactory;
|
import ghidra.javaclass.format.attributes.AttributeFactory;
|
||||||
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
|
import ghidra.javaclass.format.constantpool.*;
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolDoubleInfo;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolFactory;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolLongInfo;
|
|
||||||
import ghidra.program.model.data.ArrayDataType;
|
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.Structure;
|
|
||||||
import ghidra.program.model.data.StructureDataType;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -85,9 +79,9 @@ public class ClassFileJava implements StructConverter {
|
|||||||
minorVersion = reader.readNextShort();
|
minorVersion = reader.readNextShort();
|
||||||
majorVersion = reader.readNextShort();
|
majorVersion = reader.readNextShort();
|
||||||
constantPoolCount = reader.readNextShort();
|
constantPoolCount = reader.readNextShort();
|
||||||
constantPool = new AbstractConstantPoolInfoJava[constantPoolCount];
|
constantPool = new AbstractConstantPoolInfoJava[getConstantPoolCount()];
|
||||||
//NOTE: start at index 1 per JVM specification!!!
|
//NOTE: start at index 1 per JVM specification!!!
|
||||||
for (int i = 1; i < constantPoolCount; i++) {
|
for (int i = 1; i < getConstantPoolCount(); i++) {
|
||||||
constantPool[i] = ConstantPoolFactory.get(reader);
|
constantPool[i] = ConstantPoolFactory.get(reader);
|
||||||
|
|
||||||
//From section 4.4.5 of JVM specification:
|
//From section 4.4.5 of JVM specification:
|
||||||
@@ -105,20 +99,20 @@ public class ClassFileJava implements StructConverter {
|
|||||||
thisClass = reader.readNextShort();
|
thisClass = reader.readNextShort();
|
||||||
superClass = reader.readNextShort();
|
superClass = reader.readNextShort();
|
||||||
interfacesCount = reader.readNextShort();
|
interfacesCount = reader.readNextShort();
|
||||||
interfaces = reader.readNextShortArray(interfacesCount);
|
interfaces = reader.readNextShortArray(getInterfacesCount());
|
||||||
fieldsCount = reader.readNextShort();
|
fieldsCount = reader.readNextShort();
|
||||||
fields = new FieldInfoJava[fieldsCount];
|
fields = new FieldInfoJava[getFieldsCount()];
|
||||||
for (int i = 0; i < fieldsCount; i++) {
|
for (int i = 0; i < getFieldsCount(); i++) {
|
||||||
fields[i] = new FieldInfoJava(reader, this);
|
fields[i] = new FieldInfoJava(reader, this);
|
||||||
}
|
}
|
||||||
methodsCount = reader.readNextShort();
|
methodsCount = reader.readNextShort();
|
||||||
methods = new MethodInfoJava[methodsCount];
|
methods = new MethodInfoJava[getMethodsCount()];
|
||||||
for (int i = 0; i < methodsCount; i++) {
|
for (int i = 0; i < getMethodsCount(); i++) {
|
||||||
methods[i] = new MethodInfoJava(reader, this);
|
methods[i] = new MethodInfoJava(reader, this);
|
||||||
}
|
}
|
||||||
attributesCount = reader.readNextShort();
|
attributesCount = reader.readNextShort();
|
||||||
attributes = new AbstractAttributeInfo[attributesCount];
|
attributes = new AbstractAttributeInfo[getAttributesCount()];
|
||||||
for (int i = 0; i < attributesCount; i++) {
|
for (int i = 0; i < getAttributesCount(); i++) {
|
||||||
attributes[i] = AttributeFactory.get(reader, getConstantPool());
|
attributes[i] = AttributeFactory.get(reader, getConstantPool());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,8 +167,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* exception for constants of type long and double noted in ?4.4.5.
|
* exception for constants of type long and double noted in ?4.4.5.
|
||||||
* @return the number of entries in the constant_pool table plus one
|
* @return the number of entries in the constant_pool table plus one
|
||||||
*/
|
*/
|
||||||
public short getConstantPoolCount() {
|
public int getConstantPoolCount() {
|
||||||
return constantPoolCount;
|
return constantPoolCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,8 +201,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* defined by this class file.
|
* defined by this class file.
|
||||||
* @return a valid index into the constant_pool table to a CONSTANT_Class_info
|
* @return a valid index into the constant_pool table to a CONSTANT_Class_info
|
||||||
*/
|
*/
|
||||||
public short getThisClass() {
|
public int getThisClass() {
|
||||||
return thisClass;
|
return thisClass & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,8 +222,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* must be a CONSTANT_Class_info structure representing the class Object.
|
* must be a CONSTANT_Class_info structure representing the class Object.
|
||||||
* @return a valid index into the constant_pool table to a CONSTANT_Class_info
|
* @return a valid index into the constant_pool table to a CONSTANT_Class_info
|
||||||
*/
|
*/
|
||||||
public short getSuperClass() {
|
public int getSuperClass() {
|
||||||
return superClass;
|
return superClass & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,8 +231,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* superinterfaces of this class or interface type.
|
* superinterfaces of this class or interface type.
|
||||||
* @return the number of direct superinterfaces of this class
|
* @return the number of direct superinterfaces of this class
|
||||||
*/
|
*/
|
||||||
public short getInterfacesCount() {
|
public int getInterfacesCount() {
|
||||||
return interfacesCount;
|
return interfacesCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -248,10 +242,11 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* CONSTANT_Class_info (?4.4.1) structure representing an interface that is a
|
* CONSTANT_Class_info (?4.4.1) structure representing an interface that is a
|
||||||
* direct superinterface of this class or interface type, in the left-to-right order
|
* direct superinterface of this class or interface type, in the left-to-right order
|
||||||
* given in the source for the type.
|
* given in the source for the type.
|
||||||
* @return an array of interfaces
|
* @param i entry
|
||||||
|
* @return interface index
|
||||||
*/
|
*/
|
||||||
public short[] getInterfaces() {
|
public int getInterfacesEntry(int i) {
|
||||||
return interfaces;
|
return interfaces[i] & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,8 +256,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* interface type.
|
* interface type.
|
||||||
* @return the number of field_info structures in the fields table
|
* @return the number of field_info structures in the fields table
|
||||||
*/
|
*/
|
||||||
public short getFieldsCount() {
|
public int getFieldsCount() {
|
||||||
return fieldsCount;
|
return fieldsCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,8 +277,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* structures in the methods table.
|
* structures in the methods table.
|
||||||
* @return the number of method_info structures in the methods table
|
* @return the number of method_info structures in the methods table
|
||||||
*/
|
*/
|
||||||
public short getMethodsCount() {
|
public int getMethodsCount() {
|
||||||
return methodsCount;
|
return methodsCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,8 +304,8 @@ public class ClassFileJava implements StructConverter {
|
|||||||
* in the attributes table of this class.
|
* in the attributes table of this class.
|
||||||
* @return the number of attributes in the attributes table
|
* @return the number of attributes in the attributes table
|
||||||
*/
|
*/
|
||||||
public short getAttributesCount() {
|
public int getAttributesCount() {
|
||||||
return attributesCount;
|
return attributesCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,14 +365,14 @@ public class ClassFileJava implements StructConverter {
|
|||||||
structure.add(WORD, "super_class", null);
|
structure.add(WORD, "super_class", null);
|
||||||
structure.add(WORD, "interfaces_count", null);
|
structure.add(WORD, "interfaces_count", null);
|
||||||
|
|
||||||
if (interfacesCount > 0) {
|
if (getInterfacesCount() > 0) {
|
||||||
DataType array = new ArrayDataType(WORD, interfacesCount, WORD.getLength());
|
DataType array = new ArrayDataType(WORD, getInterfacesCount(), WORD.getLength());
|
||||||
structure.add(array, "interfaces", null);
|
structure.add(array, "interfaces", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
structure.add(WORD, "field_count", null);
|
structure.add(WORD, "field_count", null);
|
||||||
|
|
||||||
if (fieldsCount > 0) {
|
if (getFieldsCount() > 0) {
|
||||||
Structure fieldStruct = new StructureDataType("fields", 0);
|
Structure fieldStruct = new StructureDataType("fields", 0);
|
||||||
for (int i = 0; i < fields.length; ++i) {
|
for (int i = 0; i < fields.length; ++i) {
|
||||||
fieldStruct.add(fields[i].toDataType(), "field_" + i, null);
|
fieldStruct.add(fields[i].toDataType(), "field_" + i, null);
|
||||||
@@ -387,7 +382,7 @@ public class ClassFileJava implements StructConverter {
|
|||||||
|
|
||||||
structure.add(WORD, "method_count", null);
|
structure.add(WORD, "method_count", null);
|
||||||
|
|
||||||
if (methodsCount > 0) {
|
if (getMethodsCount() > 0) {
|
||||||
Structure methodsStruct = new StructureDataType("methods", 0);
|
Structure methodsStruct = new StructureDataType("methods", 0);
|
||||||
for (int i = 0; i < methods.length; ++i) {
|
for (int i = 0; i < methods.length; ++i) {
|
||||||
methodsStruct.add(methods[i].toDataType(), "methods_" + i, null);
|
methodsStruct.add(methods[i].toDataType(), "methods_" + i, null);
|
||||||
@@ -396,7 +391,7 @@ public class ClassFileJava implements StructConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
structure.add(WORD, "attributes_count", null);
|
structure.add(WORD, "attributes_count", null);
|
||||||
if (attributesCount > 0){
|
if (getAttributesCount() > 0) {
|
||||||
Structure attributesStruct = new StructureDataType("attributes", 0);
|
Structure attributesStruct = new StructureDataType("attributes", 0);
|
||||||
for (int i = 0; i < attributes.length; ++i) {
|
for (int i = 0; i < attributes.length; ++i) {
|
||||||
attributesStruct.add(attributes[i].toDataType(), "attributes_" + i, null);
|
attributesStruct.add(attributes[i].toDataType(), "attributes_" + i, null);
|
||||||
|
|||||||
+154
-89
@@ -19,12 +19,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.pcodeInject.*;
|
import ghidra.app.util.pcodeInject.*;
|
||||||
import ghidra.javaclass.format.constantpool.AbstractConstantPoolInfoJava;
|
import ghidra.javaclass.format.constantpool.*;
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolInterfaceMethodReferenceInfo;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolInvokeDynamicInfo;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolMethodReferenceInfo;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolNameAndTypeInfo;
|
|
||||||
import ghidra.javaclass.format.constantpool.ConstantPoolUtf8Info;
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +29,6 @@ import ghidra.program.model.data.*;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public class DescriptorDecoder {
|
public class DescriptorDecoder {
|
||||||
|
|
||||||
public final static byte BASE_TYPE_BYTE = 'B';
|
public final static byte BASE_TYPE_BYTE = 'B';
|
||||||
@@ -53,9 +47,8 @@ public class DescriptorDecoder {
|
|||||||
public final static byte BASE_TYPE_ENUM = 'e';
|
public final static byte BASE_TYPE_ENUM = 'e';
|
||||||
public final static byte BASE_TYPE_ANNOTATION = '@';
|
public final static byte BASE_TYPE_ANNOTATION = '@';
|
||||||
|
|
||||||
|
|
||||||
//private constructor to enforce noninstantiability
|
//private constructor to enforce noninstantiability
|
||||||
private DescriptorDecoder(){
|
private DescriptorDecoder() {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +58,11 @@ public class DescriptorDecoder {
|
|||||||
* @param methodDescriptor
|
* @param methodDescriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static int getStackPurge(String methodDescriptor){
|
public static int getStackPurge(String methodDescriptor) {
|
||||||
int stackPurge = 0;
|
int stackPurge = 0;
|
||||||
List<JavaComputationalCategory> categories = getParameterCategories(methodDescriptor);
|
List<JavaComputationalCategory> categories = getParameterCategories(methodDescriptor);
|
||||||
for (JavaComputationalCategory cat : categories){
|
for (JavaComputationalCategory cat : categories) {
|
||||||
switch (cat){
|
switch (cat) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
stackPurge += PcodeInjectLibraryJava.REFERENCE_SIZE;
|
stackPurge += PcodeInjectLibraryJava.REFERENCE_SIZE;
|
||||||
break;
|
break;
|
||||||
@@ -83,28 +76,38 @@ public class DescriptorDecoder {
|
|||||||
return stackPurge;
|
return stackPurge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the computational category of the return type of a method descriptor.
|
* Returns the computational category of the return type of a method descriptor.
|
||||||
* @param methodDescriptor
|
* @param methodDescriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static JavaComputationalCategory getReturnCategoryOfMethodDescriptor(String methodDescriptor){
|
public static JavaComputationalCategory getReturnCategoryOfMethodDescriptor(
|
||||||
|
String methodDescriptor) {
|
||||||
int closeParenIndex = methodDescriptor.indexOf(")");
|
int closeParenIndex = methodDescriptor.indexOf(")");
|
||||||
if (closeParenIndex == -1){
|
if (closeParenIndex == -1) {
|
||||||
throw new IllegalArgumentException("Invalid method descriptor: " + methodDescriptor);
|
throw new IllegalArgumentException("Invalid method descriptor: " + methodDescriptor);
|
||||||
}
|
}
|
||||||
String returnDescriptor = methodDescriptor.substring(closeParenIndex + 1, methodDescriptor.length());
|
String returnDescriptor =
|
||||||
|
methodDescriptor.substring(closeParenIndex + 1, methodDescriptor.length());
|
||||||
return DescriptorDecoder.getComputationalCategoryOfDescriptor(returnDescriptor);
|
return DescriptorDecoder.getComputationalCategoryOfDescriptor(returnDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataType getReturnTypeOfMethodDescriptor(String methodDescriptor, DataTypeManager dtManager){
|
/**
|
||||||
|
* Given a method descriptor, returns the data type of the return value of the corresponding
|
||||||
|
* method
|
||||||
|
* @param methodDescriptor descriptor of method
|
||||||
|
* @param dtManager data type manger for containing program
|
||||||
|
* @return data type of return value of method
|
||||||
|
*/
|
||||||
|
public static DataType getReturnTypeOfMethodDescriptor(String methodDescriptor,
|
||||||
|
DataTypeManager dtManager) {
|
||||||
int closeParenIndex = methodDescriptor.indexOf(")");
|
int closeParenIndex = methodDescriptor.indexOf(")");
|
||||||
if (closeParenIndex == -1){
|
if (closeParenIndex == -1) {
|
||||||
throw new IllegalArgumentException("Invalid method descriptor: " + methodDescriptor);
|
throw new IllegalArgumentException("Invalid method descriptor: " + methodDescriptor);
|
||||||
}
|
}
|
||||||
String returnDescriptor = methodDescriptor.substring(closeParenIndex + 1, methodDescriptor.length());
|
String returnDescriptor =
|
||||||
if (returnDescriptor.startsWith("[")){
|
methodDescriptor.substring(closeParenIndex + 1, methodDescriptor.length());
|
||||||
|
if (returnDescriptor.startsWith("[")) {
|
||||||
return getPointerType(returnDescriptor, dtManager);
|
return getPointerType(returnDescriptor, dtManager);
|
||||||
}
|
}
|
||||||
return DescriptorDecoder.getDataTypeOfDescriptor(returnDescriptor, dtManager);
|
return DescriptorDecoder.getDataTypeOfDescriptor(returnDescriptor, dtManager);
|
||||||
@@ -115,11 +118,12 @@ public class DescriptorDecoder {
|
|||||||
* @param descriptor
|
* @param descriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static JavaComputationalCategory getComputationalCategoryOfDescriptor(String descriptor){
|
public static JavaComputationalCategory getComputationalCategoryOfDescriptor(
|
||||||
|
String descriptor) {
|
||||||
//all references to objects start with "L"
|
//all references to objects start with "L"
|
||||||
//all references to arrays start with "["
|
//all references to arrays start with "["
|
||||||
//all other descriptors are just one letter.
|
//all other descriptors are just one letter.
|
||||||
switch (descriptor.charAt(0)){
|
switch (descriptor.charAt(0)) {
|
||||||
case BASE_TYPE_BYTE: //signed byte
|
case BASE_TYPE_BYTE: //signed byte
|
||||||
case BASE_TYPE_CHAR: //char
|
case BASE_TYPE_CHAR: //char
|
||||||
case BASE_TYPE_FLOAT: //float
|
case BASE_TYPE_FLOAT: //float
|
||||||
@@ -144,7 +148,8 @@ public class DescriptorDecoder {
|
|||||||
* @param methodDescriptor
|
* @param methodDescriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<String> getTypeNameList(String methodDescriptor, boolean fullyQualifiedName, boolean replaceSlash) {
|
public static List<String> getTypeNameList(String methodDescriptor, boolean fullyQualifiedName,
|
||||||
|
boolean replaceSlash) {
|
||||||
ArrayList<String> typeNames = new ArrayList<>();
|
ArrayList<String> typeNames = new ArrayList<>();
|
||||||
int closeParenIndex = methodDescriptor.indexOf(")");
|
int closeParenIndex = methodDescriptor.indexOf(")");
|
||||||
String argString = methodDescriptor.substring(1, closeParenIndex);
|
String argString = methodDescriptor.substring(1, closeParenIndex);
|
||||||
@@ -152,36 +157,41 @@ public class DescriptorDecoder {
|
|||||||
|
|
||||||
int currentPosition = 0;
|
int currentPosition = 0;
|
||||||
int len = argString.length();
|
int len = argString.length();
|
||||||
while (currentPosition < len){
|
while (currentPosition < len) {
|
||||||
String currentParam = argString.substring(currentPosition, currentPosition + 1);
|
String currentParam = argString.substring(currentPosition, currentPosition + 1);
|
||||||
if (currentParam.equals("[")){
|
if (currentParam.equals("[")) {
|
||||||
int initialBracket = currentPosition;
|
int initialBracket = currentPosition;
|
||||||
while (argString.charAt(currentPosition) == '['){
|
while (argString.charAt(currentPosition) == '[') {
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
}
|
}
|
||||||
//advance past the base type of the array
|
//advance past the base type of the array
|
||||||
if (argString.charAt(currentPosition) == 'L'){
|
if (argString.charAt(currentPosition) == 'L') {
|
||||||
int semiColonIndex = argString.indexOf(";", currentPosition);
|
int semiColonIndex = argString.indexOf(";", currentPosition);
|
||||||
currentPosition = semiColonIndex + 1;
|
currentPosition = semiColonIndex + 1;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
}
|
}
|
||||||
currentParamTypeName = getTypeNameFromDescriptor(argString.substring(initialBracket,currentPosition), fullyQualifiedName, replaceSlash);
|
currentParamTypeName =
|
||||||
|
getTypeNameFromDescriptor(argString.substring(initialBracket, currentPosition),
|
||||||
|
fullyQualifiedName, replaceSlash);
|
||||||
typeNames.add(currentParamTypeName);
|
typeNames.add(currentParamTypeName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//advance to next type in argString
|
//advance to next type in argString
|
||||||
//if it's a reference, it starts with L and ends with a ;
|
//if it's a reference, it starts with L and ends with a ;
|
||||||
//otherwise you only need to advance one character
|
//otherwise you only need to advance one character
|
||||||
switch(currentParam){
|
switch (currentParam) {
|
||||||
case "L":
|
case "L":
|
||||||
int semiColonIndex = argString.indexOf(";", currentPosition);
|
int semiColonIndex = argString.indexOf(";", currentPosition);
|
||||||
currentParamTypeName = getTypeNameFromDescriptor(argString.substring(currentPosition,semiColonIndex+1), fullyQualifiedName, replaceSlash);
|
currentParamTypeName = getTypeNameFromDescriptor(
|
||||||
|
argString.substring(currentPosition, semiColonIndex + 1),
|
||||||
|
fullyQualifiedName, replaceSlash);
|
||||||
currentPosition = semiColonIndex + 1; //advance past ;
|
currentPosition = semiColonIndex + 1; //advance past ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
currentParamTypeName = getTypeNameFromDescriptor(currentParam, fullyQualifiedName, replaceSlash);
|
currentParamTypeName =
|
||||||
|
getTypeNameFromDescriptor(currentParam, fullyQualifiedName, replaceSlash);
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
}
|
}
|
||||||
typeNames.add(currentParamTypeName);
|
typeNames.add(currentParamTypeName);
|
||||||
@@ -189,42 +199,43 @@ public class DescriptorDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//now add the the name of the return type
|
//now add the the name of the return type
|
||||||
String returnType = methodDescriptor.substring(closeParenIndex+1, methodDescriptor.length());
|
String returnType =
|
||||||
|
methodDescriptor.substring(closeParenIndex + 1, methodDescriptor.length());
|
||||||
typeNames.add(getTypeNameFromDescriptor(returnType, fullyQualifiedName, replaceSlash));
|
typeNames.add(getTypeNameFromDescriptor(returnType, fullyQualifiedName, replaceSlash));
|
||||||
return typeNames;
|
return typeNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the type name for a parameter descriptor
|
* Returns the type name for a parameter descriptor
|
||||||
* @param descriptor
|
* @param descriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getTypeNameFromDescriptor(String descriptor, boolean fullyQualifiedName, boolean replaceSlash){
|
public static String getTypeNameFromDescriptor(String descriptor, boolean fullyQualifiedName,
|
||||||
if (descriptor.startsWith("L")){
|
boolean replaceSlash) {
|
||||||
|
if (descriptor.startsWith("L")) {
|
||||||
//leave off the initial L and the final ;
|
//leave off the initial L and the final ;
|
||||||
String name = descriptor.substring(1, descriptor.length()-1);
|
String name = descriptor.substring(1, descriptor.length() - 1);
|
||||||
if (fullyQualifiedName){
|
if (fullyQualifiedName) {
|
||||||
if (replaceSlash){
|
if (replaceSlash) {
|
||||||
return name.replace("/", ".");
|
return name.replace("/", ".");
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
int lastSlash = name.lastIndexOf("/");
|
int lastSlash = name.lastIndexOf("/");
|
||||||
//lastSlash+1 so the slash is not included in the name
|
//lastSlash+1 so the slash is not included in the name
|
||||||
return name.substring(lastSlash+1, name.length());
|
return name.substring(lastSlash + 1, name.length());
|
||||||
}
|
}
|
||||||
if (descriptor.startsWith("[")){
|
if (descriptor.startsWith("[")) {
|
||||||
int dimension = descriptor.lastIndexOf("[") + 1;
|
int dimension = descriptor.lastIndexOf("[") + 1;
|
||||||
String baseType = getTypeNameFromDescriptor(descriptor.replace("[", ""), fullyQualifiedName, replaceSlash);
|
String baseType = getTypeNameFromDescriptor(descriptor.replace("[", ""),
|
||||||
|
fullyQualifiedName, replaceSlash);
|
||||||
StringBuilder sb = new StringBuilder(baseType);
|
StringBuilder sb = new StringBuilder(baseType);
|
||||||
for (int i = 0; i < dimension; ++i){
|
for (int i = 0; i < dimension; ++i) {
|
||||||
sb.append("[]");
|
sb.append("[]");
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
switch (descriptor.charAt(0)){
|
switch (descriptor.charAt(0)) {
|
||||||
case BASE_TYPE_BYTE: //signed byte
|
case BASE_TYPE_BYTE: //signed byte
|
||||||
return "byte";
|
return "byte";
|
||||||
case BASE_TYPE_CHAR: //char
|
case BASE_TYPE_CHAR: //char
|
||||||
@@ -248,17 +259,18 @@ public class DescriptorDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataType getReferenceTypeOfDescriptor(String descriptor, DataTypeManager dtManager, boolean includesLandSemi){
|
public static DataType getReferenceTypeOfDescriptor(String descriptor,
|
||||||
if (includesLandSemi){
|
DataTypeManager dtManager, boolean includesLandSemi) {
|
||||||
descriptor = descriptor.substring(1, descriptor.length()-1);
|
if (includesLandSemi) {
|
||||||
|
descriptor = descriptor.substring(1, descriptor.length() - 1);
|
||||||
}
|
}
|
||||||
String[] parts = descriptor.split("/");
|
String[] parts = descriptor.split("/");
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < parts.length; i++){
|
for (String part : parts) {
|
||||||
sb.append(CategoryPath.DELIMITER_CHAR);
|
sb.append(CategoryPath.DELIMITER_CHAR);
|
||||||
sb.append(parts[i]);
|
sb.append(part);
|
||||||
}
|
}
|
||||||
DataTypePath dataPath = new DataTypePath(sb.toString(), parts[parts.length-1]);
|
DataTypePath dataPath = new DataTypePath(sb.toString(), parts[parts.length - 1]);
|
||||||
DataType referencedType = dtManager.getDataType(dataPath);
|
DataType referencedType = dtManager.getDataType(dataPath);
|
||||||
return new PointerDataType(referencedType);
|
return new PointerDataType(referencedType);
|
||||||
}
|
}
|
||||||
@@ -268,14 +280,14 @@ public class DescriptorDecoder {
|
|||||||
* @param descriptor
|
* @param descriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static DataType getDataTypeOfDescriptor(String descriptor, DataTypeManager dtManager){
|
public static DataType getDataTypeOfDescriptor(String descriptor, DataTypeManager dtManager) {
|
||||||
//all references to objects start with "L"
|
//all references to objects start with "L"
|
||||||
//all references to arrays start with "["
|
//all references to arrays start with "["
|
||||||
//all other descriptors are just one letter.
|
//all other descriptors are just one letter.
|
||||||
if (descriptor.startsWith("[")){
|
if (descriptor.startsWith("[")) {
|
||||||
return getPointerType(descriptor, dtManager);
|
return getPointerType(descriptor, dtManager);
|
||||||
}
|
}
|
||||||
switch (descriptor.charAt(0)){
|
switch (descriptor.charAt(0)) {
|
||||||
case BASE_TYPE_BYTE:
|
case BASE_TYPE_BYTE:
|
||||||
return SignedByteDataType.dataType;
|
return SignedByteDataType.dataType;
|
||||||
case BASE_TYPE_CHAR:
|
case BASE_TYPE_CHAR:
|
||||||
@@ -297,15 +309,21 @@ public class DescriptorDecoder {
|
|||||||
case BASE_TYPE_VOID: //void (only for return types)
|
case BASE_TYPE_VOID: //void (only for return types)
|
||||||
return DataType.VOID;
|
return DataType.VOID;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid computational category: " + descriptor);
|
throw new IllegalArgumentException("Invalid type descriptor: " + descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataType getPointerType(String descriptor, DataTypeManager dtManager){
|
/**
|
||||||
|
* Returns the data type of a pointer to the type represented by descriptor
|
||||||
|
* @param descriptor description of base type
|
||||||
|
* @param dtManager data type manager of program
|
||||||
|
* @return pointer data type
|
||||||
|
*/
|
||||||
|
public static DataType getPointerType(String descriptor, DataTypeManager dtManager) {
|
||||||
int lastBracket = descriptor.lastIndexOf("[");
|
int lastBracket = descriptor.lastIndexOf("[");
|
||||||
String baseTypeOfArray = descriptor.substring(lastBracket+1, lastBracket+2);
|
String baseTypeOfArray = descriptor.substring(lastBracket + 1, lastBracket + 2);
|
||||||
DataType baseType = null;
|
DataType baseType = null;
|
||||||
switch (baseTypeOfArray.charAt(0)){
|
switch (baseTypeOfArray.charAt(0)) {
|
||||||
case BASE_TYPE_BYTE:
|
case BASE_TYPE_BYTE:
|
||||||
baseType = ArrayMethods.getArrayBaseType(JavaClassConstants.T_BYTE, dtManager);
|
baseType = ArrayMethods.getArrayBaseType(JavaClassConstants.T_BYTE, dtManager);
|
||||||
break;
|
break;
|
||||||
@@ -334,7 +352,8 @@ public class DescriptorDecoder {
|
|||||||
return dtManager.getPointer(DWordDataType.dataType);
|
return dtManager.getPointer(DWordDataType.dataType);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Invalid array base type category: " + baseTypeOfArray);
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid array base type category: " + baseTypeOfArray);
|
||||||
}
|
}
|
||||||
return dtManager.getPointer(baseType);
|
return dtManager.getPointer(baseType);
|
||||||
}
|
}
|
||||||
@@ -345,17 +364,18 @@ public class DescriptorDecoder {
|
|||||||
* @param methodDescriptor
|
* @param methodDescriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<JavaComputationalCategory> getParameterCategories(String methodDescriptor){
|
public static List<JavaComputationalCategory> getParameterCategories(String methodDescriptor) {
|
||||||
ArrayList<JavaComputationalCategory> categories = new ArrayList<>();
|
ArrayList<JavaComputationalCategory> categories = new ArrayList<>();
|
||||||
int closeParenIndex = methodDescriptor.indexOf(")");
|
int closeParenIndex = methodDescriptor.indexOf(")");
|
||||||
String argString = methodDescriptor.substring(1, closeParenIndex);
|
String argString = methodDescriptor.substring(1, closeParenIndex);
|
||||||
int currentPosition = 0;
|
int currentPosition = 0;
|
||||||
int len = argString.length();
|
int len = argString.length();
|
||||||
while (currentPosition < len){
|
while (currentPosition < len) {
|
||||||
String currentParam = argString.substring(currentPosition, currentPosition + 1);
|
String currentParam = argString.substring(currentPosition, currentPosition + 1);
|
||||||
JavaComputationalCategory category = DescriptorDecoder.getComputationalCategoryOfDescriptor(currentParam);
|
JavaComputationalCategory category =
|
||||||
|
DescriptorDecoder.getComputationalCategoryOfDescriptor(currentParam);
|
||||||
|
|
||||||
switch (category){
|
switch (category) {
|
||||||
case CAT_1:
|
case CAT_1:
|
||||||
categories.add(JavaComputationalCategory.CAT_1);
|
categories.add(JavaComputationalCategory.CAT_1);
|
||||||
break;
|
break;
|
||||||
@@ -370,22 +390,22 @@ public class DescriptorDecoder {
|
|||||||
//if it's a reference, it starts with L and ends with a ;
|
//if it's a reference, it starts with L and ends with a ;
|
||||||
//if it's an array, it has one "[" for each dimension, then the type (which might be a reference)
|
//if it's an array, it has one "[" for each dimension, then the type (which might be a reference)
|
||||||
//otherwise you only need to advance one character
|
//otherwise you only need to advance one character
|
||||||
switch(currentParam){
|
switch (currentParam) {
|
||||||
case "L":
|
case "L":
|
||||||
int semiColonIndex = argString.indexOf(";", currentPosition);
|
int semiColonIndex = argString.indexOf(";", currentPosition);
|
||||||
currentPosition = semiColonIndex + 1; //advance past ;
|
currentPosition = semiColonIndex + 1; //advance past ;
|
||||||
break;
|
break;
|
||||||
case "[":
|
case "[":
|
||||||
//advance past all the ['s
|
//advance past all the ['s
|
||||||
while (argString.charAt(currentPosition) == '['){
|
while (argString.charAt(currentPosition) == '[') {
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
}
|
}
|
||||||
//advance past the base type of the array
|
//advance past the base type of the array
|
||||||
if (argString.charAt(currentPosition) == 'L'){
|
if (argString.charAt(currentPosition) == 'L') {
|
||||||
semiColonIndex = argString.indexOf(";", currentPosition);
|
semiColonIndex = argString.indexOf(";", currentPosition);
|
||||||
currentPosition = semiColonIndex + 1;
|
currentPosition = semiColonIndex + 1;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -402,7 +422,8 @@ public class DescriptorDecoder {
|
|||||||
* @param methodDescriptor
|
* @param methodDescriptor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<DataType> getDataTypeList(String methodDescriptor, DataTypeManager dtManager) {
|
public static List<DataType> getDataTypeList(String methodDescriptor,
|
||||||
|
DataTypeManager dtManager) {
|
||||||
ArrayList<DataType> paramDataTypes = new ArrayList<>();
|
ArrayList<DataType> paramDataTypes = new ArrayList<>();
|
||||||
int closeParenIndex = methodDescriptor.indexOf(")");
|
int closeParenIndex = methodDescriptor.indexOf(")");
|
||||||
String argString = methodDescriptor.substring(1, closeParenIndex);
|
String argString = methodDescriptor.substring(1, closeParenIndex);
|
||||||
@@ -411,14 +432,14 @@ public class DescriptorDecoder {
|
|||||||
int currentPosition = 0;
|
int currentPosition = 0;
|
||||||
int len = argString.length();
|
int len = argString.length();
|
||||||
String currentParam = null;
|
String currentParam = null;
|
||||||
while (currentPosition < len){
|
while (currentPosition < len) {
|
||||||
int arrayDimensions = 0;
|
int arrayDimensions = 0;
|
||||||
//if it's an array, decode the number of dimensions
|
//if it's an array, decode the number of dimensions
|
||||||
while (argString.charAt(currentPosition) == '['){
|
while (argString.charAt(currentPosition) == '[') {
|
||||||
arrayDimensions++;
|
arrayDimensions++;
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
}
|
}
|
||||||
switch (argString.charAt(currentPosition)){
|
switch (argString.charAt(currentPosition)) {
|
||||||
case BASE_TYPE_BYTE:
|
case BASE_TYPE_BYTE:
|
||||||
case BASE_TYPE_CHAR:
|
case BASE_TYPE_CHAR:
|
||||||
case BASE_TYPE_SHORT:
|
case BASE_TYPE_SHORT:
|
||||||
@@ -427,17 +448,17 @@ public class DescriptorDecoder {
|
|||||||
case BASE_TYPE_FLOAT:
|
case BASE_TYPE_FLOAT:
|
||||||
case BASE_TYPE_DOUBLE:
|
case BASE_TYPE_DOUBLE:
|
||||||
case BASE_TYPE_BOOLEAN:
|
case BASE_TYPE_BOOLEAN:
|
||||||
currentParam = argString.substring(currentPosition, currentPosition+1);
|
currentParam = argString.substring(currentPosition, currentPosition + 1);
|
||||||
currentPosition++;
|
currentPosition++;
|
||||||
break;
|
break;
|
||||||
case BASE_TYPE_REFERENCE:
|
case BASE_TYPE_REFERENCE:
|
||||||
int semiColonIndex = argString.indexOf(";", currentPosition);
|
int semiColonIndex = argString.indexOf(";", currentPosition);
|
||||||
currentParam = argString.substring(currentPosition, semiColonIndex+1);
|
currentParam = argString.substring(currentPosition, semiColonIndex + 1);
|
||||||
currentPosition = semiColonIndex + 1;
|
currentPosition = semiColonIndex + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
currentParamType = getDataTypeOfDescriptor(currentParam, dtManager);
|
currentParamType = getDataTypeOfDescriptor(currentParam, dtManager);
|
||||||
if (arrayDimensions > 0){
|
if (arrayDimensions > 0) {
|
||||||
paramDataTypes.add(dtManager.getPointer(currentParamType));
|
paramDataTypes.add(dtManager.getPointer(currentParamType));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -455,47 +476,91 @@ public class DescriptorDecoder {
|
|||||||
* @param type
|
* @param type
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getDescriptorForInvoke(int offset, AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type){
|
public static String getDescriptorForInvoke(int offset,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool, JavaInvocationType type) {
|
||||||
String descriptor = null;
|
String descriptor = null;
|
||||||
int name_and_type_index = 0;
|
int name_and_type_index = 0;
|
||||||
switch (type){
|
switch (type) {
|
||||||
case INVOKE_DYNAMIC:
|
case INVOKE_DYNAMIC:
|
||||||
ConstantPoolInvokeDynamicInfo dynamicInfo = (ConstantPoolInvokeDynamicInfo) constantPool[offset];
|
ConstantPoolInvokeDynamicInfo dynamicInfo =
|
||||||
|
(ConstantPoolInvokeDynamicInfo) constantPool[offset];
|
||||||
name_and_type_index = dynamicInfo.getNameAndTypeIndex();
|
name_and_type_index = dynamicInfo.getNameAndTypeIndex();
|
||||||
break;
|
break;
|
||||||
case INVOKE_INTERFACE:
|
case INVOKE_INTERFACE:
|
||||||
ConstantPoolInterfaceMethodReferenceInfo interfaceInfo = (ConstantPoolInterfaceMethodReferenceInfo) constantPool[offset];
|
ConstantPoolInterfaceMethodReferenceInfo interfaceInfo =
|
||||||
|
(ConstantPoolInterfaceMethodReferenceInfo) constantPool[offset];
|
||||||
name_and_type_index = interfaceInfo.getNameAndTypeIndex();
|
name_and_type_index = interfaceInfo.getNameAndTypeIndex();
|
||||||
break;
|
break;
|
||||||
case INVOKE_SPECIAL:
|
|
||||||
case INVOKE_STATIC:
|
case INVOKE_STATIC:
|
||||||
|
AbstractConstantPoolInfoJava poolElem = constantPool[offset];
|
||||||
|
if (poolElem instanceof ConstantPoolInterfaceMethodReferenceInfo) {
|
||||||
|
interfaceInfo = (ConstantPoolInterfaceMethodReferenceInfo) constantPool[offset];
|
||||||
|
name_and_type_index = interfaceInfo.getNameAndTypeIndex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (poolElem instanceof ConstantPoolMethodReferenceInfo) {
|
||||||
|
ConstantPoolMethodReferenceInfo methodReferenceInfo =
|
||||||
|
(ConstantPoolMethodReferenceInfo) constantPool[offset];
|
||||||
|
name_and_type_index = methodReferenceInfo.getNameAndTypeIndex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unsupported type for invokestatic at constant pool element " + offset);
|
||||||
|
case INVOKE_SPECIAL:
|
||||||
case INVOKE_VIRTUAL:
|
case INVOKE_VIRTUAL:
|
||||||
ConstantPoolMethodReferenceInfo methodReferenceInfo = (ConstantPoolMethodReferenceInfo) constantPool[offset];
|
ConstantPoolMethodReferenceInfo methodReferenceInfo =
|
||||||
|
(ConstantPoolMethodReferenceInfo) constantPool[offset];
|
||||||
name_and_type_index = methodReferenceInfo.getNameAndTypeIndex();
|
name_and_type_index = methodReferenceInfo.getNameAndTypeIndex();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("unimplemented method type: " + type.name());
|
throw new IllegalArgumentException("unimplemented method type: " + type.name());
|
||||||
}
|
}
|
||||||
ConstantPoolNameAndTypeInfo methodNameAndType = (ConstantPoolNameAndTypeInfo) constantPool[name_and_type_index];
|
ConstantPoolNameAndTypeInfo methodNameAndType =
|
||||||
|
(ConstantPoolNameAndTypeInfo) constantPool[name_and_type_index];
|
||||||
int descriptor_index = methodNameAndType.getDescriptorIndex();
|
int descriptor_index = methodNameAndType.getDescriptorIndex();
|
||||||
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
ConstantPoolUtf8Info descriptorInfo = (ConstantPoolUtf8Info) constantPool[descriptor_index];
|
||||||
descriptor = descriptorInfo.getString();
|
descriptor = descriptorInfo.getString();
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static String decodeType(ConstantPoolUtf8Info utf,
|
/**
|
||||||
boolean useFullyQualifiedClassName) {
|
* Resolves the datatype represented by {@code fullyQualifiedName} with a base type of
|
||||||
return DescriptorDecoder.getTypeNameFromDescriptor(utf.getString(), useFullyQualifiedClassName, true);
|
* {@code baseType} into dtm
|
||||||
}
|
* @param fullyQualifiedName String representation of type
|
||||||
|
* @param dtm data type manager
|
||||||
//no L, no ;
|
* @param baseType base type
|
||||||
public static DataType resolveClassForString(String fullyQualifiedName, DataTypeManager dtm, DataType baseType){
|
* @return data type represented by input string
|
||||||
|
*/
|
||||||
|
public static DataType resolveClassForString(String fullyQualifiedName, DataTypeManager dtm,
|
||||||
|
DataType baseType) {
|
||||||
fullyQualifiedName = CategoryPath.DELIMITER_CHAR + fullyQualifiedName;
|
fullyQualifiedName = CategoryPath.DELIMITER_CHAR + fullyQualifiedName;
|
||||||
CategoryPath catPath = new CategoryPath(fullyQualifiedName);
|
CategoryPath catPath = new CategoryPath(fullyQualifiedName);
|
||||||
String[] parts = catPath.getPathElements();
|
String[] parts = catPath.getPathElements();
|
||||||
DataType dataType = new TypedefDataType(catPath,parts[parts.length-1],baseType);
|
DataType dataType = new TypedefDataType(catPath, parts[parts.length - 1], baseType);
|
||||||
dtm.resolve(dataType, DataTypeConflictHandler.KEEP_HANDLER);
|
dtm.resolve(dataType, DataTypeConflictHandler.KEEP_HANDLER);
|
||||||
return dataType;
|
return dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a String representing the types of the parameters of a method, e.g.
|
||||||
|
* (java.lang.String, java.lang.Integer) for a method with signature
|
||||||
|
* public static void test(String x, Integer y);
|
||||||
|
* @param descriptor method descriptor
|
||||||
|
* @return string representation of types of method parameters
|
||||||
|
*/
|
||||||
|
public static String getParameterString(String descriptor) {
|
||||||
|
List<String> paramTypeNames = getTypeNameList(descriptor, true, true);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("(");
|
||||||
|
//don't append the last element of the list, which is the return type
|
||||||
|
for (int i = 0, max = paramTypeNames.size() - 1; i < max; ++i) {
|
||||||
|
sb.append(paramTypeNames.get(i));
|
||||||
|
if (i < max - 1) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(")");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format;
|
package ghidra.javaclass.format;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.javaclass.format.attributes.*;
|
import ghidra.javaclass.format.attributes.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -48,18 +48,18 @@ public class FieldInfoJava implements StructConverter {
|
|||||||
private short nameIndex;
|
private short nameIndex;
|
||||||
private short descriptorIndex;
|
private short descriptorIndex;
|
||||||
private short attributesCount;
|
private short attributesCount;
|
||||||
private AbstractAttributeInfo [] attributes;
|
private AbstractAttributeInfo[] attributes;
|
||||||
|
|
||||||
public FieldInfoJava( BinaryReader reader, ClassFileJava classFile ) throws IOException {
|
public FieldInfoJava(BinaryReader reader, ClassFileJava classFile) throws IOException {
|
||||||
_offset = reader.getPointerIndex();
|
_offset = reader.getPointerIndex();
|
||||||
|
|
||||||
accessFlags = reader.readNextShort();
|
accessFlags = reader.readNextShort();
|
||||||
nameIndex = reader.readNextShort();
|
nameIndex = reader.readNextShort();
|
||||||
descriptorIndex = reader.readNextShort();
|
descriptorIndex = reader.readNextShort();
|
||||||
attributesCount = reader.readNextShort();
|
attributesCount = reader.readNextShort();
|
||||||
attributes = new AbstractAttributeInfo[ attributesCount ];
|
attributes = new AbstractAttributeInfo[getAttributesCount()];
|
||||||
for ( int i = 0 ; i < attributesCount ; i++ ) {
|
for (int i = 0; i < getAttributesCount(); i++) {
|
||||||
attributes[ i ] = AttributeFactory.get( reader, classFile.getConstantPool() );
|
attributes[i] = AttributeFactory.get(reader, classFile.getConstantPool());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +84,8 @@ public class FieldInfoJava implements StructConverter {
|
|||||||
* unqualified name denoting a field.
|
* unqualified name denoting a field.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getNameIndex() {
|
public int getNameIndex() {
|
||||||
return nameIndex;
|
return nameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,8 +95,8 @@ public class FieldInfoJava implements StructConverter {
|
|||||||
* descriptor.
|
* descriptor.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getDescriptorIndex() {
|
public int getDescriptorIndex() {
|
||||||
return descriptorIndex;
|
return descriptorIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,8 +104,8 @@ public class FieldInfoJava implements StructConverter {
|
|||||||
* attributes of this field.
|
* attributes of this field.
|
||||||
* @return the number of additional attributes
|
* @return the number of additional attributes
|
||||||
*/
|
*/
|
||||||
public short getAttributesCount() {
|
public int getAttributesCount() {
|
||||||
return attributesCount;
|
return attributesCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,13 +137,13 @@ public class FieldInfoJava implements StructConverter {
|
|||||||
* information.
|
* information.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public AbstractAttributeInfo [] getAttributes() {
|
public AbstractAttributeInfo[] getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConstantValueAttribute getConstantValueAttribute() {
|
public ConstantValueAttribute getConstantValueAttribute() {
|
||||||
for ( AbstractAttributeInfo attributeInfo : attributes ) {
|
for (AbstractAttributeInfo attributeInfo : attributes) {
|
||||||
if ( attributeInfo instanceof ConstantValueAttribute ) {
|
if (attributeInfo instanceof ConstantValueAttribute) {
|
||||||
return (ConstantValueAttribute) attributeInfo;
|
return (ConstantValueAttribute) attributeInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,15 +154,15 @@ public class FieldInfoJava implements StructConverter {
|
|||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = "field_info" + "|" + attributesCount + "|";
|
String name = "field_info" + "|" + attributesCount + "|";
|
||||||
|
|
||||||
Structure structure = new StructureDataType( name, 0 );
|
Structure structure = new StructureDataType(name, 0);
|
||||||
|
|
||||||
structure.add( WORD, "access_flags", null );
|
structure.add(WORD, "access_flags", null);
|
||||||
structure.add( WORD, "name_index", null );
|
structure.add(WORD, "name_index", null);
|
||||||
structure.add( WORD, "descriptor_index", null );
|
structure.add(WORD, "descriptor_index", null);
|
||||||
structure.add( WORD, "attributes_count", null );
|
structure.add(WORD, "attributes_count", null);
|
||||||
|
|
||||||
for ( int i = 0 ; i < attributes.length ; ++i ) {
|
for (int i = 0; i < attributes.length; ++i) {
|
||||||
structure.add( attributes[ i ].toDataType(), "attributes_" + i, null );
|
structure.add(attributes[i].toDataType(), "attributes_" + i, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return structure;
|
return structure;
|
||||||
|
|||||||
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format;
|
package ghidra.javaclass.format;
|
||||||
|
|
||||||
import ghidra.framework.options.Options;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import ghidra.app.util.opinion.JavaLoader;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class JavaClassUtil {
|
public class JavaClassUtil {
|
||||||
|
|
||||||
public final static long LOOKUP_ADDRESS = 0xE0000000L;
|
public final static long LOOKUP_ADDRESS = 0xE0000000L;
|
||||||
@@ -29,28 +29,24 @@ public class JavaClassUtil {
|
|||||||
public static final long METHOD_INDEX_SIZE = 65536 * 4;
|
public static final long METHOD_INDEX_SIZE = 65536 * 4;
|
||||||
|
|
||||||
public final static boolean isClassFile(Program program) {
|
public final static boolean isClassFile(Program program) {
|
||||||
Options options = program.getOptions(Program.PROGRAM_INFO);
|
|
||||||
String firmwarePath = options.getString("Firmware Path", "");
|
|
||||||
|
|
||||||
if (program.getExecutablePath().toLowerCase().endsWith(".class") ||
|
|
||||||
firmwarePath.toLowerCase().endsWith(".class")) {
|
|
||||||
byte[] bytes = new byte[4];
|
byte[] bytes = new byte[4];
|
||||||
try {
|
try {
|
||||||
Address address = program.getAddressFactory().getAddressSpace("constantPool").getMinAddress();
|
Address address = program.getAddressFactory().getAddressSpace(
|
||||||
|
JavaLoader.CONSTANT_POOL).getMinAddress();
|
||||||
program.getMemory().getBytes(address, bytes);
|
program.getMemory().getBytes(address, bytes);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Msg.info(JavaClassUtil.class, e.getLocalizedMessage());
|
Msg.info(JavaClassUtil.class, e.getLocalizedMessage());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return Arrays.equals(bytes, JavaClassConstants.MAGIC_BYTES);
|
return Arrays.equals(bytes, JavaClassConstants.MAGIC_BYTES);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Address toLookupAddress( Program program, int methodIndex ) {
|
public static Address toLookupAddress(Program program, int methodIndex) {
|
||||||
AddressFactory addressFactory = program.getAddressFactory( );
|
AddressFactory addressFactory = program.getAddressFactory();
|
||||||
AddressSpace defaultAddressSpace = addressFactory.getDefaultAddressSpace( );
|
AddressSpace defaultAddressSpace = addressFactory.getDefaultAddressSpace();
|
||||||
return defaultAddressSpace.getAddress( JavaClassUtil.LOOKUP_ADDRESS + ( methodIndex * 4 ) );
|
return defaultAddressSpace.getAddress(JavaClassUtil.LOOKUP_ADDRESS + (methodIndex * 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format;
|
package ghidra.javaclass.format;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
|
import ghidra.javaclass.flags.MethodsInfoAccessFlags;
|
||||||
import ghidra.javaclass.format.attributes.*;
|
import ghidra.javaclass.format.attributes.*;
|
||||||
import ghidra.javaclass.format.constantpool.*;
|
import ghidra.javaclass.format.constantpool.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each method, including each instance initialization method (2.9) and the class or
|
* Each method, including each instance initialization method (2.9) and the class or
|
||||||
* interface initialization method (2.9), is described by a method_info structure. No
|
* interface initialization method (2.9), is described by a method_info structure. No
|
||||||
@@ -58,8 +59,8 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
nameIndex = reader.readNextShort();
|
nameIndex = reader.readNextShort();
|
||||||
descriptorIndex = reader.readNextShort();
|
descriptorIndex = reader.readNextShort();
|
||||||
attributesCount = reader.readNextShort();
|
attributesCount = reader.readNextShort();
|
||||||
attributes = new AbstractAttributeInfo[attributesCount];
|
attributes = new AbstractAttributeInfo[getAttributesCount()];
|
||||||
for (int i = 0; i < attributesCount; i++) {
|
for (int i = 0; i < getAttributesCount(); i++) {
|
||||||
attributes[i] = AttributeFactory.get(reader, classFile.getConstantPool());
|
attributes[i] = AttributeFactory.get(reader, classFile.getConstantPool());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,8 +87,9 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
*
|
*
|
||||||
* @return boolean encoding whether the method is static
|
* @return boolean encoding whether the method is static
|
||||||
*/
|
*/
|
||||||
public boolean isStatic(){
|
public boolean isStatic() {
|
||||||
return AccessFlagsJava.isStatic(accessFlags);
|
return (MethodsInfoAccessFlags.ACC_STATIC.getValue() &
|
||||||
|
accessFlags) == MethodsInfoAccessFlags.ACC_STATIC.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,8 +100,8 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
* denoting a method.
|
* denoting a method.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getNameIndex() {
|
public int getNameIndex() {
|
||||||
return nameIndex;
|
return nameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,8 +110,8 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
* CONSTANT_Utf8_info structure representing a valid method descriptor.
|
* CONSTANT_Utf8_info structure representing a valid method descriptor.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getDescriptorIndex() {
|
public int getDescriptorIndex() {
|
||||||
return descriptorIndex;
|
return descriptorIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,8 +119,8 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
* attributes of this method.
|
* attributes of this method.
|
||||||
* @return the number of additional attributes of this method
|
* @return the number of additional attributes of this method
|
||||||
*/
|
*/
|
||||||
public short getAttributesCount() {
|
public int getAttributesCount() {
|
||||||
return attributesCount;
|
return attributesCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,11 +180,13 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
ConstantPoolUtf8Info methodDescriptor =
|
ConstantPoolUtf8Info methodDescriptor =
|
||||||
(ConstantPoolUtf8Info) constantPool[descriptorIndex];
|
(ConstantPoolUtf8Info) constantPool[descriptorIndex];
|
||||||
StringBuffer stringBuffer = new StringBuffer();
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
stringBuffer.append(AccessFlagsJava.toString(accessFlags, false).trim());
|
stringBuffer.append(MethodsInfoAccessFlags.toString(accessFlags));
|
||||||
|
|
||||||
if (!methodName.getString().equals("<clinit>")) {
|
if (methodName.getString().equals("<clinit>")) {
|
||||||
|
stringBuffer.append(" (class initializer)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
stringBuffer.append(' ');
|
stringBuffer.append(' ');
|
||||||
|
|
||||||
if (methodName.getString().equals("<init>")) {//replace constructors with name of this class
|
if (methodName.getString().equals("<init>")) {//replace constructors with name of this class
|
||||||
ConstantPoolClassInfo thisClass =
|
ConstantPoolClassInfo thisClass =
|
||||||
(ConstantPoolClassInfo) constantPool[classFile.getThisClass()];
|
(ConstantPoolClassInfo) constantPool[classFile.getThisClass()];
|
||||||
@@ -205,13 +209,12 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
stringBuffer.append(methodName.getString());
|
stringBuffer.append(methodName.getString());
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuffer.append('(');
|
|
||||||
|
|
||||||
CodeAttribute codeAttribute = getCodeAttribute();
|
CodeAttribute codeAttribute = getCodeAttribute();
|
||||||
if (codeAttribute != null) {
|
if (codeAttribute != null) {
|
||||||
LocalVariableTableAttribute localVariableTable =
|
LocalVariableTableAttribute localVariableTable =
|
||||||
codeAttribute.getLocalVariableTableAttribute();
|
codeAttribute.getLocalVariableTableAttribute();
|
||||||
if (localVariableTable != null) {
|
if (localVariableTable != null) {
|
||||||
|
stringBuffer.append('(');
|
||||||
LocalVariableJava[] localVariables = localVariableTable.getLocalVariables();
|
LocalVariableJava[] localVariables = localVariableTable.getLocalVariables();
|
||||||
int startIndex = getParametersStartIndex();
|
int startIndex = getParametersStartIndex();
|
||||||
for (int i = startIndex; i < localVariables.length; ++i) {
|
for (int i = startIndex; i < localVariables.length; ++i) {
|
||||||
@@ -224,22 +227,28 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
ConstantPoolUtf8Info parameterDescriptor =
|
ConstantPoolUtf8Info parameterDescriptor =
|
||||||
(ConstantPoolUtf8Info) constantPool[localVariables[i].getDescriptorIndex()];
|
(ConstantPoolUtf8Info) constantPool[localVariables[i].getDescriptorIndex()];
|
||||||
|
|
||||||
stringBuffer.append(DescriptorDecoder.decodeType(parameterDescriptor,
|
stringBuffer.append(DescriptorDecoder.getTypeNameFromDescriptor(
|
||||||
false));
|
parameterDescriptor.getString(), false, true));
|
||||||
stringBuffer.append(" ");
|
stringBuffer.append(" ");
|
||||||
stringBuffer.append(parameterName);
|
stringBuffer.append(parameterName);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stringBuffer.append(')');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stringBuffer.append(
|
||||||
|
DescriptorDecoder.getParameterString(methodDescriptor.getString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stringBuffer.append(')');
|
|
||||||
ExceptionsAttribute exceptionsAttribute = getExceptionsAttribute();
|
ExceptionsAttribute exceptionsAttribute = getExceptionsAttribute();
|
||||||
if (exceptionsAttribute != null) {
|
if (exceptionsAttribute != null) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (short s : exceptionsAttribute.getExceptionIndexTable()) {
|
for (int k = 0; k < exceptionsAttribute.getNumberOfExceptions(); k++) {
|
||||||
ConstantPoolClassInfo exceptionClass = (ConstantPoolClassInfo) constantPool[s];
|
ConstantPoolClassInfo exceptionClass =
|
||||||
|
(ConstantPoolClassInfo) constantPool[exceptionsAttribute.getExceptionIndexTableEntry(
|
||||||
|
k)];
|
||||||
ConstantPoolUtf8Info exceptionClassName =
|
ConstantPoolUtf8Info exceptionClassName =
|
||||||
(ConstantPoolUtf8Info) constantPool[exceptionClass.getNameIndex()];
|
(ConstantPoolUtf8Info) constantPool[exceptionClass.getNameIndex()];
|
||||||
String className = exceptionClassName.getString();
|
String className = exceptionClassName.getString();
|
||||||
@@ -265,7 +274,7 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
* otherwise skip index 0 because it contains the 'this' parameter.
|
* otherwise skip index 0 because it contains the 'this' parameter.
|
||||||
*/
|
*/
|
||||||
private int getParametersStartIndex() {
|
private int getParametersStartIndex() {
|
||||||
return AccessFlagsJava.isStatic(accessFlags) ? 0 : 1;
|
return isStatic() ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,7 +308,8 @@ public class MethodInfoJava implements StructConverter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = "method_info" + "|" + nameIndex + "|" + descriptorIndex + "|" + attributesCount + "|";
|
String name =
|
||||||
|
"method_info" + "|" + nameIndex + "|" + descriptorIndex + "|" + attributesCount + "|";
|
||||||
|
|
||||||
Structure structure = new StructureDataType(name, 0);
|
Structure structure = new StructureDataType(name, 0);
|
||||||
|
|
||||||
|
|||||||
+9
-10
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,12 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -94,7 +93,7 @@ public abstract class AbstractAttributeInfo implements StructConverter {
|
|||||||
private short attributeNameIndex;
|
private short attributeNameIndex;
|
||||||
private int attributeLength;
|
private int attributeLength;
|
||||||
|
|
||||||
protected AbstractAttributeInfo( BinaryReader reader ) throws IOException {
|
protected AbstractAttributeInfo(BinaryReader reader) throws IOException {
|
||||||
_offset = reader.getPointerIndex();
|
_offset = reader.getPointerIndex();
|
||||||
|
|
||||||
attributeNameIndex = reader.readNextShort();
|
attributeNameIndex = reader.readNextShort();
|
||||||
@@ -112,8 +111,8 @@ public abstract class AbstractAttributeInfo implements StructConverter {
|
|||||||
* @see AttributesConstants
|
* @see AttributesConstants
|
||||||
* @return the attribute_name_index
|
* @return the attribute_name_index
|
||||||
*/
|
*/
|
||||||
public short getAttributeNameIndex() {
|
public int getAttributeNameIndex() {
|
||||||
return attributeNameIndex;
|
return attributeNameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,10 +126,10 @@ public abstract class AbstractAttributeInfo implements StructConverter {
|
|||||||
return attributeLength;
|
return attributeLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected StructureDataType getBaseStructure( String name ) {
|
protected StructureDataType getBaseStructure(String name) {
|
||||||
StructureDataType structure = new StructureDataType( name + "|" + attributeLength + "|", 0 );
|
StructureDataType structure = new StructureDataType(name + "|" + attributeLength + "|", 0);
|
||||||
structure.add( WORD, "attribute_name_index", null );
|
structure.add(WORD, "attribute_name_index", null);
|
||||||
structure.add( DWORD, "attribute_length" , null );
|
structure.add(DWORD, "attribute_length", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-43
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.javaclass.format.DescriptorDecoder;
|
import ghidra.javaclass.format.DescriptorDecoder;
|
||||||
@@ -22,8 +24,6 @@ import ghidra.program.model.data.DataType;
|
|||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -69,38 +69,35 @@ public class AnnotationElementValue implements StructConverter {
|
|||||||
private AnnotationJava annotation;
|
private AnnotationJava annotation;
|
||||||
|
|
||||||
private short numberOfValues;
|
private short numberOfValues;
|
||||||
private AnnotationElementValue [] values;
|
private AnnotationElementValue[] values;
|
||||||
|
|
||||||
public AnnotationElementValue( BinaryReader reader ) throws IOException {
|
public AnnotationElementValue(BinaryReader reader) throws IOException {
|
||||||
tag = reader.readNextByte();
|
tag = reader.readNextByte();
|
||||||
|
|
||||||
if ( tag == DescriptorDecoder.BASE_TYPE_BYTE ||
|
if (tag == DescriptorDecoder.BASE_TYPE_BYTE || tag == DescriptorDecoder.BASE_TYPE_CHAR ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_CHAR ||
|
tag == DescriptorDecoder.BASE_TYPE_INT || tag == DescriptorDecoder.BASE_TYPE_SHORT ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_INT ||
|
tag == DescriptorDecoder.BASE_TYPE_LONG || tag == DescriptorDecoder.BASE_TYPE_FLOAT ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_SHORT ||
|
|
||||||
tag == DescriptorDecoder.BASE_TYPE_LONG ||
|
|
||||||
tag == DescriptorDecoder.BASE_TYPE_FLOAT ||
|
|
||||||
tag == DescriptorDecoder.BASE_TYPE_DOUBLE ||
|
tag == DescriptorDecoder.BASE_TYPE_DOUBLE ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_BOOLEAN ||
|
tag == DescriptorDecoder.BASE_TYPE_BOOLEAN ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_STRING ) {
|
tag == DescriptorDecoder.BASE_TYPE_STRING) {
|
||||||
|
|
||||||
constantValueIndex = reader.readNextShort();
|
constantValueIndex = reader.readNextShort();
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_ENUM ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_ENUM) {
|
||||||
typeNameIndex = reader.readNextShort();
|
typeNameIndex = reader.readNextShort();
|
||||||
constantNameIndex = reader.readNextShort();
|
constantNameIndex = reader.readNextShort();
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_CLASS ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_CLASS) {
|
||||||
classInfoIndex = reader.readNextShort();
|
classInfoIndex = reader.readNextShort();
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_ANNOTATION ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_ANNOTATION) {
|
||||||
annotation = new AnnotationJava( reader );
|
annotation = new AnnotationJava(reader);
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_ARRAY ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_ARRAY) {
|
||||||
numberOfValues = reader.readNextShort();
|
numberOfValues = reader.readNextShort();
|
||||||
values = new AnnotationElementValue[ numberOfValues ];
|
values = new AnnotationElementValue[numberOfValues & 0xffff];
|
||||||
for ( int i = 0 ; i < numberOfValues ; ++i ) {
|
for (int i = 0; i < (numberOfValues & 0xffff); ++i) {
|
||||||
values[ i ] = new AnnotationElementValue( reader );
|
values[i] = new AnnotationElementValue(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,8 +135,8 @@ public class AnnotationElementValue implements StructConverter {
|
|||||||
* for the field type designated by the tag item, as specified in Table 4.24.
|
* for the field type designated by the tag item, as specified in Table 4.24.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getConstantValueIndex() {
|
public int getConstantValueIndex() {
|
||||||
return constantValueIndex;
|
return constantValueIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,11 +148,11 @@ public class AnnotationElementValue implements StructConverter {
|
|||||||
* element_value structure.
|
* element_value structure.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getTypeNameIndex() {
|
public int getTypeNameIndex() {
|
||||||
if ( tag != DescriptorDecoder.BASE_TYPE_ENUM ) {
|
if (tag != DescriptorDecoder.BASE_TYPE_ENUM) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
return typeNameIndex;
|
return typeNameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,11 +163,11 @@ public class AnnotationElementValue implements StructConverter {
|
|||||||
* structure.
|
* structure.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getConstantNameIndex() {
|
public int getConstantNameIndex() {
|
||||||
if ( tag != DescriptorDecoder.BASE_TYPE_ENUM ) {
|
if (tag != DescriptorDecoder.BASE_TYPE_ENUM) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
return constantNameIndex;
|
return constantNameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -183,8 +180,8 @@ public class AnnotationElementValue implements StructConverter {
|
|||||||
* For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc.
|
* For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getClassInfoIndex() {
|
public int getClassInfoIndex() {
|
||||||
return classInfoIndex;
|
return classInfoIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,32 +203,29 @@ public class AnnotationElementValue implements StructConverter {
|
|||||||
* array-typed value represented by this element_value structure.
|
* array-typed value represented by this element_value structure.
|
||||||
* @return nested element value table
|
* @return nested element value table
|
||||||
*/
|
*/
|
||||||
public AnnotationElementValue [] getValues() {
|
public AnnotationElementValue[] getValues() {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = "element_value" +"|" + tag + "|";
|
String name = "element_value" + "|" + tag + "|";
|
||||||
StructureDataType structure = new StructureDataType( name, 0 );
|
StructureDataType structure = new StructureDataType(name, 0);
|
||||||
|
|
||||||
if ( tag == DescriptorDecoder.BASE_TYPE_BYTE ||
|
if (tag == DescriptorDecoder.BASE_TYPE_BYTE || tag == DescriptorDecoder.BASE_TYPE_CHAR ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_CHAR ||
|
tag == DescriptorDecoder.BASE_TYPE_INT || tag == DescriptorDecoder.BASE_TYPE_SHORT ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_INT ||
|
tag == DescriptorDecoder.BASE_TYPE_LONG || tag == DescriptorDecoder.BASE_TYPE_FLOAT ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_SHORT ||
|
|
||||||
tag == DescriptorDecoder.BASE_TYPE_LONG ||
|
|
||||||
tag == DescriptorDecoder.BASE_TYPE_FLOAT ||
|
|
||||||
tag == DescriptorDecoder.BASE_TYPE_DOUBLE ||
|
tag == DescriptorDecoder.BASE_TYPE_DOUBLE ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_BOOLEAN ||
|
tag == DescriptorDecoder.BASE_TYPE_BOOLEAN ||
|
||||||
tag == DescriptorDecoder.BASE_TYPE_STRING ) {
|
tag == DescriptorDecoder.BASE_TYPE_STRING) {
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_ENUM ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_ENUM) {
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_CLASS ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_CLASS) {
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_ANNOTATION ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_ANNOTATION) {
|
||||||
}
|
}
|
||||||
else if ( tag == DescriptorDecoder.BASE_TYPE_ARRAY ) {
|
else if (tag == DescriptorDecoder.BASE_TYPE_ARRAY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return structure;
|
return structure;
|
||||||
|
|||||||
+9
-10
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -43,9 +42,9 @@ public class AnnotationElementValuePair implements StructConverter {
|
|||||||
private short elementNameIndex;
|
private short elementNameIndex;
|
||||||
private AnnotationElementValue value;
|
private AnnotationElementValue value;
|
||||||
|
|
||||||
public AnnotationElementValuePair( BinaryReader reader ) throws IOException {
|
public AnnotationElementValuePair(BinaryReader reader) throws IOException {
|
||||||
elementNameIndex = reader.readNextShort();
|
elementNameIndex = reader.readNextShort();
|
||||||
value = new AnnotationElementValue( reader );
|
value = new AnnotationElementValue(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,8 +55,8 @@ public class AnnotationElementValuePair implements StructConverter {
|
|||||||
* element represented by this element_value_pairs entry.
|
* element represented by this element_value_pairs entry.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getElementNameIndex() {
|
public int getElementNameIndex() {
|
||||||
return elementNameIndex;
|
return elementNameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,9 +70,9 @@ public class AnnotationElementValuePair implements StructConverter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = new StructureDataType( "element_value_pair", 0 );
|
StructureDataType structure = new StructureDataType("element_value_pair", 0);
|
||||||
structure.add( WORD, "element_name_index", null );
|
structure.add(WORD, "element_name_index", null);
|
||||||
structure.add( value.toDataType(), "element_value_pair", null );
|
structure.add(value.toDataType(), "element_value_pair", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-18
@@ -15,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -45,14 +45,14 @@ public class AnnotationJava implements StructConverter {
|
|||||||
|
|
||||||
private short typeIndex;
|
private short typeIndex;
|
||||||
private short numberOfElementValuePairs;
|
private short numberOfElementValuePairs;
|
||||||
private AnnotationElementValuePair [] elementValuePairs;
|
private AnnotationElementValuePair[] elementValuePairs;
|
||||||
|
|
||||||
public AnnotationJava( BinaryReader reader ) throws IOException {
|
public AnnotationJava(BinaryReader reader) throws IOException {
|
||||||
typeIndex = reader.readNextShort();
|
typeIndex = reader.readNextShort();
|
||||||
numberOfElementValuePairs = reader.readNextShort();
|
numberOfElementValuePairs = reader.readNextShort();
|
||||||
elementValuePairs = new AnnotationElementValuePair[ numberOfElementValuePairs ];
|
elementValuePairs = new AnnotationElementValuePair[getNumberOfElementValuePairs()];
|
||||||
for ( int i = 0 ; i < numberOfElementValuePairs ; ++i ) {
|
for (int i = 0; i < getNumberOfElementValuePairs(); ++i) {
|
||||||
elementValuePairs[ i ] = new AnnotationElementValuePair( reader );
|
elementValuePairs[i] = new AnnotationElementValuePair(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +64,8 @@ public class AnnotationJava implements StructConverter {
|
|||||||
* represented by this annotation structure.
|
* represented by this annotation structure.
|
||||||
* @return valid index into the constant_pool table
|
* @return valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getTypeIndex() {
|
public int getTypeIndex() {
|
||||||
return typeIndex;
|
return typeIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,26 +77,26 @@ public class AnnotationJava implements StructConverter {
|
|||||||
* annotation.
|
* annotation.
|
||||||
* @return the number of element-value pairs of the annotation
|
* @return the number of element-value pairs of the annotation
|
||||||
*/
|
*/
|
||||||
public short getNumberOfElementValuePairs() {
|
public int getNumberOfElementValuePairs() {
|
||||||
return numberOfElementValuePairs;
|
return numberOfElementValuePairs & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the element value pair table for this annotation.
|
* Returns the element value pair table for this annotation.
|
||||||
* @return the element value pair table
|
* @return the element value pair table
|
||||||
*/
|
*/
|
||||||
public AnnotationElementValuePair [] getElementValuePairs() {
|
public AnnotationElementValuePair[] getElementValuePairs() {
|
||||||
return elementValuePairs;
|
return elementValuePairs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = "annotation" +"|" + numberOfElementValuePairs + "|";
|
String name = "annotation" + "|" + numberOfElementValuePairs + "|";
|
||||||
StructureDataType structure = new StructureDataType( name, 0 );
|
StructureDataType structure = new StructureDataType(name, 0);
|
||||||
structure.add( WORD, "type_index", null );
|
structure.add(WORD, "type_index", null);
|
||||||
structure.add( WORD, "num_element_value_pairs", null );
|
structure.add(WORD, "num_element_value_pairs", null);
|
||||||
for ( int i = 0 ; i < elementValuePairs.length ; ++i ) {
|
for (int i = 0; i < elementValuePairs.length; ++i) {
|
||||||
structure.add( elementValuePairs[ i ].toDataType(), "element_value_pair_" + i, null );
|
structure.add(elementValuePairs[i].toDataType(), "element_value_pair_" + i, null);
|
||||||
}
|
}
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-70
@@ -15,90 +15,82 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
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 java.io.IOException;
|
|
||||||
|
|
||||||
public class AttributeFactory {
|
public class AttributeFactory {
|
||||||
|
|
||||||
public static AbstractAttributeInfo get( BinaryReader reader, AbstractConstantPoolInfoJava [] constantPool ) throws IOException {
|
public static AbstractAttributeInfo get(BinaryReader reader,
|
||||||
|
AbstractConstantPoolInfoJava[] constantPool) throws IOException {
|
||||||
|
|
||||||
int attributeNameIndex = reader.readShort( reader.getPointerIndex() );
|
int attributeNameIndex = reader.readShort(reader.getPointerIndex());
|
||||||
|
|
||||||
if ( attributeNameIndex < 1 || attributeNameIndex >= constantPool.length ) {
|
if (attributeNameIndex < 1 || attributeNameIndex >= constantPool.length) {
|
||||||
throw new RuntimeException( "invalid index");
|
throw new RuntimeException("invalid index");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( constantPool[ attributeNameIndex ] instanceof ConstantPoolUtf8Info ) ) {
|
if (!(constantPool[attributeNameIndex] instanceof ConstantPoolUtf8Info)) {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantPoolUtf8Info utf8 = (ConstantPoolUtf8Info) constantPool[ attributeNameIndex ];
|
ConstantPoolUtf8Info utf8 = (ConstantPoolUtf8Info) constantPool[attributeNameIndex];
|
||||||
|
|
||||||
if ( utf8.getString().equals( AttributesConstants.ConstantValue ) ) {
|
switch (utf8.getString()) {
|
||||||
return new ConstantValueAttribute( reader );
|
case AttributesConstants.AnnotationDefault:
|
||||||
|
return new AnnotationDefaultAttribute(reader);
|
||||||
|
case AttributesConstants.BootstrapMethods:
|
||||||
|
return new BootstrapMethodsAttribute(reader);
|
||||||
|
case AttributesConstants.Code:
|
||||||
|
return new CodeAttribute(reader, constantPool);
|
||||||
|
case AttributesConstants.ConstantValue:
|
||||||
|
return new ConstantValueAttribute(reader);
|
||||||
|
case AttributesConstants.Deprecated:
|
||||||
|
return new DeprecatedAttribute(reader);
|
||||||
|
case AttributesConstants.EnclosingMethod:
|
||||||
|
return new EnclosingMethodAttribute(reader);
|
||||||
|
case AttributesConstants.Exceptions:
|
||||||
|
return new ExceptionsAttribute(reader);
|
||||||
|
case AttributesConstants.InnerClasses:
|
||||||
|
return new InnerClassesAttribute(reader);
|
||||||
|
case AttributesConstants.LineNumberTable:
|
||||||
|
return new LineNumberTableAttribute(reader);
|
||||||
|
case AttributesConstants.LocalVariableTable:
|
||||||
|
return new LocalVariableTableAttribute(reader, constantPool);
|
||||||
|
case AttributesConstants.LocalVariableTypeTable:
|
||||||
|
return new LocalVariableTypeTableAttribute(reader);
|
||||||
|
case AttributesConstants.ModuleMainClass:
|
||||||
|
return new ModuleMainClassAttribute(reader);
|
||||||
|
case AttributesConstants.ModulePackages:
|
||||||
|
return new ModulePackagesAttribute(reader);
|
||||||
|
case AttributesConstants.NestHost:
|
||||||
|
return new NestHostAttribute(reader);
|
||||||
|
case AttributesConstants.NestMembers:
|
||||||
|
return new NestMembersAttribute(reader);
|
||||||
|
case AttributesConstants.RuntimeInvisibleAnnotations:
|
||||||
|
return new RuntimeInvisibleAnnotationsAttribute(reader);
|
||||||
|
case AttributesConstants.RuntimeInvisibleParameterAnnotations:
|
||||||
|
return new RuntimeParameterAnnotationsAttribute(reader, false /*invisible*/ );
|
||||||
|
case AttributesConstants.RuntimeVisibleAnnotations:
|
||||||
|
return new RuntimeVisibleAnnotationsAttribute(reader);
|
||||||
|
case AttributesConstants.RuntimeVisibleParameterAnnotations:
|
||||||
|
return new RuntimeParameterAnnotationsAttribute(reader, true /*visible*/ );
|
||||||
|
case AttributesConstants.Signature:
|
||||||
|
return new SignatureAttribute(reader);
|
||||||
|
case AttributesConstants.SourceDebugExtension:
|
||||||
|
return new SourceDebugExtensionAttribute(reader);
|
||||||
|
case AttributesConstants.SourceFile:
|
||||||
|
return new SourceFileAttribute(reader);
|
||||||
|
case AttributesConstants.StackMapTable:
|
||||||
|
return new StackMapTableAttribute(reader);
|
||||||
|
case AttributesConstants.Synthetic:
|
||||||
|
return new SyntheticAttribute(reader);
|
||||||
|
case AttributesConstants.Module:
|
||||||
|
return new ModuleAttribute(reader);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown attribute type: " + utf8.getString());
|
||||||
}
|
}
|
||||||
else if ( utf8.getString().equals( AttributesConstants.Code ) ) {
|
|
||||||
return new CodeAttribute( reader, constantPool );
|
|
||||||
}
|
}
|
||||||
else if ( utf8.getString().equals( AttributesConstants.StackMapTable ) ) {
|
|
||||||
return new StackMapTableAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.Exceptions ) ) {
|
|
||||||
return new ExceptionsAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.InnerClasses ) ) {
|
|
||||||
return new InnerClassesAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.EnclosingMethod ) ) {
|
|
||||||
return new EnclosingMethodAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.Synthetic ) ) {
|
|
||||||
return new SyntheticAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.Signature ) ) {
|
|
||||||
return new SignatureAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.SourceFile ) ) {
|
|
||||||
return new SourceFileAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.SourceDebugExtension ) ) {
|
|
||||||
return new SourceDebugExtensionAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.LineNumberTable ) ) {
|
|
||||||
return new LineNumberTableAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.LocalVariableTable ) ) {
|
|
||||||
return new LocalVariableTableAttribute( reader, constantPool );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.LocalVariableTypeTable ) ) {
|
|
||||||
return new LocalVariableTypeTableAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.Deprecated ) ) {
|
|
||||||
return new DeprecatedAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.RuntimeVisibleAnnotations ) ) {
|
|
||||||
return new RuntimeVisibleAnnotationsAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.RuntimeInvisibleAnnotations ) ) {
|
|
||||||
return new RuntimeInvisibleAnnotationsAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.RuntimeVisibleParameterAnnotations ) ) {
|
|
||||||
return new RuntimeParameterAnnotationsAttribute( reader, true /*visible*/ );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.RuntimeInvisibleParameterAnnotations ) ) {
|
|
||||||
return new RuntimeParameterAnnotationsAttribute( reader, false /*invisible*/ );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.AnnotationDefault ) ) {
|
|
||||||
return new AnnotationDefaultAttribute( reader );
|
|
||||||
}
|
|
||||||
else if ( utf8.getString().equals( AttributesConstants.BootstrapMethods ) ) {
|
|
||||||
return new BootstrapMethodsAttribute( reader );
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException( "Unknown attribute type: " + utf8.getString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-3
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -34,9 +33,16 @@ public final class AttributesConstants {
|
|||||||
public final static String Deprecated = "Deprecated";
|
public final static String Deprecated = "Deprecated";
|
||||||
public final static String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
|
public final static String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
|
||||||
public final static String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
|
public final static String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
|
||||||
public final static String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
|
public final static String RuntimeVisibleParameterAnnotations =
|
||||||
public final static String RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
|
"RuntimeVisibleParameterAnnotations";
|
||||||
|
public final static String 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 Module = "Module";
|
||||||
|
public final static String ModulePackages = "ModulePackages";
|
||||||
|
public final static String ModuleMainClass = "ModuleMainClass";
|
||||||
|
public final static String NestHost = "NestHost";
|
||||||
|
public final static String NestMembers = "NestMembers";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-20
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,9 +19,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.ArrayDataType;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.StructureDataType;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,12 +31,12 @@ public class BootstrapMethods implements StructConverter {
|
|||||||
|
|
||||||
private short bootstrapMethodsReference;
|
private short bootstrapMethodsReference;
|
||||||
private short numberOfBootstrapArguments;
|
private short numberOfBootstrapArguments;
|
||||||
private short [] bootstrapArguments;
|
private short[] bootstrapArguments;
|
||||||
|
|
||||||
public BootstrapMethods( BinaryReader reader ) throws IOException {
|
public BootstrapMethods(BinaryReader reader) throws IOException {
|
||||||
bootstrapMethodsReference = reader.readNextShort();
|
bootstrapMethodsReference = reader.readNextShort();
|
||||||
numberOfBootstrapArguments = reader.readNextShort();
|
numberOfBootstrapArguments = reader.readNextShort();
|
||||||
bootstrapArguments = reader.readNextShortArray( numberOfBootstrapArguments & 0xffff );
|
bootstrapArguments = reader.readNextShortArray(getNumberOfBootstrapArguments());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,8 +52,8 @@ public class BootstrapMethods implements StructConverter {
|
|||||||
*
|
*
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getBootstrapMethodsReference() {
|
public int getBootstrapMethodsReference() {
|
||||||
return bootstrapMethodsReference;
|
return bootstrapMethodsReference & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,8 +61,8 @@ public class BootstrapMethods implements StructConverter {
|
|||||||
* items in the bootstrap_arguments array.
|
* items in the bootstrap_arguments array.
|
||||||
* @return the number of items in the bootstrap_arguments array
|
* @return the number of items in the bootstrap_arguments array
|
||||||
*/
|
*/
|
||||||
public short getNumberOfBootstrapArguments() {
|
public int getNumberOfBootstrapArguments() {
|
||||||
return numberOfBootstrapArguments;
|
return numberOfBootstrapArguments & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,20 +77,21 @@ public class BootstrapMethods implements StructConverter {
|
|||||||
* CONSTANT_Double_info,
|
* CONSTANT_Double_info,
|
||||||
* CONSTANT_MethodHandle_info, or
|
* CONSTANT_MethodHandle_info, or
|
||||||
* CONSTANT_MethodType_info structure.
|
* CONSTANT_MethodType_info structure.
|
||||||
* @return
|
* @param i entry
|
||||||
|
* @return index
|
||||||
*/
|
*/
|
||||||
public short [] getBootstrapArguments() {
|
public int getBootstrapArgumentsEntry(int i) {
|
||||||
return bootstrapArguments;
|
return bootstrapArguments[i] & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = new StructureDataType( "bootstrap_methods", 0 );
|
StructureDataType structure = new StructureDataType("bootstrap_methods", 0);
|
||||||
structure.add( WORD, "bootstrap_method_ref", null );
|
structure.add(WORD, "bootstrap_method_ref", null);
|
||||||
structure.add( WORD, "num_bootstrap_arguments", null );
|
structure.add(WORD, "num_bootstrap_arguments", null);
|
||||||
if ( numberOfBootstrapArguments > 0 ) {
|
if (numberOfBootstrapArguments > 0) {
|
||||||
DataType array = new ArrayDataType( WORD, numberOfBootstrapArguments, WORD.getLength() );
|
DataType array = new ArrayDataType(WORD, numberOfBootstrapArguments, WORD.getLength());
|
||||||
structure.add( array, "bootstrapArguments", null );
|
structure.add(array, "bootstrapArguments", null);
|
||||||
}
|
}
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -55,33 +55,33 @@ import java.io.IOException;
|
|||||||
public class BootstrapMethodsAttribute extends AbstractAttributeInfo {
|
public class BootstrapMethodsAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
private short numberOfBootstrapMethods;
|
private short numberOfBootstrapMethods;
|
||||||
private BootstrapMethods [] bootstrapMethods;
|
private BootstrapMethods[] bootstrapMethods;
|
||||||
|
|
||||||
public BootstrapMethodsAttribute( BinaryReader reader ) throws IOException {
|
public BootstrapMethodsAttribute(BinaryReader reader) throws IOException {
|
||||||
super(reader);
|
super(reader);
|
||||||
|
|
||||||
numberOfBootstrapMethods = reader.readNextShort();
|
numberOfBootstrapMethods = reader.readNextShort();
|
||||||
|
|
||||||
bootstrapMethods = new BootstrapMethods[ numberOfBootstrapMethods ];
|
bootstrapMethods = new BootstrapMethods[getNumberOfBootstrapMethods()];
|
||||||
for ( int i = 0 ; i < numberOfBootstrapMethods ; ++i ) {
|
for (int i = 0; i < getNumberOfBootstrapMethods(); ++i) {
|
||||||
bootstrapMethods[ i ] = new BootstrapMethods( reader );
|
bootstrapMethods[i] = new BootstrapMethods(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getNumberOfBootstrapMethods() {
|
public int getNumberOfBootstrapMethods() {
|
||||||
return numberOfBootstrapMethods;
|
return numberOfBootstrapMethods & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BootstrapMethods[] getBootstrapMethods(){
|
public BootstrapMethods[] getBootstrapMethods() {
|
||||||
return bootstrapMethods;
|
return bootstrapMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "BootstrapMethods_attribute" );
|
StructureDataType structure = getBaseStructure("BootstrapMethods_attribute");
|
||||||
structure.add( WORD, "num_bootstrap_methods", null );
|
structure.add(WORD, "num_bootstrap_methods", null);
|
||||||
for ( int i = 0 ; i < bootstrapMethods.length ; ++i ) {
|
for (int i = 0; i < bootstrapMethods.length; ++i) {
|
||||||
structure.add( bootstrapMethods[ i ].toDataType(), "bootstrap_methods" + i, null );
|
structure.add(bootstrapMethods[i].toDataType(), "bootstrap_methods" + i, null);
|
||||||
}
|
}
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
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.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -80,13 +80,13 @@ public class CodeAttribute extends AbstractAttributeInfo {
|
|||||||
_codeOffset = reader.getPointerIndex();
|
_codeOffset = reader.getPointerIndex();
|
||||||
code = reader.readNextByteArray(codeLength);
|
code = reader.readNextByteArray(codeLength);
|
||||||
exceptionTableLength = reader.readNextShort();
|
exceptionTableLength = reader.readNextShort();
|
||||||
exceptionTable = new ExceptionHandlerJava[exceptionTableLength];
|
exceptionTable = new ExceptionHandlerJava[getExceptionTableLength()];
|
||||||
for (int i = 0; i < exceptionTableLength; i++) {
|
for (int i = 0; i < getExceptionTableLength(); i++) {
|
||||||
exceptionTable[i] = new ExceptionHandlerJava(reader);
|
exceptionTable[i] = new ExceptionHandlerJava(reader);
|
||||||
}
|
}
|
||||||
attributesCount = reader.readNextShort();
|
attributesCount = reader.readNextShort();
|
||||||
attributes = new AbstractAttributeInfo[attributesCount];
|
attributes = new AbstractAttributeInfo[getAttributesCount()];
|
||||||
for (int i = 0; i < attributesCount; i++) {
|
for (int i = 0; i < getAttributesCount(); i++) {
|
||||||
attributes[i] = AttributeFactory.get(reader, constantPool);
|
attributes[i] = AttributeFactory.get(reader, constantPool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,8 +96,8 @@ public class CodeAttribute extends AbstractAttributeInfo {
|
|||||||
* operand stack of this method at any point during execution of the method.
|
* operand stack of this method at any point during execution of the method.
|
||||||
* @return the maximum depth of the operand stack
|
* @return the maximum depth of the operand stack
|
||||||
*/
|
*/
|
||||||
public short getMaxStack() {
|
public int getMaxStack() {
|
||||||
return maxStack;
|
return maxStack & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,8 +111,8 @@ public class CodeAttribute extends AbstractAttributeInfo {
|
|||||||
* @return the number of local variables in the
|
* @return the number of local variables in the
|
||||||
* local variable array allocated upon invocation of this method
|
* local variable array allocated upon invocation of this method
|
||||||
*/
|
*/
|
||||||
public short getMaxLocals() {
|
public int getMaxLocals() {
|
||||||
return maxLocals;
|
return maxLocals & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,8 +148,8 @@ public class CodeAttribute extends AbstractAttributeInfo {
|
|||||||
* in the exception_table table.
|
* in the exception_table table.
|
||||||
* @return the number of entries in the exception_table table
|
* @return the number of entries in the exception_table table
|
||||||
*/
|
*/
|
||||||
public short getExceptionTableLength() {
|
public int getExceptionTableLength() {
|
||||||
return exceptionTableLength;
|
return exceptionTableLength & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -168,8 +168,8 @@ public class CodeAttribute extends AbstractAttributeInfo {
|
|||||||
* the Code attribute.
|
* the Code attribute.
|
||||||
* @return the number of attributes of the Code attribute
|
* @return the number of attributes of the Code attribute
|
||||||
*/
|
*/
|
||||||
public short getAttributesCount() {
|
public int getAttributesCount() {
|
||||||
return attributesCount;
|
return attributesCount & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+8
-9
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -56,8 +55,8 @@ public class ConstantValueAttribute extends AbstractAttributeInfo {
|
|||||||
|
|
||||||
private short constantValueIndex;
|
private short constantValueIndex;
|
||||||
|
|
||||||
public ConstantValueAttribute( BinaryReader reader ) throws IOException {
|
public ConstantValueAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
constantValueIndex = reader.readNextShort();
|
constantValueIndex = reader.readNextShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,14 +79,14 @@ public class ConstantValueAttribute extends AbstractAttributeInfo {
|
|||||||
* </pre>
|
* </pre>
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getConstantValueIndex() {
|
public int getConstantValueIndex() {
|
||||||
return constantValueIndex;
|
return constantValueIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "ConstantValue_attribute" );
|
StructureDataType structure = getBaseStructure("ConstantValue_attribute");
|
||||||
structure.add( WORD, "constantvalue_index", null );
|
structure.add(WORD, "constantvalue_index", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-12
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -46,8 +45,8 @@ public class EnclosingMethodAttribute extends AbstractAttributeInfo {
|
|||||||
private short classIndex;
|
private short classIndex;
|
||||||
private short methodIndex;
|
private short methodIndex;
|
||||||
|
|
||||||
public EnclosingMethodAttribute( BinaryReader reader ) throws IOException {
|
public EnclosingMethodAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
|
|
||||||
classIndex = reader.readNextShort();
|
classIndex = reader.readNextShort();
|
||||||
methodIndex = reader.readNextShort();
|
methodIndex = reader.readNextShort();
|
||||||
@@ -60,8 +59,8 @@ public class EnclosingMethodAttribute extends AbstractAttributeInfo {
|
|||||||
* encloses the declaration of the current class.
|
* encloses the declaration of the current class.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getClassIndex() {
|
public int getClassIndex() {
|
||||||
return classIndex;
|
return classIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,15 +73,15 @@ public class EnclosingMethodAttribute extends AbstractAttributeInfo {
|
|||||||
* type of a method in the class referenced by the class_index attribute above.
|
* type of a method in the class referenced by the class_index attribute above.
|
||||||
* @return a valid index into the constant_pool table, or zero
|
* @return a valid index into the constant_pool table, or zero
|
||||||
*/
|
*/
|
||||||
public short getMethodIndex() {
|
public int getMethodIndex() {
|
||||||
return methodIndex;
|
return methodIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "EnclosingMethod_attribute" );
|
StructureDataType structure = getBaseStructure("EnclosingMethod_attribute");
|
||||||
structure.add( WORD, "class_index", null );
|
structure.add(WORD, "class_index", null);
|
||||||
structure.add( WORD, "method_index", null );
|
structure.add(WORD, "method_index", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-16
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -33,7 +33,7 @@ public class ExceptionHandlerJava implements StructConverter {
|
|||||||
private short handlerPC;
|
private short handlerPC;
|
||||||
private short catchType;
|
private short catchType;
|
||||||
|
|
||||||
public ExceptionHandlerJava( BinaryReader reader ) throws IOException {
|
public ExceptionHandlerJava(BinaryReader reader) throws IOException {
|
||||||
startPC = reader.readNextShort();
|
startPC = reader.readNextShort();
|
||||||
endPC = reader.readNextShort();
|
endPC = reader.readNextShort();
|
||||||
handlerPC = reader.readNextShort();
|
handlerPC = reader.readNextShort();
|
||||||
@@ -54,9 +54,10 @@ public class ExceptionHandlerJava implements StructConverter {
|
|||||||
* [start_pc, end_pc].
|
* [start_pc, end_pc].
|
||||||
* @return a valid index into the code array
|
* @return a valid index into the code array
|
||||||
*/
|
*/
|
||||||
public short getStartPC() {
|
public int getStartPC() {
|
||||||
return startPC;
|
return startPC & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The values of the two items start_pc and end_pc indicate the ranges in the
|
* The values of the two items start_pc and end_pc indicate the ranges in the
|
||||||
* code array at which the exception handler is active.
|
* code array at which the exception handler is active.
|
||||||
@@ -72,18 +73,20 @@ public class ExceptionHandlerJava implements StructConverter {
|
|||||||
* [start_pc, end_pc].
|
* [start_pc, end_pc].
|
||||||
* @return a valid index into the code array
|
* @return a valid index into the code array
|
||||||
*/
|
*/
|
||||||
public short getEndPC() {
|
public int getEndPC() {
|
||||||
return endPC;
|
return endPC & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of the handler_pc item indicates the start of the exception
|
* The value of the handler_pc item indicates the start of the exception
|
||||||
* handler. The value of the item must be a valid index into the code array
|
* handler. The value of the item must be a valid index into the code array
|
||||||
* and must be the index of the opcode of an instruction.
|
* and must be the index of the opcode of an instruction.
|
||||||
* @return the start of the exception handler
|
* @return the start of the exception handler
|
||||||
*/
|
*/
|
||||||
public short getHandlerPC() {
|
public int getHandlerPC() {
|
||||||
return handlerPC;
|
return handlerPC & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the value of the catch_type item is nonzero, it must be a valid index
|
* If the value of the catch_type item is nonzero, it must be a valid index
|
||||||
* into the constant_pool table. The constant_pool entry at that index
|
* into the constant_pool table. The constant_pool entry at that index
|
||||||
@@ -96,17 +99,17 @@ public class ExceptionHandlerJava implements StructConverter {
|
|||||||
* for all exceptions. This is used to implement finally (?3.13).
|
* for all exceptions. This is used to implement finally (?3.13).
|
||||||
* @return the value of the catch_type item
|
* @return the value of the catch_type item
|
||||||
*/
|
*/
|
||||||
public short getCatchType() {
|
public int getCatchType() {
|
||||||
return catchType;
|
return catchType & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
Structure structure = new StructureDataType( "exception_handler", 0 );
|
Structure structure = new StructureDataType("exception_handler", 0);
|
||||||
structure.add( WORD, "start_pc", null );
|
structure.add(WORD, "start_pc", null);
|
||||||
structure.add( WORD, "end_pc", null );
|
structure.add(WORD, "end_pc", null);
|
||||||
structure.add( WORD, "handler_pc", null );
|
structure.add(WORD, "handler_pc", null);
|
||||||
structure.add( WORD, "catch_type", null );
|
structure.add(WORD, "catch_type", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,12 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -49,7 +48,7 @@ public class ExceptionsAttribute extends AbstractAttributeInfo {
|
|||||||
super(reader);
|
super(reader);
|
||||||
|
|
||||||
numberOfExceptions = reader.readNextShort();
|
numberOfExceptions = reader.readNextShort();
|
||||||
exceptionIndexTable = reader.readNextShortArray(numberOfExceptions);
|
exceptionIndexTable = reader.readNextShortArray(getNumberOfExceptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,8 +56,8 @@ public class ExceptionsAttribute extends AbstractAttributeInfo {
|
|||||||
* in the exception_index_table.
|
* in the exception_index_table.
|
||||||
* @return the number of entries in the exception_index_table
|
* @return the number of entries in the exception_index_table
|
||||||
*/
|
*/
|
||||||
public short getNumberOfExceptions() {
|
public int getNumberOfExceptions() {
|
||||||
return numberOfExceptions;
|
return numberOfExceptions & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,10 +65,11 @@ public class ExceptionsAttribute extends AbstractAttributeInfo {
|
|||||||
* the constant_pool table. The constant_pool entry referenced by each table
|
* the constant_pool table. The constant_pool entry referenced by each table
|
||||||
* item must be a CONSTANT_Class_info structure representing a class
|
* item must be a CONSTANT_Class_info structure representing a class
|
||||||
* type that this method is declared to throw.
|
* type that this method is declared to throw.
|
||||||
* @return the exception_index_table array
|
* @param i entry
|
||||||
|
* @return index
|
||||||
*/
|
*/
|
||||||
public short[] getExceptionIndexTable() {
|
public int getExceptionIndexTableEntry(int i) {
|
||||||
return exceptionIndexTable;
|
return exceptionIndexTable[i] & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+14
-15
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -44,7 +43,7 @@ public class InnerClass implements StructConverter {
|
|||||||
private short innerNameIndex;
|
private short innerNameIndex;
|
||||||
private short innerClassAccessFlags;
|
private short innerClassAccessFlags;
|
||||||
|
|
||||||
public InnerClass( BinaryReader reader ) throws IOException {
|
public InnerClass(BinaryReader reader) throws IOException {
|
||||||
innerClassInfoIndex = reader.readNextShort();
|
innerClassInfoIndex = reader.readNextShort();
|
||||||
outerClassInfoIndex = reader.readNextShort();
|
outerClassInfoIndex = reader.readNextShort();
|
||||||
innerNameIndex = reader.readNextShort();
|
innerNameIndex = reader.readNextShort();
|
||||||
@@ -58,8 +57,8 @@ public class InnerClass implements StructConverter {
|
|||||||
* items in the classes array entry give information about C.
|
* items in the classes array entry give information about C.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getInnerClassInfoIndex() {
|
public int getInnerClassInfoIndex() {
|
||||||
return innerClassInfoIndex;
|
return innerClassInfoIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,8 +73,8 @@ public class InnerClass implements StructConverter {
|
|||||||
* interface of which C is a member.
|
* interface of which C is a member.
|
||||||
* @return a valid index into the constant_pool table, or zero
|
* @return a valid index into the constant_pool table, or zero
|
||||||
*/
|
*/
|
||||||
public short getOuterClassInfoIndex() {
|
public int getOuterClassInfoIndex() {
|
||||||
return outerClassInfoIndex;
|
return outerClassInfoIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,8 +87,8 @@ public class InnerClass implements StructConverter {
|
|||||||
* compiled.
|
* compiled.
|
||||||
* @return a valid index into the constant_pool table, or zero
|
* @return a valid index into the constant_pool table, or zero
|
||||||
*/
|
*/
|
||||||
public short getInnerNameIndex() {
|
public int getInnerNameIndex() {
|
||||||
return innerNameIndex;
|
return innerNameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,11 +106,11 @@ public class InnerClass implements StructConverter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = new StructureDataType( "inner_class", 0 );
|
StructureDataType structure = new StructureDataType("inner_class", 0);
|
||||||
structure.add( WORD, "inner_class_info_index", null );
|
structure.add(WORD, "inner_class_info_index", null);
|
||||||
structure.add( WORD, "outer_class_info_index", null );
|
structure.add(WORD, "outer_class_info_index", null);
|
||||||
structure.add( WORD, "inner_name_index", null );
|
structure.add(WORD, "inner_name_index", null);
|
||||||
structure.add( WORD, "inner_class_access_flags", null );
|
structure.add(WORD, "inner_class_access_flags", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-16
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -50,15 +49,15 @@ import java.io.IOException;
|
|||||||
public class InnerClassesAttribute extends AbstractAttributeInfo {
|
public class InnerClassesAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
private short numberOfInnerClasses;
|
private short numberOfInnerClasses;
|
||||||
private InnerClass [] innerClasses;
|
private InnerClass[] innerClasses;
|
||||||
|
|
||||||
public InnerClassesAttribute( BinaryReader reader ) throws IOException {
|
public InnerClassesAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
|
|
||||||
numberOfInnerClasses = reader.readNextShort();
|
numberOfInnerClasses = reader.readNextShort();
|
||||||
innerClasses = new InnerClass[ numberOfInnerClasses ];
|
innerClasses = new InnerClass[getNumberOfInnerClasses()];
|
||||||
for ( int i = 0 ; i < numberOfInnerClasses ; i++ ) {
|
for (int i = 0; i < getNumberOfInnerClasses(); i++) {
|
||||||
innerClasses[ i ] = new InnerClass( reader );
|
innerClasses[i] = new InnerClass(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,24 +66,25 @@ public class InnerClassesAttribute extends AbstractAttributeInfo {
|
|||||||
* the classes array.
|
* the classes array.
|
||||||
* @return the number of entries in the classes array
|
* @return the number of entries in the classes array
|
||||||
*/
|
*/
|
||||||
public short getNumberOfInnerClasses() {
|
public int getNumberOfInnerClasses() {
|
||||||
return numberOfInnerClasses;
|
return numberOfInnerClasses & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns array of inner classes.
|
* Returns array of inner classes.
|
||||||
* @return array of inner classes.
|
* @return array of inner classes.
|
||||||
*/
|
*/
|
||||||
public InnerClass [] getInnerClasses() {
|
public InnerClass[] getInnerClasses() {
|
||||||
return innerClasses;
|
return innerClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "InnerClasses_attribute" + "|" + numberOfInnerClasses + "|" );
|
StructureDataType structure =
|
||||||
structure.add( WORD, "number_of_classes", null );
|
getBaseStructure("InnerClasses_attribute" + "|" + numberOfInnerClasses + "|");
|
||||||
for ( int i = 0 ; i < innerClasses.length ; ++i ) {
|
structure.add(WORD, "number_of_classes", null);
|
||||||
structure.add( innerClasses[ i ].toDataType(), "inner_class_" + i, null );
|
for (int i = 0; i < innerClasses.length; ++i) {
|
||||||
|
structure.add(innerClasses[i].toDataType(), "inner_class_" + i, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return structure;
|
return structure;
|
||||||
|
|||||||
+10
-11
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -40,7 +39,7 @@ public class LineNumber implements StructConverter {
|
|||||||
private short startPC;
|
private short startPC;
|
||||||
private short lineNumber;
|
private short lineNumber;
|
||||||
|
|
||||||
public LineNumber( BinaryReader reader ) throws IOException {
|
public LineNumber(BinaryReader reader) throws IOException {
|
||||||
startPC = reader.readNextShort();
|
startPC = reader.readNextShort();
|
||||||
lineNumber = reader.readNextShort();
|
lineNumber = reader.readNextShort();
|
||||||
}
|
}
|
||||||
@@ -53,23 +52,23 @@ public class LineNumber implements StructConverter {
|
|||||||
* item of the Code attribute of which this LineNumberTable is an attribute.
|
* item of the Code attribute of which this LineNumberTable is an attribute.
|
||||||
* @return index into the code array at which the code for a new line in the original source file begins
|
* @return index into the code array at which the code for a new line in the original source file begins
|
||||||
*/
|
*/
|
||||||
public short getStartPC() {
|
public int getStartPC() {
|
||||||
return startPC;
|
return startPC & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of the line_number item must give the corresponding line number in the original source file.
|
* The value of the line_number item must give the corresponding line number in the original source file.
|
||||||
* @return the corresponding line number in the original source file
|
* @return the corresponding line number in the original source file
|
||||||
*/
|
*/
|
||||||
public short getLineNumber() {
|
public int getLineNumber() {
|
||||||
return lineNumber;
|
return lineNumber & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = new StructureDataType( "line_number", 0 );
|
StructureDataType structure = new StructureDataType("line_number", 0);
|
||||||
structure.add( WORD, "start_pc", null );
|
structure.add(WORD, "start_pc", null);
|
||||||
structure.add( WORD, "line_number", null );
|
structure.add(WORD, "line_number", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-13
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -52,25 +51,25 @@ import java.io.IOException;
|
|||||||
public class LineNumberTableAttribute extends AbstractAttributeInfo {
|
public class LineNumberTableAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
private short lineNumberTableLength;
|
private short lineNumberTableLength;
|
||||||
private LineNumber [] lineNumberTable;
|
private LineNumber[] lineNumberTable;
|
||||||
|
|
||||||
public LineNumberTableAttribute( BinaryReader reader ) throws IOException {
|
public LineNumberTableAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
|
|
||||||
lineNumberTableLength = reader.readNextShort();
|
lineNumberTableLength = reader.readNextShort();
|
||||||
lineNumberTable = new LineNumber[ lineNumberTableLength ];
|
lineNumberTable = new LineNumber[lineNumberTableLength & 0xffff];
|
||||||
for ( int i = 0 ; i < lineNumberTableLength ; i++ ) {
|
for (int i = 0; i < (lineNumberTableLength & 0xffff); i++) {
|
||||||
lineNumberTable[ i ] = new LineNumber( reader );
|
lineNumberTable[i] = new LineNumber(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = "LineNumberTable_attribute" + "|" + lineNumberTableLength + "|";
|
String name = "LineNumberTable_attribute" + "|" + lineNumberTableLength + "|";
|
||||||
StructureDataType structure = getBaseStructure( name );
|
StructureDataType structure = getBaseStructure(name);
|
||||||
structure.add( WORD, "line_number_table_length", null );
|
structure.add(WORD, "line_number_table_length", null);
|
||||||
for ( int i = 0 ; i < lineNumberTable.length ; ++i ) {
|
for (int i = 0; i < lineNumberTable.length; ++i) {
|
||||||
structure.add( lineNumberTable[ i ].toDataType(), "line_number_" + i, null );
|
structure.add(lineNumberTable[i].toDataType(), "line_number_" + i, null);
|
||||||
}
|
}
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-19
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -90,7 +90,7 @@ public class LocalVariableJava implements StructConverter {
|
|||||||
private short descriptorIndex;
|
private short descriptorIndex;
|
||||||
private short index;
|
private short index;
|
||||||
|
|
||||||
public LocalVariableJava( BinaryReader reader ) throws IOException {
|
public LocalVariableJava(BinaryReader reader) throws IOException {
|
||||||
startPC = reader.readNextShort();
|
startPC = reader.readNextShort();
|
||||||
length = reader.readNextShort();
|
length = reader.readNextShort();
|
||||||
nameIndex = reader.readNextShort();
|
nameIndex = reader.readNextShort();
|
||||||
@@ -111,16 +111,16 @@ public class LocalVariableJava implements StructConverter {
|
|||||||
* or it must be the first index beyond the end of that code array.
|
* or it must be the first index beyond the end of that code array.
|
||||||
* @return the start PC
|
* @return the start PC
|
||||||
*/
|
*/
|
||||||
public short getStartPC() {
|
public int getStartPC() {
|
||||||
return startPC;
|
return startPC & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the length of this local variable in bytes.
|
* Returns the length of this local variable in bytes.
|
||||||
* @return the length of this local variable in bytes
|
* @return the length of this local variable in bytes
|
||||||
*/
|
*/
|
||||||
public short getLength() {
|
public int getLength() {
|
||||||
return length;
|
return length & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,8 +130,8 @@ public class LocalVariableJava implements StructConverter {
|
|||||||
* name denoting a local variable.
|
* name denoting a local variable.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getNameIndex() {
|
public int getNameIndex() {
|
||||||
return nameIndex;
|
return nameIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,8 +141,8 @@ public class LocalVariableJava implements StructConverter {
|
|||||||
* encoding the type of a local variable in the source program.
|
* encoding the type of a local variable in the source program.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getDescriptorIndex() {
|
public int getDescriptorIndex() {
|
||||||
return descriptorIndex;
|
return descriptorIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,18 +153,18 @@ public class LocalVariableJava implements StructConverter {
|
|||||||
* index and index + 1.
|
* index and index + 1.
|
||||||
* @return index in the local variable array
|
* @return index in the local variable array
|
||||||
*/
|
*/
|
||||||
public short getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
Structure structure = new StructureDataType( "local_variable", 0 );
|
Structure structure = new StructureDataType("local_variable", 0);
|
||||||
structure.add( WORD, "start_pc", null );
|
structure.add(WORD, "start_pc", null);
|
||||||
structure.add( WORD, "length", null );
|
structure.add(WORD, "length", null);
|
||||||
structure.add( WORD, "name_index", null );
|
structure.add(WORD, "name_index", null);
|
||||||
structure.add( WORD, "descriptor_index", null );
|
structure.add(WORD, "descriptor_index", null);
|
||||||
structure.add( WORD, "index", null );
|
structure.add(WORD, "index", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-13
@@ -15,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
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.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -53,28 +53,29 @@ import java.io.IOException;
|
|||||||
public class LocalVariableTableAttribute extends AbstractAttributeInfo {
|
public class LocalVariableTableAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
private short localVariableTableLength;
|
private short localVariableTableLength;
|
||||||
private LocalVariableJava [] localVariableTable;
|
private LocalVariableJava[] localVariableTable;
|
||||||
|
|
||||||
public LocalVariableTableAttribute( BinaryReader reader, AbstractConstantPoolInfoJava [] constantPool ) throws IOException {
|
public LocalVariableTableAttribute(BinaryReader reader,
|
||||||
super( reader );
|
AbstractConstantPoolInfoJava[] constantPool) throws IOException {
|
||||||
|
super(reader);
|
||||||
|
|
||||||
localVariableTableLength = reader.readNextShort();
|
localVariableTableLength = reader.readNextShort();
|
||||||
localVariableTable = new LocalVariableJava[ localVariableTableLength ];
|
localVariableTable = new LocalVariableJava[localVariableTableLength & 0xffff];
|
||||||
for ( int i = 0 ; i < localVariableTableLength ; i++ ) {
|
for (int i = 0; i < (localVariableTableLength & 0xffff); i++) {
|
||||||
localVariableTable[ i ] = new LocalVariableJava( reader );
|
localVariableTable[i] = new LocalVariableJava(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalVariableJava [] getLocalVariables() {
|
public LocalVariableJava[] getLocalVariables() {
|
||||||
return localVariableTable;
|
return localVariableTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "LocalVariableTable_attribute" );
|
StructureDataType structure = getBaseStructure("LocalVariableTable_attribute");
|
||||||
structure.add( WORD, "local_variable_table_length", null );
|
structure.add(WORD, "local_variable_table_length", null);
|
||||||
for ( int i = 0 ; i < localVariableTable.length ; ++i ) {
|
for (int i = 0; i < localVariableTable.length; ++i) {
|
||||||
structure.add( localVariableTable[ i ].toDataType(), "local_variable_" + i, null );
|
structure.add(localVariableTable[i].toDataType(), "local_variable_" + i, null);
|
||||||
}
|
}
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|||||||
+478
@@ -0,0 +1,478 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.javaclass.format.constantpool.*;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: text in comments taken from jvms12.pdf
|
||||||
|
* <p>
|
||||||
|
* The {@code Module} attribute indicates:
|
||||||
|
* <ul>
|
||||||
|
* <li> the modules required by a module </li>
|
||||||
|
* <li> the packages exported and opened by a module </li>
|
||||||
|
* <li> the services used and provided by a module </li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class ModuleAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
|
private short module_name_index;
|
||||||
|
private short module_flags;
|
||||||
|
private short module_version_index;
|
||||||
|
private short requires_count;
|
||||||
|
private ModuleAttributeRequires[] moduleAttributeRequires;
|
||||||
|
private short exports_count;
|
||||||
|
private ModuleAttributeExports[] moduleAttributeExports;
|
||||||
|
private short opens_count;
|
||||||
|
private ModuleAttributeOpens[] moduleAttributeOpens;
|
||||||
|
private short uses_count;
|
||||||
|
private short[] uses_index;
|
||||||
|
private short provides_count;
|
||||||
|
private ModuleAttributeProvides[] moduleAttributeProvides;
|
||||||
|
|
||||||
|
protected ModuleAttribute(BinaryReader reader) throws IOException {
|
||||||
|
super(reader);
|
||||||
|
module_name_index = reader.readNextShort();
|
||||||
|
module_flags = reader.readNextShort();
|
||||||
|
module_version_index = reader.readNextShort();
|
||||||
|
requires_count = reader.readNextShort();
|
||||||
|
moduleAttributeRequires = new ModuleAttributeRequires[getRequiresCount()];
|
||||||
|
for (int i = 0; i < getRequiresCount(); i++) {
|
||||||
|
moduleAttributeRequires[i] = new ModuleAttributeRequires(reader);
|
||||||
|
}
|
||||||
|
exports_count = reader.readNextShort();
|
||||||
|
moduleAttributeExports = new ModuleAttributeExports[getExportsCount()];
|
||||||
|
for (int i = 0; i < getExportsCount(); i++) {
|
||||||
|
moduleAttributeExports[i] = new ModuleAttributeExports(reader);
|
||||||
|
}
|
||||||
|
opens_count = reader.readNextShort();
|
||||||
|
moduleAttributeOpens = new ModuleAttributeOpens[getOpensCount()];
|
||||||
|
for (int i = 0; i < getOpensCount(); i++) {
|
||||||
|
moduleAttributeOpens[i] = new ModuleAttributeOpens(reader);
|
||||||
|
}
|
||||||
|
uses_count = reader.readNextShort();
|
||||||
|
uses_index = new short[getUsesCount()];
|
||||||
|
for (int i = 0; i < getUsesCount(); i++) {
|
||||||
|
uses_index[i] = reader.readNextShort();
|
||||||
|
}
|
||||||
|
provides_count = reader.readNextShort();
|
||||||
|
moduleAttributeProvides = new ModuleAttributeProvides[getProvidesCount()];
|
||||||
|
for (int i = 0; i < getProvidesCount(); i++) {
|
||||||
|
moduleAttributeProvides[i] = new ModuleAttributeProvides(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code module_name_index}, which must be a valid index into the constant pool.
|
||||||
|
* The constant_pool entry at that index must be a {@link ConstantPoolModuleInfo} structure
|
||||||
|
* denoting the current module.
|
||||||
|
* @return the module name index
|
||||||
|
*/
|
||||||
|
public int getModuleNameIndex() {
|
||||||
|
return module_name_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code module_flags} item is as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li> 0x0020 (ACC_OPEN): indicates that this module is open </li>
|
||||||
|
* <li> 0x10000 (ACC_SYNTHETIC): Indicates that this module was not explicitly or implicitly
|
||||||
|
* declared </li>
|
||||||
|
* <li> 0x8000 (ACC_MANDATED) indicates that this module was implicitly declared </li>
|
||||||
|
* </ul>
|
||||||
|
* @return the module flags
|
||||||
|
*/
|
||||||
|
public int getModuleFlags() {
|
||||||
|
return module_flags & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code module_version_index} item must be either zero or a valid index
|
||||||
|
* into the constant pool table. If the value is zero, no version information about the
|
||||||
|
* current module is present. If the value is nonzero, the constant pool entry at that index
|
||||||
|
* must be a {@link ConstantPoolUtf8Info} structure representing the version of the current module.
|
||||||
|
* @return the module version index.
|
||||||
|
*/
|
||||||
|
public int getModuleVersionIndex() {
|
||||||
|
return module_version_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code requires_count} item indicates the number of entries in the
|
||||||
|
* {@code requires} table.
|
||||||
|
* @return the requires count
|
||||||
|
*/
|
||||||
|
public int getRequiresCount() {
|
||||||
|
return requires_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the number of entries in the exports table
|
||||||
|
* @return the exports count
|
||||||
|
*/
|
||||||
|
public int getExportsCount() {
|
||||||
|
return exports_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code opens_count} indicates the number of entries in the {@code opens} table.
|
||||||
|
* @return the opens count
|
||||||
|
*/
|
||||||
|
public int getOpensCount() {
|
||||||
|
return opens_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code uses_count} indicates the number of entries in the {@code uses_index} table.
|
||||||
|
* @return {@code uses_count}
|
||||||
|
*/
|
||||||
|
public int getUsesCount() {
|
||||||
|
return uses_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of each entry in the uses_index table must be a valid index into the constant
|
||||||
|
* pool. The entry at that index must be a {@link ConstantPoolClassInfo} structure representing
|
||||||
|
* a service interface which the current module may discover via {@link java.util.ServiceLoader}.
|
||||||
|
* @param i entry
|
||||||
|
* @return index at entry {@code i}
|
||||||
|
*/
|
||||||
|
public int getUsesEntry(int i) {
|
||||||
|
return uses_index[i] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code provides_count} indicates the number of entries in the {@code provides} table.
|
||||||
|
* @return {@code provides_count}
|
||||||
|
*/
|
||||||
|
public int getProvidesCount() {
|
||||||
|
return provides_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType structure = getBaseStructure("Module_attribute");
|
||||||
|
structure.add(WORD, "module_name_index", null);
|
||||||
|
structure.add(WORD, "module_flags", null);
|
||||||
|
structure.add(WORD, "module_version_index", null);
|
||||||
|
structure.add(WORD, "requires_count", null);
|
||||||
|
for (int i = 0; i < getRequiresCount(); i++) {
|
||||||
|
structure.add(moduleAttributeRequires[i].toDataType(), "requires_" + i, null);
|
||||||
|
}
|
||||||
|
structure.add(WORD, "exports_count", null);
|
||||||
|
for (int i = 0; i < getExportsCount(); i++) {
|
||||||
|
structure.add(moduleAttributeExports[i].toDataType(), "exports_" + i, null);
|
||||||
|
}
|
||||||
|
structure.add(WORD, "opens_count", null);
|
||||||
|
for (int i = 0; i < getOpensCount(); i++) {
|
||||||
|
structure.add(moduleAttributeOpens[i].toDataType(), "opens_" + i, null);
|
||||||
|
}
|
||||||
|
structure.add(WORD, "uses_count", null);
|
||||||
|
for (int i = 0; i < getUsesCount(); i++) {
|
||||||
|
structure.add(WORD, "uses_" + i, null);
|
||||||
|
}
|
||||||
|
structure.add(WORD, "provides_count", null);
|
||||||
|
for (int i = 0; i < getProvidesCount(); i++) {
|
||||||
|
structure.add(WORD, "provides_" + i, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Objects of this class specify a dependence of the current module.
|
||||||
|
*/
|
||||||
|
static class ModuleAttributeRequires implements StructConverter {
|
||||||
|
|
||||||
|
private short requires_index;
|
||||||
|
private short requires_flags;
|
||||||
|
private short requires_version_index;
|
||||||
|
|
||||||
|
public ModuleAttributeRequires(BinaryReader reader) throws IOException {
|
||||||
|
requires_index = reader.readNextShort();
|
||||||
|
requires_flags = reader.readNextShort();
|
||||||
|
requires_version_index = reader.readNextShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code requires_index} item must be a valid index into
|
||||||
|
* the constant pool. The entry at that index must be a {@link ConstantPoolModuleInfo} structure
|
||||||
|
* denoting a module that the current module depends on.
|
||||||
|
* @return the requires index
|
||||||
|
*/
|
||||||
|
public int getRequiresIndex() {
|
||||||
|
return requires_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code requires_flags} item is as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li> 0x0020 ACC_TRANSITIVE </li>
|
||||||
|
* <li> 0x0040 ACC_STATIC_PHASE </li>
|
||||||
|
* <li> 0x1000 ACC_SYNTHETIC </li>
|
||||||
|
* <li> 0x8000 ACC_MANDATED </li>
|
||||||
|
* </ul>
|
||||||
|
* @return the requires flags
|
||||||
|
*/
|
||||||
|
public short getRequiresFlags() {
|
||||||
|
return requires_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be either 0 or a valid index into the constant pool. If the value of the
|
||||||
|
* item is nonzero, the constant pool entry at that index must be a {@link ConstantPoolUtf8Info}
|
||||||
|
* structure representing the version of the module specified by {@code requires_index}.
|
||||||
|
* @return requires_index
|
||||||
|
*/
|
||||||
|
public int getRequiresVersionIndex() {
|
||||||
|
return requires_version_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
Structure structure = new StructureDataType("requires", 0);
|
||||||
|
structure.add(WORD, "requires_index", null);
|
||||||
|
structure.add(WORD, "requires_flags", null);
|
||||||
|
structure.add(WORD, "requires_version_index", null);
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each entry in the {@code exports} table specifies a package exported by the current module.
|
||||||
|
*/
|
||||||
|
static class ModuleAttributeExports implements StructConverter {
|
||||||
|
|
||||||
|
private short exports_index;
|
||||||
|
private short exports_flags;
|
||||||
|
private short exports_to_count;
|
||||||
|
private short[] exports_to_index;
|
||||||
|
|
||||||
|
public ModuleAttributeExports(BinaryReader reader) throws IOException {
|
||||||
|
exports_index = reader.readNextShort();
|
||||||
|
exports_flags = reader.readNextShort();
|
||||||
|
exports_to_count = reader.readNextShort();
|
||||||
|
exports_to_index = new short[getExportsToCount()];
|
||||||
|
for (int i = 0; i < getExportsToCount(); i++) {
|
||||||
|
exports_to_index[i] = reader.readNextShort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code exports_index} must be a valid index into the constant pool. The
|
||||||
|
* entry at that index must be a {@link ConstantPoolPackageInfo} structure
|
||||||
|
* representing a package exported by the current module.
|
||||||
|
* @return exports_index
|
||||||
|
*/
|
||||||
|
public int getExportsIndex() {
|
||||||
|
return exports_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of {@code exports_flags} is as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li> 0x1000 (ACC_SYNTHETIC) </li>
|
||||||
|
* <li> 0x8000 (ACC_MANDATED) </li>
|
||||||
|
* </ul>
|
||||||
|
* @return exports_flags
|
||||||
|
*/
|
||||||
|
public short getExportsFlags() {
|
||||||
|
return exports_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code exports_to_count} indicates the number of entries in the
|
||||||
|
* {@code exports_to_index} table
|
||||||
|
* @return {@code exports_to_count}
|
||||||
|
*/
|
||||||
|
public int getExportsToCount() {
|
||||||
|
return exports_to_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of each entry in the {@cod exports_to_index} must be a valid index
|
||||||
|
* into the constant pool. The entry at that index must be a {@link ConstantPoolModuleInfo}
|
||||||
|
* structure denoting a module whose code can access the types and members in this exported
|
||||||
|
* package
|
||||||
|
* @param i the entry to retrieve
|
||||||
|
* @return module index
|
||||||
|
*/
|
||||||
|
public int getExportsToEntry(int i) {
|
||||||
|
return exports_to_index[i] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
Structure structure = new StructureDataType("exports", 0);
|
||||||
|
structure.add(WORD, "exports_index", null);
|
||||||
|
structure.add(WORD, "exports_flags", null);
|
||||||
|
structure.add(WORD, "exports_to_counts", null);
|
||||||
|
for (int i = 0; i < getExportsToCount(); i++) {
|
||||||
|
structure.add(WORD, "exports_to_index_" + i, null);
|
||||||
|
}
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object of this class specifies a package opened by the current module.
|
||||||
|
*/
|
||||||
|
static class ModuleAttributeOpens implements StructConverter {
|
||||||
|
|
||||||
|
private short opens_index;
|
||||||
|
private short opens_flags;
|
||||||
|
private short opens_to_count;
|
||||||
|
private short[] opens_to_index;
|
||||||
|
|
||||||
|
public ModuleAttributeOpens(BinaryReader reader) throws IOException {
|
||||||
|
opens_index = reader.readNextShort();
|
||||||
|
opens_flags = reader.readNextShort();
|
||||||
|
opens_to_count = reader.readNextShort();
|
||||||
|
opens_to_index = new short[getOpensToCount()];
|
||||||
|
for (int i = 0; i < getOpensToCount(); i++) {
|
||||||
|
opens_to_index[i] = reader.readNextShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code opens_index} must be a valid index into the constant pool. The entry at this
|
||||||
|
* index must be a {@link ConstantPoolPackageInfo} structure representing a package
|
||||||
|
* opened by the current module.
|
||||||
|
* @return {@code opens_index}
|
||||||
|
*/
|
||||||
|
public int getOpensIndex() {
|
||||||
|
return opens_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of {@code opens_flags} is as follows:
|
||||||
|
* <ul>
|
||||||
|
* <li> 0x1000 (ACC_SYNTHETIC) </li>
|
||||||
|
* <li> 0x8000 (ACC_MANDATED) </li>
|
||||||
|
* </ul>
|
||||||
|
* @return {@code opens_flags}
|
||||||
|
*/
|
||||||
|
public short getOpensFlags() {
|
||||||
|
return opens_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code opens_to_count} indicates the number of entries in the {@code opens_to_index}
|
||||||
|
* table.
|
||||||
|
* @return {@code opens_to_count}
|
||||||
|
*/
|
||||||
|
public int getOpensToCount() {
|
||||||
|
return opens_to_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each entry in the {@code opens_to_index} table must be a valid index into
|
||||||
|
* the constant pool. The entry at that index must be a {@link ConstantPoolModuleInfo} structure
|
||||||
|
* denoting a module whose code can access the types and members in this opened package.
|
||||||
|
* @param i desired entry
|
||||||
|
* @return index
|
||||||
|
*/
|
||||||
|
public int getOpensToEntry(int i) {
|
||||||
|
return opens_to_index[i] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
Structure structure = new StructureDataType("exports", 0);
|
||||||
|
structure.add(WORD, "opens_index", null);
|
||||||
|
structure.add(WORD, "opens_flags", null);
|
||||||
|
structure.add(WORD, "opens_to_counts", null);
|
||||||
|
for (int i = 0; i < getOpensToCount(); i++) {
|
||||||
|
structure.add(WORD, "opens_to_index_" + i, null);
|
||||||
|
}
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each entry in the {@code provides} table represents a service implementation for a
|
||||||
|
* given service interface.
|
||||||
|
*/
|
||||||
|
static class ModuleAttributeProvides implements StructConverter {
|
||||||
|
|
||||||
|
private short provides_index;
|
||||||
|
private short provides_with_count;
|
||||||
|
private short[] provides_with_index;
|
||||||
|
|
||||||
|
public ModuleAttributeProvides(BinaryReader reader) throws IOException {
|
||||||
|
provides_index = reader.readNextShort();
|
||||||
|
provides_with_count = reader.readNextShort();
|
||||||
|
provides_with_index = new short[getProvidesWithCount()];
|
||||||
|
for (int i = 0; i < getProvidesWithCount(); i++) {
|
||||||
|
provides_with_index[i] = reader.readNextShort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code provides_index} must be a valid index into the constant pool. The entry
|
||||||
|
* at that index must be a {@link ConstantPoolClassInfo} structure representing a
|
||||||
|
* service interface for which the current module provides a service implementation.
|
||||||
|
* @return {@code provides_index}
|
||||||
|
*/
|
||||||
|
public int getProvidesIndex() {
|
||||||
|
return provides_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code provides_with_count} indicates the number of entries in the {@code provides_with_index} table
|
||||||
|
* @return {@code provides_with_count}
|
||||||
|
*/
|
||||||
|
public int getProvidesWithCount() {
|
||||||
|
return provides_with_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of each entry in the {@code provides_with_index} table must be a valid
|
||||||
|
* index into the constant pool. The entry at that index must be a {@link ConstantPoolClassInfo}
|
||||||
|
* structure representing a service implementation for the service interface specified by
|
||||||
|
* {@code provides_index}.
|
||||||
|
* @param i entry
|
||||||
|
* @return index
|
||||||
|
*/
|
||||||
|
public int getProvidesWithIndexEntry(int i) {
|
||||||
|
return provides_with_index[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
Structure structure = new StructureDataType("provides", 0);
|
||||||
|
structure.add(WORD, "provides_index", null);
|
||||||
|
structure.add(WORD, "provides_with_counts", null);
|
||||||
|
for (int i = 0; i < getProvidesWithCount(); i++) {
|
||||||
|
structure.add(WORD, "provides_with_index_" + i, null);
|
||||||
|
}
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.javaclass.format.constantpool.ConstantPoolClassInfo;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.StructureDataType;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: text based on/taken from jvms12.pdf
|
||||||
|
* <p>
|
||||||
|
* Objects of this class indicate the main class of a module.
|
||||||
|
*/
|
||||||
|
public class ModuleMainClassAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
|
private short main_class_index;
|
||||||
|
|
||||||
|
protected ModuleMainClassAttribute(BinaryReader reader) throws IOException {
|
||||||
|
super(reader);
|
||||||
|
main_class_index = reader.readNextShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code main_class index} must be a valid index into the constant pool. The entry at
|
||||||
|
* that index must be a {@link ConstantPoolClassInfo} structure representing the main
|
||||||
|
* class of the current module.
|
||||||
|
* @return index of main class.
|
||||||
|
*/
|
||||||
|
public int getMainClassIndex() {
|
||||||
|
return main_class_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType structure = getBaseStructure("ModuleMainClass_attribute");
|
||||||
|
structure.add(WORD, "main_class_index", null);
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.javaclass.format.constantpool.ConstantPoolPackageInfo;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.StructureDataType;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: text in this file based on/taken from jvms12.pdf
|
||||||
|
* <p>
|
||||||
|
* The {@code ModulePackages} attribute indicates all the packages of a module that are
|
||||||
|
* exported or opened by the {@code Module} attribute, as well as all the package of the service
|
||||||
|
* implementations recored in the {@code Module} attribute.
|
||||||
|
*/
|
||||||
|
public class ModulePackagesAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
|
private short package_count;
|
||||||
|
private short[] package_index;
|
||||||
|
|
||||||
|
protected ModulePackagesAttribute(BinaryReader reader) throws IOException {
|
||||||
|
super(reader);
|
||||||
|
package_count = reader.readNextShort();
|
||||||
|
package_index = new short[getPackageCount()];
|
||||||
|
for (short i = 0; i < getPackageCount(); i++) {
|
||||||
|
package_index[i] = reader.readNextShort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code package_count} item indicates the number of entries
|
||||||
|
* in the {@code package_index} table
|
||||||
|
* @return {@code package_index}
|
||||||
|
*/
|
||||||
|
public int getPackageCount() {
|
||||||
|
return package_count & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of each entry in the {@code package_index} table must be a valid index
|
||||||
|
* into the constant pool. The entry at that index must be a {@link ConstantPoolPackageInfo}
|
||||||
|
* structure representing a package in the current module.
|
||||||
|
* @param i entry
|
||||||
|
* @return package index
|
||||||
|
*/
|
||||||
|
public int getPackageIndexEntry(int i) {
|
||||||
|
return package_index[i] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType structure = getBaseStructure("ModulePackages_attribute");
|
||||||
|
structure.add(WORD, "package_count", null);
|
||||||
|
for (int i = 0; i < package_index.length; ++i) {
|
||||||
|
structure.add(WORD, "classes" + i, null);
|
||||||
|
}
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.javaclass.format.constantpool.ConstantPoolClassInfo;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.StructureDataType;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: text taken from/based on jvms12.pdf
|
||||||
|
* <p>
|
||||||
|
* The {@code NestHost} attribute records the nest host of the next to which the current
|
||||||
|
* class or interface claims to belong.
|
||||||
|
*/
|
||||||
|
public class NestHostAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
|
private short host_class_index;
|
||||||
|
|
||||||
|
protected NestHostAttribute(BinaryReader reader) throws IOException {
|
||||||
|
super(reader);
|
||||||
|
host_class_index = reader.readNextShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code host_class_index} item must be a valid index into the constant
|
||||||
|
* pool. The entry at that index must be a {@link ConstantPoolClassInfo} structure representing
|
||||||
|
* a class or interface which is the nest host for the current class or interface.
|
||||||
|
* @return {@code host_class_index}
|
||||||
|
*/
|
||||||
|
public int getHostClassIndex() {
|
||||||
|
return host_class_index & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType structure = getBaseStructure("NestHost_attribute");
|
||||||
|
structure.add(WORD, "host_class_index", null);
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.javaclass.format.constantpool.ConstantPoolClassInfo;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
|
import ghidra.program.model.data.StructureDataType;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: text taken from/based on jvms12.pdf
|
||||||
|
* <p>
|
||||||
|
* The {@NestMembers} attribute records the classes and interfaces that are authorized to
|
||||||
|
* claim membership in the nest hosted by the current class or interface.
|
||||||
|
*/
|
||||||
|
public class NestMembersAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
|
private short number_of_classes;
|
||||||
|
private short[] classes;
|
||||||
|
|
||||||
|
protected NestMembersAttribute(BinaryReader reader) throws IOException {
|
||||||
|
super(reader);
|
||||||
|
number_of_classes = reader.readNextShort();
|
||||||
|
classes = new short[getNumberOfClasses()];
|
||||||
|
for (short i = 0; i < getNumberOfClasses(); i++) {
|
||||||
|
classes[i] = reader.readNextShort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the {@code number_of_classes} item indicates the number of entries in
|
||||||
|
* the {@code classes} array.
|
||||||
|
* @return {@code number_of_classes}
|
||||||
|
*/
|
||||||
|
public int getNumberOfClasses() {
|
||||||
|
return number_of_classes & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each value in the {@code classes} array must be a valid index into the constant pool.
|
||||||
|
* The constant pool entry at that index must be a {@link ConstantPoolClassInfo} structure
|
||||||
|
* representing a class or interface which is a member of the nest hosted by the current
|
||||||
|
* class or interface.
|
||||||
|
* @param i entry
|
||||||
|
* @return class index
|
||||||
|
*/
|
||||||
|
public int getClassesEntry(int i) {
|
||||||
|
return classes[i] & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
|
StructureDataType structure = getBaseStructure("NestMembers_attribute");
|
||||||
|
structure.add(WORD, "number_of_classes", null);
|
||||||
|
for (int i = 0; i < classes.length; ++i) {
|
||||||
|
structure.add(WORD, "classes" + i, null);
|
||||||
|
}
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+16
-16
@@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -52,17 +52,17 @@ import java.io.IOException;
|
|||||||
public class RuntimeInvisibleAnnotationsAttribute extends AbstractAttributeInfo {
|
public class RuntimeInvisibleAnnotationsAttribute extends AbstractAttributeInfo {
|
||||||
|
|
||||||
private short numberOfAnnotations;
|
private short numberOfAnnotations;
|
||||||
private AnnotationJava [] annotations;
|
private AnnotationJava[] annotations;
|
||||||
|
|
||||||
public RuntimeInvisibleAnnotationsAttribute( BinaryReader reader ) throws IOException {
|
public RuntimeInvisibleAnnotationsAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
|
|
||||||
numberOfAnnotations = reader.readNextShort();
|
numberOfAnnotations = reader.readNextShort();
|
||||||
|
|
||||||
annotations = new AnnotationJava[ numberOfAnnotations ];
|
annotations = new AnnotationJava[getNumberOfAnnotations()];
|
||||||
|
|
||||||
for ( int i = 0 ; i < numberOfAnnotations ; ++i ) {
|
for (int i = 0; i < getNumberOfAnnotations(); ++i) {
|
||||||
annotations[ i ] = new AnnotationJava( reader );
|
annotations[i] = new AnnotationJava(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,8 +74,8 @@ public class RuntimeInvisibleAnnotationsAttribute extends AbstractAttributeInfo
|
|||||||
* may be directly attached to a program element.
|
* may be directly attached to a program element.
|
||||||
* @return the number of runtime-visible annotations
|
* @return the number of runtime-visible annotations
|
||||||
*/
|
*/
|
||||||
public short getNumberOfAnnotations() {
|
public int getNumberOfAnnotations() {
|
||||||
return numberOfAnnotations;
|
return numberOfAnnotations & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,17 +83,17 @@ public class RuntimeInvisibleAnnotationsAttribute extends AbstractAttributeInfo
|
|||||||
* annotation on a program element.
|
* annotation on a program element.
|
||||||
* @return the annotations table
|
* @return the annotations table
|
||||||
*/
|
*/
|
||||||
public AnnotationJava [] getAnnotations() {
|
public AnnotationJava[] getAnnotations() {
|
||||||
return annotations;
|
return annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = "RuntimeInvisibleAnnotations_attribute" +"|" + numberOfAnnotations + "|";
|
String name = "RuntimeInvisibleAnnotations_attribute" + "|" + numberOfAnnotations + "|";
|
||||||
StructureDataType structure = getBaseStructure( name );
|
StructureDataType structure = getBaseStructure(name);
|
||||||
structure.add( WORD, "num_annotations", null );
|
structure.add(WORD, "num_annotations", null);
|
||||||
for ( int i = 0 ; i < annotations.length ; ++i ) {
|
for (int i = 0; i < annotations.length; ++i) {
|
||||||
structure.add( annotations[ i ].toDataType(), "annotation_" + i, null );
|
structure.add(annotations[i].toDataType(), "annotation_" + i, null);
|
||||||
}
|
}
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-26
@@ -15,15 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -65,22 +65,24 @@ public class RuntimeParameterAnnotationsAttribute extends AbstractAttributeInfo
|
|||||||
private boolean _isVisible;
|
private boolean _isVisible;
|
||||||
|
|
||||||
private byte numberOfParameters;
|
private byte numberOfParameters;
|
||||||
private Map<Integer, AnnotationJava []> parameterAnnotations = new HashMap<Integer, AnnotationJava []>();
|
private Map<Integer, AnnotationJava[]> parameterAnnotations =
|
||||||
|
new HashMap<Integer, AnnotationJava[]>();
|
||||||
|
|
||||||
public RuntimeParameterAnnotationsAttribute( BinaryReader reader, boolean isVisible ) throws IOException {
|
public RuntimeParameterAnnotationsAttribute(BinaryReader reader, boolean isVisible)
|
||||||
super( reader );
|
throws IOException {
|
||||||
|
super(reader);
|
||||||
|
|
||||||
_isVisible = isVisible;
|
_isVisible = isVisible;
|
||||||
|
|
||||||
numberOfParameters = reader.readNextByte();
|
numberOfParameters = reader.readNextByte();
|
||||||
|
|
||||||
for ( int i = 0 ; i < numberOfParameters ; ++i ) {
|
for (int i = 0; i < getNumberOfParameters(); ++i) {
|
||||||
short numberOfAnnotations = reader.readNextShort();
|
short numberOfAnnotations = reader.readNextShort();
|
||||||
AnnotationJava [] annotations = new AnnotationJava[ numberOfAnnotations ];
|
AnnotationJava[] annotations = new AnnotationJava[(numberOfAnnotations & 0xffff)];
|
||||||
for ( int a = 0 ; a < numberOfAnnotations ; ++a ) {
|
for (int a = 0; a < (numberOfAnnotations & 0xffff); ++a) {
|
||||||
annotations[ a ] = new AnnotationJava( reader );
|
annotations[a] = new AnnotationJava(reader);
|
||||||
}
|
}
|
||||||
parameterAnnotations.put( i, annotations );
|
parameterAnnotations.put(i, annotations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +102,8 @@ public class RuntimeParameterAnnotationsAttribute extends AbstractAttributeInfo
|
|||||||
* (This duplicates information that could be extracted from the method descriptor.)
|
* (This duplicates information that could be extracted from the method descriptor.)
|
||||||
* @return the number of parameters for this method
|
* @return the number of parameters for this method
|
||||||
*/
|
*/
|
||||||
public byte getNumberOfParameters() {
|
public int getNumberOfParameters() {
|
||||||
return numberOfParameters;
|
return numberOfParameters & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,23 +122,23 @@ public class RuntimeParameterAnnotationsAttribute extends AbstractAttributeInfo
|
|||||||
* @param parameter the parameter index
|
* @param parameter the parameter index
|
||||||
* @return the annotations for the given parameter
|
* @return the annotations for the given parameter
|
||||||
*/
|
*/
|
||||||
public AnnotationJava [] getParameterAnnotations( int parameter ) {
|
public AnnotationJava[] getParameterAnnotations(int parameter) {
|
||||||
return parameterAnnotations.get( parameter );
|
return parameterAnnotations.get(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
String name = _isVisible ?
|
String name = _isVisible
|
||||||
"RuntimeVisibleParameterAnnotations_attribute" + "|" + numberOfParameters + "|" :
|
? "RuntimeVisibleParameterAnnotations_attribute" + "|" + numberOfParameters + "|"
|
||||||
"RuntimeInvisibleParameterAnnotations_attribute" + "|" + numberOfParameters + "|";
|
: "RuntimeInvisibleParameterAnnotations_attribute" + "|" + numberOfParameters + "|";
|
||||||
|
|
||||||
StructureDataType structure = getBaseStructure( name );
|
StructureDataType structure = getBaseStructure(name);
|
||||||
structure.add( BYTE, "num_parameters", null );
|
structure.add(BYTE, "num_parameters", null);
|
||||||
for ( int i = 0 ; i < numberOfParameters ; ++i ) {
|
for (int i = 0; i < numberOfParameters; ++i) {
|
||||||
structure.add( WORD, "num_annotations_" + i, null );
|
structure.add(WORD, "num_annotations_" + i, null);
|
||||||
AnnotationJava [] annotations = parameterAnnotations.get( i );
|
AnnotationJava[] annotations = parameterAnnotations.get(i);
|
||||||
for ( int a = 0 ; a < annotations.length ; ++a ) {
|
for (int a = 0; a < annotations.length; ++a) {
|
||||||
structure.add( annotations[ a ].toDataType(), "annotations_" + i + "_" + a, null );
|
structure.add(annotations[a].toDataType(), "annotations_" + i + "_" + a, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-9
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -45,8 +44,8 @@ public class SignatureAttribute extends AbstractAttributeInfo {
|
|||||||
|
|
||||||
private short signatureIndex;
|
private short signatureIndex;
|
||||||
|
|
||||||
public SignatureAttribute( BinaryReader reader ) throws IOException {
|
public SignatureAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
|
|
||||||
signatureIndex = reader.readNextShort();
|
signatureIndex = reader.readNextShort();
|
||||||
}
|
}
|
||||||
@@ -60,14 +59,14 @@ public class SignatureAttribute extends AbstractAttributeInfo {
|
|||||||
* type signature otherwise.
|
* type signature otherwise.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getSignatureIndex() {
|
public int getSignatureIndex() {
|
||||||
return signatureIndex;
|
return signatureIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "Signature_attribute" );
|
StructureDataType structure = getBaseStructure("Signature_attribute");
|
||||||
structure.add( WORD, "signature_index", null );
|
structure.add(WORD, "signature_index", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-9
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.javaclass.format.attributes;
|
package ghidra.javaclass.format.attributes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.StructureDataType;
|
import ghidra.program.model.data.StructureDataType;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
* NOTE: THE FOLLOWING TEXT EXTRACTED FROM JVMS7.PDF
|
||||||
* <p>
|
* <p>
|
||||||
@@ -43,8 +42,8 @@ public class SourceFileAttribute extends AbstractAttributeInfo {
|
|||||||
|
|
||||||
private short sourceFileIndex;
|
private short sourceFileIndex;
|
||||||
|
|
||||||
public SourceFileAttribute( BinaryReader reader ) throws IOException {
|
public SourceFileAttribute(BinaryReader reader) throws IOException {
|
||||||
super( reader );
|
super(reader);
|
||||||
|
|
||||||
sourceFileIndex = reader.readNextShort();
|
sourceFileIndex = reader.readNextShort();
|
||||||
}
|
}
|
||||||
@@ -62,14 +61,14 @@ public class SourceFileAttribute extends AbstractAttributeInfo {
|
|||||||
* at the time the file name is actually used.
|
* at the time the file name is actually used.
|
||||||
* @return a valid index into the constant_pool table
|
* @return a valid index into the constant_pool table
|
||||||
*/
|
*/
|
||||||
public short getSourceFileIndex() {
|
public int getSourceFileIndex() {
|
||||||
return sourceFileIndex;
|
return sourceFileIndex & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType structure = getBaseStructure( "SourceFile_attribute" );
|
StructureDataType structure = getBaseStructure("SourceFile_attribute");
|
||||||
structure.add( WORD, "sourcefile_index", null );
|
structure.add(WORD, "sourcefile_index", null);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user