[kgtp] r926 committed - Adding hotcode

  • From: kgtp@xxxxxxxxxxxxxx
  • To: kgtp@xxxxxxxxxxxxx
  • Date: Wed, 22 Feb 2012 13:27:52 +0000

Revision: 926
Author:   teawater
Date:     Wed Feb 22 05:26:42 2012
Log:      Adding hotcode

http://code.google.com/p/kgtp/source/detail?r=926

Modified:
 /branches/hotcode/hotcode.py

=======================================
--- /branches/hotcode/hotcode.py        Tue Jan 31 06:00:01 2012
+++ /branches/hotcode/hotcode.py        Wed Feb 22 05:26:42 2012
@@ -1,6 +1,6 @@
 #!/usr/bin/python

-# This script is used to find the hotcode in a task
+# This script is used to find the hotcode in some tasks
 # GPL
 # Copyright(C) Hui Zhu (teawater@xxxxxxxxx), 2012

@@ -24,34 +24,54 @@
                if s[0:1] != 'n' and s[0:1] != 'N':
                        return;
        #gdb.execute("inferior 1")
-       #gdb.execute("target remote /sys/kernel/debug/gtp", True, False)
-       #gdb.execute("set disconnected-tracing off", True, False)
-       #exit(1);
-       global keep_going
-       keep_going = 0
-
+       gdb.execute("target remote /sys/kernel/debug/gtp", True, False)
+       gdb.execute("set disconnected-tracing off", True, False)
+       exit(1);
+
+def add_inferior():
+       fid = gdb.execute("add-inferior", False, True)
+       if fid.find("Added inferior ") != 0:
+               return -1
+       fid = int(fid[len("Added inferior "):])
+       return fid
+
+#0 inferior_id  1 dir_name 2 kernel_list 3 user_list
+task_list = {}
+no_task = False
 kernel_hotcode_list = {}
-user_hotcode_list = {}
-
-def hotcode_add(name, user):
-       if user:
-               if name in user_hotcode_list:
-                       user_hotcode_list[name] += 1
-               else:
-                       user_hotcode_list[name] = 1
-       else:
+
+def task_list_add_function(is_user, pid, name):
+       if no_task:
                if name in kernel_hotcode_list:
                        kernel_hotcode_list[name] += 1
                else:
                        kernel_hotcode_list[name] = 1
+       else:
+               if is_user:
+                       if name in task_list[pid][3]:
+                               task_list[pid][3][name] += 1
+                       else:
+                               task_list[pid][3][name] = 1
+               else:
+                       if name in task_list[pid][2]:
+                               task_list[pid][2][name] += 1
+                       else:
+                               task_list[pid][2][name] = 1

 def hotcode_show():
-       print "User hotcode:"
-       for c in dict_sort(user_hotcode_list):
-               print c[0], "\t\t", c[1]
-       print "Kernel hotcode:"
-       for c in dict_sort(kernel_hotcode_list):
-               print c[0], "\t\t", c[1]
+       if no_task:
+               print "Kernel hotcode:"
+               for c in dict_sort(kernel_hotcode_list):
+                       print c[0], "\t\t", c[1]
+       else:
+               for pid in task_list:
+                       print "task", str(pid), task_list[pid][1]
+                       print "Kernel hotcode:"
+                       for c in dict_sort(task_list[pid][2]):
+                               print c[0], "\t\t", c[1]
+                       print "User hotcode:"
+                       for c in dict_sort(task_list[pid][3]):
+                               print c[0], "\t\t", c[1]

 gdb.execute("set target-async on", True, False)
 gdb.execute("set pagination off", True, False)
@@ -62,31 +82,86 @@
 except:
        pass

-#Get which task pid why want to trace
-pid = -1
+trace_user = True
+trace_kernel = True
 while 1:
+       tmp = "Both"
        try:
