Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* MethodReader.java
*
* Copyright (c) 2013 Mike Strobel
*
* This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain;
* and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.assembler.metadata;
import com.strobel.assembler.ir.ErrorOperand;
import com.strobel.assembler.ir.Instruction;
import com.strobel.assembler.ir.InstructionCollection;
import com.strobel.assembler.ir.OpCode;
import com.strobel.assembler.ir.OpCodeHelpers;
import com.strobel.assembler.ir.OperandType;
import com.strobel.assembler.ir.attributes.AttributeNames;
import com.strobel.assembler.ir.attributes.CodeAttribute;
import com.strobel.assembler.ir.attributes.ExceptionTableEntry;
import com.strobel.assembler.ir.attributes.LocalVariableTableAttribute;
import com.strobel.assembler.ir.attributes.LocalVariableTableEntry;
import com.strobel.assembler.ir.attributes.SourceAttribute;
import com.strobel.core.StringUtilities;
import com.strobel.core.VerifyArgument;
import java.lang.reflect.Modifier;
import java.util.List;
import static java.lang.String.format;
public class MethodReader {
private final MethodDefinition _methodDefinition;
private final CodeAttribute _code;
private final IMetadataScope _scope;
private final MethodBody _methodBody;
private final TypeReference _declaringType;
private final int _modifiers;
public MethodReader(final MethodDefinition methodDefinition, final IMetadataScope scope) {
_methodDefinition = VerifyArgument.notNull(methodDefinition, "methodDefinition");
_scope = VerifyArgument.notNull(scope, "scope");
_declaringType = methodDefinition.getDeclaringType();
_modifiers = methodDefinition.getModifiers();
_code = SourceAttribute.find(AttributeNames.Code, methodDefinition.getSourceAttributes());
_methodBody = new MethodBody(methodDefinition);
_methodBody.setCodeSize(_code.getCode().size());
_methodBody.setMaxStackSize(_code.getMaxStack());
_methodBody.setMaxLocals(_code.getMaxLocals());
}
@SuppressWarnings("ConstantConditions")
public MethodBody readBody() {
try {
return readBodyCore();
}
catch (final Throwable t) {
throw new MethodBodyParseException(
format(
"An error occurred while parsing the bytecode of method '%s:%s'.",
_methodDefinition.getFullName(),
_methodDefinition.getSignature()
),
t);
}
}
private MethodBody readBodyCore() {
final Buffer b = _code.getCode();
b.position(0);
final InstructionCollection body = _methodBody.getInstructions();
final VariableDefinitionCollection variables = _methodBody.getVariables();
final LocalVariableTableAttribute localVariableTable = SourceAttribute.find(
AttributeNames.LocalVariableTable,
_code.getAttributes()
);
final LocalVariableTableAttribute localVariableTypeTable = SourceAttribute.find(
AttributeNames.LocalVariableTypeTable,
_code.getAttributes()
);
final boolean hasThis = !Modifier.isStatic(_modifiers);
final List parameters = _methodDefinition.getParameters();
if (hasThis) {
final ParameterDefinition thisParameter = new ParameterDefinition(
0,
"this",
_declaringType
);
final VariableDefinition thisVariable = new VariableDefinition(
0,
"this",
_methodDefinition,
_declaringType
);
thisVariable.setScopeStart(0);
thisVariable.setScopeEnd(_code.getCodeSize());
thisVariable.setFromMetadata(false);
thisVariable.setParameter(thisParameter);
variables.add(thisVariable);
_methodBody.setThisParameter(thisParameter);
}
for (int i = 0; i < parameters.size(); i++) {
final ParameterDefinition parameter = parameters.get(i);
final int variableSlot = parameter.getSlot();
final VariableDefinition variable = new VariableDefinition(
variableSlot,
parameter.getName(),
_methodDefinition,
parameter.getParameterType()
);
variable.setScopeStart(0);
variable.setScopeEnd(_code.getCodeSize());
variable.setTypeKnown(true);
variable.setFromMetadata(false);
variable.setParameter(parameter);
variables.add(variable);
}
if (localVariableTable != null) {
processLocalVariableTable(variables, localVariableTable, parameters);
}
if (localVariableTypeTable != null) {
processLocalVariableTable(variables, localVariableTypeTable, parameters);
}
for (final VariableDefinition variable : variables) {
if (!variable.isFromMetadata()) {
variable.setScopeStart(-1);
variable.setScopeEnd(-1);
}
}
@SuppressWarnings("unchecked")
final Fixup[] fixups = new Fixup[b.size()];
while (b.position() < b.size()) {
final int offset = b.position();
int code = b.readUnsignedByte();
if (code == OpCode.WIDE) {
code = code << 8 | b.readUnsignedByte();
}
final OpCode op = OpCode.get(code);
final Instruction instruction;
switch (op.getOperandType()) {
case None: {
if (op.isLoad() || op.isStore()) {
variables.reference(OpCodeHelpers.getLoadStoreMacroArgumentIndex(op), op, offset);
}
instruction = Instruction.create(op);
break;
}
case PrimitiveTypeCode: {
instruction = Instruction.create(op, BuiltinTypes.fromPrimitiveTypeCode(b.readUnsignedByte()));
break;
}
case TypeReference: {
final int typeToken = b.readUnsignedShort();
instruction = Instruction.create(op, _scope.lookupType(typeToken));
break;
}
case TypeReferenceU1: {
instruction = Instruction.create(op, _scope.lookupType(b.readUnsignedShort()), b.readUnsignedByte());
break;
}
case DynamicCallSite: {
instruction = Instruction.create(op, _scope.lookupDynamicCallSite(b.readUnsignedShort()));
b.readUnsignedByte();
b.readUnsignedByte();
break;
}
case MethodReference: {
instruction = Instruction.create(op, _scope.lookupMethod(b.readUnsignedShort()));
if (op == OpCode.INVOKEINTERFACE) {
b.readUnsignedByte();
b.readUnsignedByte();
}
break;
}
case FieldReference: {
instruction = Instruction.create(op, _scope.lookupField(b.readUnsignedShort()));
break;
}
case BranchTarget:
case BranchTargetWide: {
final int targetOffset;
instruction = new Instruction(op);
if (op.isWide()) {
targetOffset = offset + _scope.lookupConstant(b.readUnsignedShort());
}
else if (op.getOperandType() == OperandType.BranchTargetWide) {
targetOffset = offset + b.readInt();
}
else {
targetOffset = offset + (int) b.readShort();
}
if (targetOffset < offset) {
final Instruction target = body.atOffset(targetOffset);
if (!target.hasLabel()) {
target.setLabel(new Label(targetOffset));
}
instruction.setOperand(target);
}
else if (targetOffset == offset) {
instruction.setOperand(instruction);
instruction.setLabel(new Label(offset));
}
else if (targetOffset > b.size()) {
//
// Target is a label after the last instruction. Insert a dummy NOP.
//
instruction.setOperand(new Instruction(targetOffset, OpCode.NOP));
}
else {
final Fixup oldFixup = fixups[targetOffset];
final Fixup newFixup = new Fixup() {
@Override
public void fix(final Instruction target) {
instruction.setOperand(target);
}
};
fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
: newFixup;
}
break;
}
case I1: {
instruction = Instruction.create(op, b.readByte());
break;
}
case I2: {
instruction = Instruction.create(op, b.readShort());
break;
}
case I8: {
instruction = Instruction.create(op, b.readLong());
break;
}
case Constant: {
//noinspection RedundantTypeArguments
instruction = new Instruction(op, _scope.