1
1
package com .datadog .debugger .instrumentation ;
2
2
3
3
import static com .datadog .debugger .instrumentation .Types .REFLECTIVE_FIELD_VALUE_RESOLVER_TYPE ;
4
+ import static java .lang .String .format ;
4
5
import static org .objectweb .asm .Type .getMethodDescriptor ;
5
6
import static org .objectweb .asm .Type .getObjectType ;
6
7
7
8
import com .datadog .debugger .agent .Generated ;
8
9
import datadog .trace .util .Strings ;
10
+ import de .thetaphi .forbiddenapis .SuppressForbidden ;
11
+ import java .io .File ;
12
+ import java .io .FileOutputStream ;
13
+ import java .io .IOException ;
14
+ import java .io .PrintWriter ;
15
+ import java .io .StringWriter ;
9
16
import java .lang .reflect .Field ;
10
17
import java .lang .reflect .Modifier ;
11
18
import java .util .ArrayList ;
19
+ import java .util .Arrays ;
12
20
import java .util .Collections ;
13
21
import java .util .Comparator ;
14
22
import java .util .List ;
23
+ import java .util .StringJoiner ;
15
24
import java .util .stream .Collectors ;
25
+ import org .objectweb .asm .ClassWriter ;
16
26
import org .objectweb .asm .Opcodes ;
17
- import org .objectweb .asm .Type ;
18
27
import org .objectweb .asm .signature .SignatureReader ;
19
28
import org .objectweb .asm .signature .SignatureVisitor ;
20
29
import org .objectweb .asm .tree .AbstractInsnNode ;
24
33
import org .objectweb .asm .tree .InsnList ;
25
34
import org .objectweb .asm .tree .InsnNode ;
26
35
import org .objectweb .asm .tree .LdcInsnNode ;
36
+ import org .objectweb .asm .tree .LineNumberNode ;
27
37
import org .objectweb .asm .tree .LocalVariableNode ;
28
38
import org .objectweb .asm .tree .MethodInsnNode ;
29
39
import org .objectweb .asm .tree .MethodNode ;
30
40
import org .objectweb .asm .tree .TypeInsnNode ;
41
+ import org .objectweb .asm .util .Printer ;
42
+ import org .objectweb .asm .util .Textifier ;
43
+ import org .objectweb .asm .util .TraceClassVisitor ;
31
44
32
45
/** Helper class for bytecode generation */
33
46
public class ASMHelper {
@@ -36,6 +49,45 @@ public class ASMHelper {
36
49
public static final Type STRING_TYPE = new Type (Types .STRING_TYPE );
37
50
public static final Type LONG_TYPE = new Type (org .objectweb .asm .Type .LONG_TYPE );
38
51
52
+ public static void dumpMethod (ClassNode classNode , String method , String suffix ) {
53
+ String content = extractMethod (classNode , method );
54
+ File output ;
55
+ int count = 0 ;
56
+ do {
57
+ output = new File (format ("build/%s-%d-%s.txt" , method , count ++, suffix ));
58
+ } while (output .exists ());
59
+ output .getParentFile ().mkdirs ();
60
+ try (PrintWriter writer = new PrintWriter (output )) {
61
+ writer .println (content );
62
+ String absolutePath = output .getAbsolutePath ();
63
+ absolutePath = absolutePath .substring (0 , absolutePath .lastIndexOf ('.' ));
64
+ absolutePath += ".class" ;
65
+ ClassWriter classWriter = new ClassWriter (0 );
66
+ classNode .accept (classWriter );
67
+ try (FileOutputStream stream = new FileOutputStream (absolutePath )) {
68
+ stream .write (classWriter .toByteArray ());
69
+ }
70
+ } catch (IOException e ) {
71
+ throw new RuntimeException (e );
72
+ }
73
+ }
74
+
75
+ @ SuppressForbidden
76
+ static String extractMethod (ClassNode classNode , String method ) {
77
+ StringJoiner joiner = new StringJoiner ("\n " );
78
+ joiner .add ("Class: " + classNode .name );
79
+ StringWriter writer = new StringWriter ();
80
+ classNode .accept (new TraceClassVisitor (null , new Textifier (), new PrintWriter (writer )));
81
+ List <String > strings = Arrays .asList (writer .toString ().split ("\n " ));
82
+ for (int i = 0 ; i < strings .size (); i ++) {
83
+ if (strings .get (i ).matches (format (".*(private|public).* %s\\ (.*" , method ))) {
84
+ while (!strings .get (i ).equals ("" ))
85
+ joiner .add (String .format ("[%3d] %s" , i , strings .get (i ++)));
86
+ }
87
+ }
88
+ return joiner .toString ();
89
+ }
90
+
39
91
public static void invokeInterface (
40
92
InsnList insnList ,
41
93
org .objectweb .asm .Type owner ,
@@ -322,6 +374,18 @@ public static boolean isStoreCompatibleType(
322
374
return previousSort == currentSort ;
323
375
}
324
376
377
+ public static String toString (AbstractInsnNode node ) {
378
+ String opcode = node .getOpcode () >= 0 ? Printer .OPCODES [node .getOpcode ()] : node .toString ();
379
+ if (node instanceof LineNumberNode ) {
380
+ return String .format ("LineNumber: %s" , ((LineNumberNode ) node ).line );
381
+ } else if (node instanceof MethodInsnNode ) {
382
+ MethodInsnNode method = (MethodInsnNode ) node ;
383
+ return String .format ("%s: [%s] %s" , opcode , method .name , method .desc );
384
+ } else {
385
+ return opcode ;
386
+ }
387
+ }
388
+
325
389
private static int widenIntType (int sort ) {
326
390
switch (sort ) {
327
391
case org .objectweb .asm .Type .BOOLEAN :
0 commit comments