Created
August 21, 2020 23:27
-
-
Save comp500/a752b4b5cd13f30e5e4ecbc07dabc511 to your computer and use it in GitHub Desktop.
Revisions
-
comp500 created this gist
Aug 21, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,131 @@ package link.infra.jdwp; import com.sun.jdi.Field; import com.sun.jdi.LocalVariable; import com.sun.jdi.Method; import com.sun.jdi.ReferenceType; import com.sun.jdi.*; import com.sun.jdi.connect.AttachingConnector; import com.sun.jdi.connect.Connector; import com.sun.jdi.connect.IllegalConnectorArgumentsException; import org.apache.bcel.classfile.*; import org.apache.bcel.generic.Type; import org.apache.bcel.generic.*; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.Map; public class App { public static void main(String[] args) throws IOException, IllegalConnectorArgumentsException { List<AttachingConnector> connectors = Bootstrap.virtualMachineManager().attachingConnectors(); for (AttachingConnector connector : connectors) { if (connector.name().equals("com.sun.jdi.SocketAttach")) { Map<String, Connector.Argument> connArgs = connector.defaultArguments(); connArgs.get("port").setValue("5005"); VirtualMachine vm = connector.attach(connArgs); for (ReferenceType refType : vm.allClasses()) { if (!(refType instanceof ClassType)) { continue; } ClassType clazz = ((ClassType) refType); // TODO: test with j9+ if (clazz.classLoader() == null) { continue; } // TODO: workaround for lambdas? String sourceName; try { sourceName = clazz.sourceName(); } catch (AbsentInformationException ignored) { continue; } String name = clazz.name().replace('.', '/'); byte[] hmmm = clazz.constantPool(); ByteArrayOutputStream baos = new ByteArrayOutputStream(hmmm.length + 2); DataOutputStream dos = new DataOutputStream(baos); // TODO: unsigned? dos.writeShort(clazz.constantPoolCount()); dos.write(hmmm); ConstantPoolGen poolGen = new ConstantPoolGen(new ConstantPool(new DataInputStream(new ByteArrayInputStream(baos.toByteArray())))); String superClassName; ClassType superClass = clazz.superclass(); if (superClass != null) { superClassName = superClass.name().replace('.', '/'); } else { superClassName = "java/lang/Object"; } String[] implementedInterfaces = clazz.interfaces().stream().map(ReferenceType::name).toArray(String[]::new); ClassGen classGen = new ClassGen(name, superClassName, sourceName, clazz.modifiers(), implementedInterfaces, poolGen); classGen.setMinor(clazz.minorVersion()); classGen.setMajor(clazz.majorVersion()); String classGenericSignature = clazz.genericSignature(); if (classGenericSignature != null && classGenericSignature.length() > 0) { classGen.addAttribute(new Signature(poolGen.lookupUtf8("Signature"), 2, poolGen.lookupUtf8(classGenericSignature), poolGen.getConstantPool())); } // TODO: the necessary metadata for bootstrap methods isn't available!! :( // TODO: inner classes // TODO: enclosing method? for (Field field : clazz.fields()) { FieldGen fieldGen = new FieldGen(field.modifiers(), Type.getType(Utility.getSignature(field.typeName())), field.name(), poolGen); String genericSignature = field.genericSignature(); if (genericSignature != null && genericSignature.length() > 0) { fieldGen.addAttribute(new Signature(poolGen.lookupUtf8("Signature"), 2, poolGen.lookupUtf8(genericSignature), poolGen.getConstantPool())); } classGen.addField(fieldGen.getField()); } for (Method method : clazz.methods()) { String[] argNameList = null; try { argNameList = method.arguments().stream().map(LocalVariable::name).toArray(String[]::new); } catch (AbsentInformationException ignored) {} String[] argTypeList = Utility.methodSignatureArgumentTypes(method.signature()); if (argNameList == null || argTypeList.length != argNameList.length) { // TODO: better names argNameList = argTypeList; } MethodGen methodGen = new MethodGen(method.modifiers(), Type.getReturnType(method.signature()), Type.getArgumentTypes(method.signature()), argNameList, method.name(), name, new InstructionList(method.bytecodes()), poolGen); // TODO: line numbers // TODO: LVT // TODO: LVTT //method.variables(); methodGen.setMaxStack(); methodGen.setMaxLocals(); String genericSignature = method.genericSignature(); if (genericSignature != null && genericSignature.length() > 0) { methodGen.addAttribute(new Signature(poolGen.lookupUtf8("Signature"), 2, poolGen.lookupUtf8(genericSignature), poolGen.getConstantPool())); } classGen.addMethod(methodGen.getMethod()); } if (name.endsWith("class_310")) { classGen.getJavaClass().dump(new File("test.class")); break; } } vm.dispose(); } } } }