- pid = input('Please input the pid that you want to trace:[-1 (means all the task in the kernel)]')
+               tmp = raw_input('Which part of code you want 
trace?(User/Kernel/[Both])')
        except:
-               next
+               continue
+       if tmp[0:1] == 'U' or tmp[0:1] == 'u':
+               trace_kernel = False
+       elif tmp[0:1] == 'K' or tmp[0:1] == 'k':
+               trace_user = False
        break

-trace_user = True
-trace_kernel = True
-if pid < 0:
-       trace_user = False
-else:
-       while 1:
-               tmp = "Both"
+#Get which task pid why want to trace
+print("Please input the pid of tasks that you want to trace - one per line (use empty to end input).")
+print("If not set any task, will trace all code in the Kernel.")
+while 1:
+       pid = -1
+       try:
+               pid = input('id:')
+       except:
+               pass
+       if pid <= 0:
+               break
+       if pid in task_list:
+               print("This pid already in the list.")
+               continue
+       user_dir = ""
+       fid = 0
+       if trace_user:
                try:
- tmp = raw_input('Which part of code you want trace?(User/Kernel/[Both])')
+                       orig_user_dir = user_dir = 
os.path.realpath("/proc/"+str(pid)+"/exe")
                except:
-                       next
-               if tmp[0:1] == 'U' or tmp[0:1] == 'u':
-                       trace_kernel = False
-               elif tmp[0:1] == 'K' or tmp[0:1] == 'k':
-                       trace_user = False
-               break
+                       #maybe this is the kernel task
+ print "Cannot get the user code info of thie pid, will not parse the code symbol"
+                       task_list[pid] = (fid, user_dir, {}, {})
+                       continue
+               while 1:
+                       tmp = ""
+                       try:
+ tmp = raw_input('Please input the debug binary of task if you want to change it:['+user_dir+']')
+                       except:
+                               continue
+                       if tmp != "":
+                               user_dir = os.path.realpath(tmp)
+                       break
+               print "Use "+user_dir+" as debug binary."
+               fid = add_inferior()
+               if fid < 0:
+                       print "Try to load task got error."
+                       continue
+               gdb.execute("inferior "+str(fid))
+               pfile = open("/proc/"+str(pid)+"/maps", "r")
+               tmplist = pfile.read().split(os.linesep)
+               pfile.close()
+               for c in tmplist:
+                       c_list = c.split(" ")
+                       filename = c_list[-1].strip()
+ if filename != orig_user_dir and os.path.exists(filename) and len(c_list) > 2 and len(c_list[1]) > 3 and c_list[1][2] == 'x':
+                               addr = "0x"+c_list[0][0:c.find('-')]
+                               gdb.execute("file "+filename)
+                               info_files = gdb.execute("info files", True, 
True)
+                               info_files_list = info_files.split(os.linesep)
+                               text_offset = "0x0"
+                               for line in info_files_list:
+                                       line_list = line.split(" is ")
+                                       if len(line_list) == 2 and line_list[1].strip() 
== ".text":
+                                               line_list[0] = 
line_list[0].strip()
+                                               text_offset = 
line_list[0][0:line_list[0].find(' - ')]
+                               print ("add-symbol-file "+filename+" 
("+addr+"+"+text_offset+")")
+                               gdb.execute("add-symbol-file "+filename+" 
("+addr+"+"+text_offset+")")
+               gdb.execute("file "+user_dir)
+               gdb.execute("inferior 1")
+       task_list[pid] = (fid, user_dir, {}, {})
+
+if len(task_list) == 0:
+       trace_user = False
+       trace_kernel = True
+       no_task = True

 #Set tracepoint
 gdb.execute("target remote /sys/kernel/debug/gtp", True, False)
@@ -99,20 +174,32 @@
 tempfile = open(tempfilename, "w")
 tempfile.write("trace handle_irq\n")
 pid_str = ""
-if pid >= 0:
- pid_str = "(((struct task_struct *)$current_task)->pid == "+str(pid)+") && "
+for pid in task_list:
+       if pid_str != "":
+               pid_str += " || "
+       else:
+               pid_str += "("
+       pid_str += "($current_task_pid == "+str(pid)+") "
+if pid_str != "":
+       pid_str += ")"
+cond_str = ""
 if not trace_user:
-       tempfile.write("condition $bpnum ("+pid_str+"((regs->cs & 3) == 0))\n")
+       if pid_str != "":
+               cond_str += " && "
+       cond_str = " ((regs->cs & 3) == 0)"
 elif not trace_kernel:
-       tempfile.write("condition $bpnum ("+pid_str+"((regs->cs & 3) == 3))\n")
-else:
- tempfile.write("condition $bpnum (((struct task_struct *)$current_task)->pid == "+pid+")\n")
+       if pid_str != "":
+               cond_str += "&&"
+       cond_str = " ((regs->cs & 3) == 3)"
+tempfile.write("condition $bpnum "+pid_str+cond_str+"\n")
 tempfile.write("commands\n")
-if pid < 0:
+if no_task:
        tempfile.write("collect $no_self_trace\n")
 tempfile.write("collect regs->ip\n")
 if trace_user and trace_kernel:
        tempfile.write("collect regs->cs\n")
+if not no_task:
+       tempfile.write("collect $current_task_pid\n")
 tempfile.write("end\n")
 tempfile.close()
 gdb.execute("source "+tempfilename, True, False)
@@ -124,60 +211,30 @@
 signal.signal(signal.SIGINT, sigint_handler);
 signal.siginterrupt(signal.SIGINT, False);

-user_dir = ""
-if trace_user:
-       orig_user_dir = user_dir = os.path.realpath("/proc/"+pid+"/exe")
-       while 1:
-               tmp = ""
-               try:
- tmp = raw_input('Please input the debug binary of task if you want to change it:['+user_dir+']')
-               except:
-                       next
-               if tmp != "":
-                       user_dir = os.path.realpath(tmp)
-               break
-       print "Use "+user_dir+" as debug binary."
-       gdb.execute("add-inferior")
-       gdb.execute("inferior 2")
-       tempfile = open("/proc/"+pid+"/maps", "r")
-       tmplist = tempfile.read().split(os.linesep)
-       tempfile.close()
-       for c in tmplist:
-               c_list = c.split(" ")
-               filename = c_list[-1].strip()
- if filename != orig_user_dir and os.path.exists(filename) and len(c_list) > 2 and len(c_list[1]) > 3 and c_list[1][2] == 'x':
-                       addr = "0x"+c_list[0][0:c.find('-')]
-                       gdb.execute("file "+filename)
-                       info_files = gdb.execute("info files", True, True)
-                       info_files_list = info_files.split(os.linesep)
-                       text_offset = "0x0"
-                       for line in info_files_list:
-                               line_list = line.split(" is ")
-                               if len(line_list) == 2 and line_list[1].strip() == 
".text":
-                                       line_list[0] = line_list[0].strip()
-                                       text_offset = 
line_list[0][0:line_list[0].find(' - ')]
-                       print ("add-symbol-file "+filename+" 
("+addr+"+"+text_offset+")")
-                       gdb.execute("add-symbol-file "+filename+" 
("+addr+"+"+text_offset+")")
-       gdb.execute("file "+user_dir)
-       gdb.execute("inferior 1")
-
 #Connect to pipe
 gdb.execute("target tfile /sys/kernel/debug/gtpframe_pipe")

 error_again = 0
 pack_num = 0
-keep_going = 1
-while keep_going:
+while 1:
        try:
                gdb.execute("tfind 0", False, True)
                #switch to user inferior if need
                is_user = False
+               pid = 0
+               if not no_task:
+                       pid = long(gdb.parse_and_eval("$current_task_pid"))
+                       if not pid in task_list:
+ raise gdb.error ("Cannot find inferior for pid "+ str(pid) +", drop one entry.")
                if trace_user and long(gdb.parse_and_eval("regs->cs & 3")) == 3:
-                       ip = long(gdb.parse_and_eval("regs->ip - 1"))
                        is_user = True
-                       gdb.execute("inferior 2", False, True)
-                       sym = gdb.execute("info symbol "+str(ip), True, True)
-                       gdb.execute("inferior 1", False, True)
+                       if task_list[pid][0] == 0:
+                               sym = ""
+                       else:
+                               ip = long(gdb.parse_and_eval("regs->ip - 1"))
+                               gdb.execute("inferior "+str(task_list[pid][0]), 
False, True)
+                               sym = gdb.execute("info symbol "+str(ip), True, 
True)
+                               gdb.execute("inferior 1", False, True)
                else:
                        sym = gdb.execute("info symbol (regs->ip - 1)", True, 
True)
                sym = sym.rstrip(os.linesep)
@@ -192,24 +249,18 @@
                                filename_offset = sym.find(" of ")
                                if filename_offset > 0:
                                        function += sym[filename_offset:]
-               hotcode_add(function, is_user)
+               task_list_add_function(is_user, pid, function)
                error_again = 0
                pack_num += 1
        except gdb.error, x:
                print("Drop one entry because", x)
                error_again += 1
                print error_again, pack_num
-               #try:
-                       #gdb.execute("target tfile 
/sys/kernel/debug/gtpframe_pipe")
-               #except:
-                       #pass
        except gdb.MemoryError, x:
                print("Drop one entry because", x)
                error_again += 1
                print error_again, pack_num
-               #try:
-                       #gdb.execute("target tfile 
/sys/kernel/debug/gtpframe_pipe")
-               #except:
-                       #pass
-
-       gdb.execute("tfind 1", False, True)
+       try:
+               gdb.execute("tfind 1", False, True)
+       except:
+               pass

Other related posts:

  • » [kgtp] r926 committed - Adding hotcode - kgtp