mirror of
				https://gitee.com/BDWare/common
				synced 2025-10-31 12:52:16 +00:00 
			
		
		
		
	initial commit
This commit is contained in:
		
							parent
							
								
									016d019bc7
								
							
						
					
					
						commit
						ef46d1ac4c
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,6 @@ | |||||||
| # Compiled class file | # Compiled class file | ||||||
| *.class | *.class | ||||||
| 
 | .DS_Store | ||||||
| # Log file | # Log file | ||||||
| *.log | *.log | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										59
									
								
								build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | plugins { | ||||||
|  |     id 'java' | ||||||
|  |     id 'java-library' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sourceSets { | ||||||
|  |     main { | ||||||
|  |         java { | ||||||
|  |             srcDirs 'src/main/base', 'src/main/analysis', 'src/main/asm', 'src/main/crypto', 'src/main/entry', 'src/main/gen', 'src/main/pythongen', 'src/main/DOIP', 'src/main/config' | ||||||
|  |         } | ||||||
|  |         resources { | ||||||
|  |             srcDir 'src/main/resources' | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     test { | ||||||
|  |         java { | ||||||
|  |             srcDir 'src/test/java' | ||||||
|  |         } | ||||||
|  |         resources { | ||||||
|  |             srcDir 'src/test/resources' | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | dependencies { | ||||||
|  |     api project(":gmhelper") | ||||||
|  | 
 | ||||||
|  |     api 'berkeleydb:je:3.2.76' | ||||||
|  |     api 'com.fifesoft:rsyntaxtextarea:3.1.3' | ||||||
|  |     api 'commons-io:commons-io:2.11.0' | ||||||
|  |     api 'io.grpc:grpc-all:1.40.1' | ||||||
|  |     api 'io.netty:netty-all:4.1.52.Final' | ||||||
|  |     api 'io.prometheus:simpleclient:0.12.0' | ||||||
|  |     api 'org.antlr:antlr4:4.9.2' | ||||||
|  |     api 'org.apache.commons:commons-lang3:3.12.0' | ||||||
|  |     api 'org.apache.httpcomponents:httpclient:4.5.13' | ||||||
|  |     api 'org.apache.logging.log4j:log4j-core:2.14.1' | ||||||
|  |     api 'org.apache.logging.log4j:log4j-api:2.14.1' | ||||||
|  |     api 'org.apache.velocity:velocity-engine-core:2.3' | ||||||
|  |     api 'org.knowhowlab.osgi:sigar:1.6.5_01' | ||||||
|  |     api 'org.rocksdb:rocksdbjni:6.22.1' | ||||||
|  | 
 | ||||||
|  |     api fileTree(dir: 'lib', include: '*.jar') | ||||||
|  | 
 | ||||||
|  |     testImplementation 'junit:junit:4.13.2' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | tasks.processResources.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE) | ||||||
|  | 
 | ||||||
|  | task copyLibs(type: Copy) { | ||||||
|  |     from configurations.runtimeClasspath | ||||||
|  |     into "./build/output/libs/" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | task copyJar(type: Copy) { | ||||||
|  |     from "./build/libs/$project.name-${version}.jar" | ||||||
|  |     into "./build/output/" | ||||||
|  |     rename { String fileName -> "yjs.jar" } | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-20200311-SNAPSHOT.jar.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-20200311-SNAPSHOT.jar.bak
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-dev-200712.f6d4130c.jar.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-dev-200712.f6d4130c.jar.bak
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-dev-200922.1278255c.jar.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-dev-200922.1278255c.jar.bak
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-tb-0621.jar.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-tb-0621.jar.bak
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-tb-20200722.jar.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/bdledger-java-sdk-tb-20200722.jar.bak
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										18
									
								
								src/main/analysis/org/bdware/analysis/AnalysisResult.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/analysis/org/bdware/analysis/AnalysisResult.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | 
 | ||||||
|  | public abstract class AnalysisResult { | ||||||
|  | 	public AnalysisResult() { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public abstract AnalysisResult merge(AbstractInsnNode insn); | ||||||
|  | 
 | ||||||
|  | 	public abstract void printResult(); | ||||||
|  | 
 | ||||||
|  | 	public abstract boolean covers(AnalysisResult result); | ||||||
|  | 
 | ||||||
|  | 	public abstract void mergeResult(AnalysisResult r); | ||||||
|  | 
 | ||||||
|  | 	public abstract AnalysisResult clone(); | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | public interface AnalysisTarget { | ||||||
|  | 	public boolean inList(); | ||||||
|  | 
 | ||||||
|  | 	public void setInList(boolean b); | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								src/main/analysis/org/bdware/analysis/BasicBlock.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/main/analysis/org/bdware/analysis/BasicBlock.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | 
 | ||||||
|  | public class BasicBlock { | ||||||
|  | 	public List<AbstractInsnNode> list; | ||||||
|  | 	public int blockID; | ||||||
|  | 	public int lineNum = -1; | ||||||
|  |     public int insnCount; | ||||||
|  | 
 | ||||||
|  |     public BasicBlock(int id) { | ||||||
|  | 		list = new ArrayList<>(); | ||||||
|  | 		blockID = id; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void add(AbstractInsnNode insn) { | ||||||
|  | 		list.add(insn); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public int size() { | ||||||
|  | 
 | ||||||
|  | 		return list.size(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public List<AbstractInsnNode> getInsn() { | ||||||
|  | 		return list; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	boolean inList = false; | ||||||
|  | 
 | ||||||
|  | 	public AbstractInsnNode lastInsn() { | ||||||
|  | 		return list.get(list.size() - 1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setLineNum(int line) { | ||||||
|  | 		lineNum = line; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean inList() { | ||||||
|  | 		return inList; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setInList(boolean b) { | ||||||
|  | 		inList = b; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | public abstract class BreadthFirstSearch<R extends AnalysisResult, T extends AnalysisTarget> { | ||||||
|  | 	public Map<T, AnalysisResult> results; | ||||||
|  | 	protected List<T> toAnalysis; | ||||||
|  | 
 | ||||||
|  | 	public abstract R execute(T t); | ||||||
|  | 
 | ||||||
|  | 	public abstract Collection<T> getSuc(T t); | ||||||
|  | 
 | ||||||
|  | 	public BreadthFirstSearch() { | ||||||
|  | 		results = new HashMap<T, AnalysisResult>(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public Map<T, AnalysisResult> analysis() { | ||||||
|  | 		results.clear(); | ||||||
|  | 		T current = null; | ||||||
|  | 		for (int i = 0; i < toAnalysis.size(); i++) { | ||||||
|  | 			current = toAnalysis.get(i); | ||||||
|  | 			current.setInList(false); | ||||||
|  | 			AnalysisResult preResult = results.get(current); | ||||||
|  | 			AnalysisResult sucResult = execute(current); | ||||||
|  | 
 | ||||||
|  | 			if (preResult == null || !preResult.covers(sucResult)) { | ||||||
|  | 				AnalysisResult cloneResult = sucResult.clone(); | ||||||
|  | 				if (cloneResult != null) { | ||||||
|  | 					results.put(current, cloneResult); | ||||||
|  | 				} | ||||||
|  | 				Collection<T> sucs = getSuc(current); | ||||||
|  | 				for (T next : sucs) { | ||||||
|  | 
 | ||||||
|  | 					if (toAnalysis.contains(next)) { | ||||||
|  | 						//results.remove(next); | ||||||
|  | 						//toAnalysis.remove(next); | ||||||
|  | 					} | ||||||
|  | 					if (!next.inList()) { | ||||||
|  | 						toAnalysis.add(next); | ||||||
|  | 						next.setInList(true); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return results; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public int getListLength() { | ||||||
|  | 		return toAnalysis.size(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setToAnalysis(List<T> l) { | ||||||
|  | 		toAnalysis = l; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										581
									
								
								src/main/analysis/org/bdware/analysis/CFGraph.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										581
									
								
								src/main/analysis/org/bdware/analysis/CFGraph.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,581 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | import org.apache.logging.log4j.LogManager; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import org.objectweb.asm.*; | ||||||
|  | import org.objectweb.asm.tree.*; | ||||||
|  | 
 | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public abstract class CFGraph { | ||||||
|  |     private static final Logger LOGGER = LogManager.getLogger(CFGraph.class); | ||||||
|  |     private final Map<BasicBlock, Set<BasicBlock>> preBlock; | ||||||
|  |     private final Map<Label, BasicBlock> labelToBB; | ||||||
|  |     private final Map<Label, Integer> labelOrder = new HashMap<>(); | ||||||
|  |     protected List<BasicBlock> basicBlocks; | ||||||
|  |     protected Map<BasicBlock, Set<BasicBlock>> sucBlock; | ||||||
|  |     MethodNode methodNode; | ||||||
|  |     // Pass2: build edges | ||||||
|  |     // type2(canThrow) and catchLabels | ||||||
|  |     // type3 and target labels | ||||||
|  |     // type4 and catchLabels | ||||||
|  | //    private List<TryCatchBlockNode> tryCacheList; | ||||||
|  |     // Pass1: build basic blocks | ||||||
|  |     // create a new block when: | ||||||
|  |     // 1.starts with Label(can jump) | ||||||
|  |     // 2.ends with CanReturn/CanThrow Insn | ||||||
|  |     // 3.ends with CanBranch(IF/Switch) | ||||||
|  |     // 4.ends with MethodInvoke | ||||||
|  |     // At the same time build edges between: | ||||||
|  |     // type1 and pre | ||||||
|  |     // type2 and endBlock | ||||||
|  |     // type3 and suc | ||||||
|  |     // type4 and endBlock | ||||||
|  |     // type4 and suc | ||||||
|  | 
 | ||||||
|  |     public CFGraph(MethodNode mn) { | ||||||
|  |         basicBlocks = new ArrayList<>(); | ||||||
|  |         preBlock = new HashMap<>(); | ||||||
|  |         sucBlock = new HashMap<>(); | ||||||
|  |         labelToBB = new HashMap<>(); | ||||||
|  |         methodNode = mn; | ||||||
|  |         buildBasicBlock(mn.instructions, mn.tryCatchBlocks); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void addEdge(BasicBlock pre, BasicBlock suc) { | ||||||
|  |         Set<BasicBlock> pres = getPreBlocks(suc); | ||||||
|  |         pres.add(pre); | ||||||
|  |         Set<BasicBlock> sucs = getSucBlocks(pre); | ||||||
|  |         sucs.add(suc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<BasicBlock> getSucBlocks(BasicBlock pre) { | ||||||
|  |         if (null == sucBlock.get(pre)) { | ||||||
|  |             Set<BasicBlock> ret = new HashSet<>(); | ||||||
|  |             sucBlock.put(pre, ret); | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |         return sucBlock.get(pre); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<BasicBlock> getPreBlocks(BasicBlock suc) { | ||||||
|  |         if (preBlock.get(suc) == null) { | ||||||
|  |             Set<BasicBlock> ret = new HashSet<>(); | ||||||
|  |             preBlock.put(suc, ret); | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  |         return preBlock.get(suc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public abstract BasicBlock getBasicBlock(int id); | ||||||
|  | 
 | ||||||
|  |     private void buildBasicBlock(InsnList instructions, List<TryCatchBlockNode> tryCatchBlocks) { | ||||||
|  |         InsnPass1Visitor visitor = new InsnPass1Visitor(Opcodes.ASM4); | ||||||
|  |         visitor.currBlock = getBasicBlock(0); | ||||||
|  |         basicBlocks.add(visitor.currBlock); | ||||||
|  |         for (int i = 0; i < instructions.size(); i++) { | ||||||
|  |             AbstractInsnNode insn = instructions.get(i); | ||||||
|  |             visitor.setCurrInsn(insn); | ||||||
|  |             insn.accept(visitor); | ||||||
|  |         } | ||||||
|  |         visitor.visitEnd(); | ||||||
|  |         List<BasicBlock> merged = new ArrayList<>(); | ||||||
|  |         for (BasicBlock bb : basicBlocks) | ||||||
|  |             if (bb.list.size() > 0) | ||||||
|  |                 merged.add(bb); | ||||||
|  |         basicBlocks = merged; | ||||||
|  |         InsnPass2Visitor pass2 = new InsnPass2Visitor(Opcodes.ASM4); | ||||||
|  |         pass2.tryCatchBlocks = tryCatchBlocks; | ||||||
|  |         for (int i = 0; i < basicBlocks.size(); i++) { | ||||||
|  |             pass2.blockid = i; | ||||||
|  |             BasicBlock bb = basicBlocks.get(i); | ||||||
|  |             bb.blockID = i; | ||||||
|  |             if (bb.size() > 0) | ||||||
|  |                 if (bb.list.get(0) instanceof LabelNode) { | ||||||
|  |                     pass2.preLabel = ((LabelNode) bb.list.get(0)).getLabel(); | ||||||
|  |                 } | ||||||
|  |             for (AbstractInsnNode node : bb.list) { | ||||||
|  |                 node.accept(pass2); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         int preLine = -1; | ||||||
|  |         for (BasicBlock block : basicBlocks) { | ||||||
|  |             if (block.lineNum != -1) { | ||||||
|  |                 preLine = block.lineNum; | ||||||
|  |             } else | ||||||
|  |                 block.lineNum = preLine; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void printSelf() { | ||||||
|  |         InsnPrinter printer = new InsnPrinter(Opcodes.ASM4, System.out); | ||||||
|  |         printer.setLabelOrder(getLabelOrder()); | ||||||
|  |         LOGGER.info("isStatic: " + ((methodNode.access & Opcodes.ACC_STATIC) > 0) | ||||||
|  |                 + "\tMethod:" + methodNode.name + "  " + methodNode.desc); | ||||||
|  |         LOGGER.info(methodNode.maxLocals + "  " + methodNode.maxStack); | ||||||
|  |         StringBuilder log = new StringBuilder(); | ||||||
|  |         for (BasicBlock bb : basicBlocks) { | ||||||
|  |             log.append("B").append(bb.blockID); | ||||||
|  |             if (getSucBlocks(bb).size() > 0) { | ||||||
|  |                 log.append(" -->"); | ||||||
|  |             } | ||||||
|  |             for (BasicBlock suc : getSucBlocks(bb)) { | ||||||
|  |                 log.append(" B").append(suc.blockID); | ||||||
|  |             } | ||||||
|  |             for (AbstractInsnNode an : bb.list) { | ||||||
|  |                 an.accept(printer); | ||||||
|  |             } | ||||||
|  |             log.append("\n"); | ||||||
|  |         } | ||||||
|  |         LOGGER.info(log.substring(0, log.length() - 1)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Map<Label, Integer> getLabelOrder() { | ||||||
|  |         return labelOrder; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public BasicBlock getBasicBlockAt(int i) { | ||||||
|  |         return basicBlocks.get(i); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getBasicBlockSize() { | ||||||
|  |         return basicBlocks.size(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public MethodNode getMethodNode() { | ||||||
|  |         return methodNode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public BasicBlock getBasicBlockByLabel(Label l) { | ||||||
|  |         return labelToBB.get(l); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private class InsnPass1Visitor extends MethodVisitor { | ||||||
|  |         int count = 0; | ||||||
|  |         AbstractInsnNode currInsn; | ||||||
|  |         BasicBlock currBlock; | ||||||
|  | 
 | ||||||
|  |         // ------------------------------------------------------------------------- | ||||||
|  |         // Normal instructions | ||||||
|  |         // ------------------------------------------------------------------------- | ||||||
|  |         BasicBlock endBlock = getEndBlock(); | ||||||
|  | 
 | ||||||
|  |         public InsnPass1Visitor(int api) { | ||||||
|  |             super(api); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a zero operand instruction. | ||||||
|  |          * | ||||||
|  |          * @param opcode the opcode of the instruction to be visited. This opcode is | ||||||
|  |          *               either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, | ||||||
|  |          *               ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, | ||||||
|  |          *               FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, | ||||||
|  |          *               LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, | ||||||
|  |          *               IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, | ||||||
|  |          *               SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, | ||||||
|  |          *               DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, | ||||||
|  |          *               IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, | ||||||
|  |          *               FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, | ||||||
|  |          *               IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, | ||||||
|  |          *               L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, | ||||||
|  |          *               LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, | ||||||
|  |          *               DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or | ||||||
|  |          *               MONITOREXIT. | ||||||
|  |          */ | ||||||
|  |         public void visitInsn(int opcode) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             if (OpInfo.ops[opcode].canReturn()) { | ||||||
|  |                 addEdge(currBlock, endBlock); | ||||||
|  |                 currBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  |                 basicBlocks.add(currBlock); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits an instruction with a single int operand. | ||||||
|  |          * | ||||||
|  |          * @param opcode  the opcode of the instruction to be visited. This opcode is | ||||||
|  |          *                either BIPUSH, SIPUSH or NEWARRAY. | ||||||
|  |          * @param operand the operand of the instruction to be visited.<br> | ||||||
|  |          *                When opcode is BIPUSH, operand value should be between | ||||||
|  |          *                Byte.MIN_VALUE and Byte.MAX_VALUE.<br> | ||||||
|  |          *                When opcode is SIPUSH, operand value should be between | ||||||
|  |          *                Short.MIN_VALUE and Short.MAX_VALUE.<br> | ||||||
|  |          *                When opcode is NEWARRAY, operand value should be one of | ||||||
|  |          *                {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, | ||||||
|  |          *                {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, | ||||||
|  |          *                {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, | ||||||
|  |          *                {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. | ||||||
|  |          */ | ||||||
|  |         public void visitIntInsn(int opcode, int operand) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a local variable instruction. A local variable instruction is an | ||||||
|  |          * instruction that loads or stores the value of a local variable. | ||||||
|  |          * | ||||||
|  |          * @param opcode the opcode of the local variable instruction to be visited. | ||||||
|  |          *               This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, | ||||||
|  |          *               ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. | ||||||
|  |          * @param var    the operand of the instruction to be visited. This operand is | ||||||
|  |          *               the index of a local variable. | ||||||
|  |          */ | ||||||
|  |         public void visitVarInsn(int opcode, int var) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a type instruction. A type instruction is an instruction that takes | ||||||
|  |          * the internal name of a class as parameter. | ||||||
|  |          * | ||||||
|  |          * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  |          *               is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. | ||||||
|  |          * @param type   the operand of the instruction to be visited. This operand must | ||||||
|  |          *               be the internal name of an object or array class (see | ||||||
|  |          *               {@link Type#getInternalName() getInternalName}). | ||||||
|  |          */ | ||||||
|  |         public void visitTypeInsn(int opcode, String type) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a field instruction. A field instruction is an instruction that loads | ||||||
|  |          * or stores the value of a field of an object. | ||||||
|  |          * | ||||||
|  |          * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  |          *               is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. | ||||||
|  |          * @param owner  the internal name of the field's owner class (see | ||||||
|  |          *               {@link Type#getInternalName() getInternalName}). | ||||||
|  |          * @param name   the field's name. | ||||||
|  |          * @param desc   the field's descriptor (see {@link Type Type}). | ||||||
|  |          */ | ||||||
|  |         public void visitFieldInsn(int opcode, String owner, String name, String desc) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a method instruction. A method instruction is an instruction that | ||||||
|  |          * invokes a method. | ||||||
|  |          * | ||||||
|  |          * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  |          *               is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or | ||||||
|  |          *               INVOKEINTERFACE. | ||||||
|  |          * @param owner  the internal name of the method's owner class (see | ||||||
|  |          *               {@link Type#getInternalName() getInternalName}). | ||||||
|  |          * @param name   the method's name. | ||||||
|  |          * @param desc   the method's descriptor (see {@link Type Type}). | ||||||
|  |          */ | ||||||
|  |         public void visitMethodInsn(int opcode, String owner, String name, String desc) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             addEdge(currBlock, endBlock); | ||||||
|  |             BasicBlock nextBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  |             addEdge(currBlock, nextBlock); | ||||||
|  |             currBlock = nextBlock; | ||||||
|  |             basicBlocks.add(currBlock); | ||||||
|  |             // TODO add edges to try catch blocks! | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // ------------------------------------------------------------------------- | ||||||
|  |         // Special instructions | ||||||
|  |         // ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits an invokedynamic instruction. | ||||||
|  |          * | ||||||
|  |          * @param name    the method's name. | ||||||
|  |          * @param desc    the method's descriptor (see {@link Type Type}). | ||||||
|  |          * @param bsm     the bootstrap method. | ||||||
|  |          * @param bsmArgs the bootstrap method constant arguments. Each argument must be | ||||||
|  |          *                an {@link Integer}, {@link Float}, {@link Long}, | ||||||
|  |          *                {@link Double}, {@link String}, {@link Type} or {@link Handle} | ||||||
|  |          *                value. This method is allowed to modify the content of the | ||||||
|  |          *                array so a caller should expect that this array may change. | ||||||
|  |          */ | ||||||
|  |         public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { | ||||||
|  | 
 | ||||||
|  |             // TODO add edges to try catch blocks! | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             addEdge(currBlock, endBlock); | ||||||
|  |             BasicBlock nextBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  |             addEdge(currBlock, nextBlock); | ||||||
|  |             currBlock = nextBlock; | ||||||
|  |             basicBlocks.add(currBlock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a jump instruction. A jump instruction is an instruction that may jump | ||||||
|  |          * to another instruction. | ||||||
|  |          * | ||||||
|  |          * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  |          *               is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, | ||||||
|  |          *               IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, | ||||||
|  |          *               IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. | ||||||
|  |          * @param label  the operand of the instruction to be visited. This operand is a | ||||||
|  |          *               label that designates the instruction to which the jump | ||||||
|  |          *               instruction may jump. | ||||||
|  |          */ | ||||||
|  |         public void visitJumpInsn(int opcode, Label label) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             BasicBlock nextBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  | 
 | ||||||
|  |             if (!OpInfo.ops[opcode].toString().contains("goto")) | ||||||
|  |                 addEdge(currBlock, nextBlock); | ||||||
|  |             currBlock = nextBlock; | ||||||
|  |             basicBlocks.add(currBlock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a label. A label designates the instruction that will be visited just | ||||||
|  |          * after it. | ||||||
|  |          * | ||||||
|  |          * @param label a {@link Label Label} object. | ||||||
|  |          */ | ||||||
|  |         public void visitLabel(Label label) { | ||||||
|  |             getLabelOrder().put(label, count++); | ||||||
|  |             if (currBlock.size() > 0) { | ||||||
|  |                 BasicBlock pre = currBlock; | ||||||
|  |                 currBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  |                 basicBlocks.add(currBlock); | ||||||
|  |                 addEdge(pre, currBlock); | ||||||
|  |             } | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             labelToBB.put(label, currBlock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a LDC instruction. Note that new constant types may be added in future | ||||||
|  |          * versions of the Java Virtual Machine. To easily detect new constant types, | ||||||
|  |          * implementations of this method should check for unexpected constant types, | ||||||
|  |          * like this: | ||||||
|  |          * | ||||||
|  |          * <pre> | ||||||
|  |          * if (cst instanceof Integer) { | ||||||
|  |          * 	// ... | ||||||
|  |          * } else if (cst instanceof Float) { | ||||||
|  |          * 	// ... | ||||||
|  |          * } else if (cst instanceof Long) { | ||||||
|  |          * 	// ... | ||||||
|  |          * } else if (cst instanceof Double) { | ||||||
|  |          * 	// ... | ||||||
|  |          * } else if (cst instanceof String) { | ||||||
|  |          * 	// ... | ||||||
|  |          * } else if (cst instanceof Type) { | ||||||
|  |          * 	int sort = ((Type) cst).getSort(); | ||||||
|  |          * 	if (sort == Type.OBJECT) { | ||||||
|  |          * 		// ... | ||||||
|  |          *    } else if (sort == Type.ARRAY) { | ||||||
|  |          * 		// ... | ||||||
|  |          *    } else if (sort == Type.METHOD) { | ||||||
|  |          * 		// ... | ||||||
|  |          *    } else { | ||||||
|  |          * 		// throw an exception | ||||||
|  |          *    } | ||||||
|  |          * } else if (cst instanceof Handle) { | ||||||
|  |          * 	// ... | ||||||
|  |          * } else { | ||||||
|  |          * 	// throw an exception | ||||||
|  |          * } | ||||||
|  |          * </pre> | ||||||
|  |          * | ||||||
|  |          * @param cst the constant to be loaded on the stack. This parameter must be a | ||||||
|  |          *            non null {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  |          *            {@link Double}, a {@link String}, a {@link Type} of OBJECT or | ||||||
|  |          *            ARRAY sort for <tt>.class</tt> constants, for classes whose | ||||||
|  |          *            version is 49.0, a {@link Type} of METHOD sort or a {@link Handle} | ||||||
|  |          *            for MethodType and MethodHandle constants, for classes whose | ||||||
|  |          *            version is 51.0. | ||||||
|  |          */ | ||||||
|  |         public void visitLdcInsn(Object cst) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits an IINC instruction. | ||||||
|  |          * | ||||||
|  |          * @param var       index of the local variable to be incremented. | ||||||
|  |          * @param increment amount to increment the local variable by. | ||||||
|  |          */ | ||||||
|  |         public void visitIincInsn(int var, int increment) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  |         // ------------------------------------------------------------------------- | ||||||
|  |         // Exceptions table entries, debug information, max stack and max locals | ||||||
|  |         // ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a TABLESWITCH instruction. | ||||||
|  |          * | ||||||
|  |          * @param min    the minimum key value. | ||||||
|  |          * @param max    the maximum key value. | ||||||
|  |          * @param dflt   beginning of the default handler block. | ||||||
|  |          * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the | ||||||
|  |          *               beginning of the handler block for the <tt>min + i</tt> key. | ||||||
|  |          */ | ||||||
|  |         public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             currBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  |             basicBlocks.add(currBlock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a LOOKUPSWITCH instruction. | ||||||
|  |          * | ||||||
|  |          * @param dflt   beginning of the default handler block. | ||||||
|  |          * @param keys   the values of the keys. | ||||||
|  |          * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the | ||||||
|  |          *               beginning of the handler block for the <tt>keys[i]</tt> key. | ||||||
|  |          */ | ||||||
|  |         public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |             currBlock = getBasicBlock(basicBlocks.size()); | ||||||
|  |             basicBlocks.add(currBlock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a MULTIANEWARRAY instruction. | ||||||
|  |          * | ||||||
|  |          * @param desc an array type descriptor (see {@link Type Type}). | ||||||
|  |          * @param dims number of dimensions of the array to allocate. | ||||||
|  |          */ | ||||||
|  |         public void visitMultiANewArrayInsn(String desc, int dims) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a local variable declaration. | ||||||
|  |          * | ||||||
|  |          * @param name      the name of a local variable. | ||||||
|  |          * @param desc      the type descriptor of this local variable. | ||||||
|  |          * @param signature the type signature of this local variable. May be | ||||||
|  |          *                  <tt>null</tt> if the local variable type does not use | ||||||
|  |          *                  generic types. | ||||||
|  |          * @param start     the first instruction corresponding to the scope of this | ||||||
|  |          *                  local variable (inclusive). | ||||||
|  |          * @param end       the last instruction corresponding to the scope of this | ||||||
|  |          *                  local variable (exclusive). | ||||||
|  |          * @param index     the local variable's index. | ||||||
|  |          * @throws IllegalArgumentException if one of the labels has not already been | ||||||
|  |          *                                  visited by this visitor (by the | ||||||
|  |          *                                  {@link #visitLabel visitLabel} method). | ||||||
|  |          */ | ||||||
|  |         public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Visits a line number declaration. | ||||||
|  |          * | ||||||
|  |          * @param line  a line number. This number refers to the source file from which | ||||||
|  |          *              the class was compiled. | ||||||
|  |          * @param start the first instruction corresponding to this line number. | ||||||
|  |          * @throws IllegalArgumentException if <tt>start</tt> has not already been | ||||||
|  |          *                                  visited by this visitor (by the | ||||||
|  |          *                                  {@link #visitLabel visitLabel} method). | ||||||
|  |          */ | ||||||
|  |         public void visitLineNumber(int line, Label start) { | ||||||
|  |             currBlock.add(currInsn); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void setCurrInsn(AbstractInsnNode insn) { | ||||||
|  |             currInsn = insn; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private BasicBlock getEndBlock() { | ||||||
|  |             BasicBlock ret = getBasicBlock(-1); | ||||||
|  |             Label l = new Label(); | ||||||
|  |             ret.add(new LabelNode(l)); | ||||||
|  |             labelToBB.put(l, ret); | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void visitEnd() { | ||||||
|  |             basicBlocks.add(endBlock); | ||||||
|  |             getLabelOrder().put(((LabelNode) (endBlock.list.get(0))).getLabel(), count++); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private class InsnPass2Visitor extends MethodVisitor { | ||||||
|  |         int blockid; | ||||||
|  |         Label preLabel; | ||||||
|  |         List<TryCatchBlockNode> tryCatchBlocks; | ||||||
|  | 
 | ||||||
|  |         public InsnPass2Visitor(int api) { | ||||||
|  |             super(api); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void addTryCatchNodes() { | ||||||
|  |             for (TryCatchBlockNode node : tryCatchBlocks) { | ||||||
|  |                 Label l1 = node.start.getLabel(); | ||||||
|  |                 Label l2 = node.end.getLabel(); | ||||||
|  |                 Label l3 = node.handler.getLabel(); | ||||||
|  |                 if (inLabel(l1, l2, preLabel)) | ||||||
|  |                     addEdge(labelToBB.get(preLabel), labelToBB.get(l3)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void visitLineNumber(int line, Label start) { | ||||||
|  |             BasicBlock currBlock = basicBlocks.get(blockid); | ||||||
|  |             currBlock.setLineNum(line); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void visitJumpInsn(int opcode, Label label) { | ||||||
|  |             BasicBlock currBlock = basicBlocks.get(blockid); | ||||||
|  |             BasicBlock targetBlock = labelToBB.get(label); | ||||||
|  |             addEdge(currBlock, targetBlock); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { | ||||||
|  |             BasicBlock currBlock = basicBlocks.get(blockid); | ||||||
|  |             BasicBlock targetBlock = labelToBB.get(dflt); | ||||||
|  |             addEdge(currBlock, targetBlock); | ||||||
|  |             for (Label label : labels) { | ||||||
|  |                 targetBlock = labelToBB.get(label); | ||||||
|  |                 addEdge(currBlock, targetBlock); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  | 
 | ||||||
|  |         public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { | ||||||
|  |             BasicBlock currBlock = basicBlocks.get(blockid); | ||||||
|  |             BasicBlock targetBlock = labelToBB.get(dflt); | ||||||
|  |             addEdge(currBlock, targetBlock); | ||||||
|  |             for (Label label : labels) { | ||||||
|  |                 targetBlock = labelToBB.get(label); | ||||||
|  |                 addEdge(currBlock, targetBlock); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { | ||||||
|  |             addTryCatchNodes(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private boolean inLabel(Label start, Label end, Label query) { | ||||||
|  |             int s = getLabelOrder().get(start); | ||||||
|  |             int e = getLabelOrder().get(end); | ||||||
|  |             int m = getLabelOrder().get(query); | ||||||
|  |             return (m >= s && m < e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void visitMethodInsn(int opcode, String owner, String name, String desc) { | ||||||
|  |             addTryCatchNodes(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void visitInsn(int opcode) { | ||||||
|  |             if (OpInfo.ops[opcode].toString().contains("throw")) { | ||||||
|  |                 addTryCatchNodes(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								src/main/analysis/org/bdware/analysis/CFType.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/main/analysis/org/bdware/analysis/CFType.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | public interface CFType { | ||||||
|  | 	public static final int kInstrCanBranch = 1; // conditional or unconditional branch | ||||||
|  | 	public static final int kInstrCanContinue = 1 << 1; // flow can continue to next statement | ||||||
|  | 	public static final int kInstrCanSwitch = 1 << 2; // switch | ||||||
|  | 	public static final int kInstrCanThrow = 1 << 3; // could cause an exception to be thrown | ||||||
|  | 	public static final int kInstrCanReturn = 1 << 4; // returns, no additional statements | ||||||
|  | 	public static final int kInstrInvoke = 1 << 5; // a flavor of invoke | ||||||
|  | } | ||||||
							
								
								
									
										138
									
								
								src/main/analysis/org/bdware/analysis/FrontCF.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/main/analysis/org/bdware/analysis/FrontCF.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,138 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | import java.io.FileNotFoundException; | ||||||
|  | import java.io.PrintStream; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.CFGraph; | ||||||
|  | import org.bdware.analysis.InsnPrinter; | ||||||
|  | import org.bdware.analysis.OpInfo; | ||||||
|  | import org.bdware.analysis.taint.TaintBB; | ||||||
|  | import org.bdware.analysis.taint.TaintCFG; | ||||||
|  | 
 | ||||||
|  | public class FrontCF { | ||||||
|  | 	String methodName; | ||||||
|  | 	public List<FrontBB> blocks; | ||||||
|  | 	public List<FrontEdge> edges; | ||||||
|  | 	public String ret; | ||||||
|  | 	public String finalRet; | ||||||
|  | 	transient InsnPrinter printer; | ||||||
|  | 	transient ArrayPs ps; | ||||||
|  | 
 | ||||||
|  | 	static class ArrayPs extends PrintStream { | ||||||
|  | 		List<String> content; | ||||||
|  | 
 | ||||||
|  | 		public ArrayPs() throws FileNotFoundException { | ||||||
|  | 			super("/dev/null"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		public void println(String str) { | ||||||
|  | 			if (content != null) | ||||||
|  | 				content.add(str); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public FrontCF(CFGraph graph) { | ||||||
|  | 		blocks = new ArrayList<>(); | ||||||
|  | 		edges = new ArrayList<>(); | ||||||
|  | 		try { | ||||||
|  | 			ps = new ArrayPs(); | ||||||
|  | 		} catch (FileNotFoundException e) { | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		printer = new InsnPrinter(Opcodes.ASM4, ps); | ||||||
|  | 		printer.setLabelOrder(graph.getLabelOrder()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public static class FrontBB { | ||||||
|  | 		String type; | ||||||
|  | 		String name;  //BlockNumber | ||||||
|  | 		List<String> stmts; //BlockInstructions | ||||||
|  | 		String original; | ||||||
|  | 		String result; //preResult | ||||||
|  | 		String blockDep; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public static class EdgeLabel { | ||||||
|  | 		String label; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public static class FrontEdge { | ||||||
|  | 		String from, to; | ||||||
|  | 		EdgeLabel label; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void addBB(BasicBlock bb, String original, List<Integer> ids, TaintCFG cfg) { | ||||||
|  | 		FrontBB fb = new FrontBB(); | ||||||
|  | 		blocks.add(fb); | ||||||
|  | 		fb.name = "B" + bb.blockID; | ||||||
|  | 		List<AbstractInsnNode> insnList = bb.getInsn(); | ||||||
|  | 		fb.type = "Continuous"; | ||||||
|  | 		fb.original = original; | ||||||
|  | 		 | ||||||
|  | 		//added | ||||||
|  | 		TaintBB b = (TaintBB) bb; | ||||||
|  | 		//if(b.preResult != null) | ||||||
|  | 			//b.preResult.printResult(); | ||||||
|  | 		fb.result = b.getResult(); | ||||||
|  | 		if(ids == null) | ||||||
|  | 			fb.blockDep = ""; | ||||||
|  | 		else{ | ||||||
|  | 			StringBuilder sb = new StringBuilder(); | ||||||
|  | 			//sb.append("Dependence: "); | ||||||
|  | 			for(Integer id : ids) {			 | ||||||
|  | 				//sb.append("B"+ id +" ");	 | ||||||
|  | 				TaintBB tb = (TaintBB) cfg.getBasicBlockAt(id); | ||||||
|  | 				sb.append(tb.preResult.frame.getStack(0).toReadableTaint()); | ||||||
|  | 			} | ||||||
|  | 			fb.blockDep = sb.toString();		 | ||||||
|  | 		} | ||||||
|  | 		if (insnList != null && insnList.size() > 0) { | ||||||
|  | 			AbstractInsnNode lastStmt = insnList.get(insnList.size() - 1); | ||||||
|  | 			if (lastStmt.getOpcode() >= 0) { | ||||||
|  | 				OpInfo info = OpInfo.ops[lastStmt.getOpcode()]; | ||||||
|  | 				if (info.canBranch() || info.canSwitch()) { | ||||||
|  | 					fb.type = "Branch"; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			fb.stmts = new ArrayList<String>(); | ||||||
|  | 			ps.content = fb.stmts; | ||||||
|  | 			for (AbstractInsnNode node : insnList) { | ||||||
|  | 				node.accept(printer); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void addEdge(BasicBlock bb, BasicBlock suc) { | ||||||
|  | 		FrontEdge edge = new FrontEdge(); | ||||||
|  | 		List<AbstractInsnNode> insnList = bb.getInsn(); | ||||||
|  | 		edge.label = new EdgeLabel(); | ||||||
|  | 		edge.label.label = "e"; | ||||||
|  | 		AbstractInsnNode lastStmt = insnList.get(insnList.size() - 1); | ||||||
|  | 		boolean ignore = false; | ||||||
|  | 		if (lastStmt.getOpcode() >= 0) { | ||||||
|  | 			OpInfo info = OpInfo.ops[lastStmt.getOpcode()]; | ||||||
|  | 			if (info.canBranch() && info.toString().startsWith("if")) { | ||||||
|  | 				if (suc.blockID == bb.blockID + 1) | ||||||
|  | 					edge.label.label = "false"; | ||||||
|  | 				else | ||||||
|  | 					edge.label.label = "true"; | ||||||
|  | 			} | ||||||
|  | 			if (info.canThrow() && info.toString().startsWith("invoke")) { | ||||||
|  | 				if (suc.blockID != bb.blockID + 1) { | ||||||
|  | 					ignore = true; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		edge.from = "B" + bb.blockID; | ||||||
|  | 		edge.to = "B" + suc.blockID; | ||||||
|  | 		if (!ignore) | ||||||
|  | 			edges.add(edge); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										297
									
								
								src/main/analysis/org/bdware/analysis/InsnPrinter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								src/main/analysis/org/bdware/analysis/InsnPrinter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,297 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | import java.io.PrintStream; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | 
 | ||||||
|  | public class InsnPrinter extends MethodVisitor { | ||||||
|  | 	PrintStream ps; | ||||||
|  | 	private Map<Label, Integer> labelOrder; | ||||||
|  | 
 | ||||||
|  | 	public InsnPrinter(int api, PrintStream ps) { | ||||||
|  | 		super(api); | ||||||
|  | 		this.ps = ps; | ||||||
|  | 		// TODO Auto-generated constructor stub | ||||||
|  | 	} | ||||||
|  | 	// ------------------------------------------------------------------------- | ||||||
|  | 	// Normal instructions | ||||||
|  | 	// ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a zero operand instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode the opcode of the instruction to be visited. This opcode is | ||||||
|  | 	 *               either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, | ||||||
|  | 	 *               ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, | ||||||
|  | 	 *               FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, | ||||||
|  | 	 *               LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, | ||||||
|  | 	 *               IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, | ||||||
|  | 	 *               SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, | ||||||
|  | 	 *               DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, | ||||||
|  | 	 *               IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, | ||||||
|  | 	 *               FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, | ||||||
|  | 	 *               IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, | ||||||
|  | 	 *               L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, | ||||||
|  | 	 *               LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, | ||||||
|  | 	 *               DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, or | ||||||
|  | 	 *               MONITOREXIT. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitInsn(int opcode) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits an instruction with a single int operand. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode  the opcode of the instruction to be visited. This opcode is | ||||||
|  | 	 *                either BIPUSH, SIPUSH or NEWARRAY. | ||||||
|  | 	 * @param operand the operand of the instruction to be visited.<br> | ||||||
|  | 	 *                When opcode is BIPUSH, operand value should be between | ||||||
|  | 	 *                Byte.MIN_VALUE and Byte.MAX_VALUE.<br> | ||||||
|  | 	 *                When opcode is SIPUSH, operand value should be between | ||||||
|  | 	 *                Short.MIN_VALUE and Short.MAX_VALUE.<br> | ||||||
|  | 	 *                When opcode is NEWARRAY, operand value should be one of | ||||||
|  | 	 *                {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, | ||||||
|  | 	 *                {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, | ||||||
|  | 	 *                {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, | ||||||
|  | 	 *                {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitIntInsn(int opcode, int operand) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString() + " " + operand); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a local variable instruction. A local variable instruction is an | ||||||
|  | 	 * instruction that loads or stores the value of a local variable. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode the opcode of the local variable instruction to be visited. | ||||||
|  | 	 *               This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, | ||||||
|  | 	 *               ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. | ||||||
|  | 	 * @param var    the operand of the instruction to be visited. This operand is | ||||||
|  | 	 *               the index of a local variable. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitVarInsn(int opcode, int var) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString() + " " + var); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a type instruction. A type instruction is an instruction that takes | ||||||
|  | 	 * the internal name of a class as parameter. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  | 	 *               is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. | ||||||
|  | 	 * @param type   the operand of the instruction to be visited. This operand must | ||||||
|  | 	 *               be the internal name of an object or array class (see | ||||||
|  | 	 *               {@link Type#getInternalName() getInternalName}). | ||||||
|  | 	 */ | ||||||
|  | 	public void visitTypeInsn(int opcode, String type) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString() + " " + type); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a field instruction. A field instruction is an instruction that loads | ||||||
|  | 	 * or stores the value of a field of an object. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  | 	 *               is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. | ||||||
|  | 	 * @param owner  the internal name of the field's owner class (see | ||||||
|  | 	 *               {@link Type#getInternalName() getInternalName}). | ||||||
|  | 	 * @param name   the field's name. | ||||||
|  | 	 * @param desc   the field's descriptor (see {@link Type Type}). | ||||||
|  | 	 */ | ||||||
|  | 	public void visitFieldInsn(int opcode, String owner, String name, String desc) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString() + " " + owner + " " + name + " " + desc); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a method instruction. A method instruction is an instruction that | ||||||
|  | 	 * invokes a method. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  | 	 *               is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or | ||||||
|  | 	 *               INVOKEINTERFACE. | ||||||
|  | 	 * @param owner  the internal name of the method's owner class (see | ||||||
|  | 	 *               {@link Type#getInternalName() getInternalName}). | ||||||
|  | 	 * @param name   the method's name. | ||||||
|  | 	 * @param desc   the method's descriptor (see {@link Type Type}). | ||||||
|  | 	 */ | ||||||
|  | 	public void visitMethodInsn(int opcode, String owner, String name, String desc) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString() + " " + owner + " " + name + " " + desc); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits an invokedynamic instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param name    the method's name. | ||||||
|  | 	 * @param desc    the method's descriptor (see {@link Type Type}). | ||||||
|  | 	 * @param bsm     the bootstrap method. | ||||||
|  | 	 * @param bsmArgs the bootstrap method constant arguments. Each argument must be | ||||||
|  | 	 *                an {@link Integer}, {@link Float}, {@link Long}, | ||||||
|  | 	 *                {@link Double}, {@link String}, {@link Type} or {@link Handle} | ||||||
|  | 	 *                value. This method is allowed to modify the content of the | ||||||
|  | 	 *                array so a caller should expect that this array may change. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { | ||||||
|  | 		ps.println(OpInfo.INVOKEDYNAMIC.toString() + " " + name + " " + desc + " HANDLE:" + bsm.toString() + " " | ||||||
|  | 				+ objs2Str(bsmArgs)); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private String objs2Str(Object[] bsmArgs) { | ||||||
|  | 		StringBuilder sb = new StringBuilder(); | ||||||
|  | 		for (Object obj : bsmArgs) | ||||||
|  | 			sb.append(obj.toString()).append(" "); | ||||||
|  | 		return sb.toString(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a jump instruction. A jump instruction is an instruction that may jump | ||||||
|  | 	 * to another instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param opcode the opcode of the type instruction to be visited. This opcode | ||||||
|  | 	 *               is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, | ||||||
|  | 	 *               IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, | ||||||
|  | 	 *               IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. | ||||||
|  | 	 * @param label  the operand of the instruction to be visited. This operand is a | ||||||
|  | 	 *               label that designates the instruction to which the jump | ||||||
|  | 	 *               instruction may jump. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitJumpInsn(int opcode, Label label) { | ||||||
|  | 		ps.println(OpInfo.ops[opcode].toString() + getLabelStr(label)); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a label. A label designates the instruction that will be visited just | ||||||
|  | 	 * after it. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param label a {@link Label Label} object. | ||||||
|  | 	 */ | ||||||
|  | 	private String getLabelStr(Label label) { | ||||||
|  | 		return "L" + labelOrder.get(label); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void visitLabel(Label label) { | ||||||
|  | 		ps.println("=" + getLabelStr(label) + "="); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ------------------------------------------------------------------------- | ||||||
|  | 	// Special instructions | ||||||
|  | 	// ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a LDC instruction. Note that new constant types may be added in future | ||||||
|  | 	 * versions of the Java Virtual Machine. To easily detect new constant types, | ||||||
|  | 	 * implementations of this method should check for unexpected constant types, | ||||||
|  | 	 * like this: | ||||||
|  | 	 *  | ||||||
|  | 	 * <pre> | ||||||
|  | 	 * if (cst instanceof Integer) { | ||||||
|  | 	 * 	// ... | ||||||
|  | 	 * } else if (cst instanceof Float) { | ||||||
|  | 	 * 	// ... | ||||||
|  | 	 * } else if (cst instanceof Long) { | ||||||
|  | 	 * 	// ... | ||||||
|  | 	 * } else if (cst instanceof Double) { | ||||||
|  | 	 * 	// ... | ||||||
|  | 	 * } else if (cst instanceof String) { | ||||||
|  | 	 * 	// ... | ||||||
|  | 	 * } else if (cst instanceof Type) { | ||||||
|  | 	 * 	int sort = ((Type) cst).getSort(); | ||||||
|  | 	 * 	if (sort == Type.OBJECT) { | ||||||
|  | 	 * 		// ... | ||||||
|  | 	 * 	} else if (sort == Type.ARRAY) { | ||||||
|  | 	 * 		// ... | ||||||
|  | 	 * 	} else if (sort == Type.METHOD) { | ||||||
|  | 	 * 		// ... | ||||||
|  | 	 * 	} else { | ||||||
|  | 	 * 		// throw an exception | ||||||
|  | 	 * 	} | ||||||
|  | 	 * } else if (cst instanceof Handle) { | ||||||
|  | 	 * 	// ... | ||||||
|  | 	 * } else { | ||||||
|  | 	 * 	// throw an exception | ||||||
|  | 	 * } | ||||||
|  | 	 * </pre> | ||||||
|  | 	 *  | ||||||
|  | 	 * @param cst the constant to be loaded on the stack. This parameter must be a | ||||||
|  | 	 *            non null {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  | 	 *            {@link Double}, a {@link String}, a {@link Type} of OBJECT or | ||||||
|  | 	 *            ARRAY sort for <tt>.class</tt> constants, for classes whose | ||||||
|  | 	 *            version is 49.0, a {@link Type} of METHOD sort or a {@link Handle} | ||||||
|  | 	 *            for MethodType and MethodHandle constants, for classes whose | ||||||
|  | 	 *            version is 51.0. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitLdcInsn(Object cst) { | ||||||
|  | 		ps.println("ldc " + cst); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits an IINC instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param var       index of the local variable to be incremented. | ||||||
|  | 	 * @param increment amount to increment the local variable by. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitIincInsn(int var, int increment) { | ||||||
|  | 		ps.println("iinc " + var + " " + increment); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a TABLESWITCH instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param min    the minimum key value. | ||||||
|  | 	 * @param max    the maximum key value. | ||||||
|  | 	 * @param dflt   beginning of the default handler block. | ||||||
|  | 	 * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the | ||||||
|  | 	 *               beginning of the handler block for the <tt>min + i</tt> key. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { | ||||||
|  | 		ps.println(OpInfo.TABLESWITCH.toString() + " labels:" + getLabelStr(dflt) + " " + convertLabels(labels)); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private String convertLabels(Label[] labels) { | ||||||
|  | 		StringBuilder sb = new StringBuilder(); | ||||||
|  | 		for (Label l : labels) | ||||||
|  | 			sb.append(getLabelStr(l)).append(" "); | ||||||
|  | 		return sb.toString(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a LOOKUPSWITCH instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param dflt   beginning of the default handler block. | ||||||
|  | 	 * @param keys   the values of the keys. | ||||||
|  | 	 * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the | ||||||
|  | 	 *               beginning of the handler block for the <tt>keys[i]</tt> key. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { | ||||||
|  | 		ps.println(OpInfo.LOOKUPSWITCH.toString() + " labels:" + getLabelStr(dflt) + " " + convertLabels(labels)); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Visits a MULTIANEWARRAY instruction. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param desc an array type descriptor (see {@link Type Type}). | ||||||
|  | 	 * @param dims number of dimensions of the array to allocate. | ||||||
|  | 	 */ | ||||||
|  | 	public void visitMultiANewArrayInsn(String desc, int dims) { | ||||||
|  | 		ps.println(OpInfo.MULTIANEWARRAY + " " + desc + " " + dims); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setLabelOrder(Map<Label, Integer> labelOrder) { | ||||||
|  | 		this.labelOrder = labelOrder; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										256
									
								
								src/main/analysis/org/bdware/analysis/OpInfo.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								src/main/analysis/org/bdware/analysis/OpInfo.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,256 @@ | |||||||
|  | package org.bdware.analysis; | ||||||
|  | 
 | ||||||
|  | public enum OpInfo implements CFType { | ||||||
|  | 	NOP(0x00, "nop", kInstrCanContinue, 0), // -- | ||||||
|  | 	ACONST_NULL(0x01, "aconst_null", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_M1(0x02, "iconst_m1", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_0(0x03, "iconst_0", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_1(0x04, "iconst_1", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_2(0x05, "iconst_2", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_3(0x06, "iconst_3", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_4(0x07, "iconst_4", kInstrCanContinue, 1), // -- | ||||||
|  | 	ICONST_5(0x08, "iconst_5", kInstrCanContinue, 1), // -- | ||||||
|  | 	LCONST_0(0x09, "lconst_0", kInstrCanContinue, 2), // -- | ||||||
|  | 	LCONST_1(0x0a, "lconst_1", kInstrCanContinue, 2), // -- | ||||||
|  | 	FCONST_0(0x0b, "fconst_0", kInstrCanContinue, 1), // -- | ||||||
|  | 	FCONST_1(0x0c, "fconst_1", kInstrCanContinue, 1), // -- | ||||||
|  | 	FCONST_2(0x0d, "fconst_2", kInstrCanContinue, 1), // -- | ||||||
|  | 	DCONST_0(0x0e, "dconst_0", kInstrCanContinue, 2), // -- | ||||||
|  | 	DCONST_1(0x0f, "dconst_1", kInstrCanContinue, 2), // -- | ||||||
|  | 	BIPUSH(0x10, "bipush", kInstrCanContinue, 1), // -- | ||||||
|  | 	SIPUSH(0x11, "sipush", kInstrCanContinue, 1), // -- | ||||||
|  | 	LDC(0x12, "ldc", kInstrCanContinue, 1), // -- | ||||||
|  | 	LDC_W(0x13, "ldc_w", kInstrCanContinue, 1), // -- | ||||||
|  | 	LDC2_W(0x14, "ldc2_w", kInstrCanContinue, 2), // -- | ||||||
|  | 	ILOAD(0x15, "iload", kInstrCanContinue, 1), // -- | ||||||
|  | 	LLOAD(0x16, "lload", kInstrCanContinue, 2), // -- | ||||||
|  | 	FLOAD(0x17, "fload", kInstrCanContinue, 1), // -- | ||||||
|  | 	DLOAD(0x18, "dload", kInstrCanContinue, 2), // -- | ||||||
|  | 	ALOAD(0x19, "aload", kInstrCanContinue, 1), // -- | ||||||
|  | 	ILOAD_0(0x1a, "iload_0", kInstrCanContinue, 1), // -- | ||||||
|  | 	ILOAD_1(0x1b, "iload_1", kInstrCanContinue, 1), // -- | ||||||
|  | 	ILOAD_2(0x1c, "iload_2", kInstrCanContinue, 1), // -- | ||||||
|  | 	ILOAD_3(0x1d, "iload_3", kInstrCanContinue, 1), // -- | ||||||
|  | 	LLOAD_0(0x1e, "lload_0", kInstrCanContinue, 2), // -- | ||||||
|  | 	LLOAD_1(0x1f, "lload_1", kInstrCanContinue, 2), // -- | ||||||
|  | 	LLOAD_2(0x20, "lload_2", kInstrCanContinue, 2), // -- | ||||||
|  | 	LLOAD_3(0x21, "lload_3", kInstrCanContinue, 2), // -- | ||||||
|  | 	FLOAD_0(0x22, "fload_0", kInstrCanContinue, 1), // -- | ||||||
|  | 	FLOAD_1(0x23, "fload_1", kInstrCanContinue, 1), // -- | ||||||
|  | 	FLOAD_2(0x24, "fload_2", kInstrCanContinue, 1), // -- | ||||||
|  | 	FLOAD_3(0x25, "fload_3", kInstrCanContinue, 1), // -- | ||||||
|  | 	DLOAD_0(0x26, "dload_0", kInstrCanContinue, 2), // -- | ||||||
|  | 	DLOAD_1(0x27, "dload_1", kInstrCanContinue, 2), // -- | ||||||
|  | 	DLOAD_2(0x28, "dload_2", kInstrCanContinue, 2), // -- | ||||||
|  | 	DLOAD_3(0x29, "dload_3", kInstrCanContinue, 2), // -- | ||||||
|  | 	ALOAD_0(0x2a, "aload_0", kInstrCanContinue, 1), // -- | ||||||
|  | 	ALOAD_1(0x2b, "aload_1", kInstrCanContinue, 1), // -- | ||||||
|  | 	ALOAD_2(0x2c, "aload_2", kInstrCanContinue, 1), // -- | ||||||
|  | 	ALOAD_3(0x2d, "aload_3", kInstrCanContinue, 1), // -- | ||||||
|  | 	IALOAD(0x2e, "iaload", kInstrCanContinue, -1), // -- | ||||||
|  | 	LALOAD(0x2f, "laload", kInstrCanContinue, 0), // -- | ||||||
|  | 	FALOAD(0x30, "faload", kInstrCanContinue, -1), // -- | ||||||
|  | 	DALOAD(0x31, "daload", kInstrCanContinue, 0), // -- | ||||||
|  | 	AALOAD(0x32, "aaload", kInstrCanContinue, -1), // -- | ||||||
|  | 	BALOAD(0x33, "baload", kInstrCanContinue, -1), // -- | ||||||
|  | 	CALOAD(0x34, "caload", kInstrCanContinue, -1), // -- | ||||||
|  | 	SALOAD(0x35, "saload", kInstrCanContinue, -1), // -- | ||||||
|  | 	ISTORE(0x36, "istore", kInstrCanContinue, -1), // -- | ||||||
|  | 	LSTORE(0x37, "lstore", kInstrCanContinue, -2), // -- | ||||||
|  | 	FSTORE(0x38, "fstore", kInstrCanContinue, -1), // -- | ||||||
|  | 	DSTORE(0x39, "dstore", kInstrCanContinue, -2), // -- | ||||||
|  | 	ASTORE(0x3a, "astore", kInstrCanContinue, -1), // -- | ||||||
|  | 	ISTORE_0(0x3b, "istore_0", kInstrCanContinue, -1), // -- | ||||||
|  | 	ISTORE_1(0x3c, "istore_1", kInstrCanContinue, -1), // -- | ||||||
|  | 	ISTORE_2(0x3d, "istore_2", kInstrCanContinue, -1), // -- | ||||||
|  | 	ISTORE_3(0x3e, "istore_3", kInstrCanContinue, -1), // -- | ||||||
|  | 	LSTORE_0(0x3f, "lstore_0", kInstrCanContinue, -2), // -- | ||||||
|  | 	LSTORE_1(0x40, "lstore_1", kInstrCanContinue, -2), // -- | ||||||
|  | 	LSTORE_2(0x41, "lstore_2", kInstrCanContinue, -2), // -- | ||||||
|  | 	LSTORE_3(0x42, "lstore_3", kInstrCanContinue, -2), // -- | ||||||
|  | 	FSTORE_0(0x43, "fstore_0", kInstrCanContinue, -1), // -- | ||||||
|  | 	FSTORE_1(0x44, "fstore_1", kInstrCanContinue, -1), // -- | ||||||
|  | 	FSTORE_2(0x45, "fstore_2", kInstrCanContinue, -1), // -- | ||||||
|  | 	FSTORE_3(0x46, "fstore_3", kInstrCanContinue, -1), // -- | ||||||
|  | 	DSTORE_0(0x47, "dstore_0", kInstrCanContinue, -2), // -- | ||||||
|  | 	DSTORE_1(0x48, "dstore_1", kInstrCanContinue, -2), // -- | ||||||
|  | 	DSTORE_2(0x49, "dstore_2", kInstrCanContinue, -2), // -- | ||||||
|  | 	DSTORE_3(0x4a, "dstore_3", kInstrCanContinue, -2), // -- | ||||||
|  | 	ASTORE_0(0x4b, "astore_0", kInstrCanContinue, -1), // -- | ||||||
|  | 	ASTORE_1(0x4c, "astore_1", kInstrCanContinue, -1), // -- | ||||||
|  | 	ASTORE_2(0x4d, "astore_2", kInstrCanContinue, -1), // -- | ||||||
|  | 	ASTORE_3(0x4e, "astore_3", kInstrCanContinue, -1), // -- | ||||||
|  | 	IASTORE(0x4f, "iastore", kInstrCanContinue, -3), // -- | ||||||
|  | 	LASTORE(0x50, "lastore", kInstrCanContinue, -4), // -- | ||||||
|  | 	FASTORE(0x51, "fastore", kInstrCanContinue, -3), // -- | ||||||
|  | 	DASTORE(0x52, "dastore", kInstrCanContinue, -4), // -- | ||||||
|  | 	AASTORE(0x53, "aastore", kInstrCanContinue, -3), // -- | ||||||
|  | 	BASTORE(0x54, "bastore", kInstrCanContinue, -3), // -- | ||||||
|  | 	CASTORE(0x55, "castore", kInstrCanContinue, -3), // -- | ||||||
|  | 	SASTORE(0x56, "sastore", kInstrCanContinue, -3), // -- | ||||||
|  | 	POP(0x57, "pop", kInstrCanContinue, -1), // -- | ||||||
|  | 	POP2(0x58, "pop2", kInstrCanContinue, -2), // -- | ||||||
|  | 	DUP(0x59, "dup", kInstrCanContinue, 1), // -- | ||||||
|  | 	DUP_X1(0x5a, "dup_x1", kInstrCanContinue, 1), // -- | ||||||
|  | 	DUP_X2(0x5b, "dup_x2", kInstrCanContinue, 1), // -- | ||||||
|  | 	DUP2(0x5c, "dup2", kInstrCanContinue, 2), // -- | ||||||
|  | 	DUP2_X1(0x5d, "dup2_x1", kInstrCanContinue, 2), // -- | ||||||
|  | 	DUP2_X2(0x5e, "dup2_x2", kInstrCanContinue, 2), // -- | ||||||
|  | 	SWAP(0x5f, "swap", kInstrCanContinue, 0), // -- | ||||||
|  | 	IADD(0x60, "iadd", kInstrCanContinue, -1), // -- | ||||||
|  | 	LADD(0x61, "ladd", kInstrCanContinue, -2), // -- | ||||||
|  | 	FADD(0x62, "fadd", kInstrCanContinue, -1), // -- | ||||||
|  | 	DADD(0x63, "dadd", kInstrCanContinue, -2), // -- | ||||||
|  | 	ISUB(0x64, "isub", kInstrCanContinue, -1), // -- | ||||||
|  | 	LSUB(0x65, "lsub", kInstrCanContinue, -2), // -- | ||||||
|  | 	FSUB(0x66, "fsub", kInstrCanContinue, -1), // -- | ||||||
|  | 	DSUB(0x67, "dsub", kInstrCanContinue, -2), // -- | ||||||
|  | 	IMUL(0x68, "imul", kInstrCanContinue, -1), // -- | ||||||
|  | 	LMUL(0x69, "lmul", kInstrCanContinue, -2), // -- | ||||||
|  | 	FMUL(0x6a, "fmul", kInstrCanContinue, -1), // -- | ||||||
|  | 	DMUL(0x6b, "dmul", kInstrCanContinue, -2), // -- | ||||||
|  | 	IDIV(0x6c, "idiv", kInstrCanContinue, -1), // -- | ||||||
|  | 	LDIV(0x6d, "ldiv", kInstrCanContinue, -2), // -- | ||||||
|  | 	FDIV(0x6e, "fdiv", kInstrCanContinue, -1), // -- | ||||||
|  | 	DDIV(0x6f, "ddiv", kInstrCanContinue, -2), // -- | ||||||
|  | 	IREM(0x70, "irem", kInstrCanContinue, -1), // -- | ||||||
|  | 	LREM(0x71, "lrem", kInstrCanContinue, -2), // -- | ||||||
|  | 	FREM(0x72, "frem", kInstrCanContinue, -1), // -- | ||||||
|  | 	DREM(0x73, "drem", kInstrCanContinue, -2), // -- | ||||||
|  | 	INEG(0x74, "ineg", kInstrCanContinue, 0), // -- | ||||||
|  | 	LNEG(0x75, "lneg", kInstrCanContinue, 0), // -- | ||||||
|  | 	FNEG(0x76, "fneg", kInstrCanContinue, 0), // -- | ||||||
|  | 	DNEG(0x77, "dneg", kInstrCanContinue, 0), // -- | ||||||
|  | 	ISHL(0x78, "ishl", kInstrCanContinue, -1), // -- | ||||||
|  | 	LSHL(0x79, "lshl", kInstrCanContinue, -1), // -- | ||||||
|  | 	ISHR(0x7a, "ishr", kInstrCanContinue, -1), // -- | ||||||
|  | 	LSHR(0x7b, "lshr", kInstrCanContinue, -1), // -- | ||||||
|  | 	IUSHR(0x7c, "iushr", kInstrCanContinue, -1), // -- | ||||||
|  | 	LUSHR(0x7d, "lushr", kInstrCanContinue, -1), // -- | ||||||
|  | 	IAND(0x7e, "iand", kInstrCanContinue, -1), // -- | ||||||
|  | 	LAND(0x7f, "land", kInstrCanContinue, -2), // -- | ||||||
|  | 	IOR(0x80, "ior", kInstrCanContinue, -1), // -- | ||||||
|  | 	LOR(0x81, "lor", kInstrCanContinue, -2), // -- | ||||||
|  | 	IXOR(0x82, "ixor", kInstrCanContinue, -1), // -- | ||||||
|  | 	LXOR(0x83, "lxor", kInstrCanContinue, -2), // -- | ||||||
|  | 	IINC(0x84, "iinc", kInstrCanContinue, 0), // -- | ||||||
|  | 	I2L(0x85, "i2l", kInstrCanContinue, 1), // -- | ||||||
|  | 	I2F(0x86, "i2f", kInstrCanContinue, 0), // -- | ||||||
|  | 	I2D(0x87, "i2d", kInstrCanContinue, 1), // -- | ||||||
|  | 	L2I(0x88, "l2i", kInstrCanContinue, -1), // -- | ||||||
|  | 	L2F(0x89, "l2f", kInstrCanContinue, -1), // -- | ||||||
|  | 	L2D(0x8a, "l2d", kInstrCanContinue, 0), // -- | ||||||
|  | 	F2I(0x8b, "f2i", kInstrCanContinue, 0), // -- | ||||||
|  | 	F2L(0x8c, "f2l", kInstrCanContinue, 1), // -- | ||||||
|  | 	F2D(0x8d, "f2d", kInstrCanContinue, 1), // -- | ||||||
|  | 	D2I(0x8e, "d2i", kInstrCanContinue, -1), // -- | ||||||
|  | 	D2L(0x8f, "d2l", kInstrCanContinue, 0), // -- | ||||||
|  | 	D2F(0x90, "d2f", kInstrCanContinue, -1), // -- | ||||||
|  | 	I2B(0x91, "i2b", kInstrCanContinue, 0), // -- | ||||||
|  | 	I2C(0x92, "i2c", kInstrCanContinue, 0), // -- | ||||||
|  | 	I2S(0x93, "i2s", kInstrCanContinue, 0), // -- | ||||||
|  | 	LCMP(0x94, "lcmp", kInstrCanContinue, -2), // -- | ||||||
|  | 	FCMPL(0x95, "fcmpl", kInstrCanContinue, -1), // -- | ||||||
|  | 	FCMPG(0x96, "fcmpg", kInstrCanContinue, -1), // -- | ||||||
|  | 	DCMPL(0x97, "dcmpl", kInstrCanContinue, -3), // -- | ||||||
|  | 	DCMPG(0x98, "dcmpg", kInstrCanContinue, -3), // -- | ||||||
|  | 	IFEQ(0x99, "ifeq", kInstrCanBranch, -1), // -- | ||||||
|  | 	IFNE(0x9a, "ifne", kInstrCanBranch, -1), // -- | ||||||
|  | 	IFLT(0x9b, "iflt", kInstrCanBranch, -1), // -- | ||||||
|  | 	IFGE(0x9c, "ifge", kInstrCanBranch, -1), // -- | ||||||
|  | 	IFGT(0x9d, "ifgt", kInstrCanBranch, -1), // -- | ||||||
|  | 	IFLE(0x9e, "ifle", kInstrCanBranch, -1), // -- | ||||||
|  | 	IF_ICMPEQ(0x9f, "if_icmpeq", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ICMPNE(0xa0, "if_icmpne", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ICMPLT(0xa1, "if_icmplt", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ICMPGE(0xa2, "if_icmpge", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ICMPGT(0xa3, "if_icmpgt", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ICMPLE(0xa4, "if_icmple", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ACMPEQ(0xa5, "if_acmpeq", kInstrCanBranch, -2), // -- | ||||||
|  | 	IF_ACMPNE(0xa6, "if_acmpne", kInstrCanBranch, -2), // -- | ||||||
|  | 	GOTO(0xa7, "goto", kInstrCanBranch, 0), // -- | ||||||
|  | 	JSR(0xa8, "jsr", kInstrCanContinue, 1), // ??-- | ||||||
|  | 	RET(0xa9, "ret", kInstrCanContinue, -1), // ??-- | ||||||
|  | 	TABLESWITCH(0xaa, "tableswitch", kInstrCanBranch, 1), // -- | ||||||
|  | 	LOOKUPSWITCH(0xab, "lookupswitch", kInstrCanBranch, 0), // -- | ||||||
|  | 	IRETURN(0xac, "ireturn", kInstrCanReturn, -1), // -- | ||||||
|  | 	LRETURN(0xad, "lreturn", kInstrCanReturn, -2), // -- | ||||||
|  | 	FRETURN(0xae, "freturn", kInstrCanReturn, -1), // -- | ||||||
|  | 	DRETURN(0xaf, "dreturn", kInstrCanReturn, -2), // -- | ||||||
|  | 	ARETURN(0xb0, "areturn", kInstrCanReturn, -1), // -- | ||||||
|  | 	RETURN(0xb1, "return", kInstrCanReturn, 0), // -- | ||||||
|  | 	GETSTATIC(0xb2, "getstatic", kInstrCanContinue, 0), // dynamic changing+ -- | ||||||
|  | 	PUTSTATIC(0xb3, "putstatic", kInstrCanContinue, 0), // dynamic changing- -- | ||||||
|  | 	GETFIELD(0xb4, "getfield", kInstrCanContinue, 0), // dynamic changing_+ -- | ||||||
|  | 	PUTFIELD(0xb5, "putfield", kInstrCanContinue, 0), // dynamic changing-- -- | ||||||
|  | 	INVOKEVIRTUAL(0xb6, "invokevirtual", kInstrInvoke | kInstrCanThrow, 0), // dynamic changing-- -- | ||||||
|  | 	INVOKESPECIAL(0xb7, "invokespecial", kInstrInvoke | kInstrCanThrow, 0), // dynamic changing-- -- | ||||||
|  | 	INVOKESTATIC(0xb8, "invokestatic", kInstrInvoke | kInstrCanThrow, 0), // dynamic changing-- -- | ||||||
|  | 	INVOKEINTERFACE(0xb9, "invokeinterface", kInstrInvoke | kInstrCanThrow, 0), // dynamic changing-- -- | ||||||
|  | 	INVOKEDYNAMIC(0xba, "invokedynamic", kInstrInvoke | kInstrCanThrow, 0), // dynamic changing-- -- | ||||||
|  | 	NEW(0xbb, "new", kInstrCanContinue, 1), // -- | ||||||
|  | 	NEWARRAY(0xbc, "newarray", kInstrCanContinue, 0), // -- | ||||||
|  | 	ANEWARRAY(0xbd, "anewarray", kInstrCanContinue, 0), // -- | ||||||
|  | 	ARRAYLENGTH(0xbe, "arraylength", kInstrCanContinue, 0), // -- | ||||||
|  | 	ATHROW(0xbf, "athrow", kInstrCanReturn, 0), // -- | ||||||
|  | 	CHECKCAST(0xc0, "checkcast", kInstrCanContinue, 0), // -- | ||||||
|  | 	INSTANCEOF(0xc1, "instanceof", kInstrCanContinue, 0), // -- | ||||||
|  | 	MONITORENTER(0xc2, "monitorenter", kInstrCanContinue, -1), // -- | ||||||
|  | 	MONITOREXIT(0xc3, "monitorexit", kInstrCanContinue, -1), // -- | ||||||
|  | 	WIDE(0xc4, "wide", kInstrCanContinue, 0), // -- | ||||||
|  | 	MULTIANEWARRAY(0xc5, "multianewarray", kInstrCanContinue, 0), // dynamic changing-- | ||||||
|  | 	IFNULL(0xc6, "ifnull", kInstrCanBranch, -1), // -- | ||||||
|  | 	IFNONNULL(0xc7, "ifnonnull", kInstrCanBranch, -1), // -- | ||||||
|  | 	GOTO_W(0xc8, "goto_w", kInstrCanBranch, 0), // -- | ||||||
|  | 	JSR_W(0xc9, "jsr_w", kInstrCanContinue, 1);// ??-- | ||||||
|  | 	public final static OpInfo ops[] = new OpInfo[256]; | ||||||
|  | 
 | ||||||
|  | 	static { | ||||||
|  | 		OpInfo[] ops = OpInfo.ops; | ||||||
|  | 		for (OpInfo op : OpInfo.values()) { | ||||||
|  | 			if (op.opcode >= 0) { | ||||||
|  | 				ops[op.opcode] = op; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	public boolean changeFrame; | ||||||
|  | 	int changeStack; | ||||||
|  | 	private int flags; | ||||||
|  | 	private String displayName; | ||||||
|  | 	private int opcode; | ||||||
|  | 
 | ||||||
|  | 	OpInfo() { | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	OpInfo(int opcode, String displayName, int branchType, int changStack) { | ||||||
|  | 		flags = branchType; | ||||||
|  | 		this.displayName = displayName; | ||||||
|  | 		this.opcode = opcode; | ||||||
|  | 		this.changeStack = changeStack; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean canBranch() { | ||||||
|  | 		return 0 != (flags & kInstrCanBranch); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean canContinue() { | ||||||
|  | 		return 0 != (flags & kInstrCanContinue); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean canReturn() { | ||||||
|  | 		return 0 != (flags & kInstrCanReturn); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean canSwitch() { | ||||||
|  | 		return 0 != (flags & kInstrCanSwitch); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public boolean canThrow() { | ||||||
|  | 		return 0 != (flags & kInstrCanThrow); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	public String toString() { | ||||||
|  | 		return displayName; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,193 @@ | |||||||
|  | package org.bdware.analysis.dynamic; | ||||||
|  | 
 | ||||||
|  | import org.apache.logging.log4j.LogManager; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.BreadthFirstSearch; | ||||||
|  | import org.bdware.analysis.OpInfo; | ||||||
|  | import org.bdware.analysis.taint.TaintBB; | ||||||
|  | import org.bdware.analysis.taint.TaintCFG; | ||||||
|  | import org.bdware.analysis.taint.TaintResult; | ||||||
|  | import org.bdware.analysis.taint.TaintValue; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.JumpInsnNode; | ||||||
|  | import org.objectweb.asm.tree.LabelNode; | ||||||
|  | import org.objectweb.asm.tree.MethodNode; | ||||||
|  | 
 | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public class FieldSensitiveDynamicTaintAnalysis extends BreadthFirstSearch<TaintResult, TaintBB> { | ||||||
|  |     private static final Logger LOGGER = LogManager.getLogger(FieldSensitiveDynamicTaintAnalysis.class); | ||||||
|  |     public static boolean isDebug = false; | ||||||
|  |     TaintCFG cfg; | ||||||
|  |     TracedFile tf; | ||||||
|  |     int count = 0; | ||||||
|  | 
 | ||||||
|  |     public FieldSensitiveDynamicTaintAnalysis(TaintCFG cfg, TracedFile tf) { | ||||||
|  |         this.cfg = cfg; | ||||||
|  |         this.tf = tf; | ||||||
|  |         List<TaintBB> toAnalysis = new ArrayList<>(); | ||||||
|  |         MethodNode mn = cfg.getMethodNode(); | ||||||
|  |         LOGGER.info("mn: " + mn.name); | ||||||
|  |         String methodDesc = mn.desc; | ||||||
|  |         LOGGER.info("method desc: " + methodDesc); | ||||||
|  |         methodDesc = methodDesc.replaceAll("\\).*$", ")"); | ||||||
|  |         LOGGER.info("method desc: " + methodDesc); | ||||||
|  |         int pos = 2; | ||||||
|  |         if (methodDesc.split(";").length == 3) | ||||||
|  |             pos = 1; | ||||||
|  |         // TODO add inputBlock! | ||||||
|  |         LOGGER.info("p+++ " + pos); | ||||||
|  |         TaintBB b = (TaintBB) cfg.getBasicBlockAt(0); | ||||||
|  |         b.preResult = new TaintResult(); | ||||||
|  |         LOGGER.info(TaintResult.nLocals); | ||||||
|  |         if (TaintResult.nLocals > 2) { | ||||||
|  |             for (int i = 0; i < TaintResult.nLocals; i++) | ||||||
|  |                 b.preResult.frame.setLocal(i, new TaintValue(1, i == pos ? 1 : 0)); | ||||||
|  |         } | ||||||
|  |         b.preResult.ret = new TaintValue(1); | ||||||
|  |         // NaiveTaintResult.printer.setLabelOrder(cfg.getLabelOrder()); | ||||||
|  |         toAnalysis.add(b); | ||||||
|  |         b.setInList(true); | ||||||
|  |         setToAnalysis(toAnalysis); | ||||||
|  |         if (isDebug) { | ||||||
|  |             MethodNode methodNode = cfg.getMethodNode(); | ||||||
|  |             LOGGER.info("Method: " + methodNode.name + " " + methodNode.desc); | ||||||
|  |             LOGGER.info("Local: " + methodNode.maxLocals + " " + methodNode.maxStack); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public TaintResult execute(TaintBB t) { | ||||||
|  |         return t.forwardAnalysis(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Current Block is done, merge sucResult to sucBlocks! | ||||||
|  |     @Override | ||||||
|  |     public Collection<TaintBB> getSuc(TaintBB t) { | ||||||
|  |         Set<BasicBlock> subBlock = new HashSet<>();// | ||||||
|  |         if (t.list.size() > 0) { | ||||||
|  |             AbstractInsnNode insn = t.lastInsn(); | ||||||
|  |             if (insn != null) { | ||||||
|  |                 OpInfo info = null; | ||||||
|  |                 if (insn.getOpcode() >= 0) | ||||||
|  |                     info = OpInfo.ops[insn.getOpcode()]; | ||||||
|  |                 if (info == null) { | ||||||
|  |                     subBlock.addAll(cfg.getSucBlocks(t)); | ||||||
|  |                 } else if (info.canThrow()) { | ||||||
|  |                     // subBlock.clear(); | ||||||
|  |                     subBlock.add(cfg.getBasicBlockAt(t.blockID + 1)); | ||||||
|  |                 } else if (OpInfo.ops[insn.getOpcode()].canBranch()) { | ||||||
|  | //                    subBlock.clear(); | ||||||
|  | //                    LOGGER.info("can branch " + t.blockID); | ||||||
|  |                     int block = handleBranchCase(subBlock, insn, t); | ||||||
|  |                     subBlock.add(cfg.getBasicBlockAt(block)); | ||||||
|  |                 } else if (OpInfo.ops[insn.getOpcode()].canSwitch()) { | ||||||
|  |                     subBlock.add(cfg.getBasicBlockAt(t.blockID + 1)); | ||||||
|  |                 } else { | ||||||
|  |                     subBlock.addAll(cfg.getSucBlocks(t)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Set<TaintBB> ret = new HashSet<>(); | ||||||
|  | //        StringBuilder log = new StringBuilder("nextBB:"); | ||||||
|  |         for (BasicBlock bb : subBlock) { | ||||||
|  | //            log.append("\n\t").append(bb.blockID); | ||||||
|  |             TaintBB ntbb = (TaintBB) bb; | ||||||
|  |             ntbb.preResult.mergeResult(t.sucResult); | ||||||
|  |             ret.add(ntbb); | ||||||
|  |         } | ||||||
|  | //        LOGGER.info(log.toString()); | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private int handleBranchCase(Set<BasicBlock> subBlock, AbstractInsnNode insn, TaintBB t) { | ||||||
|  |         int blockid = 0; | ||||||
|  |         switch (insn.getOpcode()) { | ||||||
|  |             case Opcodes.IFNE:// succeeds if and only if value ≠ 0 | ||||||
|  |                 count++; | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(0).get(0) != 0) { | ||||||
|  |                     // test first tracemark{"traceMark":0, "val":1} | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFEQ:// succeeds if and only if value = 0 | ||||||
|  | 
 | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(0).get(0) == 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFGE:// succeeds if and only if value ≥ 0 | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(0).get(0) >= 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFLE:// succeeds if and only if value ≤ 0 | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(0).get(0) <= 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFLT:// succeeds if and only if value < 0 | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(0).get(0) < 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFGT:// succeeds if and only if value > 0 | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(0).get(0) < 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IF_ACMPEQ:// succeeds if and only if value1 = value2 | ||||||
|  |             case Opcodes.IF_ACMPNE:// succeeds if and only if value1 ≠ value2 | ||||||
|  |             case Opcodes.IF_ICMPEQ:// succeeds if and only if value1 = value2 | ||||||
|  |             case Opcodes.IF_ICMPGE:// succeeds if and only if value1 ≠ value2 | ||||||
|  |             case Opcodes.IF_ICMPGT:// succeeds if and only if value1 > value2 | ||||||
|  |             case Opcodes.IF_ICMPLE:// succeeds if and only if value1 ≤ value2 | ||||||
|  |             case Opcodes.IF_ICMPLT:// succeeds if and only if value1 < value2 | ||||||
|  | 
 | ||||||
|  |             case Opcodes.IFNONNULL: | ||||||
|  |             case Opcodes.TABLESWITCH: | ||||||
|  |             case Opcodes.LOOKUPSWITCH: | ||||||
|  |             default: | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.GOTO: | ||||||
|  |                 if (insn instanceof JumpInsnNode) { | ||||||
|  |                     LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                     blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                 } | ||||||
|  |         } | ||||||
|  |         return blockid; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,208 @@ | |||||||
|  | package org.bdware.analysis.dynamic; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.BreadthFirstSearch; | ||||||
|  | import org.bdware.analysis.OpInfo; | ||||||
|  | import org.bdware.analysis.taint.*; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.*; | ||||||
|  | 
 | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public class NaiveDynamicTaintAnalysis extends BreadthFirstSearch<TaintResult, TaintBB> { | ||||||
|  | 
 | ||||||
|  |     TaintCFG cfg; | ||||||
|  |     TracedFile tf; | ||||||
|  |     public static boolean isDebug = false; | ||||||
|  |     int count = 0; | ||||||
|  |     String functionGlobel; | ||||||
|  |     public static HashMap<String, HashMap<Integer, Integer>> branchCount = new HashMap<>(); | ||||||
|  | 
 | ||||||
|  |     public NaiveDynamicTaintAnalysis(TaintCFG cfg, TracedFile tf) { | ||||||
|  |         this.cfg = cfg; | ||||||
|  |         this.tf = tf; | ||||||
|  |         List<TaintBB> toAnalysis = new ArrayList<>(); | ||||||
|  |         MethodNode mn = cfg.getMethodNode(); | ||||||
|  | 
 | ||||||
|  |         String methodDesc = mn.desc; | ||||||
|  |         methodDesc = methodDesc.replaceAll("\\).*$", ")"); | ||||||
|  |         int pos = 2; | ||||||
|  |         if (methodDesc.split(";").length == 3) pos = 1; | ||||||
|  |         // TODO add inputBlock! | ||||||
|  |         TaintBB b = (TaintBB) cfg.getBasicBlockAt(0); | ||||||
|  |         b.preResult = new TaintResult(); | ||||||
|  |         int arg = cfg.argsLocal(); | ||||||
|  |         b.preResult.frame.setLocal(arg, new TaintValue(1, cfg.taintBits.allocate("arg" + arg))); | ||||||
|  |         b.preResult.frame.setLocal(0, HeapObject.getRootObject()); | ||||||
|  |         cfg.executeLocal(); | ||||||
|  |         TaintResult.interpreter.setTaintBits(cfg.taintBits); | ||||||
|  |         functionGlobel = cfg.getMethodNode().name; | ||||||
|  |         branchCount.put(functionGlobel, new HashMap<Integer, Integer>()); | ||||||
|  |         // local0=scriptfuncion, is not tainted; | ||||||
|  |         // local1=this, is not tainted; | ||||||
|  |         // local2=this, is not tainted; | ||||||
|  |         // NaiveTaintResult.printer.setLabelOrder(cfg.getLabelOrder()); | ||||||
|  |         toAnalysis.add(b); | ||||||
|  |         b.setInList(true); | ||||||
|  |         setToAnalysis(toAnalysis); | ||||||
|  |         if (isDebug) { | ||||||
|  |             System.out.println("===Method:" + cfg.getMethodNode().name + cfg.getMethodNode().desc); | ||||||
|  |             System.out.println( | ||||||
|  |                     "===Local:" | ||||||
|  |                             + cfg.getMethodNode().maxLocals | ||||||
|  |                             + " " | ||||||
|  |                             + cfg.getMethodNode().maxStack); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public TaintResult execute(TaintBB t) { | ||||||
|  |         return t.forwardAnalysis(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Current Block is done, merge sucResult to sucBlocks! | ||||||
|  |     @Override | ||||||
|  |     public Collection<TaintBB> getSuc(TaintBB t) { | ||||||
|  |         Set<BasicBlock> subBlock = new HashSet<>(); // bug ! clear() no suc | ||||||
|  |         if (t.list.size() > 0) { | ||||||
|  |             AbstractInsnNode insn = t.lastInsn(); | ||||||
|  |             if (insn != null) { | ||||||
|  |                 OpInfo info = null; | ||||||
|  |                 if (insn.getOpcode() >= 0) info = OpInfo.ops[insn.getOpcode()]; | ||||||
|  |                 if (info == null) { | ||||||
|  |                     subBlock.addAll(cfg.getSucBlocks(t)); | ||||||
|  |                 } else if (info.canThrow()) { | ||||||
|  |                     callCount(insn); | ||||||
|  |                     subBlock.add(cfg.getBasicBlockAt(t.blockID + 1)); | ||||||
|  |                 } else if (OpInfo.ops[insn.getOpcode()].canBranch()) { | ||||||
|  |                     subBlock.clear(); | ||||||
|  |                     int block = handleBranchCase(subBlock, insn, t); | ||||||
|  |                     subBlock.add(cfg.getBasicBlockAt(block)); | ||||||
|  |                 } else if (OpInfo.ops[insn.getOpcode()].canSwitch()) { | ||||||
|  |                     subBlock.add(cfg.getBasicBlockAt(t.blockID + 1)); | ||||||
|  |                 } else { | ||||||
|  |                     subBlock.addAll(cfg.getSucBlocks(t)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Set<TaintBB> ret = new HashSet<>(); | ||||||
|  |         // System.out.print("[NaiveDynamicTaintAnalysis] nextBB:"); | ||||||
|  |         for (BasicBlock bb : subBlock) { | ||||||
|  |             // System.out.print(" " + bb.blockID); | ||||||
|  |             TaintBB ntbb = (TaintBB) bb; | ||||||
|  |             ntbb.preResult.mergeResult(t.sucResult); | ||||||
|  |             ret.add(ntbb); | ||||||
|  |         } | ||||||
|  |         // System.out.println(); | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void callCount(AbstractInsnNode insn) { | ||||||
|  |         if (insn instanceof InvokeDynamicInsnNode) { | ||||||
|  |             Object invoke = ((InvokeDynamicInsnNode) insn).bsmArgs[0]; | ||||||
|  |             String functionName = ((InvokeDynamicInsnNode) insn).name; | ||||||
|  |             if (functionName.contains("traceif")) { | ||||||
|  |                 traceIfNum = (int) invoke; | ||||||
|  |                 if (branchCount.get(functionGlobel).containsKey(traceIfNum)) { | ||||||
|  |                     branchCount | ||||||
|  |                             .get(functionGlobel) | ||||||
|  |                             .put(traceIfNum, branchCount.get(functionGlobel).get(traceIfNum) + 1); | ||||||
|  |                 } else { | ||||||
|  |                     branchCount.get(functionGlobel).put(traceIfNum, 1); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int traceIfNum = 0; | ||||||
|  | 
 | ||||||
|  |     private int handleBranchCase(Set<BasicBlock> subBlock, AbstractInsnNode insn, TaintBB t) { | ||||||
|  |         int blockid = 0; | ||||||
|  |         switch (insn.getOpcode()) { | ||||||
|  |             case Opcodes.IFNE: // succeeds if and only if value ≠ 0 | ||||||
|  |                 int ifneCount = branchCount.get(functionGlobel).get(traceIfNum); | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(traceIfNum).get(ifneCount) != 0) { // test first | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFEQ: // succeeds if and only if value = 0 | ||||||
|  |                 int ifeqCount = branchCount.get(functionGlobel).get(traceIfNum); | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(traceIfNum).get(ifeqCount) == 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFGE: // succeeds if and only if value ≥ 0 | ||||||
|  |                 int ifgeCount = branchCount.get(functionGlobel).get(traceIfNum); | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(traceIfNum).get(ifgeCount) >= 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFLE: // succeeds if and only if value ≤ 0 | ||||||
|  |                 int ifleCount = branchCount.get(functionGlobel).get(traceIfNum); | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(traceIfNum).get(ifleCount) <= 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFLT: // succeeds if and only if value < 0 | ||||||
|  |                 int ifltCount = branchCount.get(functionGlobel).get(traceIfNum); | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(traceIfNum).get(ifltCount) < 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IFGT: // succeeds if and only if value > 0 | ||||||
|  |                 int ifgtCount = branchCount.get(functionGlobel).get(traceIfNum); | ||||||
|  |                 if (tf.trans.get(0).tmToVal.get(traceIfNum).get(ifgtCount) < 0) { | ||||||
|  |                     if (insn instanceof JumpInsnNode) { | ||||||
|  |                         LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                         blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     blockid = t.blockID + 1; | ||||||
|  |                 } | ||||||
|  |                 return blockid; | ||||||
|  |             case Opcodes.IF_ACMPEQ: // succeeds if and only if value1 = value2 | ||||||
|  |             case Opcodes.IF_ACMPNE: // succeeds if and only if value1 ≠ value2 | ||||||
|  |             case Opcodes.IF_ICMPEQ: // succeeds if and only if value1 = value2 | ||||||
|  |             case Opcodes.IF_ICMPGE: // succeeds if and only if value1 ≠ value2 | ||||||
|  |             case Opcodes.IF_ICMPGT: // succeeds if and only if value1 > value2 | ||||||
|  |             case Opcodes.IF_ICMPLE: // succeeds if and only if value1 ≤ value2 | ||||||
|  |             case Opcodes.IF_ICMPLT: // succeeds if and only if value1 < value2 | ||||||
|  |             case Opcodes.IFNONNULL: | ||||||
|  |             case Opcodes.TABLESWITCH: | ||||||
|  |             case Opcodes.LOOKUPSWITCH: | ||||||
|  |             default: | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.GOTO: | ||||||
|  |                 if (insn instanceof JumpInsnNode) { | ||||||
|  |                     LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                     blockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                 } | ||||||
|  |         } | ||||||
|  |         return blockid; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,91 @@ | |||||||
|  | package org.bdware.analysis.dynamic; | ||||||
|  | 
 | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import com.google.gson.JsonParser; | ||||||
|  | import org.apache.logging.log4j.LogManager; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | 
 | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public class ProgramPoint { | ||||||
|  |     private static final Logger LOGGER = LogManager.getLogger(ProgramPoint.class); | ||||||
|  |     List<Transaction> trans; | ||||||
|  |     List<FunctionTran> functionTrans; | ||||||
|  | 
 | ||||||
|  |     public ProgramPoint(InputStream in) { | ||||||
|  |         Scanner sc = new Scanner(in); | ||||||
|  |         trans = new ArrayList<>(); | ||||||
|  |         functionTrans = new ArrayList<>(); | ||||||
|  |         Transaction transaction = new Transaction(); | ||||||
|  |         FunctionTran functionTran = new FunctionTran(); | ||||||
|  |         transaction.tmToVal = new HashMap<>(); | ||||||
|  |         functionTran.ppToVal = new HashMap<>(); | ||||||
|  |         // TODO ignore handle transaction start | ||||||
|  |         // TODO ignore handle contractID/method.... | ||||||
|  |         // TODO ignore handle transaction end | ||||||
|  |         while (sc.hasNextLine()) { | ||||||
|  |             String string = sc.nextLine().replace("[ProgramPointCounter]", ""); | ||||||
|  |             LOGGER.debug("[string: ]" + string); | ||||||
|  |             if (string.contains("ENTER")) { | ||||||
|  |                 String[] strings = string.split("_"); | ||||||
|  |                 strings = strings[1].split("[(]"); | ||||||
|  |                 System.out.println("[stringsss: ]" + strings[0]); | ||||||
|  |                 functionTran.insert(strings[0], "ENTER"); | ||||||
|  |             } | ||||||
|  |             //			if (string.contains("EXIT")) { | ||||||
|  |             //				String[] strings = string.split("_"); | ||||||
|  |             //				strings=strings[1].split("-"); | ||||||
|  |             //				System.out.println("[stringsss: ]" + strings[0]); | ||||||
|  |             //				functionMap.put(strings[1], "EXIT"); | ||||||
|  |             //			} | ||||||
|  |             if (string.contains("traceMark")) { | ||||||
|  |                 JsonObject jo = JsonParser.parseString(string).getAsJsonObject(); | ||||||
|  |                 if (jo.get("traceMark") != null) { | ||||||
|  |                     if (jo.get("lval") != null) { | ||||||
|  |                         transaction.insert( | ||||||
|  |                                 jo.get("traceMark").getAsInt(), jo.get("lval").getAsInt()); | ||||||
|  |                         transaction.insert( | ||||||
|  |                                 jo.get("traceMark").getAsInt(), jo.get("rval").getAsInt()); | ||||||
|  |                     } else { | ||||||
|  |                         transaction.insert( | ||||||
|  |                                 jo.get("traceMark").getAsInt(), jo.get("val").getAsInt()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         LOGGER.info(functionTran.ppToVal); | ||||||
|  |         LOGGER.info(transaction.tmToVal); | ||||||
|  |         sc.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     static class Transaction { | ||||||
|  |         Map<Integer, List<Integer>> tmToVal; | ||||||
|  | 
 | ||||||
|  |         public void insert(int traceMark, int val) { | ||||||
|  |             List<Integer> ret; | ||||||
|  |             if (!tmToVal.containsKey(traceMark)) { | ||||||
|  |                 ret = new ArrayList<>(); | ||||||
|  |                 tmToVal.put(traceMark, ret); | ||||||
|  |             } else { | ||||||
|  |                 ret = tmToVal.get(traceMark); | ||||||
|  |             } | ||||||
|  |             ret.add(val); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     static class FunctionTran { | ||||||
|  |         Map<String, List<String>> ppToVal; | ||||||
|  | 
 | ||||||
|  |         public void insert(String functionID, String val) { | ||||||
|  |             List<String> ret; | ||||||
|  |             if (!ppToVal.containsKey(functionID)) { | ||||||
|  |                 ret = new ArrayList<>(); | ||||||
|  |                 ppToVal.put(functionID, ret); | ||||||
|  |             } else { | ||||||
|  |                 ret = ppToVal.get(functionID); | ||||||
|  |             } | ||||||
|  |             ret.add(val); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,49 @@ | |||||||
|  | package org.bdware.analysis.dynamic; | ||||||
|  | 
 | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  | import com.google.gson.JsonParser; | ||||||
|  | 
 | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public class TracedFile { | ||||||
|  |     public List<Transaction> trans; | ||||||
|  | 
 | ||||||
|  |     public TracedFile(InputStream in) { | ||||||
|  |         Scanner sc = new Scanner(in); | ||||||
|  |         trans = new ArrayList<>(); | ||||||
|  |         Transaction transaction = new Transaction(); | ||||||
|  |         transaction.tmToVal = new HashMap<Integer, List<Integer>>(); | ||||||
|  |         // TODO ignore handle transaction start | ||||||
|  |         // TODO ignore handle contractID/method.... | ||||||
|  |         // TODO ignore handle transaction end | ||||||
|  |         while (sc.hasNextLine()) { | ||||||
|  |             JsonObject jo = JsonParser.parseString(sc.nextLine()).getAsJsonObject(); | ||||||
|  |             if (null != jo.get("traceMark")) { | ||||||
|  |                 if (null != jo.get("lval")) { | ||||||
|  |                     transaction.insert(jo.get("traceMark").getAsInt(), jo.get("lval").getAsInt()); | ||||||
|  |                     transaction.insert(jo.get("traceMark").getAsInt(), jo.get("rval").getAsInt()); | ||||||
|  |                 } else { | ||||||
|  |                     transaction.insert(jo.get("traceMark").getAsInt(), jo.get("val").getAsInt()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         trans.add(transaction); | ||||||
|  |         sc.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static class Transaction { | ||||||
|  |         public Map<Integer, List<Integer>> tmToVal; | ||||||
|  | 
 | ||||||
|  |         public void insert(int traceMark, int val) { | ||||||
|  |             List<Integer> ret; | ||||||
|  |             if (!tmToVal.containsKey(traceMark)) { | ||||||
|  |                 ret = new ArrayList<>(); | ||||||
|  |                 tmToVal.put(traceMark, ret); | ||||||
|  |             } else { | ||||||
|  |                 ret = tmToVal.get(traceMark); | ||||||
|  |             } | ||||||
|  |             ret.add(val); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,94 @@ | |||||||
|  | package org.bdware.analysis.example; | ||||||
|  | 
 | ||||||
|  | import org.apache.logging.log4j.LogManager; | ||||||
|  | import org.apache.logging.log4j.Logger; | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.BreadthFirstSearch; | ||||||
|  | import org.bdware.analysis.taint.TaintBB; | ||||||
|  | import org.bdware.analysis.taint.TaintCFG; | ||||||
|  | import org.bdware.analysis.taint.TaintResult; | ||||||
|  | import org.bdware.analysis.taint.TaintValue; | ||||||
|  | import org.objectweb.asm.tree.MethodNode; | ||||||
|  | 
 | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public class FieldSensitiveTaintAnalysis extends BreadthFirstSearch<TaintResult, TaintBB> { | ||||||
|  |     private static final Logger LOGGER = LogManager.getLogger(FieldSensitiveTaintAnalysis.class); | ||||||
|  |     public static boolean isDebug = false; | ||||||
|  |     TaintCFG cfg; | ||||||
|  | 
 | ||||||
|  |     public FieldSensitiveTaintAnalysis(TaintCFG cfg) { | ||||||
|  |         this.cfg = cfg; | ||||||
|  |         List<TaintBB> toAnalysis = new ArrayList<>(); | ||||||
|  |         /* | ||||||
|  |          * NaiveTaintBB<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> boolean inList NaiveTaintResult preResult NaiveTaintResult | ||||||
|  |          * sucResult | ||||||
|  |          */ | ||||||
|  |         TaintBB b = (TaintBB) cfg.getBasicBlockAt(0); | ||||||
|  |         /* | ||||||
|  |          * NaiveTaintResult<EFBFBD>еı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Frame<TaintValue> frame TaintInterpreter interpreter | ||||||
|  |          * TaintValue ret InsnPrinter printer int nLocals int nStack | ||||||
|  |          * NaiveTaintResult<EFBFBD>е<EFBFBD><EFBFBD>ࣺ TaintValue int size boolean isTainted | ||||||
|  |          * TaintInterpreter() NaiveTaintResult currentResult Frame<EFBFBD>еı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> V returnValue | ||||||
|  |          * //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊvoid<EFBFBD><EFBFBD>Ϊnull V[] values //<EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> int locals | ||||||
|  |          * //<EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD> int top //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> | ||||||
|  |          */ | ||||||
|  |         b.preResult = new TaintResult(); | ||||||
|  |         // <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD> | ||||||
|  |         int arg = cfg.argsLocal(); | ||||||
|  |         cfg.executeLocal(); | ||||||
|  |         TaintResult.interpreter.setTaintBits(cfg.taintBits); | ||||||
|  |         b.preResult.frame.setLocal(arg, new TaintValue(1, cfg.taintBits.allocate("arg" + arg))); | ||||||
|  |         /* | ||||||
|  |          * if (NaiveTaintResult.nLocals > 2) { b.preResult.frame.setLocal(0, new | ||||||
|  |          * TaintValue(1, cfg.taintBits.allocate("arg0"))); b.preResult.frame.setLocal(1, | ||||||
|  |          * new TaintValue(1, cfg.taintBits.allocate("arg1"))); | ||||||
|  |          * b.preResult.frame.setLocal(2, new TaintValue(1, | ||||||
|  |          * cfg.taintBits.allocate("arg2"))); } | ||||||
|  |          */ | ||||||
|  |         // .ret = TaintValue<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>size=1 | ||||||
|  |         b.preResult.ret = new TaintValue(1); | ||||||
|  |         TaintResult.printer.setLabelOrder(cfg.getLabelOrder()); | ||||||
|  |         // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>b<EFBFBD><EFBFBD><EFBFBD>뵽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD> | ||||||
|  |         toAnalysis.add(b); | ||||||
|  |         b.setInList(true); | ||||||
|  |         // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>BreadthFirstSearch<EFBFBD><EFBFBD><EFBFBD>еĺ<EFBFBD><EFBFBD><EFBFBD>setToAnalysis<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱBreadthFirstSearch<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>toAnalysisΪ<EFBFBD><EFBFBD>ǰ<EFBFBD>Ŀ<EFBFBD><EFBFBD>б<EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>B0 | ||||||
|  |         /* | ||||||
|  |          * BreadthFirstSearch<EFBFBD><EFBFBD><EFBFBD>еı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Map<T, AnalysisResult> results; List<T> | ||||||
|  |          * toAnalysis; | ||||||
|  |          */ | ||||||
|  |         setToAnalysis(toAnalysis); | ||||||
|  |         if (isDebug) { | ||||||
|  |             MethodNode methodNode = cfg.getMethodNode(); | ||||||
|  |             LOGGER.info("Method: " + methodNode.name + " " + methodNode.desc); | ||||||
|  |             LOGGER.info("Local: " + methodNode.maxLocals + " " + methodNode.maxStack); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public TaintResult execute(TaintBB t) { | ||||||
|  |         return t.forwardAnalysis(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Current Block is done, merge sucResult to sucBlocks! | ||||||
|  |     @Override | ||||||
|  |     public Collection<TaintBB> getSuc(TaintBB t) { | ||||||
|  |         // System.out.println("---------------------------------"); | ||||||
|  |         // System.out.println("XXXXXB" + t.blockID + " sucBlock:" + | ||||||
|  |         // t.sucResult.frame2Str()); | ||||||
|  |         Set<BasicBlock> subBlock = cfg.getSucBlocks(t); | ||||||
|  |         Set<TaintBB> ret = new HashSet<>(); | ||||||
|  |         for (BasicBlock bb : subBlock) { | ||||||
|  |             TaintBB ntbb = (TaintBB) bb; | ||||||
|  |             ntbb.preResult.mergeResult(t.sucResult); | ||||||
|  |             // System.out.println( | ||||||
|  |             // "XXXXXB" + ntbb.blockID + " mergedBlock:" + | ||||||
|  |             // ntbb.preResult.frame2Str() + " " | ||||||
|  |             // + ntbb.preResult); | ||||||
|  |             ret.add(ntbb); | ||||||
|  |         } | ||||||
|  |         // System.out.println("---------------------------------"); | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,184 @@ | |||||||
|  | package org.bdware.analysis.example; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.BreadthFirstSearch; | ||||||
|  | import org.bdware.analysis.OpInfo; | ||||||
|  | import org.bdware.analysis.taint.*; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.InsnNode; | ||||||
|  | import org.objectweb.asm.tree.JumpInsnNode; | ||||||
|  | 
 | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | // 1. Dependency Analysis .. | ||||||
|  | // 2. Mulitple Source + Muliple Sink | ||||||
|  | // 3. Combine Dependency+TaintAnalysis | ||||||
|  | public class MultiSourceTaintAnalysis extends BreadthFirstSearch<TaintResult, TaintBB> { | ||||||
|  |     TaintCFG cfg; | ||||||
|  | 
 | ||||||
|  |     public MultiSourceTaintAnalysis(TaintCFG cfg) { | ||||||
|  |         this.cfg = cfg; | ||||||
|  |         List<TaintBB> toAnalysis = new ArrayList<>(); | ||||||
|  |         TaintBB b = (TaintBB) cfg.getBasicBlockAt(0); | ||||||
|  |         b.preResult = new TaintResult(); | ||||||
|  |         // Put the RootObject into the index 0 of the Local Variable Table | ||||||
|  |         b.preResult.frame.setLocal(0, HeapObject.getRootObject()); | ||||||
|  |         // The number of parameters of this method minus one | ||||||
|  |         int arg = cfg.argsLocal(); | ||||||
|  |         // Put the arg into the index 2 of the Local Variable Table | ||||||
|  |         b.preResult.frame.setLocal(1, new TaintValue(1, cfg.taintBits.allocate("arg"))); | ||||||
|  |         // Find the executeContract functions and allocate taintBits | ||||||
|  |         cfg.executeLocal(); | ||||||
|  |         TaintResult.interpreter.setTaintBits(cfg.taintBits); | ||||||
|  |         b.preResult.ret = new TaintValue(1); | ||||||
|  |         TaintResult.printer.setLabelOrder(cfg.getLabelOrder()); | ||||||
|  |         toAnalysis.add(b); | ||||||
|  |         b.setInList(true); | ||||||
|  |         setToAnalysis(toAnalysis); | ||||||
|  |         if (TaintConfig.isDebug) { | ||||||
|  |             System.out.println("===Method:" + cfg.getMethodNode().name + cfg.getMethodNode().desc); | ||||||
|  |             System.out.println( | ||||||
|  |                     "===Local:" | ||||||
|  |                             + cfg.getMethodNode().maxLocals | ||||||
|  |                             + " " | ||||||
|  |                             + cfg.getMethodNode().maxStack); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public TaintResult execute(TaintBB t) { | ||||||
|  |         return t.forwardAnalysis(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Collection<TaintBB> getSuc(TaintBB t) { | ||||||
|  |         Set<BasicBlock> subBlock = cfg.getSucBlocks(t); | ||||||
|  |         Set<TaintBB> ret = new HashSet<>(); | ||||||
|  |         for (BasicBlock bb : subBlock) { | ||||||
|  |             TaintBB ntbb = (TaintBB) bb; | ||||||
|  |             if (TaintConfig.isDebug) | ||||||
|  |                 System.out.println( | ||||||
|  |                         "[MultiSoruceTaintAnalysis] B" | ||||||
|  |                                 + ntbb.blockID | ||||||
|  |                                 + " beforeMerge:" | ||||||
|  |                                 + ntbb.preResult.frame2Str()); | ||||||
|  |             ntbb.preResult.mergeResult(t.sucResult); | ||||||
|  |             if (TaintConfig.isDebug) | ||||||
|  |                 System.out.println( | ||||||
|  |                         "[MultiSoruceTaintAnalysis] B" | ||||||
|  |                                 + ntbb.blockID | ||||||
|  |                                 + " afterMerge:" | ||||||
|  |                                 + ntbb.preResult.frame2Str()); | ||||||
|  | 
 | ||||||
|  |             ret.add(ntbb); | ||||||
|  |         } | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |      * Dependency Analysis | ||||||
|  |      */ | ||||||
|  |     public static Map<Integer, List<Integer>> depAnalysis(TaintCFG cfg) { | ||||||
|  |         // public static Set<Integer> depAnalysis(TaintCFG cfg) { | ||||||
|  |         // Step1: Find all the jump blocks | ||||||
|  |         Set<Integer> depBlocks = new HashSet<>(); | ||||||
|  |         for (BasicBlock b : cfg.getBlocks()) { | ||||||
|  |             Set<BasicBlock> suc = cfg.getSucBlocks(b); | ||||||
|  |             int sucSize = suc.size(); | ||||||
|  |             // Get rid of some jump nodes such as "GOTO" | ||||||
|  |             if (sucSize > 1) { | ||||||
|  |                 for (AbstractInsnNode an : b.getInsn()) { | ||||||
|  |                     if (an instanceof JumpInsnNode) { | ||||||
|  |                         int blockID = b.blockID; | ||||||
|  |                         depBlocks.add(blockID); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         /*Step2: Traverse all the blocks, for each block, traverse all the depBlocks, | ||||||
|  |          * for each depBlock, traverse all the sucBlocks, | ||||||
|  |          * if all the sucBlocks are arrival from each block, then the block is dependency with the depBlock. | ||||||
|  |          */ | ||||||
|  |         List<BasicBlock> blocks = cfg.getBlocks(); | ||||||
|  |         Map<Integer, List<Integer>> map = new HashMap<>(); | ||||||
|  |         for (BasicBlock bb : blocks) { | ||||||
|  |             List<Integer> list = new ArrayList<>(); | ||||||
|  |             for (int id : depBlocks) { | ||||||
|  |                 Set<BasicBlock> sucBlocks = cfg.getSucBlocks(cfg.getBasicBlockAt(id)); | ||||||
|  |                 int sucSize = sucBlocks.size(); | ||||||
|  |                 int count = 0; | ||||||
|  |                 for (BasicBlock sucBlock : sucBlocks) { | ||||||
|  |                     if (isArrival(cfg, sucBlock, bb)) count++; | ||||||
|  |                 } | ||||||
|  |                 if (count > 0 && count != sucSize) list.add(id); | ||||||
|  |             } | ||||||
|  |             map.put(bb.blockID, list); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Map<Integer, List<Integer>> returnMap = new HashMap<>(); | ||||||
|  |         for (Map.Entry<Integer, List<Integer>> entry : map.entrySet()) { | ||||||
|  |             // System.out.print(entry.getKey() +" : "); | ||||||
|  |             BasicBlock tmp = cfg.getBasicBlockAt(entry.getKey()); | ||||||
|  |             for (AbstractInsnNode an : tmp.getInsn()) { | ||||||
|  |                 int opcode; | ||||||
|  |                 if (an instanceof InsnNode) { | ||||||
|  |                     opcode = an.getOpcode(); | ||||||
|  |                     if (OpInfo.ops[opcode].canReturn()) { | ||||||
|  |                         returnMap.put(entry.getKey(), entry.getValue()); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             /* | ||||||
|  |             for(int i : entry.getValue()) | ||||||
|  |             	System.out.print(i+ " "); | ||||||
|  |             System.out.println(); | ||||||
|  |             */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // add dependence to the last block | ||||||
|  |         if (returnMap != null) { | ||||||
|  |             List<Integer> lastBlockDep = new ArrayList<>(); | ||||||
|  |             for (Map.Entry<Integer, List<Integer>> entry : returnMap.entrySet()) { | ||||||
|  |                 List<Integer> listID = entry.getValue(); | ||||||
|  |                 for (Integer i : listID) { | ||||||
|  |                     if (!lastBlockDep.contains(i)) lastBlockDep.add(i); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             returnMap.put(cfg.getBasicBlockSize() - 1, lastBlockDep); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // TODO get value from branch block | ||||||
|  |         /* | ||||||
|  |         List<Integer> list = returnMap.get(cfg.getBasicBlockSize()-1); | ||||||
|  |         for(int i : list) { | ||||||
|  |         	System.out.println(i); | ||||||
|  |         	TaintBB tb = (TaintBB) cfg.getBasicBlockAt(i); | ||||||
|  |         	System.out.println("Test:"); | ||||||
|  |         	tb.preResult.printResult(); | ||||||
|  |         } | ||||||
|  |         */ | ||||||
|  | 
 | ||||||
|  |         return returnMap; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static boolean isArrival(TaintCFG cfg, BasicBlock suc, BasicBlock bb) { | ||||||
|  |         // Test | ||||||
|  |         /* | ||||||
|  |         if(suc.blockID == bb.blockID) | ||||||
|  |         	return true; | ||||||
|  |         if(suc.blockID == 7 && bb.blockID == 11) | ||||||
|  |         	return true; | ||||||
|  |         if(suc.blockID == 9 && bb.blockID == 11) | ||||||
|  |         	return true; | ||||||
|  |         if(suc.blockID == 7 && bb.blockID == 12) | ||||||
|  |         	return true; | ||||||
|  |         if(suc.blockID == 9 && bb.blockID == 12) | ||||||
|  |         	return true; | ||||||
|  |         return false; | ||||||
|  |         */ | ||||||
|  | 
 | ||||||
|  |         if (suc.blockID == bb.blockID) return true; | ||||||
|  |         DirectGraphDFS dgDFS = new DirectGraphDFS(cfg, suc); | ||||||
|  |         return dgDFS.isArrival(bb); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,79 @@ | |||||||
|  | package org.bdware.analysis.example; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.BreadthFirstSearch; | ||||||
|  | import org.bdware.analysis.taint.*; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.LabelNode; | ||||||
|  | 
 | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | public class NaiveTaintAnalysis extends BreadthFirstSearch<TaintResult, TaintBB> { | ||||||
|  |     TaintCFG cfg; | ||||||
|  | 
 | ||||||
|  |     public NaiveTaintAnalysis(TaintCFG cfg) { | ||||||
|  |         this.cfg = cfg; | ||||||
|  |         List<TaintBB> toAnalysis = new ArrayList<>(); | ||||||
|  |         // TODO add inputBlock! | ||||||
|  |         TaintBB b = (TaintBB) cfg.getBasicBlockAt(0); | ||||||
|  | 
 | ||||||
|  |         b.preResult = new TaintResult(); | ||||||
|  |         // local0=scriptfuncion, is not tainted; | ||||||
|  |         // local1=this, is not tainted; | ||||||
|  |         // local2=this, is not tainted; | ||||||
|  |         if (TaintResult.nLocals > 2) { | ||||||
|  |             b.preResult.frame.setLocal(0, new TaintValue(1, 0)); | ||||||
|  |             b.preResult.frame.setLocal(1, new TaintValue(1, 0)); | ||||||
|  |             b.preResult.frame.setLocal(2, new TaintValue(1, 1)); | ||||||
|  |         } | ||||||
|  |         b.preResult.ret = new TaintValue(1); | ||||||
|  |         TaintResult.printer.setLabelOrder(cfg.getLabelOrder()); | ||||||
|  |         toAnalysis.add(b); | ||||||
|  |         b.setInList(true); | ||||||
|  |         setToAnalysis(toAnalysis); | ||||||
|  |         if (TaintConfig.isDebug) { | ||||||
|  |             System.out.println("===Method:" + cfg.getMethodNode().name + cfg.getMethodNode().desc); | ||||||
|  |             System.out.println( | ||||||
|  |                     "===Local:" | ||||||
|  |                             + cfg.getMethodNode().maxLocals | ||||||
|  |                             + " " | ||||||
|  |                             + cfg.getMethodNode().maxStack); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public TaintResult execute(TaintBB t) { | ||||||
|  |         return t.forwardAnalysis(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Current Block is done, merge sucResult to sucBlocks! | ||||||
|  |     @Override | ||||||
|  |     public Collection<TaintBB> getSuc(TaintBB t) { | ||||||
|  |         // System.out.println("---------------------------------"); | ||||||
|  |         // System.out.println("XXXXXB" + t.blockID + " sucBlock:" + | ||||||
|  |         // t.sucResult.frame2Str()); | ||||||
|  |         Set<BasicBlock> subBlock = cfg.getSucBlocks(t); | ||||||
|  |         System.out.println("ttlist" + t.list); | ||||||
|  |         System.out.println("subblock" + subBlock.size()); | ||||||
|  |         Set<TaintBB> ret = new HashSet<>(); | ||||||
|  |         AbstractInsnNode insn = t.lastInsn(); | ||||||
|  |         if (insn instanceof LabelNode) { | ||||||
|  |             LabelNode label = ((LabelNode) insn); | ||||||
|  |             System.out.println("-----"); | ||||||
|  |             System.out.println("label" + label.getLabel().toString()); | ||||||
|  |             System.out.println(cfg.getBasicBlockByLabel(label.getLabel()).blockID); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (BasicBlock bb : subBlock) { | ||||||
|  |             System.out.println(bb.blockID); | ||||||
|  |             TaintBB ntbb = (TaintBB) bb; | ||||||
|  |             ntbb.preResult.mergeResult(t.sucResult); | ||||||
|  |             // System.out.println( | ||||||
|  |             // "XXXXXB" + ntbb.blockID + " mergedBlock:" + ntbb.preResult.frame2Str() + " " | ||||||
|  |             // + ntbb.preResult); | ||||||
|  |             ret.add(ntbb); | ||||||
|  |         } | ||||||
|  |         // System.out.println("---------------------------------"); | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/main/analysis/org/bdware/analysis/gas/BFS.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/analysis/org/bdware/analysis/gas/BFS.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
|  | 
 | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | 
 | ||||||
|  | public abstract class BFS { | ||||||
|  | 	protected List<BasicBlock> toAnalysis; | ||||||
|  | 	public abstract Collection<BasicBlock> getSuc(BasicBlock BB); | ||||||
|  | 	public void analysis() { | ||||||
|  | 		BasicBlock current = null; | ||||||
|  | 		for (int i = 0; i < toAnalysis.size(); i++) { | ||||||
|  | 			current = toAnalysis.get(i); | ||||||
|  | 			//current.setInList(false); | ||||||
|  | 			if(current.inList()) { | ||||||
|  | 			Collection<BasicBlock> sucs = getSuc(current); | ||||||
|  | 			for (BasicBlock next : sucs) { | ||||||
|  | 					if (!next.inList()) { | ||||||
|  | 						toAnalysis.add(next); | ||||||
|  | 						next.setInList(true); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	public void setToAnalysis(List<BasicBlock> l) { | ||||||
|  | 		toAnalysis = l; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | } | ||||||
| @ -0,0 +1 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
							
								
								
									
										226
									
								
								src/main/analysis/org/bdware/analysis/gas/CountProgramPoint.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								src/main/analysis/org/bdware/analysis/gas/CountProgramPoint.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,226 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.CFGraph; | ||||||
|  | import org.bdware.analysis.OpInfo; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.InvokeDynamicInsnNode; | ||||||
|  | import org.objectweb.asm.tree.JumpInsnNode; | ||||||
|  | 
 | ||||||
|  | public class CountProgramPoint { | ||||||
|  | 	public static HashMap<Integer, Map<String, Integer>> ppcount; | ||||||
|  | 	CFGraph actionCfg; | ||||||
|  | 	private String bdName; | ||||||
|  | 	HashMap<String, CFGraph> cfgraphMap; | ||||||
|  | 	String actionName; | ||||||
|  | 	int globalPC; | ||||||
|  | 
 | ||||||
|  | 	public CountProgramPoint(HashMap<String, CFGraph> cfgMap, int startPc, int endPc, String aName, | ||||||
|  | 			HashMap<Integer, Map<String, Integer>> ppc) { | ||||||
|  | 		ppcount = ppc; | ||||||
|  | 		cfgraphMap = cfgMap; | ||||||
|  | 		actionName = aName; | ||||||
|  | 		typeCount(startPc, endPc); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private HashMap<Integer, Map<String, Integer>> callCount(AbstractInsnNode insn) { | ||||||
|  | 		if (insn instanceof InvokeDynamicInsnNode) { | ||||||
|  | 			invoke = ((InvokeDynamicInsnNode) insn).bsmArgs[0]; | ||||||
|  | 			String functionName = ((InvokeDynamicInsnNode) insn).name; | ||||||
|  | 			dynCount(functionName); | ||||||
|  | 		} else { | ||||||
|  | 			normalCount(insn); | ||||||
|  | 		} | ||||||
|  | 		return ppcount; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Object invoke = 0; | ||||||
|  | 
 | ||||||
|  | 	public HashMap<Integer, Map<String, Integer>> typeCount(int startPc, int endPc) { | ||||||
|  | 		if (startPc == 0) { | ||||||
|  | 			ppcount.put(startPc, new HashMap<>()); | ||||||
|  | 			globalPC = startPc; | ||||||
|  | 		} else { | ||||||
|  | 			ppcount.put(endPc, new HashMap<>()); | ||||||
|  | 			globalPC = endPc; | ||||||
|  | 		} | ||||||
|  | 		actionCfg = cfgraphMap.get(actionName); | ||||||
|  | 		int blockStart = 0, blockend = 0; | ||||||
|  | 		if (startPc == 0) { | ||||||
|  | 			blockStart = 0; | ||||||
|  | 		} else { | ||||||
|  | 			OUT: for (int j = 0; j < actionCfg.getBasicBlockSize(); j++) { | ||||||
|  | 				BasicBlock bb = actionCfg.getBasicBlockAt(j); | ||||||
|  | 				AbstractInsnNode insnNode = bb.lastInsn(); | ||||||
|  | 				if (insnNode instanceof InvokeDynamicInsnNode) { | ||||||
|  | 					invoke = ((InvokeDynamicInsnNode) insnNode).bsmArgs[0]; | ||||||
|  | 					if ((int) invoke == startPc) { | ||||||
|  | 						blockStart = j; | ||||||
|  | 						break OUT; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		OUT: for (int j = 0; j < actionCfg.getBasicBlockSize(); j++) { | ||||||
|  | 			BasicBlock bb = actionCfg.getBasicBlockAt(j); | ||||||
|  | 			AbstractInsnNode insnNode = bb.lastInsn(); | ||||||
|  | 			if (insnNode instanceof InvokeDynamicInsnNode) { | ||||||
|  | 				invoke = ((InvokeDynamicInsnNode) insnNode).bsmArgs[0]; | ||||||
|  | 				if ((int) invoke == endPc) { | ||||||
|  | 					blockend = j; | ||||||
|  | 					break OUT; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return getInsn(blockStart, blockend); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private HashMap<Integer, Map<String, Integer>> getInsn(int blockStart, int blockend) { | ||||||
|  | 		BasicBlock t; | ||||||
|  | 		if (blockend == blockStart && blockStart != 0) { | ||||||
|  | 			System.out.println("blockend" + blockend); | ||||||
|  | 			t = actionCfg.getBasicBlockAt(blockend); | ||||||
|  | 			if (t.list.size() > 0) { | ||||||
|  | 				List<AbstractInsnNode> insnList = t.getInsn(); | ||||||
|  | 				for (AbstractInsnNode insn : insnList) { | ||||||
|  | 					if (insn instanceof InvokeDynamicInsnNode) { | ||||||
|  | 						callCount(insn); | ||||||
|  | 					} else if (insn instanceof JumpInsnNode) { | ||||||
|  | 						jumpCount(insn); | ||||||
|  | 					} else { | ||||||
|  | 						normalCount(insn); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return ppcount; | ||||||
|  | 		} else if (blockend == 0) { | ||||||
|  | 			return ppcount; | ||||||
|  | 		} else if (blockend != blockStart && blockStart != 0) { | ||||||
|  | 			blockStart = blockStart + 1; | ||||||
|  | 			blockend = blockend + 1; | ||||||
|  | 			System.out.println(blockStart); | ||||||
|  | 		} | ||||||
|  | 		for (int i = blockStart; i < blockend; i++) { | ||||||
|  | 			t = actionCfg.getBasicBlockAt(i); | ||||||
|  | 			System.out.println("[t.blockID]" + t.blockID); | ||||||
|  | 			if (t.list.size() > 0) { | ||||||
|  | 				List<AbstractInsnNode> insnList = t.getInsn(); | ||||||
|  | 				for (AbstractInsnNode insn : insnList) { | ||||||
|  | 					if (insn != null) { | ||||||
|  | 						OpInfo info = null; | ||||||
|  | 						if (insn.getOpcode() >= 0) { | ||||||
|  | 							info = OpInfo.ops[insn.getOpcode()]; | ||||||
|  | 							System.out.println("[info.toString()]" + info.toString()); | ||||||
|  | 						} | ||||||
|  | 						if (info == null) { | ||||||
|  | 
 | ||||||
|  | 						} else if (info.canThrow()) { | ||||||
|  | 							callCount(insn); | ||||||
|  | 						} else if (info.canBranch()) { | ||||||
|  | 							jumpCount(insn); | ||||||
|  | 						} else if (info.canContinue()) { | ||||||
|  | 							normalCount(insn); | ||||||
|  | 						} else if (info.canReturn()) { | ||||||
|  | 							normalCount(insn); | ||||||
|  | 						} else if (info.canSwitch()) { | ||||||
|  | 							normalCount(insn); | ||||||
|  | 						} else { | ||||||
|  | 							System.out.println("[info:else]" + info); | ||||||
|  | 							normalCount(insn); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		} | ||||||
|  | 		return ppcount; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void normalCount(AbstractInsnNode insn) { | ||||||
|  | 		bdName = FeeSchedule.BDInsn.name(); | ||||||
|  | 		if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 			ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 		} else { | ||||||
|  | 			ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void jumpCount(AbstractInsnNode insn) { | ||||||
|  | 		bdName = FeeSchedule.BDjump.name(); | ||||||
|  | 		if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 			ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 		} else { | ||||||
|  | 			ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void dynCount(String functionName) { | ||||||
|  | 		if (functionName.contains("getProp")) { | ||||||
|  | 			bdName = FeeSchedule.BDgetMethod.name(); | ||||||
|  | 			if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 				System.out.println("   function   " + functionName); | ||||||
|  | 			} else { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 			} | ||||||
|  | 		} else if (functionName.contains("setProp")) { | ||||||
|  | 			bdName = FeeSchedule.BDsetMethod.name(); | ||||||
|  | 			if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 				System.out.println("   function   " + functionName); | ||||||
|  | 			} else { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 			} | ||||||
|  | 		} else if (functionName.contains("call") && functionName.contains("Util")) { | ||||||
|  | 			bdName = FeeSchedule.BDcallUtil.name(); | ||||||
|  | 			if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 				System.out.println("   function   " + functionName); | ||||||
|  | 			} else { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 			} | ||||||
|  | 		} else if (functionName.contains("call") && isInnerfunction(functionName)) { | ||||||
|  | 			bdName = FeeSchedule.BDcallFuntion.name(); | ||||||
|  | 			if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 				System.out.println("   function   " + functionName); | ||||||
|  | 			} else { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 			} | ||||||
|  | 		} else if (functionName.contains("call")) { | ||||||
|  | 			bdName = FeeSchedule.BDcallUtil.name(); | ||||||
|  | 			if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 				System.out.println("   function   " + functionName); | ||||||
|  | 			} else { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		} else { | ||||||
|  | 			bdName = FeeSchedule.BDInsn.name(); | ||||||
|  | 			if (ppcount.get(globalPC).containsKey(bdName)) { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, ppcount.get(globalPC).get(bdName) + 1); | ||||||
|  | 			} else { | ||||||
|  | 				ppcount.get(globalPC).put(bdName, 1); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private boolean isInnerfunction(String functionName) { | ||||||
|  | 		String string = functionName.split(":")[2]; | ||||||
|  | 		if (cfgraphMap.containsKey(string)) { | ||||||
|  | 			return true; | ||||||
|  | 		} else { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								src/main/analysis/org/bdware/analysis/gas/DFS.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/analysis/org/bdware/analysis/gas/DFS.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.CFGraph; | ||||||
|  | 
 | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | public abstract class DFS { | ||||||
|  |     private boolean[] marked = new boolean[2048]; | ||||||
|  | 
 | ||||||
|  |     public abstract Set<BasicBlock> getSuc(BasicBlock BB); | ||||||
|  | 
 | ||||||
|  |     public void dfs(CFGraph cfg, BasicBlock start) { | ||||||
|  |         marked[start.blockID] = true; | ||||||
|  |         // System.out.println("[start.blockID]" + start.blockID); | ||||||
|  |         Set<BasicBlock> sucBlocks = getSuc(start); | ||||||
|  |         for (BasicBlock bb : sucBlocks) { | ||||||
|  |             if (!marked[bb.blockID]) dfs(cfg, bb); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean isArrival(BasicBlock end) { | ||||||
|  |         return marked[end.blockID]; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										96
									
								
								src/main/analysis/org/bdware/analysis/gas/Evaluates.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/main/analysis/org/bdware/analysis/gas/Evaluates.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Map.Entry; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | public class Evaluates { | ||||||
|  |     Map<Integer, HashMap<String, Integer>> callFunctionResult; | ||||||
|  |     Map<Integer, Long> CountResult = new HashMap<>(); | ||||||
|  | 
 | ||||||
|  |     public Map<Integer, Long> getCallFee() { | ||||||
|  |         for (Entry<Integer, HashMap<String, Integer>> c : callFunctionResult.entrySet()) { | ||||||
|  |             Integer cfrKey = c.getKey(); | ||||||
|  |             long value = 0; | ||||||
|  |             HashMap<String, Integer> map = c.getValue(); | ||||||
|  |             for (Entry<String, Integer> cmap : map.entrySet()) { | ||||||
|  | 
 | ||||||
|  |                 long fee = getValue(cmap.getKey()); | ||||||
|  |                 value = fee * cmap.getValue() + value; | ||||||
|  |             } | ||||||
|  |                 CountResult.put(cfrKey, value); | ||||||
|  |         } | ||||||
|  |         return CountResult; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public long getValue(String name) { | ||||||
|  |         long value = 0; | ||||||
|  |         switch (name) { | ||||||
|  |             case "BDgetMethod": | ||||||
|  |                 value = FeeSchedule.BDgetMethod.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDsetMethod": | ||||||
|  |                 value = FeeSchedule.BDsetMethod.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDnew": | ||||||
|  |                 value = FeeSchedule.BDnew.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDcallUtil": | ||||||
|  |                 value = FeeSchedule.BDcallUtil.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDcallFuntion": | ||||||
|  |                 value = FeeSchedule.BDcallFuntion.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDcall": | ||||||
|  |                 value = FeeSchedule.BDcall.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDjump": | ||||||
|  |                 value = FeeSchedule.BDjump.getFee(); | ||||||
|  |                 break; | ||||||
|  |             case "BDInsn": | ||||||
|  |                 value = FeeSchedule.BDInsn.getFee(); | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     long sum; | ||||||
|  |     Set<HashMap<String, Long>> set = new HashSet<>(); | ||||||
|  | 
 | ||||||
|  |     public void getGas(HashMap<String, Set<Map<Integer, HashMap<String, Integer>>>> branchCount) { | ||||||
|  |             for (Entry<String, Set<Map<Integer, HashMap<String, Integer>>>> varInsn : | ||||||
|  |                     branchCount.entrySet()) { | ||||||
|  |                 sum = 0; | ||||||
|  |                 for (Map<Integer, HashMap<String, Integer>> m : varInsn.getValue()) { | ||||||
|  |                     blockGas(m); | ||||||
|  |                 } | ||||||
|  |                 map.put(varInsn.getKey(), sum); | ||||||
|  |             } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void blockGas(Map<Integer, HashMap<String, Integer>> m) { | ||||||
|  |         for (Entry<Integer, HashMap<String, Integer>> map : m.entrySet()) { | ||||||
|  |             for (Entry<String, Integer> insnMap : map.getValue().entrySet()) { | ||||||
|  |                 long value = getValue(insnMap.getKey()) * insnMap.getValue(); | ||||||
|  |                 sum = sum + value; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static HashMap<String, Long> map = new HashMap<>(); | ||||||
|  | 
 | ||||||
|  |     public void getInsnGas(Map<Integer, Set<Map<Integer, HashMap<String, Integer>>>> ppMap) { | ||||||
|  |         for (Entry<Integer, Set<Map<Integer, HashMap<String, Integer>>>> varInsn : | ||||||
|  |                 ppMap.entrySet()) { | ||||||
|  |             sum = 0; | ||||||
|  |             for (Map<Integer, HashMap<String, Integer>> m : varInsn.getValue()) { | ||||||
|  |                 blockGas(m); | ||||||
|  |             } | ||||||
|  |             map.put(varInsn.getKey().toString(), sum); | ||||||
|  |     } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								src/main/analysis/org/bdware/analysis/gas/FeeSchedule.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/main/analysis/org/bdware/analysis/gas/FeeSchedule.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
|  | 
 | ||||||
|  | public enum FeeSchedule { | ||||||
|  | 	// BDaload(20L),BDstore(200L), | ||||||
|  | 	BDgetMethod(10L), BDsetMethod(20L), BDnew(20L),BDcallUtil(30L), BDcallFuntion(40L), BDcall(10L), BDjump(15L), BDInsn(1L); | ||||||
|  | 
 | ||||||
|  | 	long fee; | ||||||
|  | 
 | ||||||
|  | 	FeeSchedule(long value) { | ||||||
|  | 		fee = value; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public long getFee() { | ||||||
|  | 		return fee; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public long getValue(String name) { | ||||||
|  | 		long value=0; | ||||||
|  | 		switch (name) { | ||||||
|  | 		case "BDgetMethod": | ||||||
|  | 			value=BDgetMethod.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		case "BDsetMethod": | ||||||
|  | 			value= BDsetMethod.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		case "BDcallUtil": | ||||||
|  | 			value= BDcallUtil.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		case "BDcallFuntion": | ||||||
|  | 			value= BDcallFuntion.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		case "BDcall": | ||||||
|  | 			value= BDcall.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		case "BDjump": | ||||||
|  | 			value= BDjump.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		case "BDInsn": | ||||||
|  | 			value= BDInsn.getFee(); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String getString(FeeSchedule feeName) { | ||||||
|  | 		return feeName.toString(); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										450
									
								
								src/main/analysis/org/bdware/analysis/gas/PPCount.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										450
									
								
								src/main/analysis/org/bdware/analysis/gas/PPCount.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,450 @@ | |||||||
|  | package org.bdware.analysis.gas; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.CFGraph; | ||||||
|  | import org.bdware.analysis.OpInfo; | ||||||
|  | import org.bdware.analysis.gas.DFS; | ||||||
|  | import org.bdware.analysis.gas.FeeSchedule; | ||||||
|  | import org.objectweb.asm.ClassReader; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.ClassNode; | ||||||
|  | import org.objectweb.asm.tree.InvokeDynamicInsnNode; | ||||||
|  | import org.objectweb.asm.tree.JumpInsnNode; | ||||||
|  | import org.objectweb.asm.tree.LabelNode; | ||||||
|  | 
 | ||||||
|  | public class PPCount extends DFS { | ||||||
|  |     CFGraph cfg; | ||||||
|  |     String functionGlobel; | ||||||
|  |     private String bdName; | ||||||
|  |     private int globalInvoke = 0; | ||||||
|  |     static List<String> functionList = new ArrayList<>(); | ||||||
|  |     private int globalBlockID; | ||||||
|  | 
 | ||||||
|  |     public static Map<String, HashMap<String, Integer>> varInsnCount = new HashMap<>(); | ||||||
|  |     public static HashMap<String, Set<Map<Integer, HashMap<String, Integer>>>> branchCount = | ||||||
|  |             new HashMap<>();; | ||||||
|  |     public static Map<Integer, HashMap<String, Integer>> callFunction = new HashMap<>(); | ||||||
|  |     public static Map<Integer, HashMap<String, Integer>> BlockInsn = new HashMap<>(); | ||||||
|  |     public static Map<Integer, Set<Map<Integer, HashMap<String, Integer>>>> ppMap = new HashMap<>(); | ||||||
|  |     public HashSet<Integer> countBlock = new HashSet<>(); | ||||||
|  |     boolean[] isBranchBlock; | ||||||
|  | 
 | ||||||
|  |     public PPCount(CFGraph cfg, int flag) { | ||||||
|  |         this.cfg = cfg; | ||||||
|  |         functionGlobel = cfg.getMethodNode().name; | ||||||
|  |         varInsnCount.put(functionGlobel, new HashMap<>()); | ||||||
|  |         globalInvoke = flag; | ||||||
|  |         ppMap.put(globalInvoke, new HashSet<>()); | ||||||
|  |         callFunction.put(flag, new HashMap<>()); | ||||||
|  |         List<BasicBlock> toAnalysis = new ArrayList<>(); | ||||||
|  |         BasicBlock b = cfg.getBasicBlockAt(0); | ||||||
|  |         toAnalysis.add(b); | ||||||
|  |         b.setInList(true); | ||||||
|  | //        System.out.println("=========:"+cfg.getMethodNode().name); | ||||||
|  |         functionList.add(cfg.getMethodNode().name); | ||||||
|  |         isBranchBlock = new boolean[cfg.getBasicBlockSize()]; | ||||||
|  |         // setToAnalysis(toAnalysis); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // @Override | ||||||
|  |     // public Collection<BasicBlock> getSuc(BasicBlock t) { | ||||||
|  |     // System.out.println("++++++++++" + t.blockID); | ||||||
|  |     // typeCount(t); | ||||||
|  |     // Set<BasicBlock> subBlock = cfg.getSucBlocks(t); | ||||||
|  |     // DFS dgDFS = new DFS(cfg, t); | ||||||
|  |     // | ||||||
|  |     // return subBlock; | ||||||
|  |     // } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Set<BasicBlock> getSuc(BasicBlock t) { | ||||||
|  |         // System.out.println("++++++++++" + t.blockID); | ||||||
|  |         Set<BasicBlock> subBlock = cfg.getSucBlocks(t); | ||||||
|  |         typeCount(t); | ||||||
|  |         return subBlock; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void typeCount(BasicBlock t) { // 一个基本块里面的所有指令 | ||||||
|  |         int count = 0; | ||||||
|  |         countBlock.add(t.blockID); | ||||||
|  |         globalBlockID = t.blockID; | ||||||
|  |         BlockInsn.put(t.blockID, new HashMap<>()); | ||||||
|  |         List<AbstractInsnNode> insnList = t.getInsn(); | ||||||
|  |         OpInfo info = null; | ||||||
|  |         if (t.list.size() > 0) { | ||||||
|  |             for (AbstractInsnNode ab : insnList) { | ||||||
|  |                 if (ab != null) { | ||||||
|  |                     if (ab.getOpcode() >= 0) { | ||||||
|  |                         count++; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         t.insnCount = count; | ||||||
|  |         if (t.list.size() > 0) { | ||||||
|  |             for (int i = 0; i < insnList.size(); i++) { | ||||||
|  |                 AbstractInsnNode insn = insnList.get(i); | ||||||
|  |                 if (insn != null) { | ||||||
|  |                     if (insn.getOpcode() >= 0) { | ||||||
|  |                         info = OpInfo.ops[insn.getOpcode()]; | ||||||
|  |                     } | ||||||
|  |                     if (info == null) { | ||||||
|  |                     } else if (info.canThrow()) { | ||||||
|  |                         callCount(insn, t); | ||||||
|  |                     } else if (info.canBranch()) { | ||||||
|  |                         normalCount(insn, t); | ||||||
|  |                         jumpCount(insn, t); | ||||||
|  |                     } else if (info.canContinue() || info.canSwitch() || info.canReturn()) { | ||||||
|  |                         normalCount(insn, t); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         addBlock(t); | ||||||
|  |         removeBranch(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int jumpBlockid = -1; | ||||||
|  |     int conBlockid = -1; | ||||||
|  |     private boolean isBranch = false; | ||||||
|  |     private List<Integer> globalBranch = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|  |     private void jumpCount(AbstractInsnNode insn, BasicBlock t) { | ||||||
|  |         switch (insn.getOpcode()) { | ||||||
|  |             case Opcodes.IFNE: // succeeds if and only if value ≠ 0 | ||||||
|  |             case Opcodes.IFEQ: // succeeds if and only if value = 0 | ||||||
|  |             case Opcodes.IFLT: // succeeds if and only if value < 0 | ||||||
|  |             case Opcodes.IFLE: | ||||||
|  | 
 | ||||||
|  |             case Opcodes.IFGE: // succeeds if and only if value ≥ 0 | ||||||
|  |                 isBranch = true; | ||||||
|  |                 globalBranch.add(globalInvoke); | ||||||
|  |                 Map<Integer, HashMap<String, Integer>> map = new HashMap<>(); | ||||||
|  |                 Map<Integer, HashMap<String, Integer>> map2 = new HashMap<>(); | ||||||
|  |                 Set<Map<Integer, HashMap<String, Integer>>> ret = new HashSet<>(); | ||||||
|  |                 Set<Map<Integer, HashMap<String, Integer>>> ret2 = new HashSet<>(); | ||||||
|  |                 map.put(t.blockID, BlockInsn.get(t.blockID)); | ||||||
|  |                 map2.put(t.blockID - 1, BlockInsn.get(t.blockID - 1)); | ||||||
|  |                 ret.add(map); | ||||||
|  |                 ret.add(map2); | ||||||
|  |                 ret2.add(map); | ||||||
|  |                 ret2.add(map2); | ||||||
|  |                 if (insn instanceof JumpInsnNode) { | ||||||
|  |                     LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                     jumpBlockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  | 
 | ||||||
|  |                     branchCount.put(globalInvoke + "false" + jumpBlockid, ret); | ||||||
|  |                 } | ||||||
|  |                 conBlockid = t.blockID + 1; | ||||||
|  | 
 | ||||||
|  |                 branchCount.put(globalInvoke + "true" + conBlockid, ret2); | ||||||
|  |                 // System.out.println(branchCount); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.IFGT: // succeeds if and only if value > 0 | ||||||
|  |                 if (insn instanceof JumpInsnNode) { | ||||||
|  |                     LabelNode jump = ((JumpInsnNode) insn).label; | ||||||
|  |                     jumpBlockid = cfg.getBasicBlockByLabel(jump.getLabel()).blockID; | ||||||
|  |                     branchCount.put(globalInvoke + "false" + jumpBlockid, new HashSet<>()); | ||||||
|  |                 } | ||||||
|  |                 conBlockid = t.blockID + 1; | ||||||
|  |                 branchCount.put(globalInvoke + "true" + conBlockid, new HashSet<>()); | ||||||
|  |                 // System.out.println(branchCount); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.IF_ACMPEQ: // succeeds if and only if value1 = value2 | ||||||
|  |             case Opcodes.IF_ACMPNE: // succeeds if and only if value1 ≠ value2 | ||||||
|  |             case Opcodes.IF_ICMPEQ: // succeeds if and only if value1 = value2 | ||||||
|  |             case Opcodes.IF_ICMPGE: // succeeds if and only if value1 ≠ value2 | ||||||
|  |             case Opcodes.IF_ICMPGT: // succeeds if and only if value1 > value2 | ||||||
|  |             case Opcodes.IF_ICMPLE: // succeeds if and only if value1 ≤ value2 | ||||||
|  |             case Opcodes.IF_ICMPLT: // succeeds if and only if value1 < value2 | ||||||
|  |             case Opcodes.IFNONNULL: | ||||||
|  |             case Opcodes.TABLESWITCH: | ||||||
|  |             case Opcodes.LOOKUPSWITCH: | ||||||
|  |             case Opcodes.GOTO: | ||||||
|  |                 lastBlockId = t.blockID + 1; | ||||||
|  |             default: | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int lastBlockId = 0; | ||||||
|  |     int globalBlock = 0; | ||||||
|  | 
 | ||||||
|  |     private void normalCount(AbstractInsnNode insn, BasicBlock t) { | ||||||
|  |         if (t.blockID != lastBlockId) { | ||||||
|  |             lastBlockId = t.blockID; | ||||||
|  |             globalBlock = 0; | ||||||
|  |         } | ||||||
|  |         OpInfo info = OpInfo.ops[insn.getOpcode()]; | ||||||
|  |         bdName = FeeSchedule.BDInsn.name(); | ||||||
|  |         if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |             BlockInsn.get(globalBlockID).put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |         } else { | ||||||
|  |             BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |         } | ||||||
|  |         globalBlock++; | ||||||
|  | 
 | ||||||
|  |         if (globalBranch.size() != 0) { | ||||||
|  |             int gb = globalBranch.get(globalBranch.size() - 1); | ||||||
|  |             if (gb == globalInvoke) { | ||||||
|  |                 if (globalBlock == t.insnCount && !(insn instanceof JumpInsnNode)) { | ||||||
|  |                     chosenBranch(t); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void chosenBranch(BasicBlock t) { | ||||||
|  |         if (globalBranch.size() != 0) { | ||||||
|  |             int branch = globalBranch.get(globalBranch.size() - 1); | ||||||
|  |             Set<Map<Integer, HashMap<String, Integer>>> ret = new HashSet<>(); | ||||||
|  |             if (isBranch && t.blockID < jumpBlockid) { | ||||||
|  |                 isBranchBlock[t.blockID] = true; | ||||||
|  |                 if (branchCount.get(branch + "true" + conBlockid) != null | ||||||
|  |                         && !branchCount.get(branch + "true" + conBlockid).isEmpty()) { | ||||||
|  |                     ret = branchCount.get(branch + "true" + conBlockid); | ||||||
|  |                     Map<Integer, HashMap<String, Integer>> map = new HashMap<>(); | ||||||
|  |                     map.put(t.blockID, BlockInsn.get(t.blockID)); | ||||||
|  |                     ret.add(map); | ||||||
|  |                     branchCount.put(branch + "true" + conBlockid, ret); | ||||||
|  | 
 | ||||||
|  |                 } else if (branchCount.get(branch + "true" + conBlockid) != null) { | ||||||
|  |                     ret = branchCount.get(branch + "true" + conBlockid); | ||||||
|  |                     Map<Integer, HashMap<String, Integer>> map = new HashMap<>(); | ||||||
|  |                     map.put(t.blockID, BlockInsn.get(t.blockID)); | ||||||
|  |                     branchCount.get(branch + "true" + conBlockid).add(map); | ||||||
|  |                 } | ||||||
|  |             } else if (isBranch && t.blockID >= jumpBlockid) { | ||||||
|  |                 isBranchBlock[t.blockID] = true; | ||||||
|  |                 if (branchCount.get(branch + "false" + jumpBlockid) != null | ||||||
|  |                         && !branchCount.get(branch + "false" + jumpBlockid).isEmpty()) { | ||||||
|  |                     Set<Map<Integer, HashMap<String, Integer>>> list = | ||||||
|  |                             branchCount.get(branch + "false" + jumpBlockid); | ||||||
|  |                     Map<Integer, HashMap<String, Integer>> map = new HashMap<>(); | ||||||
|  |                     map.put(t.blockID, BlockInsn.get(t.blockID)); | ||||||
|  |                     list.add(map); | ||||||
|  |                     branchCount.put(branch + "false" + jumpBlockid, list); | ||||||
|  | 
 | ||||||
|  |                 } else if (branchCount.get(branch + "false" + jumpBlockid) != null) { | ||||||
|  |                     Map<Integer, HashMap<String, Integer>> map = new HashMap<>(); | ||||||
|  |                     if (ret.isEmpty()) { | ||||||
|  |                         map.put(t.blockID, BlockInsn.get(t.blockID)); | ||||||
|  |                         branchCount.get(branch + "false" + jumpBlockid).add(map); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int perBlockId = 0; | ||||||
|  | 
 | ||||||
|  |     public void removeBranch() { | ||||||
|  |         if (!globalBranch.isEmpty()) { | ||||||
|  |             for (int i = 0; i < globalBranch.size(); i++) { | ||||||
|  |                 if (ppMap.containsKey(globalBranch.get(i))) { | ||||||
|  |                     ppMap.remove(globalBranch.get(i)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void callCount(AbstractInsnNode insn, BasicBlock t) { | ||||||
|  |         boolean isNewCall = false; | ||||||
|  |         lastBlockId = t.blockID; | ||||||
|  |         if (insn instanceof InvokeDynamicInsnNode) { | ||||||
|  |             Object invoke = ((InvokeDynamicInsnNode) insn).bsmArgs[0]; | ||||||
|  |             String functionName = ((InvokeDynamicInsnNode) insn).name; | ||||||
|  |             isNewCall = true; | ||||||
|  |             if ((int) invoke > 5) { | ||||||
|  |                 dynCount(functionName); | ||||||
|  |                 globalInvoke = (int) invoke; | ||||||
|  |                 ppMap.put((int) invoke, new HashSet<>()); | ||||||
|  |                 perBlockId = t.blockID; | ||||||
|  |             } else { | ||||||
|  |                 dynCount(functionName); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             normalCount(insn, t); | ||||||
|  |         } | ||||||
|  |         if (!isNewCall || t.blockID == jumpBlockid || t.blockID == conBlockid) { | ||||||
|  |             branchEnd = true; | ||||||
|  |             chosenBranch(t); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void addBlock(BasicBlock t) { | ||||||
|  |         if (t.list.size() > 0) { | ||||||
|  |             Set<Map<Integer, HashMap<String, Integer>>> ret = new HashSet<>(); | ||||||
|  |             Map<Integer, HashMap<String, Integer>> map = new HashMap<>(); | ||||||
|  |             map.put(t.blockID, BlockInsn.get(t.blockID)); | ||||||
|  |             if (!isBranchBlock[t.blockID]) { | ||||||
|  |                 if (!ppMap.containsKey(globalInvoke)) { | ||||||
|  |                     ppMap.put(globalInvoke, new HashSet<>()); | ||||||
|  |                 } | ||||||
|  |                 ppMap.get(globalInvoke).add(map); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     boolean branchEnd; | ||||||
|  | 
 | ||||||
|  |     private void dynCount(String functionName) { | ||||||
|  |         String function = functionName.split(":")[1]; | ||||||
|  |         if (function.contains("getProp")) { | ||||||
|  |             bdName = FeeSchedule.BDgetMethod.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |             } | ||||||
|  |         } else if (function.contains("setProp")) { | ||||||
|  |             bdName = FeeSchedule.BDsetMethod.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |             } | ||||||
|  |         } else if (function.contains("new")) { | ||||||
|  |             bdName = FeeSchedule.BDnew.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |             } | ||||||
|  |         } else if (function.contains("call") && functionName.split(":")[2].contains("Util")) { | ||||||
|  |             bdName = FeeSchedule.BDcallUtil.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |             } | ||||||
|  |         } else if (function.contains("call") && isInnerfunction(functionName)) { | ||||||
|  |            // System.out.println("[call ]" + functionName); | ||||||
|  |             String methName = functionName.split(":")[2]; | ||||||
|  |             bdName = FeeSchedule.BDcallFuntion.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put( | ||||||
|  |                                 bdName + "," + methName, | ||||||
|  |                                 BlockInsn.get(globalBlockID).get(bdName + "," + methName) + 1); | ||||||
|  |                 System.out.println("   function   " + functionName); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName + "," + methName, 1); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } else if (function.contains("call")) { | ||||||
|  |             bdName = FeeSchedule.BDcall.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |             } | ||||||
|  |         } else if (functionName.contains("traceif")) { | ||||||
|  |             bdName = FeeSchedule.BDjump.name(); | ||||||
|  |             if (BlockInsn.get(globalBlockID).containsKey(bdName)) { | ||||||
|  |                 BlockInsn.get(globalBlockID) | ||||||
|  |                         .put(bdName, BlockInsn.get(globalBlockID).get(bdName) + 1); | ||||||
|  |             } else { | ||||||
|  |                 BlockInsn.get(globalBlockID).put(bdName, 1); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private boolean isInnerfunction(String functionName) { | ||||||
|  |         String string = functionName.split(":")[2]; | ||||||
|  |        // System.out.println("++++++++++++++" + functionName); | ||||||
|  |        // System.out.println("【function】" + functionList); | ||||||
|  |         if (functionList.contains(string)) { | ||||||
|  |             return true; | ||||||
|  |         } else { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //    public static void main(String[] args) throws Exception { | ||||||
|  |     //        String path = "/Users/hulingxuan/git/SmartContract/output/main.yjs"; | ||||||
|  |     //        ContractNode contractNode = null; | ||||||
|  |     //        YJSCompiler compiler = new YJSCompiler(); | ||||||
|  |     //        contractNode = compiler.compile(new FileInputStream(path), null); | ||||||
|  |     //        engine = new DesktopEngine(); | ||||||
|  |     //        engine.loadContract(contractNode, false); | ||||||
|  |     // | ||||||
|  |     //        Map<String, byte[]> clzs = engine.dumpClass(); | ||||||
|  |     //        Map<String, MethodNode> methods = new HashMap<>(); | ||||||
|  |     //        for (byte[] clz : clzs.values()) { | ||||||
|  |     //            ClassNode classNode = new ClassNode(); | ||||||
|  |     //            ClassReader cr = new ClassReader(clz); | ||||||
|  |     //            cr.accept(classNode, ClassReader.EXPAND_FRAMES); | ||||||
|  |     //            for (MethodNode mn : classNode.methods) { | ||||||
|  |     //                methods.put(mn.name, mn); | ||||||
|  |     //            } | ||||||
|  |     //        } | ||||||
|  |     //        int flag = 0; | ||||||
|  |     //        for (FunctionNode fn : contractNode.getFunctions()) { | ||||||
|  |     //            functionList.add(fn.functionName); | ||||||
|  |     //            MethodNode mn = methods.get(fn.functionName); | ||||||
|  |     //            if (mn != null) { | ||||||
|  |     //                CFGraph cfg = new CFGraph(mn) { | ||||||
|  |     //                    @Override | ||||||
|  |     //                    public BasicBlock getBasicBlock(int id) { | ||||||
|  |     //                        return new BasicBlock(id); | ||||||
|  |     //                    } | ||||||
|  |     //                }; | ||||||
|  |     //                // cfg.getLabelOrder(); | ||||||
|  |     //                PPCount countFee = new PPCount(cfg, flag); | ||||||
|  |     // | ||||||
|  |     //                BasicBlock bb = cfg.getBasicBlockAt(0); | ||||||
|  |     //                countFee.dfs(cfg, bb); | ||||||
|  |     //                // cfg.printSelf(); | ||||||
|  |     // | ||||||
|  |     //                Evaluates feEvaluates = new Evaluates(); | ||||||
|  |     //                feEvaluates.getGas(branchCount); | ||||||
|  |     //                feEvaluates.getInsnGas(ppMap); | ||||||
|  |     //                countFunction(fn.functionName, Evaluates.map); | ||||||
|  |     //                System.out.println("+++++++" + functionSumGas); | ||||||
|  |     //                System.out.println("========" + Evaluates.map); | ||||||
|  |     //                flag++; | ||||||
|  |     //            } | ||||||
|  |     //        } | ||||||
|  |     //        System.out.println(branchCount); | ||||||
|  |     //        System.out.println(BlockInsn); | ||||||
|  |     //        System.out.println(ppMap); | ||||||
|  |     // | ||||||
|  |     //        // System.out.println(feEvaluates.getCallFee()); | ||||||
|  |     //    } | ||||||
|  | 
 | ||||||
|  |     public static HashMap<String, Long> functionSumGas = new HashMap<>(); | ||||||
|  | 
 | ||||||
|  |     public static void countFunction(String functionName, HashMap<String, Long> map) { | ||||||
|  |         long sumTrue = 0; | ||||||
|  |         long sumFalse = 0; | ||||||
|  |         long sum = 0; | ||||||
|  | 
 | ||||||
|  |         for (Map.Entry<String, Long> entry : map.entrySet()) { | ||||||
|  |             if (entry.getKey().contains("true")) { | ||||||
|  |                 sumTrue = entry.getValue(); | ||||||
|  |             } else if (entry.getKey().contains("false")) { | ||||||
|  |                 sumFalse = entry.getValue(); | ||||||
|  |             } else { | ||||||
|  |                 sum += entry.getValue(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         functionSumGas.put(functionName, sum); | ||||||
|  |         functionSumGas.put(functionName + "true", sumTrue); | ||||||
|  |         functionSumGas.put(functionName + "false", sumFalse); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,28 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | 
 | ||||||
|  | public class DirectGraphDFS { | ||||||
|  | 	private boolean[] marked; | ||||||
|  | 	 | ||||||
|  | 	public DirectGraphDFS(TaintCFG cfg, BasicBlock start) { | ||||||
|  | 		marked = new boolean[cfg.getBlocks().size()]; | ||||||
|  | 		dfs(cfg, start); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	private void dfs(TaintCFG cfg, BasicBlock start) { | ||||||
|  | 		marked[start.blockID] = true; | ||||||
|  | 		Set<BasicBlock> sucBlocks = cfg.getSucBlocks(start); | ||||||
|  | 		for(BasicBlock bb : sucBlocks) { | ||||||
|  | 			if(!marked[bb.blockID]) | ||||||
|  | 				dfs(cfg, bb); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public boolean isArrival(BasicBlock end) { | ||||||
|  | 		return marked[end.blockID]; | ||||||
|  | 	} | ||||||
|  |   | ||||||
|  | } | ||||||
							
								
								
									
										247
									
								
								src/main/analysis/org/bdware/analysis/taint/HeapObject.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								src/main/analysis/org/bdware/analysis/taint/HeapObject.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,247 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.HashSet; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.MethodInsnNode; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.tree.InvokeDynamicInsnNode; | ||||||
|  | 
 | ||||||
|  | public class HeapObject extends TaintValue { | ||||||
|  | 	private Map<String, TaintValue> fields = new HashMap<String, TaintValue>(); | ||||||
|  | 	static int allocatID = 0; | ||||||
|  | 	int id; | ||||||
|  | 
 | ||||||
|  | 	public HeapObject() { | ||||||
|  | 		super(1); | ||||||
|  | 		id = allocatID++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public HeapObject(TaintValue t) { | ||||||
|  | 		this(); | ||||||
|  | 		if (t != null) { | ||||||
|  | 			merge(t); | ||||||
|  | 			size = t.size; | ||||||
|  | 		} else { | ||||||
|  | 			isTainted = 0; | ||||||
|  | 			size = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public static HeapObject getRootObject() { | ||||||
|  | 		HeapObject ret = new HeapObject(); | ||||||
|  | 		ret.setProp("Global", new HeapObject()); | ||||||
|  | 		ret.setProp("getScope", new HeapObject()); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String toString() { | ||||||
|  | 		return countSize() + "|" + super.toString(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private String countSize() { | ||||||
|  | 		objSet = new HashSet<>(); | ||||||
|  | 		return countSizeInternal(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private String countSizeInternal() { | ||||||
|  | 		if (objSet.contains(this)) | ||||||
|  | 			return "{H" + id + "}"; | ||||||
|  | 		objSet.add(this); | ||||||
|  | 		String ret = "{H" + id + ","; | ||||||
|  | 		for (String field : fields.keySet()) { | ||||||
|  | 			TaintValue tv = fields.get(field); | ||||||
|  | 			if (tv instanceof HeapObject) | ||||||
|  | 				ret += field + ":" + ((HeapObject) tv).countSizeInternal() + ","; | ||||||
|  | 			else | ||||||
|  | 				ret += field + ":" + tv.isTainted; | ||||||
|  | 		} | ||||||
|  | 		ret += isTainted + "}"; | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static HashSet<HeapObject> objSet; | ||||||
|  | 
 | ||||||
|  | 	public static TaintValue operate(AbstractInsnNode insn, List<? extends TaintValue> values, | ||||||
|  | 			TaintValue calculatedVal) { | ||||||
|  | 		TaintValue retVal = null; | ||||||
|  | 		String desc; | ||||||
|  | 		switch (insn.getOpcode()) { | ||||||
|  | 		case Opcodes.INVOKEVIRTUAL: | ||||||
|  | 			desc = ((MethodInsnNode) insn).owner; | ||||||
|  | 			if (isGetScopeObject((MethodInsnNode) insn) && values.size() != 0) { | ||||||
|  | 				TaintValue tv = values.get(0); | ||||||
|  | 				if (tv instanceof HeapObject) { | ||||||
|  | 					HeapObject heapObject = (HeapObject) tv; | ||||||
|  | 					retVal = heapObject.getProp("getScope"); | ||||||
|  | 					if (retVal == null) { | ||||||
|  | 						return calculatedVal; | ||||||
|  | 					} else | ||||||
|  | 						return retVal; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case Opcodes.INVOKESPECIAL: | ||||||
|  | 		case Opcodes.INVOKESTATIC: | ||||||
|  | 		case Opcodes.INVOKEINTERFACE: | ||||||
|  | 			break; | ||||||
|  | 		case Opcodes.INVOKEDYNAMIC: | ||||||
|  | 			desc = ((InvokeDynamicInsnNode) insn).name; | ||||||
|  | 			desc = desc.replaceAll(".*:", ""); | ||||||
|  | 			if (isDynGet((InvokeDynamicInsnNode) insn)) { | ||||||
|  | 				TaintValue tval = values.get(0); | ||||||
|  | 				if (tval instanceof HeapObject) { | ||||||
|  | 					HeapObject heapObject = (HeapObject) tval; | ||||||
|  | 					retVal = heapObject.getProp(desc); | ||||||
|  | 					if (retVal != null) { | ||||||
|  | 						if (TaintConfig.isDebug) | ||||||
|  | 							System.out.println("[HeapObject] get:" + desc + " taintVal:" + retVal); | ||||||
|  | 						return retVal; | ||||||
|  | 					} else { | ||||||
|  | 						if (TaintConfig.isDebug) | ||||||
|  | 							System.out.println("[HeapObject] get:" + desc + " taintVal: empty"); | ||||||
|  | 						heapObject.setProp(desc, new HeapObject()); | ||||||
|  | 						return heapObject.getProp(desc); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					// TODO | ||||||
|  | 				} | ||||||
|  | 			} else if (isDynSet((InvokeDynamicInsnNode) insn)) { | ||||||
|  | 				// TaintValue tv = values.get(0); | ||||||
|  | 				if (TaintConfig.isDebug) | ||||||
|  | 					System.out.println("[HeapObject] set:" + desc + " taintVal:" + values.get(1)); | ||||||
|  | 				TaintValue tval = values.get(0); | ||||||
|  | 				if (tval instanceof HeapObject) { | ||||||
|  | 					HeapObject heapObject = (HeapObject) tval; | ||||||
|  | 					// heapObject.merge(values.get(1)); | ||||||
|  | 					heapObject.setProp(desc, | ||||||
|  | 							values.get(1) instanceof HeapObject ? values.get(1) : new HeapObject(values.get(1))); | ||||||
|  | 				} else { | ||||||
|  | 					HeapObject heapObject = new HeapObject(tval); | ||||||
|  | 					heapObject.merge(tval); | ||||||
|  | 					// heapObject.merge(values.get(1)); | ||||||
|  | 					heapObject.setProp(desc, values.get(1)); | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				for (TaintValue tv : values) { | ||||||
|  | 					if (tv instanceof HeapObject) { | ||||||
|  | 						calculatedVal.isTainted |= ((HeapObject) tv).wholeTaint(); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 		return calculatedVal; | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static boolean isDynGet(InvokeDynamicInsnNode insn) { | ||||||
|  | 		String desc = insn.name; | ||||||
|  | 		if (desc.contains("getProp") && desc.contains("getMethod") && desc.contains("getElem")) { | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static boolean isDynSet(InvokeDynamicInsnNode insn) { | ||||||
|  | 		String desc = insn.name; | ||||||
|  | 		if (desc.contains("setProp") && desc.contains("setElem")) { | ||||||
|  | 			// System.out.println(desc); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static boolean isGetScopeObject(MethodInsnNode insn) { | ||||||
|  | 		if (insn.owner.contains("wrp/jdk/nashorn/internal/runtime/ScriptFunction") && insn.name.equals("getScope")) | ||||||
|  | 			return true; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintValue getProp(String str) { | ||||||
|  | 		return fields.get(str); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintValue setProp(String str, TaintValue val) { | ||||||
|  | 		return fields.put(str, val); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public HeapObject clone() { | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public HeapObject actualClone() { | ||||||
|  | 		ccObj = new HashMap<>(); | ||||||
|  | 		return cloneInternal(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	static Map<HeapObject, HeapObject> ccObj; | ||||||
|  | 
 | ||||||
|  | 	private HeapObject cloneInternal() { | ||||||
|  | 		if (ccObj.containsKey(this)) | ||||||
|  | 			return ccObj.get(this); | ||||||
|  | 		HeapObject ho = new HeapObject(); | ||||||
|  | 		ccObj.put(this, ho); | ||||||
|  | 		ho.isTainted = isTainted; | ||||||
|  | 		for (String field : fields.keySet()) { | ||||||
|  | 			TaintValue target = fields.get(field); | ||||||
|  | 			if (target instanceof HeapObject) | ||||||
|  | 				ho.fields.put(field, ((HeapObject) target).cloneInternal()); | ||||||
|  | 			else | ||||||
|  | 				ho.fields.put(field, target.clone()); | ||||||
|  | 		} | ||||||
|  | 		return ho; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO consider the "Cite circle" | ||||||
|  | 	public void heapMerge(TaintValue target) { | ||||||
|  | 		merge(target); | ||||||
|  | 		if (target instanceof HeapObject) { | ||||||
|  | 			HeapObject targetObject = (HeapObject) target; | ||||||
|  | 			for (String field : targetObject.fields.keySet()) { | ||||||
|  | 				if (fields.containsKey(field)) { | ||||||
|  | 					TaintValue t2 = fields.get(field); | ||||||
|  | 					TaintValue target2 = targetObject.fields.get(field); | ||||||
|  | 					// System.out.println("[HeapObject heapMerge]:" + field); | ||||||
|  | 					if (t2 instanceof HeapObject) { | ||||||
|  | 						((HeapObject) t2).heapMerge(target2); | ||||||
|  | 					} else if (target2 instanceof HeapObject) { | ||||||
|  | 						HeapObject next = ((HeapObject) target2).clone(); | ||||||
|  | 						next.merge(t2); | ||||||
|  | 						fields.put(field, next); | ||||||
|  | 					} else | ||||||
|  | 						t2.merge(target2); | ||||||
|  | 
 | ||||||
|  | 				} else | ||||||
|  | 					fields.put(field, targetObject.fields.get(field).clone()); | ||||||
|  | 
 | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public synchronized long wholeTaint() { | ||||||
|  | 		objSet = new HashSet<>(); | ||||||
|  | 		return wholeTaintInternal(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private long wholeTaintInternal() { | ||||||
|  | 		if (objSet.contains(this)) | ||||||
|  | 			return 0L; | ||||||
|  | 		objSet.add(this); | ||||||
|  | 		long ret = isTainted; | ||||||
|  | 		for (TaintValue tv : fields.values()) { | ||||||
|  | 			if (tv instanceof HeapObject) | ||||||
|  | 				ret |= ((HeapObject) tv).wholeTaintInternal(); | ||||||
|  | 			else | ||||||
|  | 				ret |= tv.isTainted; | ||||||
|  | 		} | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										70
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintBB.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintBB.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.AnalysisTarget; | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | 
 | ||||||
|  | public class TaintBB extends BasicBlock implements AnalysisTarget { | ||||||
|  | 	boolean inList = false; | ||||||
|  | 
 | ||||||
|  | 	public TaintBB(int id) { | ||||||
|  | 		super(id); | ||||||
|  | 		preResult = new TaintResult(); | ||||||
|  | 		sucResult = new TaintResult(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintResult preResult; | ||||||
|  | 	public TaintResult sucResult; | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean inList() { | ||||||
|  | 		return inList; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void setInList(boolean b) { | ||||||
|  | 		inList = b; | ||||||
|  | 	} | ||||||
|  | 	  | ||||||
|  | 	public String getResult() { | ||||||
|  | 		return (sucResult.frame2Str() + " Ret:" + sucResult.ret.toString()); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String getResultWithTaintBit() { | ||||||
|  | 		return "Ret:" + sucResult.ret.toReadableTaint(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintResult forwardAnalysis() { | ||||||
|  | 		TaintResult oldSuc = sucResult; | ||||||
|  | 		sucResult = (TaintResult) preResult.clone(); | ||||||
|  | 		TaintResult currentResult = sucResult; | ||||||
|  | 		List<AbstractInsnNode> insns = getInsn(); | ||||||
|  | 		if (TaintConfig.isDebug) | ||||||
|  | 			System.out.println("[TaintBB] Enter B" + blockID + ":" + getResult() + " size:" + insns.size()); | ||||||
|  | 
 | ||||||
|  | 		for (int i = 0; i < insns.size(); i++) { | ||||||
|  | 			currentResult = (TaintResult) currentResult.merge(insns.get(i)); | ||||||
|  | 		} | ||||||
|  | 		currentResult.mergeResult(oldSuc); | ||||||
|  | 
 | ||||||
|  | 		if (TaintConfig.isDebug) | ||||||
|  | 			System.out.println("[TaintBB] Leave B" + blockID + ":" + getResult() + " size:" + insns.size()); | ||||||
|  | 		// already done. | ||||||
|  | 		return currentResult; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public AbstractInsnNode lastInsn() { | ||||||
|  | 		return list.get(list.size() - 1); | ||||||
|  | 	} | ||||||
|  | 	public AbstractInsnNode firstInsn() { | ||||||
|  | 		return list.get(0); | ||||||
|  | 	} | ||||||
|  | 	public List<AbstractInsnNode> AllInsn() { | ||||||
|  | 		return list; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintBits.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintBits.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | public class TaintBits { | ||||||
|  | 	Map<Long, String> data; | ||||||
|  | 	Map<String, Long> type2Taint; | ||||||
|  | 	long curr; | ||||||
|  | 	Map<String, String> reallocate; | ||||||
|  | 	int count = 0; | ||||||
|  | 
 | ||||||
|  | 	public TaintBits() { | ||||||
|  | 		curr = 1L; | ||||||
|  | 		data = new HashMap<>(); | ||||||
|  | 		type2Taint = new HashMap<>(); | ||||||
|  | 		reallocate = new HashMap<>(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public long allocate(String type) { | ||||||
|  | 		type = reallocateCall(type); | ||||||
|  | 		if (type2Taint.containsKey(type)) | ||||||
|  | 			return type2Taint.get(type); | ||||||
|  | 		long ret = curr; | ||||||
|  | 		data.put(curr, type); | ||||||
|  | 		type2Taint.put(type, curr); | ||||||
|  | 		curr <<= 1; | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private String reallocateCall(String type) { | ||||||
|  | 		if (reallocate.containsKey(type)) | ||||||
|  | 			return reallocate.get(type); | ||||||
|  | 		if (type.contains("dyn:call:executeContract")) { | ||||||
|  | 			reallocate.put(type, "executeContract" + (count++)); | ||||||
|  | 			return reallocate.get(type); | ||||||
|  | 		} | ||||||
|  | 		return type; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public long getTaintValue(String type) { | ||||||
|  | 		type = reallocateCall(type); | ||||||
|  | 		if (type2Taint.containsKey(type)) | ||||||
|  | 			return type2Taint.get(type); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String taintInfo() { | ||||||
|  | 		String ret = ""; | ||||||
|  | 		long curr = this.curr >> 1; | ||||||
|  | 		for (; curr >= 1L;) { | ||||||
|  | 			ret += data.get(curr) + ", "; | ||||||
|  | 			curr >>= 1; | ||||||
|  | 		} | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String parse(long isTainted) { | ||||||
|  | 		String ret = ""; | ||||||
|  | 		long curr = this.curr >> 1; | ||||||
|  | 		for (; curr >= 1L;) { | ||||||
|  | 			if ((isTainted & curr) != 0) | ||||||
|  | 				ret += data.get(curr) + " "; | ||||||
|  | 			curr >>= 1; | ||||||
|  | 		} | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										84
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintCFG.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintCFG.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.BasicBlock; | ||||||
|  | import org.bdware.analysis.CFGraph; | ||||||
|  | import org.bdware.analysis.InsnPrinter; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.InvokeDynamicInsnNode; | ||||||
|  | import org.objectweb.asm.tree.MethodNode; | ||||||
|  | 
 | ||||||
|  | public class TaintCFG extends CFGraph { | ||||||
|  | 	public TaintBits taintBits; | ||||||
|  | 
 | ||||||
|  | 	public TaintCFG(MethodNode mn) { | ||||||
|  | 		super(mn); | ||||||
|  | 		taintBits = new TaintBits(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public BasicBlock getBasicBlock(int id) { | ||||||
|  | 		return new TaintBB(id); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public int argsLocal() { | ||||||
|  | 		String desc = getMethodNode().desc; | ||||||
|  | 		String[] parameters = desc.split("[)]"); | ||||||
|  | 		String parameter = parameters[0]; | ||||||
|  | 		String[] args = parameter.split("[;]"); | ||||||
|  | 		return args.length - 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void executeLocal() { | ||||||
|  | 		for (BasicBlock bb : basicBlocks) { | ||||||
|  | 			for (AbstractInsnNode an : bb.getInsn()) { | ||||||
|  | 				if (an instanceof InvokeDynamicInsnNode) { | ||||||
|  | 					InvokeDynamicInsnNode inDy = (InvokeDynamicInsnNode) an; | ||||||
|  | 					if (inDy.name.contains("dyn:call:executeContract")) { | ||||||
|  | 						taintBits.allocate(inDy.name + inDy.hashCode()); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void printSelf() { | ||||||
|  | 		InsnPrinter printer = new InsnPrinter(Opcodes.ASM4, System.out); | ||||||
|  | 		printer.setLabelOrder(getLabelOrder()); | ||||||
|  | 		System.out.println("======Method:" + getMethodNode().name + getMethodNode().desc + "======="); | ||||||
|  | 		System.out.println("=====TaintInfo: " + taintBits.taintInfo() + "==========="); | ||||||
|  | 		for (BasicBlock bb : basicBlocks) { | ||||||
|  | 			System.out.print("==B" + bb.blockID); | ||||||
|  | 			if (getSucBlocks(bb).size() > 0) | ||||||
|  | 				System.out.print("-->"); | ||||||
|  | 			for (BasicBlock suc : getSucBlocks(bb)) | ||||||
|  | 				System.out.print(" B" + suc.blockID); | ||||||
|  | 			System.out.println("=="); | ||||||
|  | 			TaintBB b = (TaintBB) bb; | ||||||
|  | 			if (b.preResult != null) { | ||||||
|  | 				System.out.print("前序分析结果:"); | ||||||
|  | 				b.preResult.printResult(); | ||||||
|  | 			    //System.out.println("test:"+b.getResultWithTaintBit()); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			for (AbstractInsnNode an : bb.getInsn()) { | ||||||
|  | 				an.accept(printer); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintBB getLastBlock() { | ||||||
|  | 		if (basicBlocks != null && basicBlocks.size() > 0) | ||||||
|  | 			return (TaintBB) basicBlocks.get(basicBlocks.size() - 1); | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public List<BasicBlock> getBlocks() { | ||||||
|  | 		return basicBlocks; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | public class TaintConfig { | ||||||
|  | 	public static boolean isDebug = false; | ||||||
|  | } | ||||||
| @ -0,0 +1,177 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.InvokeDynamicInsnNode; | ||||||
|  | import org.objectweb.asm.tree.MethodInsnNode; | ||||||
|  | import org.objectweb.asm.tree.TypeInsnNode; | ||||||
|  | import org.objectweb.asm.tree.analysis.AnalyzerException; | ||||||
|  | import org.objectweb.asm.tree.analysis.Interpreter; | ||||||
|  | 
 | ||||||
|  | public class TaintInterpreter extends Interpreter<TaintValue> { | ||||||
|  | 	TaintResult currentResult; | ||||||
|  | 	TaintBits taintBits; | ||||||
|  | 
 | ||||||
|  | 	public TaintInterpreter(int api) { | ||||||
|  | 		super(api); | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue newValue(Type type) { | ||||||
|  | 		if (type != null) | ||||||
|  | 			return new TaintValue(type.getSize()); | ||||||
|  | 		return new TaintValue(1); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue newOperation(AbstractInsnNode insn) throws AnalyzerException { | ||||||
|  | 		TaintValue ret; | ||||||
|  | 		switch (insn.getOpcode()) { | ||||||
|  | 		case Opcodes.LCONST_0: | ||||||
|  | 		case Opcodes.LCONST_1: | ||||||
|  | 		case Opcodes.DCONST_0: | ||||||
|  | 		case Opcodes.DCONST_1: | ||||||
|  | 			ret = new TaintValue(2); | ||||||
|  | 			break; | ||||||
|  | 		case Opcodes.NEW: | ||||||
|  | 			TypeInsnNode typeNode = (TypeInsnNode) insn; | ||||||
|  | 			if (typeNode.desc.startsWith("wrp/jdk/nashorn/internal/scripts/JO")) { | ||||||
|  | 				ret = new HeapObject(); | ||||||
|  | 			} else { | ||||||
|  | 				ret = new TaintValue(1); | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			ret = new TaintValue(1); | ||||||
|  | 		} | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue copyOperation(AbstractInsnNode insn, TaintValue value) throws AnalyzerException { | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue unaryOperation(AbstractInsnNode insn, TaintValue value) throws AnalyzerException { | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue binaryOperation(AbstractInsnNode insn, TaintValue value1, TaintValue value2) | ||||||
|  | 			throws AnalyzerException { | ||||||
|  | 		/* | ||||||
|  | 		 * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD, LADD, | ||||||
|  | 		 * FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, | ||||||
|  | 		 * DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, | ||||||
|  | 		 * LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IF_ICMPEQ, | ||||||
|  | 		 * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, | ||||||
|  | 		 * PUTFIELD | ||||||
|  | 		 */ | ||||||
|  | 		TaintValue ret = new TaintValue(1); | ||||||
|  | 		ret.isTainted = value1.isTainted | value2.isTainted; | ||||||
|  | 		switch (insn.getOpcode()) { | ||||||
|  | 		case Opcodes.DALOAD: | ||||||
|  | 		case Opcodes.DADD: | ||||||
|  | 		case Opcodes.DSUB: | ||||||
|  | 		case Opcodes.DMUL: | ||||||
|  | 		case Opcodes.DDIV: | ||||||
|  | 		case Opcodes.DREM: | ||||||
|  | 		case Opcodes.LALOAD: | ||||||
|  | 		case Opcodes.LADD: | ||||||
|  | 		case Opcodes.LSUB: | ||||||
|  | 		case Opcodes.LMUL: | ||||||
|  | 		case Opcodes.LDIV: | ||||||
|  | 		case Opcodes.LREM: | ||||||
|  | 		case Opcodes.LSHL: | ||||||
|  | 		case Opcodes.LSHR: | ||||||
|  | 		case Opcodes.LUSHR: | ||||||
|  | 		case Opcodes.LAND: | ||||||
|  | 		case Opcodes.LXOR: | ||||||
|  | 		case Opcodes.LOR: | ||||||
|  | 			ret.size = 2; | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue ternaryOperation(AbstractInsnNode insn, TaintValue value1, TaintValue value2, TaintValue value3) | ||||||
|  | 			throws AnalyzerException { | ||||||
|  | 		// TODO | ||||||
|  | 		value1.isTainted |= value3.isTainted; | ||||||
|  | 		return value1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue naryOperation(AbstractInsnNode insn, List<? extends TaintValue> values) throws AnalyzerException { | ||||||
|  | 		int size = 1; | ||||||
|  | 		/* | ||||||
|  | 		 * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, MULTIANEWARRAY | ||||||
|  | 		 * and INVOKEDYNAMIC | ||||||
|  | 		 */ | ||||||
|  | 		String desc; | ||||||
|  | 		switch (insn.getOpcode()) { | ||||||
|  | 		case Opcodes.INVOKEVIRTUAL: | ||||||
|  | 		case Opcodes.INVOKESPECIAL: | ||||||
|  | 		case Opcodes.INVOKESTATIC: | ||||||
|  | 		case Opcodes.INVOKEINTERFACE: | ||||||
|  | 			desc = ((MethodInsnNode) insn).desc; | ||||||
|  | 			if (desc != null && (desc.charAt(desc.length() - 1) == 'D' || desc.charAt(desc.length() - 1) == 'J')) | ||||||
|  | 				size = 2; | ||||||
|  | 			break; | ||||||
|  | 		case Opcodes.INVOKEDYNAMIC: | ||||||
|  | 			desc = ((InvokeDynamicInsnNode) insn).desc; | ||||||
|  | 			if (desc != null && (desc.charAt(desc.length() - 1) == 'D' || desc.charAt(desc.length() - 1) == 'J')) | ||||||
|  | 				size = 2; | ||||||
|  | 
 | ||||||
|  | 			// Extra..Judgeffff x | ||||||
|  | 			if (((InvokeDynamicInsnNode) insn).name.startsWith("dyn:setElem|setProp:")) { | ||||||
|  | 				if (values.size() == 2) { | ||||||
|  | 					values.get(0).isTainted |= values.get(1).isTainted; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 		TaintValue ret = new TaintValue(size); | ||||||
|  | 		for (TaintValue v : values) | ||||||
|  | 			if (v != null) | ||||||
|  | 				ret.isTainted |= v.isTainted; | ||||||
|  | 		if (insn instanceof InvokeDynamicInsnNode) { | ||||||
|  | 			long taint = (taintBits.getTaintValue(((InvokeDynamicInsnNode) insn).name + insn.hashCode())); | ||||||
|  | 
 | ||||||
|  | 			if (taint > 0L) | ||||||
|  | 				ret.isTainted |= taint; | ||||||
|  | 		} | ||||||
|  | 		return HeapObject.operate(insn, values, ret); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void returnOperation(AbstractInsnNode insn, TaintValue value, TaintValue expected) throws AnalyzerException { | ||||||
|  | 		if (value instanceof HeapObject) { | ||||||
|  | 			currentResult.ret.isTainted |= ((HeapObject) value).wholeTaint(); | ||||||
|  | 		} else if (value!=null) | ||||||
|  | 			currentResult.ret.isTainted |= value.isTainted; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public TaintValue merge(TaintValue v, TaintValue w) { | ||||||
|  | 		TaintValue ret = new TaintValue(v.getSize()); | ||||||
|  | 		ret.isTainted |= v.isTainted; | ||||||
|  | 		ret.isTainted |= w.isTainted; | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setCurrentResult(TaintResult naiveTaintResult) { | ||||||
|  | 		currentResult = naiveTaintResult; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setTaintBits(TaintBits tb) { | ||||||
|  | 		taintBits = tb; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										190
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintResult.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintResult.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,190 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import org.bdware.analysis.AnalysisResult; | ||||||
|  | import org.bdware.analysis.InsnPrinter; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.analysis.AnalyzerException; | ||||||
|  | import org.objectweb.asm.tree.analysis.Frame; | ||||||
|  | 
 | ||||||
|  | public class TaintResult extends AnalysisResult { | ||||||
|  | 	// public HeapObject heapObejct; | ||||||
|  | 	public Frame<TaintValue> frame; | ||||||
|  | 	public TaintValue ret; | ||||||
|  | 	public static int nLocals = 0; | ||||||
|  | 	public static int nStack = 0; | ||||||
|  | 	public static InsnPrinter printer = new InsnPrinter(Opcodes.ASM4, System.out); | ||||||
|  | 	public static TaintInterpreter interpreter = new TaintInterpreter(Opcodes.ASM4); | ||||||
|  | 
 | ||||||
|  | 	public TaintResult() { | ||||||
|  | 		frame = new Frame<>(nLocals, nStack); | ||||||
|  | 		ret = new TaintValue(1); | ||||||
|  | 		ret.isTainted = 0L; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public AnalysisResult merge(AbstractInsnNode insn) { | ||||||
|  | 		interpreter.setCurrentResult(this); | ||||||
|  | 		try { | ||||||
|  | 			if (TaintConfig.isDebug && insn.getOpcode() >= 0) { | ||||||
|  | 				System.out.println("[TaintResult] frameStatus:" + frame2Str()); | ||||||
|  | 				insn.accept(printer); | ||||||
|  | 			} | ||||||
|  | 			if (insn.getOpcode() < 0) { | ||||||
|  | 				// System.out.println("[TaintResult] MetLabel:" + | ||||||
|  | 				// insn.getClass().getCanonicalName()); | ||||||
|  | 			} else | ||||||
|  | 				frame.execute(insn, interpreter); | ||||||
|  | 			if (TaintConfig.isDebug && insn.getOpcode() >= 0) { | ||||||
|  | 				System.out.println("[TaintResult] frameStatus:" + frame2Str()); | ||||||
|  | 
 | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		} catch (AnalyzerException e) { | ||||||
|  | 			// TODO Auto-generated catch block | ||||||
|  | 			e.printStackTrace(); | ||||||
|  | 		} | ||||||
|  | 		// we use suc instead,so we don't create new object here. | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void printResult() { | ||||||
|  | 		System.out.println("====" + frame2Str() + " Ret:" + ret.toString() + "===="); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String frame2Str() { | ||||||
|  | 		StringBuilder sb = new StringBuilder(); | ||||||
|  | 		sb.append("Local:"); | ||||||
|  | 		for (int i = 0; i < frame.getLocals(); i++) { // getLocals<EFBFBD><EFBFBD><EFBFBD><EFBFBD>local<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>size | ||||||
|  | 			TaintValue t = frame.getLocal(i); | ||||||
|  | 			if (t != null) | ||||||
|  | 				sb.append(t.toString()); | ||||||
|  | 			else | ||||||
|  | 				sb.append("0--"); | ||||||
|  | 		} | ||||||
|  | 		sb.append(" Stack:"); | ||||||
|  | 		for (int i = 0; i < frame.getStackSize(); i++) { // getStackSize<EFBFBD><EFBFBD><EFBFBD><EFBFBD>stack<EFBFBD>ĵ<EFBFBD>ǰsize | ||||||
|  | 			TaintValue t = frame.getStack(i); | ||||||
|  | 			if (t != null) | ||||||
|  | 				sb.append(t.toString()); | ||||||
|  | 			else | ||||||
|  | 				sb.append("0--"); | ||||||
|  | 		} | ||||||
|  | 		return sb.toString(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private static boolean cover(TaintValue t1, TaintValue t2) { | ||||||
|  | 		// if (t2 == null || t2.isTainted == 0) | ||||||
|  | 		// return true; | ||||||
|  | 		// TODO whether is cover? | ||||||
|  | 		if (t1 != null && t1.isTainted != 0) { | ||||||
|  | 			if (t2 == null || t1.isTainted != t2.isTainted) | ||||||
|  | 				return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* | ||||||
|  | 	 * private static boolean isTainted(TaintValue t1) { if (t1 != null && | ||||||
|  | 	 * t1.isTainted) { return true; } return false; } | ||||||
|  | 	 */ | ||||||
|  | 	private static boolean isTainted(TaintValue t1) { | ||||||
|  | 		if (t1 != null && t1.isTainted != 0) { | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean covers(AnalysisResult result) { | ||||||
|  | 		TaintResult tr = (TaintResult) result; | ||||||
|  | 		boolean ret = coversInternal(tr); | ||||||
|  | 		return ret; | ||||||
|  | 		// System.out.println("[NaiveTaintResult] Cover:" + ret); | ||||||
|  | 		// System.out.println("[NaiveTaintResult] " + frame.toString()); | ||||||
|  | 		// System.out.println("[NaiveTaintResult] " + tr.frame.toString());	 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// preResult cover sucResult means | ||||||
|  | 	// preResult's taint is large or equals sucResult. | ||||||
|  | 	public boolean coversInternal(TaintResult tr) { | ||||||
|  | 		for (int i = 0; i < frame.getLocals() && i < tr.frame.getLocals(); i++) | ||||||
|  | 			if (cover(tr.frame.getLocal(i), frame.getLocal(i))) | ||||||
|  | 				return false; | ||||||
|  | 		// TODO why locals is not equal?? | ||||||
|  | 		for (int i = frame.getLocals(); i < tr.frame.getLocals(); i++) | ||||||
|  | 			if (isTainted(tr.frame.getLocal(i))) | ||||||
|  | 				return false; | ||||||
|  | 		for (int i = 0; i < frame.getStackSize() && i < tr.frame.getStackSize(); i++) | ||||||
|  | 			if (cover(tr.frame.getStack(i), frame.getStack(i))) | ||||||
|  | 				return false; | ||||||
|  | 		for (int i = frame.getStackSize(); i < tr.frame.getStackSize(); i++) | ||||||
|  | 			if (isTainted(tr.frame.getStack(i))) | ||||||
|  | 				return false; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void mergeResult(AnalysisResult r) { | ||||||
|  | 		TaintResult from = (TaintResult) r; | ||||||
|  | 		for (int i = 0; i < from.frame.getLocals(); i++) { | ||||||
|  | 			TaintValue target = from.frame.getLocal(i); | ||||||
|  | 			if (frame.getLocals() > i) { | ||||||
|  | 				TaintValue t1 = frame.getLocal(i); | ||||||
|  | 				if (target != null) { | ||||||
|  | 					if (t1 == null) { | ||||||
|  | 						t1 = target.clone(); | ||||||
|  | 						frame.setLocal(i, t1); | ||||||
|  | 					} else { | ||||||
|  | 						t1.merge(target); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				frame.setLocal(i, target.clone()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for (int i = 0; i < from.frame.getStackSize(); i++) { | ||||||
|  | 			TaintValue target = from.frame.getStack(i); | ||||||
|  | 			if (frame.getStackSize() > i) { | ||||||
|  | 				TaintValue t1 = frame.getStack(i); | ||||||
|  | 				if (target != null) { | ||||||
|  | 					if (t1 == null) { | ||||||
|  | 						t1 = target.clone(); | ||||||
|  | 						frame.setStack(i, t1); | ||||||
|  | 					} else { | ||||||
|  | 						t1.merge(target); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				t1.merge(from.frame.getStack(i)); | ||||||
|  | 			} else { | ||||||
|  | 				if (target != null) | ||||||
|  | 					frame.push(target.clone()); | ||||||
|  | 				else | ||||||
|  | 					frame.push(new TaintValue(1,0)); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		ret.merge(from.ret);  | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public AnalysisResult clone() { | ||||||
|  | 		TaintResult ret = new TaintResult(); | ||||||
|  | 		ret.frame = new Frame<>(frame); | ||||||
|  | 		for (int i = 0; i < ret.frame.getLocals(); i++) { | ||||||
|  | 			TaintValue t = ret.frame.getLocal(i); | ||||||
|  | 			if (t != null) | ||||||
|  | 				ret.frame.setLocal(i, t.clone()); | ||||||
|  | 		} | ||||||
|  | 		for (int i = 0; i < ret.frame.getStackSize(); i++) { | ||||||
|  | 			TaintValue t = ret.frame.getStack(i); | ||||||
|  | 			if (t != null) | ||||||
|  | 				ret.frame.setStack(i, t.clone()); | ||||||
|  | 		} | ||||||
|  | 		ret.ret = this.ret.clone(); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintValue.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/main/analysis/org/bdware/analysis/taint/TaintValue.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | package org.bdware.analysis.taint; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.tree.analysis.Value; | ||||||
|  | 
 | ||||||
|  | public class TaintValue implements Value { | ||||||
|  | 	public int size; | ||||||
|  | 	// public boolean isTainted; | ||||||
|  | 	public long isTainted; | ||||||
|  | 
 | ||||||
|  | 	public TaintValue(int size) { | ||||||
|  | 		this.size = size; | ||||||
|  | 		isTainted = 0L; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintValue(int size, long isTainted) { | ||||||
|  | 		this.size = size; | ||||||
|  | 		this.isTainted = isTainted; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public int getSize() { | ||||||
|  | 		return size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String toString() { | ||||||
|  | 		String s = Long.toBinaryString(isTainted); | ||||||
|  | 		char[] c = s.toCharArray(); | ||||||
|  | 		StringBuffer buf = new StringBuffer(); | ||||||
|  | 		for (int i = 0; i < c.length; i++) { | ||||||
|  | 			if (c[i] == '1') | ||||||
|  | 				buf.append("1/"); | ||||||
|  | 			else | ||||||
|  | 				buf.append("0/"); | ||||||
|  | 		} | ||||||
|  | 		buf.append("--"); | ||||||
|  | 		return buf.toString(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public TaintValue clone() { | ||||||
|  | 		TaintValue ret = new TaintValue(size); | ||||||
|  | 		ret.isTainted = isTainted; | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String toReadableTaint() { | ||||||
|  | 		return TaintResult.interpreter.taintBits.parse(isTainted); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void merge(TaintValue target) { | ||||||
|  | 		if (target != null) | ||||||
|  | 			isTainted |= target.isTainted; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										169
									
								
								src/main/asm/org/objectweb/asm/AnnotationVisitor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/main/asm/org/objectweb/asm/AnnotationVisitor.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A visitor to visit a Java annotation. The methods of this class must be | ||||||
|  |  * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> | | ||||||
|  |  * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public abstract class AnnotationVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The ASM API version implemented by this visitor. The value of this field | ||||||
|  |      * must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     protected final int api; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The annotation visitor to which this visitor must delegate method calls. | ||||||
|  |      * May be null. | ||||||
|  |      */ | ||||||
|  |     protected AnnotationVisitor av; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link AnnotationVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor(final int api) { | ||||||
|  |         this(api, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link AnnotationVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param av | ||||||
|  |      *            the annotation visitor to which this visitor must delegate | ||||||
|  |      *            method calls. May be null. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor(final int api, final AnnotationVisitor av) { | ||||||
|  |         if (api != Opcodes.ASM4) { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         this.api = api; | ||||||
|  |         this.av = av; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a primitive value of the annotation. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the value name. | ||||||
|  |      * @param value | ||||||
|  |      *            the actual value, whose type must be {@link Byte}, | ||||||
|  |      *            {@link Boolean}, {@link Character}, {@link Short}, | ||||||
|  |      *            {@link Integer} , {@link Long}, {@link Float}, {@link Double}, | ||||||
|  |      *            {@link String} or {@link Type} or OBJECT or ARRAY sort. This | ||||||
|  |      *            value can also be an array of byte, boolean, short, char, int, | ||||||
|  |      *            long, float or double values (this is equivalent to using | ||||||
|  |      *            {@link #visitArray visitArray} and visiting each array element | ||||||
|  |      *            in turn, but is more convenient). | ||||||
|  |      */ | ||||||
|  |     public void visit(String name, Object value) { | ||||||
|  |         if (av != null) { | ||||||
|  |             av.visit(name, value); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an enumeration value of the annotation. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the value name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the class descriptor of the enumeration class. | ||||||
|  |      * @param value | ||||||
|  |      *            the actual enumeration value. | ||||||
|  |      */ | ||||||
|  |     public void visitEnum(String name, String desc, String value) { | ||||||
|  |         if (av != null) { | ||||||
|  |             av.visitEnum(name, desc, value); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a nested annotation value of the annotation. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the value name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the class descriptor of the nested annotation class. | ||||||
|  |      * @return a visitor to visit the actual nested annotation value, or | ||||||
|  |      *         <tt>null</tt> if this visitor is not interested in visiting this | ||||||
|  |      *         nested annotation. <i>The nested annotation value must be fully | ||||||
|  |      *         visited before calling other methods on this annotation | ||||||
|  |      *         visitor</i>. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitAnnotation(String name, String desc) { | ||||||
|  |         if (av != null) { | ||||||
|  |             return av.visitAnnotation(name, desc); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an array value of the annotation. Note that arrays of primitive | ||||||
|  |      * types (such as byte, boolean, short, char, int, long, float or double) | ||||||
|  |      * can be passed as value to {@link #visit visit}. This is what | ||||||
|  |      * {@link ClassReader} does. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the value name. | ||||||
|  |      * @return a visitor to visit the actual array value elements, or | ||||||
|  |      *         <tt>null</tt> if this visitor is not interested in visiting these | ||||||
|  |      *         values. The 'name' parameters passed to the methods of this | ||||||
|  |      *         visitor are ignored. <i>All the array values must be visited | ||||||
|  |      *         before calling other methods on this annotation visitor</i>. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitArray(String name) { | ||||||
|  |         if (av != null) { | ||||||
|  |             return av.visitArray(name); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the end of the annotation. | ||||||
|  |      */ | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (av != null) { | ||||||
|  |             av.visitEnd(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										378
									
								
								src/main/asm/org/objectweb/asm/AnnotationWriter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								src/main/asm/org/objectweb/asm/AnnotationWriter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,378 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An {@link AnnotationVisitor} that generates annotations in bytecode form. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | final class AnnotationWriter extends AnnotationVisitor | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The class writer to which this annotation must be added. | ||||||
|  | 	 */ | ||||||
|  | 	private final ClassWriter cw; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The number of values in this annotation. | ||||||
|  | 	 */ | ||||||
|  | 	private int size; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation | ||||||
|  | 	 * writers used for annotation default and annotation arrays use unnamed | ||||||
|  | 	 * values. | ||||||
|  | 	 */ | ||||||
|  | 	private final boolean named; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The annotation values in bytecode form. This byte vector only contains | ||||||
|  | 	 * the values themselves, i.e. the number of values must be stored as a | ||||||
|  | 	 * unsigned short just before these bytes. | ||||||
|  | 	 */ | ||||||
|  | 	private final ByteVector bv; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The byte vector to be used to store the number of values of this | ||||||
|  | 	 * annotation. See {@link #bv}. | ||||||
|  | 	 */ | ||||||
|  | 	private final ByteVector parent; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Where the number of values of this annotation must be stored in | ||||||
|  | 	 * {@link #parent}. | ||||||
|  | 	 */ | ||||||
|  | 	private final int offset; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Next annotation writer. This field is used to store annotation lists. | ||||||
|  | 	 */ | ||||||
|  | 	AnnotationWriter next; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Previous annotation writer. This field is used to store annotation lists. | ||||||
|  | 	 */ | ||||||
|  | 	AnnotationWriter prev; | ||||||
|  | 
 | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 	// Constructor | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Constructs a new {@link AnnotationWriter}. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param cw | ||||||
|  | 	 *            the class writer to which this annotation must be added. | ||||||
|  | 	 * @param named | ||||||
|  | 	 *            <tt>true<tt> if values are named, <tt>false</tt> otherwise. | ||||||
|  | 	 * @param bv | ||||||
|  | 	 *            where the annotation values must be stored. | ||||||
|  | 	 * @param parent | ||||||
|  | 	 *            where the number of annotation values must be stored. | ||||||
|  | 	 * @param offset | ||||||
|  | 	 *            where in <tt>parent</tt> the number of annotation values must | ||||||
|  | 	 *            be stored. | ||||||
|  | 	 */ | ||||||
|  | 	AnnotationWriter(final ClassWriter cw, final boolean named, | ||||||
|  | 			final ByteVector bv, final ByteVector parent, final int offset) | ||||||
|  | 	{ | ||||||
|  | 		super(Opcodes.ASM4); | ||||||
|  | 		this.cw = cw; | ||||||
|  | 		this.named = named; | ||||||
|  | 		this.bv = bv; | ||||||
|  | 		this.parent = parent; | ||||||
|  | 		this.offset = offset; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 	// Implementation of the AnnotationVisitor abstract class | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void visit(final String name, final Object value) | ||||||
|  | 	{ | ||||||
|  | 		++size; | ||||||
|  | 		if (named) | ||||||
|  | 		{ | ||||||
|  | 			bv.putShort(cw.newUTF8(name)); | ||||||
|  | 		} | ||||||
|  | 		if (value instanceof String) | ||||||
|  | 		{ | ||||||
|  | 			bv.put12('s', cw.newUTF8((String) value)); | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof Byte) | ||||||
|  | 		{ | ||||||
|  | 			bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof Boolean) | ||||||
|  | 		{ | ||||||
|  | 			int v = ((Boolean) value).booleanValue() ? 1 : 0; | ||||||
|  | 			bv.put12('Z', cw.newInteger(v).index); | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof Character) | ||||||
|  | 		{ | ||||||
|  | 			bv.put12('C', cw.newInteger(((Character) value).charValue()).index); | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof Short) | ||||||
|  | 		{ | ||||||
|  | 			bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof Type) | ||||||
|  | 		{ | ||||||
|  | 			bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof byte[]) | ||||||
|  | 		{ | ||||||
|  | 			byte[] v = (byte[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('B', cw.newInteger(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof boolean[]) | ||||||
|  | 		{ | ||||||
|  | 			boolean[] v = (boolean[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof short[]) | ||||||
|  | 		{ | ||||||
|  | 			short[] v = (short[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('S', cw.newInteger(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof char[]) | ||||||
|  | 		{ | ||||||
|  | 			char[] v = (char[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('C', cw.newInteger(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof int[]) | ||||||
|  | 		{ | ||||||
|  | 			int[] v = (int[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('I', cw.newInteger(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof long[]) | ||||||
|  | 		{ | ||||||
|  | 			long[] v = (long[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('J', cw.newLong(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof float[]) | ||||||
|  | 		{ | ||||||
|  | 			float[] v = (float[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('F', cw.newFloat(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (value instanceof double[]) | ||||||
|  | 		{ | ||||||
|  | 			double[] v = (double[]) value; | ||||||
|  | 			bv.put12('[', v.length); | ||||||
|  | 			for (int i = 0; i < v.length; i++) | ||||||
|  | 			{ | ||||||
|  | 				bv.put12('D', cw.newDouble(v[i]).index); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			Item i = cw.newConstItem(value); | ||||||
|  | 			bv.put12(".s.IFJDCS".charAt(i.type), i.index); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void visitEnum(final String name, final String desc, | ||||||
|  | 			final String value) | ||||||
|  | 	{ | ||||||
|  | 		++size; | ||||||
|  | 		// TODO add by chq! &&name!=null; | ||||||
|  | 		if (named && name != null) | ||||||
|  | 		{ | ||||||
|  | 			bv.putShort(cw.newUTF8(name)); | ||||||
|  | 		} | ||||||
|  | 		bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public AnnotationVisitor visitAnnotation(final String name, | ||||||
|  | 			final String desc) | ||||||
|  | 	{ | ||||||
|  | 		++size; | ||||||
|  | 		if (named) | ||||||
|  | 		{ | ||||||
|  | 			bv.putShort(cw.newUTF8(name)); | ||||||
|  | 		} | ||||||
|  | 		// write tag and type, and reserve space for values count | ||||||
|  | 		bv.put12('@', cw.newUTF8(desc)).putShort(0); | ||||||
|  | 		return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public AnnotationVisitor visitArray(final String name) | ||||||
|  | 	{ | ||||||
|  | 		++size; | ||||||
|  | 		if (named) | ||||||
|  | 		{ | ||||||
|  | 			bv.putShort(cw.newUTF8(name)); | ||||||
|  | 		} | ||||||
|  | 		// write tag, and reserve space for array size | ||||||
|  | 		bv.put12('[', 0); | ||||||
|  | 		return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void visitEnd() | ||||||
|  | 	{ | ||||||
|  | 		if (parent != null) | ||||||
|  | 		{ | ||||||
|  | 			byte[] data = parent.data; | ||||||
|  | 			data[offset] = (byte) (size >>> 8); | ||||||
|  | 			data[offset + 1] = (byte) size; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 	// Utility methods | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the size of this annotation writer list. | ||||||
|  | 	 *  | ||||||
|  | 	 * @return the size of this annotation writer list. | ||||||
|  | 	 */ | ||||||
|  | 	int getSize() | ||||||
|  | 	{ | ||||||
|  | 		int size = 0; | ||||||
|  | 		AnnotationWriter aw = this; | ||||||
|  | 		while (aw != null) | ||||||
|  | 		{ | ||||||
|  | 			size += aw.bv.length; | ||||||
|  | 			aw = aw.next; | ||||||
|  | 		} | ||||||
|  | 		return size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Puts the annotations of this annotation writer list into the given byte | ||||||
|  | 	 * vector. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param out | ||||||
|  | 	 *            where the annotations must be put. | ||||||
|  | 	 */ | ||||||
|  | 	void put(final ByteVector out) | ||||||
|  | 	{ | ||||||
|  | 		int n = 0; | ||||||
|  | 		int size = 2; | ||||||
|  | 		AnnotationWriter aw = this; | ||||||
|  | 		AnnotationWriter last = null; | ||||||
|  | 		while (aw != null) | ||||||
|  | 		{ | ||||||
|  | 			++n; | ||||||
|  | 			size += aw.bv.length; | ||||||
|  | 			aw.visitEnd(); // in case user forgot to call visitEnd | ||||||
|  | 			aw.prev = last; | ||||||
|  | 			last = aw; | ||||||
|  | 			aw = aw.next; | ||||||
|  | 		} | ||||||
|  | 		out.putInt(size); | ||||||
|  | 		out.putShort(n); | ||||||
|  | 		aw = last; | ||||||
|  | 		while (aw != null) | ||||||
|  | 		{ | ||||||
|  | 			out.putByteArray(aw.bv.data, 0, aw.bv.length); | ||||||
|  | 			aw = aw.prev; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Puts the given annotation lists into the given byte vector. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param panns | ||||||
|  | 	 *            an array of annotation writer lists. | ||||||
|  | 	 * @param off | ||||||
|  | 	 *            index of the first annotation to be written. | ||||||
|  | 	 * @param out | ||||||
|  | 	 *            where the annotations must be put. | ||||||
|  | 	 */ | ||||||
|  | 	static void put(final AnnotationWriter[] panns, final int off, | ||||||
|  | 			final ByteVector out) | ||||||
|  | 	{ | ||||||
|  | 		int size = 1 + 2 * (panns.length - off); | ||||||
|  | 		for (int i = off; i < panns.length; ++i) | ||||||
|  | 		{ | ||||||
|  | 			size += panns[i] == null ? 0 : panns[i].getSize(); | ||||||
|  | 		} | ||||||
|  | 		out.putInt(size).putByte(panns.length - off); | ||||||
|  | 		for (int i = off; i < panns.length; ++i) | ||||||
|  | 		{ | ||||||
|  | 			AnnotationWriter aw = panns[i]; | ||||||
|  | 			AnnotationWriter last = null; | ||||||
|  | 			int n = 0; | ||||||
|  | 			while (aw != null) | ||||||
|  | 			{ | ||||||
|  | 				++n; | ||||||
|  | 				aw.visitEnd(); // in case user forgot to call visitEnd | ||||||
|  | 				aw.prev = last; | ||||||
|  | 				last = aw; | ||||||
|  | 				aw = aw.next; | ||||||
|  | 			} | ||||||
|  | 			out.putShort(n); | ||||||
|  | 			aw = last; | ||||||
|  | 			while (aw != null) | ||||||
|  | 			{ | ||||||
|  | 				out.putByteArray(aw.bv.data, 0, aw.bv.length); | ||||||
|  | 				aw = aw.prev; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										255
									
								
								src/main/asm/org/objectweb/asm/Attribute.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								src/main/asm/org/objectweb/asm/Attribute.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,255 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A non standard class, field, method or code attribute. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class Attribute { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of this attribute. | ||||||
|  |      */ | ||||||
|  |     public final String type; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The raw value of this attribute, used only for unknown attributes. | ||||||
|  |      */ | ||||||
|  |     byte[] value; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The next attribute in this attribute list. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     Attribute next; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new empty attribute. | ||||||
|  |      *  | ||||||
|  |      * @param type | ||||||
|  |      *            the type of the attribute. | ||||||
|  |      */ | ||||||
|  |     protected Attribute(final String type) { | ||||||
|  |         this.type = type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns <tt>true</tt> if this type of attribute is unknown. The default | ||||||
|  |      * implementation of this method always returns <tt>true</tt>. | ||||||
|  |      *  | ||||||
|  |      * @return <tt>true</tt> if this type of attribute is unknown. | ||||||
|  |      */ | ||||||
|  |     public boolean isUnknown() { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns <tt>true</tt> if this type of attribute is a code attribute. | ||||||
|  |      *  | ||||||
|  |      * @return <tt>true</tt> if this type of attribute is a code attribute. | ||||||
|  |      */ | ||||||
|  |     public boolean isCodeAttribute() { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the labels corresponding to this attribute. | ||||||
|  |      *  | ||||||
|  |      * @return the labels corresponding to this attribute, or <tt>null</tt> if | ||||||
|  |      *         this attribute is not a code attribute that contains labels. | ||||||
|  |      */ | ||||||
|  |     protected Label[] getLabels() { | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Reads a {@link #type type} attribute. This method must return a | ||||||
|  |      * <i>new</i> {@link Attribute} object, of type {@link #type type}, | ||||||
|  |      * corresponding to the <tt>len</tt> bytes starting at the given offset, in | ||||||
|  |      * the given class reader. | ||||||
|  |      *  | ||||||
|  |      * @param cr | ||||||
|  |      *            the class that contains the attribute to be read. | ||||||
|  |      * @param off | ||||||
|  |      *            index of the first byte of the attribute's content in | ||||||
|  |      *            {@link ClassReader#b cr.b}. The 6 attribute header bytes, | ||||||
|  |      *            containing the type and the length of the attribute, are not | ||||||
|  |      *            taken into account here. | ||||||
|  |      * @param len | ||||||
|  |      *            the length of the attribute's content. | ||||||
|  |      * @param buf | ||||||
|  |      *            buffer to be used to call {@link ClassReader#readUTF8 | ||||||
|  |      *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} | ||||||
|  |      *            or {@link ClassReader#readConst readConst}. | ||||||
|  |      * @param codeOff | ||||||
|  |      *            index of the first byte of code's attribute content in | ||||||
|  |      *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read | ||||||
|  |      *            is not a code attribute. The 6 attribute header bytes, | ||||||
|  |      *            containing the type and the length of the attribute, are not | ||||||
|  |      *            taken into account here. | ||||||
|  |      * @param labels | ||||||
|  |      *            the labels of the method's code, or <tt>null</tt> if the | ||||||
|  |      *            attribute to be read is not a code attribute. | ||||||
|  |      * @return a <i>new</i> {@link Attribute} object corresponding to the given | ||||||
|  |      *         bytes. | ||||||
|  |      */ | ||||||
|  |     protected Attribute read(final ClassReader cr, final int off, | ||||||
|  |             final int len, final char[] buf, final int codeOff, | ||||||
|  |             final Label[] labels) { | ||||||
|  |         Attribute attr = new Attribute(type); | ||||||
|  |         attr.value = new byte[len]; | ||||||
|  |         System.arraycopy(cr.b, off, attr.value, 0, len); | ||||||
|  |         return attr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the byte array form of this attribute. | ||||||
|  |      *  | ||||||
|  |      * @param cw | ||||||
|  |      *            the class to which this attribute must be added. This | ||||||
|  |      *            parameter can be used to add to the constant pool of this | ||||||
|  |      *            class the items that corresponds to this attribute. | ||||||
|  |      * @param code | ||||||
|  |      *            the bytecode of the method corresponding to this code | ||||||
|  |      *            attribute, or <tt>null</tt> if this attribute is not a code | ||||||
|  |      *            attributes. | ||||||
|  |      * @param len | ||||||
|  |      *            the length of the bytecode of the method corresponding to this | ||||||
|  |      *            code attribute, or <tt>null</tt> if this attribute is not a | ||||||
|  |      *            code attribute. | ||||||
|  |      * @param maxStack | ||||||
|  |      *            the maximum stack size of the method corresponding to this | ||||||
|  |      *            code attribute, or -1 if this attribute is not a code | ||||||
|  |      *            attribute. | ||||||
|  |      * @param maxLocals | ||||||
|  |      *            the maximum number of local variables of the method | ||||||
|  |      *            corresponding to this code attribute, or -1 if this attribute | ||||||
|  |      *            is not a code attribute. | ||||||
|  |      * @return the byte array form of this attribute. | ||||||
|  |      */ | ||||||
|  |     protected ByteVector write(final ClassWriter cw, final byte[] code, | ||||||
|  |             final int len, final int maxStack, final int maxLocals) { | ||||||
|  |         ByteVector v = new ByteVector(); | ||||||
|  |         v.data = value; | ||||||
|  |         v.length = value.length; | ||||||
|  |         return v; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the length of the attribute list that begins with this attribute. | ||||||
|  |      *  | ||||||
|  |      * @return the length of the attribute list that begins with this attribute. | ||||||
|  |      */ | ||||||
|  |     final int getCount() { | ||||||
|  |         int count = 0; | ||||||
|  |         Attribute attr = this; | ||||||
|  |         while (attr != null) { | ||||||
|  |             count += 1; | ||||||
|  |             attr = attr.next; | ||||||
|  |         } | ||||||
|  |         return count; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the size of all the attributes in this attribute list. | ||||||
|  |      *  | ||||||
|  |      * @param cw | ||||||
|  |      *            the class writer to be used to convert the attributes into | ||||||
|  |      *            byte arrays, with the {@link #write write} method. | ||||||
|  |      * @param code | ||||||
|  |      *            the bytecode of the method corresponding to these code | ||||||
|  |      *            attributes, or <tt>null</tt> if these attributes are not code | ||||||
|  |      *            attributes. | ||||||
|  |      * @param len | ||||||
|  |      *            the length of the bytecode of the method corresponding to | ||||||
|  |      *            these code attributes, or <tt>null</tt> if these attributes | ||||||
|  |      *            are not code attributes. | ||||||
|  |      * @param maxStack | ||||||
|  |      *            the maximum stack size of the method corresponding to these | ||||||
|  |      *            code attributes, or -1 if these attributes are not code | ||||||
|  |      *            attributes. | ||||||
|  |      * @param maxLocals | ||||||
|  |      *            the maximum number of local variables of the method | ||||||
|  |      *            corresponding to these code attributes, or -1 if these | ||||||
|  |      *            attributes are not code attributes. | ||||||
|  |      * @return the size of all the attributes in this attribute list. This size | ||||||
|  |      *         includes the size of the attribute headers. | ||||||
|  |      */ | ||||||
|  |     final int getSize(final ClassWriter cw, final byte[] code, final int len, | ||||||
|  |             final int maxStack, final int maxLocals) { | ||||||
|  |         Attribute attr = this; | ||||||
|  |         int size = 0; | ||||||
|  |         while (attr != null) { | ||||||
|  |             cw.newUTF8(attr.type); | ||||||
|  |             size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; | ||||||
|  |             attr = attr.next; | ||||||
|  |         } | ||||||
|  |         return size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Writes all the attributes of this attribute list in the given byte | ||||||
|  |      * vector. | ||||||
|  |      *  | ||||||
|  |      * @param cw | ||||||
|  |      *            the class writer to be used to convert the attributes into | ||||||
|  |      *            byte arrays, with the {@link #write write} method. | ||||||
|  |      * @param code | ||||||
|  |      *            the bytecode of the method corresponding to these code | ||||||
|  |      *            attributes, or <tt>null</tt> if these attributes are not code | ||||||
|  |      *            attributes. | ||||||
|  |      * @param len | ||||||
|  |      *            the length of the bytecode of the method corresponding to | ||||||
|  |      *            these code attributes, or <tt>null</tt> if these attributes | ||||||
|  |      *            are not code attributes. | ||||||
|  |      * @param maxStack | ||||||
|  |      *            the maximum stack size of the method corresponding to these | ||||||
|  |      *            code attributes, or -1 if these attributes are not code | ||||||
|  |      *            attributes. | ||||||
|  |      * @param maxLocals | ||||||
|  |      *            the maximum number of local variables of the method | ||||||
|  |      *            corresponding to these code attributes, or -1 if these | ||||||
|  |      *            attributes are not code attributes. | ||||||
|  |      * @param out | ||||||
|  |      *            where the attributes must be written. | ||||||
|  |      */ | ||||||
|  |     final void put(final ClassWriter cw, final byte[] code, final int len, | ||||||
|  |             final int maxStack, final int maxLocals, final ByteVector out) { | ||||||
|  |         Attribute attr = this; | ||||||
|  |         while (attr != null) { | ||||||
|  |             ByteVector b = attr.write(cw, code, len, maxStack, maxLocals); | ||||||
|  |             out.putShort(cw.newUTF8(attr.type)).putInt(b.length); | ||||||
|  |             out.putByteArray(b.data, 0, b.length); | ||||||
|  |             attr = attr.next; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										312
									
								
								src/main/asm/org/objectweb/asm/ByteVector.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/main/asm/org/objectweb/asm/ByteVector.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,312 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A dynamically extensible vector of bytes. This class is roughly equivalent to | ||||||
|  |  * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class ByteVector { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The content of this vector. | ||||||
|  |      */ | ||||||
|  |     byte[] data; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Actual number of bytes in this vector. | ||||||
|  |      */ | ||||||
|  |     int length; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link ByteVector ByteVector} with a default initial | ||||||
|  |      * size. | ||||||
|  |      */ | ||||||
|  |     public ByteVector() { | ||||||
|  |         data = new byte[64]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link ByteVector ByteVector} with the given initial | ||||||
|  |      * size. | ||||||
|  |      *  | ||||||
|  |      * @param initialSize | ||||||
|  |      *            the initial size of the byte vector to be constructed. | ||||||
|  |      */ | ||||||
|  |     public ByteVector(final int initialSize) { | ||||||
|  |         data = new byte[initialSize]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts a byte into this byte vector. The byte vector is automatically | ||||||
|  |      * enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param b | ||||||
|  |      *            a byte. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     public ByteVector putByte(final int b) { | ||||||
|  |         int length = this.length; | ||||||
|  |         if (length + 1 > data.length) { | ||||||
|  |             enlarge(1); | ||||||
|  |         } | ||||||
|  |         data[length++] = (byte) b; | ||||||
|  |         this.length = length; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts two bytes into this byte vector. The byte vector is automatically | ||||||
|  |      * enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param b1 | ||||||
|  |      *            a byte. | ||||||
|  |      * @param b2 | ||||||
|  |      *            another byte. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     ByteVector put11(final int b1, final int b2) { | ||||||
|  |         int length = this.length; | ||||||
|  |         if (length + 2 > data.length) { | ||||||
|  |             enlarge(2); | ||||||
|  |         } | ||||||
|  |         byte[] data = this.data; | ||||||
|  |         data[length++] = (byte) b1; | ||||||
|  |         data[length++] = (byte) b2; | ||||||
|  |         this.length = length; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts a short into this byte vector. The byte vector is automatically | ||||||
|  |      * enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param s | ||||||
|  |      *            a short. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     public ByteVector putShort(final int s) { | ||||||
|  |         int length = this.length; | ||||||
|  |         if (length + 2 > data.length) { | ||||||
|  |             enlarge(2); | ||||||
|  |         } | ||||||
|  |         byte[] data = this.data; | ||||||
|  |         data[length++] = (byte) (s >>> 8); | ||||||
|  |         data[length++] = (byte) s; | ||||||
|  |         this.length = length; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts a byte and a short into this byte vector. The byte vector is | ||||||
|  |      * automatically enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param b | ||||||
|  |      *            a byte. | ||||||
|  |      * @param s | ||||||
|  |      *            a short. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     ByteVector put12(final int b, final int s) { | ||||||
|  |         int length = this.length; | ||||||
|  |         if (length + 3 > data.length) { | ||||||
|  |             enlarge(3); | ||||||
|  |         } | ||||||
|  |         byte[] data = this.data; | ||||||
|  |         data[length++] = (byte) b; | ||||||
|  |         data[length++] = (byte) (s >>> 8); | ||||||
|  |         data[length++] = (byte) s; | ||||||
|  |         this.length = length; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts an int into this byte vector. The byte vector is automatically | ||||||
|  |      * enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param i | ||||||
|  |      *            an int. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     public ByteVector putInt(final int i) { | ||||||
|  |         int length = this.length; | ||||||
|  |         if (length + 4 > data.length) { | ||||||
|  |             enlarge(4); | ||||||
|  |         } | ||||||
|  |         byte[] data = this.data; | ||||||
|  |         data[length++] = (byte) (i >>> 24); | ||||||
|  |         data[length++] = (byte) (i >>> 16); | ||||||
|  |         data[length++] = (byte) (i >>> 8); | ||||||
|  |         data[length++] = (byte) i; | ||||||
|  |         this.length = length; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts a long into this byte vector. The byte vector is automatically | ||||||
|  |      * enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param l | ||||||
|  |      *            a long. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     public ByteVector putLong(final long l) { | ||||||
|  |         int length = this.length; | ||||||
|  |         if (length + 8 > data.length) { | ||||||
|  |             enlarge(8); | ||||||
|  |         } | ||||||
|  |         byte[] data = this.data; | ||||||
|  |         int i = (int) (l >>> 32); | ||||||
|  |         data[length++] = (byte) (i >>> 24); | ||||||
|  |         data[length++] = (byte) (i >>> 16); | ||||||
|  |         data[length++] = (byte) (i >>> 8); | ||||||
|  |         data[length++] = (byte) i; | ||||||
|  |         i = (int) l; | ||||||
|  |         data[length++] = (byte) (i >>> 24); | ||||||
|  |         data[length++] = (byte) (i >>> 16); | ||||||
|  |         data[length++] = (byte) (i >>> 8); | ||||||
|  |         data[length++] = (byte) i; | ||||||
|  |         this.length = length; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts an UTF8 string into this byte vector. The byte vector is | ||||||
|  |      * automatically enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param s | ||||||
|  |      *            a String whose UTF8 encoded length must be less than 65536. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     public ByteVector putUTF8(final String s) { | ||||||
|  |         int charLength = s.length(); | ||||||
|  |         if (charLength > 65535) { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         int len = length; | ||||||
|  |         if (len + 2 + charLength > data.length) { | ||||||
|  |             enlarge(2 + charLength); | ||||||
|  |         } | ||||||
|  |         byte[] data = this.data; | ||||||
|  |         // optimistic algorithm: instead of computing the byte length and then | ||||||
|  |         // serializing the string (which requires two loops), we assume the byte | ||||||
|  |         // length is equal to char length (which is the most frequent case), and | ||||||
|  |         // we start serializing the string right away. During the serialization, | ||||||
|  |         // if we find that this assumption is wrong, we continue with the | ||||||
|  |         // general method. | ||||||
|  |         data[len++] = (byte) (charLength >>> 8); | ||||||
|  |         data[len++] = (byte) charLength; | ||||||
|  |         for (int i = 0; i < charLength; ++i) { | ||||||
|  |             char c = s.charAt(i); | ||||||
|  |             if (c >= '\001' && c <= '\177') { | ||||||
|  |                 data[len++] = (byte) c; | ||||||
|  |             } else { | ||||||
|  |                 int byteLength = i; | ||||||
|  |                 for (int j = i; j < charLength; ++j) { | ||||||
|  |                     c = s.charAt(j); | ||||||
|  |                     if (c >= '\001' && c <= '\177') { | ||||||
|  |                         byteLength++; | ||||||
|  |                     } else if (c > '\u07FF') { | ||||||
|  |                         byteLength += 3; | ||||||
|  |                     } else { | ||||||
|  |                         byteLength += 2; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (byteLength > 65535) { | ||||||
|  |                     throw new IllegalArgumentException(); | ||||||
|  |                 } | ||||||
|  |                 data[length] = (byte) (byteLength >>> 8); | ||||||
|  |                 data[length + 1] = (byte) byteLength; | ||||||
|  |                 if (length + 2 + byteLength > data.length) { | ||||||
|  |                     length = len; | ||||||
|  |                     enlarge(2 + byteLength); | ||||||
|  |                     data = this.data; | ||||||
|  |                 } | ||||||
|  |                 for (int j = i; j < charLength; ++j) { | ||||||
|  |                     c = s.charAt(j); | ||||||
|  |                     if (c >= '\001' && c <= '\177') { | ||||||
|  |                         data[len++] = (byte) c; | ||||||
|  |                     } else if (c > '\u07FF') { | ||||||
|  |                         data[len++] = (byte) (0xE0 | c >> 12 & 0xF); | ||||||
|  |                         data[len++] = (byte) (0x80 | c >> 6 & 0x3F); | ||||||
|  |                         data[len++] = (byte) (0x80 | c & 0x3F); | ||||||
|  |                     } else { | ||||||
|  |                         data[len++] = (byte) (0xC0 | c >> 6 & 0x1F); | ||||||
|  |                         data[len++] = (byte) (0x80 | c & 0x3F); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         length = len; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts an array of bytes into this byte vector. The byte vector is | ||||||
|  |      * automatically enlarged if necessary. | ||||||
|  |      *  | ||||||
|  |      * @param b | ||||||
|  |      *            an array of bytes. May be <tt>null</tt> to put <tt>len</tt> | ||||||
|  |      *            null bytes into this byte vector. | ||||||
|  |      * @param off | ||||||
|  |      *            index of the fist byte of b that must be copied. | ||||||
|  |      * @param len | ||||||
|  |      *            number of bytes of b that must be copied. | ||||||
|  |      * @return this byte vector. | ||||||
|  |      */ | ||||||
|  |     public ByteVector putByteArray(final byte[] b, final int off, final int len) { | ||||||
|  |         if (length + len > data.length) { | ||||||
|  |             enlarge(len); | ||||||
|  |         } | ||||||
|  |         if (b != null) { | ||||||
|  |             System.arraycopy(b, off, data, length, len); | ||||||
|  |         } | ||||||
|  |         length += len; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Enlarge this byte vector so that it can receive n more bytes. | ||||||
|  |      *  | ||||||
|  |      * @param size | ||||||
|  |      *            number of additional bytes that this byte vector should be | ||||||
|  |      *            able to receive. | ||||||
|  |      */ | ||||||
|  |     private void enlarge(final int size) { | ||||||
|  |         int length1 = 2 * data.length; | ||||||
|  |         int length2 = length + size; | ||||||
|  |         byte[] newData = new byte[length1 > length2 ? length1 : length2]; | ||||||
|  |         System.arraycopy(data, 0, newData, 0, length); | ||||||
|  |         data = newData; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										2518
									
								
								src/main/asm/org/objectweb/asm/ClassReader.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2518
									
								
								src/main/asm/org/objectweb/asm/ClassReader.java
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										286
									
								
								src/main/asm/org/objectweb/asm/ClassVisitor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								src/main/asm/org/objectweb/asm/ClassVisitor.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A visitor to visit a Java class. The methods of this class must be called in | ||||||
|  |  * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ | ||||||
|  |  * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | | ||||||
|  |  * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> | <tt>visitField</tt> | | ||||||
|  |  * <tt>visitMethod</tt> )* <tt>visitEnd</tt>. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public abstract class ClassVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The ASM API version implemented by this visitor. The value of this field | ||||||
|  |      * must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     protected final int api; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The class visitor to which this visitor must delegate method calls. May | ||||||
|  |      * be null. | ||||||
|  |      */ | ||||||
|  |     protected ClassVisitor cv; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link ClassVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public ClassVisitor(final int api) { | ||||||
|  |         this(api, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link ClassVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param cv | ||||||
|  |      *            the class visitor to which this visitor must delegate method | ||||||
|  |      *            calls. May be null. | ||||||
|  |      */ | ||||||
|  |     public ClassVisitor(final int api, final ClassVisitor cv) { | ||||||
|  |         if (api != Opcodes.ASM4) { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         this.api = api; | ||||||
|  |         this.cv = cv; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the header of the class. | ||||||
|  |      *  | ||||||
|  |      * @param version | ||||||
|  |      *            the class version. | ||||||
|  |      * @param access | ||||||
|  |      *            the class's access flags (see {@link Opcodes}). This parameter | ||||||
|  |      *            also indicates if the class is deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the internal name of the class (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the signature of this class. May be <tt>null</tt> if the class | ||||||
|  |      *            is not a generic one, and does not extend or implement generic | ||||||
|  |      *            classes or interfaces. | ||||||
|  |      * @param superName | ||||||
|  |      *            the internal of name of the super class (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). For | ||||||
|  |      *            interfaces, the super class is {@link Object}. May be | ||||||
|  |      *            <tt>null</tt>, but only for the {@link Object} class. | ||||||
|  |      * @param interfaces | ||||||
|  |      *            the internal names of the class's interfaces (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). May be | ||||||
|  |      *            <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public void visit(int version, int access, String name, String signature, | ||||||
|  |             String superName, String[] interfaces) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             cv.visit(version, access, name, signature, superName, interfaces); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the source of the class. | ||||||
|  |      *  | ||||||
|  |      * @param source | ||||||
|  |      *            the name of the source file from which the class was compiled. | ||||||
|  |      *            May be <tt>null</tt>. | ||||||
|  |      * @param debug | ||||||
|  |      *            additional debug information to compute the correspondance | ||||||
|  |      *            between source and compiled elements of the class. May be | ||||||
|  |      *            <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public void visitSource(String source, String debug) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             cv.visitSource(source, debug); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the enclosing class of the class. This method must be called only | ||||||
|  |      * if the class has an enclosing class. | ||||||
|  |      *  | ||||||
|  |      * @param owner | ||||||
|  |      *            internal name of the enclosing class of the class. | ||||||
|  |      * @param name | ||||||
|  |      *            the name of the method that contains the class, or | ||||||
|  |      *            <tt>null</tt> if the class is not enclosed in a method of its | ||||||
|  |      *            enclosing class. | ||||||
|  |      * @param desc | ||||||
|  |      *            the descriptor of the method that contains the class, or | ||||||
|  |      *            <tt>null</tt> if the class is not enclosed in a method of its | ||||||
|  |      *            enclosing class. | ||||||
|  |      */ | ||||||
|  |     public void visitOuterClass(String owner, String name, String desc) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             cv.visitOuterClass(owner, name, desc); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an annotation of the class. | ||||||
|  |      *  | ||||||
|  |      * @param desc | ||||||
|  |      *            the class descriptor of the annotation class. | ||||||
|  |      * @param visible | ||||||
|  |      *            <tt>true</tt> if the annotation is visible at runtime. | ||||||
|  |      * @return a visitor to visit the annotation values, or <tt>null</tt> if | ||||||
|  |      *         this visitor is not interested in visiting this annotation. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             return cv.visitAnnotation(desc, visible); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a non standard attribute of the class. | ||||||
|  |      *  | ||||||
|  |      * @param attr | ||||||
|  |      *            an attribute. | ||||||
|  |      */ | ||||||
|  |     public void visitAttribute(Attribute attr) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             cv.visitAttribute(attr); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits information about an inner class. This inner class is not | ||||||
|  |      * necessarily a member of the class being visited. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the internal name of an inner class (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). | ||||||
|  |      * @param outerName | ||||||
|  |      *            the internal name of the class to which the inner class | ||||||
|  |      *            belongs (see {@link Type#getInternalName() getInternalName}). | ||||||
|  |      *            May be <tt>null</tt> for not member classes. | ||||||
|  |      * @param innerName | ||||||
|  |      *            the (simple) name of the inner class inside its enclosing | ||||||
|  |      *            class. May be <tt>null</tt> for anonymous inner classes. | ||||||
|  |      * @param access | ||||||
|  |      *            the access flags of the inner class as originally declared in | ||||||
|  |      *            the enclosing class. | ||||||
|  |      */ | ||||||
|  |     public void visitInnerClass(String name, String outerName, | ||||||
|  |             String innerName, int access) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             cv.visitInnerClass(name, outerName, innerName, access); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a field of the class. | ||||||
|  |      *  | ||||||
|  |      * @param access | ||||||
|  |      *            the field's access flags (see {@link Opcodes}). This parameter | ||||||
|  |      *            also indicates if the field is synthetic and/or deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the field's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the field's descriptor (see {@link Type Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the field's signature. May be <tt>null</tt> if the field's | ||||||
|  |      *            type does not use generic types. | ||||||
|  |      * @param value | ||||||
|  |      *            the field's initial value. This parameter, which may be | ||||||
|  |      *            <tt>null</tt> if the field does not have an initial value, | ||||||
|  |      *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  |      *            {@link Double} or a {@link String} (for <tt>int</tt>, | ||||||
|  |      *            <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields | ||||||
|  |      *            respectively). <i>This parameter is only used for static | ||||||
|  |      *            fields</i>. Its value is ignored for non static fields, which | ||||||
|  |      *            must be initialized through bytecode instructions in | ||||||
|  |      *            constructors or methods. | ||||||
|  |      * @return a visitor to visit field annotations and attributes, or | ||||||
|  |      *         <tt>null</tt> if this class visitor is not interested in visiting | ||||||
|  |      *         these annotations and attributes. | ||||||
|  |      */ | ||||||
|  |     public FieldVisitor visitField(int access, String name, String desc, | ||||||
|  |             String signature, Object value) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             return cv.visitField(access, name, desc, signature, value); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a method of the class. This method <i>must</i> return a new | ||||||
|  |      * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called, | ||||||
|  |      * i.e., it should not return a previously returned visitor. | ||||||
|  |      *  | ||||||
|  |      * @param access | ||||||
|  |      *            the method's access flags (see {@link Opcodes}). This | ||||||
|  |      *            parameter also indicates if the method is synthetic and/or | ||||||
|  |      *            deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the method's signature. May be <tt>null</tt> if the method | ||||||
|  |      *            parameters, return type and exceptions do not use generic | ||||||
|  |      *            types. | ||||||
|  |      * @param exceptions | ||||||
|  |      *            the internal names of the method's exception classes (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). May be | ||||||
|  |      *            <tt>null</tt>. | ||||||
|  |      * @return an object to visit the byte code of the method, or <tt>null</tt> | ||||||
|  |      *         if this class visitor is not interested in visiting the code of | ||||||
|  |      *         this method. | ||||||
|  |      */ | ||||||
|  |     public MethodVisitor visitMethod(int access, String name, String desc, | ||||||
|  |             String signature, String[] exceptions) { | ||||||
|  |         if (cv != null) { | ||||||
|  |             return cv.visitMethod(access, name, desc, signature, exceptions); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the end of the class. This method, which is the last one to be | ||||||
|  |      * called, is used to inform the visitor that all the fields and methods of | ||||||
|  |      * the class have been visited. | ||||||
|  |      */ | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (cv != null) { | ||||||
|  |             cv.visitEnd(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1706
									
								
								src/main/asm/org/objectweb/asm/ClassWriter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1706
									
								
								src/main/asm/org/objectweb/asm/ClassWriter.java
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										110
									
								
								src/main/asm/org/objectweb/asm/Context.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/main/asm/org/objectweb/asm/Context.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Information about a class being parsed in a {@link ClassReader}. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | class Context { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Prototypes of the attributes that must be parsed for this class. | ||||||
|  |      */ | ||||||
|  |     Attribute[] attrs; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The {@link ClassReader} option flags for the parsing of this class. | ||||||
|  |      */ | ||||||
|  |     int flags; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The buffer used to read strings. | ||||||
|  |      */ | ||||||
|  |     char[] buffer; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The start index of each bootstrap method. | ||||||
|  |      */ | ||||||
|  |     int[] bootstrapMethods; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The access flags of the method currently being parsed. | ||||||
|  |      */ | ||||||
|  |     int access; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The name of the method currently being parsed. | ||||||
|  |      */ | ||||||
|  |     String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The descriptor of the method currently being parsed. | ||||||
|  |      */ | ||||||
|  |     String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The offset of the latest stack map frame that has been parsed. | ||||||
|  |      */ | ||||||
|  |     int offset; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The encoding of the latest stack map frame that has been parsed. | ||||||
|  |      */ | ||||||
|  |     int mode; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The number of locals in the latest stack map frame that has been parsed. | ||||||
|  |      */ | ||||||
|  |     int localCount; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The number locals in the latest stack map frame that has been parsed, | ||||||
|  |      * minus the number of locals in the previous frame. | ||||||
|  |      */ | ||||||
|  |     int localDiff; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The local values of the latest stack map frame that has been parsed. | ||||||
|  |      */ | ||||||
|  |     Object[] local; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The stack size of the latest stack map frame that has been parsed. | ||||||
|  |      */ | ||||||
|  |     int stackCount; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The stack values of the latest stack map frame that has been parsed. | ||||||
|  |      */ | ||||||
|  |     Object[] stack; | ||||||
|  | } | ||||||
							
								
								
									
										75
									
								
								src/main/asm/org/objectweb/asm/Edge.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/main/asm/org/objectweb/asm/Edge.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An edge in the control flow graph of a method body. See {@link Label Label}. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | class Edge { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Denotes a normal control flow graph edge. | ||||||
|  |      */ | ||||||
|  |     static final int NORMAL = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Denotes a control flow graph edge corresponding to an exception handler. | ||||||
|  |      * More precisely any {@link Edge} whose {@link #info} is strictly positive | ||||||
|  |      * corresponds to an exception handler. The actual value of {@link #info} is | ||||||
|  |      * the index, in the {@link ClassWriter} type table, of the exception that | ||||||
|  |      * is catched. | ||||||
|  |      */ | ||||||
|  |     static final int EXCEPTION = 0x7FFFFFFF; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Information about this control flow graph edge. If | ||||||
|  |      * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) | ||||||
|  |      * stack size in the basic block from which this edge originates. This size | ||||||
|  |      * is equal to the stack size at the "jump" instruction to which this edge | ||||||
|  |      * corresponds, relatively to the stack size at the beginning of the | ||||||
|  |      * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, | ||||||
|  |      * this field is the kind of this control flow graph edge (i.e. NORMAL or | ||||||
|  |      * EXCEPTION). | ||||||
|  |      */ | ||||||
|  |     int info; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The successor block of the basic block from which this edge originates. | ||||||
|  |      */ | ||||||
|  |     Label successor; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The next edge in the list of successors of the originating basic block. | ||||||
|  |      * See {@link Label#successors successors}. | ||||||
|  |      */ | ||||||
|  |     Edge next; | ||||||
|  | } | ||||||
							
								
								
									
										121
									
								
								src/main/asm/org/objectweb/asm/FieldVisitor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/main/asm/org/objectweb/asm/FieldVisitor.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A visitor to visit a Java field. The methods of this class must be called in | ||||||
|  |  * the following order: ( <tt>visitAnnotation</tt> | <tt>visitAttribute</tt> )* | ||||||
|  |  * <tt>visitEnd</tt>. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public abstract class FieldVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The ASM API version implemented by this visitor. The value of this field | ||||||
|  |      * must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     protected final int api; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field visitor to which this visitor must delegate method calls. May | ||||||
|  |      * be null. | ||||||
|  |      */ | ||||||
|  |     protected FieldVisitor fv; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FieldVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public FieldVisitor(final int api) { | ||||||
|  |         this(api, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FieldVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param fv | ||||||
|  |      *            the field visitor to which this visitor must delegate method | ||||||
|  |      *            calls. May be null. | ||||||
|  |      */ | ||||||
|  |     public FieldVisitor(final int api, final FieldVisitor fv) { | ||||||
|  |         if (api != Opcodes.ASM4) { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         this.api = api; | ||||||
|  |         this.fv = fv; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an annotation of the field. | ||||||
|  |      *  | ||||||
|  |      * @param desc | ||||||
|  |      *            the class descriptor of the annotation class. | ||||||
|  |      * @param visible | ||||||
|  |      *            <tt>true</tt> if the annotation is visible at runtime. | ||||||
|  |      * @return a visitor to visit the annotation values, or <tt>null</tt> if | ||||||
|  |      *         this visitor is not interested in visiting this annotation. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | ||||||
|  |         if (fv != null) { | ||||||
|  |             return fv.visitAnnotation(desc, visible); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a non standard attribute of the field. | ||||||
|  |      *  | ||||||
|  |      * @param attr | ||||||
|  |      *            an attribute. | ||||||
|  |      */ | ||||||
|  |     public void visitAttribute(Attribute attr) { | ||||||
|  |         if (fv != null) { | ||||||
|  |             fv.visitAttribute(attr); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the end of the field. This method, which is the last one to be | ||||||
|  |      * called, is used to inform the visitor that all the annotations and | ||||||
|  |      * attributes of the field have been visited. | ||||||
|  |      */ | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (fv != null) { | ||||||
|  |             fv.visitEnd(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										273
									
								
								src/main/asm/org/objectweb/asm/FieldWriter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								src/main/asm/org/objectweb/asm/FieldWriter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,273 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An {@link FieldVisitor} that generates Java fields in bytecode form. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | final class FieldWriter extends FieldVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The class writer to which this field must be added. | ||||||
|  |      */ | ||||||
|  |     private final ClassWriter cw; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Access flags of this field. | ||||||
|  |      */ | ||||||
|  |     private final int access; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The index of the constant pool item that contains the name of this | ||||||
|  |      * method. | ||||||
|  |      */ | ||||||
|  |     private final int name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The index of the constant pool item that contains the descriptor of this | ||||||
|  |      * field. | ||||||
|  |      */ | ||||||
|  |     private final int desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The index of the constant pool item that contains the signature of this | ||||||
|  |      * field. | ||||||
|  |      */ | ||||||
|  |     private int signature; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The index of the constant pool item that contains the constant value of | ||||||
|  |      * this field. | ||||||
|  |      */ | ||||||
|  |     private int value; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The runtime visible annotations of this field. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     private AnnotationWriter anns; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The runtime invisible annotations of this field. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     private AnnotationWriter ianns; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The non standard attributes of this field. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     private Attribute attrs; | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Constructor | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FieldWriter}. | ||||||
|  |      *  | ||||||
|  |      * @param cw | ||||||
|  |      *            the class writer to which this field must be added. | ||||||
|  |      * @param access | ||||||
|  |      *            the field's access flags (see {@link Opcodes}). | ||||||
|  |      * @param name | ||||||
|  |      *            the field's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the field's descriptor (see {@link Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the field's signature. May be <tt>null</tt>. | ||||||
|  |      * @param value | ||||||
|  |      *            the field's constant value. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     FieldWriter(final ClassWriter cw, final int access, final String name, | ||||||
|  |             final String desc, final String signature, final Object value) { | ||||||
|  |         super(Opcodes.ASM4); | ||||||
|  |         if (cw.firstField == null) { | ||||||
|  |             cw.firstField = this; | ||||||
|  |         } else { | ||||||
|  |             cw.lastField.fv = this; | ||||||
|  |         } | ||||||
|  |         cw.lastField = this; | ||||||
|  |         this.cw = cw; | ||||||
|  |         this.access = access; | ||||||
|  |         this.name = cw.newUTF8(name); | ||||||
|  |         this.desc = cw.newUTF8(desc); | ||||||
|  |         if (ClassReader.SIGNATURES && signature != null) { | ||||||
|  |             this.signature = cw.newUTF8(signature); | ||||||
|  |         } | ||||||
|  |         if (value != null) { | ||||||
|  |             this.value = cw.newConstItem(value).index; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Implementation of the FieldVisitor abstract class | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(final String desc, | ||||||
|  |             final boolean visible) { | ||||||
|  |         if (!ClassReader.ANNOTATIONS) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         ByteVector bv = new ByteVector(); | ||||||
|  |         // write type, and reserve space for values count | ||||||
|  |         bv.putShort(cw.newUTF8(desc)).putShort(0); | ||||||
|  |         AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); | ||||||
|  |         if (visible) { | ||||||
|  |             aw.next = anns; | ||||||
|  |             anns = aw; | ||||||
|  |         } else { | ||||||
|  |             aw.next = ianns; | ||||||
|  |             ianns = aw; | ||||||
|  |         } | ||||||
|  |         return aw; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitAttribute(final Attribute attr) { | ||||||
|  |         attr.next = attrs; | ||||||
|  |         attrs = attr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Utility methods | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the size of this field. | ||||||
|  |      *  | ||||||
|  |      * @return the size of this field. | ||||||
|  |      */ | ||||||
|  |     int getSize() { | ||||||
|  |         int size = 8; | ||||||
|  |         if (value != 0) { | ||||||
|  |             cw.newUTF8("ConstantValue"); | ||||||
|  |             size += 8; | ||||||
|  |         } | ||||||
|  |         if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||||||
|  |             if ((cw.version & 0xFFFF) < Opcodes.V1_5 | ||||||
|  |                     || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { | ||||||
|  |                 cw.newUTF8("Synthetic"); | ||||||
|  |                 size += 6; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ((access & Opcodes.ACC_DEPRECATED) != 0) { | ||||||
|  |             cw.newUTF8("Deprecated"); | ||||||
|  |             size += 6; | ||||||
|  |         } | ||||||
|  |         if (ClassReader.SIGNATURES && signature != 0) { | ||||||
|  |             cw.newUTF8("Signature"); | ||||||
|  |             size += 8; | ||||||
|  |         } | ||||||
|  |         if (ClassReader.ANNOTATIONS && anns != null) { | ||||||
|  |             cw.newUTF8("RuntimeVisibleAnnotations"); | ||||||
|  |             size += 8 + anns.getSize(); | ||||||
|  |         } | ||||||
|  |         if (ClassReader.ANNOTATIONS && ianns != null) { | ||||||
|  |             cw.newUTF8("RuntimeInvisibleAnnotations"); | ||||||
|  |             size += 8 + ianns.getSize(); | ||||||
|  |         } | ||||||
|  |         if (attrs != null) { | ||||||
|  |             size += attrs.getSize(cw, null, 0, -1, -1); | ||||||
|  |         } | ||||||
|  |         return size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts the content of this field into the given byte vector. | ||||||
|  |      *  | ||||||
|  |      * @param out | ||||||
|  |      *            where the content of this field must be put. | ||||||
|  |      */ | ||||||
|  |     void put(final ByteVector out) { | ||||||
|  |         final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; | ||||||
|  |         int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE | ||||||
|  |                 | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); | ||||||
|  |         out.putShort(access & ~mask).putShort(name).putShort(desc); | ||||||
|  |         int attributeCount = 0; | ||||||
|  |         if (value != 0) { | ||||||
|  |             ++attributeCount; | ||||||
|  |         } | ||||||
|  |         if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||||||
|  |             if ((cw.version & 0xFFFF) < Opcodes.V1_5 | ||||||
|  |                     || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { | ||||||
|  |                 ++attributeCount; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ((access & Opcodes.ACC_DEPRECATED) != 0) { | ||||||
|  |             ++attributeCount; | ||||||
|  |         } | ||||||
|  |         if (ClassReader.SIGNATURES && signature != 0) { | ||||||
|  |             ++attributeCount; | ||||||
|  |         } | ||||||
|  |         if (ClassReader.ANNOTATIONS && anns != null) { | ||||||
|  |             ++attributeCount; | ||||||
|  |         } | ||||||
|  |         if (ClassReader.ANNOTATIONS && ianns != null) { | ||||||
|  |             ++attributeCount; | ||||||
|  |         } | ||||||
|  |         if (attrs != null) { | ||||||
|  |             attributeCount += attrs.getCount(); | ||||||
|  |         } | ||||||
|  |         out.putShort(attributeCount); | ||||||
|  |         if (value != 0) { | ||||||
|  |             out.putShort(cw.newUTF8("ConstantValue")); | ||||||
|  |             out.putInt(2).putShort(value); | ||||||
|  |         } | ||||||
|  |         if ((access & Opcodes.ACC_SYNTHETIC) != 0) { | ||||||
|  |             if ((cw.version & 0xFFFF) < Opcodes.V1_5 | ||||||
|  |                     || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { | ||||||
|  |                 out.putShort(cw.newUTF8("Synthetic")).putInt(0); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ((access & Opcodes.ACC_DEPRECATED) != 0) { | ||||||
|  |             out.putShort(cw.newUTF8("Deprecated")).putInt(0); | ||||||
|  |         } | ||||||
|  |         if (ClassReader.SIGNATURES && signature != 0) { | ||||||
|  |             out.putShort(cw.newUTF8("Signature")); | ||||||
|  |             out.putInt(2).putShort(signature); | ||||||
|  |         } | ||||||
|  |         if (ClassReader.ANNOTATIONS && anns != null) { | ||||||
|  |             out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); | ||||||
|  |             anns.put(out); | ||||||
|  |         } | ||||||
|  |         if (ClassReader.ANNOTATIONS && ianns != null) { | ||||||
|  |             out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); | ||||||
|  |             ianns.put(out); | ||||||
|  |         } | ||||||
|  |         if (attrs != null) { | ||||||
|  |             attrs.put(cw, null, 0, -1, -1, out); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1453
									
								
								src/main/asm/org/objectweb/asm/Frame.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1453
									
								
								src/main/asm/org/objectweb/asm/Frame.java
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										170
									
								
								src/main/asm/org/objectweb/asm/Handle.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/main/asm/org/objectweb/asm/Handle.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,170 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A reference to a field or a method. | ||||||
|  |  *  | ||||||
|  |  * @author Remi Forax | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public final class Handle { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The kind of field or method designated by this Handle. Should be | ||||||
|  |      * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, | ||||||
|  |      * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, | ||||||
|  |      * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, | ||||||
|  |      * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or | ||||||
|  |      * {@link Opcodes#H_INVOKEINTERFACE}. | ||||||
|  |      */ | ||||||
|  |     final int tag; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal name of the class that owns the field or method designated | ||||||
|  |      * by this handle. | ||||||
|  |      */ | ||||||
|  |     final String owner; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The name of the field or method designated by this handle. | ||||||
|  |      */ | ||||||
|  |     final String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The descriptor of the field or method designated by this handle. | ||||||
|  |      */ | ||||||
|  |     final String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new field or method handle. | ||||||
|  |      *  | ||||||
|  |      * @param tag | ||||||
|  |      *            the kind of field or method designated by this Handle. Must be | ||||||
|  |      *            {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, | ||||||
|  |      *            {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, | ||||||
|  |      *            {@link Opcodes#H_INVOKEVIRTUAL}, | ||||||
|  |      *            {@link Opcodes#H_INVOKESTATIC}, | ||||||
|  |      *            {@link Opcodes#H_INVOKESPECIAL}, | ||||||
|  |      *            {@link Opcodes#H_NEWINVOKESPECIAL} or | ||||||
|  |      *            {@link Opcodes#H_INVOKEINTERFACE}. | ||||||
|  |      * @param owner | ||||||
|  |      *            the internal name of the class that owns the field or method | ||||||
|  |      *            designated by this handle. | ||||||
|  |      * @param name | ||||||
|  |      *            the name of the field or method designated by this handle. | ||||||
|  |      * @param desc | ||||||
|  |      *            the descriptor of the field or method designated by this | ||||||
|  |      *            handle. | ||||||
|  |      */ | ||||||
|  |     public Handle(int tag, String owner, String name, String desc) { | ||||||
|  |         this.tag = tag; | ||||||
|  |         this.owner = owner; | ||||||
|  |         this.name = name; | ||||||
|  |         this.desc = desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the kind of field or method designated by this handle. | ||||||
|  |      *  | ||||||
|  |      * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, | ||||||
|  |      *         {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, | ||||||
|  |      *         {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, | ||||||
|  |      *         {@link Opcodes#H_INVOKESPECIAL}, | ||||||
|  |      *         {@link Opcodes#H_NEWINVOKESPECIAL} or | ||||||
|  |      *         {@link Opcodes#H_INVOKEINTERFACE}. | ||||||
|  |      */ | ||||||
|  |     public int getTag() { | ||||||
|  |         return tag; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the internal name of the class that owns the field or method | ||||||
|  |      * designated by this handle. | ||||||
|  |      *  | ||||||
|  |      * @return the internal name of the class that owns the field or method | ||||||
|  |      *         designated by this handle. | ||||||
|  |      */ | ||||||
|  |     public String getOwner() { | ||||||
|  |         return owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the name of the field or method designated by this handle. | ||||||
|  |      *  | ||||||
|  |      * @return the name of the field or method designated by this handle. | ||||||
|  |      */ | ||||||
|  |     public String getName() { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor of the field or method designated by this handle. | ||||||
|  |      *  | ||||||
|  |      * @return the descriptor of the field or method designated by this handle. | ||||||
|  |      */ | ||||||
|  |     public String getDesc() { | ||||||
|  |         return desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(Object obj) { | ||||||
|  |         if (obj == this) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (!(obj instanceof Handle)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         Handle h = (Handle) obj; | ||||||
|  |         return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) | ||||||
|  |                 && desc.equals(h.desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the textual representation of this handle. The textual | ||||||
|  |      * representation is: | ||||||
|  |      *  | ||||||
|  |      * <pre> | ||||||
|  |      * owner '.' name desc ' ' '(' tag ')' | ||||||
|  |      * </pre> | ||||||
|  |      *  | ||||||
|  |      * . As this format is unambiguous, it can be parsed if necessary. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return owner + '.' + name + desc + " (" + tag + ')'; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										121
									
								
								src/main/asm/org/objectweb/asm/Handler.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/main/asm/org/objectweb/asm/Handler.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Information about an exception handler block. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | class Handler { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Beginning of the exception handler's scope (inclusive). | ||||||
|  |      */ | ||||||
|  |     Label start; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * End of the exception handler's scope (exclusive). | ||||||
|  |      */ | ||||||
|  |     Label end; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Beginning of the exception handler's code. | ||||||
|  |      */ | ||||||
|  |     Label handler; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Internal name of the type of exceptions handled by this handler, or | ||||||
|  |      * <tt>null</tt> to catch any exceptions. | ||||||
|  |      */ | ||||||
|  |     String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constant pool index of the internal name of the type of exceptions | ||||||
|  |      * handled by this handler, or 0 to catch any exceptions. | ||||||
|  |      */ | ||||||
|  |     int type; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Next exception handler block info. | ||||||
|  |      */ | ||||||
|  |     Handler next; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes the range between start and end from the given exception | ||||||
|  |      * handlers. | ||||||
|  |      *  | ||||||
|  |      * @param h | ||||||
|  |      *            an exception handler list. | ||||||
|  |      * @param start | ||||||
|  |      *            the start of the range to be removed. | ||||||
|  |      * @param end | ||||||
|  |      *            the end of the range to be removed. Maybe null. | ||||||
|  |      * @return the exception handler list with the start-end range removed. | ||||||
|  |      */ | ||||||
|  |     static Handler remove(Handler h, Label start, Label end) { | ||||||
|  |         if (h == null) { | ||||||
|  |             return null; | ||||||
|  |         } else { | ||||||
|  |             h.next = remove(h.next, start, end); | ||||||
|  |         } | ||||||
|  |         int hstart = h.start.position; | ||||||
|  |         int hend = h.end.position; | ||||||
|  |         int s = start.position; | ||||||
|  |         int e = end == null ? Integer.MAX_VALUE : end.position; | ||||||
|  |         // if [hstart,hend[ and [s,e[ intervals intersect... | ||||||
|  |         if (s < hend && e > hstart) { | ||||||
|  |             if (s <= hstart) { | ||||||
|  |                 if (e >= hend) { | ||||||
|  |                     // [hstart,hend[ fully included in [s,e[, h removed | ||||||
|  |                     h = h.next; | ||||||
|  |                 } else { | ||||||
|  |                     // [hstart,hend[ minus [s,e[ = [e,hend[ | ||||||
|  |                     h.start = end; | ||||||
|  |                 } | ||||||
|  |             } else if (e >= hend) { | ||||||
|  |                 // [hstart,hend[ minus [s,e[ = [hstart,s[ | ||||||
|  |                 h.end = start; | ||||||
|  |             } else { | ||||||
|  |                 // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[ | ||||||
|  |                 Handler g = new Handler(); | ||||||
|  |                 g.start = end; | ||||||
|  |                 g.end = h.end; | ||||||
|  |                 g.handler = h.handler; | ||||||
|  |                 g.desc = h.desc; | ||||||
|  |                 g.type = h.type; | ||||||
|  |                 g.next = h.next; | ||||||
|  |                 h.end = start; | ||||||
|  |                 h.next = g; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return h; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										311
									
								
								src/main/asm/org/objectweb/asm/Item.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								src/main/asm/org/objectweb/asm/Item.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,311 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A constant pool item. Constant pool items can be created with the 'newXXX' | ||||||
|  |  * methods in the {@link ClassWriter} class. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | final class Item { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Index of this item in the constant pool. | ||||||
|  |      */ | ||||||
|  |     int index; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Type of this constant pool item. A single class is used to represent all | ||||||
|  |      * constant pool item types, in order to minimize the bytecode size of this | ||||||
|  |      * package. The value of this field is one of {@link ClassWriter#INT}, | ||||||
|  |      * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, | ||||||
|  |      * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8}, | ||||||
|  |      * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, | ||||||
|  |      * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, | ||||||
|  |      * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, | ||||||
|  |      * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. | ||||||
|  |      *  | ||||||
|  |      * MethodHandle constant 9 variations are stored using a range of 9 values | ||||||
|  |      * from {@link ClassWriter#HANDLE_BASE} + 1 to | ||||||
|  |      * {@link ClassWriter#HANDLE_BASE} + 9. | ||||||
|  |      *  | ||||||
|  |      * Special Item types are used for Items that are stored in the ClassWriter | ||||||
|  |      * {@link ClassWriter#typeTable}, instead of the constant pool, in order to | ||||||
|  |      * avoid clashes with normal constant pool items in the ClassWriter constant | ||||||
|  |      * pool's hash table. These special item types are | ||||||
|  |      * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and | ||||||
|  |      * {@link ClassWriter#TYPE_MERGED}. | ||||||
|  |      */ | ||||||
|  |     int type; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Value of this item, for an integer item. | ||||||
|  |      */ | ||||||
|  |     int intVal; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Value of this item, for a long item. | ||||||
|  |      */ | ||||||
|  |     long longVal; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * First part of the value of this item, for items that do not hold a | ||||||
|  |      * primitive value. | ||||||
|  |      */ | ||||||
|  |     String strVal1; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Second part of the value of this item, for items that do not hold a | ||||||
|  |      * primitive value. | ||||||
|  |      */ | ||||||
|  |     String strVal2; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Third part of the value of this item, for items that do not hold a | ||||||
|  |      * primitive value. | ||||||
|  |      */ | ||||||
|  |     String strVal3; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The hash code value of this constant pool item. | ||||||
|  |      */ | ||||||
|  |     int hashCode; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Link to another constant pool item, used for collision lists in the | ||||||
|  |      * constant pool's hash table. | ||||||
|  |      */ | ||||||
|  |     Item next; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs an uninitialized {@link Item}. | ||||||
|  |      */ | ||||||
|  |     Item() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs an uninitialized {@link Item} for constant pool element at | ||||||
|  |      * given position. | ||||||
|  |      *  | ||||||
|  |      * @param index | ||||||
|  |      *            index of the item to be constructed. | ||||||
|  |      */ | ||||||
|  |     Item(final int index) { | ||||||
|  |         this.index = index; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a copy of the given item. | ||||||
|  |      *  | ||||||
|  |      * @param index | ||||||
|  |      *            index of the item to be constructed. | ||||||
|  |      * @param i | ||||||
|  |      *            the item that must be copied into the item to be constructed. | ||||||
|  |      */ | ||||||
|  |     Item(final int index, final Item i) { | ||||||
|  |         this.index = index; | ||||||
|  |         type = i.type; | ||||||
|  |         intVal = i.intVal; | ||||||
|  |         longVal = i.longVal; | ||||||
|  |         strVal1 = i.strVal1; | ||||||
|  |         strVal2 = i.strVal2; | ||||||
|  |         strVal3 = i.strVal3; | ||||||
|  |         hashCode = i.hashCode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets this item to an integer item. | ||||||
|  |      *  | ||||||
|  |      * @param intVal | ||||||
|  |      *            the value of this item. | ||||||
|  |      */ | ||||||
|  |     void set(final int intVal) { | ||||||
|  |         this.type = ClassWriter.INT; | ||||||
|  |         this.intVal = intVal; | ||||||
|  |         this.hashCode = 0x7FFFFFFF & (type + intVal); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets this item to a long item. | ||||||
|  |      *  | ||||||
|  |      * @param longVal | ||||||
|  |      *            the value of this item. | ||||||
|  |      */ | ||||||
|  |     void set(final long longVal) { | ||||||
|  |         this.type = ClassWriter.LONG; | ||||||
|  |         this.longVal = longVal; | ||||||
|  |         this.hashCode = 0x7FFFFFFF & (type + (int) longVal); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets this item to a float item. | ||||||
|  |      *  | ||||||
|  |      * @param floatVal | ||||||
|  |      *            the value of this item. | ||||||
|  |      */ | ||||||
|  |     void set(final float floatVal) { | ||||||
|  |         this.type = ClassWriter.FLOAT; | ||||||
|  |         this.intVal = Float.floatToRawIntBits(floatVal); | ||||||
|  |         this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets this item to a double item. | ||||||
|  |      *  | ||||||
|  |      * @param doubleVal | ||||||
|  |      *            the value of this item. | ||||||
|  |      */ | ||||||
|  |     void set(final double doubleVal) { | ||||||
|  |         this.type = ClassWriter.DOUBLE; | ||||||
|  |         this.longVal = Double.doubleToRawLongBits(doubleVal); | ||||||
|  |         this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets this item to an item that do not hold a primitive value. | ||||||
|  |      *  | ||||||
|  |      * @param type | ||||||
|  |      *            the type of this item. | ||||||
|  |      * @param strVal1 | ||||||
|  |      *            first part of the value of this item. | ||||||
|  |      * @param strVal2 | ||||||
|  |      *            second part of the value of this item. | ||||||
|  |      * @param strVal3 | ||||||
|  |      *            third part of the value of this item. | ||||||
|  |      */ | ||||||
|  |     void set(final int type, final String strVal1, final String strVal2, | ||||||
|  |             final String strVal3) { | ||||||
|  |         this.type = type; | ||||||
|  |         this.strVal1 = strVal1; | ||||||
|  |         this.strVal2 = strVal2; | ||||||
|  |         this.strVal3 = strVal3; | ||||||
|  |         switch (type) { | ||||||
|  |         case ClassWriter.UTF8: | ||||||
|  |         case ClassWriter.STR: | ||||||
|  |         case ClassWriter.CLASS: | ||||||
|  |         case ClassWriter.MTYPE: | ||||||
|  |         case ClassWriter.TYPE_NORMAL: | ||||||
|  |             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); | ||||||
|  |             return; | ||||||
|  |         case ClassWriter.NAME_TYPE: { | ||||||
|  |             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() | ||||||
|  |                     * strVal2.hashCode()); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         // ClassWriter.FIELD: | ||||||
|  |         // ClassWriter.METH: | ||||||
|  |         // ClassWriter.IMETH: | ||||||
|  |         // ClassWriter.HANDLE_BASE + 1..9 | ||||||
|  |         default: | ||||||
|  |             hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() | ||||||
|  |                     * strVal2.hashCode() * strVal3.hashCode()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets the item to an InvokeDynamic item. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            invokedynamic's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            invokedynamic's desc. | ||||||
|  |      * @param bsmIndex | ||||||
|  |      *            zero based index into the class attribute BootrapMethods. | ||||||
|  |      */ | ||||||
|  |     void set(String name, String desc, int bsmIndex) { | ||||||
|  |         this.type = ClassWriter.INDY; | ||||||
|  |         this.longVal = bsmIndex; | ||||||
|  |         this.strVal1 = name; | ||||||
|  |         this.strVal2 = desc; | ||||||
|  |         this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex | ||||||
|  |                 * strVal1.hashCode() * strVal2.hashCode()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets the item to a BootstrapMethod item. | ||||||
|  |      *  | ||||||
|  |      * @param position | ||||||
|  |      *            position in byte in the class attribute BootrapMethods. | ||||||
|  |      * @param hashCode | ||||||
|  |      *            hashcode of the item. This hashcode is processed from the | ||||||
|  |      *            hashcode of the bootstrap method and the hashcode of all | ||||||
|  |      *            bootstrap arguments. | ||||||
|  |      */ | ||||||
|  |     void set(int position, int hashCode) { | ||||||
|  |         this.type = ClassWriter.BSM; | ||||||
|  |         this.intVal = position; | ||||||
|  |         this.hashCode = hashCode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if the given item is equal to this one. <i>This method assumes | ||||||
|  |      * that the two items have the same {@link #type}</i>. | ||||||
|  |      *  | ||||||
|  |      * @param i | ||||||
|  |      *            the item to be compared to this one. Both items must have the | ||||||
|  |      *            same {@link #type}. | ||||||
|  |      * @return <tt>true</tt> if the given item if equal to this one, | ||||||
|  |      *         <tt>false</tt> otherwise. | ||||||
|  |      */ | ||||||
|  |     boolean isEqualTo(final Item i) { | ||||||
|  |         switch (type) { | ||||||
|  |         case ClassWriter.UTF8: | ||||||
|  |         case ClassWriter.STR: | ||||||
|  |         case ClassWriter.CLASS: | ||||||
|  |         case ClassWriter.MTYPE: | ||||||
|  |         case ClassWriter.TYPE_NORMAL: | ||||||
|  |             return i.strVal1.equals(strVal1); | ||||||
|  |         case ClassWriter.TYPE_MERGED: | ||||||
|  |         case ClassWriter.LONG: | ||||||
|  |         case ClassWriter.DOUBLE: | ||||||
|  |             return i.longVal == longVal; | ||||||
|  |         case ClassWriter.INT: | ||||||
|  |         case ClassWriter.FLOAT: | ||||||
|  |             return i.intVal == intVal; | ||||||
|  |         case ClassWriter.TYPE_UNINIT: | ||||||
|  |             return i.intVal == intVal && i.strVal1.equals(strVal1); | ||||||
|  |         case ClassWriter.NAME_TYPE: | ||||||
|  |             return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); | ||||||
|  |         case ClassWriter.INDY: { | ||||||
|  |             return i.longVal == longVal && i.strVal1.equals(strVal1) | ||||||
|  |                     && i.strVal2.equals(strVal2); | ||||||
|  |         } | ||||||
|  |         // case ClassWriter.FIELD: | ||||||
|  |         // case ClassWriter.METH: | ||||||
|  |         // case ClassWriter.IMETH: | ||||||
|  |         // case ClassWriter.HANDLE_BASE + 1..9 | ||||||
|  |         default: | ||||||
|  |             return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) | ||||||
|  |                     && i.strVal3.equals(strVal3); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										560
									
								
								src/main/asm/org/objectweb/asm/Label.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										560
									
								
								src/main/asm/org/objectweb/asm/Label.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,560 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A label represents a position in the bytecode of a method. Labels are used | ||||||
|  |  * for jump, goto, and switch instructions, and for try catch blocks. A label | ||||||
|  |  * designates the <i>instruction</i> that is just after. Note however that there | ||||||
|  |  * can be other elements between a label and the instruction it designates (such | ||||||
|  |  * as other labels, stack map frames, line numbers, etc.). | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class Label { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this label is only used for debug attributes. Such a label | ||||||
|  |      * is not the start of a basic block, the target of a jump instruction, or | ||||||
|  |      * an exception handler. It can be safely ignored in control flow graph | ||||||
|  |      * analysis algorithms (for optimization purposes). | ||||||
|  |      */ | ||||||
|  |     static final int DEBUG = 1; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if the position of this label is known. | ||||||
|  |      */ | ||||||
|  |     static final int RESOLVED = 2; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this label has been updated, after instruction resizing. | ||||||
|  |      */ | ||||||
|  |     static final int RESIZED = 4; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this basic block has been pushed in the basic block stack. | ||||||
|  |      * See {@link MethodWriter#visitMaxs visitMaxs}. | ||||||
|  |      */ | ||||||
|  |     static final int PUSHED = 8; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this label is the target of a jump instruction, or the start | ||||||
|  |      * of an exception handler. | ||||||
|  |      */ | ||||||
|  |     static final int TARGET = 16; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if a stack map frame must be stored for this label. | ||||||
|  |      */ | ||||||
|  |     static final int STORE = 32; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this label corresponds to a reachable basic block. | ||||||
|  |      */ | ||||||
|  |     static final int REACHABLE = 64; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this basic block ends with a JSR instruction. | ||||||
|  |      */ | ||||||
|  |     static final int JSR = 128; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this basic block ends with a RET instruction. | ||||||
|  |      */ | ||||||
|  |     static final int RET = 256; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this basic block is the start of a subroutine. | ||||||
|  |      */ | ||||||
|  |     static final int SUBROUTINE = 512; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this subroutine basic block has been visited by a | ||||||
|  |      * visitSubroutine(null, ...) call. | ||||||
|  |      */ | ||||||
|  |     static final int VISITED = 1024; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if this subroutine basic block has been visited by a | ||||||
|  |      * visitSubroutine(!null, ...) call. | ||||||
|  |      */ | ||||||
|  |     static final int VISITED2 = 2048; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Field used to associate user information to a label. Warning: this field | ||||||
|  |      * is used by the ASM tree package. In order to use it with the ASM tree | ||||||
|  |      * package you must override the | ||||||
|  |      * {@link org.objectweb.asm.tree.MethodNode#getLabelNode} method. | ||||||
|  |      */ | ||||||
|  |     public Object info; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Flags that indicate the status of this label. | ||||||
|  |      *  | ||||||
|  |      * @see #DEBUG | ||||||
|  |      * @see #RESOLVED | ||||||
|  |      * @see #RESIZED | ||||||
|  |      * @see #PUSHED | ||||||
|  |      * @see #TARGET | ||||||
|  |      * @see #STORE | ||||||
|  |      * @see #REACHABLE | ||||||
|  |      * @see #JSR | ||||||
|  |      * @see #RET | ||||||
|  |      */ | ||||||
|  |     int status; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The line number corresponding to this label, if known. | ||||||
|  |      */ | ||||||
|  |     int line; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The position of this label in the code, if known. | ||||||
|  |      */ | ||||||
|  |     int position; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Number of forward references to this label, times two. | ||||||
|  |      */ | ||||||
|  |     private int referenceCount; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Informations about forward references. Each forward reference is | ||||||
|  |      * described by two consecutive integers in this array: the first one is the | ||||||
|  |      * position of the first byte of the bytecode instruction that contains the | ||||||
|  |      * forward reference, while the second is the position of the first byte of | ||||||
|  |      * the forward reference itself. In fact the sign of the first integer | ||||||
|  |      * indicates if this reference uses 2 or 4 bytes, and its absolute value | ||||||
|  |      * gives the position of the bytecode instruction. This array is also used | ||||||
|  |      * as a bitset to store the subroutines to which a basic block belongs. This | ||||||
|  |      * information is needed in {@linked MethodWriter#visitMaxs}, after all | ||||||
|  |      * forward references have been resolved. Hence the same array can be used | ||||||
|  |      * for both purposes without problems. | ||||||
|  |      */ | ||||||
|  |     private int[] srcAndRefPositions; | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |      * Fields for the control flow and data flow graph analysis algorithms (used | ||||||
|  |      * to compute the maximum stack size or the stack map frames). A control | ||||||
|  |      * flow graph contains one node per "basic block", and one edge per "jump" | ||||||
|  |      * from one basic block to another. Each node (i.e., each basic block) is | ||||||
|  |      * represented by the Label object that corresponds to the first instruction | ||||||
|  |      * of this basic block. Each node also stores the list of its successors in | ||||||
|  |      * the graph, as a linked list of Edge objects. | ||||||
|  |      *  | ||||||
|  |      * The control flow analysis algorithms used to compute the maximum stack | ||||||
|  |      * size or the stack map frames are similar and use two steps. The first | ||||||
|  |      * step, during the visit of each instruction, builds information about the | ||||||
|  |      * state of the local variables and the operand stack at the end of each | ||||||
|  |      * basic block, called the "output frame", <i>relatively</i> to the frame | ||||||
|  |      * state at the beginning of the basic block, which is called the "input | ||||||
|  |      * frame", and which is <i>unknown</i> during this step. The second step, in | ||||||
|  |      * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes | ||||||
|  |      * information about the input frame of each basic block, from the input | ||||||
|  |      * state of the first basic block (known from the method signature), and by | ||||||
|  |      * the using the previously computed relative output frames. | ||||||
|  |      *  | ||||||
|  |      * The algorithm used to compute the maximum stack size only computes the | ||||||
|  |      * relative output and absolute input stack heights, while the algorithm | ||||||
|  |      * used to compute stack map frames computes relative output frames and | ||||||
|  |      * absolute input frames. | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Start of the output stack relatively to the input stack. The exact | ||||||
|  |      * semantics of this field depends on the algorithm that is used. | ||||||
|  |      *  | ||||||
|  |      * When only the maximum stack size is computed, this field is the number of | ||||||
|  |      * elements in the input stack. | ||||||
|  |      *  | ||||||
|  |      * When the stack map frames are completely computed, this field is the | ||||||
|  |      * offset of the first output stack element relatively to the top of the | ||||||
|  |      * input stack. This offset is always negative or null. A null offset means | ||||||
|  |      * that the output stack must be appended to the input stack. A -n offset | ||||||
|  |      * means that the first n output stack elements must replace the top n input | ||||||
|  |      * stack elements, and that the other elements must be appended to the input | ||||||
|  |      * stack. | ||||||
|  |      */ | ||||||
|  |     int inputStackTop; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Maximum height reached by the output stack, relatively to the top of the | ||||||
|  |      * input stack. This maximum is always positive or null. | ||||||
|  |      */ | ||||||
|  |     int outputStackMax; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Information about the input and output stack map frames of this basic | ||||||
|  |      * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} | ||||||
|  |      * option is used. | ||||||
|  |      */ | ||||||
|  |     Frame frame; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The successor of this label, in the order they are visited. This linked | ||||||
|  |      * list does not include labels used for debug info only. If | ||||||
|  |      * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it | ||||||
|  |      * does not contain successive labels that denote the same bytecode position | ||||||
|  |      * (in this case only the first label appears in this list). | ||||||
|  |      */ | ||||||
|  |     Label successor; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The successors of this node in the control flow graph. These successors | ||||||
|  |      * are stored in a linked list of {@link Edge Edge} objects, linked to each | ||||||
|  |      * other by their {@link Edge#next} field. | ||||||
|  |      */ | ||||||
|  |     Edge successors; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The next basic block in the basic block stack. This stack is used in the | ||||||
|  |      * main loop of the fix point algorithm used in the second step of the | ||||||
|  |      * control flow analysis algorithms. It is also used in | ||||||
|  |      * {@link #visitSubroutine} to avoid using a recursive method. | ||||||
|  |      *  | ||||||
|  |      * @see MethodWriter#visitMaxs | ||||||
|  |      */ | ||||||
|  |     Label next; | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Constructor | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new label. | ||||||
|  |      */ | ||||||
|  |     public Label() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Methods to compute offsets and to manage forward references | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the offset corresponding to this label. This offset is computed | ||||||
|  |      * from the start of the method's bytecode. <i>This method is intended for | ||||||
|  |      * {@link Attribute} sub classes, and is normally not needed by class | ||||||
|  |      * generators or adapters.</i> | ||||||
|  |      *  | ||||||
|  |      * @return the offset corresponding to this label. | ||||||
|  |      * @throws IllegalStateException | ||||||
|  |      *             if this label is not resolved yet. | ||||||
|  |      */ | ||||||
|  |     public int getOffset() { | ||||||
|  |         if ((status & RESOLVED) == 0) { | ||||||
|  |             throw new IllegalStateException( | ||||||
|  |                     "Label offset position has not been resolved yet"); | ||||||
|  |         } | ||||||
|  |         return position; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Puts a reference to this label in the bytecode of a method. If the | ||||||
|  |      * position of the label is known, the offset is computed and written | ||||||
|  |      * directly. Otherwise, a null offset is written and a new forward reference | ||||||
|  |      * is declared for this label. | ||||||
|  |      *  | ||||||
|  |      * @param owner | ||||||
|  |      *            the code writer that calls this method. | ||||||
|  |      * @param out | ||||||
|  |      *            the bytecode of the method. | ||||||
|  |      * @param source | ||||||
|  |      *            the position of first byte of the bytecode instruction that | ||||||
|  |      *            contains this label. | ||||||
|  |      * @param wideOffset | ||||||
|  |      *            <tt>true</tt> if the reference must be stored in 4 bytes, or | ||||||
|  |      *            <tt>false</tt> if it must be stored with 2 bytes. | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if this label has not been created by the given code writer. | ||||||
|  |      */ | ||||||
|  |     void put(final MethodWriter owner, final ByteVector out, final int source, | ||||||
|  |             final boolean wideOffset) { | ||||||
|  |         if ((status & RESOLVED) == 0) { | ||||||
|  |             if (wideOffset) { | ||||||
|  |                 addReference(-1 - source, out.length); | ||||||
|  |                 out.putInt(-1); | ||||||
|  |             } else { | ||||||
|  |                 addReference(source, out.length); | ||||||
|  |                 out.putShort(-1); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if (wideOffset) { | ||||||
|  |                 out.putInt(position - source); | ||||||
|  |             } else { | ||||||
|  |                 out.putShort(position - source); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds a forward reference to this label. This method must be called only | ||||||
|  |      * for a true forward reference, i.e. only if this label is not resolved | ||||||
|  |      * yet. For backward references, the offset of the reference can be, and | ||||||
|  |      * must be, computed and stored directly. | ||||||
|  |      *  | ||||||
|  |      * @param sourcePosition | ||||||
|  |      *            the position of the referencing instruction. This position | ||||||
|  |      *            will be used to compute the offset of this forward reference. | ||||||
|  |      * @param referencePosition | ||||||
|  |      *            the position where the offset for this forward reference must | ||||||
|  |      *            be stored. | ||||||
|  |      */ | ||||||
|  |     private void addReference(final int sourcePosition, | ||||||
|  |             final int referencePosition) { | ||||||
|  |         if (srcAndRefPositions == null) { | ||||||
|  |             srcAndRefPositions = new int[6]; | ||||||
|  |         } | ||||||
|  |         if (referenceCount >= srcAndRefPositions.length) { | ||||||
|  |             int[] a = new int[srcAndRefPositions.length + 6]; | ||||||
|  |             System.arraycopy(srcAndRefPositions, 0, a, 0, | ||||||
|  |                     srcAndRefPositions.length); | ||||||
|  |             srcAndRefPositions = a; | ||||||
|  |         } | ||||||
|  |         srcAndRefPositions[referenceCount++] = sourcePosition; | ||||||
|  |         srcAndRefPositions[referenceCount++] = referencePosition; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Resolves all forward references to this label. This method must be called | ||||||
|  |      * when this label is added to the bytecode of the method, i.e. when its | ||||||
|  |      * position becomes known. This method fills in the blanks that where left | ||||||
|  |      * in the bytecode by each forward reference previously added to this label. | ||||||
|  |      *  | ||||||
|  |      * @param owner | ||||||
|  |      *            the code writer that calls this method. | ||||||
|  |      * @param position | ||||||
|  |      *            the position of this label in the bytecode. | ||||||
|  |      * @param data | ||||||
|  |      *            the bytecode of the method. | ||||||
|  |      * @return <tt>true</tt> if a blank that was left for this label was to | ||||||
|  |      *         small to store the offset. In such a case the corresponding jump | ||||||
|  |      *         instruction is replaced with a pseudo instruction (using unused | ||||||
|  |      *         opcodes) using an unsigned two bytes offset. These pseudo | ||||||
|  |      *         instructions will need to be replaced with true instructions with | ||||||
|  |      *         wider offsets (4 bytes instead of 2). This is done in | ||||||
|  |      *         {@link MethodWriter#resizeInstructions}. | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if this label has already been resolved, or if it has not | ||||||
|  |      *             been created by the given code writer. | ||||||
|  |      */ | ||||||
|  |     boolean resolve(final MethodWriter owner, final int position, | ||||||
|  |             final byte[] data) { | ||||||
|  |         boolean needUpdate = false; | ||||||
|  |         this.status |= RESOLVED; | ||||||
|  |         this.position = position; | ||||||
|  |         int i = 0; | ||||||
|  |         while (i < referenceCount) { | ||||||
|  |             int source = srcAndRefPositions[i++]; | ||||||
|  |             int reference = srcAndRefPositions[i++]; | ||||||
|  |             int offset; | ||||||
|  |             if (source >= 0) { | ||||||
|  |                 offset = position - source; | ||||||
|  |                 if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { | ||||||
|  |                     /* | ||||||
|  |                      * changes the opcode of the jump instruction, in order to | ||||||
|  |                      * be able to find it later (see resizeInstructions in | ||||||
|  |                      * MethodWriter). These temporary opcodes are similar to | ||||||
|  |                      * jump instruction opcodes, except that the 2 bytes offset | ||||||
|  |                      * is unsigned (and can therefore represent values from 0 to | ||||||
|  |                      * 65535, which is sufficient since the size of a method is | ||||||
|  |                      * limited to 65535 bytes). | ||||||
|  |                      */ | ||||||
|  |                     int opcode = data[reference - 1] & 0xFF; | ||||||
|  |                     if (opcode <= Opcodes.JSR) { | ||||||
|  |                         // changes IFEQ ... JSR to opcodes 202 to 217 | ||||||
|  |                         data[reference - 1] = (byte) (opcode + 49); | ||||||
|  |                     } else { | ||||||
|  |                         // changes IFNULL and IFNONNULL to opcodes 218 and 219 | ||||||
|  |                         data[reference - 1] = (byte) (opcode + 20); | ||||||
|  |                     } | ||||||
|  |                     needUpdate = true; | ||||||
|  |                 } | ||||||
|  |                 data[reference++] = (byte) (offset >>> 8); | ||||||
|  |                 data[reference] = (byte) offset; | ||||||
|  |             } else { | ||||||
|  |                 offset = position + source + 1; | ||||||
|  |                 data[reference++] = (byte) (offset >>> 24); | ||||||
|  |                 data[reference++] = (byte) (offset >>> 16); | ||||||
|  |                 data[reference++] = (byte) (offset >>> 8); | ||||||
|  |                 data[reference] = (byte) offset; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return needUpdate; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the first label of the series to which this label belongs. For an | ||||||
|  |      * isolated label or for the first label in a series of successive labels, | ||||||
|  |      * this method returns the label itself. For other labels it returns the | ||||||
|  |      * first label of the series. | ||||||
|  |      *  | ||||||
|  |      * @return the first label of the series to which this label belongs. | ||||||
|  |      */ | ||||||
|  |     Label getFirst() { | ||||||
|  |         return !ClassReader.FRAMES || frame == null ? this : frame.owner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Methods related to subroutines | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns true is this basic block belongs to the given subroutine. | ||||||
|  |      *  | ||||||
|  |      * @param id | ||||||
|  |      *            a subroutine id. | ||||||
|  |      * @return true is this basic block belongs to the given subroutine. | ||||||
|  |      */ | ||||||
|  |     boolean inSubroutine(final long id) { | ||||||
|  |         if ((status & Label.VISITED) != 0) { | ||||||
|  |             return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns true if this basic block and the given one belong to a common | ||||||
|  |      * subroutine. | ||||||
|  |      *  | ||||||
|  |      * @param block | ||||||
|  |      *            another basic block. | ||||||
|  |      * @return true if this basic block and the given one belong to a common | ||||||
|  |      *         subroutine. | ||||||
|  |      */ | ||||||
|  |     boolean inSameSubroutine(final Label block) { | ||||||
|  |         if ((status & VISITED) == 0 || (block.status & VISITED) == 0) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         for (int i = 0; i < srcAndRefPositions.length; ++i) { | ||||||
|  |             if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Marks this basic block as belonging to the given subroutine. | ||||||
|  |      *  | ||||||
|  |      * @param id | ||||||
|  |      *            a subroutine id. | ||||||
|  |      * @param nbSubroutines | ||||||
|  |      *            the total number of subroutines in the method. | ||||||
|  |      */ | ||||||
|  |     void addToSubroutine(final long id, final int nbSubroutines) { | ||||||
|  |         if ((status & VISITED) == 0) { | ||||||
|  |             status |= VISITED; | ||||||
|  |             srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1]; | ||||||
|  |         } | ||||||
|  |         srcAndRefPositions[(int) (id >>> 32)] |= (int) id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Finds the basic blocks that belong to a given subroutine, and marks these | ||||||
|  |      * blocks as belonging to this subroutine. This method follows the control | ||||||
|  |      * flow graph to find all the blocks that are reachable from the current | ||||||
|  |      * block WITHOUT following any JSR target. | ||||||
|  |      *  | ||||||
|  |      * @param JSR | ||||||
|  |      *            a JSR block that jumps to this subroutine. If this JSR is not | ||||||
|  |      *            null it is added to the successor of the RET blocks found in | ||||||
|  |      *            the subroutine. | ||||||
|  |      * @param id | ||||||
|  |      *            the id of this subroutine. | ||||||
|  |      * @param nbSubroutines | ||||||
|  |      *            the total number of subroutines in the method. | ||||||
|  |      */ | ||||||
|  |     void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { | ||||||
|  |         // user managed stack of labels, to avoid using a recursive method | ||||||
|  |         // (recursivity can lead to stack overflow with very large methods) | ||||||
|  |         Label stack = this; | ||||||
|  |         while (stack != null) { | ||||||
|  |             // removes a label l from the stack | ||||||
|  |             Label l = stack; | ||||||
|  |             stack = l.next; | ||||||
|  |             l.next = null; | ||||||
|  | 
 | ||||||
|  |             if (JSR != null) { | ||||||
|  |                 if ((l.status & VISITED2) != 0) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 l.status |= VISITED2; | ||||||
|  |                 // adds JSR to the successors of l, if it is a RET block | ||||||
|  |                 if ((l.status & RET) != 0) { | ||||||
|  |                     if (!l.inSameSubroutine(JSR)) { | ||||||
|  |                         Edge e = new Edge(); | ||||||
|  |                         e.info = l.inputStackTop; | ||||||
|  |                         e.successor = JSR.successors.successor; | ||||||
|  |                         e.next = l.successors; | ||||||
|  |                         l.successors = e; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 // if the l block already belongs to subroutine 'id', continue | ||||||
|  |                 if (l.inSubroutine(id)) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 // marks the l block as belonging to subroutine 'id' | ||||||
|  |                 l.addToSubroutine(id, nbSubroutines); | ||||||
|  |             } | ||||||
|  |             // pushes each successor of l on the stack, except JSR targets | ||||||
|  |             Edge e = l.successors; | ||||||
|  |             while (e != null) { | ||||||
|  |                 // if the l block is a JSR block, then 'l.successors.next' leads | ||||||
|  |                 // to the JSR target (see {@link #visitJumpInsn}) and must | ||||||
|  |                 // therefore not be followed | ||||||
|  |                 if ((l.status & Label.JSR) == 0 || e != l.successors.next) { | ||||||
|  |                     // pushes e.successor on the stack if it not already added | ||||||
|  |                     if (e.successor.next == null) { | ||||||
|  |                         e.successor.next = stack; | ||||||
|  |                         stack = e.successor; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 e = e.next; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Overriden Object methods | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a string representation of this label. | ||||||
|  |      *  | ||||||
|  |      * @return a string representation of this label. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "L" + System.identityHashCode(this); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										662
									
								
								src/main/asm/org/objectweb/asm/MethodVisitor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										662
									
								
								src/main/asm/org/objectweb/asm/MethodVisitor.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,662 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A visitor to visit a Java method. The methods of this class must be called in | ||||||
|  |  * the following order: [ <tt>visitAnnotationDefault</tt> ] ( | ||||||
|  |  * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> | | ||||||
|  |  * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> | | ||||||
|  |  * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | | ||||||
|  |  * <tt>visitTryCatchBlock</tt> | <tt>visitLocalVariable</tt> | | ||||||
|  |  * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In | ||||||
|  |  * addition, the <tt>visit</tt><i>X</i>Insn</tt> and <tt>visitLabel</tt> methods | ||||||
|  |  * must be called in the sequential order of the bytecode instructions of the | ||||||
|  |  * visited code, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the | ||||||
|  |  * labels passed as arguments have been visited, and the | ||||||
|  |  * <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt> methods must be | ||||||
|  |  * called <i>after</i> the labels passed as arguments have been visited. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public abstract class MethodVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The ASM API version implemented by this visitor. The value of this field | ||||||
|  |      * must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     protected final int api; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The method visitor to which this visitor must delegate method calls. May | ||||||
|  |      * be null. | ||||||
|  |      */ | ||||||
|  |     protected MethodVisitor mv; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link MethodVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public MethodVisitor(final int api) { | ||||||
|  |         this(api, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link MethodVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor to which this visitor must delegate method | ||||||
|  |      *            calls. May be null. | ||||||
|  |      */ | ||||||
|  |     public MethodVisitor(final int api, final MethodVisitor mv) { | ||||||
|  |         if (api != Opcodes.ASM4) { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         this.api = api; | ||||||
|  |         this.mv = mv; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  |     // Annotations and non standard attributes | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the default value of this annotation interface method. | ||||||
|  |      *  | ||||||
|  |      * @return a visitor to the visit the actual default value of this | ||||||
|  |      *         annotation interface method, or <tt>null</tt> if this visitor is | ||||||
|  |      *         not interested in visiting this default value. The 'name' | ||||||
|  |      *         parameters passed to the methods of this annotation visitor are | ||||||
|  |      *         ignored. Moreover, exacly one visit method must be called on this | ||||||
|  |      *         annotation visitor, followed by visitEnd. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitAnnotationDefault() { | ||||||
|  |         if (mv != null) { | ||||||
|  |             return mv.visitAnnotationDefault(); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an annotation of this method. | ||||||
|  |      *  | ||||||
|  |      * @param desc | ||||||
|  |      *            the class descriptor of the annotation class. | ||||||
|  |      * @param visible | ||||||
|  |      *            <tt>true</tt> if the annotation is visible at runtime. | ||||||
|  |      * @return a visitor to visit the annotation values, or <tt>null</tt> if | ||||||
|  |      *         this visitor is not interested in visiting this annotation. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             return mv.visitAnnotation(desc, visible); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an annotation of a parameter this method. | ||||||
|  |      *  | ||||||
|  |      * @param parameter | ||||||
|  |      *            the parameter index. | ||||||
|  |      * @param desc | ||||||
|  |      *            the class descriptor of the annotation class. | ||||||
|  |      * @param visible | ||||||
|  |      *            <tt>true</tt> if the annotation is visible at runtime. | ||||||
|  |      * @return a visitor to visit the annotation values, or <tt>null</tt> if | ||||||
|  |      *         this visitor is not interested in visiting this annotation. | ||||||
|  |      */ | ||||||
|  |     public AnnotationVisitor visitParameterAnnotation(int parameter, | ||||||
|  |             String desc, boolean visible) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             return mv.visitParameterAnnotation(parameter, desc, visible); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a non standard attribute of this method. | ||||||
|  |      *  | ||||||
|  |      * @param attr | ||||||
|  |      *            an attribute. | ||||||
|  |      */ | ||||||
|  |     public void visitAttribute(Attribute attr) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitAttribute(attr); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Starts the visit of the method's code, if any (i.e. non abstract method). | ||||||
|  |      */ | ||||||
|  |     public void visitCode() { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitCode(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the current state of the local variables and operand stack | ||||||
|  |      * elements. This method must(*) be called <i>just before</i> any | ||||||
|  |      * instruction <b>i</b> that follows an unconditional branch instruction | ||||||
|  |      * such as GOTO or THROW, that is the target of a jump instruction, or that | ||||||
|  |      * starts an exception handler block. The visited types must describe the | ||||||
|  |      * values of the local variables and of the operand stack elements <i>just | ||||||
|  |      * before</i> <b>i</b> is executed.<br> | ||||||
|  |      * <br> | ||||||
|  |      * (*) this is mandatory only for classes whose version is greater than or | ||||||
|  |      * equal to {@link Opcodes#V1_6 V1_6}. <br> | ||||||
|  |      * <br> | ||||||
|  |      * The frames of a method must be given either in expanded form, or in | ||||||
|  |      * compressed form (all frames must use the same format, i.e. you must not | ||||||
|  |      * mix expanded and compressed frames within a single method): | ||||||
|  |      * <ul> | ||||||
|  |      * <li>In expanded form, all frames must have the F_NEW type.</li> | ||||||
|  |      * <li>In compressed form, frames are basically "deltas" from the state of | ||||||
|  |      * the previous frame: | ||||||
|  |      * <ul> | ||||||
|  |      * <li>{@link Opcodes#F_SAME} representing frame with exactly the same | ||||||
|  |      * locals as the previous frame and with the empty stack.</li> | ||||||
|  |      * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same | ||||||
|  |      * locals as the previous frame and with single value on the stack ( | ||||||
|  |      * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the | ||||||
|  |      * type of the stack item).</li> | ||||||
|  |      * <li>{@link Opcodes#F_APPEND} representing frame with current locals are | ||||||
|  |      * the same as the locals in the previous frame, except that additional | ||||||
|  |      * locals are defined (<code>nLocal</code> is 1, 2 or 3 and | ||||||
|  |      * <code>local</code> elements contains values representing added types).</li> | ||||||
|  |      * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the | ||||||
|  |      * same as the locals in the previous frame, except that the last 1-3 locals | ||||||
|  |      * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li> | ||||||
|  |      * <li>{@link Opcodes#F_FULL} representing complete frame data.</li></li> | ||||||
|  |      * </ul> | ||||||
|  |      * </ul> <br> | ||||||
|  |      * In both cases the first frame, corresponding to the method's parameters | ||||||
|  |      * and access flags, is implicit and must not be visited. Also, it is | ||||||
|  |      * illegal to visit two or more frames for the same code location (i.e., at | ||||||
|  |      * least one instruction must be visited between two calls to visitFrame). | ||||||
|  |      *  | ||||||
|  |      * @param type | ||||||
|  |      *            the type of this stack map frame. Must be | ||||||
|  |      *            {@link Opcodes#F_NEW} for expanded frames, or | ||||||
|  |      *            {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, | ||||||
|  |      *            {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or | ||||||
|  |      *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for | ||||||
|  |      *            compressed frames. | ||||||
|  |      * @param nLocal | ||||||
|  |      *            the number of local variables in the visited frame. | ||||||
|  |      * @param local | ||||||
|  |      *            the local variable types in this frame. This array must not be | ||||||
|  |      *            modified. Primitive types are represented by | ||||||
|  |      *            {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, | ||||||
|  |      *            {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, | ||||||
|  |      *            {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or | ||||||
|  |      *            {@link Opcodes#UNINITIALIZED_THIS} (long and double are | ||||||
|  |      *            represented by a single element). Reference types are | ||||||
|  |      *            represented by String objects (representing internal names), | ||||||
|  |      *            and uninitialized types by Label objects (this label | ||||||
|  |      *            designates the NEW instruction that created this uninitialized | ||||||
|  |      *            value). | ||||||
|  |      * @param nStack | ||||||
|  |      *            the number of operand stack elements in the visited frame. | ||||||
|  |      * @param stack | ||||||
|  |      *            the operand stack types in this frame. This array must not be | ||||||
|  |      *            modified. Its content has the same format as the "local" | ||||||
|  |      *            array. | ||||||
|  |      * @throws IllegalStateException | ||||||
|  |      *             if a frame is visited just after another one, without any | ||||||
|  |      *             instruction between the two (unless this frame is a | ||||||
|  |      *             Opcodes#F_SAME frame, in which case it is silently ignored). | ||||||
|  |      */ | ||||||
|  |     public void visitFrame(int type, int nLocal, Object[] local, int nStack, | ||||||
|  |             Object[] stack) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitFrame(type, nLocal, local, nStack, stack); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  |     // Normal instructions | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a zero operand instruction. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the instruction to be visited. This opcode is | ||||||
|  |      *            either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, | ||||||
|  |      *            ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, | ||||||
|  |      *            FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, | ||||||
|  |      *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, | ||||||
|  |      *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, | ||||||
|  |      *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, | ||||||
|  |      *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, | ||||||
|  |      *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, | ||||||
|  |      *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, | ||||||
|  |      *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, | ||||||
|  |      *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, | ||||||
|  |      *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, | ||||||
|  |      *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, | ||||||
|  |      *            or MONITOREXIT. | ||||||
|  |      */ | ||||||
|  |     public void visitInsn(int opcode) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitInsn(opcode); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an instruction with a single int operand. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the instruction to be visited. This opcode is | ||||||
|  |      *            either BIPUSH, SIPUSH or NEWARRAY. | ||||||
|  |      * @param operand | ||||||
|  |      *            the operand of the instruction to be visited.<br> | ||||||
|  |      *            When opcode is BIPUSH, operand value should be between | ||||||
|  |      *            Byte.MIN_VALUE and Byte.MAX_VALUE.<br> | ||||||
|  |      *            When opcode is SIPUSH, operand value should be between | ||||||
|  |      *            Short.MIN_VALUE and Short.MAX_VALUE.<br> | ||||||
|  |      *            When opcode is NEWARRAY, operand value should be one of | ||||||
|  |      *            {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, | ||||||
|  |      *            {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, | ||||||
|  |      *            {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, | ||||||
|  |      *            {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. | ||||||
|  |      */ | ||||||
|  |     public void visitIntInsn(int opcode, int operand) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitIntInsn(opcode, operand); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a local variable instruction. A local variable instruction is an | ||||||
|  |      * instruction that loads or stores the value of a local variable. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the local variable instruction to be visited. | ||||||
|  |      *            This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, | ||||||
|  |      *            ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. | ||||||
|  |      * @param var | ||||||
|  |      *            the operand of the instruction to be visited. This operand is | ||||||
|  |      *            the index of a local variable. | ||||||
|  |      */ | ||||||
|  |     public void visitVarInsn(int opcode, int var) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitVarInsn(opcode, var); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a type instruction. A type instruction is an instruction that | ||||||
|  |      * takes the internal name of a class as parameter. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the type instruction to be visited. This opcode | ||||||
|  |      *            is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. | ||||||
|  |      * @param type | ||||||
|  |      *            the operand of the instruction to be visited. This operand | ||||||
|  |      *            must be the internal name of an object or array class (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). | ||||||
|  |      */ | ||||||
|  |     public void visitTypeInsn(int opcode, String type) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTypeInsn(opcode, type); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a field instruction. A field instruction is an instruction that | ||||||
|  |      * loads or stores the value of a field of an object. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the type instruction to be visited. This opcode | ||||||
|  |      *            is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. | ||||||
|  |      * @param owner | ||||||
|  |      *            the internal name of the field's owner class (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). | ||||||
|  |      * @param name | ||||||
|  |      *            the field's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the field's descriptor (see {@link Type Type}). | ||||||
|  |      */ | ||||||
|  |     public void visitFieldInsn(int opcode, String owner, String name, | ||||||
|  |             String desc) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitFieldInsn(opcode, owner, name, desc); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a method instruction. A method instruction is an instruction that | ||||||
|  |      * invokes a method. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the type instruction to be visited. This opcode | ||||||
|  |      *            is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or | ||||||
|  |      *            INVOKEINTERFACE. | ||||||
|  |      * @param owner | ||||||
|  |      *            the internal name of the method's owner class (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      */ | ||||||
|  |     public void visitMethodInsn(int opcode, String owner, String name, | ||||||
|  |             String desc) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMethodInsn(opcode, owner, name, desc); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an invokedynamic instruction. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      * @param bsm | ||||||
|  |      *            the bootstrap method. | ||||||
|  |      * @param bsmArgs | ||||||
|  |      *            the bootstrap method constant arguments. Each argument must be | ||||||
|  |      *            an {@link Integer}, {@link Float}, {@link Long}, | ||||||
|  |      *            {@link Double}, {@link String}, {@link Type} or {@link Handle} | ||||||
|  |      *            value. This method is allowed to modify the content of the | ||||||
|  |      *            array so a caller should expect that this array may change. | ||||||
|  |      */ | ||||||
|  |     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, | ||||||
|  |             Object... bsmArgs) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a jump instruction. A jump instruction is an instruction that may | ||||||
|  |      * jump to another instruction. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the type instruction to be visited. This opcode | ||||||
|  |      *            is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, | ||||||
|  |      *            IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, | ||||||
|  |      *            IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. | ||||||
|  |      * @param label | ||||||
|  |      *            the operand of the instruction to be visited. This operand is | ||||||
|  |      *            a label that designates the instruction to which the jump | ||||||
|  |      *            instruction may jump. | ||||||
|  |      */ | ||||||
|  |     public void visitJumpInsn(int opcode, Label label) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitJumpInsn(opcode, label); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a label. A label designates the instruction that will be visited | ||||||
|  |      * just after it. | ||||||
|  |      *  | ||||||
|  |      * @param label | ||||||
|  |      *            a {@link Label Label} object. | ||||||
|  |      */ | ||||||
|  |     public void visitLabel(Label label) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLabel(label); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  |     // Special instructions | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a LDC instruction. Note that new constant types may be added in | ||||||
|  |      * future versions of the Java Virtual Machine. To easily detect new | ||||||
|  |      * constant types, implementations of this method should check for | ||||||
|  |      * unexpected constant types, like this: | ||||||
|  |      *  | ||||||
|  |      * <pre> | ||||||
|  |      * if (cst instanceof Integer) { | ||||||
|  |      *     // ... | ||||||
|  |      * } else if (cst instanceof Float) { | ||||||
|  |      *     // ... | ||||||
|  |      * } else if (cst instanceof Long) { | ||||||
|  |      *     // ... | ||||||
|  |      * } else if (cst instanceof Double) { | ||||||
|  |      *     // ... | ||||||
|  |      * } else if (cst instanceof String) { | ||||||
|  |      *     // ... | ||||||
|  |      * } else if (cst instanceof Type) { | ||||||
|  |      *     int sort = ((Type) cst).getSort(); | ||||||
|  |      *     if (sort == Type.OBJECT) { | ||||||
|  |      *         // ... | ||||||
|  |      *     } else if (sort == Type.ARRAY) { | ||||||
|  |      *         // ... | ||||||
|  |      *     } else if (sort == Type.METHOD) { | ||||||
|  |      *         // ... | ||||||
|  |      *     } else { | ||||||
|  |      *         // throw an exception | ||||||
|  |      *     } | ||||||
|  |      * } else if (cst instanceof Handle) { | ||||||
|  |      *     // ... | ||||||
|  |      * } else { | ||||||
|  |      *     // throw an exception | ||||||
|  |      * } | ||||||
|  |      * </pre> | ||||||
|  |      *  | ||||||
|  |      * @param cst | ||||||
|  |      *            the constant to be loaded on the stack. This parameter must be | ||||||
|  |      *            a non null {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  |      *            {@link Double}, a {@link String}, a {@link Type} of OBJECT or | ||||||
|  |      *            ARRAY sort for <tt>.class</tt> constants, for classes whose | ||||||
|  |      *            version is 49.0, a {@link Type} of METHOD sort or a | ||||||
|  |      *            {@link Handle} for MethodType and MethodHandle constants, for | ||||||
|  |      *            classes whose version is 51.0. | ||||||
|  |      */ | ||||||
|  |     public void visitLdcInsn(Object cst) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLdcInsn(cst); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an IINC instruction. | ||||||
|  |      *  | ||||||
|  |      * @param var | ||||||
|  |      *            index of the local variable to be incremented. | ||||||
|  |      * @param increment | ||||||
|  |      *            amount to increment the local variable by. | ||||||
|  |      */ | ||||||
|  |     public void visitIincInsn(int var, int increment) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitIincInsn(var, increment); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a TABLESWITCH instruction. | ||||||
|  |      *  | ||||||
|  |      * @param min | ||||||
|  |      *            the minimum key value. | ||||||
|  |      * @param max | ||||||
|  |      *            the maximum key value. | ||||||
|  |      * @param dflt | ||||||
|  |      *            beginning of the default handler block. | ||||||
|  |      * @param labels | ||||||
|  |      *            beginnings of the handler blocks. <tt>labels[i]</tt> is the | ||||||
|  |      *            beginning of the handler block for the <tt>min + i</tt> key. | ||||||
|  |      */ | ||||||
|  |     public void visitTableSwitchInsn(int min, int max, Label dflt, | ||||||
|  |             Label... labels) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTableSwitchInsn(min, max, dflt, labels); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a LOOKUPSWITCH instruction. | ||||||
|  |      *  | ||||||
|  |      * @param dflt | ||||||
|  |      *            beginning of the default handler block. | ||||||
|  |      * @param keys | ||||||
|  |      *            the values of the keys. | ||||||
|  |      * @param labels | ||||||
|  |      *            beginnings of the handler blocks. <tt>labels[i]</tt> is the | ||||||
|  |      *            beginning of the handler block for the <tt>keys[i]</tt> key. | ||||||
|  |      */ | ||||||
|  |     public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLookupSwitchInsn(dflt, keys, labels); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a MULTIANEWARRAY instruction. | ||||||
|  |      *  | ||||||
|  |      * @param desc | ||||||
|  |      *            an array type descriptor (see {@link Type Type}). | ||||||
|  |      * @param dims | ||||||
|  |      *            number of dimensions of the array to allocate. | ||||||
|  |      */ | ||||||
|  |     public void visitMultiANewArrayInsn(String desc, int dims) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMultiANewArrayInsn(desc, dims); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  |     // Exceptions table entries, debug information, max stack and max locals | ||||||
|  |     // ------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a try catch block. | ||||||
|  |      *  | ||||||
|  |      * @param start | ||||||
|  |      *            beginning of the exception handler's scope (inclusive). | ||||||
|  |      * @param end | ||||||
|  |      *            end of the exception handler's scope (exclusive). | ||||||
|  |      * @param handler | ||||||
|  |      *            beginning of the exception handler's code. | ||||||
|  |      * @param type | ||||||
|  |      *            internal name of the type of exceptions handled by the | ||||||
|  |      *            handler, or <tt>null</tt> to catch any exceptions (for | ||||||
|  |      *            "finally" blocks). | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if one of the labels has already been visited by this visitor | ||||||
|  |      *             (by the {@link #visitLabel visitLabel} method). | ||||||
|  |      */ | ||||||
|  |     public void visitTryCatchBlock(Label start, Label end, Label handler, | ||||||
|  |             String type) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTryCatchBlock(start, end, handler, type); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a local variable declaration. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the name of a local variable. | ||||||
|  |      * @param desc | ||||||
|  |      *            the type descriptor of this local variable. | ||||||
|  |      * @param signature | ||||||
|  |      *            the type signature of this local variable. May be | ||||||
|  |      *            <tt>null</tt> if the local variable type does not use generic | ||||||
|  |      *            types. | ||||||
|  |      * @param start | ||||||
|  |      *            the first instruction corresponding to the scope of this local | ||||||
|  |      *            variable (inclusive). | ||||||
|  |      * @param end | ||||||
|  |      *            the last instruction corresponding to the scope of this local | ||||||
|  |      *            variable (exclusive). | ||||||
|  |      * @param index | ||||||
|  |      *            the local variable's index. | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if one of the labels has not already been visited by this | ||||||
|  |      *             visitor (by the {@link #visitLabel visitLabel} method). | ||||||
|  |      */ | ||||||
|  |     public void visitLocalVariable(String name, String desc, String signature, | ||||||
|  |             Label start, Label end, int index) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLocalVariable(name, desc, signature, start, end, index); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a line number declaration. | ||||||
|  |      *  | ||||||
|  |      * @param line | ||||||
|  |      *            a line number. This number refers to the source file from | ||||||
|  |      *            which the class was compiled. | ||||||
|  |      * @param start | ||||||
|  |      *            the first instruction corresponding to this line number. | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if <tt>start</tt> has not already been visited by this | ||||||
|  |      *             visitor (by the {@link #visitLabel visitLabel} method). | ||||||
|  |      */ | ||||||
|  |     public void visitLineNumber(int line, Label start) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLineNumber(line, start); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the maximum stack size and the maximum number of local variables | ||||||
|  |      * of the method. | ||||||
|  |      *  | ||||||
|  |      * @param maxStack | ||||||
|  |      *            maximum stack size of the method. | ||||||
|  |      * @param maxLocals | ||||||
|  |      *            maximum number of local variables for the method. | ||||||
|  |      */ | ||||||
|  |     public void visitMaxs(int maxStack, int maxLocals) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMaxs(maxStack, maxLocals); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the end of the method. This method, which is the last one to be | ||||||
|  |      * called, is used to inform the visitor that all the annotations and | ||||||
|  |      * attributes of the method have been visited. | ||||||
|  |      */ | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitEnd(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										2685
									
								
								src/main/asm/org/objectweb/asm/MethodWriter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2685
									
								
								src/main/asm/org/objectweb/asm/MethodWriter.java
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										360
									
								
								src/main/asm/org/objectweb/asm/Opcodes.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								src/main/asm/org/objectweb/asm/Opcodes.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,360 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Defines the JVM opcodes, access flags and array type codes. This interface | ||||||
|  |  * does not define all the JVM opcodes because some opcodes are automatically | ||||||
|  |  * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced | ||||||
|  |  * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n | ||||||
|  |  * opcodes are therefore not defined in this interface. Likewise for LDC, | ||||||
|  |  * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and | ||||||
|  |  * JSR_W. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public interface Opcodes { | ||||||
|  | 
 | ||||||
|  |     // ASM API versions | ||||||
|  | 
 | ||||||
|  |     int ASM4 = 4 << 16 | 0 << 8 | 0; | ||||||
|  | 
 | ||||||
|  |     // versions | ||||||
|  | 
 | ||||||
|  |     int V1_1 = 3 << 16 | 45; | ||||||
|  |     int V1_2 = 0 << 16 | 46; | ||||||
|  |     int V1_3 = 0 << 16 | 47; | ||||||
|  |     int V1_4 = 0 << 16 | 48; | ||||||
|  |     int V1_5 = 0 << 16 | 49; | ||||||
|  |     int V1_6 = 0 << 16 | 50; | ||||||
|  |     int V1_7 = 0 << 16 | 51; | ||||||
|  |     int V1_8 = 0 << 16 | 52; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     // access flags | ||||||
|  | 
 | ||||||
|  |     int ACC_PUBLIC = 0x0001; // class, field, method | ||||||
|  |     int ACC_PRIVATE = 0x0002; // class, field, method | ||||||
|  |     int ACC_PROTECTED = 0x0004; // class, field, method | ||||||
|  |     int ACC_STATIC = 0x0008; // field, method | ||||||
|  |     int ACC_FINAL = 0x0010; // class, field, method | ||||||
|  |     int ACC_SUPER = 0x0020; // class | ||||||
|  |     int ACC_SYNCHRONIZED = 0x0020; // method | ||||||
|  |     int ACC_VOLATILE = 0x0040; // field | ||||||
|  |     int ACC_BRIDGE = 0x0040; // method | ||||||
|  |     int ACC_VARARGS = 0x0080; // method | ||||||
|  |     int ACC_TRANSIENT = 0x0080; // field | ||||||
|  |     int ACC_NATIVE = 0x0100; // method | ||||||
|  |     int ACC_INTERFACE = 0x0200; // class | ||||||
|  |     int ACC_ABSTRACT = 0x0400; // class, method | ||||||
|  |     int ACC_STRICT = 0x0800; // method | ||||||
|  |     int ACC_SYNTHETIC = 0x1000; // class, field, method | ||||||
|  |     int ACC_ANNOTATION = 0x2000; // class | ||||||
|  |     int ACC_ENUM = 0x4000; // class(?) field inner | ||||||
|  | 
 | ||||||
|  |     // ASM specific pseudo access flags | ||||||
|  | 
 | ||||||
|  |     int ACC_DEPRECATED = 0x20000; // class, field, method | ||||||
|  | 
 | ||||||
|  |     // types for NEWARRAY | ||||||
|  | 
 | ||||||
|  |     int T_BOOLEAN = 4; | ||||||
|  |     int T_CHAR = 5; | ||||||
|  |     int T_FLOAT = 6; | ||||||
|  |     int T_DOUBLE = 7; | ||||||
|  |     int T_BYTE = 8; | ||||||
|  |     int T_SHORT = 9; | ||||||
|  |     int T_INT = 10; | ||||||
|  |     int T_LONG = 11; | ||||||
|  | 
 | ||||||
|  |     // tags for Handle | ||||||
|  | 
 | ||||||
|  |     int H_GETFIELD = 1; | ||||||
|  |     int H_GETSTATIC = 2; | ||||||
|  |     int H_PUTFIELD = 3; | ||||||
|  |     int H_PUTSTATIC = 4; | ||||||
|  |     int H_INVOKEVIRTUAL = 5; | ||||||
|  |     int H_INVOKESTATIC = 6; | ||||||
|  |     int H_INVOKESPECIAL = 7; | ||||||
|  |     int H_NEWINVOKESPECIAL = 8; | ||||||
|  |     int H_INVOKEINTERFACE = 9; | ||||||
|  | 
 | ||||||
|  |     // stack map frame types | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. | ||||||
|  |      */ | ||||||
|  |     int F_NEW = -1; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Represents a compressed frame with complete frame data. | ||||||
|  |      */ | ||||||
|  |     int F_FULL = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Represents a compressed frame where locals are the same as the locals in | ||||||
|  |      * the previous frame, except that additional 1-3 locals are defined, and | ||||||
|  |      * with an empty stack. | ||||||
|  |      */ | ||||||
|  |     int F_APPEND = 1; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Represents a compressed frame where locals are the same as the locals in | ||||||
|  |      * the previous frame, except that the last 1-3 locals are absent and with | ||||||
|  |      * an empty stack. | ||||||
|  |      */ | ||||||
|  |     int F_CHOP = 2; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Represents a compressed frame with exactly the same locals as the | ||||||
|  |      * previous frame and with an empty stack. | ||||||
|  |      */ | ||||||
|  |     int F_SAME = 3; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Represents a compressed frame with exactly the same locals as the | ||||||
|  |      * previous frame and with a single value on the stack. | ||||||
|  |      */ | ||||||
|  |     int F_SAME1 = 4; | ||||||
|  | 
 | ||||||
|  |     Integer TOP = new Integer(0); | ||||||
|  |     Integer INTEGER = new Integer(1); | ||||||
|  |     Integer FLOAT = new Integer(2); | ||||||
|  |     Integer DOUBLE = new Integer(3); | ||||||
|  |     Integer LONG = new Integer(4); | ||||||
|  |     Integer NULL = new Integer(5); | ||||||
|  |     Integer UNINITIALIZED_THIS = new Integer(6); | ||||||
|  | 
 | ||||||
|  |     // opcodes // visit method (- = idem) | ||||||
|  | 
 | ||||||
|  |     int NOP = 0; // visitInsn | ||||||
|  |     int ACONST_NULL = 1; // - | ||||||
|  |     int ICONST_M1 = 2; // - | ||||||
|  |     int ICONST_0 = 3; // - | ||||||
|  |     int ICONST_1 = 4; // - | ||||||
|  |     int ICONST_2 = 5; // - | ||||||
|  |     int ICONST_3 = 6; // - | ||||||
|  |     int ICONST_4 = 7; // - | ||||||
|  |     int ICONST_5 = 8; // - | ||||||
|  |     int LCONST_0 = 9; // - | ||||||
|  |     int LCONST_1 = 10; // - | ||||||
|  |     int FCONST_0 = 11; // - | ||||||
|  |     int FCONST_1 = 12; // - | ||||||
|  |     int FCONST_2 = 13; // - | ||||||
|  |     int DCONST_0 = 14; // - | ||||||
|  |     int DCONST_1 = 15; // - | ||||||
|  |     int BIPUSH = 16; // visitIntInsn | ||||||
|  |     int SIPUSH = 17; // - | ||||||
|  |     int LDC = 18; // visitLdcInsn | ||||||
|  |     // int LDC_W = 19; // - | ||||||
|  |     // int LDC2_W = 20; // - | ||||||
|  |     int ILOAD = 21; // visitVarInsn | ||||||
|  |     int LLOAD = 22; // - | ||||||
|  |     int FLOAD = 23; // - | ||||||
|  |     int DLOAD = 24; // - | ||||||
|  |     int ALOAD = 25; // - | ||||||
|  |     // int ILOAD_0 = 26; // - | ||||||
|  |     // int ILOAD_1 = 27; // - | ||||||
|  |     // int ILOAD_2 = 28; // - | ||||||
|  |     // int ILOAD_3 = 29; // - | ||||||
|  |     // int LLOAD_0 = 30; // - | ||||||
|  |     // int LLOAD_1 = 31; // - | ||||||
|  |     // int LLOAD_2 = 32; // - | ||||||
|  |     // int LLOAD_3 = 33; // - | ||||||
|  |     // int FLOAD_0 = 34; // - | ||||||
|  |     // int FLOAD_1 = 35; // - | ||||||
|  |     // int FLOAD_2 = 36; // - | ||||||
|  |     // int FLOAD_3 = 37; // - | ||||||
|  |     // int DLOAD_0 = 38; // - | ||||||
|  |     // int DLOAD_1 = 39; // - | ||||||
|  |     // int DLOAD_2 = 40; // - | ||||||
|  |     // int DLOAD_3 = 41; // - | ||||||
|  |     // int ALOAD_0 = 42; // - | ||||||
|  |     // int ALOAD_1 = 43; // - | ||||||
|  |     // int ALOAD_2 = 44; // - | ||||||
|  |     // int ALOAD_3 = 45; // - | ||||||
|  |     int IALOAD = 46; // visitInsn | ||||||
|  |     int LALOAD = 47; // - | ||||||
|  |     int FALOAD = 48; // - | ||||||
|  |     int DALOAD = 49; // - | ||||||
|  |     int AALOAD = 50; // - | ||||||
|  |     int BALOAD = 51; // - | ||||||
|  |     int CALOAD = 52; // - | ||||||
|  |     int SALOAD = 53; // - | ||||||
|  |     int ISTORE = 54; // visitVarInsn | ||||||
|  |     int LSTORE = 55; // - | ||||||
|  |     int FSTORE = 56; // - | ||||||
|  |     int DSTORE = 57; // - | ||||||
|  |     int ASTORE = 58; // - | ||||||
|  |     // int ISTORE_0 = 59; // - | ||||||
|  |     // int ISTORE_1 = 60; // - | ||||||
|  |     // int ISTORE_2 = 61; // - | ||||||
|  |     // int ISTORE_3 = 62; // - | ||||||
|  |     // int LSTORE_0 = 63; // - | ||||||
|  |     // int LSTORE_1 = 64; // - | ||||||
|  |     // int LSTORE_2 = 65; // - | ||||||
|  |     // int LSTORE_3 = 66; // - | ||||||
|  |     // int FSTORE_0 = 67; // - | ||||||
|  |     // int FSTORE_1 = 68; // - | ||||||
|  |     // int FSTORE_2 = 69; // - | ||||||
|  |     // int FSTORE_3 = 70; // - | ||||||
|  |     // int DSTORE_0 = 71; // - | ||||||
|  |     // int DSTORE_1 = 72; // - | ||||||
|  |     // int DSTORE_2 = 73; // - | ||||||
|  |     // int DSTORE_3 = 74; // - | ||||||
|  |     // int ASTORE_0 = 75; // - | ||||||
|  |     // int ASTORE_1 = 76; // - | ||||||
|  |     // int ASTORE_2 = 77; // - | ||||||
|  |     // int ASTORE_3 = 78; // - | ||||||
|  |     int IASTORE = 79; // visitInsn | ||||||
|  |     int LASTORE = 80; // - | ||||||
|  |     int FASTORE = 81; // - | ||||||
|  |     int DASTORE = 82; // - | ||||||
|  |     int AASTORE = 83; // - | ||||||
|  |     int BASTORE = 84; // - | ||||||
|  |     int CASTORE = 85; // - | ||||||
|  |     int SASTORE = 86; // - | ||||||
|  |     int POP = 87; // - | ||||||
|  |     int POP2 = 88; // - | ||||||
|  |     int DUP = 89; // - | ||||||
|  |     int DUP_X1 = 90; // - | ||||||
|  |     int DUP_X2 = 91; // - | ||||||
|  |     int DUP2 = 92; // - | ||||||
|  |     int DUP2_X1 = 93; // - | ||||||
|  |     int DUP2_X2 = 94; // - | ||||||
|  |     int SWAP = 95; // - | ||||||
|  |     int IADD = 96; // - | ||||||
|  |     int LADD = 97; // - | ||||||
|  |     int FADD = 98; // - | ||||||
|  |     int DADD = 99; // - | ||||||
|  |     int ISUB = 100; // - | ||||||
|  |     int LSUB = 101; // - | ||||||
|  |     int FSUB = 102; // - | ||||||
|  |     int DSUB = 103; // - | ||||||
|  |     int IMUL = 104; // - | ||||||
|  |     int LMUL = 105; // - | ||||||
|  |     int FMUL = 106; // - | ||||||
|  |     int DMUL = 107; // - | ||||||
|  |     int IDIV = 108; // - | ||||||
|  |     int LDIV = 109; // - | ||||||
|  |     int FDIV = 110; // - | ||||||
|  |     int DDIV = 111; // - | ||||||
|  |     int IREM = 112; // - | ||||||
|  |     int LREM = 113; // - | ||||||
|  |     int FREM = 114; // - | ||||||
|  |     int DREM = 115; // - | ||||||
|  |     int INEG = 116; // - | ||||||
|  |     int LNEG = 117; // - | ||||||
|  |     int FNEG = 118; // - | ||||||
|  |     int DNEG = 119; // - | ||||||
|  |     int ISHL = 120; // - | ||||||
|  |     int LSHL = 121; // - | ||||||
|  |     int ISHR = 122; // - | ||||||
|  |     int LSHR = 123; // - | ||||||
|  |     int IUSHR = 124; // - | ||||||
|  |     int LUSHR = 125; // - | ||||||
|  |     int IAND = 126; // - | ||||||
|  |     int LAND = 127; // - | ||||||
|  |     int IOR = 128; // - | ||||||
|  |     int LOR = 129; // - | ||||||
|  |     int IXOR = 130; // - | ||||||
|  |     int LXOR = 131; // - | ||||||
|  |     int IINC = 132; // visitIincInsn | ||||||
|  |     int I2L = 133; // visitInsn | ||||||
|  |     int I2F = 134; // - | ||||||
|  |     int I2D = 135; // - | ||||||
|  |     int L2I = 136; // - | ||||||
|  |     int L2F = 137; // - | ||||||
|  |     int L2D = 138; // - | ||||||
|  |     int F2I = 139; // - | ||||||
|  |     int F2L = 140; // - | ||||||
|  |     int F2D = 141; // - | ||||||
|  |     int D2I = 142; // - | ||||||
|  |     int D2L = 143; // - | ||||||
|  |     int D2F = 144; // - | ||||||
|  |     int I2B = 145; // - | ||||||
|  |     int I2C = 146; // - | ||||||
|  |     int I2S = 147; // - | ||||||
|  |     int LCMP = 148; // - | ||||||
|  |     int FCMPL = 149; // - | ||||||
|  |     int FCMPG = 150; // - | ||||||
|  |     int DCMPL = 151; // - | ||||||
|  |     int DCMPG = 152; // - | ||||||
|  |     int IFEQ = 153; // visitJumpInsn | ||||||
|  |     int IFNE = 154; // - | ||||||
|  |     int IFLT = 155; // - | ||||||
|  |     int IFGE = 156; // - | ||||||
|  |     int IFGT = 157; // - | ||||||
|  |     int IFLE = 158; // - | ||||||
|  |     int IF_ICMPEQ = 159; // - | ||||||
|  |     int IF_ICMPNE = 160; // - | ||||||
|  |     int IF_ICMPLT = 161; // - | ||||||
|  |     int IF_ICMPGE = 162; // - | ||||||
|  |     int IF_ICMPGT = 163; // - | ||||||
|  |     int IF_ICMPLE = 164; // - | ||||||
|  |     int IF_ACMPEQ = 165; // - | ||||||
|  |     int IF_ACMPNE = 166; // - | ||||||
|  |     int GOTO = 167; // - | ||||||
|  |     int JSR = 168; // - | ||||||
|  |     int RET = 169; // visitVarInsn | ||||||
|  |     int TABLESWITCH = 170; // visiTableSwitchInsn | ||||||
|  |     int LOOKUPSWITCH = 171; // visitLookupSwitch | ||||||
|  |     int IRETURN = 172; // visitInsn | ||||||
|  |     int LRETURN = 173; // - | ||||||
|  |     int FRETURN = 174; // - | ||||||
|  |     int DRETURN = 175; // - | ||||||
|  |     int ARETURN = 176; // - | ||||||
|  |     int RETURN = 177; // - | ||||||
|  |     int GETSTATIC = 178; // visitFieldInsn | ||||||
|  |     int PUTSTATIC = 179; // - | ||||||
|  |     int GETFIELD = 180; // - | ||||||
|  |     int PUTFIELD = 181; // - | ||||||
|  |     int INVOKEVIRTUAL = 182; // visitMethodInsn | ||||||
|  |     int INVOKESPECIAL = 183; // - | ||||||
|  |     int INVOKESTATIC = 184; // - | ||||||
|  |     int INVOKEINTERFACE = 185; // - | ||||||
|  |     int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn | ||||||
|  |     int NEW = 187; // visitTypeInsn | ||||||
|  |     int NEWARRAY = 188; // visitIntInsn | ||||||
|  |     int ANEWARRAY = 189; // visitTypeInsn | ||||||
|  |     int ARRAYLENGTH = 190; // visitInsn | ||||||
|  |     int ATHROW = 191; // - | ||||||
|  |     int CHECKCAST = 192; // visitTypeInsn | ||||||
|  |     int INSTANCEOF = 193; // - | ||||||
|  |     int MONITORENTER = 194; // visitInsn | ||||||
|  |     int MONITOREXIT = 195; // - | ||||||
|  |     // int WIDE = 196; // NOT VISITED | ||||||
|  |     int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn | ||||||
|  |     int IFNULL = 198; // visitJumpInsn | ||||||
|  |     int IFNONNULL = 199; // - | ||||||
|  |     // int GOTO_W = 200; // - | ||||||
|  |     // int JSR_W = 201; // - | ||||||
|  | } | ||||||
							
								
								
									
										895
									
								
								src/main/asm/org/objectweb/asm/Type.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										895
									
								
								src/main/asm/org/objectweb/asm/Type.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,895 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Constructor; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A Java field or method type. This class can be used to make it easier to | ||||||
|  |  * manipulate type and method descriptors. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  * @author Chris Nokleberg | ||||||
|  |  */ | ||||||
|  | public class Type { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int VOID = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int BOOLEAN = 1; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int CHAR = 2; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int BYTE = 3; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int SHORT = 4; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int INT = 5; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int FLOAT = 6; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int LONG = 7; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int DOUBLE = 8; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of array reference types. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int ARRAY = 9; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of object reference types. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int OBJECT = 10; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of method types. See {@link #getSort getSort}. | ||||||
|  |      */ | ||||||
|  |     public static final int METHOD = 11; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>void</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) | ||||||
|  |             | (5 << 16) | (0 << 8) | 0, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>boolean</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) | ||||||
|  |             | (0 << 16) | (5 << 8) | 1, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>char</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) | ||||||
|  |             | (0 << 16) | (6 << 8) | 1, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>byte</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) | ||||||
|  |             | (0 << 16) | (5 << 8) | 1, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>short</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) | ||||||
|  |             | (0 << 16) | (7 << 8) | 1, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>int</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) | ||||||
|  |             | (0 << 16) | (0 << 8) | 1, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>float</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) | ||||||
|  |             | (2 << 16) | (2 << 8) | 1, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>long</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) | ||||||
|  |             | (1 << 16) | (1 << 8) | 2, 1); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The <tt>double</tt> type. | ||||||
|  |      */ | ||||||
|  |     public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) | ||||||
|  |             | (3 << 16) | (3 << 8) | 2, 1); | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Fields | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The sort of this Java type. | ||||||
|  |      */ | ||||||
|  |     private final int sort; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A buffer containing the internal name of this Java type. This field is | ||||||
|  |      * only used for reference types. | ||||||
|  |      */ | ||||||
|  |     private final char[] buf; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The offset of the internal name of this Java type in {@link #buf buf} or, | ||||||
|  |      * for primitive types, the size, descriptor and getOpcode offsets for this | ||||||
|  |      * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset | ||||||
|  |      * for IALOAD or IASTORE, byte 3 the offset for all other instructions). | ||||||
|  |      */ | ||||||
|  |     private final int off; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The length of the internal name of this Java type. | ||||||
|  |      */ | ||||||
|  |     private final int len; | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Constructors | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a reference type. | ||||||
|  |      *  | ||||||
|  |      * @param sort | ||||||
|  |      *            the sort of the reference type to be constructed. | ||||||
|  |      * @param buf | ||||||
|  |      *            a buffer containing the descriptor of the previous type. | ||||||
|  |      * @param off | ||||||
|  |      *            the offset of this descriptor in the previous buffer. | ||||||
|  |      * @param len | ||||||
|  |      *            the length of this descriptor. | ||||||
|  |      */ | ||||||
|  |     private Type(final int sort, final char[] buf, final int off, final int len) { | ||||||
|  |         this.sort = sort; | ||||||
|  |         this.buf = buf; | ||||||
|  |         this.off = off; | ||||||
|  |         this.len = len; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the given type descriptor. | ||||||
|  |      *  | ||||||
|  |      * @param typeDescriptor | ||||||
|  |      *            a field or method type descriptor. | ||||||
|  |      * @return the Java type corresponding to the given type descriptor. | ||||||
|  |      */ | ||||||
|  |     public static Type getType(final String typeDescriptor) { | ||||||
|  |         return getType(typeDescriptor.toCharArray(), 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the given internal name. | ||||||
|  |      *  | ||||||
|  |      * @param internalName | ||||||
|  |      *            an internal name. | ||||||
|  |      * @return the Java type corresponding to the given internal name. | ||||||
|  |      */ | ||||||
|  |     public static Type getObjectType(final String internalName) { | ||||||
|  |         char[] buf = internalName.toCharArray(); | ||||||
|  |         return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the given method descriptor. | ||||||
|  |      * Equivalent to <code>Type.getType(methodDescriptor)</code>. | ||||||
|  |      *  | ||||||
|  |      * @param methodDescriptor | ||||||
|  |      *            a method descriptor. | ||||||
|  |      * @return the Java type corresponding to the given method descriptor. | ||||||
|  |      */ | ||||||
|  |     public static Type getMethodType(final String methodDescriptor) { | ||||||
|  |         return getType(methodDescriptor.toCharArray(), 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java method type corresponding to the given argument and | ||||||
|  |      * return types. | ||||||
|  |      *  | ||||||
|  |      * @param returnType | ||||||
|  |      *            the return type of the method. | ||||||
|  |      * @param argumentTypes | ||||||
|  |      *            the argument types of the method. | ||||||
|  |      * @return the Java type corresponding to the given argument and return | ||||||
|  |      *         types. | ||||||
|  |      */ | ||||||
|  |     public static Type getMethodType(final Type returnType, | ||||||
|  |             final Type... argumentTypes) { | ||||||
|  |         return getType(getMethodDescriptor(returnType, argumentTypes)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the given class. | ||||||
|  |      *  | ||||||
|  |      * @param c | ||||||
|  |      *            a class. | ||||||
|  |      * @return the Java type corresponding to the given class. | ||||||
|  |      */ | ||||||
|  |     public static Type getType(final Class<?> c) { | ||||||
|  |         if (c.isPrimitive()) { | ||||||
|  |             if (c == Integer.TYPE) { | ||||||
|  |                 return INT_TYPE; | ||||||
|  |             } else if (c == Void.TYPE) { | ||||||
|  |                 return VOID_TYPE; | ||||||
|  |             } else if (c == Boolean.TYPE) { | ||||||
|  |                 return BOOLEAN_TYPE; | ||||||
|  |             } else if (c == Byte.TYPE) { | ||||||
|  |                 return BYTE_TYPE; | ||||||
|  |             } else if (c == Character.TYPE) { | ||||||
|  |                 return CHAR_TYPE; | ||||||
|  |             } else if (c == Short.TYPE) { | ||||||
|  |                 return SHORT_TYPE; | ||||||
|  |             } else if (c == Double.TYPE) { | ||||||
|  |                 return DOUBLE_TYPE; | ||||||
|  |             } else if (c == Float.TYPE) { | ||||||
|  |                 return FLOAT_TYPE; | ||||||
|  |             } else /* if (c == Long.TYPE) */{ | ||||||
|  |                 return LONG_TYPE; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             return getType(getDescriptor(c)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java method type corresponding to the given constructor. | ||||||
|  |      *  | ||||||
|  |      * @param c | ||||||
|  |      *            a {@link Constructor Constructor} object. | ||||||
|  |      * @return the Java method type corresponding to the given constructor. | ||||||
|  |      */ | ||||||
|  |     public static Type getType(final Constructor<?> c) { | ||||||
|  |         return getType(getConstructorDescriptor(c)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java method type corresponding to the given method. | ||||||
|  |      *  | ||||||
|  |      * @param m | ||||||
|  |      *            a {@link Method Method} object. | ||||||
|  |      * @return the Java method type corresponding to the given method. | ||||||
|  |      */ | ||||||
|  |     public static Type getType(final Method m) { | ||||||
|  |         return getType(getMethodDescriptor(m)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java types corresponding to the argument types of the given | ||||||
|  |      * method descriptor. | ||||||
|  |      *  | ||||||
|  |      * @param methodDescriptor | ||||||
|  |      *            a method descriptor. | ||||||
|  |      * @return the Java types corresponding to the argument types of the given | ||||||
|  |      *         method descriptor. | ||||||
|  |      */ | ||||||
|  |     public static Type[] getArgumentTypes(final String methodDescriptor) { | ||||||
|  |         char[] buf = methodDescriptor.toCharArray(); | ||||||
|  |         int off = 1; | ||||||
|  |         int size = 0; | ||||||
|  |         while (true) { | ||||||
|  |             char car = buf[off++]; | ||||||
|  |             if (car == ')') { | ||||||
|  |                 break; | ||||||
|  |             } else if (car == 'L') { | ||||||
|  |                 while (buf[off++] != ';') { | ||||||
|  |                 } | ||||||
|  |                 ++size; | ||||||
|  |             } else if (car != '[') { | ||||||
|  |                 ++size; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Type[] args = new Type[size]; | ||||||
|  |         off = 1; | ||||||
|  |         size = 0; | ||||||
|  |         while (buf[off] != ')') { | ||||||
|  |             args[size] = getType(buf, off); | ||||||
|  |             off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); | ||||||
|  |             size += 1; | ||||||
|  |         } | ||||||
|  |         return args; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java types corresponding to the argument types of the given | ||||||
|  |      * method. | ||||||
|  |      *  | ||||||
|  |      * @param method | ||||||
|  |      *            a method. | ||||||
|  |      * @return the Java types corresponding to the argument types of the given | ||||||
|  |      *         method. | ||||||
|  |      */ | ||||||
|  |     public static Type[] getArgumentTypes(final Method method) { | ||||||
|  |         Class<?>[] classes = method.getParameterTypes(); | ||||||
|  |         Type[] types = new Type[classes.length]; | ||||||
|  |         for (int i = classes.length - 1; i >= 0; --i) { | ||||||
|  |             types[i] = getType(classes[i]); | ||||||
|  |         } | ||||||
|  |         return types; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the return type of the given | ||||||
|  |      * method descriptor. | ||||||
|  |      *  | ||||||
|  |      * @param methodDescriptor | ||||||
|  |      *            a method descriptor. | ||||||
|  |      * @return the Java type corresponding to the return type of the given | ||||||
|  |      *         method descriptor. | ||||||
|  |      */ | ||||||
|  |     public static Type getReturnType(final String methodDescriptor) { | ||||||
|  |         char[] buf = methodDescriptor.toCharArray(); | ||||||
|  |         return getType(buf, methodDescriptor.indexOf(')') + 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the return type of the given | ||||||
|  |      * method. | ||||||
|  |      *  | ||||||
|  |      * @param method | ||||||
|  |      *            a method. | ||||||
|  |      * @return the Java type corresponding to the return type of the given | ||||||
|  |      *         method. | ||||||
|  |      */ | ||||||
|  |     public static Type getReturnType(final Method method) { | ||||||
|  |         return getType(method.getReturnType()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Computes the size of the arguments and of the return value of a method. | ||||||
|  |      *  | ||||||
|  |      * @param desc | ||||||
|  |      *            the descriptor of a method. | ||||||
|  |      * @return the size of the arguments of the method (plus one for the | ||||||
|  |      *         implicit this argument), argSize, and the size of its return | ||||||
|  |      *         value, retSize, packed into a single int i = | ||||||
|  |      *         <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to | ||||||
|  |      *         <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). | ||||||
|  |      */ | ||||||
|  |     public static int getArgumentsAndReturnSizes(final String desc) { | ||||||
|  |         int n = 1; | ||||||
|  |         int c = 1; | ||||||
|  |         while (true) { | ||||||
|  |             char car = desc.charAt(c++); | ||||||
|  |             if (car == ')') { | ||||||
|  |                 car = desc.charAt(c); | ||||||
|  |                 return n << 2 | ||||||
|  |                         | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); | ||||||
|  |             } else if (car == 'L') { | ||||||
|  |                 while (desc.charAt(c++) != ';') { | ||||||
|  |                 } | ||||||
|  |                 n += 1; | ||||||
|  |             } else if (car == '[') { | ||||||
|  |                 while ((car = desc.charAt(c)) == '[') { | ||||||
|  |                     ++c; | ||||||
|  |                 } | ||||||
|  |                 if (car == 'D' || car == 'J') { | ||||||
|  |                     n -= 1; | ||||||
|  |                 } | ||||||
|  |             } else if (car == 'D' || car == 'J') { | ||||||
|  |                 n += 2; | ||||||
|  |             } else { | ||||||
|  |                 n += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the Java type corresponding to the given type descriptor. For | ||||||
|  |      * method descriptors, buf is supposed to contain nothing more than the | ||||||
|  |      * descriptor itself. | ||||||
|  |      *  | ||||||
|  |      * @param buf | ||||||
|  |      *            a buffer containing a type descriptor. | ||||||
|  |      * @param off | ||||||
|  |      *            the offset of this descriptor in the previous buffer. | ||||||
|  |      * @return the Java type corresponding to the given type descriptor. | ||||||
|  |      */ | ||||||
|  |     private static Type getType(final char[] buf, final int off) { | ||||||
|  |         int len; | ||||||
|  |         switch (buf[off]) { | ||||||
|  |         case 'V': | ||||||
|  |             return VOID_TYPE; | ||||||
|  |         case 'Z': | ||||||
|  |             return BOOLEAN_TYPE; | ||||||
|  |         case 'C': | ||||||
|  |             return CHAR_TYPE; | ||||||
|  |         case 'B': | ||||||
|  |             return BYTE_TYPE; | ||||||
|  |         case 'S': | ||||||
|  |             return SHORT_TYPE; | ||||||
|  |         case 'I': | ||||||
|  |             return INT_TYPE; | ||||||
|  |         case 'F': | ||||||
|  |             return FLOAT_TYPE; | ||||||
|  |         case 'J': | ||||||
|  |             return LONG_TYPE; | ||||||
|  |         case 'D': | ||||||
|  |             return DOUBLE_TYPE; | ||||||
|  |         case '[': | ||||||
|  |             len = 1; | ||||||
|  |             while (buf[off + len] == '[') { | ||||||
|  |                 ++len; | ||||||
|  |             } | ||||||
|  |             if (buf[off + len] == 'L') { | ||||||
|  |                 ++len; | ||||||
|  |                 while (buf[off + len] != ';') { | ||||||
|  |                     ++len; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return new Type(ARRAY, buf, off, len + 1); | ||||||
|  |         case 'L': | ||||||
|  |             len = 1; | ||||||
|  |             while (buf[off + len] != ';') { | ||||||
|  |                 ++len; | ||||||
|  |             } | ||||||
|  |             return new Type(OBJECT, buf, off + 1, len - 1); | ||||||
|  |             // case '(': | ||||||
|  |         default: | ||||||
|  |             return new Type(METHOD, buf, off, buf.length - off); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Accessors | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the sort of this Java type. | ||||||
|  |      *  | ||||||
|  |      * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, | ||||||
|  |      *         {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, | ||||||
|  |      *         {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, | ||||||
|  |      *         {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD | ||||||
|  |      *         METHOD}. | ||||||
|  |      */ | ||||||
|  |     public int getSort() { | ||||||
|  |         return sort; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the number of dimensions of this array type. This method should | ||||||
|  |      * only be used for an array type. | ||||||
|  |      *  | ||||||
|  |      * @return the number of dimensions of this array type. | ||||||
|  |      */ | ||||||
|  |     public int getDimensions() { | ||||||
|  |         int i = 1; | ||||||
|  |         while (buf[off + i] == '[') { | ||||||
|  |             ++i; | ||||||
|  |         } | ||||||
|  |         return i; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the type of the elements of this array type. This method should | ||||||
|  |      * only be used for an array type. | ||||||
|  |      *  | ||||||
|  |      * @return Returns the type of the elements of this array type. | ||||||
|  |      */ | ||||||
|  |     public Type getElementType() { | ||||||
|  |         return getType(buf, off + getDimensions()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the binary name of the class corresponding to this type. This | ||||||
|  |      * method must not be used on method types. | ||||||
|  |      *  | ||||||
|  |      * @return the binary name of the class corresponding to this type. | ||||||
|  |      */ | ||||||
|  |     public String getClassName() { | ||||||
|  |         switch (sort) { | ||||||
|  |         case VOID: | ||||||
|  |             return "void"; | ||||||
|  |         case BOOLEAN: | ||||||
|  |             return "boolean"; | ||||||
|  |         case CHAR: | ||||||
|  |             return "char"; | ||||||
|  |         case BYTE: | ||||||
|  |             return "byte"; | ||||||
|  |         case SHORT: | ||||||
|  |             return "short"; | ||||||
|  |         case INT: | ||||||
|  |             return "int"; | ||||||
|  |         case FLOAT: | ||||||
|  |             return "float"; | ||||||
|  |         case LONG: | ||||||
|  |             return "long"; | ||||||
|  |         case DOUBLE: | ||||||
|  |             return "double"; | ||||||
|  |         case ARRAY: | ||||||
|  |             StringBuffer b = new StringBuffer(getElementType().getClassName()); | ||||||
|  |             for (int i = getDimensions(); i > 0; --i) { | ||||||
|  |                 b.append("[]"); | ||||||
|  |             } | ||||||
|  |             return b.toString(); | ||||||
|  |         case OBJECT: | ||||||
|  |             return new String(buf, off, len).replace('/', '.'); | ||||||
|  |         default: | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the internal name of the class corresponding to this object or | ||||||
|  |      * array type. The internal name of a class is its fully qualified name (as | ||||||
|  |      * returned by Class.getName(), where '.' are replaced by '/'. This method | ||||||
|  |      * should only be used for an object or array type. | ||||||
|  |      *  | ||||||
|  |      * @return the internal name of the class corresponding to this object type. | ||||||
|  |      */ | ||||||
|  |     public String getInternalName() { | ||||||
|  |         return new String(buf, off, len); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the argument types of methods of this type. This method should | ||||||
|  |      * only be used for method types. | ||||||
|  |      *  | ||||||
|  |      * @return the argument types of methods of this type. | ||||||
|  |      */ | ||||||
|  |     public Type[] getArgumentTypes() { | ||||||
|  |         return getArgumentTypes(getDescriptor()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the return type of methods of this type. This method should only | ||||||
|  |      * be used for method types. | ||||||
|  |      *  | ||||||
|  |      * @return the return type of methods of this type. | ||||||
|  |      */ | ||||||
|  |     public Type getReturnType() { | ||||||
|  |         return getReturnType(getDescriptor()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the size of the arguments and of the return value of methods of | ||||||
|  |      * this type. This method should only be used for method types. | ||||||
|  |      *  | ||||||
|  |      * @return the size of the arguments (plus one for the implicit this | ||||||
|  |      *         argument), argSize, and the size of the return value, retSize, | ||||||
|  |      *         packed into a single int i = <tt>(argSize << 2) | retSize</tt> | ||||||
|  |      *         (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to | ||||||
|  |      *         <tt>i & 0x03</tt>). | ||||||
|  |      */ | ||||||
|  |     public int getArgumentsAndReturnSizes() { | ||||||
|  |         return getArgumentsAndReturnSizes(getDescriptor()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Conversion to type descriptors | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor corresponding to this Java type. | ||||||
|  |      *  | ||||||
|  |      * @return the descriptor corresponding to this Java type. | ||||||
|  |      */ | ||||||
|  |     public String getDescriptor() { | ||||||
|  |         StringBuffer buf = new StringBuffer(); | ||||||
|  |         getDescriptor(buf); | ||||||
|  |         return buf.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor corresponding to the given argument and return | ||||||
|  |      * types. | ||||||
|  |      *  | ||||||
|  |      * @param returnType | ||||||
|  |      *            the return type of the method. | ||||||
|  |      * @param argumentTypes | ||||||
|  |      *            the argument types of the method. | ||||||
|  |      * @return the descriptor corresponding to the given argument and return | ||||||
|  |      *         types. | ||||||
|  |      */ | ||||||
|  |     public static String getMethodDescriptor(final Type returnType, | ||||||
|  |             final Type... argumentTypes) { | ||||||
|  |         StringBuffer buf = new StringBuffer(); | ||||||
|  |         buf.append('('); | ||||||
|  |         for (int i = 0; i < argumentTypes.length; ++i) { | ||||||
|  |             argumentTypes[i].getDescriptor(buf); | ||||||
|  |         } | ||||||
|  |         buf.append(')'); | ||||||
|  |         returnType.getDescriptor(buf); | ||||||
|  |         return buf.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Appends the descriptor corresponding to this Java type to the given | ||||||
|  |      * string buffer. | ||||||
|  |      *  | ||||||
|  |      * @param buf | ||||||
|  |      *            the string buffer to which the descriptor must be appended. | ||||||
|  |      */ | ||||||
|  |     private void getDescriptor(final StringBuffer buf) { | ||||||
|  |         if (this.buf == null) { | ||||||
|  |             // descriptor is in byte 3 of 'off' for primitive types (buf == | ||||||
|  |             // null) | ||||||
|  |             buf.append((char) ((off & 0xFF000000) >>> 24)); | ||||||
|  |         } else if (sort == OBJECT) { | ||||||
|  |             buf.append('L'); | ||||||
|  |             buf.append(this.buf, off, len); | ||||||
|  |             buf.append(';'); | ||||||
|  |         } else { // sort == ARRAY || sort == METHOD | ||||||
|  |             buf.append(this.buf, off, len); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Direct conversion from classes to type descriptors, | ||||||
|  |     // without intermediate Type objects | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the internal name of the given class. The internal name of a | ||||||
|  |      * class is its fully qualified name, as returned by Class.getName(), where | ||||||
|  |      * '.' are replaced by '/'. | ||||||
|  |      *  | ||||||
|  |      * @param c | ||||||
|  |      *            an object or array class. | ||||||
|  |      * @return the internal name of the given class. | ||||||
|  |      */ | ||||||
|  |     public static String getInternalName(final Class<?> c) { | ||||||
|  |         return c.getName().replace('.', '/'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor corresponding to the given Java type. | ||||||
|  |      *  | ||||||
|  |      * @param c | ||||||
|  |      *            an object class, a primitive class or an array class. | ||||||
|  |      * @return the descriptor corresponding to the given class. | ||||||
|  |      */ | ||||||
|  |     public static String getDescriptor(final Class<?> c) { | ||||||
|  |         StringBuffer buf = new StringBuffer(); | ||||||
|  |         getDescriptor(buf, c); | ||||||
|  |         return buf.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor corresponding to the given constructor. | ||||||
|  |      *  | ||||||
|  |      * @param c | ||||||
|  |      *            a {@link Constructor Constructor} object. | ||||||
|  |      * @return the descriptor of the given constructor. | ||||||
|  |      */ | ||||||
|  |     public static String getConstructorDescriptor(final Constructor<?> c) { | ||||||
|  |         Class<?>[] parameters = c.getParameterTypes(); | ||||||
|  |         StringBuffer buf = new StringBuffer(); | ||||||
|  |         buf.append('('); | ||||||
|  |         for (int i = 0; i < parameters.length; ++i) { | ||||||
|  |             getDescriptor(buf, parameters[i]); | ||||||
|  |         } | ||||||
|  |         return buf.append(")V").toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor corresponding to the given method. | ||||||
|  |      *  | ||||||
|  |      * @param m | ||||||
|  |      *            a {@link Method Method} object. | ||||||
|  |      * @return the descriptor of the given method. | ||||||
|  |      */ | ||||||
|  |     public static String getMethodDescriptor(final Method m) { | ||||||
|  |         Class<?>[] parameters = m.getParameterTypes(); | ||||||
|  |         StringBuffer buf = new StringBuffer(); | ||||||
|  |         buf.append('('); | ||||||
|  |         for (int i = 0; i < parameters.length; ++i) { | ||||||
|  |             getDescriptor(buf, parameters[i]); | ||||||
|  |         } | ||||||
|  |         buf.append(')'); | ||||||
|  |         getDescriptor(buf, m.getReturnType()); | ||||||
|  |         return buf.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Appends the descriptor of the given class to the given string buffer. | ||||||
|  |      *  | ||||||
|  |      * @param buf | ||||||
|  |      *            the string buffer to which the descriptor must be appended. | ||||||
|  |      * @param c | ||||||
|  |      *            the class whose descriptor must be computed. | ||||||
|  |      */ | ||||||
|  |     private static void getDescriptor(final StringBuffer buf, final Class<?> c) { | ||||||
|  |         Class<?> d = c; | ||||||
|  |         while (true) { | ||||||
|  |             if (d.isPrimitive()) { | ||||||
|  |                 char car; | ||||||
|  |                 if (d == Integer.TYPE) { | ||||||
|  |                     car = 'I'; | ||||||
|  |                 } else if (d == Void.TYPE) { | ||||||
|  |                     car = 'V'; | ||||||
|  |                 } else if (d == Boolean.TYPE) { | ||||||
|  |                     car = 'Z'; | ||||||
|  |                 } else if (d == Byte.TYPE) { | ||||||
|  |                     car = 'B'; | ||||||
|  |                 } else if (d == Character.TYPE) { | ||||||
|  |                     car = 'C'; | ||||||
|  |                 } else if (d == Short.TYPE) { | ||||||
|  |                     car = 'S'; | ||||||
|  |                 } else if (d == Double.TYPE) { | ||||||
|  |                     car = 'D'; | ||||||
|  |                 } else if (d == Float.TYPE) { | ||||||
|  |                     car = 'F'; | ||||||
|  |                 } else /* if (d == Long.TYPE) */{ | ||||||
|  |                     car = 'J'; | ||||||
|  |                 } | ||||||
|  |                 buf.append(car); | ||||||
|  |                 return; | ||||||
|  |             } else if (d.isArray()) { | ||||||
|  |                 buf.append('['); | ||||||
|  |                 d = d.getComponentType(); | ||||||
|  |             } else { | ||||||
|  |                 buf.append('L'); | ||||||
|  |                 String name = d.getName(); | ||||||
|  |                 int len = name.length(); | ||||||
|  |                 for (int i = 0; i < len; ++i) { | ||||||
|  |                     char car = name.charAt(i); | ||||||
|  |                     buf.append(car == '.' ? '/' : car); | ||||||
|  |                 } | ||||||
|  |                 buf.append(';'); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Corresponding size and opcodes | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the size of values of this type. This method must not be used for | ||||||
|  |      * method types. | ||||||
|  |      *  | ||||||
|  |      * @return the size of values of this type, i.e., 2 for <tt>long</tt> and | ||||||
|  |      *         <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. | ||||||
|  |      */ | ||||||
|  |     public int getSize() { | ||||||
|  |         // the size is in byte 0 of 'off' for primitive types (buf == null) | ||||||
|  |         return buf == null ? (off & 0xFF) : 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a JVM instruction opcode adapted to this Java type. This method | ||||||
|  |      * must not be used for method types. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            a JVM instruction opcode. This opcode must be one of ILOAD, | ||||||
|  |      *            ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, | ||||||
|  |      *            ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. | ||||||
|  |      * @return an opcode that is similar to the given opcode, but adapted to | ||||||
|  |      *         this Java type. For example, if this type is <tt>float</tt> and | ||||||
|  |      *         <tt>opcode</tt> is IRETURN, this method returns FRETURN. | ||||||
|  |      */ | ||||||
|  |     public int getOpcode(final int opcode) { | ||||||
|  |         if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { | ||||||
|  |             // the offset for IALOAD or IASTORE is in byte 1 of 'off' for | ||||||
|  |             // primitive types (buf == null) | ||||||
|  |             return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); | ||||||
|  |         } else { | ||||||
|  |             // the offset for other instructions is in byte 2 of 'off' for | ||||||
|  |             // primitive types (buf == null) | ||||||
|  |             return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Equals, hashCode and toString | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Tests if the given object is equal to this type. | ||||||
|  |      *  | ||||||
|  |      * @param o | ||||||
|  |      *            the object to be compared to this type. | ||||||
|  |      * @return <tt>true</tt> if the given object is equal to this type. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(final Object o) { | ||||||
|  |         if (this == o) { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         if (!(o instanceof Type)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         Type t = (Type) o; | ||||||
|  |         if (sort != t.sort) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if (sort >= ARRAY) { | ||||||
|  |             if (len != t.len) { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { | ||||||
|  |                 if (buf[i] != t.buf[j]) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a hash code value for this type. | ||||||
|  |      *  | ||||||
|  |      * @return a hash code value for this type. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         int hc = 13 * sort; | ||||||
|  |         if (sort >= ARRAY) { | ||||||
|  |             for (int i = off, end = i + len; i < end; i++) { | ||||||
|  |                 hc = 17 * (hc + buf[i]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return hc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a string representation of this type. | ||||||
|  |      *  | ||||||
|  |      * @return the descriptor of this type. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return getDescriptor(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								src/main/asm/org/objectweb/asm/attrs/package.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/main/asm/org/objectweb/asm/attrs/package.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | <html> | ||||||
|  | <!-- | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | --> | ||||||
|  | <body> | ||||||
|  | Provides an implementation for optional class, field and method attributes. | ||||||
|  | 
 | ||||||
|  | <p> | ||||||
|  | 
 | ||||||
|  | By default ASM strips optional attributes, in order to keep them in | ||||||
|  | the bytecode that is being readed you should pass an array of required attribute | ||||||
|  | instances to {@link org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, org.objectweb.asm.Attribute[], boolean) ClassReader.accept()} method. | ||||||
|  | In order to add custom attributes to the manually constructed bytecode concrete | ||||||
|  | subclasses of the {@link org.objectweb.asm.Attribute Attribute} can be passed to | ||||||
|  | the visitAttribute methods of the | ||||||
|  | {@link org.objectweb.asm.ClassVisitor ClassVisitor}, | ||||||
|  | {@link org.objectweb.asm.FieldVisitor FieldVisitor} and | ||||||
|  | {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces. | ||||||
|  | 
 | ||||||
|  | @since ASM 1.4.1 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										625
									
								
								src/main/asm/org/objectweb/asm/commons/AdviceAdapter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										625
									
								
								src/main/asm/org/objectweb/asm/commons/AdviceAdapter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,625 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link org.objectweb.asm.MethodVisitor} to insert before, after and around | ||||||
|  |  * advices in methods and constructors. | ||||||
|  |  * <p> | ||||||
|  |  * The behavior for constructors is like this: | ||||||
|  |  * <ol> | ||||||
|  |  *  | ||||||
|  |  * <li>as long as the INVOKESPECIAL for the object initialization has not been | ||||||
|  |  * reached, every bytecode instruction is dispatched in the ctor code visitor</li> | ||||||
|  |  *  | ||||||
|  |  * <li>when this one is reached, it is only added in the ctor code visitor and a | ||||||
|  |  * JP invoke is added</li> | ||||||
|  |  *  | ||||||
|  |  * <li>after that, only the other code visitor receives the instructions</li> | ||||||
|  |  *  | ||||||
|  |  * </ol> | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { | ||||||
|  | 
 | ||||||
|  |     private static final Object THIS = new Object(); | ||||||
|  | 
 | ||||||
|  |     private static final Object OTHER = new Object(); | ||||||
|  | 
 | ||||||
|  |     protected int methodAccess; | ||||||
|  | 
 | ||||||
|  |     protected String methodDesc; | ||||||
|  | 
 | ||||||
|  |     private boolean constructor; | ||||||
|  | 
 | ||||||
|  |     private boolean superInitialized; | ||||||
|  | 
 | ||||||
|  |     private List<Object> stackFrame; | ||||||
|  | 
 | ||||||
|  |     private Map<Label, List<Object>> branches; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link AdviceAdapter}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor to which this adapter delegates calls. | ||||||
|  |      * @param access | ||||||
|  |      *            the method's access flags (see {@link Opcodes}). | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      */ | ||||||
|  |     protected AdviceAdapter(final int api, final MethodVisitor mv, | ||||||
|  |             final int access, final String name, final String desc) { | ||||||
|  |         super(api, mv, access, name, desc); | ||||||
|  |         methodAccess = access; | ||||||
|  |         methodDesc = desc; | ||||||
|  |         constructor = "<init>".equals(name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitCode() { | ||||||
|  |         mv.visitCode(); | ||||||
|  |         if (constructor) { | ||||||
|  |             stackFrame = new ArrayList<Object>(); | ||||||
|  |             branches = new HashMap<Label, List<Object>>(); | ||||||
|  |         } else { | ||||||
|  |             superInitialized = true; | ||||||
|  |             onMethodEnter(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLabel(final Label label) { | ||||||
|  |         mv.visitLabel(label); | ||||||
|  |         if (constructor && branches != null) { | ||||||
|  |             List<Object> frame = branches.get(label); | ||||||
|  |             if (frame != null) { | ||||||
|  |                 stackFrame = frame; | ||||||
|  |                 branches.remove(label); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInsn(final int opcode) { | ||||||
|  |         if (constructor) { | ||||||
|  |             int s; | ||||||
|  |             switch (opcode) { | ||||||
|  |             case RETURN: // empty stack | ||||||
|  |                 onMethodExit(opcode); | ||||||
|  |                 break; | ||||||
|  |             case IRETURN: // 1 before n/a after | ||||||
|  |             case FRETURN: // 1 before n/a after | ||||||
|  |             case ARETURN: // 1 before n/a after | ||||||
|  |             case ATHROW: // 1 before n/a after | ||||||
|  |                 popValue(); | ||||||
|  |                 onMethodExit(opcode); | ||||||
|  |                 break; | ||||||
|  |             case LRETURN: // 2 before n/a after | ||||||
|  |             case DRETURN: // 2 before n/a after | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 onMethodExit(opcode); | ||||||
|  |                 break; | ||||||
|  |             case NOP: | ||||||
|  |             case LALOAD: // remove 2 add 2 | ||||||
|  |             case DALOAD: // remove 2 add 2 | ||||||
|  |             case LNEG: | ||||||
|  |             case DNEG: | ||||||
|  |             case FNEG: | ||||||
|  |             case INEG: | ||||||
|  |             case L2D: | ||||||
|  |             case D2L: | ||||||
|  |             case F2I: | ||||||
|  |             case I2B: | ||||||
|  |             case I2C: | ||||||
|  |             case I2S: | ||||||
|  |             case I2F: | ||||||
|  |             case ARRAYLENGTH: | ||||||
|  |                 break; | ||||||
|  |             case ACONST_NULL: | ||||||
|  |             case ICONST_M1: | ||||||
|  |             case ICONST_0: | ||||||
|  |             case ICONST_1: | ||||||
|  |             case ICONST_2: | ||||||
|  |             case ICONST_3: | ||||||
|  |             case ICONST_4: | ||||||
|  |             case ICONST_5: | ||||||
|  |             case FCONST_0: | ||||||
|  |             case FCONST_1: | ||||||
|  |             case FCONST_2: | ||||||
|  |             case F2L: // 1 before 2 after | ||||||
|  |             case F2D: | ||||||
|  |             case I2L: | ||||||
|  |             case I2D: | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 break; | ||||||
|  |             case LCONST_0: | ||||||
|  |             case LCONST_1: | ||||||
|  |             case DCONST_0: | ||||||
|  |             case DCONST_1: | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 break; | ||||||
|  |             case IALOAD: // remove 2 add 1 | ||||||
|  |             case FALOAD: // remove 2 add 1 | ||||||
|  |             case AALOAD: // remove 2 add 1 | ||||||
|  |             case BALOAD: // remove 2 add 1 | ||||||
|  |             case CALOAD: // remove 2 add 1 | ||||||
|  |             case SALOAD: // remove 2 add 1 | ||||||
|  |             case POP: | ||||||
|  |             case IADD: | ||||||
|  |             case FADD: | ||||||
|  |             case ISUB: | ||||||
|  |             case LSHL: // 3 before 2 after | ||||||
|  |             case LSHR: // 3 before 2 after | ||||||
|  |             case LUSHR: // 3 before 2 after | ||||||
|  |             case L2I: // 2 before 1 after | ||||||
|  |             case L2F: // 2 before 1 after | ||||||
|  |             case D2I: // 2 before 1 after | ||||||
|  |             case D2F: // 2 before 1 after | ||||||
|  |             case FSUB: | ||||||
|  |             case FMUL: | ||||||
|  |             case FDIV: | ||||||
|  |             case FREM: | ||||||
|  |             case FCMPL: // 2 before 1 after | ||||||
|  |             case FCMPG: // 2 before 1 after | ||||||
|  |             case IMUL: | ||||||
|  |             case IDIV: | ||||||
|  |             case IREM: | ||||||
|  |             case ISHL: | ||||||
|  |             case ISHR: | ||||||
|  |             case IUSHR: | ||||||
|  |             case IAND: | ||||||
|  |             case IOR: | ||||||
|  |             case IXOR: | ||||||
|  |             case MONITORENTER: | ||||||
|  |             case MONITOREXIT: | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case POP2: | ||||||
|  |             case LSUB: | ||||||
|  |             case LMUL: | ||||||
|  |             case LDIV: | ||||||
|  |             case LREM: | ||||||
|  |             case LADD: | ||||||
|  |             case LAND: | ||||||
|  |             case LOR: | ||||||
|  |             case LXOR: | ||||||
|  |             case DADD: | ||||||
|  |             case DMUL: | ||||||
|  |             case DSUB: | ||||||
|  |             case DDIV: | ||||||
|  |             case DREM: | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case IASTORE: | ||||||
|  |             case FASTORE: | ||||||
|  |             case AASTORE: | ||||||
|  |             case BASTORE: | ||||||
|  |             case CASTORE: | ||||||
|  |             case SASTORE: | ||||||
|  |             case LCMP: // 4 before 1 after | ||||||
|  |             case DCMPL: | ||||||
|  |             case DCMPG: | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case LASTORE: | ||||||
|  |             case DASTORE: | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case DUP: | ||||||
|  |                 pushValue(peekValue()); | ||||||
|  |                 break; | ||||||
|  |             case DUP_X1: | ||||||
|  |                 s = stackFrame.size(); | ||||||
|  |                 stackFrame.add(s - 2, stackFrame.get(s - 1)); | ||||||
|  |                 break; | ||||||
|  |             case DUP_X2: | ||||||
|  |                 s = stackFrame.size(); | ||||||
|  |                 stackFrame.add(s - 3, stackFrame.get(s - 1)); | ||||||
|  |                 break; | ||||||
|  |             case DUP2: | ||||||
|  |                 s = stackFrame.size(); | ||||||
|  |                 stackFrame.add(s - 2, stackFrame.get(s - 1)); | ||||||
|  |                 stackFrame.add(s - 2, stackFrame.get(s - 1)); | ||||||
|  |                 break; | ||||||
|  |             case DUP2_X1: | ||||||
|  |                 s = stackFrame.size(); | ||||||
|  |                 stackFrame.add(s - 3, stackFrame.get(s - 1)); | ||||||
|  |                 stackFrame.add(s - 3, stackFrame.get(s - 1)); | ||||||
|  |                 break; | ||||||
|  |             case DUP2_X2: | ||||||
|  |                 s = stackFrame.size(); | ||||||
|  |                 stackFrame.add(s - 4, stackFrame.get(s - 1)); | ||||||
|  |                 stackFrame.add(s - 4, stackFrame.get(s - 1)); | ||||||
|  |                 break; | ||||||
|  |             case SWAP: | ||||||
|  |                 s = stackFrame.size(); | ||||||
|  |                 stackFrame.add(s - 2, stackFrame.get(s - 1)); | ||||||
|  |                 stackFrame.remove(s); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             switch (opcode) { | ||||||
|  |             case RETURN: | ||||||
|  |             case IRETURN: | ||||||
|  |             case FRETURN: | ||||||
|  |             case ARETURN: | ||||||
|  |             case LRETURN: | ||||||
|  |             case DRETURN: | ||||||
|  |             case ATHROW: | ||||||
|  |                 onMethodExit(opcode); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         mv.visitInsn(opcode); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitVarInsn(final int opcode, final int var) { | ||||||
|  |         super.visitVarInsn(opcode, var); | ||||||
|  |         if (constructor) { | ||||||
|  |             switch (opcode) { | ||||||
|  |             case ILOAD: | ||||||
|  |             case FLOAD: | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 break; | ||||||
|  |             case LLOAD: | ||||||
|  |             case DLOAD: | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 break; | ||||||
|  |             case ALOAD: | ||||||
|  |                 pushValue(var == 0 ? THIS : OTHER); | ||||||
|  |                 break; | ||||||
|  |             case ASTORE: | ||||||
|  |             case ISTORE: | ||||||
|  |             case FSTORE: | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case LSTORE: | ||||||
|  |             case DSTORE: | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFieldInsn(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         mv.visitFieldInsn(opcode, owner, name, desc); | ||||||
|  |         if (constructor) { | ||||||
|  |             char c = desc.charAt(0); | ||||||
|  |             boolean longOrDouble = c == 'J' || c == 'D'; | ||||||
|  |             switch (opcode) { | ||||||
|  |             case GETSTATIC: | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 if (longOrDouble) { | ||||||
|  |                     pushValue(OTHER); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case PUTSTATIC: | ||||||
|  |                 popValue(); | ||||||
|  |                 if (longOrDouble) { | ||||||
|  |                     popValue(); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case PUTFIELD: | ||||||
|  |                 popValue(); | ||||||
|  |                 if (longOrDouble) { | ||||||
|  |                     popValue(); | ||||||
|  |                     popValue(); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             // case GETFIELD: | ||||||
|  |             default: | ||||||
|  |                 if (longOrDouble) { | ||||||
|  |                     pushValue(OTHER); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitIntInsn(final int opcode, final int operand) { | ||||||
|  |         mv.visitIntInsn(opcode, operand); | ||||||
|  |         if (constructor && opcode != NEWARRAY) { | ||||||
|  |             pushValue(OTHER); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLdcInsn(final Object cst) { | ||||||
|  |         mv.visitLdcInsn(cst); | ||||||
|  |         if (constructor) { | ||||||
|  |             pushValue(OTHER); | ||||||
|  |             if (cst instanceof Double || cst instanceof Long) { | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMultiANewArrayInsn(final String desc, final int dims) { | ||||||
|  |         mv.visitMultiANewArrayInsn(desc, dims); | ||||||
|  |         if (constructor) { | ||||||
|  |             for (int i = 0; i < dims; i++) { | ||||||
|  |                 popValue(); | ||||||
|  |             } | ||||||
|  |             pushValue(OTHER); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeInsn(final int opcode, final String type) { | ||||||
|  |         mv.visitTypeInsn(opcode, type); | ||||||
|  |         // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack | ||||||
|  |         if (constructor && opcode == NEW) { | ||||||
|  |             pushValue(OTHER); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMethodInsn(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         mv.visitMethodInsn(opcode, owner, name, desc); | ||||||
|  |         if (constructor) { | ||||||
|  |             Type[] types = Type.getArgumentTypes(desc); | ||||||
|  |             for (int i = 0; i < types.length; i++) { | ||||||
|  |                 popValue(); | ||||||
|  |                 if (types[i].getSize() == 2) { | ||||||
|  |                     popValue(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             switch (opcode) { | ||||||
|  |             // case INVOKESTATIC: | ||||||
|  |             // break; | ||||||
|  |             case INVOKEINTERFACE: | ||||||
|  |             case INVOKEVIRTUAL: | ||||||
|  |                 popValue(); // objectref | ||||||
|  |                 break; | ||||||
|  |             case INVOKESPECIAL: | ||||||
|  |                 Object type = popValue(); // objectref | ||||||
|  |                 if (type == THIS && !superInitialized) { | ||||||
|  |                     onMethodEnter(); | ||||||
|  |                     superInitialized = true; | ||||||
|  |                     // once super has been initialized it is no longer | ||||||
|  |                     // necessary to keep track of stack state | ||||||
|  |                     constructor = false; | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Type returnType = Type.getReturnType(desc); | ||||||
|  |             if (returnType != Type.VOID_TYPE) { | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 if (returnType.getSize() == 2) { | ||||||
|  |                     pushValue(OTHER); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, | ||||||
|  |             Object... bsmArgs) { | ||||||
|  |         mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); | ||||||
|  |         if (constructor) { | ||||||
|  |             Type[] types = Type.getArgumentTypes(desc); | ||||||
|  |             for (int i = 0; i < types.length; i++) { | ||||||
|  |                 popValue(); | ||||||
|  |                 if (types[i].getSize() == 2) { | ||||||
|  |                     popValue(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Type returnType = Type.getReturnType(desc); | ||||||
|  |             if (returnType != Type.VOID_TYPE) { | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 if (returnType.getSize() == 2) { | ||||||
|  |                     pushValue(OTHER); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitJumpInsn(final int opcode, final Label label) { | ||||||
|  |         mv.visitJumpInsn(opcode, label); | ||||||
|  |         if (constructor) { | ||||||
|  |             switch (opcode) { | ||||||
|  |             case IFEQ: | ||||||
|  |             case IFNE: | ||||||
|  |             case IFLT: | ||||||
|  |             case IFGE: | ||||||
|  |             case IFGT: | ||||||
|  |             case IFLE: | ||||||
|  |             case IFNULL: | ||||||
|  |             case IFNONNULL: | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case IF_ICMPEQ: | ||||||
|  |             case IF_ICMPNE: | ||||||
|  |             case IF_ICMPLT: | ||||||
|  |             case IF_ICMPGE: | ||||||
|  |             case IF_ICMPGT: | ||||||
|  |             case IF_ICMPLE: | ||||||
|  |             case IF_ACMPEQ: | ||||||
|  |             case IF_ACMPNE: | ||||||
|  |                 popValue(); | ||||||
|  |                 popValue(); | ||||||
|  |                 break; | ||||||
|  |             case JSR: | ||||||
|  |                 pushValue(OTHER); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             addBranch(label); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLookupSwitchInsn(final Label dflt, final int[] keys, | ||||||
|  |             final Label[] labels) { | ||||||
|  |         mv.visitLookupSwitchInsn(dflt, keys, labels); | ||||||
|  |         if (constructor) { | ||||||
|  |             popValue(); | ||||||
|  |             addBranches(dflt, labels); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTableSwitchInsn(final int min, final int max, | ||||||
|  |             final Label dflt, final Label... labels) { | ||||||
|  |         mv.visitTableSwitchInsn(min, max, dflt, labels); | ||||||
|  |         if (constructor) { | ||||||
|  |             popValue(); | ||||||
|  |             addBranches(dflt, labels); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTryCatchBlock(Label start, Label end, Label handler, | ||||||
|  |             String type) { | ||||||
|  |         super.visitTryCatchBlock(start, end, handler, type); | ||||||
|  |         if (constructor && !branches.containsKey(handler)) { | ||||||
|  |             List<Object> stackFrame = new ArrayList<Object>(); | ||||||
|  |             stackFrame.add(OTHER); | ||||||
|  |             branches.put(handler, stackFrame); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void addBranches(final Label dflt, final Label[] labels) { | ||||||
|  |         addBranch(dflt); | ||||||
|  |         for (int i = 0; i < labels.length; i++) { | ||||||
|  |             addBranch(labels[i]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void addBranch(final Label label) { | ||||||
|  |         if (branches.containsKey(label)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         branches.put(label, new ArrayList<Object>(stackFrame)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Object popValue() { | ||||||
|  |         return stackFrame.remove(stackFrame.size() - 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Object peekValue() { | ||||||
|  |         return stackFrame.get(stackFrame.size() - 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void pushValue(final Object o) { | ||||||
|  |         stackFrame.add(o); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Called at the beginning of the method or after super class class call in | ||||||
|  |      * the constructor. <br> | ||||||
|  |      * <br> | ||||||
|  |      *  | ||||||
|  |      * <i>Custom code can use or change all the local variables, but should not | ||||||
|  |      * change state of the stack.</i> | ||||||
|  |      */ | ||||||
|  |     protected void onMethodEnter() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Called before explicit exit from the method using either return or throw. | ||||||
|  |      * Top element on the stack contains the return value or exception instance. | ||||||
|  |      * For example: | ||||||
|  |      *  | ||||||
|  |      * <pre> | ||||||
|  |      *   public void onMethodExit(int opcode) { | ||||||
|  |      *     if(opcode==RETURN) { | ||||||
|  |      *         visitInsn(ACONST_NULL); | ||||||
|  |      *     } else if(opcode==ARETURN || opcode==ATHROW) { | ||||||
|  |      *         dup(); | ||||||
|  |      *     } else { | ||||||
|  |      *         if(opcode==LRETURN || opcode==DRETURN) { | ||||||
|  |      *             dup2(); | ||||||
|  |      *         } else { | ||||||
|  |      *             dup(); | ||||||
|  |      *         } | ||||||
|  |      *         box(Type.getReturnType(this.methodDesc)); | ||||||
|  |      *     } | ||||||
|  |      *     visitIntInsn(SIPUSH, opcode); | ||||||
|  |      *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V"); | ||||||
|  |      *   } | ||||||
|  |      *  | ||||||
|  |      *   // an actual call back method | ||||||
|  |      *   public static void onExit(Object param, int opcode) { | ||||||
|  |      *     ... | ||||||
|  |      * </pre> | ||||||
|  |      *  | ||||||
|  |      * <br> | ||||||
|  |      * <br> | ||||||
|  |      *  | ||||||
|  |      * <i>Custom code can use or change all the local variables, but should not | ||||||
|  |      * change state of the stack.</i> | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN | ||||||
|  |      *            or ATHROW | ||||||
|  |      *  | ||||||
|  |      */ | ||||||
|  |     protected void onMethodExit(int opcode) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // TODO onException, onMethodCall | ||||||
|  | } | ||||||
							
								
								
									
										920
									
								
								src/main/asm/org/objectweb/asm/commons/AnalyzerAdapter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										920
									
								
								src/main/asm/org/objectweb/asm/commons/AnalyzerAdapter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,920 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link MethodVisitor} that keeps track of stack map frame changes between | ||||||
|  |  * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This | ||||||
|  |  * adapter must be used with the | ||||||
|  |  * {@link org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each | ||||||
|  |  * visit<i>X</i> instruction delegates to the next visitor in the chain, if any, | ||||||
|  |  * and then simulates the effect of this instruction on the stack map frame, | ||||||
|  |  * represented by {@link #locals} and {@link #stack}. The next visitor in the | ||||||
|  |  * chain can get the state of the stack map frame <i>before</i> each instruction | ||||||
|  |  * by reading the value of these fields in its visit<i>X</i> methods (this | ||||||
|  |  * requires a reference to the AnalyzerAdapter that is before it in the chain). | ||||||
|  |  * If this adapter is used with a class that does not contain stack map table | ||||||
|  |  * attributes (i.e., pre Java 6 classes) then this adapter may not be able to | ||||||
|  |  * compute the stack map frame for each instruction. In this case no exception | ||||||
|  |  * is thrown but the {@link #locals} and {@link #stack} fields will be null for | ||||||
|  |  * these instructions. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class AnalyzerAdapter extends MethodVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * <code>List</code> of the local variable slots for current execution | ||||||
|  |      * frame. Primitive types are represented by {@link Opcodes#TOP}, | ||||||
|  |      * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, | ||||||
|  |      * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or | ||||||
|  |      * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by | ||||||
|  |      * two elements, the second one being TOP). Reference types are represented | ||||||
|  |      * by String objects (representing internal names), and uninitialized types | ||||||
|  |      * by Label objects (this label designates the NEW instruction that created | ||||||
|  |      * this uninitialized value). This field is <tt>null</tt> for unreachable | ||||||
|  |      * instructions. | ||||||
|  |      */ | ||||||
|  |     public List<Object> locals; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * <code>List</code> of the operand stack slots for current execution frame. | ||||||
|  |      * Primitive types are represented by {@link Opcodes#TOP}, | ||||||
|  |      * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, | ||||||
|  |      * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or | ||||||
|  |      * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by | ||||||
|  |      * two elements, the second one being TOP). Reference types are represented | ||||||
|  |      * by String objects (representing internal names), and uninitialized types | ||||||
|  |      * by Label objects (this label designates the NEW instruction that created | ||||||
|  |      * this uninitialized value). This field is <tt>null</tt> for unreachable | ||||||
|  |      * instructions. | ||||||
|  |      */ | ||||||
|  |     public List<Object> stack; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The labels that designate the next instruction to be visited. May be | ||||||
|  |      * <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     private List<Label> labels; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Information about uninitialized types in the current execution frame. | ||||||
|  |      * This map associates internal names to Label objects. Each label | ||||||
|  |      * designates a NEW instruction that created the currently uninitialized | ||||||
|  |      * types, and the associated internal name represents the NEW operand, i.e. | ||||||
|  |      * the final, initialized type value. | ||||||
|  |      */ | ||||||
|  |     public Map<Object, Object> uninitializedTypes; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The maximum stack size of this method. | ||||||
|  |      */ | ||||||
|  |     private int maxStack; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The maximum number of local variables of this method. | ||||||
|  |      */ | ||||||
|  |     private int maxLocals; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The owner's class name. | ||||||
|  |      */ | ||||||
|  |     private String owner; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this | ||||||
|  |      * constructor</i>. Instead, they must use the | ||||||
|  |      * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)} | ||||||
|  |      * version. | ||||||
|  |      *  | ||||||
|  |      * @param owner | ||||||
|  |      *            the owner's class name. | ||||||
|  |      * @param access | ||||||
|  |      *            the method's access flags (see {@link Opcodes}). | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor to which this adapter delegates calls. May | ||||||
|  |      *            be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public AnalyzerAdapter(final String owner, final int access, | ||||||
|  |             final String name, final String desc, final MethodVisitor mv) { | ||||||
|  |         this(Opcodes.ASM4, owner, access, name, desc, mv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link AnalyzerAdapter}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param owner | ||||||
|  |      *            the owner's class name. | ||||||
|  |      * @param access | ||||||
|  |      *            the method's access flags (see {@link Opcodes}). | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor to which this adapter delegates calls. May | ||||||
|  |      *            be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     protected AnalyzerAdapter(final int api, final String owner, | ||||||
|  |             final int access, final String name, final String desc, | ||||||
|  |             final MethodVisitor mv) { | ||||||
|  |         super(api, mv); | ||||||
|  |         this.owner = owner; | ||||||
|  |         locals = new ArrayList<Object>(); | ||||||
|  |         stack = new ArrayList<Object>(); | ||||||
|  |         uninitializedTypes = new HashMap<Object, Object>(); | ||||||
|  | 
 | ||||||
|  |         if ((access & Opcodes.ACC_STATIC) == 0) { | ||||||
|  |             if ("<init>".equals(name)) { | ||||||
|  |                 locals.add(Opcodes.UNINITIALIZED_THIS); | ||||||
|  |             } else { | ||||||
|  |                 locals.add(owner); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Type[] types = Type.getArgumentTypes(desc); | ||||||
|  |         for (int i = 0; i < types.length; ++i) { | ||||||
|  |             Type type = types[i]; | ||||||
|  |             switch (type.getSort()) { | ||||||
|  |             case Type.BOOLEAN: | ||||||
|  |             case Type.CHAR: | ||||||
|  |             case Type.BYTE: | ||||||
|  |             case Type.SHORT: | ||||||
|  |             case Type.INT: | ||||||
|  |                 locals.add(Opcodes.INTEGER); | ||||||
|  |                 break; | ||||||
|  |             case Type.FLOAT: | ||||||
|  |                 locals.add(Opcodes.FLOAT); | ||||||
|  |                 break; | ||||||
|  |             case Type.LONG: | ||||||
|  |                 locals.add(Opcodes.LONG); | ||||||
|  |                 locals.add(Opcodes.TOP); | ||||||
|  |                 break; | ||||||
|  |             case Type.DOUBLE: | ||||||
|  |                 locals.add(Opcodes.DOUBLE); | ||||||
|  |                 locals.add(Opcodes.TOP); | ||||||
|  |                 break; | ||||||
|  |             case Type.ARRAY: | ||||||
|  |                 locals.add(types[i].getDescriptor()); | ||||||
|  |                 break; | ||||||
|  |             // case Type.OBJECT: | ||||||
|  |             default: | ||||||
|  |                 locals.add(types[i].getInternalName()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFrame(final int type, final int nLocal, | ||||||
|  |             final Object[] local, final int nStack, final Object[] stack) { | ||||||
|  |         if (type != Opcodes.F_NEW) { // uncompressed frame | ||||||
|  |             throw new IllegalStateException( | ||||||
|  |                     "ClassReader.accept() should be called with EXPAND_FRAMES flag"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitFrame(type, nLocal, local, nStack, stack); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (this.locals != null) { | ||||||
|  |             this.locals.clear(); | ||||||
|  |             this.stack.clear(); | ||||||
|  |         } else { | ||||||
|  |             this.locals = new ArrayList<Object>(); | ||||||
|  |             this.stack = new ArrayList<Object>(); | ||||||
|  |         } | ||||||
|  |         visitFrameTypes(nLocal, local, this.locals); | ||||||
|  |         visitFrameTypes(nStack, stack, this.stack); | ||||||
|  |         maxStack = Math.max(maxStack, this.stack.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static void visitFrameTypes(final int n, final Object[] types, | ||||||
|  |             final List<Object> result) { | ||||||
|  |         for (int i = 0; i < n; ++i) { | ||||||
|  |             Object type = types[i]; | ||||||
|  |             result.add(type); | ||||||
|  |             if (type == Opcodes.LONG || type == Opcodes.DOUBLE) { | ||||||
|  |                 result.add(Opcodes.TOP); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInsn(final int opcode) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitInsn(opcode); | ||||||
|  |         } | ||||||
|  |         execute(opcode, 0, null); | ||||||
|  |         if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) | ||||||
|  |                 || opcode == Opcodes.ATHROW) { | ||||||
|  |             this.locals = null; | ||||||
|  |             this.stack = null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitIntInsn(final int opcode, final int operand) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitIntInsn(opcode, operand); | ||||||
|  |         } | ||||||
|  |         execute(opcode, operand, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitVarInsn(final int opcode, final int var) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitVarInsn(opcode, var); | ||||||
|  |         } | ||||||
|  |         execute(opcode, var, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeInsn(final int opcode, final String type) { | ||||||
|  |         if (opcode == Opcodes.NEW) { | ||||||
|  |             if (labels == null) { | ||||||
|  |                 Label l = new Label(); | ||||||
|  |                 labels = new ArrayList<Label>(3); | ||||||
|  |                 labels.add(l); | ||||||
|  |                 if (mv != null) { | ||||||
|  |                     mv.visitLabel(l); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             for (int i = 0; i < labels.size(); ++i) { | ||||||
|  |                 uninitializedTypes.put(labels.get(i), type); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTypeInsn(opcode, type); | ||||||
|  |         } | ||||||
|  |         execute(opcode, 0, type); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFieldInsn(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitFieldInsn(opcode, owner, name, desc); | ||||||
|  |         } | ||||||
|  |         execute(opcode, 0, desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMethodInsn(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMethodInsn(opcode, owner, name, desc); | ||||||
|  |         } | ||||||
|  |         if (this.locals == null) { | ||||||
|  |             labels = null; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         pop(desc); | ||||||
|  |         if (opcode != Opcodes.INVOKESTATIC) { | ||||||
|  |             Object t = pop(); | ||||||
|  |             if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') { | ||||||
|  |                 Object u; | ||||||
|  |                 if (t == Opcodes.UNINITIALIZED_THIS) { | ||||||
|  |                     u = this.owner; | ||||||
|  |                 } else { | ||||||
|  |                     u = uninitializedTypes.get(t); | ||||||
|  |                 } | ||||||
|  |                 for (int i = 0; i < locals.size(); ++i) { | ||||||
|  |                     if (locals.get(i) == t) { | ||||||
|  |                         locals.set(i, u); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 for (int i = 0; i < stack.size(); ++i) { | ||||||
|  |                     if (stack.get(i) == t) { | ||||||
|  |                         stack.set(i, u); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         pushDesc(desc); | ||||||
|  |         labels = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, | ||||||
|  |             Object... bsmArgs) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); | ||||||
|  |         } | ||||||
|  |         if (this.locals == null) { | ||||||
|  |             labels = null; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         pop(desc); | ||||||
|  |         pushDesc(desc); | ||||||
|  |         labels = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitJumpInsn(final int opcode, final Label label) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitJumpInsn(opcode, label); | ||||||
|  |         } | ||||||
|  |         execute(opcode, 0, null); | ||||||
|  |         if (opcode == Opcodes.GOTO) { | ||||||
|  |             this.locals = null; | ||||||
|  |             this.stack = null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLabel(final Label label) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLabel(label); | ||||||
|  |         } | ||||||
|  |         if (labels == null) { | ||||||
|  |             labels = new ArrayList<Label>(3); | ||||||
|  |         } | ||||||
|  |         labels.add(label); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLdcInsn(final Object cst) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLdcInsn(cst); | ||||||
|  |         } | ||||||
|  |         if (this.locals == null) { | ||||||
|  |             labels = null; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if (cst instanceof Integer) { | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |         } else if (cst instanceof Long) { | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |         } else if (cst instanceof Float) { | ||||||
|  |             push(Opcodes.FLOAT); | ||||||
|  |         } else if (cst instanceof Double) { | ||||||
|  |             push(Opcodes.DOUBLE); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |         } else if (cst instanceof String) { | ||||||
|  |             push("java/lang/String"); | ||||||
|  |         } else if (cst instanceof Type) { | ||||||
|  |             int sort = ((Type) cst).getSort(); | ||||||
|  |             if (sort == Type.OBJECT || sort == Type.ARRAY) { | ||||||
|  |                 push("java/lang/Class"); | ||||||
|  |             } else if (sort == Type.METHOD) { | ||||||
|  |                 push("java/lang/invoke/MethodType"); | ||||||
|  |             } else { | ||||||
|  |                 throw new IllegalArgumentException(); | ||||||
|  |             } | ||||||
|  |         } else if (cst instanceof Handle) { | ||||||
|  |             push("java/lang/invoke/MethodHandle"); | ||||||
|  |         } else { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         labels = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitIincInsn(final int var, final int increment) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitIincInsn(var, increment); | ||||||
|  |         } | ||||||
|  |         execute(Opcodes.IINC, var, null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTableSwitchInsn(final int min, final int max, | ||||||
|  |             final Label dflt, final Label... labels) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTableSwitchInsn(min, max, dflt, labels); | ||||||
|  |         } | ||||||
|  |         execute(Opcodes.TABLESWITCH, 0, null); | ||||||
|  |         this.locals = null; | ||||||
|  |         this.stack = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLookupSwitchInsn(final Label dflt, final int[] keys, | ||||||
|  |             final Label[] labels) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLookupSwitchInsn(dflt, keys, labels); | ||||||
|  |         } | ||||||
|  |         execute(Opcodes.LOOKUPSWITCH, 0, null); | ||||||
|  |         this.locals = null; | ||||||
|  |         this.stack = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMultiANewArrayInsn(final String desc, final int dims) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMultiANewArrayInsn(desc, dims); | ||||||
|  |         } | ||||||
|  |         execute(Opcodes.MULTIANEWARRAY, dims, desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMaxs(final int maxStack, final int maxLocals) { | ||||||
|  |         if (mv != null) { | ||||||
|  |             this.maxStack = Math.max(this.maxStack, maxStack); | ||||||
|  |             this.maxLocals = Math.max(this.maxLocals, maxLocals); | ||||||
|  |             mv.visitMaxs(this.maxStack, this.maxLocals); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     private Object get(final int local) { | ||||||
|  |         maxLocals = Math.max(maxLocals, local); | ||||||
|  |         return local < locals.size() ? locals.get(local) : Opcodes.TOP; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void set(final int local, final Object type) { | ||||||
|  |         maxLocals = Math.max(maxLocals, local); | ||||||
|  |         while (local >= locals.size()) { | ||||||
|  |             locals.add(Opcodes.TOP); | ||||||
|  |         } | ||||||
|  |         locals.set(local, type); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void push(final Object type) { | ||||||
|  |         stack.add(type); | ||||||
|  |         maxStack = Math.max(maxStack, stack.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void pushDesc(final String desc) { | ||||||
|  |         int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; | ||||||
|  |         switch (desc.charAt(index)) { | ||||||
|  |         case 'V': | ||||||
|  |             return; | ||||||
|  |         case 'Z': | ||||||
|  |         case 'C': | ||||||
|  |         case 'B': | ||||||
|  |         case 'S': | ||||||
|  |         case 'I': | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |             return; | ||||||
|  |         case 'F': | ||||||
|  |             push(Opcodes.FLOAT); | ||||||
|  |             return; | ||||||
|  |         case 'J': | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             return; | ||||||
|  |         case 'D': | ||||||
|  |             push(Opcodes.DOUBLE); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             return; | ||||||
|  |         case '[': | ||||||
|  |             if (index == 0) { | ||||||
|  |                 push(desc); | ||||||
|  |             } else { | ||||||
|  |                 push(desc.substring(index, desc.length())); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         // case 'L': | ||||||
|  |         default: | ||||||
|  |             if (index == 0) { | ||||||
|  |                 push(desc.substring(1, desc.length() - 1)); | ||||||
|  |             } else { | ||||||
|  |                 push(desc.substring(index + 1, desc.length() - 1)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Object pop() { | ||||||
|  |         return stack.remove(stack.size() - 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void pop(final int n) { | ||||||
|  |         int size = stack.size(); | ||||||
|  |         int end = size - n; | ||||||
|  |         for (int i = size - 1; i >= end; --i) { | ||||||
|  |             stack.remove(i); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void pop(final String desc) { | ||||||
|  |         char c = desc.charAt(0); | ||||||
|  |         if (c == '(') { | ||||||
|  |             int n = 0; | ||||||
|  |             Type[] types = Type.getArgumentTypes(desc); | ||||||
|  |             for (int i = 0; i < types.length; ++i) { | ||||||
|  |                 n += types[i].getSize(); | ||||||
|  |             } | ||||||
|  |             pop(n); | ||||||
|  |         } else if (c == 'J' || c == 'D') { | ||||||
|  |             pop(2); | ||||||
|  |         } else { | ||||||
|  |             pop(1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void execute(final int opcode, final int iarg, final String sarg) { | ||||||
|  |         if (this.locals == null) { | ||||||
|  |             labels = null; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         Object t1, t2, t3, t4; | ||||||
|  |         switch (opcode) { | ||||||
|  |         case Opcodes.NOP: | ||||||
|  |         case Opcodes.INEG: | ||||||
|  |         case Opcodes.LNEG: | ||||||
|  |         case Opcodes.FNEG: | ||||||
|  |         case Opcodes.DNEG: | ||||||
|  |         case Opcodes.I2B: | ||||||
|  |         case Opcodes.I2C: | ||||||
|  |         case Opcodes.I2S: | ||||||
|  |         case Opcodes.GOTO: | ||||||
|  |         case Opcodes.RETURN: | ||||||
|  |             break; | ||||||
|  |         case Opcodes.ACONST_NULL: | ||||||
|  |             push(Opcodes.NULL); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.ICONST_M1: | ||||||
|  |         case Opcodes.ICONST_0: | ||||||
|  |         case Opcodes.ICONST_1: | ||||||
|  |         case Opcodes.ICONST_2: | ||||||
|  |         case Opcodes.ICONST_3: | ||||||
|  |         case Opcodes.ICONST_4: | ||||||
|  |         case Opcodes.ICONST_5: | ||||||
|  |         case Opcodes.BIPUSH: | ||||||
|  |         case Opcodes.SIPUSH: | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LCONST_0: | ||||||
|  |         case Opcodes.LCONST_1: | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.FCONST_0: | ||||||
|  |         case Opcodes.FCONST_1: | ||||||
|  |         case Opcodes.FCONST_2: | ||||||
|  |             push(Opcodes.FLOAT); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DCONST_0: | ||||||
|  |         case Opcodes.DCONST_1: | ||||||
|  |             push(Opcodes.DOUBLE); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.ILOAD: | ||||||
|  |         case Opcodes.FLOAD: | ||||||
|  |         case Opcodes.ALOAD: | ||||||
|  |             push(get(iarg)); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LLOAD: | ||||||
|  |         case Opcodes.DLOAD: | ||||||
|  |             push(get(iarg)); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.IALOAD: | ||||||
|  |         case Opcodes.BALOAD: | ||||||
|  |         case Opcodes.CALOAD: | ||||||
|  |         case Opcodes.SALOAD: | ||||||
|  |             pop(2); | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LALOAD: | ||||||
|  |         case Opcodes.D2L: | ||||||
|  |             pop(2); | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.FALOAD: | ||||||
|  |             pop(2); | ||||||
|  |             push(Opcodes.FLOAT); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DALOAD: | ||||||
|  |         case Opcodes.L2D: | ||||||
|  |             pop(2); | ||||||
|  |             push(Opcodes.DOUBLE); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.AALOAD: | ||||||
|  |             pop(1); | ||||||
|  |             t1 = pop(); | ||||||
|  |             if (t1 instanceof String) { | ||||||
|  |                 pushDesc(((String) t1).substring(1)); | ||||||
|  |             } else { | ||||||
|  |                 push("java/lang/Object"); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case Opcodes.ISTORE: | ||||||
|  |         case Opcodes.FSTORE: | ||||||
|  |         case Opcodes.ASTORE: | ||||||
|  |             t1 = pop(); | ||||||
|  |             set(iarg, t1); | ||||||
|  |             if (iarg > 0) { | ||||||
|  |                 t2 = get(iarg - 1); | ||||||
|  |                 if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { | ||||||
|  |                     set(iarg - 1, Opcodes.TOP); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LSTORE: | ||||||
|  |         case Opcodes.DSTORE: | ||||||
|  |             pop(1); | ||||||
|  |             t1 = pop(); | ||||||
|  |             set(iarg, t1); | ||||||
|  |             set(iarg + 1, Opcodes.TOP); | ||||||
|  |             if (iarg > 0) { | ||||||
|  |                 t2 = get(iarg - 1); | ||||||
|  |                 if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { | ||||||
|  |                     set(iarg - 1, Opcodes.TOP); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case Opcodes.IASTORE: | ||||||
|  |         case Opcodes.BASTORE: | ||||||
|  |         case Opcodes.CASTORE: | ||||||
|  |         case Opcodes.SASTORE: | ||||||
|  |         case Opcodes.FASTORE: | ||||||
|  |         case Opcodes.AASTORE: | ||||||
|  |             pop(3); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LASTORE: | ||||||
|  |         case Opcodes.DASTORE: | ||||||
|  |             pop(4); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.POP: | ||||||
|  |         case Opcodes.IFEQ: | ||||||
|  |         case Opcodes.IFNE: | ||||||
|  |         case Opcodes.IFLT: | ||||||
|  |         case Opcodes.IFGE: | ||||||
|  |         case Opcodes.IFGT: | ||||||
|  |         case Opcodes.IFLE: | ||||||
|  |         case Opcodes.IRETURN: | ||||||
|  |         case Opcodes.FRETURN: | ||||||
|  |         case Opcodes.ARETURN: | ||||||
|  |         case Opcodes.TABLESWITCH: | ||||||
|  |         case Opcodes.LOOKUPSWITCH: | ||||||
|  |         case Opcodes.ATHROW: | ||||||
|  |         case Opcodes.MONITORENTER: | ||||||
|  |         case Opcodes.MONITOREXIT: | ||||||
|  |         case Opcodes.IFNULL: | ||||||
|  |         case Opcodes.IFNONNULL: | ||||||
|  |             pop(1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.POP2: | ||||||
|  |         case Opcodes.IF_ICMPEQ: | ||||||
|  |         case Opcodes.IF_ICMPNE: | ||||||
|  |         case Opcodes.IF_ICMPLT: | ||||||
|  |         case Opcodes.IF_ICMPGE: | ||||||
|  |         case Opcodes.IF_ICMPGT: | ||||||
|  |         case Opcodes.IF_ICMPLE: | ||||||
|  |         case Opcodes.IF_ACMPEQ: | ||||||
|  |         case Opcodes.IF_ACMPNE: | ||||||
|  |         case Opcodes.LRETURN: | ||||||
|  |         case Opcodes.DRETURN: | ||||||
|  |             pop(2); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DUP: | ||||||
|  |             t1 = pop(); | ||||||
|  |             push(t1); | ||||||
|  |             push(t1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DUP_X1: | ||||||
|  |             t1 = pop(); | ||||||
|  |             t2 = pop(); | ||||||
|  |             push(t1); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DUP_X2: | ||||||
|  |             t1 = pop(); | ||||||
|  |             t2 = pop(); | ||||||
|  |             t3 = pop(); | ||||||
|  |             push(t1); | ||||||
|  |             push(t3); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DUP2: | ||||||
|  |             t1 = pop(); | ||||||
|  |             t2 = pop(); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DUP2_X1: | ||||||
|  |             t1 = pop(); | ||||||
|  |             t2 = pop(); | ||||||
|  |             t3 = pop(); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             push(t3); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DUP2_X2: | ||||||
|  |             t1 = pop(); | ||||||
|  |             t2 = pop(); | ||||||
|  |             t3 = pop(); | ||||||
|  |             t4 = pop(); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             push(t4); | ||||||
|  |             push(t3); | ||||||
|  |             push(t2); | ||||||
|  |             push(t1); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.SWAP: | ||||||
|  |             t1 = pop(); | ||||||
|  |             t2 = pop(); | ||||||
|  |             push(t1); | ||||||
|  |             push(t2); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.IADD: | ||||||
|  |         case Opcodes.ISUB: | ||||||
|  |         case Opcodes.IMUL: | ||||||
|  |         case Opcodes.IDIV: | ||||||
|  |         case Opcodes.IREM: | ||||||
|  |         case Opcodes.IAND: | ||||||
|  |         case Opcodes.IOR: | ||||||
|  |         case Opcodes.IXOR: | ||||||
|  |         case Opcodes.ISHL: | ||||||
|  |         case Opcodes.ISHR: | ||||||
|  |         case Opcodes.IUSHR: | ||||||
|  |         case Opcodes.L2I: | ||||||
|  |         case Opcodes.D2I: | ||||||
|  |         case Opcodes.FCMPL: | ||||||
|  |         case Opcodes.FCMPG: | ||||||
|  |             pop(2); | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LADD: | ||||||
|  |         case Opcodes.LSUB: | ||||||
|  |         case Opcodes.LMUL: | ||||||
|  |         case Opcodes.LDIV: | ||||||
|  |         case Opcodes.LREM: | ||||||
|  |         case Opcodes.LAND: | ||||||
|  |         case Opcodes.LOR: | ||||||
|  |         case Opcodes.LXOR: | ||||||
|  |             pop(4); | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.FADD: | ||||||
|  |         case Opcodes.FSUB: | ||||||
|  |         case Opcodes.FMUL: | ||||||
|  |         case Opcodes.FDIV: | ||||||
|  |         case Opcodes.FREM: | ||||||
|  |         case Opcodes.L2F: | ||||||
|  |         case Opcodes.D2F: | ||||||
|  |             pop(2); | ||||||
|  |             push(Opcodes.FLOAT); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.DADD: | ||||||
|  |         case Opcodes.DSUB: | ||||||
|  |         case Opcodes.DMUL: | ||||||
|  |         case Opcodes.DDIV: | ||||||
|  |         case Opcodes.DREM: | ||||||
|  |             pop(4); | ||||||
|  |             push(Opcodes.DOUBLE); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LSHL: | ||||||
|  |         case Opcodes.LSHR: | ||||||
|  |         case Opcodes.LUSHR: | ||||||
|  |             pop(3); | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.IINC: | ||||||
|  |             set(iarg, Opcodes.INTEGER); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.I2L: | ||||||
|  |         case Opcodes.F2L: | ||||||
|  |             pop(1); | ||||||
|  |             push(Opcodes.LONG); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.I2F: | ||||||
|  |             pop(1); | ||||||
|  |             push(Opcodes.FLOAT); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.I2D: | ||||||
|  |         case Opcodes.F2D: | ||||||
|  |             pop(1); | ||||||
|  |             push(Opcodes.DOUBLE); | ||||||
|  |             push(Opcodes.TOP); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F2I: | ||||||
|  |         case Opcodes.ARRAYLENGTH: | ||||||
|  |         case Opcodes.INSTANCEOF: | ||||||
|  |             pop(1); | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.LCMP: | ||||||
|  |         case Opcodes.DCMPL: | ||||||
|  |         case Opcodes.DCMPG: | ||||||
|  |             pop(4); | ||||||
|  |             push(Opcodes.INTEGER); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.JSR: | ||||||
|  |         case Opcodes.RET: | ||||||
|  |             throw new RuntimeException("JSR/RET are not supported"); | ||||||
|  |         case Opcodes.GETSTATIC: | ||||||
|  |             pushDesc(sarg); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.PUTSTATIC: | ||||||
|  |             pop(sarg); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.GETFIELD: | ||||||
|  |             pop(1); | ||||||
|  |             pushDesc(sarg); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.PUTFIELD: | ||||||
|  |             pop(sarg); | ||||||
|  |             pop(); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.NEW: | ||||||
|  |             push(labels.get(0)); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.NEWARRAY: | ||||||
|  |             pop(); | ||||||
|  |             switch (iarg) { | ||||||
|  |             case Opcodes.T_BOOLEAN: | ||||||
|  |                 pushDesc("[Z"); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.T_CHAR: | ||||||
|  |                 pushDesc("[C"); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.T_BYTE: | ||||||
|  |                 pushDesc("[B"); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.T_SHORT: | ||||||
|  |                 pushDesc("[S"); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.T_INT: | ||||||
|  |                 pushDesc("[I"); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.T_FLOAT: | ||||||
|  |                 pushDesc("[F"); | ||||||
|  |                 break; | ||||||
|  |             case Opcodes.T_DOUBLE: | ||||||
|  |                 pushDesc("[D"); | ||||||
|  |                 break; | ||||||
|  |             // case Opcodes.T_LONG: | ||||||
|  |             default: | ||||||
|  |                 pushDesc("[J"); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case Opcodes.ANEWARRAY: | ||||||
|  |             pop(); | ||||||
|  |             pushDesc("[" + Type.getObjectType(sarg)); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.CHECKCAST: | ||||||
|  |             pop(); | ||||||
|  |             pushDesc(Type.getObjectType(sarg).getDescriptor()); | ||||||
|  |             break; | ||||||
|  |         // case Opcodes.MULTIANEWARRAY: | ||||||
|  |         default: | ||||||
|  |             pop(iarg); | ||||||
|  |             pushDesc(sarg); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         labels = null; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										217
									
								
								src/main/asm/org/objectweb/asm/commons/CodeSizeEvaluator.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								src/main/asm/org/objectweb/asm/commons/CodeSizeEvaluator.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,217 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link MethodVisitor} that can be used to approximate method size. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { | ||||||
|  | 
 | ||||||
|  |     private int minSize; | ||||||
|  | 
 | ||||||
|  |     private int maxSize; | ||||||
|  | 
 | ||||||
|  |     public CodeSizeEvaluator(final MethodVisitor mv) { | ||||||
|  |         this(Opcodes.ASM4, mv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { | ||||||
|  |         super(api, mv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getMinSize() { | ||||||
|  |         return this.minSize; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getMaxSize() { | ||||||
|  |         return this.maxSize; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInsn(final int opcode) { | ||||||
|  |         minSize += 1; | ||||||
|  |         maxSize += 1; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitInsn(opcode); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitIntInsn(final int opcode, final int operand) { | ||||||
|  |         if (opcode == SIPUSH) { | ||||||
|  |             minSize += 3; | ||||||
|  |             maxSize += 3; | ||||||
|  |         } else { | ||||||
|  |             minSize += 2; | ||||||
|  |             maxSize += 2; | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitIntInsn(opcode, operand); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitVarInsn(final int opcode, final int var) { | ||||||
|  |         if (var < 4 && opcode != RET) { | ||||||
|  |             minSize += 1; | ||||||
|  |             maxSize += 1; | ||||||
|  |         } else if (var >= 256) { | ||||||
|  |             minSize += 4; | ||||||
|  |             maxSize += 4; | ||||||
|  |         } else { | ||||||
|  |             minSize += 2; | ||||||
|  |             maxSize += 2; | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitVarInsn(opcode, var); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeInsn(final int opcode, final String type) { | ||||||
|  |         minSize += 3; | ||||||
|  |         maxSize += 3; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTypeInsn(opcode, type); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFieldInsn(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         minSize += 3; | ||||||
|  |         maxSize += 3; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitFieldInsn(opcode, owner, name, desc); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMethodInsn(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         if (opcode == INVOKEINTERFACE) { | ||||||
|  |             minSize += 5; | ||||||
|  |             maxSize += 5; | ||||||
|  |         } else { | ||||||
|  |             minSize += 3; | ||||||
|  |             maxSize += 3; | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMethodInsn(opcode, owner, name, desc); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, | ||||||
|  |             Object... bsmArgs) { | ||||||
|  |         minSize += 5; | ||||||
|  |         maxSize += 5; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitJumpInsn(final int opcode, final Label label) { | ||||||
|  |         minSize += 3; | ||||||
|  |         if (opcode == GOTO || opcode == JSR) { | ||||||
|  |             maxSize += 5; | ||||||
|  |         } else { | ||||||
|  |             maxSize += 8; | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitJumpInsn(opcode, label); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLdcInsn(final Object cst) { | ||||||
|  |         if (cst instanceof Long || cst instanceof Double) { | ||||||
|  |             minSize += 3; | ||||||
|  |             maxSize += 3; | ||||||
|  |         } else { | ||||||
|  |             minSize += 2; | ||||||
|  |             maxSize += 3; | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLdcInsn(cst); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitIincInsn(final int var, final int increment) { | ||||||
|  |         if (var > 255 || increment > 127 || increment < -128) { | ||||||
|  |             minSize += 6; | ||||||
|  |             maxSize += 6; | ||||||
|  |         } else { | ||||||
|  |             minSize += 3; | ||||||
|  |             maxSize += 3; | ||||||
|  |         } | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitIincInsn(var, increment); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTableSwitchInsn(final int min, final int max, | ||||||
|  |             final Label dflt, final Label... labels) { | ||||||
|  |         minSize += 13 + labels.length * 4; | ||||||
|  |         maxSize += 16 + labels.length * 4; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitTableSwitchInsn(min, max, dflt, labels); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLookupSwitchInsn(final Label dflt, final int[] keys, | ||||||
|  |             final Label[] labels) { | ||||||
|  |         minSize += 9 + keys.length * 8; | ||||||
|  |         maxSize += 12 + keys.length * 8; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitLookupSwitchInsn(dflt, keys, labels); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMultiANewArrayInsn(final String desc, final int dims) { | ||||||
|  |         minSize += 4; | ||||||
|  |         maxSize += 4; | ||||||
|  |         if (mv != null) { | ||||||
|  |             mv.visitMultiANewArrayInsn(desc, dims); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1623
									
								
								src/main/asm/org/objectweb/asm/commons/GeneratorAdapter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1623
									
								
								src/main/asm/org/objectweb/asm/commons/GeneratorAdapter.java
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1090
									
								
								src/main/asm/org/objectweb/asm/commons/InstructionAdapter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1090
									
								
								src/main/asm/org/objectweb/asm/commons/InstructionAdapter.java
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										747
									
								
								src/main/asm/org/objectweb/asm/commons/JSRInlinerAdapter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										747
									
								
								src/main/asm/org/objectweb/asm/commons/JSRInlinerAdapter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,747 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import java.util.AbstractMap; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.BitSet; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Iterator; | ||||||
|  | import java.util.LinkedList; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Set; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | import org.objectweb.asm.tree.AbstractInsnNode; | ||||||
|  | import org.objectweb.asm.tree.InsnList; | ||||||
|  | import org.objectweb.asm.tree.InsnNode; | ||||||
|  | import org.objectweb.asm.tree.JumpInsnNode; | ||||||
|  | import org.objectweb.asm.tree.LabelNode; | ||||||
|  | import org.objectweb.asm.tree.LocalVariableNode; | ||||||
|  | import org.objectweb.asm.tree.LookupSwitchInsnNode; | ||||||
|  | import org.objectweb.asm.tree.MethodNode; | ||||||
|  | import org.objectweb.asm.tree.TableSwitchInsnNode; | ||||||
|  | import org.objectweb.asm.tree.TryCatchBlockNode; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link org.objectweb.asm.MethodVisitor} that removes JSR instructions and | ||||||
|  |  * inlines the referenced subroutines. | ||||||
|  |  *  | ||||||
|  |  * <b>Explanation of how it works</b> TODO | ||||||
|  |  *  | ||||||
|  |  * @author Niko Matsakis | ||||||
|  |  */ | ||||||
|  | public class JSRInlinerAdapter extends MethodNode implements Opcodes { | ||||||
|  | 
 | ||||||
|  |     private static final boolean LOGGING = false; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * For each label that is jumped to by a JSR, we create a BitSet instance. | ||||||
|  |      */ | ||||||
|  |     private final Map<LabelNode, BitSet> subroutineHeads = new HashMap<LabelNode, BitSet>(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * This subroutine instance denotes the line of execution that is not | ||||||
|  |      * contained within any subroutine; i.e., the "subroutine" that is executing | ||||||
|  |      * when a method first begins. | ||||||
|  |      */ | ||||||
|  |     private final BitSet mainSubroutine = new BitSet(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * This BitSet contains the index of every instruction that belongs to more | ||||||
|  |      * than one subroutine. This should not happen often. | ||||||
|  |      */ | ||||||
|  |     final BitSet dualCitizens = new BitSet(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new JSRInliner. <i>Subclasses must not use this | ||||||
|  |      * constructor</i>. Instead, they must use the | ||||||
|  |      * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])} | ||||||
|  |      * version. | ||||||
|  |      *  | ||||||
|  |      * @param mv | ||||||
|  |      *            the <code>MethodVisitor</code> to send the resulting inlined | ||||||
|  |      *            method code to (use <code>null</code> for none). | ||||||
|  |      * @param access | ||||||
|  |      *            the method's access flags (see {@link Opcodes}). This | ||||||
|  |      *            parameter also indicates if the method is synthetic and/or | ||||||
|  |      *            deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the method's signature. May be <tt>null</tt>. | ||||||
|  |      * @param exceptions | ||||||
|  |      *            the internal names of the method's exception classes (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). May be | ||||||
|  |      *            <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public JSRInlinerAdapter(final MethodVisitor mv, final int access, | ||||||
|  |             final String name, final String desc, final String signature, | ||||||
|  |             final String[] exceptions) { | ||||||
|  |         this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new JSRInliner. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param mv | ||||||
|  |      *            the <code>MethodVisitor</code> to send the resulting inlined | ||||||
|  |      *            method code to (use <code>null</code> for none). | ||||||
|  |      * @param access | ||||||
|  |      *            the method's access flags (see {@link Opcodes}). This | ||||||
|  |      *            parameter also indicates if the method is synthetic and/or | ||||||
|  |      *            deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the method's signature. May be <tt>null</tt>. | ||||||
|  |      * @param exceptions | ||||||
|  |      *            the internal names of the method's exception classes (see | ||||||
|  |      *            {@link Type#getInternalName() getInternalName}). May be | ||||||
|  |      *            <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     protected JSRInlinerAdapter(final int api, final MethodVisitor mv, | ||||||
|  |             final int access, final String name, final String desc, | ||||||
|  |             final String signature, final String[] exceptions) { | ||||||
|  |         super(api, access, name, desc, signature, exceptions); | ||||||
|  |         this.mv = mv; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Detects a JSR instruction and sets a flag to indicate we will need to do | ||||||
|  |      * inlining. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void visitJumpInsn(final int opcode, final Label lbl) { | ||||||
|  |         super.visitJumpInsn(opcode, lbl); | ||||||
|  |         LabelNode ln = ((JumpInsnNode) instructions.getLast()).label; | ||||||
|  |         if (opcode == JSR && !subroutineHeads.containsKey(ln)) { | ||||||
|  |             subroutineHeads.put(ln, new BitSet()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * If any JSRs were seen, triggers the inlining process. Otherwise, forwards | ||||||
|  |      * the byte codes untouched. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (!subroutineHeads.isEmpty()) { | ||||||
|  |             markSubroutines(); | ||||||
|  |             if (LOGGING) { | ||||||
|  |                 log(mainSubroutine.toString()); | ||||||
|  |                 Iterator<BitSet> it = subroutineHeads.values().iterator(); | ||||||
|  |                 while (it.hasNext()) { | ||||||
|  |                     BitSet sub = it.next(); | ||||||
|  |                     log(sub.toString()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             emitCode(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Forward the translate opcodes on if appropriate: | ||||||
|  |         if (mv != null) { | ||||||
|  |             accept(mv); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Walks the method and determines which internal subroutine(s), if any, | ||||||
|  |      * each instruction is a method of. | ||||||
|  |      */ | ||||||
|  |     private void markSubroutines() { | ||||||
|  |         BitSet anyvisited = new BitSet(); | ||||||
|  | 
 | ||||||
|  |         // First walk the main subroutine and find all those instructions which | ||||||
|  |         // can be reached without invoking any JSR at all | ||||||
|  |         markSubroutineWalk(mainSubroutine, 0, anyvisited); | ||||||
|  | 
 | ||||||
|  |         // Go through the head of each subroutine and find any nodes reachable | ||||||
|  |         // to that subroutine without following any JSR links. | ||||||
|  |         for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads | ||||||
|  |                 .entrySet().iterator(); it.hasNext();) { | ||||||
|  |             Map.Entry<LabelNode, BitSet> entry = it.next(); | ||||||
|  |             LabelNode lab = entry.getKey(); | ||||||
|  |             BitSet sub = entry.getValue(); | ||||||
|  |             int index = instructions.indexOf(lab); | ||||||
|  |             markSubroutineWalk(sub, index, anyvisited); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Performs a depth first search walking the normal byte code path starting | ||||||
|  |      * at <code>index</code>, and adding each instruction encountered into the | ||||||
|  |      * subroutine <code>sub</code>. After this walk is complete, iterates over | ||||||
|  |      * the exception handlers to ensure that we also include those byte codes | ||||||
|  |      * which are reachable through an exception that may be thrown during the | ||||||
|  |      * execution of the subroutine. Invoked from <code>markSubroutines()</code>. | ||||||
|  |      *  | ||||||
|  |      * @param sub | ||||||
|  |      *            the subroutine whose instructions must be computed. | ||||||
|  |      * @param index | ||||||
|  |      *            an instruction of this subroutine. | ||||||
|  |      * @param anyvisited | ||||||
|  |      *            indexes of the already visited instructions, i.e. marked as | ||||||
|  |      *            part of this subroutine or any previously computed subroutine. | ||||||
|  |      */ | ||||||
|  |     private void markSubroutineWalk(final BitSet sub, final int index, | ||||||
|  |             final BitSet anyvisited) { | ||||||
|  |         if (LOGGING) { | ||||||
|  |             log("markSubroutineWalk: sub=" + sub + " index=" + index); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // First find those instructions reachable via normal execution | ||||||
|  |         markSubroutineWalkDFS(sub, index, anyvisited); | ||||||
|  | 
 | ||||||
|  |         // Now, make sure we also include any applicable exception handlers | ||||||
|  |         boolean loop = true; | ||||||
|  |         while (loop) { | ||||||
|  |             loop = false; | ||||||
|  |             for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it | ||||||
|  |                     .hasNext();) { | ||||||
|  |                 TryCatchBlockNode trycatch = it.next(); | ||||||
|  | 
 | ||||||
|  |                 if (LOGGING) { | ||||||
|  |                     // TODO use of default toString(). | ||||||
|  |                     log("Scanning try/catch " + trycatch); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 // If the handler has already been processed, skip it. | ||||||
|  |                 int handlerindex = instructions.indexOf(trycatch.handler); | ||||||
|  |                 if (sub.get(handlerindex)) { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 int startindex = instructions.indexOf(trycatch.start); | ||||||
|  |                 int endindex = instructions.indexOf(trycatch.end); | ||||||
|  |                 int nextbit = sub.nextSetBit(startindex); | ||||||
|  |                 if (nextbit != -1 && nextbit < endindex) { | ||||||
|  |                     if (LOGGING) { | ||||||
|  |                         log("Adding exception handler: " + startindex + '-' | ||||||
|  |                                 + endindex + " due to " + nextbit + " handler " | ||||||
|  |                                 + handlerindex); | ||||||
|  |                     } | ||||||
|  |                     markSubroutineWalkDFS(sub, handlerindex, anyvisited); | ||||||
|  |                     loop = true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Performs a simple DFS of the instructions, assigning each to the | ||||||
|  |      * subroutine <code>sub</code>. Starts from <code>index</code>. Invoked only | ||||||
|  |      * by <code>markSubroutineWalk()</code>. | ||||||
|  |      *  | ||||||
|  |      * @param sub | ||||||
|  |      *            the subroutine whose instructions must be computed. | ||||||
|  |      * @param index | ||||||
|  |      *            an instruction of this subroutine. | ||||||
|  |      * @param anyvisited | ||||||
|  |      *            indexes of the already visited instructions, i.e. marked as | ||||||
|  |      *            part of this subroutine or any previously computed subroutine. | ||||||
|  |      */ | ||||||
|  |     private void markSubroutineWalkDFS(final BitSet sub, int index, | ||||||
|  |             final BitSet anyvisited) { | ||||||
|  |         while (true) { | ||||||
|  |             AbstractInsnNode node = instructions.get(index); | ||||||
|  | 
 | ||||||
|  |             // don't visit a node twice | ||||||
|  |             if (sub.get(index)) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             sub.set(index); | ||||||
|  | 
 | ||||||
|  |             // check for those nodes already visited by another subroutine | ||||||
|  |             if (anyvisited.get(index)) { | ||||||
|  |                 dualCitizens.set(index); | ||||||
|  |                 if (LOGGING) { | ||||||
|  |                     log("Instruction #" + index + " is dual citizen."); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             anyvisited.set(index); | ||||||
|  | 
 | ||||||
|  |             if (node.getType() == AbstractInsnNode.JUMP_INSN | ||||||
|  |                     && node.getOpcode() != JSR) { | ||||||
|  |                 // we do not follow recursively called subroutines here; but any | ||||||
|  |                 // other sort of branch we do follow | ||||||
|  |                 JumpInsnNode jnode = (JumpInsnNode) node; | ||||||
|  |                 int destidx = instructions.indexOf(jnode.label); | ||||||
|  |                 markSubroutineWalkDFS(sub, destidx, anyvisited); | ||||||
|  |             } | ||||||
|  |             if (node.getType() == AbstractInsnNode.TABLESWITCH_INSN) { | ||||||
|  |                 TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node; | ||||||
|  |                 int destidx = instructions.indexOf(tsnode.dflt); | ||||||
|  |                 markSubroutineWalkDFS(sub, destidx, anyvisited); | ||||||
|  |                 for (int i = tsnode.labels.size() - 1; i >= 0; --i) { | ||||||
|  |                     LabelNode l = tsnode.labels.get(i); | ||||||
|  |                     destidx = instructions.indexOf(l); | ||||||
|  |                     markSubroutineWalkDFS(sub, destidx, anyvisited); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if (node.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) { | ||||||
|  |                 LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node; | ||||||
|  |                 int destidx = instructions.indexOf(lsnode.dflt); | ||||||
|  |                 markSubroutineWalkDFS(sub, destidx, anyvisited); | ||||||
|  |                 for (int i = lsnode.labels.size() - 1; i >= 0; --i) { | ||||||
|  |                     LabelNode l = lsnode.labels.get(i); | ||||||
|  |                     destidx = instructions.indexOf(l); | ||||||
|  |                     markSubroutineWalkDFS(sub, destidx, anyvisited); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // check to see if this opcode falls through to the next instruction | ||||||
|  |             // or not; if not, return. | ||||||
|  |             switch (instructions.get(index).getOpcode()) { | ||||||
|  |             case GOTO: | ||||||
|  |             case RET: | ||||||
|  |             case TABLESWITCH: | ||||||
|  |             case LOOKUPSWITCH: | ||||||
|  |             case IRETURN: | ||||||
|  |             case LRETURN: | ||||||
|  |             case FRETURN: | ||||||
|  |             case DRETURN: | ||||||
|  |             case ARETURN: | ||||||
|  |             case RETURN: | ||||||
|  |             case ATHROW: | ||||||
|  |                 /* | ||||||
|  |                  * note: this either returns from this subroutine, or a parent | ||||||
|  |                  * subroutine which invoked it | ||||||
|  |                  */ | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Use tail recursion here in the form of an outer while loop to | ||||||
|  |             // avoid our stack growing needlessly: | ||||||
|  |             index++; | ||||||
|  | 
 | ||||||
|  |             // We implicitly assumed above that execution can always fall | ||||||
|  |             // through to the next instruction after a JSR. But a subroutine may | ||||||
|  |             // never return, in which case the code after the JSR is unreachable | ||||||
|  |             // and can be anything. In particular, it can seem to fall off the | ||||||
|  |             // end of the method, so we must handle this case here (we could | ||||||
|  |             // instead detect whether execution can return or not from a JSR, | ||||||
|  |             // but this is more complicated). | ||||||
|  |             if (index >= instructions.size()) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates the new instructions, inlining each instantiation of each | ||||||
|  |      * subroutine until the code is fully elaborated. | ||||||
|  |      */ | ||||||
|  |     private void emitCode() { | ||||||
|  |         LinkedList<Instantiation> worklist = new LinkedList<Instantiation>(); | ||||||
|  |         // Create an instantiation of the "root" subroutine, which is just the | ||||||
|  |         // main routine | ||||||
|  |         worklist.add(new Instantiation(null, mainSubroutine)); | ||||||
|  | 
 | ||||||
|  |         // Emit instantiations of each subroutine we encounter, including the | ||||||
|  |         // main subroutine | ||||||
|  |         InsnList newInstructions = new InsnList(); | ||||||
|  |         List<TryCatchBlockNode> newTryCatchBlocks = new ArrayList<TryCatchBlockNode>(); | ||||||
|  |         List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>(); | ||||||
|  |         while (!worklist.isEmpty()) { | ||||||
|  |             Instantiation inst = worklist.removeFirst(); | ||||||
|  |             emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks, | ||||||
|  |                     newLocalVariables); | ||||||
|  |         } | ||||||
|  |         instructions = newInstructions; | ||||||
|  |         tryCatchBlocks = newTryCatchBlocks; | ||||||
|  |         localVariables = newLocalVariables; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Emits one instantiation of one subroutine, specified by | ||||||
|  |      * <code>instant</code>. May add new instantiations that are invoked by this | ||||||
|  |      * one to the <code>worklist</code> parameter, and new try/catch blocks to | ||||||
|  |      * <code>newTryCatchBlocks</code>. | ||||||
|  |      *  | ||||||
|  |      * @param instant | ||||||
|  |      *            the instantiation that must be performed. | ||||||
|  |      * @param worklist | ||||||
|  |      *            list of the instantiations that remain to be done. | ||||||
|  |      * @param newInstructions | ||||||
|  |      *            the instruction list to which the instantiated code must be | ||||||
|  |      *            appended. | ||||||
|  |      * @param newTryCatchBlocks | ||||||
|  |      *            the exception handler list to which the instantiated handlers | ||||||
|  |      *            must be appended. | ||||||
|  |      */ | ||||||
|  |     private void emitSubroutine(final Instantiation instant, | ||||||
|  |             final List<Instantiation> worklist, final InsnList newInstructions, | ||||||
|  |             final List<TryCatchBlockNode> newTryCatchBlocks, | ||||||
|  |             final List<LocalVariableNode> newLocalVariables) { | ||||||
|  |         LabelNode duplbl = null; | ||||||
|  | 
 | ||||||
|  |         if (LOGGING) { | ||||||
|  |             log("--------------------------------------------------------"); | ||||||
|  |             log("Emitting instantiation of subroutine " + instant.subroutine); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Emit the relevant instructions for this instantiation, translating | ||||||
|  |         // labels and jump targets as we go: | ||||||
|  |         for (int i = 0, c = instructions.size(); i < c; i++) { | ||||||
|  |             AbstractInsnNode insn = instructions.get(i); | ||||||
|  |             Instantiation owner = instant.findOwner(i); | ||||||
|  | 
 | ||||||
|  |             // Always remap labels: | ||||||
|  |             if (insn.getType() == AbstractInsnNode.LABEL) { | ||||||
|  |                 // Translate labels into their renamed equivalents. | ||||||
|  |                 // Avoid adding the same label more than once. Note | ||||||
|  |                 // that because we own this instruction the gotoTable | ||||||
|  |                 // and the rangeTable will always agree. | ||||||
|  |                 LabelNode ilbl = (LabelNode) insn; | ||||||
|  |                 LabelNode remap = instant.rangeLabel(ilbl); | ||||||
|  |                 if (LOGGING) { | ||||||
|  |                     // TODO use of default toString(). | ||||||
|  |                     log("Translating lbl #" + i + ':' + ilbl + " to " + remap); | ||||||
|  |                 } | ||||||
|  |                 if (remap != duplbl) { | ||||||
|  |                     newInstructions.add(remap); | ||||||
|  |                     duplbl = remap; | ||||||
|  |                 } | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // We don't want to emit instructions that were already | ||||||
|  |             // emitted by a subroutine higher on the stack. Note that | ||||||
|  |             // it is still possible for a given instruction to be | ||||||
|  |             // emitted twice because it may belong to two subroutines | ||||||
|  |             // that do not invoke each other. | ||||||
|  |             if (owner != instant) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (LOGGING) { | ||||||
|  |                 log("Emitting inst #" + i); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (insn.getOpcode() == RET) { | ||||||
|  |                 // Translate RET instruction(s) to a jump to the return label | ||||||
|  |                 // for the appropriate instantiation. The problem is that the | ||||||
|  |                 // subroutine may "fall through" to the ret of a parent | ||||||
|  |                 // subroutine; therefore, to find the appropriate ret label we | ||||||
|  |                 // find the lowest subroutine on the stack that claims to own | ||||||
|  |                 // this instruction. See the class javadoc comment for an | ||||||
|  |                 // explanation on why this technique is safe (note: it is only | ||||||
|  |                 // safe if the input is verifiable). | ||||||
|  |                 LabelNode retlabel = null; | ||||||
|  |                 for (Instantiation p = instant; p != null; p = p.previous) { | ||||||
|  |                     if (p.subroutine.get(i)) { | ||||||
|  |                         retlabel = p.returnLabel; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (retlabel == null) { | ||||||
|  |                     // This is only possible if the mainSubroutine owns a RET | ||||||
|  |                     // instruction, which should never happen for verifiable | ||||||
|  |                     // code. | ||||||
|  |                     throw new RuntimeException("Instruction #" + i | ||||||
|  |                             + " is a RET not owned by any subroutine"); | ||||||
|  |                 } | ||||||
|  |                 newInstructions.add(new JumpInsnNode(GOTO, retlabel)); | ||||||
|  |             } else if (insn.getOpcode() == JSR) { | ||||||
|  |                 LabelNode lbl = ((JumpInsnNode) insn).label; | ||||||
|  |                 BitSet sub = subroutineHeads.get(lbl); | ||||||
|  |                 Instantiation newinst = new Instantiation(instant, sub); | ||||||
|  |                 LabelNode startlbl = newinst.gotoLabel(lbl); | ||||||
|  | 
 | ||||||
|  |                 if (LOGGING) { | ||||||
|  |                     log(" Creating instantiation of subr " + sub); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 // Rather than JSRing, we will jump to the inline version and | ||||||
|  |                 // push NULL for what was once the return value. This hack | ||||||
|  |                 // allows us to avoid doing any sort of data flow analysis to | ||||||
|  |                 // figure out which instructions manipulate the old return value | ||||||
|  |                 // pointer which is now known to be unneeded. | ||||||
|  |                 newInstructions.add(new InsnNode(ACONST_NULL)); | ||||||
|  |                 newInstructions.add(new JumpInsnNode(GOTO, startlbl)); | ||||||
|  |                 newInstructions.add(newinst.returnLabel); | ||||||
|  | 
 | ||||||
|  |                 // Insert this new instantiation into the queue to be emitted | ||||||
|  |                 // later. | ||||||
|  |                 worklist.add(newinst); | ||||||
|  |             } else { | ||||||
|  |                 newInstructions.add(insn.clone(instant)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Emit try/catch blocks that are relevant to this method. | ||||||
|  |         for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it | ||||||
|  |                 .hasNext();) { | ||||||
|  |             TryCatchBlockNode trycatch = it.next(); | ||||||
|  | 
 | ||||||
|  |             if (LOGGING) { | ||||||
|  |                 // TODO use of default toString(). | ||||||
|  |                 log("try catch block original labels=" + trycatch.start + '-' | ||||||
|  |                         + trycatch.end + "->" + trycatch.handler); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             final LabelNode start = instant.rangeLabel(trycatch.start); | ||||||
|  |             final LabelNode end = instant.rangeLabel(trycatch.end); | ||||||
|  | 
 | ||||||
|  |             // Ignore empty try/catch regions | ||||||
|  |             if (start == end) { | ||||||
|  |                 if (LOGGING) { | ||||||
|  |                     log(" try catch block empty in this subroutine"); | ||||||
|  |                 } | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             final LabelNode handler = instant.gotoLabel(trycatch.handler); | ||||||
|  | 
 | ||||||
|  |             if (LOGGING) { | ||||||
|  |                 // TODO use of default toString(). | ||||||
|  |                 log(" try catch block new labels=" + start + '-' + end + "->" | ||||||
|  |                         + handler); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (start == null || end == null || handler == null) { | ||||||
|  |                 throw new RuntimeException("Internal error!"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, | ||||||
|  |                     trycatch.type)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (Iterator<LocalVariableNode> it = localVariables.iterator(); it | ||||||
|  |                 .hasNext();) { | ||||||
|  |             LocalVariableNode lvnode = it.next(); | ||||||
|  |             if (LOGGING) { | ||||||
|  |                 log("local var " + lvnode.name); | ||||||
|  |             } | ||||||
|  |             final LabelNode start = instant.rangeLabel(lvnode.start); | ||||||
|  |             final LabelNode end = instant.rangeLabel(lvnode.end); | ||||||
|  |             if (start == end) { | ||||||
|  |                 if (LOGGING) { | ||||||
|  |                     log("  local variable empty in this sub"); | ||||||
|  |                 } | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             newLocalVariables.add(new LocalVariableNode(lvnode.name, | ||||||
|  |                     lvnode.desc, lvnode.signature, start, end, lvnode.index)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static void log(final String str) { | ||||||
|  |         System.err.println(str); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A class that represents an instantiation of a subroutine. Each | ||||||
|  |      * instantiation has an associate "stack" --- which is a listing of those | ||||||
|  |      * instantiations that were active when this particular instance of this | ||||||
|  |      * subroutine was invoked. Each instantiation also has a map from the | ||||||
|  |      * original labels of the program to the labels appropriate for this | ||||||
|  |      * instantiation, and finally a label to return to. | ||||||
|  |      */ | ||||||
|  |     private class Instantiation extends AbstractMap<LabelNode, LabelNode> { | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Previous instantiations; the stack must be statically predictable to | ||||||
|  |          * be inlinable. | ||||||
|  |          */ | ||||||
|  |         final Instantiation previous; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * The subroutine this is an instantiation of. | ||||||
|  |          */ | ||||||
|  |         public final BitSet subroutine; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * This table maps Labels from the original source to Labels pointing at | ||||||
|  |          * code specific to this instantiation, for use in remapping try/catch | ||||||
|  |          * blocks,as well as gotos. | ||||||
|  |          *  | ||||||
|  |          * Note that in the presence of dual citizens instructions, that is, | ||||||
|  |          * instructions which belong to more than one subroutine due to the | ||||||
|  |          * merging of control flow without a RET instruction, we will map the | ||||||
|  |          * target label of a GOTO to the label used by the instantiation lowest | ||||||
|  |          * on the stack. This avoids code duplication during inlining in most | ||||||
|  |          * cases. | ||||||
|  |          *  | ||||||
|  |          * @see #findOwner(int) | ||||||
|  |          */ | ||||||
|  |         public final Map<LabelNode, LabelNode> rangeTable = new HashMap<LabelNode, LabelNode>(); | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * All returns for this instantiation will be mapped to this label | ||||||
|  |          */ | ||||||
|  |         public final LabelNode returnLabel; | ||||||
|  | 
 | ||||||
|  |         Instantiation(final Instantiation prev, final BitSet sub) { | ||||||
|  |             previous = prev; | ||||||
|  |             subroutine = sub; | ||||||
|  |             for (Instantiation p = prev; p != null; p = p.previous) { | ||||||
|  |                 if (p.subroutine == sub) { | ||||||
|  |                     throw new RuntimeException("Recursive invocation of " + sub); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Determine the label to return to when this subroutine terminates | ||||||
|  |             // via RET: note that the main subroutine never terminates via RET. | ||||||
|  |             if (prev != null) { | ||||||
|  |                 returnLabel = new LabelNode(); | ||||||
|  |             } else { | ||||||
|  |                 returnLabel = null; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Each instantiation will remap the labels from the code above to | ||||||
|  |             // refer to its particular copy of its own instructions. Note that | ||||||
|  |             // we collapse labels which point at the same instruction into one: | ||||||
|  |             // this is fairly common as we are often ignoring large chunks of | ||||||
|  |             // instructions, so what were previously distinct labels become | ||||||
|  |             // duplicates. | ||||||
|  |             LabelNode duplbl = null; | ||||||
|  |             for (int i = 0, c = instructions.size(); i < c; i++) { | ||||||
|  |                 AbstractInsnNode insn = instructions.get(i); | ||||||
|  | 
 | ||||||
|  |                 if (insn.getType() == AbstractInsnNode.LABEL) { | ||||||
|  |                     LabelNode ilbl = (LabelNode) insn; | ||||||
|  | 
 | ||||||
|  |                     if (duplbl == null) { | ||||||
|  |                         // if we already have a label pointing at this spot, | ||||||
|  |                         // don't recreate it. | ||||||
|  |                         duplbl = new LabelNode(); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     // Add an entry in the rangeTable for every label | ||||||
|  |                     // in the original code which points at the next | ||||||
|  |                     // instruction of our own to be emitted. | ||||||
|  |                     rangeTable.put(ilbl, duplbl); | ||||||
|  |                 } else if (findOwner(i) == this) { | ||||||
|  |                     // We will emit this instruction, so clear the 'duplbl' flag | ||||||
|  |                     // since the next Label will refer to a distinct | ||||||
|  |                     // instruction. | ||||||
|  |                     duplbl = null; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Returns the "owner" of a particular instruction relative to this | ||||||
|  |          * instantiation: the owner referes to the Instantiation which will emit | ||||||
|  |          * the version of this instruction that we will execute. | ||||||
|  |          *  | ||||||
|  |          * Typically, the return value is either <code>this</code> or | ||||||
|  |          * <code>null</code>. <code>this</code> indicates that this | ||||||
|  |          * instantiation will generate the version of this instruction that we | ||||||
|  |          * will execute, and <code>null</code> indicates that this instantiation | ||||||
|  |          * never executes the given instruction. | ||||||
|  |          *  | ||||||
|  |          * Sometimes, however, an instruction can belong to multiple | ||||||
|  |          * subroutines; this is called a "dual citizen" instruction (though it | ||||||
|  |          * may belong to more than 2 subroutines), and occurs when multiple | ||||||
|  |          * subroutines branch to common points of control. In this case, the | ||||||
|  |          * owner is the subroutine that appears lowest on the stack, and which | ||||||
|  |          * also owns the instruction in question. | ||||||
|  |          *  | ||||||
|  |          * @param i | ||||||
|  |          *            the index of the instruction in the original code | ||||||
|  |          * @return the "owner" of a particular instruction relative to this | ||||||
|  |          *         instantiation. | ||||||
|  |          */ | ||||||
|  |         public Instantiation findOwner(final int i) { | ||||||
|  |             if (!subroutine.get(i)) { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |             if (!dualCitizens.get(i)) { | ||||||
|  |                 return this; | ||||||
|  |             } | ||||||
|  |             Instantiation own = this; | ||||||
|  |             for (Instantiation p = previous; p != null; p = p.previous) { | ||||||
|  |                 if (p.subroutine.get(i)) { | ||||||
|  |                     own = p; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return own; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Looks up the label <code>l</code> in the <code>gotoTable</code>, thus | ||||||
|  |          * translating it from a Label in the original code, to a Label in the | ||||||
|  |          * inlined code that is appropriate for use by an instruction that | ||||||
|  |          * branched to the original label. | ||||||
|  |          *  | ||||||
|  |          * @param l | ||||||
|  |          *            The label we will be translating | ||||||
|  |          * @return a label for use by a branch instruction in the inlined code | ||||||
|  |          * @see #rangeLabel | ||||||
|  |          */ | ||||||
|  |         public LabelNode gotoLabel(final LabelNode l) { | ||||||
|  |             // owner should never be null, because owner is only null | ||||||
|  |             // if an instruction cannot be reached from this subroutine | ||||||
|  |             Instantiation owner = findOwner(instructions.indexOf(l)); | ||||||
|  |             return owner.rangeTable.get(l); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Looks up the label <code>l</code> in the <code>rangeTable</code>, | ||||||
|  |          * thus translating it from a Label in the original code, to a Label in | ||||||
|  |          * the inlined code that is appropriate for use by an try/catch or | ||||||
|  |          * variable use annotation. | ||||||
|  |          *  | ||||||
|  |          * @param l | ||||||
|  |          *            The label we will be translating | ||||||
|  |          * @return a label for use by a try/catch or variable annotation in the | ||||||
|  |          *         original code | ||||||
|  |          * @see #rangeTable | ||||||
|  |          */ | ||||||
|  |         public LabelNode rangeLabel(final LabelNode l) { | ||||||
|  |             return rangeTable.get(l); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // AbstractMap implementation | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public Set<Map.Entry<LabelNode, LabelNode>> entrySet() { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public LabelNode get(final Object o) { | ||||||
|  |             return gotoLabel((LabelNode) o); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										361
									
								
								src/main/asm/org/objectweb/asm/commons/LocalVariablesSorter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										361
									
								
								src/main/asm/org/objectweb/asm/commons/LocalVariablesSorter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,361 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link MethodVisitor} that renumbers local variables in their order of | ||||||
|  |  * appearance. This adapter allows one to easily add new local variables to a | ||||||
|  |  * method. It may be used by inheriting from this class, but the preferred way | ||||||
|  |  * of using it is via delegation: the next visitor in the chain can indeed add | ||||||
|  |  * new locals when needed by calling {@link #newLocal} on this adapter (this | ||||||
|  |  * requires a reference back to this {@link LocalVariablesSorter}). | ||||||
|  |  *  | ||||||
|  |  * @author Chris Nokleberg | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class LocalVariablesSorter extends MethodVisitor { | ||||||
|  | 
 | ||||||
|  |     private static final Type OBJECT_TYPE = Type | ||||||
|  |             .getObjectType("java/lang/Object"); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Mapping from old to new local variable indexes. A local variable at index | ||||||
|  |      * i of size 1 is remapped to 'mapping[2*i]', while a local variable at | ||||||
|  |      * index i of size 2 is remapped to 'mapping[2*i+1]'. | ||||||
|  |      */ | ||||||
|  |     private int[] mapping = new int[40]; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Array used to store stack map local variable types after remapping. | ||||||
|  |      */ | ||||||
|  |     private Object[] newLocals = new Object[20]; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Index of the first local variable, after formal parameters. | ||||||
|  |      */ | ||||||
|  |     protected final int firstLocal; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Index of the next local variable to be created by {@link #newLocal}. | ||||||
|  |      */ | ||||||
|  |     protected int nextLocal; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if at least one local variable has moved due to remapping. | ||||||
|  |      */ | ||||||
|  |     private boolean changed; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use | ||||||
|  |      * this constructor</i>. Instead, they must use the | ||||||
|  |      * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version. | ||||||
|  |      *  | ||||||
|  |      * @param access | ||||||
|  |      *            access flags of the adapted method. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor to which this adapter delegates calls. | ||||||
|  |      */ | ||||||
|  |     public LocalVariablesSorter(final int access, final String desc, | ||||||
|  |             final MethodVisitor mv) { | ||||||
|  |         this(Opcodes.ASM4, access, desc, mv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link LocalVariablesSorter}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param access | ||||||
|  |      *            access flags of the adapted method. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor (see {@link Type Type}). | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor to which this adapter delegates calls. | ||||||
|  |      */ | ||||||
|  |     protected LocalVariablesSorter(final int api, final int access, | ||||||
|  |             final String desc, final MethodVisitor mv) { | ||||||
|  |         super(api, mv); | ||||||
|  |         Type[] args = Type.getArgumentTypes(desc); | ||||||
|  |         nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0; | ||||||
|  |         for (int i = 0; i < args.length; i++) { | ||||||
|  |             nextLocal += args[i].getSize(); | ||||||
|  |         } | ||||||
|  |         firstLocal = nextLocal; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitVarInsn(final int opcode, final int var) { | ||||||
|  |         Type type; | ||||||
|  |         switch (opcode) { | ||||||
|  |         case Opcodes.LLOAD: | ||||||
|  |         case Opcodes.LSTORE: | ||||||
|  |             type = Type.LONG_TYPE; | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         case Opcodes.DLOAD: | ||||||
|  |         case Opcodes.DSTORE: | ||||||
|  |             type = Type.DOUBLE_TYPE; | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         case Opcodes.FLOAD: | ||||||
|  |         case Opcodes.FSTORE: | ||||||
|  |             type = Type.FLOAT_TYPE; | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         case Opcodes.ILOAD: | ||||||
|  |         case Opcodes.ISTORE: | ||||||
|  |             type = Type.INT_TYPE; | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         default: | ||||||
|  |             // case Opcodes.ALOAD: | ||||||
|  |             // case Opcodes.ASTORE: | ||||||
|  |             // case RET: | ||||||
|  |             type = OBJECT_TYPE; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         mv.visitVarInsn(opcode, remap(var, type)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitIincInsn(final int var, final int increment) { | ||||||
|  |         mv.visitIincInsn(remap(var, Type.INT_TYPE), increment); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMaxs(final int maxStack, final int maxLocals) { | ||||||
|  |         mv.visitMaxs(maxStack, nextLocal); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLocalVariable(final String name, final String desc, | ||||||
|  |             final String signature, final Label start, final Label end, | ||||||
|  |             final int index) { | ||||||
|  |         int newIndex = remap(index, Type.getType(desc)); | ||||||
|  |         mv.visitLocalVariable(name, desc, signature, start, end, newIndex); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFrame(final int type, final int nLocal, | ||||||
|  |             final Object[] local, final int nStack, final Object[] stack) { | ||||||
|  |         if (type != Opcodes.F_NEW) { // uncompressed frame | ||||||
|  |             throw new IllegalStateException( | ||||||
|  |                     "ClassReader.accept() should be called with EXPAND_FRAMES flag"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!changed) { // optimization for the case where mapping = identity | ||||||
|  |             mv.visitFrame(type, nLocal, local, nStack, stack); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // creates a copy of newLocals | ||||||
|  |         Object[] oldLocals = new Object[newLocals.length]; | ||||||
|  |         System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length); | ||||||
|  | 
 | ||||||
|  |         updateNewLocals(newLocals); | ||||||
|  | 
 | ||||||
|  |         // copies types from 'local' to 'newLocals' | ||||||
|  |         // 'newLocals' already contains the variables added with 'newLocal' | ||||||
|  | 
 | ||||||
|  |         int index = 0; // old local variable index | ||||||
|  |         int number = 0; // old local variable number | ||||||
|  |         for (; number < nLocal; ++number) { | ||||||
|  |             Object t = local[number]; | ||||||
|  |             int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1; | ||||||
|  |             if (t != Opcodes.TOP) { | ||||||
|  |                 Type typ = OBJECT_TYPE; | ||||||
|  |                 if (t == Opcodes.INTEGER) { | ||||||
|  |                     typ = Type.INT_TYPE; | ||||||
|  |                 } else if (t == Opcodes.FLOAT) { | ||||||
|  |                     typ = Type.FLOAT_TYPE; | ||||||
|  |                 } else if (t == Opcodes.LONG) { | ||||||
|  |                     typ = Type.LONG_TYPE; | ||||||
|  |                 } else if (t == Opcodes.DOUBLE) { | ||||||
|  |                     typ = Type.DOUBLE_TYPE; | ||||||
|  |                 } else if (t instanceof String) { | ||||||
|  |                     typ = Type.getObjectType((String) t); | ||||||
|  |                 } | ||||||
|  |                 setFrameLocal(remap(index, typ), t); | ||||||
|  |             } | ||||||
|  |             index += size; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // removes TOP after long and double types as well as trailing TOPs | ||||||
|  | 
 | ||||||
|  |         index = 0; | ||||||
|  |         number = 0; | ||||||
|  |         for (int i = 0; index < newLocals.length; ++i) { | ||||||
|  |             Object t = newLocals[index++]; | ||||||
|  |             if (t != null && t != Opcodes.TOP) { | ||||||
|  |                 newLocals[i] = t; | ||||||
|  |                 number = i + 1; | ||||||
|  |                 if (t == Opcodes.LONG || t == Opcodes.DOUBLE) { | ||||||
|  |                     index += 1; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 newLocals[i] = Opcodes.TOP; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // visits remapped frame | ||||||
|  |         mv.visitFrame(type, number, newLocals, nStack, stack); | ||||||
|  | 
 | ||||||
|  |         // restores original value of 'newLocals' | ||||||
|  |         newLocals = oldLocals; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------- | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new local variable of the given type. | ||||||
|  |      *  | ||||||
|  |      * @param type | ||||||
|  |      *            the type of the local variable to be created. | ||||||
|  |      * @return the identifier of the newly created local variable. | ||||||
|  |      */ | ||||||
|  |     public int newLocal(final Type type) { | ||||||
|  |         Object t; | ||||||
|  |         switch (type.getSort()) { | ||||||
|  |         case Type.BOOLEAN: | ||||||
|  |         case Type.CHAR: | ||||||
|  |         case Type.BYTE: | ||||||
|  |         case Type.SHORT: | ||||||
|  |         case Type.INT: | ||||||
|  |             t = Opcodes.INTEGER; | ||||||
|  |             break; | ||||||
|  |         case Type.FLOAT: | ||||||
|  |             t = Opcodes.FLOAT; | ||||||
|  |             break; | ||||||
|  |         case Type.LONG: | ||||||
|  |             t = Opcodes.LONG; | ||||||
|  |             break; | ||||||
|  |         case Type.DOUBLE: | ||||||
|  |             t = Opcodes.DOUBLE; | ||||||
|  |             break; | ||||||
|  |         case Type.ARRAY: | ||||||
|  |             t = type.getDescriptor(); | ||||||
|  |             break; | ||||||
|  |         // case Type.OBJECT: | ||||||
|  |         default: | ||||||
|  |             t = type.getInternalName(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         int local = newLocalMapping(type); | ||||||
|  |         setLocalType(local, type); | ||||||
|  |         setFrameLocal(local, t); | ||||||
|  |         changed = true; | ||||||
|  |         return local; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Notifies subclasses that a new stack map frame is being visited. The | ||||||
|  |      * array argument contains the stack map frame types corresponding to the | ||||||
|  |      * local variables added with {@link #newLocal}. This method can update | ||||||
|  |      * these types in place for the stack map frame being visited. The default | ||||||
|  |      * implementation of this method does nothing, i.e. a local variable added | ||||||
|  |      * with {@link #newLocal} will have the same type in all stack map frames. | ||||||
|  |      * But this behavior is not always the desired one, for instance if a local | ||||||
|  |      * variable is added in the middle of a try/catch block: the frame for the | ||||||
|  |      * exception handler should have a TOP type for this new local. | ||||||
|  |      *  | ||||||
|  |      * @param newLocals | ||||||
|  |      *            the stack map frame types corresponding to the local variables | ||||||
|  |      *            added with {@link #newLocal} (and null for the others). The | ||||||
|  |      *            format of this array is the same as in | ||||||
|  |      *            {@link MethodVisitor#visitFrame}, except that long and double | ||||||
|  |      *            types use two slots. The types for the current stack map frame | ||||||
|  |      *            must be updated in place in this array. | ||||||
|  |      */ | ||||||
|  |     protected void updateNewLocals(Object[] newLocals) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Notifies subclasses that a local variable has been added or remapped. The | ||||||
|  |      * default implementation of this method does nothing. | ||||||
|  |      *  | ||||||
|  |      * @param local | ||||||
|  |      *            a local variable identifier, as returned by {@link #newLocal | ||||||
|  |      *            newLocal()}. | ||||||
|  |      * @param type | ||||||
|  |      *            the type of the value being stored in the local variable. | ||||||
|  |      */ | ||||||
|  |     protected void setLocalType(final int local, final Type type) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void setFrameLocal(final int local, final Object type) { | ||||||
|  |         int l = newLocals.length; | ||||||
|  |         if (local >= l) { | ||||||
|  |             Object[] a = new Object[Math.max(2 * l, local + 1)]; | ||||||
|  |             System.arraycopy(newLocals, 0, a, 0, l); | ||||||
|  |             newLocals = a; | ||||||
|  |         } | ||||||
|  |         newLocals[local] = type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private int remap(final int var, final Type type) { | ||||||
|  |         if (var + type.getSize() <= firstLocal) { | ||||||
|  |             return var; | ||||||
|  |         } | ||||||
|  |         int key = 2 * var + type.getSize() - 1; | ||||||
|  |         int size = mapping.length; | ||||||
|  |         if (key >= size) { | ||||||
|  |             int[] newMapping = new int[Math.max(2 * size, key + 1)]; | ||||||
|  |             System.arraycopy(mapping, 0, newMapping, 0, size); | ||||||
|  |             mapping = newMapping; | ||||||
|  |         } | ||||||
|  |         int value = mapping[key]; | ||||||
|  |         if (value == 0) { | ||||||
|  |             value = newLocalMapping(type); | ||||||
|  |             setLocalType(value, type); | ||||||
|  |             mapping[key] = value + 1; | ||||||
|  |         } else { | ||||||
|  |             value--; | ||||||
|  |         } | ||||||
|  |         if (value != var) { | ||||||
|  |             changed = true; | ||||||
|  |         } | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected int newLocalMapping(final Type type) { | ||||||
|  |         int local = nextLocal; | ||||||
|  |         nextLocal += type.getSize(); | ||||||
|  |         return local; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										282
									
								
								src/main/asm/org/objectweb/asm/commons/Method.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								src/main/asm/org/objectweb/asm/commons/Method.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,282 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A named method descriptor. | ||||||
|  |  *  | ||||||
|  |  * @author Juozas Baliuka | ||||||
|  |  * @author Chris Nokleberg | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class Method { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The method name. | ||||||
|  |      */ | ||||||
|  |     private final String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The method descriptor. | ||||||
|  |      */ | ||||||
|  |     private final String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Maps primitive Java type names to their descriptors. | ||||||
|  |      */ | ||||||
|  |     private static final Map<String, String> DESCRIPTORS; | ||||||
|  | 
 | ||||||
|  |     static { | ||||||
|  |         DESCRIPTORS = new HashMap<String, String>(); | ||||||
|  |         DESCRIPTORS.put("void", "V"); | ||||||
|  |         DESCRIPTORS.put("byte", "B"); | ||||||
|  |         DESCRIPTORS.put("char", "C"); | ||||||
|  |         DESCRIPTORS.put("double", "D"); | ||||||
|  |         DESCRIPTORS.put("float", "F"); | ||||||
|  |         DESCRIPTORS.put("int", "I"); | ||||||
|  |         DESCRIPTORS.put("long", "J"); | ||||||
|  |         DESCRIPTORS.put("short", "S"); | ||||||
|  |         DESCRIPTORS.put("boolean", "Z"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link Method}. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the method's descriptor. | ||||||
|  |      */ | ||||||
|  |     public Method(final String name, final String desc) { | ||||||
|  |         this.name = name; | ||||||
|  |         this.desc = desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link Method}. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the method's name. | ||||||
|  |      * @param returnType | ||||||
|  |      *            the method's return type. | ||||||
|  |      * @param argumentTypes | ||||||
|  |      *            the method's argument types. | ||||||
|  |      */ | ||||||
|  |     public Method(final String name, final Type returnType, | ||||||
|  |             final Type[] argumentTypes) { | ||||||
|  |         this(name, Type.getMethodDescriptor(returnType, argumentTypes)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link Method}. | ||||||
|  |      *  | ||||||
|  |      * @param m | ||||||
|  |      *            a java.lang.reflect method descriptor | ||||||
|  |      * @return a {@link Method} corresponding to the given Java method | ||||||
|  |      *         declaration. | ||||||
|  |      */ | ||||||
|  |     public static Method getMethod(java.lang.reflect.Method m) { | ||||||
|  |         return new Method(m.getName(), Type.getMethodDescriptor(m)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link Method}. | ||||||
|  |      *  | ||||||
|  |      * @param c | ||||||
|  |      *            a java.lang.reflect constructor descriptor | ||||||
|  |      * @return a {@link Method} corresponding to the given Java constructor | ||||||
|  |      *         declaration. | ||||||
|  |      */ | ||||||
|  |     public static Method getMethod(java.lang.reflect.Constructor<?> c) { | ||||||
|  |         return new Method("<init>", Type.getConstructorDescriptor(c)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a {@link Method} corresponding to the given Java method | ||||||
|  |      * declaration. | ||||||
|  |      *  | ||||||
|  |      * @param method | ||||||
|  |      *            a Java method declaration, without argument names, of the form | ||||||
|  |      *            "returnType name (argumentType1, ... argumentTypeN)", where | ||||||
|  |      *            the types are in plain Java (e.g. "int", "float", | ||||||
|  |      *            "java.util.List", ...). Classes of the java.lang package can | ||||||
|  |      *            be specified by their unqualified name; all other classes | ||||||
|  |      *            names must be fully qualified. | ||||||
|  |      * @return a {@link Method} corresponding to the given Java method | ||||||
|  |      *         declaration. | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if <code>method</code> could not get parsed. | ||||||
|  |      */ | ||||||
|  |     public static Method getMethod(final String method) | ||||||
|  |             throws IllegalArgumentException { | ||||||
|  |         return getMethod(method, false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a {@link Method} corresponding to the given Java method | ||||||
|  |      * declaration. | ||||||
|  |      *  | ||||||
|  |      * @param method | ||||||
|  |      *            a Java method declaration, without argument names, of the form | ||||||
|  |      *            "returnType name (argumentType1, ... argumentTypeN)", where | ||||||
|  |      *            the types are in plain Java (e.g. "int", "float", | ||||||
|  |      *            "java.util.List", ...). Classes of the java.lang package may | ||||||
|  |      *            be specified by their unqualified name, depending on the | ||||||
|  |      *            defaultPackage argument; all other classes names must be fully | ||||||
|  |      *            qualified. | ||||||
|  |      * @param defaultPackage | ||||||
|  |      *            true if unqualified class names belong to the default package, | ||||||
|  |      *            or false if they correspond to java.lang classes. For instance | ||||||
|  |      *            "Object" means "Object" if this option is true, or | ||||||
|  |      *            "java.lang.Object" otherwise. | ||||||
|  |      * @return a {@link Method} corresponding to the given Java method | ||||||
|  |      *         declaration. | ||||||
|  |      * @throws IllegalArgumentException | ||||||
|  |      *             if <code>method</code> could not get parsed. | ||||||
|  |      */ | ||||||
|  |     public static Method getMethod(final String method, | ||||||
|  |             final boolean defaultPackage) throws IllegalArgumentException { | ||||||
|  |         int space = method.indexOf(' '); | ||||||
|  |         int start = method.indexOf('(', space) + 1; | ||||||
|  |         int end = method.indexOf(')', start); | ||||||
|  |         if (space == -1 || start == -1 || end == -1) { | ||||||
|  |             throw new IllegalArgumentException(); | ||||||
|  |         } | ||||||
|  |         String returnType = method.substring(0, space); | ||||||
|  |         String methodName = method.substring(space + 1, start - 1).trim(); | ||||||
|  |         StringBuffer sb = new StringBuffer(); | ||||||
|  |         sb.append('('); | ||||||
|  |         int p; | ||||||
|  |         do { | ||||||
|  |             String s; | ||||||
|  |             p = method.indexOf(',', start); | ||||||
|  |             if (p == -1) { | ||||||
|  |                 s = map(method.substring(start, end).trim(), defaultPackage); | ||||||
|  |             } else { | ||||||
|  |                 s = map(method.substring(start, p).trim(), defaultPackage); | ||||||
|  |                 start = p + 1; | ||||||
|  |             } | ||||||
|  |             sb.append(s); | ||||||
|  |         } while (p != -1); | ||||||
|  |         sb.append(')'); | ||||||
|  |         sb.append(map(returnType, defaultPackage)); | ||||||
|  |         return new Method(methodName, sb.toString()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static String map(final String type, final boolean defaultPackage) { | ||||||
|  |         if ("".equals(type)) { | ||||||
|  |             return type; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         StringBuffer sb = new StringBuffer(); | ||||||
|  |         int index = 0; | ||||||
|  |         while ((index = type.indexOf("[]", index) + 1) > 0) { | ||||||
|  |             sb.append('['); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         String t = type.substring(0, type.length() - sb.length() * 2); | ||||||
|  |         String desc = DESCRIPTORS.get(t); | ||||||
|  |         if (desc != null) { | ||||||
|  |             sb.append(desc); | ||||||
|  |         } else { | ||||||
|  |             sb.append('L'); | ||||||
|  |             if (t.indexOf('.') < 0) { | ||||||
|  |                 if (!defaultPackage) { | ||||||
|  |                     sb.append("java/lang/"); | ||||||
|  |                 } | ||||||
|  |                 sb.append(t); | ||||||
|  |             } else { | ||||||
|  |                 sb.append(t.replace('.', '/')); | ||||||
|  |             } | ||||||
|  |             sb.append(';'); | ||||||
|  |         } | ||||||
|  |         return sb.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the name of the method described by this object. | ||||||
|  |      *  | ||||||
|  |      * @return the name of the method described by this object. | ||||||
|  |      */ | ||||||
|  |     public String getName() { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the descriptor of the method described by this object. | ||||||
|  |      *  | ||||||
|  |      * @return the descriptor of the method described by this object. | ||||||
|  |      */ | ||||||
|  |     public String getDescriptor() { | ||||||
|  |         return desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the return type of the method described by this object. | ||||||
|  |      *  | ||||||
|  |      * @return the return type of the method described by this object. | ||||||
|  |      */ | ||||||
|  |     public Type getReturnType() { | ||||||
|  |         return Type.getReturnType(desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the argument types of the method described by this object. | ||||||
|  |      *  | ||||||
|  |      * @return the argument types of the method described by this object. | ||||||
|  |      */ | ||||||
|  |     public Type[] getArgumentTypes() { | ||||||
|  |         return Type.getArgumentTypes(desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return name + desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean equals(final Object o) { | ||||||
|  |         if (!(o instanceof Method)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         Method other = (Method) o; | ||||||
|  |         return name.equals(other.name) && desc.equals(other.desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int hashCode() { | ||||||
|  |         return name.hashCode() ^ desc.hashCode(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										223
									
								
								src/main/asm/org/objectweb/asm/commons/Remapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								src/main/asm/org/objectweb/asm/commons/Remapper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,223 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.Type; | ||||||
|  | import org.objectweb.asm.signature.SignatureReader; | ||||||
|  | import org.objectweb.asm.signature.SignatureVisitor; | ||||||
|  | import org.objectweb.asm.signature.SignatureWriter; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A class responsible for remapping types and names. Subclasses can override | ||||||
|  |  * the following methods: | ||||||
|  |  *  | ||||||
|  |  * <ul> | ||||||
|  |  * <li>{@link #map(String)} - map type</li> | ||||||
|  |  * <li>{@link #mapFieldName(String, String, String)} - map field name</li> | ||||||
|  |  * <li>{@link #mapMethodName(String, String, String)} - map method name</li> | ||||||
|  |  * </ul> | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public abstract class Remapper { | ||||||
|  | 
 | ||||||
|  |     public String mapDesc(String desc) { | ||||||
|  |         Type t = Type.getType(desc); | ||||||
|  |         switch (t.getSort()) { | ||||||
|  |         case Type.ARRAY: | ||||||
|  |             String s = mapDesc(t.getElementType().getDescriptor()); | ||||||
|  |             for (int i = 0; i < t.getDimensions(); ++i) { | ||||||
|  |                 s = '[' + s; | ||||||
|  |             } | ||||||
|  |             return s; | ||||||
|  |         case Type.OBJECT: | ||||||
|  |             String newType = map(t.getInternalName()); | ||||||
|  |             if (newType != null) { | ||||||
|  |                 return 'L' + newType + ';'; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Type mapType(Type t) { | ||||||
|  |         switch (t.getSort()) { | ||||||
|  |         case Type.ARRAY: | ||||||
|  |             String s = mapDesc(t.getElementType().getDescriptor()); | ||||||
|  |             for (int i = 0; i < t.getDimensions(); ++i) { | ||||||
|  |                 s = '[' + s; | ||||||
|  |             } | ||||||
|  |             return Type.getType(s); | ||||||
|  |         case Type.OBJECT: | ||||||
|  |             s = map(t.getInternalName()); | ||||||
|  |             return s != null ? Type.getObjectType(s) : t; | ||||||
|  |         case Type.METHOD: | ||||||
|  |             return Type.getMethodType(mapMethodDesc(t.getDescriptor())); | ||||||
|  |         } | ||||||
|  |         return t; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String mapType(String type) { | ||||||
|  |         if (type == null) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         return mapType(Type.getObjectType(type)).getInternalName(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String[] mapTypes(String[] types) { | ||||||
|  |         String[] newTypes = null; | ||||||
|  |         boolean needMapping = false; | ||||||
|  |         for (int i = 0; i < types.length; i++) { | ||||||
|  |             String type = types[i]; | ||||||
|  |             String newType = map(type); | ||||||
|  |             if (newType != null && newTypes == null) { | ||||||
|  |                 newTypes = new String[types.length]; | ||||||
|  |                 if (i > 0) { | ||||||
|  |                     System.arraycopy(types, 0, newTypes, 0, i); | ||||||
|  |                 } | ||||||
|  |                 needMapping = true; | ||||||
|  |             } | ||||||
|  |             if (needMapping) { | ||||||
|  |                 newTypes[i] = newType == null ? type : newType; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return needMapping ? newTypes : types; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String mapMethodDesc(String desc) { | ||||||
|  |         if ("()V".equals(desc)) { | ||||||
|  |             return desc; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Type[] args = Type.getArgumentTypes(desc); | ||||||
|  |         StringBuffer s = new StringBuffer("("); | ||||||
|  |         for (int i = 0; i < args.length; i++) { | ||||||
|  |             s.append(mapDesc(args[i].getDescriptor())); | ||||||
|  |         } | ||||||
|  |         Type returnType = Type.getReturnType(desc); | ||||||
|  |         if (returnType == Type.VOID_TYPE) { | ||||||
|  |             s.append(")V"); | ||||||
|  |             return s.toString(); | ||||||
|  |         } | ||||||
|  |         s.append(')').append(mapDesc(returnType.getDescriptor())); | ||||||
|  |         return s.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Object mapValue(Object value) { | ||||||
|  |         if (value instanceof Type) { | ||||||
|  |             return mapType((Type) value); | ||||||
|  |         } | ||||||
|  |         if (value instanceof Handle) { | ||||||
|  |             Handle h = (Handle) value; | ||||||
|  |             return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName( | ||||||
|  |                     h.getOwner(), h.getName(), h.getDesc()), | ||||||
|  |                     mapMethodDesc(h.getDesc())); | ||||||
|  |         } | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      *  | ||||||
|  |      * @param typeSignature | ||||||
|  |      *            true if signature is a FieldTypeSignature, such as the | ||||||
|  |      *            signature parameter of the ClassVisitor.visitField or | ||||||
|  |      *            MethodVisitor.visitLocalVariable methods | ||||||
|  |      */ | ||||||
|  |     public String mapSignature(String signature, boolean typeSignature) { | ||||||
|  |         if (signature == null) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |         SignatureReader r = new SignatureReader(signature); | ||||||
|  |         SignatureWriter w = new SignatureWriter(); | ||||||
|  |         SignatureVisitor a = createRemappingSignatureAdapter(w); | ||||||
|  |         if (typeSignature) { | ||||||
|  |             r.acceptType(a); | ||||||
|  |         } else { | ||||||
|  |             r.accept(a); | ||||||
|  |         } | ||||||
|  |         return w.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected SignatureVisitor createRemappingSignatureAdapter( | ||||||
|  |             SignatureVisitor v) { | ||||||
|  |         return new RemappingSignatureAdapter(v, this); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Map method name to the new name. Subclasses can override. | ||||||
|  |      *  | ||||||
|  |      * @param owner | ||||||
|  |      *            owner of the method. | ||||||
|  |      * @param name | ||||||
|  |      *            name of the method. | ||||||
|  |      * @param desc | ||||||
|  |      *            descriptor of the method. | ||||||
|  |      * @return new name of the method | ||||||
|  |      */ | ||||||
|  |     public String mapMethodName(String owner, String name, String desc) { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Map invokedynamic method name to the new name. Subclasses can override. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            name of the invokedynamic. | ||||||
|  |      * @param desc | ||||||
|  |      *            descriptor of the invokedynamic. | ||||||
|  |      * @return new invokdynamic name. | ||||||
|  |      */ | ||||||
|  |     public String mapInvokeDynamicMethodName(String name, String desc) { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Map field name to the new name. Subclasses can override. | ||||||
|  |      *  | ||||||
|  |      * @param owner | ||||||
|  |      *            owner of the field. | ||||||
|  |      * @param name | ||||||
|  |      *            name of the field | ||||||
|  |      * @param desc | ||||||
|  |      *            descriptor of the field | ||||||
|  |      * @return new name of the field. | ||||||
|  |      */ | ||||||
|  |     public String mapFieldName(String owner, String name, String desc) { | ||||||
|  |         return name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Map type name to the new name. Subclasses can override. | ||||||
|  |      */ | ||||||
|  |     public String map(String typeName) { | ||||||
|  |         return typeName; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,79 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An {@link AnnotationVisitor} adapter for type remapping. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class RemappingAnnotationAdapter extends AnnotationVisitor { | ||||||
|  | 
 | ||||||
|  |     protected final Remapper remapper; | ||||||
|  | 
 | ||||||
|  |     public RemappingAnnotationAdapter(final AnnotationVisitor av, | ||||||
|  |             final Remapper remapper) { | ||||||
|  |         this(Opcodes.ASM4, av, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected RemappingAnnotationAdapter(final int api, | ||||||
|  |             final AnnotationVisitor av, final Remapper remapper) { | ||||||
|  |         super(api, av); | ||||||
|  |         this.remapper = remapper; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visit(String name, Object value) { | ||||||
|  |         av.visit(name, remapper.mapValue(value)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnum(String name, String desc, String value) { | ||||||
|  |         av.visitEnum(name, remapper.mapDesc(desc), value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(String name, String desc) { | ||||||
|  |         AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc)); | ||||||
|  |         return v == null ? null : (v == av ? this | ||||||
|  |                 : new RemappingAnnotationAdapter(v, remapper)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitArray(String name) { | ||||||
|  |         AnnotationVisitor v = av.visitArray(name); | ||||||
|  |         return v == null ? null : (v == av ? this | ||||||
|  |                 : new RemappingAnnotationAdapter(v, remapper)); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,126 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | import org.objectweb.asm.FieldVisitor; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link ClassVisitor} for type remapping. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class RemappingClassAdapter extends ClassVisitor { | ||||||
|  | 
 | ||||||
|  |     protected final Remapper remapper; | ||||||
|  | 
 | ||||||
|  |     protected String className; | ||||||
|  | 
 | ||||||
|  |     public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) { | ||||||
|  |         this(Opcodes.ASM4, cv, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected RemappingClassAdapter(final int api, final ClassVisitor cv, | ||||||
|  |             final Remapper remapper) { | ||||||
|  |         super(api, cv); | ||||||
|  |         this.remapper = remapper; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visit(int version, int access, String name, String signature, | ||||||
|  |             String superName, String[] interfaces) { | ||||||
|  |         this.className = name; | ||||||
|  |         super.visit(version, access, remapper.mapType(name), remapper | ||||||
|  |                 .mapSignature(signature, false), remapper.mapType(superName), | ||||||
|  |                 interfaces == null ? null : remapper.mapTypes(interfaces)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | ||||||
|  |         AnnotationVisitor av; | ||||||
|  |         av = super.visitAnnotation(remapper.mapDesc(desc), visible); | ||||||
|  |         return av == null ? null : createRemappingAnnotationAdapter(av); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public FieldVisitor visitField(int access, String name, String desc, | ||||||
|  |             String signature, Object value) { | ||||||
|  |         FieldVisitor fv = super.visitField(access, | ||||||
|  |                 remapper.mapFieldName(className, name, desc), | ||||||
|  |                 remapper.mapDesc(desc), remapper.mapSignature(signature, true), | ||||||
|  |                 remapper.mapValue(value)); | ||||||
|  |         return fv == null ? null : createRemappingFieldAdapter(fv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public MethodVisitor visitMethod(int access, String name, String desc, | ||||||
|  |             String signature, String[] exceptions) { | ||||||
|  |         String newDesc = remapper.mapMethodDesc(desc); | ||||||
|  |         MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName( | ||||||
|  |                 className, name, desc), newDesc, remapper.mapSignature( | ||||||
|  |                 signature, false), | ||||||
|  |                 exceptions == null ? null : remapper.mapTypes(exceptions)); | ||||||
|  |         return mv == null ? null : createRemappingMethodAdapter(access, | ||||||
|  |                 newDesc, mv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInnerClass(String name, String outerName, | ||||||
|  |             String innerName, int access) { | ||||||
|  |         // TODO should innerName be changed? | ||||||
|  |         super.visitInnerClass(remapper.mapType(name), outerName == null ? null | ||||||
|  |                 : remapper.mapType(outerName), innerName, access); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitOuterClass(String owner, String name, String desc) { | ||||||
|  |         super.visitOuterClass(remapper.mapType(owner), name == null ? null | ||||||
|  |                 : remapper.mapMethodName(owner, name, desc), | ||||||
|  |                 desc == null ? null : remapper.mapMethodDesc(desc)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) { | ||||||
|  |         return new RemappingFieldAdapter(fv, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected MethodVisitor createRemappingMethodAdapter(int access, | ||||||
|  |             String newDesc, MethodVisitor mv) { | ||||||
|  |         return new RemappingMethodAdapter(access, newDesc, mv, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected AnnotationVisitor createRemappingAnnotationAdapter( | ||||||
|  |             AnnotationVisitor av) { | ||||||
|  |         return new RemappingAnnotationAdapter(av, remapper); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.FieldVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link FieldVisitor} adapter for type remapping. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class RemappingFieldAdapter extends FieldVisitor { | ||||||
|  | 
 | ||||||
|  |     private final Remapper remapper; | ||||||
|  | 
 | ||||||
|  |     public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) { | ||||||
|  |         this(Opcodes.ASM4, fv, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected RemappingFieldAdapter(final int api, final FieldVisitor fv, | ||||||
|  |             final Remapper remapper) { | ||||||
|  |         super(api, fv); | ||||||
|  |         this.remapper = remapper; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | ||||||
|  |         AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc), | ||||||
|  |                 visible); | ||||||
|  |         return av == null ? null : new RemappingAnnotationAdapter(av, remapper); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,161 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link LocalVariablesSorter} for type mapping. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class RemappingMethodAdapter extends LocalVariablesSorter { | ||||||
|  | 
 | ||||||
|  |     protected final Remapper remapper; | ||||||
|  | 
 | ||||||
|  |     public RemappingMethodAdapter(final int access, final String desc, | ||||||
|  |             final MethodVisitor mv, final Remapper remapper) { | ||||||
|  |         this(Opcodes.ASM4, access, desc, mv, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected RemappingMethodAdapter(final int api, final int access, | ||||||
|  |             final String desc, final MethodVisitor mv, final Remapper remapper) { | ||||||
|  |         super(api, access, desc, mv); | ||||||
|  |         this.remapper = remapper; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotationDefault() { | ||||||
|  |         AnnotationVisitor av = mv.visitAnnotationDefault(); | ||||||
|  |         return av == null ? av : new RemappingAnnotationAdapter(av, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(String desc, boolean visible) { | ||||||
|  |         AnnotationVisitor av = mv.visitAnnotation(remapper.mapDesc(desc), | ||||||
|  |                 visible); | ||||||
|  |         return av == null ? av : new RemappingAnnotationAdapter(av, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitParameterAnnotation(int parameter, | ||||||
|  |             String desc, boolean visible) { | ||||||
|  |         AnnotationVisitor av = mv.visitParameterAnnotation(parameter, | ||||||
|  |                 remapper.mapDesc(desc), visible); | ||||||
|  |         return av == null ? av : new RemappingAnnotationAdapter(av, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFrame(int type, int nLocal, Object[] local, int nStack, | ||||||
|  |             Object[] stack) { | ||||||
|  |         super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack, | ||||||
|  |                 remapEntries(nStack, stack)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private Object[] remapEntries(int n, Object[] entries) { | ||||||
|  |         for (int i = 0; i < n; i++) { | ||||||
|  |             if (entries[i] instanceof String) { | ||||||
|  |                 Object[] newEntries = new Object[n]; | ||||||
|  |                 if (i > 0) { | ||||||
|  |                     System.arraycopy(entries, 0, newEntries, 0, i); | ||||||
|  |                 } | ||||||
|  |                 do { | ||||||
|  |                     Object t = entries[i]; | ||||||
|  |                     newEntries[i++] = t instanceof String ? remapper | ||||||
|  |                             .mapType((String) t) : t; | ||||||
|  |                 } while (i < n); | ||||||
|  |                 return newEntries; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return entries; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFieldInsn(int opcode, String owner, String name, | ||||||
|  |             String desc) { | ||||||
|  |         super.visitFieldInsn(opcode, remapper.mapType(owner), | ||||||
|  |                 remapper.mapFieldName(owner, name, desc), | ||||||
|  |                 remapper.mapDesc(desc)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMethodInsn(int opcode, String owner, String name, | ||||||
|  |             String desc) { | ||||||
|  |         super.visitMethodInsn(opcode, remapper.mapType(owner), | ||||||
|  |                 remapper.mapMethodName(owner, name, desc), | ||||||
|  |                 remapper.mapMethodDesc(desc)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, | ||||||
|  |             Object... bsmArgs) { | ||||||
|  |         for (int i = 0; i < bsmArgs.length; i++) { | ||||||
|  |             bsmArgs[i] = remapper.mapValue(bsmArgs[i]); | ||||||
|  |         } | ||||||
|  |         super.visitInvokeDynamicInsn( | ||||||
|  |                 remapper.mapInvokeDynamicMethodName(name, desc), | ||||||
|  |                 remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm), | ||||||
|  |                 bsmArgs); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeInsn(int opcode, String type) { | ||||||
|  |         super.visitTypeInsn(opcode, remapper.mapType(type)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLdcInsn(Object cst) { | ||||||
|  |         super.visitLdcInsn(remapper.mapValue(cst)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitMultiANewArrayInsn(String desc, int dims) { | ||||||
|  |         super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTryCatchBlock(Label start, Label end, Label handler, | ||||||
|  |             String type) { | ||||||
|  |         super.visitTryCatchBlock(start, end, handler, type == null ? null | ||||||
|  |                 : remapper.mapType(type)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitLocalVariable(String name, String desc, String signature, | ||||||
|  |             Label start, Label end, int index) { | ||||||
|  |         super.visitLocalVariable(name, remapper.mapDesc(desc), | ||||||
|  |                 remapper.mapSignature(signature, true), start, end, index); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,155 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.signature.SignatureVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link SignatureVisitor} adapter for type mapping. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class RemappingSignatureAdapter extends SignatureVisitor { | ||||||
|  | 
 | ||||||
|  |     private final SignatureVisitor v; | ||||||
|  | 
 | ||||||
|  |     private final Remapper remapper; | ||||||
|  | 
 | ||||||
|  |     private String className; | ||||||
|  | 
 | ||||||
|  |     public RemappingSignatureAdapter(final SignatureVisitor v, | ||||||
|  |             final Remapper remapper) { | ||||||
|  |         this(Opcodes.ASM4, v, remapper); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected RemappingSignatureAdapter(final int api, | ||||||
|  |             final SignatureVisitor v, final Remapper remapper) { | ||||||
|  |         super(api); | ||||||
|  |         this.v = v; | ||||||
|  |         this.remapper = remapper; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitClassType(String name) { | ||||||
|  |         className = name; | ||||||
|  |         v.visitClassType(remapper.mapType(name)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInnerClassType(String name) { | ||||||
|  |         String remappedOuter = remapper.mapType(className) + '$'; | ||||||
|  |         className = className + '$' + name; | ||||||
|  |         String remappedName = remapper.mapType(className); | ||||||
|  |         int index = remappedName.startsWith(remappedOuter) ? remappedOuter | ||||||
|  |                 .length() : remappedName.lastIndexOf('$') + 1; | ||||||
|  |         v.visitInnerClassType(remappedName.substring(index)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFormalTypeParameter(String name) { | ||||||
|  |         v.visitFormalTypeParameter(name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeVariable(String name) { | ||||||
|  |         v.visitTypeVariable(name); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitArrayType() { | ||||||
|  |         v.visitArrayType(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitBaseType(char descriptor) { | ||||||
|  |         v.visitBaseType(descriptor); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitClassBound() { | ||||||
|  |         v.visitClassBound(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitExceptionType() { | ||||||
|  |         v.visitExceptionType(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitInterface() { | ||||||
|  |         v.visitInterface(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitInterfaceBound() { | ||||||
|  |         v.visitInterfaceBound(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitParameterType() { | ||||||
|  |         v.visitParameterType(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitReturnType() { | ||||||
|  |         v.visitReturnType(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitSuperclass() { | ||||||
|  |         v.visitSuperclass(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeArgument() { | ||||||
|  |         v.visitTypeArgument(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitTypeArgument(char wildcard) { | ||||||
|  |         v.visitTypeArgument(wildcard); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |         v.visitEnd(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,515 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | import org.objectweb.asm.FieldVisitor; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.DataOutput; | ||||||
|  | import java.io.DataOutputStream; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.security.MessageDigest; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.Collection; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link ClassVisitor} that adds a serial version unique identifier to a | ||||||
|  |  * class if missing. Here is typical usage of this class: | ||||||
|  |  * | ||||||
|  |  * <pre> | ||||||
|  |  *   ClassWriter cw = new ClassWriter(...); | ||||||
|  |  *   ClassVisitor sv = new SerialVersionUIDAdder(cw); | ||||||
|  |  *   ClassVisitor ca = new MyClassAdapter(sv); | ||||||
|  |  *   new ClassReader(orginalClass).accept(ca, false); | ||||||
|  |  * </pre> | ||||||
|  |  * <p> | ||||||
|  |  * The SVUID algorithm can be found <a href= | ||||||
|  |  * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html" | ||||||
|  |  * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>: | ||||||
|  |  * | ||||||
|  |  * <pre> | ||||||
|  |  * The serialVersionUID is computed using the signature of a stream of bytes | ||||||
|  |  * that reflect the class definition. The National Institute of Standards and | ||||||
|  |  * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a | ||||||
|  |  * signature for the stream. The first two 32-bit quantities are used to form a | ||||||
|  |  * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data | ||||||
|  |  * types to a sequence of bytes. The values input to the stream are defined by | ||||||
|  |  * the Java Virtual Machine (VM) specification for classes. | ||||||
|  |  * | ||||||
|  |  * The sequence of items in the stream is as follows: | ||||||
|  |  * | ||||||
|  |  * 1. The class name written using UTF encoding. | ||||||
|  |  * 2. The class modifiers written as a 32-bit integer. | ||||||
|  |  * 3. The name of each interface sorted by name written using UTF encoding. | ||||||
|  |  * 4. For each field of the class sorted by field name (except private static | ||||||
|  |  * and private transient fields): | ||||||
|  |  * 1. The name of the field in UTF encoding. | ||||||
|  |  * 2. The modifiers of the field written as a 32-bit integer. | ||||||
|  |  * 3. The descriptor of the field in UTF encoding | ||||||
|  |  * 5. If a class initializer exists, write out the following: | ||||||
|  |  * 1. The name of the method, <clinit>, in UTF encoding. | ||||||
|  |  * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC, | ||||||
|  |  * written as a 32-bit integer. | ||||||
|  |  * 3. The descriptor of the method, ()V, in UTF encoding. | ||||||
|  |  * 6. For each non-private constructor sorted by method name and signature: | ||||||
|  |  * 1. The name of the method, <init>, in UTF encoding. | ||||||
|  |  * 2. The modifiers of the method written as a 32-bit integer. | ||||||
|  |  * 3. The descriptor of the method in UTF encoding. | ||||||
|  |  * 7. For each non-private method sorted by method name and signature: | ||||||
|  |  * 1. The name of the method in UTF encoding. | ||||||
|  |  * 2. The modifiers of the method written as a 32-bit integer. | ||||||
|  |  * 3. The descriptor of the method in UTF encoding. | ||||||
|  |  * 8. The SHA-1 algorithm is executed on the stream of bytes produced by | ||||||
|  |  * DataOutputStream and produces five 32-bit values sha[0..4]. | ||||||
|  |  * | ||||||
|  |  * 9. The hash value is assembled from the first and second 32-bit values of | ||||||
|  |  * the SHA-1 message digest. If the result of the message digest, the five | ||||||
|  |  * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named | ||||||
|  |  * sha, the hash value would be computed as follows: | ||||||
|  |  * | ||||||
|  |  * long hash = ((sha[0] >>> 24) & 0xFF) | | ||||||
|  |  * ((sha[0] >>> 16) & 0xFF) << 8 | | ||||||
|  |  * ((sha[0] >>> 8) & 0xFF) << 16 | | ||||||
|  |  * ((sha[0] >>> 0) & 0xFF) << 24 | | ||||||
|  |  * ((sha[1] >>> 24) & 0xFF) << 32 | | ||||||
|  |  * ((sha[1] >>> 16) & 0xFF) << 40 | | ||||||
|  |  * ((sha[1] >>> 8) & 0xFF) << 48 | | ||||||
|  |  * ((sha[1] >>> 0) & 0xFF) << 56; | ||||||
|  |  * </pre> | ||||||
|  |  * | ||||||
|  |  * @author Rajendra Inamdar, Vishal Vishnoi | ||||||
|  |  */ | ||||||
|  | public class SerialVersionUIDAdder extends ClassVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Collection of fields. (except private static and private transient | ||||||
|  |      * fields) | ||||||
|  |      */ | ||||||
|  |     private final Collection<Item> svuidFields; | ||||||
|  |     /** | ||||||
|  |      * Collection of non-private constructors. | ||||||
|  |      */ | ||||||
|  |     private final Collection<Item> svuidConstructors; | ||||||
|  |     /** | ||||||
|  |      * Collection of non-private methods. | ||||||
|  |      */ | ||||||
|  |     private final Collection<Item> svuidMethods; | ||||||
|  |     /** | ||||||
|  |      * Flag that indicates if we need to compute SVUID. | ||||||
|  |      */ | ||||||
|  |     private boolean computeSVUID; | ||||||
|  |     /** | ||||||
|  |      * Set to true if the class already has SVUID. | ||||||
|  |      */ | ||||||
|  |     private boolean hasSVUID; | ||||||
|  |     /** | ||||||
|  |      * Classes access flags. | ||||||
|  |      */ | ||||||
|  |     private int access; | ||||||
|  |     /** | ||||||
|  |      * Internal name of the class | ||||||
|  |      */ | ||||||
|  |     private String name; | ||||||
|  |     /** | ||||||
|  |      * Interfaces implemented by the class. | ||||||
|  |      */ | ||||||
|  |     private String[] interfaces; | ||||||
|  |     /** | ||||||
|  |      * Set to true if the class has static initializer. | ||||||
|  |      */ | ||||||
|  |     private boolean hasStaticInitializer; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use | ||||||
|  |      * this constructor</i>. Instead, they must use the | ||||||
|  |      * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version. | ||||||
|  |      * | ||||||
|  |      * @param cv a {@link ClassVisitor} to which this visitor will delegate | ||||||
|  |      *           calls. | ||||||
|  |      */ | ||||||
|  |     public SerialVersionUIDAdder(final ClassVisitor cv) { | ||||||
|  |         this(Opcodes.ASM4, cv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Creates a new {@link SerialVersionUIDAdder}. | ||||||
|  |      * | ||||||
|  |      * @param api the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param cv  a {@link ClassVisitor} to which this visitor will delegate | ||||||
|  |      *            calls. | ||||||
|  |      */ | ||||||
|  |     protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) { | ||||||
|  |         super(api, cv); | ||||||
|  |         svuidFields = new ArrayList<>(); | ||||||
|  |         svuidConstructors = new ArrayList<>(); | ||||||
|  |         svuidMethods = new ArrayList<>(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Overriden methods | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sorts the items in the collection and writes it to the data output stream | ||||||
|  |      * | ||||||
|  |      * @param itemCollection collection of items | ||||||
|  |      * @param dos            a <code>DataOutputStream</code> value | ||||||
|  |      * @param dotted         a <code>boolean</code> value | ||||||
|  |      * @throws IOException if an error occurs | ||||||
|  |      */ | ||||||
|  |     private static void writeItems(final Collection<Item> itemCollection, | ||||||
|  |                                    final DataOutput dos, final boolean dotted) throws IOException { | ||||||
|  |         int size = itemCollection.size(); | ||||||
|  |         Item[] items = itemCollection.toArray(new Item[size]); | ||||||
|  |         Arrays.sort(items); | ||||||
|  |         for (int i = 0; i < size; i++) { | ||||||
|  |             dos.writeUTF(items[i].name); | ||||||
|  |             dos.writeInt(items[i].access); | ||||||
|  |             dos.writeUTF(dotted ? items[i].desc.replace('/', '.') | ||||||
|  |                     : items[i].desc); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |      * Visit class header and get class name, access , and interfaces | ||||||
|  |      * information (step 1,2, and 3) for SVUID computation. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void visit(final int version, final int access, final String name, | ||||||
|  |                       final String signature, final String superName, | ||||||
|  |                       final String[] interfaces) { | ||||||
|  |         computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0; | ||||||
|  | 
 | ||||||
|  |         if (computeSVUID) { | ||||||
|  |             this.name = name; | ||||||
|  |             this.access = access; | ||||||
|  |             this.interfaces = interfaces; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         super.visit(version, access, name, signature, superName, interfaces); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |      * Visit the methods and get constructor and method information (step 5 and | ||||||
|  |      * 7). Also determine if there is a class initializer (step 6). | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public MethodVisitor visitMethod(final int access, final String name, | ||||||
|  |                                      final String desc, final String signature, final String[] exceptions) { | ||||||
|  |         if (computeSVUID) { | ||||||
|  |             if ("<clinit>".equals(name)) { | ||||||
|  |                 hasStaticInitializer = true; | ||||||
|  |             } | ||||||
|  |             /* | ||||||
|  |              * Remembers non private constructors and methods for SVUID | ||||||
|  |              * computation For constructor and method modifiers, only the | ||||||
|  |              * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, | ||||||
|  |              * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags | ||||||
|  |              * are used. | ||||||
|  |              */ | ||||||
|  |             int mods = access | ||||||
|  |                     & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | ||||||
|  |                     | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC | ||||||
|  |                     | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED | ||||||
|  |                     | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT); | ||||||
|  | 
 | ||||||
|  |             // all non private methods | ||||||
|  |             if ((access & Opcodes.ACC_PRIVATE) == 0) { | ||||||
|  |                 if ("<init>".equals(name)) { | ||||||
|  |                     svuidConstructors.add(new Item(name, mods, desc)); | ||||||
|  |                 } else if (!"<clinit>".equals(name)) { | ||||||
|  |                     svuidMethods.add(new Item(name, mods, desc)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return super.visitMethod(access, name, desc, signature, exceptions); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |      * Gets class field information for step 4 of the algorithm. Also determines | ||||||
|  |      * if the class already has a SVUID. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public FieldVisitor visitField(final int access, final String name, | ||||||
|  |                                    final String desc, final String signature, final Object value) { | ||||||
|  |         if (computeSVUID) { | ||||||
|  |             if ("serialVersionUID".equals(name)) { | ||||||
|  |                 // since the class already has SVUID, we won't be computing it. | ||||||
|  |                 computeSVUID = false; | ||||||
|  |                 hasSVUID = true; | ||||||
|  |             } | ||||||
|  |             /* | ||||||
|  |              * Remember field for SVUID computation For field modifiers, only | ||||||
|  |              * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, | ||||||
|  |              * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when | ||||||
|  |              * computing serialVersionUID values. | ||||||
|  |              */ | ||||||
|  |             if ((access & Opcodes.ACC_PRIVATE) == 0 | ||||||
|  |                     || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) { | ||||||
|  |                 int mods = access | ||||||
|  |                         & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | ||||||
|  |                         | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC | ||||||
|  |                         | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT); | ||||||
|  |                 svuidFields.add(new Item(name, mods, desc)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return super.visitField(access, name, desc, signature, value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Handle a bizarre special case. Nested classes (static classes declared | ||||||
|  |      * inside another class) that are protected have their access bit set to | ||||||
|  |      * public in their class files to deal with some odd reflection situation. | ||||||
|  |      * Our SVUID computation must do as the JVM does and ignore access bits in | ||||||
|  |      * the class file in favor of the access bits InnerClass attribute. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void visitInnerClass(final String aname, final String outerName, | ||||||
|  |                                 final String innerName, final int attr_access) { | ||||||
|  |         if ((name != null) && name.equals(aname)) { | ||||||
|  |             this.access = attr_access; | ||||||
|  |         } | ||||||
|  |         super.visitInnerClass(aname, outerName, innerName, attr_access); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Utility methods | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /* | ||||||
|  |      * Add the SVUID if class doesn't have one | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |         // compute SVUID and add it to the class | ||||||
|  |         if (computeSVUID && !hasSVUID) { | ||||||
|  |             try { | ||||||
|  |                 addSVUID(computeSVUID()); | ||||||
|  |             } catch (Throwable e) { | ||||||
|  |                 throw new RuntimeException("Error while computing SVUID for " | ||||||
|  |                         + name, e); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         super.visitEnd(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns true if the class already has a SVUID field. The result of this | ||||||
|  |      * method is only valid when visitEnd is or has been called. | ||||||
|  |      * | ||||||
|  |      * @return true if the class already has a SVUID field. | ||||||
|  |      */ | ||||||
|  |     public boolean hasSVUID() { | ||||||
|  |         return hasSVUID; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected void addSVUID(long svuid) { | ||||||
|  |         FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL | ||||||
|  |                 + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, svuid); | ||||||
|  |         if (null != fv) { | ||||||
|  |             fv.visitEnd(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Computes and returns the value of SVUID. | ||||||
|  |      * | ||||||
|  |      * @return Returns the serial version UID | ||||||
|  |      * @throws IOException if an I/O error occurs | ||||||
|  |      */ | ||||||
|  |     protected long computeSVUID() throws IOException { | ||||||
|  |         ByteArrayOutputStream bos; | ||||||
|  |         DataOutputStream dos = null; | ||||||
|  |         long svuid = 0; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             bos = new ByteArrayOutputStream(); | ||||||
|  |             dos = new DataOutputStream(bos); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 1. The class name written using UTF encoding. | ||||||
|  |              */ | ||||||
|  |             dos.writeUTF(name.replace('/', '.')); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 2. The class modifiers written as a 32-bit integer. | ||||||
|  |              */ | ||||||
|  |             dos.writeInt(access | ||||||
|  |                     & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | ||||||
|  |                     | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT)); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 3. The name of each interface sorted by name written using UTF | ||||||
|  |              * encoding. | ||||||
|  |              */ | ||||||
|  |             Arrays.sort(interfaces); | ||||||
|  |             for (String anInterface : interfaces) { | ||||||
|  |                 dos.writeUTF(anInterface.replace('/', '.')); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 4. For each field of the class sorted by field name (except | ||||||
|  |              * private static and private transient fields): | ||||||
|  |              * | ||||||
|  |              * 1. The name of the field in UTF encoding. 2. The modifiers of the | ||||||
|  |              * field written as a 32-bit integer. 3. The descriptor of the field | ||||||
|  |              * in UTF encoding | ||||||
|  |              * | ||||||
|  |              * Note that field signatures are not dot separated. Method and | ||||||
|  |              * constructor signatures are dot separated. Go figure... | ||||||
|  |              */ | ||||||
|  |             writeItems(svuidFields, dos, false); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 5. If a class initializer exists, write out the following: 1. The | ||||||
|  |              * name of the method, <clinit>, in UTF encoding. 2. The modifier of | ||||||
|  |              * the method, java.lang.reflect.Modifier.STATIC, written as a | ||||||
|  |              * 32-bit integer. 3. The descriptor of the method, ()V, in UTF | ||||||
|  |              * encoding. | ||||||
|  |              */ | ||||||
|  |             if (hasStaticInitializer) { | ||||||
|  |                 dos.writeUTF("<clinit>"); | ||||||
|  |                 dos.writeInt(Opcodes.ACC_STATIC); | ||||||
|  |                 dos.writeUTF("()V"); | ||||||
|  |             } // if.. | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 6. For each non-private constructor sorted by method name and | ||||||
|  |              * signature: 1. The name of the method, <init>, in UTF encoding. 2. | ||||||
|  |              * The modifiers of the method written as a 32-bit integer. 3. The | ||||||
|  |              * descriptor of the method in UTF encoding. | ||||||
|  |              */ | ||||||
|  |             writeItems(svuidConstructors, dos, true); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 7. For each non-private method sorted by method name and | ||||||
|  |              * signature: 1. The name of the method in UTF encoding. 2. The | ||||||
|  |              * modifiers of the method written as a 32-bit integer. 3. The | ||||||
|  |              * descriptor of the method in UTF encoding. | ||||||
|  |              */ | ||||||
|  |             writeItems(svuidMethods, dos, true); | ||||||
|  | 
 | ||||||
|  |             dos.flush(); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 8. The SHA-1 algorithm is executed on the stream of bytes | ||||||
|  |              * produced by DataOutputStream and produces five 32-bit values | ||||||
|  |              * sha[0..4]. | ||||||
|  |              */ | ||||||
|  |             byte[] hashBytes = computeSHAdigest(bos.toByteArray()); | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |              * 9. The hash value is assembled from the first and second 32-bit | ||||||
|  |              * values of the SHA-1 message digest. If the result of the message | ||||||
|  |              * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of | ||||||
|  |              * five int values named sha, the hash value would be computed as | ||||||
|  |              * follows: | ||||||
|  |              * | ||||||
|  |              * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) | ||||||
|  |              * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) << | ||||||
|  |              * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) << | ||||||
|  |              * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) << | ||||||
|  |              * 56; | ||||||
|  |              */ | ||||||
|  |             for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) { | ||||||
|  |                 svuid = (svuid << 8) | (hashBytes[i] & 0xFF); | ||||||
|  |             } | ||||||
|  |         } finally { | ||||||
|  |             // close the stream (if open) | ||||||
|  |             if (dos != null) { | ||||||
|  |                 dos.close(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return svuid; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the SHA-1 message digest of the given value. | ||||||
|  |      * | ||||||
|  |      * @param value the value whose SHA message digest must be computed. | ||||||
|  |      * @return the SHA-1 message digest of the given value. | ||||||
|  |      */ | ||||||
|  |     protected byte[] computeSHAdigest(final byte[] value) { | ||||||
|  |         try { | ||||||
|  |             return MessageDigest.getInstance("SHA").digest(value); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             throw new UnsupportedOperationException(e.toString()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Inner classes | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     private static class Item implements Comparable<Item> { | ||||||
|  | 
 | ||||||
|  |         final String name; | ||||||
|  | 
 | ||||||
|  |         final int access; | ||||||
|  | 
 | ||||||
|  |         final String desc; | ||||||
|  | 
 | ||||||
|  |         Item(final String name, final int access, final String desc) { | ||||||
|  |             this.name = name; | ||||||
|  |             this.access = access; | ||||||
|  |             this.desc = desc; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public int compareTo(final Item other) { | ||||||
|  |             int retVal = name.compareTo(other.name); | ||||||
|  |             if (retVal == 0) { | ||||||
|  |                 retVal = desc.compareTo(other.desc); | ||||||
|  |             } | ||||||
|  |             return retVal; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean equals(final Object o) { | ||||||
|  |             if (o instanceof Item) { | ||||||
|  |                 return compareTo((Item) o) == 0; | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public int hashCode() { | ||||||
|  |             return (name + desc).hashCode(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								src/main/asm/org/objectweb/asm/commons/SimpleRemapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/main/asm/org/objectweb/asm/commons/SimpleRemapper.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link Remapper} using a {@link Map} to define its mapping. | ||||||
|  |  *  | ||||||
|  |  * @author Eugene Kuleshov | ||||||
|  |  */ | ||||||
|  | public class SimpleRemapper extends Remapper { | ||||||
|  | 
 | ||||||
|  |     private final Map<String, String> mapping; | ||||||
|  | 
 | ||||||
|  |     public SimpleRemapper(Map<String, String> mapping) { | ||||||
|  |         this.mapping = mapping; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public SimpleRemapper(String oldName, String newName) { | ||||||
|  |         this.mapping = Collections.singletonMap(oldName, newName); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String mapMethodName(String owner, String name, String desc) { | ||||||
|  |         String s = map(owner + '.' + name + desc); | ||||||
|  |         return s == null ? name : s; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String mapFieldName(String owner, String name, String desc) { | ||||||
|  |         String s = map(owner + '.' + name); | ||||||
|  |         return s == null ? name : s; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String map(String key) { | ||||||
|  |         return mapping.get(key); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										96
									
								
								src/main/asm/org/objectweb/asm/commons/StaticInitMerger.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/main/asm/org/objectweb/asm/commons/StaticInitMerger.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link ClassVisitor} that merges clinit methods into a single one. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class StaticInitMerger extends ClassVisitor { | ||||||
|  | 
 | ||||||
|  |     private String name; | ||||||
|  | 
 | ||||||
|  |     private MethodVisitor clinit; | ||||||
|  | 
 | ||||||
|  |     private final String prefix; | ||||||
|  | 
 | ||||||
|  |     private int counter; | ||||||
|  | 
 | ||||||
|  |     public StaticInitMerger(final String prefix, final ClassVisitor cv) { | ||||||
|  |         this(Opcodes.ASM4, prefix, cv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected StaticInitMerger(final int api, final String prefix, | ||||||
|  |             final ClassVisitor cv) { | ||||||
|  |         super(api, cv); | ||||||
|  |         this.prefix = prefix; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visit(final int version, final int access, final String name, | ||||||
|  |             final String signature, final String superName, | ||||||
|  |             final String[] interfaces) { | ||||||
|  |         cv.visit(version, access, name, signature, superName, interfaces); | ||||||
|  |         this.name = name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public MethodVisitor visitMethod(final int access, final String name, | ||||||
|  |             final String desc, final String signature, final String[] exceptions) { | ||||||
|  |         MethodVisitor mv; | ||||||
|  |         if ("<clinit>".equals(name)) { | ||||||
|  |             int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC; | ||||||
|  |             String n = prefix + counter++; | ||||||
|  |             mv = cv.visitMethod(a, n, desc, signature, exceptions); | ||||||
|  | 
 | ||||||
|  |             if (clinit == null) { | ||||||
|  |                 clinit = cv.visitMethod(a, name, desc, null, null); | ||||||
|  |             } | ||||||
|  |             clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc); | ||||||
|  |         } else { | ||||||
|  |             mv = cv.visitMethod(access, name, desc, signature, exceptions); | ||||||
|  |         } | ||||||
|  |         return mv; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |         if (clinit != null) { | ||||||
|  |             clinit.visitInsn(Opcodes.RETURN); | ||||||
|  |             clinit.visitMaxs(0, 0); | ||||||
|  |         } | ||||||
|  |         cv.visitEnd(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,57 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A code generator for switch statements. | ||||||
|  |  *  | ||||||
|  |  * @author Juozas Baliuka | ||||||
|  |  * @author Chris Nokleberg | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public interface TableSwitchGenerator { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Generates the code for a switch case. | ||||||
|  |      *  | ||||||
|  |      * @param key | ||||||
|  |      *            the switch case key. | ||||||
|  |      * @param end | ||||||
|  |      *            a label that corresponds to the end of the switch statement. | ||||||
|  |      */ | ||||||
|  |     void generateCase(int key, Label end); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Generates the code for the default switch case. | ||||||
|  |      */ | ||||||
|  |     void generateDefault(); | ||||||
|  | } | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.objectweb.asm.commons; | ||||||
|  | 
 | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.Comparator; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | import org.objectweb.asm.tree.MethodNode; | ||||||
|  | import org.objectweb.asm.tree.TryCatchBlockNode; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers | ||||||
|  |  * are sorted in a method innermost-to-outermost. This allows the programmer to | ||||||
|  |  * add handlers without worrying about ordering them correctly with respect to | ||||||
|  |  * existing, in-code handlers. | ||||||
|  |  *  | ||||||
|  |  * Behavior is only defined for properly-nested handlers. If any "try" blocks | ||||||
|  |  * overlap (something that isn't possible in Java code) then this may not do | ||||||
|  |  * what you want. In fact, this adapter just sorts by the length of the "try" | ||||||
|  |  * block, taking advantage of the fact that a given try block must be larger | ||||||
|  |  * than any block it contains). | ||||||
|  |  *  | ||||||
|  |  * @author Adrian Sampson | ||||||
|  |  */ | ||||||
|  | public class TryCatchBlockSorter extends MethodNode { | ||||||
|  | 
 | ||||||
|  |     public TryCatchBlockSorter(final MethodVisitor mv, final int access, | ||||||
|  |             final String name, final String desc, final String signature, | ||||||
|  |             final String[] exceptions) { | ||||||
|  |         this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected TryCatchBlockSorter(final int api, final MethodVisitor mv, | ||||||
|  |             final int access, final String name, final String desc, | ||||||
|  |             final String signature, final String[] exceptions) { | ||||||
|  |         super(api, access, name, desc, signature, exceptions); | ||||||
|  |         this.mv = mv; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |         // Compares TryCatchBlockNodes by the length of their "try" block. | ||||||
|  |         Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() { | ||||||
|  | 
 | ||||||
|  |             public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) { | ||||||
|  |                 int len1 = blockLength(t1); | ||||||
|  |                 int len2 = blockLength(t2); | ||||||
|  |                 return len1 - len2; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             private int blockLength(TryCatchBlockNode block) { | ||||||
|  |                 int startidx = instructions.indexOf(block.start); | ||||||
|  |                 int endidx = instructions.indexOf(block.end); | ||||||
|  |                 return endidx - startidx; | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Collections.sort(tryCatchBlocks, comp); | ||||||
|  |         if (mv != null) { | ||||||
|  |             accept(mv); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								src/main/asm/org/objectweb/asm/commons/package.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/main/asm/org/objectweb/asm/commons/package.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | <html> | ||||||
|  | <!-- | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | --> | ||||||
|  | <body> | ||||||
|  | Provides some useful class and method adapters. <i>The preferred way of using | ||||||
|  | these adapters is by chaining them together and to custom adapters (instead of | ||||||
|  | inheriting from them)</i>. Indeed this approach provides more combination | ||||||
|  | possibilities than inheritance. For instance, suppose you want to implement an | ||||||
|  | adapter MyAdapter than needs sorted local variables and intermediate stack map | ||||||
|  | frame values taking into account the local variables sort. By using inheritance, | ||||||
|  | this would require MyAdapter to extend AnalyzerAdapter, itself extending | ||||||
|  | LocalVariablesSorter. But AnalyzerAdapter is not a subclass of | ||||||
|  | LocalVariablesSorter, so this is not possible. On the contrary, by using | ||||||
|  | delegation, you can make LocalVariablesSorter delegate to AnalyzerAdapter, | ||||||
|  | itself delegating to MyAdapter. In this case AnalyzerAdapter computes | ||||||
|  | intermediate frames based on the output of LocalVariablesSorter, and MyAdapter | ||||||
|  | can add new locals by calling the newLocal method on LocalVariablesSorter, and | ||||||
|  | can get the stack map frame state before each instruction by reading the locals | ||||||
|  | and stack fields in AnalyzerAdapter (this requires references from MyAdapter | ||||||
|  | back to LocalVariablesSorter and AnalyzerAdapter). | ||||||
|  | </body> | ||||||
							
								
								
									
										87
									
								
								src/main/asm/org/objectweb/asm/package.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/main/asm/org/objectweb/asm/package.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | |||||||
|  | <html> | ||||||
|  | <!-- | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | --> | ||||||
|  | <body> | ||||||
|  | Provides a small and fast bytecode manipulation framework. | ||||||
|  | 
 | ||||||
|  | <p> | ||||||
|  | The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized | ||||||
|  | around the {@link org.objectweb.asm.ClassVisitor ClassVisitor}, | ||||||
|  | {@link org.objectweb.asm.FieldVisitor FieldVisitor}, | ||||||
|  | {@link org.objectweb.asm.MethodVisitor MethodVisitor} and | ||||||
|  | {@link org.objectweb.asm.AnnotationVisitor AnnotationVisitor} abstract classes, | ||||||
|  | which allow one to visit the fields, methods and annotations of a class, | ||||||
|  | including the bytecode instructions of each method. | ||||||
|  | 
 | ||||||
|  | <p> | ||||||
|  | In addition to these main abstract classes, ASM provides a {@link | ||||||
|  | org.objectweb.asm.ClassReader ClassReader} class, that can parse an | ||||||
|  | existing class and make a given visitor visit it. ASM also provides | ||||||
|  | a {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is | ||||||
|  | a visitor that generates Java class files. | ||||||
|  | 
 | ||||||
|  | <p> | ||||||
|  | In order to generate a class from scratch, only the {@link | ||||||
|  | org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed, | ||||||
|  | in order to generate a class, one must just call its visit<i>Xxx</i> | ||||||
|  | methods with the appropriate arguments to generate the desired fields | ||||||
|  | and methods. See the "helloworld" example in the ASM distribution for | ||||||
|  | more details about class generation. | ||||||
|  | 
 | ||||||
|  | <p> | ||||||
|  | In order to modify existing classes, one must use a {@link | ||||||
|  | org.objectweb.asm.ClassReader ClassReader} class to analyze | ||||||
|  | the original class, a class modifier, and a {@link org.objectweb.asm.ClassWriter | ||||||
|  | ClassWriter} to construct the modified class. The class modifier | ||||||
|  | is just a {@link org.objectweb.asm.ClassVisitor ClassVisitor} | ||||||
|  | that delegates most of the work to another {@link org.objectweb.asm.ClassVisitor | ||||||
|  | ClassVisitor}, but that sometimes changes some parameter values, | ||||||
|  | or call additional methods, in order to implement the desired | ||||||
|  | modification process. In order to make it easier to implement such | ||||||
|  | class modifiers, the {@link org.objectweb.asm.ClassVisitor | ||||||
|  | ClassVisitor} and {@link org.objectweb.asm.MethodVisitor MethodVisitor} | ||||||
|  | classes delegate by default all the method calls they receive to an | ||||||
|  | optional visitor. See the "adapt" example in the ASM | ||||||
|  | distribution for more details about class modification. | ||||||
|  | 
 | ||||||
|  | <p> | ||||||
|  | The size of the core ASM library, <tt>asm.jar</tt>, is only 45KB, which is much | ||||||
|  | smaller than the size of the | ||||||
|  | <a href="http://jakarta.apache.org/bcel">BCEL</a> library (504KB), and than the | ||||||
|  | size of the | ||||||
|  | <a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also | ||||||
|  | much faster than these tools. Indeed the overhead of a load time class | ||||||
|  | transformation process is of the order of 60% with ASM, 700% or more with BCEL, | ||||||
|  | and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM | ||||||
|  | distribution)! | ||||||
|  | 
 | ||||||
|  | @since ASM 1.3 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										228
									
								
								src/main/asm/org/objectweb/asm/signature/SignatureReader.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								src/main/asm/org/objectweb/asm/signature/SignatureReader.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,228 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.signature; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A type signature parser to make a signature visitor visit an existing | ||||||
|  |  * signature. | ||||||
|  |  *  | ||||||
|  |  * @author Thomas Hallgren | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class SignatureReader { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The signature to be read. | ||||||
|  |      */ | ||||||
|  |     private final String signature; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a {@link SignatureReader} for the given signature. | ||||||
|  |      *  | ||||||
|  |      * @param signature | ||||||
|  |      *            A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or | ||||||
|  |      *            <i>FieldTypeSignature</i>. | ||||||
|  |      */ | ||||||
|  |     public SignatureReader(final String signature) { | ||||||
|  |         this.signature = signature; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given visitor visit the signature of this | ||||||
|  |      * {@link SignatureReader}. This signature is the one specified in the | ||||||
|  |      * constructor (see {@link #SignatureReader(String) SignatureReader}). This | ||||||
|  |      * method is intended to be called on a {@link SignatureReader} that was | ||||||
|  |      * created using a <i>ClassSignature</i> (such as the <code>signature</code> | ||||||
|  |      * parameter of the {@link org.objectweb.asm.ClassVisitor#visit | ||||||
|  |      * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the | ||||||
|  |      * <code>signature</code> parameter of the | ||||||
|  |      * {@link org.objectweb.asm.ClassVisitor#visitMethod | ||||||
|  |      * ClassVisitor.visitMethod} method). | ||||||
|  |      *  | ||||||
|  |      * @param v | ||||||
|  |      *            the visitor that must visit this signature. | ||||||
|  |      */ | ||||||
|  |     public void accept(final SignatureVisitor v) { | ||||||
|  |         String signature = this.signature; | ||||||
|  |         int len = signature.length(); | ||||||
|  |         int pos; | ||||||
|  |         char c; | ||||||
|  | 
 | ||||||
|  |         if (signature.charAt(0) == '<') { | ||||||
|  |             pos = 2; | ||||||
|  |             do { | ||||||
|  |                 int end = signature.indexOf(':', pos); | ||||||
|  |                 v.visitFormalTypeParameter(signature.substring(pos - 1, end)); | ||||||
|  |                 pos = end + 1; | ||||||
|  | 
 | ||||||
|  |                 c = signature.charAt(pos); | ||||||
|  |                 if (c == 'L' || c == '[' || c == 'T') { | ||||||
|  |                     pos = parseType(signature, pos, v.visitClassBound()); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 while ((c = signature.charAt(pos++)) == ':') { | ||||||
|  |                     pos = parseType(signature, pos, v.visitInterfaceBound()); | ||||||
|  |                 } | ||||||
|  |             } while (c != '>'); | ||||||
|  |         } else { | ||||||
|  |             pos = 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (signature.charAt(pos) == '(') { | ||||||
|  |             pos++; | ||||||
|  |             while (signature.charAt(pos) != ')') { | ||||||
|  |                 pos = parseType(signature, pos, v.visitParameterType()); | ||||||
|  |             } | ||||||
|  |             pos = parseType(signature, pos + 1, v.visitReturnType()); | ||||||
|  |             while (pos < len) { | ||||||
|  |                 pos = parseType(signature, pos + 1, v.visitExceptionType()); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             pos = parseType(signature, pos, v.visitSuperclass()); | ||||||
|  |             while (pos < len) { | ||||||
|  |                 pos = parseType(signature, pos, v.visitInterface()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given visitor visit the signature of this | ||||||
|  |      * {@link SignatureReader}. This signature is the one specified in the | ||||||
|  |      * constructor (see {@link #SignatureReader(String) SignatureReader}). This | ||||||
|  |      * method is intended to be called on a {@link SignatureReader} that was | ||||||
|  |      * created using a <i>FieldTypeSignature</i>, such as the | ||||||
|  |      * <code>signature</code> parameter of the | ||||||
|  |      * {@link org.objectweb.asm.ClassVisitor#visitField ClassVisitor.visitField} | ||||||
|  |      * or {@link org.objectweb.asm.MethodVisitor#visitLocalVariable | ||||||
|  |      * MethodVisitor.visitLocalVariable} methods. | ||||||
|  |      *  | ||||||
|  |      * @param v | ||||||
|  |      *            the visitor that must visit this signature. | ||||||
|  |      */ | ||||||
|  |     public void acceptType(final SignatureVisitor v) { | ||||||
|  |         parseType(this.signature, 0, v); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Parses a field type signature and makes the given visitor visit it. | ||||||
|  |      *  | ||||||
|  |      * @param signature | ||||||
|  |      *            a string containing the signature that must be parsed. | ||||||
|  |      * @param pos | ||||||
|  |      *            index of the first character of the signature to parsed. | ||||||
|  |      * @param v | ||||||
|  |      *            the visitor that must visit this signature. | ||||||
|  |      * @return the index of the first character after the parsed signature. | ||||||
|  |      */ | ||||||
|  |     private static int parseType(final String signature, int pos, | ||||||
|  |             final SignatureVisitor v) { | ||||||
|  |         char c; | ||||||
|  |         int start, end; | ||||||
|  |         boolean visited, inner; | ||||||
|  |         String name; | ||||||
|  | 
 | ||||||
|  |         switch (c = signature.charAt(pos++)) { | ||||||
|  |         case 'Z': | ||||||
|  |         case 'C': | ||||||
|  |         case 'B': | ||||||
|  |         case 'S': | ||||||
|  |         case 'I': | ||||||
|  |         case 'F': | ||||||
|  |         case 'J': | ||||||
|  |         case 'D': | ||||||
|  |         case 'V': | ||||||
|  |             v.visitBaseType(c); | ||||||
|  |             return pos; | ||||||
|  | 
 | ||||||
|  |         case '[': | ||||||
|  |             return parseType(signature, pos, v.visitArrayType()); | ||||||
|  | 
 | ||||||
|  |         case 'T': | ||||||
|  |             end = signature.indexOf(';', pos); | ||||||
|  |             v.visitTypeVariable(signature.substring(pos, end)); | ||||||
|  |             return end + 1; | ||||||
|  | 
 | ||||||
|  |         default: // case 'L': | ||||||
|  |             start = pos; | ||||||
|  |             visited = false; | ||||||
|  |             inner = false; | ||||||
|  |             for (;;) { | ||||||
|  |                 switch (c = signature.charAt(pos++)) { | ||||||
|  |                 case '.': | ||||||
|  |                 case ';': | ||||||
|  |                     if (!visited) { | ||||||
|  |                         name = signature.substring(start, pos - 1); | ||||||
|  |                         if (inner) { | ||||||
|  |                             v.visitInnerClassType(name); | ||||||
|  |                         } else { | ||||||
|  |                             v.visitClassType(name); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     if (c == ';') { | ||||||
|  |                         v.visitEnd(); | ||||||
|  |                         return pos; | ||||||
|  |                     } | ||||||
|  |                     start = pos; | ||||||
|  |                     visited = false; | ||||||
|  |                     inner = true; | ||||||
|  |                     break; | ||||||
|  | 
 | ||||||
|  |                 case '<': | ||||||
|  |                     name = signature.substring(start, pos - 1); | ||||||
|  |                     if (inner) { | ||||||
|  |                         v.visitInnerClassType(name); | ||||||
|  |                     } else { | ||||||
|  |                         v.visitClassType(name); | ||||||
|  |                     } | ||||||
|  |                     visited = true; | ||||||
|  |                     top: for (;;) { | ||||||
|  |                         switch (c = signature.charAt(pos)) { | ||||||
|  |                         case '>': | ||||||
|  |                             break top; | ||||||
|  |                         case '*': | ||||||
|  |                             ++pos; | ||||||
|  |                             v.visitTypeArgument(); | ||||||
|  |                             break; | ||||||
|  |                         case '+': | ||||||
|  |                         case '-': | ||||||
|  |                             pos = parseType(signature, pos + 1, | ||||||
|  |                                     v.visitTypeArgument(c)); | ||||||
|  |                             break; | ||||||
|  |                         default: | ||||||
|  |                             pos = parseType(signature, pos, | ||||||
|  |                                     v.visitTypeArgument('=')); | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										235
									
								
								src/main/asm/org/objectweb/asm/signature/SignatureVisitor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								src/main/asm/org/objectweb/asm/signature/SignatureVisitor.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,235 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.signature; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A visitor to visit a generic signature. The methods of this interface must be | ||||||
|  |  * called in one of the three following orders (the last one is the only valid | ||||||
|  |  * order for a {@link SignatureVisitor} that is returned by a method of this | ||||||
|  |  * interface): | ||||||
|  |  * <ul> | ||||||
|  |  * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt> | ||||||
|  |  * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( | ||||||
|  |  * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li> | ||||||
|  |  * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt> | ||||||
|  |  * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* ( | ||||||
|  |  * <tt>visitParameterType</tt>* <tt>visitReturnType</tt> | ||||||
|  |  * <tt>visitExceptionType</tt>* )</li> | ||||||
|  |  * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> | | ||||||
|  |  * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | ( | ||||||
|  |  * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* ( | ||||||
|  |  * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt> | ||||||
|  |  * ) )</li> | ||||||
|  |  * </ul> | ||||||
|  |  *  | ||||||
|  |  * @author Thomas Hallgren | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public abstract class SignatureVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Wildcard for an "extends" type argument. | ||||||
|  |      */ | ||||||
|  |     public final static char EXTENDS = '+'; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Wildcard for a "super" type argument. | ||||||
|  |      */ | ||||||
|  |     public final static char SUPER = '-'; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Wildcard for a normal type argument. | ||||||
|  |      */ | ||||||
|  |     public final static char INSTANCEOF = '='; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The ASM API version implemented by this visitor. The value of this field | ||||||
|  |      * must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     protected final int api; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link SignatureVisitor}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor(final int api) { | ||||||
|  |         this.api = api; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a formal type parameter. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the name of the formal parameter. | ||||||
|  |      */ | ||||||
|  |     public void visitFormalTypeParameter(String name) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the class bound of the last visited formal type parameter. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the class bound. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitClassBound() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an interface bound of the last visited formal type parameter. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the interface bound. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitInterfaceBound() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the type of the super class. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the super class | ||||||
|  |      *         type. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitSuperclass() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the type of an interface implemented by the class. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the interface type. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitInterface() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the type of a method parameter. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the parameter type. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitParameterType() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the return type of the method. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the return type. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitReturnType() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits the type of a method exception. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the exception type. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitExceptionType() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a signature corresponding to a primitive type. | ||||||
|  |      *  | ||||||
|  |      * @param descriptor | ||||||
|  |      *            the descriptor of the primitive type, or 'V' for <tt>void</tt> | ||||||
|  |      *            . | ||||||
|  |      */ | ||||||
|  |     public void visitBaseType(char descriptor) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a signature corresponding to a type variable. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the name of the type variable. | ||||||
|  |      */ | ||||||
|  |     public void visitTypeVariable(String name) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a signature corresponding to an array type. | ||||||
|  |      *  | ||||||
|  |      * @return a non null visitor to visit the signature of the array element | ||||||
|  |      *         type. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitArrayType() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Starts the visit of a signature corresponding to a class or interface | ||||||
|  |      * type. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the internal name of the class or interface. | ||||||
|  |      */ | ||||||
|  |     public void visitClassType(String name) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an inner class. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the local name of the inner class in its enclosing class. | ||||||
|  |      */ | ||||||
|  |     public void visitInnerClassType(String name) { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits an unbounded type argument of the last visited class or inner | ||||||
|  |      * class type. | ||||||
|  |      */ | ||||||
|  |     public void visitTypeArgument() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Visits a type argument of the last visited class or inner class type. | ||||||
|  |      *  | ||||||
|  |      * @param wildcard | ||||||
|  |      *            '+', '-' or '='. | ||||||
|  |      * @return a non null visitor to visit the signature of the type argument. | ||||||
|  |      */ | ||||||
|  |     public SignatureVisitor visitTypeArgument(char wildcard) { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Ends the visit of a signature corresponding to a class or interface type. | ||||||
|  |      */ | ||||||
|  |     public void visitEnd() { | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										227
									
								
								src/main/asm/org/objectweb/asm/signature/SignatureWriter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								src/main/asm/org/objectweb/asm/signature/SignatureWriter.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,227 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.signature; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A signature visitor that generates signatures in string format. | ||||||
|  |  *  | ||||||
|  |  * @author Thomas Hallgren | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class SignatureWriter extends SignatureVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Buffer used to construct the signature. | ||||||
|  |      */ | ||||||
|  |     private final StringBuffer buf = new StringBuffer(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if the signature contains formal type parameters. | ||||||
|  |      */ | ||||||
|  |     private boolean hasFormals; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates if the signature contains method parameter types. | ||||||
|  |      */ | ||||||
|  |     private boolean hasParameters; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Stack used to keep track of class types that have arguments. Each element | ||||||
|  |      * of this stack is a boolean encoded in one bit. The top of the stack is | ||||||
|  |      * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = | ||||||
|  |      * /2. | ||||||
|  |      */ | ||||||
|  |     private int argumentStack; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link SignatureWriter} object. | ||||||
|  |      */ | ||||||
|  |     public SignatureWriter() { | ||||||
|  |         super(Opcodes.ASM4); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Implementation of the SignatureVisitor interface | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitFormalTypeParameter(final String name) { | ||||||
|  |         if (!hasFormals) { | ||||||
|  |             hasFormals = true; | ||||||
|  |             buf.append('<'); | ||||||
|  |         } | ||||||
|  |         buf.append(name); | ||||||
|  |         buf.append(':'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitClassBound() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitInterfaceBound() { | ||||||
|  |         buf.append(':'); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitSuperclass() { | ||||||
|  |         endFormals(); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitInterface() { | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitParameterType() { | ||||||
|  |         endFormals(); | ||||||
|  |         if (!hasParameters) { | ||||||
|  |             hasParameters = true; | ||||||
|  |             buf.append('('); | ||||||
|  |         } | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitReturnType() { | ||||||
|  |         endFormals(); | ||||||
|  |         if (!hasParameters) { | ||||||
|  |             buf.append('('); | ||||||
|  |         } | ||||||
|  |         buf.append(')'); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitExceptionType() { | ||||||
|  |         buf.append('^'); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitBaseType(final char descriptor) { | ||||||
|  |         buf.append(descriptor); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeVariable(final String name) { | ||||||
|  |         buf.append('T'); | ||||||
|  |         buf.append(name); | ||||||
|  |         buf.append(';'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitArrayType() { | ||||||
|  |         buf.append('['); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitClassType(final String name) { | ||||||
|  |         buf.append('L'); | ||||||
|  |         buf.append(name); | ||||||
|  |         argumentStack *= 2; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInnerClassType(final String name) { | ||||||
|  |         endArguments(); | ||||||
|  |         buf.append('.'); | ||||||
|  |         buf.append(name); | ||||||
|  |         argumentStack *= 2; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitTypeArgument() { | ||||||
|  |         if (argumentStack % 2 == 0) { | ||||||
|  |             ++argumentStack; | ||||||
|  |             buf.append('<'); | ||||||
|  |         } | ||||||
|  |         buf.append('*'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public SignatureVisitor visitTypeArgument(final char wildcard) { | ||||||
|  |         if (argumentStack % 2 == 0) { | ||||||
|  |             ++argumentStack; | ||||||
|  |             buf.append('<'); | ||||||
|  |         } | ||||||
|  |         if (wildcard != '=') { | ||||||
|  |             buf.append(wildcard); | ||||||
|  |         } | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |         endArguments(); | ||||||
|  |         buf.append(';'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the signature that was built by this signature writer. | ||||||
|  |      *  | ||||||
|  |      * @return the signature that was built by this signature writer. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return buf.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Utility methods | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Ends the formal type parameters section of the signature. | ||||||
|  |      */ | ||||||
|  |     private void endFormals() { | ||||||
|  |         if (hasFormals) { | ||||||
|  |             hasFormals = false; | ||||||
|  |             buf.append('>'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Ends the type arguments of a class or inner class type. | ||||||
|  |      */ | ||||||
|  |     private void endArguments() { | ||||||
|  |         if (argumentStack % 2 != 0) { | ||||||
|  |             buf.append('>'); | ||||||
|  |         } | ||||||
|  |         argumentStack /= 2; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								src/main/asm/org/objectweb/asm/signature/package.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/main/asm/org/objectweb/asm/signature/package.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | <html> | ||||||
|  | <!-- | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | --> | ||||||
|  | <body> | ||||||
|  | Provides support for type signatures. | ||||||
|  | 
 | ||||||
|  | @since ASM 2.0 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										248
									
								
								src/main/asm/org/objectweb/asm/tree/AbstractInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								src/main/asm/org/objectweb/asm/tree/AbstractInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,248 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a bytecode instruction. <i>An instruction can appear | ||||||
|  |  * at most once in at most one {@link InsnList} at a time</i>. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public abstract class AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link InsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int INSN = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link IntInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int INT_INSN = 1; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link VarInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int VAR_INSN = 2; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link TypeInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int TYPE_INSN = 3; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link FieldInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int FIELD_INSN = 4; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link MethodInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int METHOD_INSN = 5; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link InvokeDynamicInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int INVOKE_DYNAMIC_INSN = 6; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link JumpInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int JUMP_INSN = 7; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link LabelNode} "instructions". | ||||||
|  |      */ | ||||||
|  |     public static final int LABEL = 8; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link LdcInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int LDC_INSN = 9; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link IincInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int IINC_INSN = 10; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link TableSwitchInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int TABLESWITCH_INSN = 11; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link LookupSwitchInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int LOOKUPSWITCH_INSN = 12; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link MultiANewArrayInsnNode} instructions. | ||||||
|  |      */ | ||||||
|  |     public static final int MULTIANEWARRAY_INSN = 13; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link FrameNode} "instructions". | ||||||
|  |      */ | ||||||
|  |     public static final int FRAME = 14; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of {@link LineNumberNode} "instructions". | ||||||
|  |      */ | ||||||
|  |     public static final int LINE = 15; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The opcode of this instruction. | ||||||
|  |      */ | ||||||
|  |     protected int opcode; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Previous instruction in the list to which this instruction belongs. | ||||||
|  |      */ | ||||||
|  |     AbstractInsnNode prev; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Next instruction in the list to which this instruction belongs. | ||||||
|  |      */ | ||||||
|  |     AbstractInsnNode next; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Index of this instruction in the list to which it belongs. The value of | ||||||
|  |      * this field is correct only when {@link InsnList#cache} is not null. A | ||||||
|  |      * value of -1 indicates that this instruction does not belong to any | ||||||
|  |      * {@link InsnList}. | ||||||
|  |      */ | ||||||
|  |     int index; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link AbstractInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the instruction to be constructed. | ||||||
|  |      */ | ||||||
|  |     protected AbstractInsnNode(final int opcode) { | ||||||
|  |         this.opcode = opcode; | ||||||
|  |         this.index = -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the opcode of this instruction. | ||||||
|  |      *  | ||||||
|  |      * @return the opcode of this instruction. | ||||||
|  |      */ | ||||||
|  |     public int getOpcode() { | ||||||
|  |         return opcode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the type of this instruction. | ||||||
|  |      *  | ||||||
|  |      * @return the type of this instruction, i.e. one the constants defined in | ||||||
|  |      *         this class. | ||||||
|  |      */ | ||||||
|  |     public abstract int getType(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the previous instruction in the list to which this instruction | ||||||
|  |      * belongs, if any. | ||||||
|  |      *  | ||||||
|  |      * @return the previous instruction in the list to which this instruction | ||||||
|  |      *         belongs, if any. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public AbstractInsnNode getPrevious() { | ||||||
|  |         return prev; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the next instruction in the list to which this instruction | ||||||
|  |      * belongs, if any. | ||||||
|  |      *  | ||||||
|  |      * @return the next instruction in the list to which this instruction | ||||||
|  |      *         belongs, if any. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public AbstractInsnNode getNext() { | ||||||
|  |         return next; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given code visitor visit this instruction. | ||||||
|  |      *  | ||||||
|  |      * @param cv | ||||||
|  |      *            a code visitor. | ||||||
|  |      */ | ||||||
|  |     public abstract void accept(final MethodVisitor cv); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns a copy of this instruction. | ||||||
|  |      *  | ||||||
|  |      * @param labels | ||||||
|  |      *            a map from LabelNodes to cloned LabelNodes. | ||||||
|  |      * @return a copy of this instruction. The returned instruction does not | ||||||
|  |      *         belong to any {@link InsnList}. | ||||||
|  |      */ | ||||||
|  |     public abstract AbstractInsnNode clone( | ||||||
|  |             final Map<LabelNode, LabelNode> labels); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the clone of the given label. | ||||||
|  |      *  | ||||||
|  |      * @param label | ||||||
|  |      *            a label. | ||||||
|  |      * @param map | ||||||
|  |      *            a map from LabelNodes to cloned LabelNodes. | ||||||
|  |      * @return the clone of the given label. | ||||||
|  |      */ | ||||||
|  |     static LabelNode clone(final LabelNode label, | ||||||
|  |             final Map<LabelNode, LabelNode> map) { | ||||||
|  |         return map.get(label); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the clones of the given labels. | ||||||
|  |      *  | ||||||
|  |      * @param labels | ||||||
|  |      *            a list of labels. | ||||||
|  |      * @param map | ||||||
|  |      *            a map from LabelNodes to cloned LabelNodes. | ||||||
|  |      * @return the clones of the given labels. | ||||||
|  |      */ | ||||||
|  |     static LabelNode[] clone(final List<LabelNode> labels, | ||||||
|  |             final Map<LabelNode, LabelNode> map) { | ||||||
|  |         LabelNode[] clones = new LabelNode[labels.size()]; | ||||||
|  |         for (int i = 0; i < clones.length; ++i) { | ||||||
|  |             clones[i] = map.get(labels.get(i)); | ||||||
|  |         } | ||||||
|  |         return clones; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										281
									
								
								src/main/asm/org/objectweb/asm/tree/AnnotationNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								src/main/asm/org/objectweb/asm/tree/AnnotationNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,281 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | //import cn.edu.pku.dpartner.comm.api.context.DelayLogger; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents an annotationn. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class AnnotationNode extends AnnotationVisitor | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The class descriptor of the annotation class. | ||||||
|  | 	 */ | ||||||
|  | 	public String desc; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The name value pairs of this annotation. Each name value pair is stored | ||||||
|  | 	 * as two consecutive elements in the list. The name is a {@link String}, | ||||||
|  | 	 * and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, | ||||||
|  | 	 * {@link Short}, {@link Integer}, {@link Long}, {@link Float}, | ||||||
|  | 	 * {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or an | ||||||
|  | 	 * two elements String array (for enumeration values), a | ||||||
|  | 	 * {@link AnnotationNode}, or a {@link List} of values of one of the | ||||||
|  | 	 * preceding types. The list may be <tt>null</tt> if there is no name value | ||||||
|  | 	 * pair. | ||||||
|  | 	 */ | ||||||
|  | 	public List<Object> values; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this | ||||||
|  | 	 * constructor</i>. Instead, they must use the | ||||||
|  | 	 * {@link #AnnotationNode(int, String)} version. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param desc | ||||||
|  | 	 *            the class descriptor of the annotation class. | ||||||
|  | 	 */ | ||||||
|  | 	public AnnotationNode(final String desc) | ||||||
|  | 	{ | ||||||
|  | 		this(Opcodes.ASM4, desc); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Constructs a new {@link AnnotationNode}. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param api | ||||||
|  | 	 *            the ASM API version implemented by this visitor. Must be one | ||||||
|  | 	 *            of {@link Opcodes#ASM4}. | ||||||
|  | 	 * @param desc | ||||||
|  | 	 *            the class descriptor of the annotation class. | ||||||
|  | 	 */ | ||||||
|  | 	public AnnotationNode(final int api, final String desc) | ||||||
|  | 	{ | ||||||
|  | 		super(api); | ||||||
|  | 		this.desc = desc; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Constructs a new {@link AnnotationNode} to visit an array value. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param values | ||||||
|  | 	 *            where the visited values must be stored. | ||||||
|  | 	 */ | ||||||
|  | 	AnnotationNode(final List<Object> values) | ||||||
|  | 	{ | ||||||
|  | 		super(Opcodes.ASM4); | ||||||
|  | 		this.values = values; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 	// Implementation of the AnnotationVisitor abstract class | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void visit(final String name, final Object value) | ||||||
|  | 	{ | ||||||
|  | 		if (values == null) | ||||||
|  | 		{ | ||||||
|  | 			values = new ArrayList<Object>(this.desc != null ? 2 : 1); | ||||||
|  | 		} | ||||||
|  | 		if (this.desc != null) | ||||||
|  | 		{ | ||||||
|  | 			values.add(name); | ||||||
|  | 		} | ||||||
|  | 		// else | ||||||
|  | 		// { | ||||||
|  | 		// System.out.println("[AnnotationNode] desc is null!"); | ||||||
|  | 		// values.add(""); | ||||||
|  | 		// } | ||||||
|  | 		values.add(value); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void visitEnum(final String name, final String desc, | ||||||
|  | 			final String value) | ||||||
|  | 	{ | ||||||
|  | 		if (values == null) | ||||||
|  | 		{ | ||||||
|  | 			values = new ArrayList<Object>(this.desc != null ? 2 : 1); | ||||||
|  | 		} | ||||||
|  | 		if (this.desc != null) | ||||||
|  | 		{ | ||||||
|  | 			values.add(name); | ||||||
|  | 		} | ||||||
|  | 		values.add(new String[] | ||||||
|  | 		{ desc, value }); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public AnnotationVisitor visitAnnotation(final String name, | ||||||
|  | 			final String desc) | ||||||
|  | 	{ | ||||||
|  | 		if (values == null) | ||||||
|  | 		{ | ||||||
|  | 			values = new ArrayList<Object>(this.desc != null ? 2 : 1); | ||||||
|  | 		} | ||||||
|  | 		if (this.desc != null) | ||||||
|  | 		{ | ||||||
|  | 			values.add(name); | ||||||
|  | 		} | ||||||
|  | 		AnnotationNode annotation = new AnnotationNode(desc); | ||||||
|  | 		values.add(annotation); | ||||||
|  | 		return annotation; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public AnnotationVisitor visitArray(final String name) | ||||||
|  | 	{ | ||||||
|  | 		if (values == null) | ||||||
|  | 		{ | ||||||
|  | 			values = new ArrayList<Object>(this.desc != null ? 2 : 1); | ||||||
|  | 		} | ||||||
|  | 		if (this.desc != null) | ||||||
|  | 		{ | ||||||
|  | 			values.add(name); | ||||||
|  | 		} | ||||||
|  | 		List<Object> array = new ArrayList<Object>(); | ||||||
|  | 		values.add(array); | ||||||
|  | 		return new AnnotationNode(array); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public void visitEnd() | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 	// Accept methods | ||||||
|  | 	// ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Checks that this annotation node is compatible with the given ASM API | ||||||
|  | 	 * version. This methods checks that this node, and all its nodes | ||||||
|  | 	 * recursively, do not contain elements that were introduced in more recent | ||||||
|  | 	 * versions of the ASM API than the given version. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param api | ||||||
|  | 	 *            an ASM API version. Must be one of {@link Opcodes#ASM4}. | ||||||
|  | 	 */ | ||||||
|  | 	public void check(final int api) | ||||||
|  | 	{ | ||||||
|  | 		// nothing to do | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Makes the given visitor visit this annotation. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param av | ||||||
|  | 	 *            an annotation visitor. Maybe <tt>null</tt>. | ||||||
|  | 	 */ | ||||||
|  | 	public void accept(final AnnotationVisitor av) | ||||||
|  | 	{ | ||||||
|  | 		if (av != null) | ||||||
|  | 		{ | ||||||
|  | 			if (values != null) | ||||||
|  | 			{ | ||||||
|  | 				for (int i = 0; i < values.size(); i += 2) | ||||||
|  | 				{ | ||||||
|  | 					if (values.get(i) == null) | ||||||
|  | 					{ | ||||||
|  | 						System.out | ||||||
|  | 								.println("[AnnotationNode] name is null!!!!!"); | ||||||
|  | 					//	DelayLogger.logValue(values); | ||||||
|  | 						System.out.flush(); | ||||||
|  | 						try | ||||||
|  | 						{ | ||||||
|  | 							Thread.sleep(2000); | ||||||
|  | 						} | ||||||
|  | 						catch (InterruptedException e) | ||||||
|  | 						{ | ||||||
|  | 							// TODO Auto-generated catch block | ||||||
|  | 							e.printStackTrace(); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					String name = (String) values.get(i); | ||||||
|  | 					Object value = values.get(i + 1); | ||||||
|  | 					accept(av, name, value); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			av.visitEnd(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Makes the given visitor visit a given annotation value. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param av | ||||||
|  | 	 *            an annotation visitor. Maybe <tt>null</tt>. | ||||||
|  | 	 * @param name | ||||||
|  | 	 *            the value name. | ||||||
|  | 	 * @param value | ||||||
|  | 	 *            the actual value. | ||||||
|  | 	 */ | ||||||
|  | 	static void accept(final AnnotationVisitor av, final String name, | ||||||
|  | 			final Object value) | ||||||
|  | 	{ | ||||||
|  | 		if (av != null) | ||||||
|  | 		{ | ||||||
|  | 			if (value instanceof String[]) | ||||||
|  | 			{ | ||||||
|  | 				String[] typeconst = (String[]) value; | ||||||
|  | 				av.visitEnum(name, typeconst[0], typeconst[1]); | ||||||
|  | 			} | ||||||
|  | 			else if (value instanceof AnnotationNode) | ||||||
|  | 			{ | ||||||
|  | 				AnnotationNode an = (AnnotationNode) value; | ||||||
|  | 				an.accept(av.visitAnnotation(name, an.desc)); | ||||||
|  | 			} | ||||||
|  | 			else if (value instanceof List) | ||||||
|  | 			{ | ||||||
|  | 				AnnotationVisitor v = av.visitArray(name); | ||||||
|  | 				List<?> array = (List<?>) value; | ||||||
|  | 				for (int j = 0; j < array.size(); ++j) | ||||||
|  | 				{ | ||||||
|  | 					accept(v, null, array.get(j)); | ||||||
|  | 				} | ||||||
|  | 				v.visitEnd(); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				av.visit(name, value); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										345
									
								
								src/main/asm/org/objectweb/asm/tree/ClassNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								src/main/asm/org/objectweb/asm/tree/ClassNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,345 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.Attribute; | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | import org.objectweb.asm.FieldVisitor; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a class. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class ClassNode extends ClassVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The class version. | ||||||
|  |      */ | ||||||
|  |     public int version; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The class's access flags (see {@link org.objectweb.asm.Opcodes}). This | ||||||
|  |      * field also indicates if the class is deprecated. | ||||||
|  |      */ | ||||||
|  |     public int access; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal name of the class (see | ||||||
|  |      * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). | ||||||
|  |      */ | ||||||
|  |     public String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The signature of the class. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public String signature; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal of name of the super class (see | ||||||
|  |      * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). For | ||||||
|  |      * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but | ||||||
|  |      * only for the {@link Object} class. | ||||||
|  |      */ | ||||||
|  |     public String superName; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal names of the class's interfaces (see | ||||||
|  |      * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). This | ||||||
|  |      * list is a list of {@link String} objects. | ||||||
|  |      */ | ||||||
|  |     public List<String> interfaces; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The name of the source file from which this class was compiled. May be | ||||||
|  |      * <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public String sourceFile; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Debug information to compute the correspondence between source and | ||||||
|  |      * compiled elements of the class. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public String sourceDebug; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal name of the enclosing class of the class. May be | ||||||
|  |      * <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public String outerClass; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The name of the method that contains the class, or <tt>null</tt> if the | ||||||
|  |      * class is not enclosed in a method. | ||||||
|  |      */ | ||||||
|  |     public String outerMethod; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The descriptor of the method that contains the class, or <tt>null</tt> if | ||||||
|  |      * the class is not enclosed in a method. | ||||||
|  |      */ | ||||||
|  |     public String outerMethodDesc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The runtime visible annotations of this class. This list is a list of | ||||||
|  |      * {@link AnnotationNode} objects. May be <tt>null</tt>. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.AnnotationNode | ||||||
|  |      * @label visible | ||||||
|  |      */ | ||||||
|  |     public List<AnnotationNode> visibleAnnotations; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The runtime invisible annotations of this class. This list is a list of | ||||||
|  |      * {@link AnnotationNode} objects. May be <tt>null</tt>. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.AnnotationNode | ||||||
|  |      * @label invisible | ||||||
|  |      */ | ||||||
|  |     public List<AnnotationNode> invisibleAnnotations; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The non standard attributes of this class. This list is a list of | ||||||
|  |      * {@link Attribute} objects. May be <tt>null</tt>. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.Attribute | ||||||
|  |      */ | ||||||
|  |     public List<Attribute> attrs; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Informations about the inner classes of this class. This list is a list | ||||||
|  |      * of {@link InnerClassNode} objects. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.InnerClassNode | ||||||
|  |      */ | ||||||
|  |     public List<InnerClassNode> innerClasses; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The fields of this class. This list is a list of {@link FieldNode} | ||||||
|  |      * objects. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.FieldNode | ||||||
|  |      */ | ||||||
|  |     public List<FieldNode> fields; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The methods of this class. This list is a list of {@link MethodNode} | ||||||
|  |      * objects. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.MethodNode | ||||||
|  |      */ | ||||||
|  |     public List<MethodNode> methods; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link ClassNode}. <i>Subclasses must not use this | ||||||
|  |      * constructor</i>. Instead, they must use the {@link #ClassNode(int)} | ||||||
|  |      * version. | ||||||
|  |      */ | ||||||
|  |     public ClassNode() { | ||||||
|  |         this(Opcodes.ASM4); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link ClassNode}. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public ClassNode(final int api) { | ||||||
|  |         super(api); | ||||||
|  |         this.interfaces = new ArrayList<String>(); | ||||||
|  |         this.innerClasses = new ArrayList<InnerClassNode>(); | ||||||
|  |         this.fields = new ArrayList<FieldNode>(); | ||||||
|  |         this.methods = new ArrayList<MethodNode>(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Implementation of the ClassVisitor abstract class | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visit(final int version, final int access, final String name, | ||||||
|  |             final String signature, final String superName, | ||||||
|  |             final String[] interfaces) { | ||||||
|  |         this.version = version; | ||||||
|  |         this.access = access; | ||||||
|  |         this.name = name; | ||||||
|  |         this.signature = signature; | ||||||
|  |         this.superName = superName; | ||||||
|  |         if (interfaces != null) { | ||||||
|  |             this.interfaces.addAll(Arrays.asList(interfaces)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitSource(final String file, final String debug) { | ||||||
|  |         sourceFile = file; | ||||||
|  |         sourceDebug = debug; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitOuterClass(final String owner, final String name, | ||||||
|  |             final String desc) { | ||||||
|  |         outerClass = owner; | ||||||
|  |         outerMethod = name; | ||||||
|  |         outerMethodDesc = desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(final String desc, | ||||||
|  |             final boolean visible) { | ||||||
|  |         AnnotationNode an = new AnnotationNode(desc); | ||||||
|  |         if (visible) { | ||||||
|  |             if (visibleAnnotations == null) { | ||||||
|  |                 visibleAnnotations = new ArrayList<AnnotationNode>(1); | ||||||
|  |             } | ||||||
|  |             visibleAnnotations.add(an); | ||||||
|  |         } else { | ||||||
|  |             if (invisibleAnnotations == null) { | ||||||
|  |                 invisibleAnnotations = new ArrayList<AnnotationNode>(1); | ||||||
|  |             } | ||||||
|  |             invisibleAnnotations.add(an); | ||||||
|  |         } | ||||||
|  |         return an; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitAttribute(final Attribute attr) { | ||||||
|  |         if (attrs == null) { | ||||||
|  |             attrs = new ArrayList<Attribute>(1); | ||||||
|  |         } | ||||||
|  |         attrs.add(attr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitInnerClass(final String name, final String outerName, | ||||||
|  |             final String innerName, final int access) { | ||||||
|  |         InnerClassNode icn = new InnerClassNode(name, outerName, innerName, | ||||||
|  |                 access); | ||||||
|  |         innerClasses.add(icn); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public FieldVisitor visitField(final int access, final String name, | ||||||
|  |             final String desc, final String signature, final Object value) { | ||||||
|  |         FieldNode fn = new FieldNode(access, name, desc, signature, value); | ||||||
|  |         fields.add(fn); | ||||||
|  |         return fn; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public MethodVisitor visitMethod(final int access, final String name, | ||||||
|  |             final String desc, final String signature, final String[] exceptions) { | ||||||
|  |         MethodNode mn = new MethodNode(access, name, desc, signature, | ||||||
|  |                 exceptions); | ||||||
|  |         methods.add(mn); | ||||||
|  |         return mn; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Accept method | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Checks that this class node is compatible with the given ASM API version. | ||||||
|  |      * This methods checks that this node, and all its nodes recursively, do not | ||||||
|  |      * contain elements that were introduced in more recent versions of the ASM | ||||||
|  |      * API than the given version. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            an ASM API version. Must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public void check(final int api) { | ||||||
|  |         // nothing to do | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given class visitor visit this class. | ||||||
|  |      *  | ||||||
|  |      * @param cv | ||||||
|  |      *            a class visitor. | ||||||
|  |      */ | ||||||
|  |     public void accept(final ClassVisitor cv) { | ||||||
|  |         // visits header | ||||||
|  |         String[] interfaces = new String[this.interfaces.size()]; | ||||||
|  |         this.interfaces.toArray(interfaces); | ||||||
|  |         cv.visit(version, access, name, signature, superName, interfaces); | ||||||
|  |         // visits source | ||||||
|  |         if (sourceFile != null || sourceDebug != null) { | ||||||
|  |             cv.visitSource(sourceFile, sourceDebug); | ||||||
|  |         } | ||||||
|  |         // visits outer class | ||||||
|  |         if (outerClass != null) { | ||||||
|  |             cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); | ||||||
|  |         } | ||||||
|  |         // visits attributes | ||||||
|  |         int i, n; | ||||||
|  |         n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); | ||||||
|  |         for (i = 0; i < n; ++i) { | ||||||
|  |             AnnotationNode an = visibleAnnotations.get(i); | ||||||
|  |             an.accept(cv.visitAnnotation(an.desc, true)); | ||||||
|  |         } | ||||||
|  |         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); | ||||||
|  |         for (i = 0; i < n; ++i) { | ||||||
|  |             AnnotationNode an = invisibleAnnotations.get(i); | ||||||
|  |             an.accept(cv.visitAnnotation(an.desc, false)); | ||||||
|  |         } | ||||||
|  |         n = attrs == null ? 0 : attrs.size(); | ||||||
|  |         for (i = 0; i < n; ++i) { | ||||||
|  |             cv.visitAttribute(attrs.get(i)); | ||||||
|  |         } | ||||||
|  |         // visits inner classes | ||||||
|  |         for (i = 0; i < innerClasses.size(); ++i) { | ||||||
|  |             innerClasses.get(i).accept(cv); | ||||||
|  |         } | ||||||
|  |         // visits fields | ||||||
|  |         for (i = 0; i < fields.size(); ++i) { | ||||||
|  |             fields.get(i).accept(cv); | ||||||
|  |         } | ||||||
|  |         // visits methods | ||||||
|  |         for (i = 0; i < methods.size(); ++i) { | ||||||
|  |             methods.get(i).accept(cv); | ||||||
|  |         } | ||||||
|  |         // visits end | ||||||
|  |         cv.visitEnd(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										108
									
								
								src/main/asm/org/objectweb/asm/tree/FieldInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/main/asm/org/objectweb/asm/tree/FieldInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a field instruction. A field instruction is an | ||||||
|  |  * instruction that loads or stores the value of a field of an object. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class FieldInsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal name of the field's owner class (see | ||||||
|  |      * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). | ||||||
|  |      */ | ||||||
|  |     public String owner; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's name. | ||||||
|  |      */ | ||||||
|  |     public String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's descriptor (see {@link org.objectweb.asm.Type}). | ||||||
|  |      */ | ||||||
|  |     public String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FieldInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the type instruction to be constructed. This | ||||||
|  |      *            opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. | ||||||
|  |      * @param owner | ||||||
|  |      *            the internal name of the field's owner class (see | ||||||
|  |      *            {@link org.objectweb.asm.Type#getInternalName() | ||||||
|  |      *            getInternalName}). | ||||||
|  |      * @param name | ||||||
|  |      *            the field's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the field's descriptor (see {@link org.objectweb.asm.Type}). | ||||||
|  |      */ | ||||||
|  |     public FieldInsnNode(final int opcode, final String owner, | ||||||
|  |             final String name, final String desc) { | ||||||
|  |         super(opcode); | ||||||
|  |         this.owner = owner; | ||||||
|  |         this.name = name; | ||||||
|  |         this.desc = desc; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets the opcode of this instruction. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the new instruction opcode. This opcode must be GETSTATIC, | ||||||
|  |      *            PUTSTATIC, GETFIELD or PUTFIELD. | ||||||
|  |      */ | ||||||
|  |     public void setOpcode(final int opcode) { | ||||||
|  |         this.opcode = opcode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return FIELD_INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor cv) { | ||||||
|  |         cv.visitFieldInsn(opcode, owner, name, desc); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new FieldInsnNode(opcode, owner, name, desc); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										243
									
								
								src/main/asm/org/objectweb/asm/tree/FieldNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								src/main/asm/org/objectweb/asm/tree/FieldNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,243 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.AnnotationVisitor; | ||||||
|  | import org.objectweb.asm.Attribute; | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | import org.objectweb.asm.FieldVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a field. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class FieldNode extends FieldVisitor { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's access flags (see {@link org.objectweb.asm.Opcodes}). This | ||||||
|  |      * field also indicates if the field is synthetic and/or deprecated. | ||||||
|  |      */ | ||||||
|  |     public int access; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's name. | ||||||
|  |      */ | ||||||
|  |     public String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's descriptor (see {@link org.objectweb.asm.Type}). | ||||||
|  |      */ | ||||||
|  |     public String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's signature. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public String signature; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The field's initial value. This field, which may be <tt>null</tt> if the | ||||||
|  |      * field does not have an initial value, must be an {@link Integer}, a | ||||||
|  |      * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. | ||||||
|  |      */ | ||||||
|  |     public Object value; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The runtime visible annotations of this field. This list is a list of | ||||||
|  |      * {@link AnnotationNode} objects. May be <tt>null</tt>. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.AnnotationNode | ||||||
|  |      * @label visible | ||||||
|  |      */ | ||||||
|  |     public List<AnnotationNode> visibleAnnotations; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The runtime invisible annotations of this field. This list is a list of | ||||||
|  |      * {@link AnnotationNode} objects. May be <tt>null</tt>. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.tree.AnnotationNode | ||||||
|  |      * @label invisible | ||||||
|  |      */ | ||||||
|  |     public List<AnnotationNode> invisibleAnnotations; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The non standard attributes of this field. This list is a list of | ||||||
|  |      * {@link Attribute} objects. May be <tt>null</tt>. | ||||||
|  |      *  | ||||||
|  |      * @associates org.objectweb.asm.Attribute | ||||||
|  |      */ | ||||||
|  |     public List<Attribute> attrs; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FieldNode}. <i>Subclasses must not use this | ||||||
|  |      * constructor</i>. Instead, they must use the | ||||||
|  |      * {@link #FieldNode(int, int, String, String, String, Object)} version. | ||||||
|  |      *  | ||||||
|  |      * @param access | ||||||
|  |      *            the field's access flags (see | ||||||
|  |      *            {@link org.objectweb.asm.Opcodes}). This parameter also | ||||||
|  |      *            indicates if the field is synthetic and/or deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the field's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the field's descriptor (see {@link org.objectweb.asm.Type | ||||||
|  |      *            Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the field's signature. | ||||||
|  |      * @param value | ||||||
|  |      *            the field's initial value. This parameter, which may be | ||||||
|  |      *            <tt>null</tt> if the field does not have an initial value, | ||||||
|  |      *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  |      *            {@link Double} or a {@link String}. | ||||||
|  |      */ | ||||||
|  |     public FieldNode(final int access, final String name, final String desc, | ||||||
|  |             final String signature, final Object value) { | ||||||
|  |         this(Opcodes.ASM4, access, name, desc, signature, value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FieldNode}. <i>Subclasses must not use this | ||||||
|  |      * constructor</i>. Instead, they must use the | ||||||
|  |      * {@link #FieldNode(int, int, String, String, String, Object)} version. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            the ASM API version implemented by this visitor. Must be one | ||||||
|  |      *            of {@link Opcodes#ASM4}. | ||||||
|  |      * @param access | ||||||
|  |      *            the field's access flags (see | ||||||
|  |      *            {@link org.objectweb.asm.Opcodes}). This parameter also | ||||||
|  |      *            indicates if the field is synthetic and/or deprecated. | ||||||
|  |      * @param name | ||||||
|  |      *            the field's name. | ||||||
|  |      * @param desc | ||||||
|  |      *            the field's descriptor (see {@link org.objectweb.asm.Type | ||||||
|  |      *            Type}). | ||||||
|  |      * @param signature | ||||||
|  |      *            the field's signature. | ||||||
|  |      * @param value | ||||||
|  |      *            the field's initial value. This parameter, which may be | ||||||
|  |      *            <tt>null</tt> if the field does not have an initial value, | ||||||
|  |      *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  |      *            {@link Double} or a {@link String}. | ||||||
|  |      */ | ||||||
|  |     public FieldNode(final int api, final int access, final String name, | ||||||
|  |             final String desc, final String signature, final Object value) { | ||||||
|  |         super(api); | ||||||
|  |         this.access = access; | ||||||
|  |         this.name = name; | ||||||
|  |         this.desc = desc; | ||||||
|  |         this.signature = signature; | ||||||
|  |         this.value = value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Implementation of the FieldVisitor abstract class | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AnnotationVisitor visitAnnotation(final String desc, | ||||||
|  |             final boolean visible) { | ||||||
|  |         AnnotationNode an = new AnnotationNode(desc); | ||||||
|  |         if (visible) { | ||||||
|  |             if (visibleAnnotations == null) { | ||||||
|  |                 visibleAnnotations = new ArrayList<AnnotationNode>(1); | ||||||
|  |             } | ||||||
|  |             visibleAnnotations.add(an); | ||||||
|  |         } else { | ||||||
|  |             if (invisibleAnnotations == null) { | ||||||
|  |                 invisibleAnnotations = new ArrayList<AnnotationNode>(1); | ||||||
|  |             } | ||||||
|  |             invisibleAnnotations.add(an); | ||||||
|  |         } | ||||||
|  |         return an; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitAttribute(final Attribute attr) { | ||||||
|  |         if (attrs == null) { | ||||||
|  |             attrs = new ArrayList<Attribute>(1); | ||||||
|  |         } | ||||||
|  |         attrs.add(attr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void visitEnd() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  |     // Accept methods | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Checks that this field node is compatible with the given ASM API version. | ||||||
|  |      * This methods checks that this node, and all its nodes recursively, do not | ||||||
|  |      * contain elements that were introduced in more recent versions of the ASM | ||||||
|  |      * API than the given version. | ||||||
|  |      *  | ||||||
|  |      * @param api | ||||||
|  |      *            an ASM API version. Must be one of {@link Opcodes#ASM4}. | ||||||
|  |      */ | ||||||
|  |     public void check(final int api) { | ||||||
|  |         // nothing to do | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given class visitor visit this field. | ||||||
|  |      *  | ||||||
|  |      * @param cv | ||||||
|  |      *            a class visitor. | ||||||
|  |      */ | ||||||
|  |     public void accept(final ClassVisitor cv) { | ||||||
|  |         FieldVisitor fv = cv.visitField(access, name, desc, signature, value); | ||||||
|  |         if (fv == null) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         int i, n; | ||||||
|  |         n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); | ||||||
|  |         for (i = 0; i < n; ++i) { | ||||||
|  |             AnnotationNode an = visibleAnnotations.get(i); | ||||||
|  |             an.accept(fv.visitAnnotation(an.desc, true)); | ||||||
|  |         } | ||||||
|  |         n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); | ||||||
|  |         for (i = 0; i < n; ++i) { | ||||||
|  |             AnnotationNode an = invisibleAnnotations.get(i); | ||||||
|  |             an.accept(fv.visitAnnotation(an.desc, false)); | ||||||
|  |         } | ||||||
|  |         n = attrs == null ? 0 : attrs.size(); | ||||||
|  |         for (i = 0; i < n; ++i) { | ||||||
|  |             fv.visitAttribute(attrs.get(i)); | ||||||
|  |         } | ||||||
|  |         fv.visitEnd(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										210
									
								
								src/main/asm/org/objectweb/asm/tree/FrameNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/main/asm/org/objectweb/asm/tree/FrameNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,210 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a stack map frame. These nodes are pseudo instruction | ||||||
|  |  * nodes in order to be inserted in an instruction list. In fact these nodes | ||||||
|  |  * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that | ||||||
|  |  * follows an unconditionnal branch instruction such as GOTO or THROW, that is | ||||||
|  |  * the target of a jump instruction, or that starts an exception handler block. | ||||||
|  |  * The stack map frame types must describe the values of the local variables and | ||||||
|  |  * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br> | ||||||
|  |  * <br> | ||||||
|  |  * (*) this is mandatory only for classes whose version is greater than or equal | ||||||
|  |  * to {@link Opcodes#V1_6 V1_6}. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class FrameNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded | ||||||
|  |      * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, | ||||||
|  |      * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or | ||||||
|  |      * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames. | ||||||
|  |      */ | ||||||
|  |     public int type; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The types of the local variables of this stack map frame. Elements of | ||||||
|  |      * this list can be Integer, String or LabelNode objects (for primitive, | ||||||
|  |      * reference and uninitialized types respectively - see | ||||||
|  |      * {@link MethodVisitor}). | ||||||
|  |      */ | ||||||
|  |     public List<Object> local; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The types of the operand stack elements of this stack map frame. Elements | ||||||
|  |      * of this list can be Integer, String or LabelNode objects (for primitive, | ||||||
|  |      * reference and uninitialized types respectively - see | ||||||
|  |      * {@link MethodVisitor}). | ||||||
|  |      */ | ||||||
|  |     public List<Object> stack; | ||||||
|  | 
 | ||||||
|  |     private FrameNode() { | ||||||
|  |         super(-1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link FrameNode}. | ||||||
|  |      *  | ||||||
|  |      * @param type | ||||||
|  |      *            the type of this frame. Must be {@link Opcodes#F_NEW} for | ||||||
|  |      *            expanded frames, or {@link Opcodes#F_FULL}, | ||||||
|  |      *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, | ||||||
|  |      *            {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, | ||||||
|  |      *            {@link Opcodes#F_SAME1} for compressed frames. | ||||||
|  |      * @param nLocal | ||||||
|  |      *            number of local variables of this stack map frame. | ||||||
|  |      * @param local | ||||||
|  |      *            the types of the local variables of this stack map frame. | ||||||
|  |      *            Elements of this list can be Integer, String or LabelNode | ||||||
|  |      *            objects (for primitive, reference and uninitialized types | ||||||
|  |      *            respectively - see {@link MethodVisitor}). | ||||||
|  |      * @param nStack | ||||||
|  |      *            number of operand stack elements of this stack map frame. | ||||||
|  |      * @param stack | ||||||
|  |      *            the types of the operand stack elements of this stack map | ||||||
|  |      *            frame. Elements of this list can be Integer, String or | ||||||
|  |      *            LabelNode objects (for primitive, reference and uninitialized | ||||||
|  |      *            types respectively - see {@link MethodVisitor}). | ||||||
|  |      */ | ||||||
|  |     public FrameNode(final int type, final int nLocal, final Object[] local, | ||||||
|  |             final int nStack, final Object[] stack) { | ||||||
|  |         super(-1); | ||||||
|  |         this.type = type; | ||||||
|  |         switch (type) { | ||||||
|  |         case Opcodes.F_NEW: | ||||||
|  |         case Opcodes.F_FULL: | ||||||
|  |             this.local = asList(nLocal, local); | ||||||
|  |             this.stack = asList(nStack, stack); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_APPEND: | ||||||
|  |             this.local = asList(nLocal, local); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_CHOP: | ||||||
|  |             this.local = Arrays.asList(new Object[nLocal]); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_SAME: | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_SAME1: | ||||||
|  |             this.stack = asList(1, stack); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return FRAME; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given visitor visit this stack map frame. | ||||||
|  |      *  | ||||||
|  |      * @param mv | ||||||
|  |      *            a method visitor. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         switch (type) { | ||||||
|  |         case Opcodes.F_NEW: | ||||||
|  |         case Opcodes.F_FULL: | ||||||
|  |             mv.visitFrame(type, local.size(), asArray(local), stack.size(), | ||||||
|  |                     asArray(stack)); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_APPEND: | ||||||
|  |             mv.visitFrame(type, local.size(), asArray(local), 0, null); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_CHOP: | ||||||
|  |             mv.visitFrame(type, local.size(), null, 0, null); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_SAME: | ||||||
|  |             mv.visitFrame(type, 0, null, 0, null); | ||||||
|  |             break; | ||||||
|  |         case Opcodes.F_SAME1: | ||||||
|  |             mv.visitFrame(type, 0, null, 1, asArray(stack)); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         FrameNode clone = new FrameNode(); | ||||||
|  |         clone.type = type; | ||||||
|  |         if (local != null) { | ||||||
|  |             clone.local = new ArrayList<Object>(); | ||||||
|  |             for (int i = 0; i < local.size(); ++i) { | ||||||
|  |                 Object l = local.get(i); | ||||||
|  |                 if (l instanceof LabelNode) { | ||||||
|  |                     l = labels.get(l); | ||||||
|  |                 } | ||||||
|  |                 clone.local.add(l); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (stack != null) { | ||||||
|  |             clone.stack = new ArrayList<Object>(); | ||||||
|  |             for (int i = 0; i < stack.size(); ++i) { | ||||||
|  |                 Object s = stack.get(i); | ||||||
|  |                 if (s instanceof LabelNode) { | ||||||
|  |                     s = labels.get(s); | ||||||
|  |                 } | ||||||
|  |                 clone.stack.add(s); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return clone; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // ------------------------------------------------------------------------ | ||||||
|  | 
 | ||||||
|  |     private static List<Object> asList(final int n, final Object[] o) { | ||||||
|  |         return Arrays.asList(o).subList(0, n); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static Object[] asArray(final List<Object> l) { | ||||||
|  |         Object[] objs = new Object[l.size()]; | ||||||
|  |         for (int i = 0; i < objs.length; ++i) { | ||||||
|  |             Object o = l.get(i); | ||||||
|  |             if (o instanceof LabelNode) { | ||||||
|  |                 o = ((LabelNode) o).getLabel(); | ||||||
|  |             } | ||||||
|  |             objs[i] = o; | ||||||
|  |         } | ||||||
|  |         return objs; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										82
									
								
								src/main/asm/org/objectweb/asm/tree/IincInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/main/asm/org/objectweb/asm/tree/IincInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents an IINC instruction. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class IincInsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Index of the local variable to be incremented. | ||||||
|  |      */ | ||||||
|  |     public int var; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Amount to increment the local variable by. | ||||||
|  |      */ | ||||||
|  |     public int incr; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link IincInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param var | ||||||
|  |      *            index of the local variable to be incremented. | ||||||
|  |      * @param incr | ||||||
|  |      *            increment amount to increment the local variable by. | ||||||
|  |      */ | ||||||
|  |     public IincInsnNode(final int var, final int incr) { | ||||||
|  |         super(Opcodes.IINC); | ||||||
|  |         this.var = var; | ||||||
|  |         this.incr = incr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return IINC_INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         mv.visitIincInsn(var, incr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new IincInsnNode(var, incr); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										101
									
								
								src/main/asm/org/objectweb/asm/tree/InnerClassNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/main/asm/org/objectweb/asm/tree/InnerClassNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.ClassVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents an inner class. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class InnerClassNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal name of an inner class (see | ||||||
|  |      * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). | ||||||
|  |      */ | ||||||
|  |     public String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The internal name of the class to which the inner class belongs (see | ||||||
|  |      * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). May be | ||||||
|  |      * <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     public String outerName; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The (simple) name of the inner class inside its enclosing class. May be | ||||||
|  |      * <tt>null</tt> for anonymous inner classes. | ||||||
|  |      */ | ||||||
|  |     public String innerName; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The access flags of the inner class as originally declared in the | ||||||
|  |      * enclosing class. | ||||||
|  |      */ | ||||||
|  |     public int access; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link InnerClassNode}. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            the internal name of an inner class (see | ||||||
|  |      *            {@link org.objectweb.asm.Type#getInternalName() | ||||||
|  |      *            getInternalName}). | ||||||
|  |      * @param outerName | ||||||
|  |      *            the internal name of the class to which the inner class | ||||||
|  |      *            belongs (see {@link org.objectweb.asm.Type#getInternalName() | ||||||
|  |      *            getInternalName}). May be <tt>null</tt>. | ||||||
|  |      * @param innerName | ||||||
|  |      *            the (simple) name of the inner class inside its enclosing | ||||||
|  |      *            class. May be <tt>null</tt> for anonymous inner classes. | ||||||
|  |      * @param access | ||||||
|  |      *            the access flags of the inner class as originally declared in | ||||||
|  |      *            the enclosing class. | ||||||
|  |      */ | ||||||
|  |     public InnerClassNode(final String name, final String outerName, | ||||||
|  |             final String innerName, final int access) { | ||||||
|  |         this.name = name; | ||||||
|  |         this.outerName = outerName; | ||||||
|  |         this.innerName = innerName; | ||||||
|  |         this.access = access; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given class visitor visit this inner class. | ||||||
|  |      *  | ||||||
|  |      * @param cv | ||||||
|  |      *            a class visitor. | ||||||
|  |      */ | ||||||
|  |     public void accept(final ClassVisitor cv) { | ||||||
|  |         cv.visitInnerClass(name, outerName, innerName, access); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										600
									
								
								src/main/asm/org/objectweb/asm/tree/InsnList.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										600
									
								
								src/main/asm/org/objectweb/asm/tree/InsnList.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,600 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.ListIterator; | ||||||
|  | import java.util.NoSuchElementException; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A doubly linked list of {@link AbstractInsnNode} objects. <i>This | ||||||
|  |  * implementation is not thread safe</i>. | ||||||
|  |  */ | ||||||
|  | public class InsnList { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The number of instructions in this list. | ||||||
|  |      */ | ||||||
|  |     private int size; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The first instruction in this list. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     private AbstractInsnNode first; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The last instruction in this list. May be <tt>null</tt>. | ||||||
|  |      */ | ||||||
|  |     private AbstractInsnNode last; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A cache of the instructions of this list. This cache is used to improve | ||||||
|  |      * the performance of the {@link #get} method. | ||||||
|  |      */ | ||||||
|  |     AbstractInsnNode[] cache; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the number of instructions in this list. | ||||||
|  |      *  | ||||||
|  |      * @return the number of instructions in this list. | ||||||
|  |      */ | ||||||
|  |     public int size() { | ||||||
|  |         return size; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the first instruction in this list. | ||||||
|  |      *  | ||||||
|  |      * @return the first instruction in this list, or <tt>null</tt> if the list | ||||||
|  |      *         is empty. | ||||||
|  |      */ | ||||||
|  |     public AbstractInsnNode getFirst() { | ||||||
|  |         return first; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the last instruction in this list. | ||||||
|  |      *  | ||||||
|  |      * @return the last instruction in this list, or <tt>null</tt> if the list | ||||||
|  |      *         is empty. | ||||||
|  |      */ | ||||||
|  |     public AbstractInsnNode getLast() { | ||||||
|  |         return last; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the instruction whose index is given. This method builds a cache | ||||||
|  |      * of the instructions in this list to avoid scanning the whole list each | ||||||
|  |      * time it is called. Once the cache is built, this method run in constant | ||||||
|  |      * time. This cache is invalidated by all the methods that modify the list. | ||||||
|  |      *  | ||||||
|  |      * @param index | ||||||
|  |      *            the index of the instruction that must be returned. | ||||||
|  |      * @return the instruction whose index is given. | ||||||
|  |      * @throws IndexOutOfBoundsException | ||||||
|  |      *             if (index < 0 || index >= size()). | ||||||
|  |      */ | ||||||
|  |     public AbstractInsnNode get(final int index) { | ||||||
|  |         if (index < 0 || index >= size) { | ||||||
|  |             throw new IndexOutOfBoundsException(); | ||||||
|  |         } | ||||||
|  |         if (cache == null) { | ||||||
|  |             cache = toArray(); | ||||||
|  |         } | ||||||
|  |         return cache[index]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns <tt>true</tt> if the given instruction belongs to this list. This | ||||||
|  |      * method always scans the instructions of this list until it finds the | ||||||
|  |      * given instruction or reaches the end of the list. | ||||||
|  |      *  | ||||||
|  |      * @param insn | ||||||
|  |      *            an instruction. | ||||||
|  |      * @return <tt>true</tt> if the given instruction belongs to this list. | ||||||
|  |      */ | ||||||
|  |     public boolean contains(final AbstractInsnNode insn) { | ||||||
|  |         AbstractInsnNode i = first; | ||||||
|  |         while (i != null && i != insn) { | ||||||
|  |             i = i.next; | ||||||
|  |         } | ||||||
|  |         return i != null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the index of the given instruction in this list. This method | ||||||
|  |      * builds a cache of the instruction indexes to avoid scanning the whole | ||||||
|  |      * list each time it is called. Once the cache is built, this method run in | ||||||
|  |      * constant time. The cache is invalidated by all the methods that modify | ||||||
|  |      * the list. | ||||||
|  |      *  | ||||||
|  |      * @param insn | ||||||
|  |      *            an instruction <i>of this list</i>. | ||||||
|  |      * @return the index of the given instruction in this list. <i>The result of | ||||||
|  |      *         this method is undefined if the given instruction does not belong | ||||||
|  |      *         to this list</i>. Use {@link #contains contains} to test if an | ||||||
|  |      *         instruction belongs to an instruction list or not. | ||||||
|  |      */ | ||||||
|  |     public int indexOf(final AbstractInsnNode insn) { | ||||||
|  |         if (cache == null) { | ||||||
|  |             cache = toArray(); | ||||||
|  |         } | ||||||
|  |         return insn.index; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given visitor visit all of the instructions in this list. | ||||||
|  |      *  | ||||||
|  |      * @param mv | ||||||
|  |      *            the method visitor that must visit the instructions. | ||||||
|  |      */ | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         AbstractInsnNode insn = first; | ||||||
|  |         while (insn != null) { | ||||||
|  |             insn.accept(mv); | ||||||
|  |             insn = insn.next; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns an iterator over the instructions in this list. | ||||||
|  |      *  | ||||||
|  |      * @return an iterator over the instructions in this list. | ||||||
|  |      */ | ||||||
|  |     public ListIterator<AbstractInsnNode> iterator() { | ||||||
|  |         return iterator(0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns an iterator over the instructions in this list. | ||||||
|  |      *  | ||||||
|  |      * @return an iterator over the instructions in this list. | ||||||
|  |      */ | ||||||
|  |     @SuppressWarnings("unchecked") | ||||||
|  |     public ListIterator<AbstractInsnNode> iterator(int index) { | ||||||
|  |         return new InsnListIterator(index); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns an array containing all of the instructions in this list. | ||||||
|  |      *  | ||||||
|  |      * @return an array containing all of the instructions in this list. | ||||||
|  |      */ | ||||||
|  |     public AbstractInsnNode[] toArray() { | ||||||
|  |         int i = 0; | ||||||
|  |         AbstractInsnNode elem = first; | ||||||
|  |         AbstractInsnNode[] insns = new AbstractInsnNode[size]; | ||||||
|  |         while (elem != null) { | ||||||
|  |             insns[i] = elem; | ||||||
|  |             elem.index = i++; | ||||||
|  |             elem = elem.next; | ||||||
|  |         } | ||||||
|  |         return insns; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Replaces an instruction of this list with another instruction. | ||||||
|  |      *  | ||||||
|  |      * @param location | ||||||
|  |      *            an instruction <i>of this list</i>. | ||||||
|  |      * @param insn | ||||||
|  |      *            another instruction, <i>which must not belong to any | ||||||
|  |      *            {@link InsnList}</i>. | ||||||
|  |      */ | ||||||
|  |     public void set(final AbstractInsnNode location, final AbstractInsnNode insn) { | ||||||
|  |         AbstractInsnNode next = location.next; | ||||||
|  |         insn.next = next; | ||||||
|  |         if (next != null) { | ||||||
|  |             next.prev = insn; | ||||||
|  |         } else { | ||||||
|  |             last = insn; | ||||||
|  |         } | ||||||
|  |         AbstractInsnNode prev = location.prev; | ||||||
|  |         insn.prev = prev; | ||||||
|  |         if (prev != null) { | ||||||
|  |             prev.next = insn; | ||||||
|  |         } else { | ||||||
|  |             first = insn; | ||||||
|  |         } | ||||||
|  |         if (cache != null) { | ||||||
|  |             int index = location.index; | ||||||
|  |             cache[index] = insn; | ||||||
|  |             insn.index = index; | ||||||
|  |         } else { | ||||||
|  |             insn.index = 0; // insn now belongs to an InsnList | ||||||
|  |         } | ||||||
|  |         location.index = -1; // i no longer belongs to an InsnList | ||||||
|  |         location.prev = null; | ||||||
|  |         location.next = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds the given instruction to the end of this list. | ||||||
|  |      *  | ||||||
|  |      * @param insn | ||||||
|  |      *            an instruction, <i>which must not belong to any | ||||||
|  |      *            {@link InsnList}</i>. | ||||||
|  |      */ | ||||||
|  |     public void add(final AbstractInsnNode insn) { | ||||||
|  |         ++size; | ||||||
|  |         if (last == null) { | ||||||
|  |             first = insn; | ||||||
|  |             last = insn; | ||||||
|  |         } else { | ||||||
|  |             last.next = insn; | ||||||
|  |             insn.prev = last; | ||||||
|  |         } | ||||||
|  |         last = insn; | ||||||
|  |         cache = null; | ||||||
|  |         insn.index = 0; // insn now belongs to an InsnList | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds the given instructions to the end of this list. | ||||||
|  |      *  | ||||||
|  |      * @param insns | ||||||
|  |      *            an instruction list, which is cleared during the process. This | ||||||
|  |      *            list must be different from 'this'. | ||||||
|  |      */ | ||||||
|  |     public void add(final InsnList insns) { | ||||||
|  |         if (insns.size == 0) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         size += insns.size; | ||||||
|  |         if (last == null) { | ||||||
|  |             first = insns.first; | ||||||
|  |             last = insns.last; | ||||||
|  |         } else { | ||||||
|  |             AbstractInsnNode elem = insns.first; | ||||||
|  |             last.next = elem; | ||||||
|  |             elem.prev = last; | ||||||
|  |             last = insns.last; | ||||||
|  |         } | ||||||
|  |         cache = null; | ||||||
|  |         insns.removeAll(false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Inserts the given instruction at the begining of this list. | ||||||
|  |      *  | ||||||
|  |      * @param insn | ||||||
|  |      *            an instruction, <i>which must not belong to any | ||||||
|  |      *            {@link InsnList}</i>. | ||||||
|  |      */ | ||||||
|  |     public void insert(final AbstractInsnNode insn) { | ||||||
|  |         ++size; | ||||||
|  |         if (first == null) { | ||||||
|  |             first = insn; | ||||||
|  |             last = insn; | ||||||
|  |         } else { | ||||||
|  |             first.prev = insn; | ||||||
|  |             insn.next = first; | ||||||
|  |         } | ||||||
|  |         first = insn; | ||||||
|  |         cache = null; | ||||||
|  |         insn.index = 0; // insn now belongs to an InsnList | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Inserts the given instructions at the begining of this list. | ||||||
|  |      *  | ||||||
|  |      * @param insns | ||||||
|  |      *            an instruction list, which is cleared during the process. This | ||||||
|  |      *            list must be different from 'this'. | ||||||
|  |      */ | ||||||
|  |     public void insert(final InsnList insns) { | ||||||
|  |         if (insns.size == 0) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         size += insns.size; | ||||||
|  |         if (first == null) { | ||||||
|  |             first = insns.first; | ||||||
|  |             last = insns.last; | ||||||
|  |         } else { | ||||||
|  |             AbstractInsnNode elem = insns.last; | ||||||
|  |             first.prev = elem; | ||||||
|  |             elem.next = first; | ||||||
|  |             first = insns.first; | ||||||
|  |         } | ||||||
|  |         cache = null; | ||||||
|  |         insns.removeAll(false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Inserts the given instruction after the specified instruction. | ||||||
|  |      *  | ||||||
|  |      * @param location | ||||||
|  |      *            an instruction <i>of this list</i> after which insn must be | ||||||
|  |      *            inserted. | ||||||
|  |      * @param insn | ||||||
|  |      *            the instruction to be inserted, <i>which must not belong to | ||||||
|  |      *            any {@link InsnList}</i>. | ||||||
|  |      */ | ||||||
|  |     public void insert(final AbstractInsnNode location, | ||||||
|  |             final AbstractInsnNode insn) { | ||||||
|  |         ++size; | ||||||
|  |         AbstractInsnNode next = location.next; | ||||||
|  |         if (next == null) { | ||||||
|  |             last = insn; | ||||||
|  |         } else { | ||||||
|  |             next.prev = insn; | ||||||
|  |         } | ||||||
|  |         location.next = insn; | ||||||
|  |         insn.next = next; | ||||||
|  |         insn.prev = location; | ||||||
|  |         cache = null; | ||||||
|  |         insn.index = 0; // insn now belongs to an InsnList | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Inserts the given instructions after the specified instruction. | ||||||
|  |      *  | ||||||
|  |      * @param location | ||||||
|  |      *            an instruction <i>of this list</i> after which the | ||||||
|  |      *            instructions must be inserted. | ||||||
|  |      * @param insns | ||||||
|  |      *            the instruction list to be inserted, which is cleared during | ||||||
|  |      *            the process. This list must be different from 'this'. | ||||||
|  |      */ | ||||||
|  |     public void insert(final AbstractInsnNode location, final InsnList insns) { | ||||||
|  |         if (insns.size == 0) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         size += insns.size; | ||||||
|  |         AbstractInsnNode ifirst = insns.first; | ||||||
|  |         AbstractInsnNode ilast = insns.last; | ||||||
|  |         AbstractInsnNode next = location.next; | ||||||
|  |         if (next == null) { | ||||||
|  |             last = ilast; | ||||||
|  |         } else { | ||||||
|  |             next.prev = ilast; | ||||||
|  |         } | ||||||
|  |         location.next = ifirst; | ||||||
|  |         ilast.next = next; | ||||||
|  |         ifirst.prev = location; | ||||||
|  |         cache = null; | ||||||
|  |         insns.removeAll(false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Inserts the given instruction before the specified instruction. | ||||||
|  |      *  | ||||||
|  |      * @param location | ||||||
|  |      *            an instruction <i>of this list</i> before which insn must be | ||||||
|  |      *            inserted. | ||||||
|  |      * @param insn | ||||||
|  |      *            the instruction to be inserted, <i>which must not belong to | ||||||
|  |      *            any {@link InsnList}</i>. | ||||||
|  |      */ | ||||||
|  |     public void insertBefore(final AbstractInsnNode location, | ||||||
|  |             final AbstractInsnNode insn) { | ||||||
|  |         ++size; | ||||||
|  |         AbstractInsnNode prev = location.prev; | ||||||
|  |         if (prev == null) { | ||||||
|  |             first = insn; | ||||||
|  |         } else { | ||||||
|  |             prev.next = insn; | ||||||
|  |         } | ||||||
|  |         location.prev = insn; | ||||||
|  |         insn.next = location; | ||||||
|  |         insn.prev = prev; | ||||||
|  |         cache = null; | ||||||
|  |         insn.index = 0; // insn now belongs to an InsnList | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Inserts the given instructions before the specified instruction. | ||||||
|  |      *  | ||||||
|  |      * @param location | ||||||
|  |      *            an instruction <i>of this list</i> before which the | ||||||
|  |      *            instructions must be inserted. | ||||||
|  |      * @param insns | ||||||
|  |      *            the instruction list to be inserted, which is cleared during | ||||||
|  |      *            the process. This list must be different from 'this'. | ||||||
|  |      */ | ||||||
|  |     public void insertBefore(final AbstractInsnNode location, | ||||||
|  |             final InsnList insns) { | ||||||
|  |         if (insns.size == 0) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         size += insns.size; | ||||||
|  |         AbstractInsnNode ifirst = insns.first; | ||||||
|  |         AbstractInsnNode ilast = insns.last; | ||||||
|  |         AbstractInsnNode prev = location.prev; | ||||||
|  |         if (prev == null) { | ||||||
|  |             first = ifirst; | ||||||
|  |         } else { | ||||||
|  |             prev.next = ifirst; | ||||||
|  |         } | ||||||
|  |         location.prev = ilast; | ||||||
|  |         ilast.next = location; | ||||||
|  |         ifirst.prev = prev; | ||||||
|  |         cache = null; | ||||||
|  |         insns.removeAll(false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes the given instruction from this list. | ||||||
|  |      *  | ||||||
|  |      * @param insn | ||||||
|  |      *            the instruction <i>of this list</i> that must be removed. | ||||||
|  |      */ | ||||||
|  |     public void remove(final AbstractInsnNode insn) { | ||||||
|  |         --size; | ||||||
|  |         AbstractInsnNode next = insn.next; | ||||||
|  |         AbstractInsnNode prev = insn.prev; | ||||||
|  |         if (next == null) { | ||||||
|  |             if (prev == null) { | ||||||
|  |                 first = null; | ||||||
|  |                 last = null; | ||||||
|  |             } else { | ||||||
|  |                 prev.next = null; | ||||||
|  |                 last = prev; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if (prev == null) { | ||||||
|  |                 first = next; | ||||||
|  |                 next.prev = null; | ||||||
|  |             } else { | ||||||
|  |                 prev.next = next; | ||||||
|  |                 next.prev = prev; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         cache = null; | ||||||
|  |         insn.index = -1; // insn no longer belongs to an InsnList | ||||||
|  |         insn.prev = null; | ||||||
|  |         insn.next = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes all of the instructions of this list. | ||||||
|  |      *  | ||||||
|  |      * @param mark | ||||||
|  |      *            if the instructions must be marked as no longer belonging to | ||||||
|  |      *            any {@link InsnList}. | ||||||
|  |      */ | ||||||
|  |     void removeAll(final boolean mark) { | ||||||
|  |         if (mark) { | ||||||
|  |             AbstractInsnNode insn = first; | ||||||
|  |             while (insn != null) { | ||||||
|  |                 AbstractInsnNode next = insn.next; | ||||||
|  |                 insn.index = -1; // insn no longer belongs to an InsnList | ||||||
|  |                 insn.prev = null; | ||||||
|  |                 insn.next = null; | ||||||
|  |                 insn = next; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         size = 0; | ||||||
|  |         first = null; | ||||||
|  |         last = null; | ||||||
|  |         cache = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Removes all of the instructions of this list. | ||||||
|  |      */ | ||||||
|  |     public void clear() { | ||||||
|  |         removeAll(false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Reset all labels in the instruction list. This method should be called | ||||||
|  |      * before reusing same instructions list between several | ||||||
|  |      * <code>ClassWriter</code>s. | ||||||
|  |      */ | ||||||
|  |     public void resetLabels() { | ||||||
|  |         AbstractInsnNode insn = first; | ||||||
|  |         while (insn != null) { | ||||||
|  |             if (insn instanceof LabelNode) { | ||||||
|  |                 ((LabelNode) insn).resetLabel(); | ||||||
|  |             } | ||||||
|  |             insn = insn.next; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // this class is not generified because it will create bridges | ||||||
|  |     private final class InsnListIterator implements ListIterator { | ||||||
|  | 
 | ||||||
|  |         AbstractInsnNode next; | ||||||
|  | 
 | ||||||
|  |         AbstractInsnNode prev; | ||||||
|  | 
 | ||||||
|  |         InsnListIterator(int index) { | ||||||
|  |             if (index == size()) { | ||||||
|  |                 next = null; | ||||||
|  |                 prev = getLast(); | ||||||
|  |             } else { | ||||||
|  |                 next = get(index); | ||||||
|  |                 prev = next.prev; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public boolean hasNext() { | ||||||
|  |             return next != null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Object next() { | ||||||
|  |             if (next == null) { | ||||||
|  |                 throw new NoSuchElementException(); | ||||||
|  |             } | ||||||
|  |             AbstractInsnNode result = next; | ||||||
|  |             prev = result; | ||||||
|  |             next = result.next; | ||||||
|  |             return result; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void remove() { | ||||||
|  |             InsnList.this.remove(prev); | ||||||
|  |             prev = prev.prev; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public boolean hasPrevious() { | ||||||
|  |             return prev != null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Object previous() { | ||||||
|  |             AbstractInsnNode result = prev; | ||||||
|  |             next = result; | ||||||
|  |             prev = result.prev; | ||||||
|  |             return result; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public int nextIndex() { | ||||||
|  |             if (next == null) { | ||||||
|  |                 return size(); | ||||||
|  |             } | ||||||
|  |             if (cache == null) { | ||||||
|  |                 cache = toArray(); | ||||||
|  |             } | ||||||
|  |             return next.index; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public int previousIndex() { | ||||||
|  |             if (prev == null) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|  |             if (cache == null) { | ||||||
|  |                 cache = toArray(); | ||||||
|  |             } | ||||||
|  |             return prev.index; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void add(Object o) { | ||||||
|  |             InsnList.this.insertBefore(next, (AbstractInsnNode) o); | ||||||
|  |             prev = (AbstractInsnNode) o; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void set(Object o) { | ||||||
|  |             InsnList.this.set(next.prev, (AbstractInsnNode) o); | ||||||
|  |             prev = (AbstractInsnNode) o; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										87
									
								
								src/main/asm/org/objectweb/asm/tree/InsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/main/asm/org/objectweb/asm/tree/InsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a zero operand instruction. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class InsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link InsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the instruction to be constructed. This opcode | ||||||
|  |      *            must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, | ||||||
|  |      *            ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, | ||||||
|  |      *            FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, | ||||||
|  |      *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, | ||||||
|  |      *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, | ||||||
|  |      *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, | ||||||
|  |      *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, | ||||||
|  |      *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, | ||||||
|  |      *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, | ||||||
|  |      *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, | ||||||
|  |      *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, | ||||||
|  |      *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, | ||||||
|  |      *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, | ||||||
|  |      *            or MONITOREXIT. | ||||||
|  |      */ | ||||||
|  |     public InsnNode(final int opcode) { | ||||||
|  |         super(opcode); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Makes the given visitor visit this instruction. | ||||||
|  |      *  | ||||||
|  |      * @param mv | ||||||
|  |      *            a method visitor. | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         mv.visitInsn(opcode); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new InsnNode(opcode); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										87
									
								
								src/main/asm/org/objectweb/asm/tree/IntInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/main/asm/org/objectweb/asm/tree/IntInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents an instruction with a single int operand. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class IntInsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The operand of this instruction. | ||||||
|  |      */ | ||||||
|  |     public int operand; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link IntInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the instruction to be constructed. This opcode | ||||||
|  |      *            must be BIPUSH, SIPUSH or NEWARRAY. | ||||||
|  |      * @param operand | ||||||
|  |      *            the operand of the instruction to be constructed. | ||||||
|  |      */ | ||||||
|  |     public IntInsnNode(final int opcode, final int operand) { | ||||||
|  |         super(opcode); | ||||||
|  |         this.operand = operand; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets the opcode of this instruction. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the new instruction opcode. This opcode must be BIPUSH, SIPUSH | ||||||
|  |      *            or NEWARRAY. | ||||||
|  |      */ | ||||||
|  |     public void setOpcode(final int opcode) { | ||||||
|  |         this.opcode = opcode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return INT_INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         mv.visitIntInsn(opcode, operand); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new IntInsnNode(opcode, operand); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										100
									
								
								src/main/asm/org/objectweb/asm/tree/InvokeDynamicInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/main/asm/org/objectweb/asm/tree/InvokeDynamicInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Handle; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents an invokedynamic instruction. | ||||||
|  |  *  | ||||||
|  |  * @author Remi Forax | ||||||
|  |  */ | ||||||
|  | public class InvokeDynamicInsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Invokedynamic name. | ||||||
|  |      */ | ||||||
|  |     public String name; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Invokedynamic descriptor. | ||||||
|  |      */ | ||||||
|  |     public String desc; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Bootstrap method | ||||||
|  |      */ | ||||||
|  |     public Handle bsm; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Bootstrap constant arguments | ||||||
|  |      */ | ||||||
|  |     public Object[] bsmArgs; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link InvokeDynamicInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param name | ||||||
|  |      *            invokedynamic name. | ||||||
|  |      * @param desc | ||||||
|  |      *            invokedynamic descriptor (see {@link org.objectweb.asm.Type}). | ||||||
|  |      * @param bsm | ||||||
|  |      *            the bootstrap method. | ||||||
|  |      * @param bsmArgs | ||||||
|  |      *            the boostrap constant arguments. | ||||||
|  |      */ | ||||||
|  |     public InvokeDynamicInsnNode(final String name, final String desc, | ||||||
|  |             final Handle bsm, final Object... bsmArgs) { | ||||||
|  |         super(Opcodes.INVOKEDYNAMIC); | ||||||
|  |         this.name = name; | ||||||
|  |         this.desc = desc; | ||||||
|  |         this.bsm = bsm; | ||||||
|  |         this.bsmArgs = bsmArgs; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return INVOKE_DYNAMIC_INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										95
									
								
								src/main/asm/org/objectweb/asm/tree/JumpInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/main/asm/org/objectweb/asm/tree/JumpInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents a jump instruction. A jump instruction is an | ||||||
|  |  * instruction that may jump to another instruction. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class JumpInsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The operand of this instruction. This operand is a label that designates | ||||||
|  |      * the instruction to which this instruction may jump. | ||||||
|  |      */ | ||||||
|  |     public LabelNode label; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link JumpInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the opcode of the type instruction to be constructed. This | ||||||
|  |      *            opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, | ||||||
|  |      *            IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, | ||||||
|  |      *            IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. | ||||||
|  |      * @param label | ||||||
|  |      *            the operand of the instruction to be constructed. This operand | ||||||
|  |      *            is a label that designates the instruction to which the jump | ||||||
|  |      *            instruction may jump. | ||||||
|  |      */ | ||||||
|  |     public JumpInsnNode(final int opcode, final LabelNode label) { | ||||||
|  |         super(opcode); | ||||||
|  |         this.label = label; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets the opcode of this instruction. | ||||||
|  |      *  | ||||||
|  |      * @param opcode | ||||||
|  |      *            the new instruction opcode. This opcode must be IFEQ, IFNE, | ||||||
|  |      *            IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, | ||||||
|  |      *            IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, | ||||||
|  |      *            JSR, IFNULL or IFNONNULL. | ||||||
|  |      */ | ||||||
|  |     public void setOpcode(final int opcode) { | ||||||
|  |         this.opcode = opcode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return JUMP_INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         mv.visitJumpInsn(opcode, label.getLabel()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new JumpInsnNode(opcode, clone(label, labels)); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										78
									
								
								src/main/asm/org/objectweb/asm/tree/LabelNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/main/asm/org/objectweb/asm/tree/LabelNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.Label; | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An {@link AbstractInsnNode} that encapsulates a {@link Label}. | ||||||
|  |  */ | ||||||
|  | public class LabelNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     private Label label; | ||||||
|  | 
 | ||||||
|  |     public LabelNode() { | ||||||
|  |         super(-1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public LabelNode(final Label label) { | ||||||
|  |         super(-1); | ||||||
|  |         this.label = label; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return LABEL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Label getLabel() { | ||||||
|  |         if (label == null) { | ||||||
|  |             label = new Label(); | ||||||
|  |         } | ||||||
|  |         return label; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor cv) { | ||||||
|  |         cv.visitLabel(getLabel()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return labels.get(this); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void resetLabel() { | ||||||
|  |         label = null; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										78
									
								
								src/main/asm/org/objectweb/asm/tree/LdcInsnNode.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/main/asm/org/objectweb/asm/tree/LdcInsnNode.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | |||||||
|  | /*** | ||||||
|  |  * ASM: a very small and fast Java bytecode manipulation framework | ||||||
|  |  * Copyright (c) 2000-2011 INRIA, France Telecom | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. Neither the name of the copyright holders nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived from | ||||||
|  |  *    this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||||
|  |  * THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | package org.objectweb.asm.tree; | ||||||
|  | 
 | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | import org.objectweb.asm.MethodVisitor; | ||||||
|  | import org.objectweb.asm.Opcodes; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A node that represents an LDC instruction. | ||||||
|  |  *  | ||||||
|  |  * @author Eric Bruneton | ||||||
|  |  */ | ||||||
|  | public class LdcInsnNode extends AbstractInsnNode { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * The constant to be loaded on the stack. This parameter must be a non null | ||||||
|  |      * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a | ||||||
|  |      * {@link String} or a {@link org.objectweb.asm.Type}. | ||||||
|  |      */ | ||||||
|  |     public Object cst; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs a new {@link LdcInsnNode}. | ||||||
|  |      *  | ||||||
|  |      * @param cst | ||||||
|  |      *            the constant to be loaded on the stack. This parameter must be | ||||||
|  |      *            a non null {@link Integer}, a {@link Float}, a {@link Long}, a | ||||||
|  |      *            {@link Double} or a {@link String}. | ||||||
|  |      */ | ||||||
|  |     public LdcInsnNode(final Object cst) { | ||||||
|  |         super(Opcodes.LDC); | ||||||
|  |         this.cst = cst; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getType() { | ||||||
|  |         return LDC_INSN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void accept(final MethodVisitor mv) { | ||||||
|  |         mv.visitLdcInsn(cst); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) { | ||||||
|  |         return new LdcInsnNode(cst); | ||||||
|  |     } | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user