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