Java Code Examples for org.objectweb.asm.tree.analysis.Frame#getLocal()
The following examples show how to use
org.objectweb.asm.tree.analysis.Frame#getLocal() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SimpleStringEncryptionTransformer.java From deobfuscator with Apache License 2.0 | 5 votes |
private AbstractInsnNode getSource(MethodNode methodNode, Frame<SourceValue>[] frames, AbstractInsnNode now, int... wants) { Frame<SourceValue> currentFrame = frames[methodNode.instructions.indexOf(now)]; SourceValue currentValue; for (int want : wants) if (want == now.getOpcode()) return now; switch (now.getOpcode()) { case ALOAD: { currentValue = currentFrame.getLocal(((VarInsnNode) now).var); break; } case ASTORE: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } case DUP: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } case PUTSTATIC: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } case SWAP: { currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1); break; } default: { oops("Unexpected opcode {}", now.getOpcode()); return null; } } if (currentValue.insns.size() != 1) { oops("Expected 1 source insn, found {}", TransformerHelper.insnsToString(currentValue.insns)); return null; } return getSource(methodNode, frames, currentValue.insns.iterator().next(), wants); }
Example 2
Source File: Variables.java From Recaf with MIT License | 4 votes |
/** * Fills missing index-to-descriptor mappings. * * @param labels * Map of label names to instances. * @param frames * Stack-frame analysis data. * * @throws AssemblerException * When multiple types for a single variable have conflicting array-levels. */ void visitWithFrames(Frame<AbstractValue>[] frames, Map<String, LabelNode> labels) throws AssemblerException { // TODO: Reuse variable slots of the same sort if the scope of the variables do not collide for(Map.Entry<String, Integer> entry : nameToIndex.entrySet()) { // Skip already visitied String name = entry.getKey(); String startName = nameToStart.get(name); String endName = nameToEnd.get(name); LabelNode start = labels.get(startName); LabelNode end = labels.get(endName); if (start == null || end == null) continue; // Collect the types stored in this index Set<Type> types = new HashSet<>(); int index = entry.getValue(); for(Frame<AbstractValue> frame : frames) { if(frame == null) continue; AbstractValue value = frame.getLocal(index); if(value != null && value.getType() != null) types.add(value.getType()); } Iterator<Type> it = types.iterator(); // If we don't have type information, abort for this index if (!it.hasNext()) continue; Type lastElementType = it.next(); int arrayLevel = TypeUtil.getArrayDepth(lastElementType); while (it.hasNext()) { int lastArrayLevel = TypeUtil.getArrayDepth(lastElementType); Type type1 = it.next(); if (lastArrayLevel != TypeUtil.getArrayDepth(type1)) { // TODO: See above TODO about variable index re-use // - The problem here is this logic assumes no index re-use... // - This should throw an exception later, but for now // we just pretend the variable is an object (since everything is) lastElementType = TypeUtil.OBJECT_TYPE; break; //throw new VerifierException("Stored multiple array sizes in same variable slot: " + index); } if (lastElementType.equals(type1)) continue; if(Recaf.getCurrentWorkspace() != null) { Type lastType = lastElementType; Type otherType = type1; if (lastType.getSort() == Type.ARRAY) lastType = lastType.getElementType(); if (otherType.getSort() == Type.ARRAY) otherType = otherType.getElementType(); lastElementType = Type.getObjectType(Recaf.getCurrentWorkspace().getHierarchyGraph() .getCommon(lastType.getInternalName(), otherType.getInternalName())); } else break; } while (lastElementType.getSort() == Type.ARRAY) { lastElementType = lastElementType.getElementType(); } // Save type StringBuilder arr = new StringBuilder(); for(int i = 0; i < arrayLevel; i++) arr.append('['); // TODO: Boolean is saved as int, which is technically correct but not expected by most users // - Sort is saved as INTEGER because we don't analyze difference between int/bool cases if (lastElementType.getSort() < Type.ARRAY) nameToDesc.put(name, arr.toString() + lastElementType.getDescriptor()); else nameToDesc.put(name, arr.toString() + "L" + lastElementType.getInternalName() + ";"); } }
Example 3
Source File: LocalsStateGenerators.java From coroutines with GNU Lesser General Public License v3.0 | 4 votes |
/** * Compute sizes required for the storage arrays that will contain the local variables table at this frame. * @param frame frame to compute for * @return size required by each storage array * @throws NullPointerException if any argument is {@code null} */ public static StorageSizes computeSizes(Frame<BasicValue> frame) { Validate.notNull(frame); // Count size required for each storage array int intsSize = 0; int longsSize = 0; int floatsSize = 0; int doublesSize = 0; int objectsSize = 0; for (int i = 0; i < frame.getLocals(); i++) { BasicValue basicValue = frame.getLocal(i); Type type = basicValue.getType(); // If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return '.'. This means that this // slot contains nothing to save. So, skip this slot if we encounter it. if (type == null) { continue; } // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot, thereby // keeping the same 'Lnull;' type. if ("Lnull;".equals(type.getDescriptor())) { continue; } switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: intsSize++; break; case Type.FLOAT: floatsSize++; break; case Type.LONG: longsSize++; break; case Type.DOUBLE: doublesSize++; break; case Type.ARRAY: case Type.OBJECT: objectsSize++; break; case Type.METHOD: case Type.VOID: default: throw new IllegalStateException(); } } return new StorageSizes(intsSize, longsSize, floatsSize, doublesSize, objectsSize); }
Example 4
Source File: SimpleVerifierTest.java From coroutines with GNU Lesser General Public License v3.0 | 4 votes |
@Test public void testVertificationWithoutUsingClassLoader() throws Exception { // augment method to take in a single int argument methodNode.desc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE); // augment method instructions VariableTable varTable = new VariableTable(classNode, methodNode); Class<?> iterableClass = Iterable.class; Constructor arrayListConstructor = ConstructorUtils.getAccessibleConstructor(ArrayList.class); Constructor linkedListConstructor = ConstructorUtils.getAccessibleConstructor(LinkedList.class); Constructor hashSetConstructor = ConstructorUtils.getAccessibleConstructor(HashSet.class); Method iteratorMethod = MethodUtils.getAccessibleMethod(iterableClass, "iterator"); Type iterableType = Type.getType(iterableClass); VariableTable.Variable testArg = varTable.getArgument(1); VariableTable.Variable listVar = varTable.acquireExtra(iterableType); /** * Collection it; * switch(arg1) { * case 0: * it = new ArrayList() * break; * case 1: * it = new LinkedList() * break; * case 2: * it = new HashSet() * break; * default: throw new RuntimeException("must be 0 or 1"); * } * list.iterator(); */ LabelNode invokePoint = new LabelNode(); InsnList methodInsnList = merge(tableSwitch(loadVar(testArg), throwRuntimeException("must be 0 or 1"), 0, merge( construct(arrayListConstructor), saveVar(listVar), jumpTo(invokePoint) ), merge( construct(linkedListConstructor), saveVar(listVar), jumpTo(invokePoint) ), merge( construct(hashSetConstructor), saveVar(listVar), jumpTo(invokePoint) ) ), addLabel(invokePoint), call(iteratorMethod, loadVar(listVar)), pop(), // discard results of call returnVoid() ); methodNode.instructions = methodInsnList; // write out class and read it back in again so maxes and frames can be properly computed for frame analyzer SimpleClassWriter writer = new SimpleClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS, classRepo); classNode.accept(writer); byte[] data = writer.toByteArray(); ClassReader cr = new ClassReader(data); classNode = new SimpleClassNode(); cr.accept(classNode, 0); methodNode = classNode.methods.get(1); // analyze Frame<BasicValue>[] frames; try { frames = new Analyzer<>(new SimpleVerifier(classRepo)).analyze(classNode.name, methodNode); } catch (AnalyzerException ae) { throw new IllegalArgumentException("Analyzer failed to analyze method", ae); } // get last frame Frame frame = frames[frames.length - 1]; BasicValue basicValue = (BasicValue) frame.getLocal(listVar.getIndex()); // ensure that that the local variable for the collection we created in the switch blocks is an abstract type assertEquals("java/util/AbstractCollection", basicValue.getType().getInternalName()); }