public static ConstantPoolInfo Read(ClassReader classReader) { ushort tag = classReader.ReadU1(); ConstantPoolInfo constantPoolInfo = null; switch (tag) { case 7: constantPoolInfo = new ConstantClass(); break; case 9: constantPoolInfo = new ConstantFieldRef(); break; case 10: constantPoolInfo = new ConstantMethodRef(); break; case 11: constantPoolInfo = new ConstantInterfaceMethodRef(); break; case 8: constantPoolInfo = new ConstantString(); break; case 3: constantPoolInfo = new ConstantInteger(); break; case 4: constantPoolInfo = new ConstantFloat(); break; case 5: constantPoolInfo = new ConstantLong(); break; case 6: constantPoolInfo = new ConstantDouble(); break; case 12: constantPoolInfo = new ConstantNameAndType(); break; case 1: constantPoolInfo = new ConstantUtf8(); break; case 15: constantPoolInfo = new ConstantMethodHandle(); break; case 16: constantPoolInfo = new ConstantMethodType(); break; case 18: constantPoolInfo = new ConstantInvokeDynamic(); break; default: throw new Exception("ClassFileError:constantPoolInfo incorrect"); } constantPoolInfo.Tag = tag; constantPoolInfo.ReadConstantPoolInfo(classReader); return(constantPoolInfo); }
internal static AttributeInfo FromMemory(IList <ConstantPoolEntry> constantPool, IntPtr ptr, int offset) { Contract.Requires <ArgumentNullException>(constantPool != null, "constantPool"); Contract.Ensures(Contract.Result <AttributeInfo>() != null); ushort attributeNameIndex = ConstantPoolEntry.ByteSwap((ushort)Marshal.ReadInt16(ptr, offset)); uint attributeLength = ConstantPoolEntry.ByteSwap((uint)Marshal.ReadInt32(ptr, offset + sizeof(ushort))); byte[] info = new byte[attributeLength]; Marshal.Copy(ptr + offset + sizeof(ushort) + sizeof(uint), info, 0, (int)attributeLength); ConstantUtf8 entry = (ConstantUtf8)constantPool[attributeNameIndex - 1]; switch (entry.Value) { case "Code": return(new Code(attributeNameIndex, info)); default: return(new UnknownAttributeInfo(entry.Value, attributeNameIndex, info)); } }
public static ImmutableList <int?> GetEvaluationStackDepths(DisassembledMethod disassembledMethod, ReadOnlyCollection <ConstantPoolEntry> constantPool, ReadOnlyCollection <ExceptionTableEntry> exceptionTable) { Contract.Requires <ArgumentNullException>(disassembledMethod != null, "disassembledMethod"); Contract.Requires <ArgumentNullException>(constantPool != null, "constantPool"); Contract.Requires <ArgumentNullException>(exceptionTable != null, "exceptionTable"); Contract.Ensures(Contract.Result <ImmutableList <int?> >() != null); Contract.Ensures(Contract.Result <ImmutableList <int?> >().Count == disassembledMethod.Instructions.Count); int?[] depths = new int?[disassembledMethod.Instructions.Count]; Queue <int> workQueue = new Queue <int>(); // can obviously start at the beginning of the method depths[0] = 0; workQueue.Enqueue(0); // can also start inside each exception handler foreach (var entry in exceptionTable) { int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == entry.HandlerOffset); if (!depths[nextIndex].HasValue) { depths[nextIndex] = 1; workQueue.Enqueue(nextIndex); } } while (workQueue.Count > 0) { int index = workQueue.Dequeue(); JavaInstruction instruction = disassembledMethod.Instructions[index]; int netImpact; List <string> argumentSignatures = null; string returnTypeSignature = null; if (instruction.OpCode.FlowControl == JavaFlowControl.Call) { IConstantMemberReference memberReference = (IConstantMemberReference)constantPool[instruction.Operands.ConstantPoolIndex - 1]; ConstantNameAndType nameAndType = (ConstantNameAndType)constantPool[memberReference.NameAndTypeIndex - 1]; ConstantUtf8 descriptor = (ConstantUtf8)constantPool[nameAndType.DescriptorIndex - 1]; string signature = descriptor.Value; SignatureHelper.ParseMethodSignature(signature, out argumentSignatures, out returnTypeSignature); } switch (instruction.OpCode.StackBehaviorPop) { case JavaStackBehavior.Pop0: netImpact = 0; break; case JavaStackBehavior.Pop1: case JavaStackBehavior.PopI: case JavaStackBehavior.PopI8: case JavaStackBehavior.PopR4: case JavaStackBehavior.PopR8: case JavaStackBehavior.PopRef: netImpact = -1; break; case JavaStackBehavior.Pop1_Pop1: case JavaStackBehavior.PopI_PopI: case JavaStackBehavior.PopI8_PopI8: case JavaStackBehavior.PopI8_PopI: case JavaStackBehavior.PopR4_PopR4: case JavaStackBehavior.PopR8_PopR8: case JavaStackBehavior.PopRef_Pop1: case JavaStackBehavior.PopRef_PopI: netImpact = -2; break; case JavaStackBehavior.PopRef_PopI_PopI: case JavaStackBehavior.PopRef_PopI_PopI8: case JavaStackBehavior.PopRef_PopI_PopR4: case JavaStackBehavior.PopRef_PopI_PopR8: case JavaStackBehavior.PopRef_PopI_PopRef: case JavaStackBehavior.PopRef_PopRef: netImpact = -3; break; case JavaStackBehavior.PopVar: switch (instruction.OpCode.OpCode) { case JavaOpCodeTag.Dup_x2: case JavaOpCodeTag.Dup2: case JavaOpCodeTag.Dup2_x1: case JavaOpCodeTag.Dup2_x2: netImpact = 1; break; case JavaOpCodeTag.Invokestatic: netImpact = -argumentSignatures.Count; if (returnTypeSignature != "V") { netImpact++; } break; case JavaOpCodeTag.Invokeinterface: case JavaOpCodeTag.Invokespecial: case JavaOpCodeTag.Invokevirtual: netImpact = -argumentSignatures.Count - 1; if (returnTypeSignature != "V") { netImpact++; } break; case JavaOpCodeTag.Multianewarray: netImpact = -instruction.Operands.Dimensions; break; default: throw new FormatException(); } break; default: throw new FormatException(); } switch (instruction.OpCode.StackBehaviorPush) { case JavaStackBehavior.Push0: break; case JavaStackBehavior.Push1: case JavaStackBehavior.PushI: case JavaStackBehavior.PushI8: case JavaStackBehavior.PushR4: case JavaStackBehavior.PushR8: case JavaStackBehavior.PushRef: case JavaStackBehavior.PushRet: netImpact++; break; case JavaStackBehavior.Push1_Push1: netImpact += 2; break; case JavaStackBehavior.PushVar: // these are all handled in the pop section break; default: throw new FormatException(); } switch (instruction.OpCode.FlowControl) { case JavaFlowControl.Next: case JavaFlowControl.Break: case JavaFlowControl.Call: case JavaFlowControl.ConditionalBranch: case JavaFlowControl.Special: if (!depths[index + 1].HasValue) { depths[index + 1] = depths[index] + netImpact; workQueue.Enqueue(index + 1); } if (instruction.OpCode.FlowControl == JavaFlowControl.ConditionalBranch) { goto case JavaFlowControl.Branch; } break; case JavaFlowControl.Branch: switch (instruction.OpCode.OpCode) { case JavaOpCodeTag.Lookupswitch: { LookupSwitchData switchData = (LookupSwitchData)disassembledMethod.SwitchData[instruction.Operands.SwitchDataIndex]; foreach (var pair in switchData.Pairs) { int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == instruction.Offset + pair.Value); if (!depths[nextIndex].HasValue) { depths[nextIndex] = depths[index] + netImpact; workQueue.Enqueue(nextIndex); } } break; } case JavaOpCodeTag.Tableswitch: { TableSwitchData switchData = (TableSwitchData)disassembledMethod.SwitchData[instruction.Operands.SwitchDataIndex]; foreach (var offset in switchData.Offsets) { int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == instruction.Offset + offset); if (!depths[nextIndex].HasValue) { depths[nextIndex] = depths[index] + netImpact; workQueue.Enqueue(nextIndex); } } break; } default: { // single branch target int nextIndex = disassembledMethod.Instructions.FindIndex(i => i.Offset == instruction.Offset + instruction.Operands.BranchTarget); if (!depths[nextIndex].HasValue) { depths[nextIndex] = depths[index] + netImpact; workQueue.Enqueue(nextIndex); } break; } } break; case JavaFlowControl.Return: // no work in this method following this instruction break; case JavaFlowControl.Throw: // 'catch' blocks are handled separately break; case JavaFlowControl.Meta: throw new NotImplementedException(); default: throw new FormatException(); } } return(new ImmutableList <int?>(depths)); }
public void AddConstantUtf8(ConstantUtf8 constantUtf8) { constantUtf8s.Add(constantUtf8); router.Add(constantUtf8s.Count); }