1*387f9dfdSAndroid Build Coastguard WorkerDemonstrations of uflow. 2*387f9dfdSAndroid Build Coastguard Worker 3*387f9dfdSAndroid Build Coastguard Worker 4*387f9dfdSAndroid Build Coastguard Workeruflow traces method entry and exit events and prints a visual flow graph that 5*387f9dfdSAndroid Build Coastguard Workershows how methods are entered and exited, similar to a tracing debugger with 6*387f9dfdSAndroid Build Coastguard Workerbreakpoints. This can be useful for understanding program flow in high-level 7*387f9dfdSAndroid Build Coastguard Workerlanguages such as Java, Perl, PHP, Python, Ruby, and Tcl which provide USDT 8*387f9dfdSAndroid Build Coastguard Workerprobes for method invocations. 9*387f9dfdSAndroid Build Coastguard Worker 10*387f9dfdSAndroid Build Coastguard Worker 11*387f9dfdSAndroid Build Coastguard WorkerFor example, trace all Ruby method calls in a specific process: 12*387f9dfdSAndroid Build Coastguard Worker 13*387f9dfdSAndroid Build Coastguard Worker# ./uflow -l ruby 27245 14*387f9dfdSAndroid Build Coastguard WorkerTracing method calls in ruby process 27245... Ctrl-C to quit. 15*387f9dfdSAndroid Build Coastguard WorkerCPU PID TID TIME(us) METHOD 16*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- IO.gets 17*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- IRB::StdioInputMethod.gets 18*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 -> IRB::Context.verbose? 19*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 -> NilClass.nil? 20*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- NilClass.nil? 21*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 -> IO.tty? 22*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- IO.tty? 23*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 -> Kernel.kind_of? 24*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- Kernel.kind_of? 25*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- IRB::Context.verbose? 26*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- IRB::Irb.signal_status 27*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 -> String.chars 28*387f9dfdSAndroid Build Coastguard Worker3 27245 27245 4.536 <- String.chars 29*387f9dfdSAndroid Build Coastguard Worker^C 30*387f9dfdSAndroid Build Coastguard Worker 31*387f9dfdSAndroid Build Coastguard WorkerIn the preceding output, indentation indicates the depth of the flow graph, 32*387f9dfdSAndroid Build Coastguard Workerand the <- and -> arrows indicate the direction of the event (exit or entry). 33*387f9dfdSAndroid Build Coastguard Worker 34*387f9dfdSAndroid Build Coastguard WorkerOften, the amount of output can be overwhelming. You can filter specific 35*387f9dfdSAndroid Build Coastguard Workerclasses or methods. For example, trace only methods from the Thread class: 36*387f9dfdSAndroid Build Coastguard Worker 37*387f9dfdSAndroid Build Coastguard Worker# ./uflow -C java/lang/Thread $(pidof java) 38*387f9dfdSAndroid Build Coastguard WorkerTracing method calls in java process 27722... Ctrl-C to quit. 39*387f9dfdSAndroid Build Coastguard WorkerCPU PID TID TIME(us) METHOD 40*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/Thread.<init> 41*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/Thread.init 42*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/Thread.init 43*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/Thread.currentThread 44*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 <- java/lang/Thread.currentThread 45*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/Thread.getThreadGroup 46*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 <- java/lang/Thread.getThreadGroup 47*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/ThreadGroup.checkAccess 48*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 <- java/lang/ThreadGroup.checkAccess 49*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 -> java/lang/ThreadGroup.addUnstarted 50*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.144 <- java/lang/ThreadGroup.addUnstarted 51*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.isDaemon 52*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.isDaemon 53*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.getPriority 54*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.getPriority 55*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.getContextClassLoader 56*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.getContextClassLoader 57*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.setPriority 58*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.checkAccess 59*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.checkAccess 60*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.getThreadGroup 61*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.getThreadGroup 62*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/ThreadGroup.getMaxPriority 63*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/ThreadGroup.getMaxPriority 64*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.setPriority0 65*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.setPriority0 66*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.setPriority 67*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.nextThreadID 68*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.nextThreadID 69*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.init 70*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.init 71*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.<init> 72*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.start 73*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/ThreadGroup.add 74*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/ThreadGroup.add 75*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 -> java/lang/Thread.start0 76*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.145 <- java/lang/Thread.start0 77*387f9dfdSAndroid Build Coastguard Worker3 27722 27731 3.146 <- java/lang/Thread.start 78*387f9dfdSAndroid Build Coastguard Worker2 27722 27742 3.146 -> java/lang/Thread.run 79*387f9dfdSAndroid Build Coastguard Worker^C 80*387f9dfdSAndroid Build Coastguard Worker 81*387f9dfdSAndroid Build Coastguard WorkerThe reason that the CPU number is printed in the first column is that events 82*387f9dfdSAndroid Build Coastguard Workerfrom different threads can be reordered when running on different CPUs, and 83*387f9dfdSAndroid Build Coastguard Workerproduce non-sensible output. By looking for changes in the CPU column, you can 84*387f9dfdSAndroid Build Coastguard Workereasily see if the events you're following make sense and belong to the same 85*387f9dfdSAndroid Build Coastguard Workerthread running on the same CPU. 86*387f9dfdSAndroid Build Coastguard Worker 87*387f9dfdSAndroid Build Coastguard Worker 88*387f9dfdSAndroid Build Coastguard WorkerUSAGE message: 89*387f9dfdSAndroid Build Coastguard Worker 90*387f9dfdSAndroid Build Coastguard Worker# ./uflow -h 91*387f9dfdSAndroid Build Coastguard Workerusage: uflow.py [-h] [-l {java,perl,php,python,ruby,tcl}] [-M METHOD] [-C CLAZZ] [-v] 92*387f9dfdSAndroid Build Coastguard Worker pid 93*387f9dfdSAndroid Build Coastguard Worker 94*387f9dfdSAndroid Build Coastguard WorkerTrace method execution flow in high-level languages. 95*387f9dfdSAndroid Build Coastguard Worker 96*387f9dfdSAndroid Build Coastguard Workerpositional arguments: 97*387f9dfdSAndroid Build Coastguard Worker pid process id to attach to 98*387f9dfdSAndroid Build Coastguard Worker 99*387f9dfdSAndroid Build Coastguard Workeroptional arguments: 100*387f9dfdSAndroid Build Coastguard Worker -h, --help show this help message and exit 101*387f9dfdSAndroid Build Coastguard Worker -l {java,perl,php,python,ruby,tcl}, --language {java,perl,php,python,ruby,tcl} 102*387f9dfdSAndroid Build Coastguard Worker language to trace 103*387f9dfdSAndroid Build Coastguard Worker -M METHOD, --method METHOD 104*387f9dfdSAndroid Build Coastguard Worker trace only calls to methods starting with this prefix 105*387f9dfdSAndroid Build Coastguard Worker -C CLAZZ, --class CLAZZ 106*387f9dfdSAndroid Build Coastguard Worker trace only calls to classes starting with this prefix 107*387f9dfdSAndroid Build Coastguard Worker -v, --verbose verbose mode: print the BPF program (for debugging 108*387f9dfdSAndroid Build Coastguard Worker purposes) 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Workerexamples: 111*387f9dfdSAndroid Build Coastguard Worker ./uflow -l java 185 # trace Java method calls in process 185 112*387f9dfdSAndroid Build Coastguard Worker ./uflow -l ruby 134 # trace Ruby method calls in process 134 113*387f9dfdSAndroid Build Coastguard Worker ./uflow -M indexOf -l java 185 # trace only 'indexOf'-prefixed methods 114*387f9dfdSAndroid Build Coastguard Worker ./uflow -C '<stdin>' -l python 180 # trace only REPL-defined methods 115