Messages in this thread Patch in this message | | | Date | Tue, 24 Apr 2012 21:20:50 +0800 | From | Hui Zhu <> | Subject | KGTP (Linux Kernel debugger and tracer) 20120424 release(doc update)[3/3]script |
| |
Signed-off-by: Hui Zhu <teawater@gmail.com> --- scripts/gtp/add-ons/hotcode.py | 747 +++++++++++++++++++++++++++++++++++++++++ scripts/gtp/add-ons/pe.py | 729 ++++++++++++++++++++++++++++++++++++++++ scripts/gtp/getgtprsp.pl | 141 +++++++ scripts/gtp/getmod.py | 148 ++++++++ 4 files changed, 1765 insertions(+)
--- /dev/null +++ b/scripts/gtp/add-ons/hotcode.py @@ -0,0 +1,747 @@ +#!/usr/bin/python + +# This script is used to find the hotcode in some tasks +# GPL +# Copyright(C) Hui Zhu (teawater@gmail.com), 2012 + +import gdb +import tempfile +import os +import signal +import sys +import traceback +import time + +class hotcode_list: + def __init__(self): + self.function_list = {} + self.file_list = {} + self.line_list = {} + self.function_list_line = {} + self.file_list_line = {} + self.num = 0 + +class task: + def __init__(self, fid, user_dir): + self.fid = fid + self.user_dir = user_dir + self.kernel = hotcode_list() + self.user = hotcode_list() + +debug_dir = "/usr/lib/debug/" +task_list = {} +no_task = False +kernel_hotcode_list = hotcode_list() + +output_html = True +output_html_file = "./hotcode.html" +show_line_number_default = 20 +show_line_number = show_line_number_default + +#-------------------------------------------------------------------------------------------------- +#For signal handler + +from operator import itemgetter +def dict_sort(d, reverse=False): + #proposed in PEP 265, using the itemgetter + return sorted(d.iteritems(), key=itemgetter(1), reverse=True) + +def hotcode_show_code_list(string, code_list): + if len(code_list) > 0: + print "\t", string + i = 1 + for c in dict_sort(code_list): + print "\t", c[0], "\t\t", c[1] + i += 1 + if i > show_line_number: + break + print + +def hotcode_show(): + if no_task: + hotcode_show_code_list("Hotest function", kernel_hotcode_list.function_list) + hotcode_show_code_list("Hotest file", kernel_hotcode_list.file_list) + hotcode_show_code_list("Hotest line", kernel_hotcode_list.line_list) + else: + for pid in task_list: + print "task", str(pid), task_list[pid].user_dir + print "Kernel hotcode:" + hotcode_show_code_list("Hotest function", task_list[pid].kernel.function_list) + hotcode_show_code_list("Hotest file", task_list[pid].kernel.file_list) + hotcode_show_code_list("Hotest line", task_list[pid].kernel.line_list) + print "User hotcode:" + hotcode_show_code_list("Hotest function", task_list[pid].user.function_list) + hotcode_show_code_list("Hotest file", task_list[pid].user.file_list) + hotcode_show_code_list("Hotest line", task_list[pid].user.line_list) + print + +html_id = 0 + +def hotcode_list_to_output_html_fd_1(llist, tlist, fd): + global html_id + i = 1 + for c in dict_sort(llist): + if tlist != None: + fd.write('''<tr><td onclick='sh("'''+str(html_id)+'''");'>'''+str(c[0])+'''</td><td style=" width: 10%; text-align: right;">'''+str(c[1])+'''</td></tr>''') + fd.write('''<tr><td style="text-align: center; display: none;" colspan="2" id="''' + str(html_id) + '''"><table style="width: 100%;" border="1" cellpadding="0" cellspacing="0"><tbody>''') + for d in dict_sort(tlist[c[0]]): + fd.write("<tr><td>" + str(d[0]) + '''</td><td style=" width: 10%; text-align: right;">''' + str(d[1]) + "</td></tr>") + fd.write('</tbody></table>') + else: + fd.write('<tr><td>'+str(c[0])+'''</td><td style=" width: 10%; text-align: right;">'''+str(c[1])+'''</td></tr>''') + i += 1 + html_id += 1 + if i > show_line_number: + break + +def hotcode_list_to_output_html_fd(hlist, fd): + global html_id + fd.write('''<tr><td style="text-align: center;" colspan="2">Hot functions list</td></tr>''') + hotcode_list_to_output_html_fd_1(hlist.function_list, hlist.function_list_line, fd) + + fd.write('''<tr><td style="text-align: center;" colspan="2">Hot file list</td></tr>''') + hotcode_list_to_output_html_fd_1(hlist.file_list, hlist.file_list_line, fd) + + fd.write('''<tr><td style="text-align: center;" colspan="2">Hot line list</td></tr>''') + hotcode_list_to_output_html_fd_1(hlist.line_list, None, fd) + +def hotcode_to_output_html_file(): + global html_id + html_id = 0 + fd = open(output_html_file, "w") + fd.write(''' +<html><head><title>Hotcode</title> +<script> +<!-- +function sh(id) +{ + if(document.getElementById(id).style.display=='none') { + document.getElementById(id).style.display='block'; + } + else { + document.getElementById(id).style.display='none'; + } +} +--> +</script></head> +<body> +<div style="text-align: center;">This file is generated by KGTP (<a href="http://code.google.com/p/kgtp/">http://code.google.com/p/kgtp/</a>) in ''' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + '''.</div> +<div style="text-align: center;">Click the function name or file name to see the detailed info.</div>''') + if show_line_number > 0: + fd.write('''<div style="text-align: center;">Just show top 20 of each list.</div>''') + if no_task: + fd.write('<br><br>') + fd.write('''<table style="margin-left: auto; margin-right: auto;" border="1" cellpadding="2" cellspacing="0"><tbody>''') + fd.write('''<tr><td><strong>Kernel space hotcode list</strong></td><td style=" width: 10%; text-align: right;">'''+str(kernel_hotcode_list.num)+'''</td></tr>''') + hotcode_list_to_output_html_fd(kernel_hotcode_list, fd) + fd.write('</tbody></table>') + else: + for pid in task_list: + fd.write('<br><br>') + fd.write('''<table style="margin-left: auto; margin-right: auto;" border="1" cellpadding="2" cellspacing="0"><tbody>''') + fd.write('''<tr><td style="text-align: center;" colspan="2">pid:''' + str(pid) + " " + task_list[pid].user_dir + "</td></tr>") + if trace_user: + fd.write('''<tr><td style="text-align: center;" colspan="2">User space hotcode list </td></tr>''') + fd.write('''<tr><td><strong>User space hotcode list</strong></td><td style=" width: 10%; text-align: right;">'''+str(task_list[pid].user.num)+'''</td></tr>''') + hotcode_list_to_output_html_fd(task_list[pid].user, fd) + if trace_kernel: + if trace_user: + fd.write('''<tr><td style="text-align: center;" colspan="2"></td></tr>''') + fd.write('''<tr><td><strong>Kernel space hotcode list</strong></td><td style=" width: 10%; text-align: right;">'''+str(task_list[pid].kernel.num)+'''</td></tr>''') + hotcode_list_to_output_html_fd(task_list[pid].kernel, fd) + fd.write('</tbody></table>') + fd.write('</body></html>') + fd.close() + print "Save", html_id, "entries." + +def sigint_handler(num, e): + if output_html: + hotcode_to_output_html_file() + else: + hotcode_show() + try: + s = raw_input('Conitnue? [(y)es], (n)o:') + except: + s = 'y' + finally: + if s[0:1] != 'n' and s[0:1] != 'N': + return; + #gdb.execute("inferior 1") + try: + gdb.execute("tfind -1", True, False) + gdb.execute("target remote /sys/kernel/debug/gtp", True, False) + gdb.execute("set disconnected-tracing off", True, False) + except: + print "Try to stop GTP got error, please use command \"sudo rmmod gtp.ko\" stop it." + exit(1); +#-------------------------------------------------------------------------------------------------- +#init + +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 + +gdb.execute("set target-async on", True, False) +gdb.execute("set pagination off", True, False) +gdb.execute("set confirm off", True, False) +gdb.execute("set circular-trace-buffer on", True, False) +gdb.execute("set debug-file-directory "+debug_dir, True, False) +try: + gdb.execute("kill", True, False) +except: + pass + +trace_user = True +trace_kernel = True +while 1: + tmp = "both" + try: + tmp = raw_input('Which part of code you want trace? [(b)oth], (u)ser, (k)ernel:') + except: + 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 + +#Get which task pid why want to trace +print("Please input the pid of task that you want to trace - one per line.") +print("If not set any task, will trace all code in the Linux kernel.") +while 1: + pid = -1 + try: + pid = input('task pid (use empty to stop pid input):') + 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: + orig_user_dir = user_dir = os.path.realpath("/proc/"+str(pid)+"/exe") + except: + #maybe this is the kernel task + print "Cannot get the user code info of this pid, will not parse the user level code symbol" + task_list[pid] = task(fid, user_dir) + continue + if os.path.exists(debug_dir+user_dir): + user_dir = debug_dir+user_dir + 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 + if not os.path.exists(user_dir): + print "Cannot get the user code info of this pid, will not parse the user level code symbol" + task_list[pid] = task(fid, user_dir) + continue + 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] = task(fid, user_dir) + +def get_addr_range_list(fun): + buf = gdb.execute("info line "+fun, False, True) + line_list = buf.split(os.linesep) + ret = [] + begin = -1 + end = -1 + for line in line_list: + addr_begin = line.find("starts at address ") + if addr_begin >= 0: + line = line[addr_begin + len("starts at address "):] + addr_end = line.find(" <"+fun) + if addr_end >= 0: + begin = int(line[:addr_end], 0) + line = line[addr_end + len(" <"+fun):] + addr_begin = line.find("ends at ") + if addr_begin >= 0: + line = line[addr_begin + len("ends at "):] + addr_end = line.find(" <"+fun) + if addr_end > 0: + end = int(line[:addr_end], 0) + if begin != -1: + ret.append([begin, end]) + begin = -1 + end = -1 + + if len(ret) > 0: + buf = gdb.execute("disassemble "+fun, False, True) + line_list = buf.split(os.linesep) + line_list.reverse() + end = 0 + for line in line_list: + addr_begin = line.find("0x") + if addr_begin >= 0: + line = line[addr_begin:] + addr_end = line.find(" <+") + if addr_end > 0: + end = int(line[:addr_end], 0) + 1 + break + if end != 0: + offset = 0 + for c in ret: + if c[1] < end: + if offset == 0 or offset > (end - c[1]): + offset = end - c[1] + for c in ret: + c[1] += offset + + return ret + +def get_ignore_str(function): + ret = "" + try: + s = raw_input('Do you want to ignore function \"'+function+'\"? [(y)es], (n)o:') + except: + s = 'y' + if s[0:1] != 'n' and s[0:1] != 'N': + r_list = get_addr_range_list(function) + for r in r_list: + if ret != "": + ret += " && " + else: + ret += "&& (" + #(regs->ip < r[0] || regs->ip > r[1]) + ret += "($pc_ip0 < "+str(r[0])+" || $pc_ip0 > "+str(r[1])+")" + if ret != "": + ret += ")" + return ret + +if len(task_list) == 0: + trace_user = False + trace_kernel = True + no_task = True + +try: + s = raw_input('Which way you want to output hotcode info when ctrl-c? [(h)tml], (t)ty:') +except: + s = 'h' +if s[0:1] == 't' or s[0:1] == 'T': + output_html = False +else: + output_html = True + +if output_html: + while 1: + try: + s = raw_input('Which file you want to save the html output? [' + output_html_file + ']:') + if os.path.exists(s): + if os.path.isfile(s): + s = raw_input('File ' + s +' exist, do you want to over write it? (y)es, [(n)o]:') + if s[0:1] != 'y' and s[0:1] != 'Y': + continue + else: + print 'File ' + s +' exist, but it cannot be written. Please choice another file.' + continue + except: + continue + if len(s) > 0: + output_html_file = s + break + +try: + show_line_number = input('Show line number (0 meas all)? ['+str(show_line_number)+']:') +except: + show_line_number = show_line_number_default + +#Set tracepoint +gdb.execute("target remote /sys/kernel/debug/gtp", True, False) + +try: + gdb.execute("tstop", True, False) + gdb.execute("delete", True, False) +except: + pass + + +def getmod(): + #following code is get from ../getmod.py + #use the code directly because sys.argv = [''] inside GDB + def format_file(name): + tmp = "" + for c in name: + if c == "_": + c = "-" + tmp += c + return tmp + + #Check if the target is available + if str(gdb.selected_thread()) == "None": + raise gdb.error("Please connect to Linux Kernel before use the script.") + + #Output the help + print "Use GDB command \"set $mod_search_dir=dir\" to set an directory for search the modules." + + ignore_gtp_ko = gdb.parse_and_eval("$ignore_gtp_ko") + if ignore_gtp_ko.type.code == gdb.TYPE_CODE_INT: + ignore_gtp_ko = int(ignore_gtp_ko) + else: + ignore_gtp_ko = 1 + + #Get the mod_search_dir + mod_search_dir_list = [] + #Get dir from $mod_search_dir + tmp_dir = gdb.parse_and_eval("$mod_search_dir") + if tmp_dir.type.code == gdb.TYPE_CODE_ARRAY: + tmp_dir = str(tmp_dir) + tmp_dir = tmp_dir[1:len(tmp_dir)] + tmp_dir = tmp_dir[0:tmp_dir.index("\"")] + mod_search_dir_list.append(tmp_dir) + #Get dir that same with current vmlinux + tmp_dir = str(gdb.execute("info files", False, True)) + tmp_dir = tmp_dir[tmp_dir.index("Symbols from \"")+len("Symbols from \""):len(tmp_dir)] + tmp_dir = tmp_dir[0:tmp_dir.index("\"")] + tmp_dir = tmp_dir[0:tmp_dir.rindex("/")] + mod_search_dir_list.append(tmp_dir) + #Get the dir of current Kernel + tmp_dir = "/lib/modules/" + str(os.uname()[2]) + if os.path.isdir(tmp_dir): + mod_search_dir_list.append(tmp_dir) + #Let user choice dir + mod_search_dir = "" + while mod_search_dir == "": + for i in range(0, len(mod_search_dir_list)): + print str(i)+". "+mod_search_dir_list[i] + try: + s = input('Select a directory for search the modules [0]:') + except SyntaxError: + s = 0 + except: + continue + if s < 0 or s >= len(mod_search_dir_list): + continue + mod_search_dir = mod_search_dir_list[s] + + mod_list_offset = long(gdb.parse_and_eval("((size_t) &(((struct module *)0)->list))")) + mod_list = long(gdb.parse_and_eval("(&modules)")) + mod_list_current = mod_list + + while 1: + mod_list_current = long(gdb.parse_and_eval("((struct list_head *) "+str(mod_list_current)+")->next")) + + #check if need break the loop + if mod_list == mod_list_current: + break + + mod = mod_list_current - mod_list_offset + + #get mod_name + mod_name = str(gdb.parse_and_eval("((struct module *)"+str(mod)+")->name")) + mod_name = mod_name[mod_name.index("\"")+1:len(mod_name)] + mod_name = mod_name[0:mod_name.index("\"")] + if mod_name == "fglrx": + contiue + mod_name += ".ko" + mod_name = format_file(mod_name) + + #get mod_dir_name + mod_dir_name = "" + for root, dirs, files in os.walk(mod_search_dir): + for afile in files: + tmp_file = format_file(afile) + if tmp_file == mod_name: + mod_dir_name = os.path.join(root,afile) + break + if mod_dir_name != "": + break + + command = " " + + #Add module_core to command + command += str(gdb.parse_and_eval("((struct module *)"+str(mod)+")->module_core")) + + #Add each sect_attrs->attrs to command + #get nsections + nsections = int(gdb.parse_and_eval("((struct module *)"+str(mod)+")->sect_attrs->nsections")) + sect_attrs = long(gdb.parse_and_eval("(u64)((struct module *)"+str(mod)+")->sect_attrs")) + for i in range(0, nsections): + command += " -s" + tmp = str(gdb.parse_and_eval("((struct module_sect_attrs *)"+str(sect_attrs)+")->attrs["+str(i)+"].name")) + tmp = tmp[tmp.index("\"")+1:len(tmp)] + tmp = tmp[0:tmp.index("\"")] + command += " "+tmp + tmp = str(gdb.parse_and_eval("((struct module_sect_attrs *)"+str(sect_attrs)+")->attrs["+str(i)+"].address")) + command += " "+tmp + + if mod_dir_name == "": + print "Cannot find out",mod_name,"from directory." + print "Please use following command load the symbols from it:" + print "add-symbol-file some_dir/"+mod_name+command + else: + if ignore_gtp_ko and mod_name == "gtp.ko": + pass + else: + #print "add-symbol-file "+mod_dir_name+command + gdb.execute("add-symbol-file "+mod_dir_name+command, False, False) + +if trace_kernel: + try: + s = raw_input('Do you load the symbol from LKM? (y)es, [(n)o]:') + except: + s = 'n' + if s[0:1] == 'y' or s[0:1] == 'Y': + getmod() + +cpu_number = int(gdb.parse_and_eval("$cpu_number")) +tempfilename = tempfile.mktemp() +tempfile = open(tempfilename, "w") +if no_task: + ignore_str = "" + #Setup first tracepoint + ignore_str += get_ignore_str("arch_local_irq_enable") + ignore_str += get_ignore_str("intel_idle") + # GDB have bug with long conditon so close them + #ignore_str += get_ignore_str("__do_softirq") + #ignore_str += get_ignore_str("_raw_spin_unlock_irqrestore") + + for i in range(0, cpu_number): + tempfile.write("tvariable $pc_ip"+str(i)+"\n") + tempfile.write("tvariable $pc_cs"+str(i)+"\n") + tempfile.write("trace handle_irq\n") + tempfile.write("commands\n") + tempfile.write("teval $pc_ip0=(u64)regs->ip\n") + tempfile.write("teval $pc_cs0=(u64)regs->cs\n") + tempfile.write("end\n") + #Setup second tracepoint + tempfile.write("trace handle_irq\n") + cond_str = " (($pc_cs0 & 3) == 0)" + tempfile.write("condition $bpnum "+cond_str+ignore_str+"\n") + tempfile.write("commands\n") + tempfile.write("collect $no_self_trace\n") + tempfile.write("collect $pc_ip0\n") + tempfile.write("end\n") + tempfile.write("trace smp_apic_timer_interrupt\n") + tempfile.write("commands\n") + tempfile.write("teval $pc_ip0=(u64)regs->ip\n") + tempfile.write("teval $pc_cs0=(u64)regs->cs\n") + tempfile.write("end\n") + #Setup second tracepoint + tempfile.write("trace smp_apic_timer_interrupt\n") + cond_str = " (($pc_cs0 & 3) == 0)" + tempfile.write("condition $bpnum "+cond_str+ignore_str+"\n") + tempfile.write("commands\n") + tempfile.write("collect $no_self_trace\n") + tempfile.write("collect $pc_ip0\n") + tempfile.write("end\n") +else: + pid_str = "" + 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: + if pid_str != "": + cond_str += " && " + cond_str += " ((regs->cs & 3) == 0)" + elif not trace_kernel: + if pid_str != "": + cond_str += "&&" + cond_str += " ((regs->cs & 3) == 3)" + tempfile.write("trace handle_irq\n") + tempfile.write("condition $bpnum "+pid_str+cond_str+"\n") + tempfile.write("commands\n") + tempfile.write("collect regs->ip\n") + if trace_user and trace_kernel: + tempfile.write("collect regs->cs\n") + tempfile.write("collect $current_task_pid\n") + tempfile.write("end\n") + tempfile.write("trace smp_apic_timer_interrupt\n") + tempfile.write("condition $bpnum "+pid_str+cond_str+"\n") + tempfile.write("commands\n") + tempfile.write("collect regs->ip\n") + if trace_user and trace_kernel: + tempfile.write("collect regs->cs\n") + tempfile.write("collect $current_task_pid\n") + tempfile.write("end\n") +tempfile.close() +tempfile = open(tempfilename, "r") +print "Tracepoint command:" +print tempfile.read() +tempfile.close() +gdb.execute("source "+tempfilename, True, False) +os.remove(tempfilename) +gdb.execute("set disconnected-tracing on", True, False) +gdb.execute("tstart") +gdb.execute("kill", True, False) + +signal.signal(signal.SIGINT, sigint_handler); +signal.siginterrupt(signal.SIGINT, False); + +#Connect to pipe +gdb.execute("target tfile /sys/kernel/debug/gtpframe_pipe") + +#-------------------------------------------------------------------------------------------------- +#cycle + +def add_line_to_list(line, line_list): + if line in line_list: + line_list[line] += 1 + else: + line_list[line] = 1 + +#info[0] line_num, info[1] file_name, info[2] function_name +def add_info_to_code_list(info, code_list): + line = str(info[1]) + ":" + str(info[0]) + #function_list + if info[2] in code_list.function_list: + code_list.function_list[info[2]] += 1 + else: + code_list.function_list[info[2]] = 1 + code_list.function_list_line[info[2]] = {} + add_line_to_list(line, code_list.function_list_line[info[2]]) + #file_list + if info[1] in code_list.file_list: + code_list.file_list[info[1]] += 1 + else: + code_list.file_list[info[1]] = 1 + code_list.file_list_line[info[1]] = {} + add_line_to_list(line, code_list.file_list_line[info[1]]) + #line_list + add_line_to_list(line, code_list.line_list) + #num + code_list.num += 1 + +def task_list_add_line(is_user, pid, info): + global task_list + if no_task: + add_info_to_code_list (info, kernel_hotcode_list) + else: + if is_user: + add_info_to_code_list (info, task_list[pid].user) + else: + add_info_to_code_list (info, task_list[pid].kernel) + +def get_line_from_sym(sym): + sym = sym.rstrip(os.linesep) + + #Get line_num and file_name + begin = sym.find("Line ") + end = sym.find("\" starts at address") + line_num = None + file_name = None + if begin >= 0 and end > 0 and begin + len("Line ") < end: + line = sym[begin + len("Line "):end] + line = line.split(" of \"") + if len(line) == 2: + line_num = line[0] + file_name = line[1] + sym = sym[end:] + + #Get function_name + begin = sym.find("<") + end = sym.find(">") + if begin >= 0 and end > 0 and begin + 1 < end: + function_name = sym[begin + 1:end] + end = function_name.rfind("+") + if end > 0: + function_name = function_name[:end] + sym = gdb.execute("info symbol "+function_name, True, True).rstrip(os.linesep) + begin = sym.rfind(" of ") + if begin > 0: + begin += len(" of ") + function_name = sym[begin:] + ":" + function_name + else: + function_name = None + return (line_num, file_name, function_name) + +if no_task: + while 1: + try: + gdb.execute("tfind 0", False, True) + cpu_id = long(gdb.parse_and_eval("$cpu_id")); + sym = gdb.execute("info line *($pc_ip"+str(cpu_id)+" - 1)", True, True) + line = get_line_from_sym(sym) + task_list_add_line(False, 0, line) + except gdb.error, x: + print("Drop one entry because:") + for file, lineno, function, text in traceback.extract_tb(sys.exc_info()[2]): + print file, lineno, function, text + except gdb.MemoryError, x: + print("Drop one entry because:") + for file, lineno, function, text in traceback.extract_tb(sys.exc_info()[2]): + print file, lineno, function, text + try: + gdb.execute("tfind 1", False, True) + except: + pass +else: + while 1: + try: + gdb.execute("tfind 0", False, True) + is_user = False + 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 (not trace_kernel or long(gdb.parse_and_eval("regs->cs & 3")) == 3): + is_user = True + ip = long(gdb.parse_and_eval("regs->ip - 1")) + gdb.execute("inferior "+str(task_list[pid].fid), False, True) + sym = gdb.execute("info line *"+str(ip), True, True) + else: + sym = gdb.execute("info line *(regs->ip - 1)", True, True) + line = get_line_from_sym(sym) + if is_user: + gdb.execute("inferior 1", False, True) + task_list_add_line(is_user, pid, line) + except gdb.error, x: + print("Drop one entry because:") + for file, lineno, function, text in traceback.extract_tb(sys.exc_info()[2]): + print file, lineno, function, text + try: + gdb.execute("inferior 1", False, True) + except: + pass + except gdb.MemoryError, x: + print("Drop one entry because:") + for file, lineno, function, text in traceback.extract_tb(sys.exc_info()[2]): + print file, lineno, function, text + try: + gdb.execute("inferior 1", False, True) + except: + pass + try: + gdb.execute("tfind 1", False, True) + except: + pass --- /dev/null +++ b/scripts/gtp/add-ons/pe.py @@ -0,0 +1,729 @@ +#!/usr/bin/python + +# This script is used to show the performance counters in graph mode +# GPL +# Copyright(C) Hui Zhu (teawater@gmail.com), 2011 + + +pe_list = [] +#0 type, 1 config, 2 name +#typt and config can get from https://code.google.com/p/kgtp/wiki/HOWTO#How_to_use_performance_counters +pe_list.append(["0","0", "CPU_CYCLES"]) +pe_list.append(["0","1", "INSTRUCTIONS"]) +pe_list.append(["0","2", "CACHE_REFERENCES"]) +pe_list.append(["0","3", "CACHE_MISSES"]) +pe_list.append(["0","4", "BRANCH_INSTRUCTIONS"]) +pe_list.append(["0","5", "BRANCH_MISSES"]) +pe_list.append(["0","6", "BUS_CYCLES"]) +pe_list.append(["3","0", "L1D_READ_ACCESS"]) +pe_list.append(["3","1", "L1I_READ_ACCESS"]) + +#sleep time +sleep_sec = 1 + +#0 text 1 gtk +gui_type = 1 + +in_gdb = False + + +pe_list_type = 0 +pe_list_config = 1 +pe_list_name = 2 +pe_list_prev = 3 +pe_list_qtv = 4 + +if in_gdb: + import gdb +else: + import os + + +class kgtp: + fd = -1 + retry_count = 3 + buf_max = 1024 + tvariable = {} + tvariable_next_number = 0 + + def __init__(self): + #Open fd + try: + self.fd = os.open("/sys/kernel/debug/gtp", os.O_RDWR) + except: + print "Please do not forget insmod and sudo." + exit(0) + + def __del__(self): + if self.fd >= 0: + os.close(self.fd) + + def read_fd(self): + try: + buf = os.read(self.fd, self.buf_max) + except: + return False + return buf + + def write_fd(self, msg): + try: + buf = os.write(self.fd, msg) + except: + return False + return True + + def read(self): + for i in range(0, self.retry_count): + if i != 0: + self.write_fd("-") + + buf = self.read_fd() + if buf == False: + continue + buf_len = len(buf) + if buf_len < 4: + continue + + csum = 0 + for i in range(0, buf_len - 2): + if i == 0: + if buf[i] != "$": + retry = True + break + elif buf[i] == '#': + break + else: + csum += ord(buf[i]) + if i == 0 or buf[i] != "#": + continue + if int("0x"+buf[i+1:i+3], 16) != (csum & 0xff): + continue + buf = buf[1:i] + self.write_fd("+") + + #print "KGTP read: "+buf + return buf + + print "KGTP read got error" + return False + + def write(self, msg): + for i in range(0, self.retry_count): + if i != 0: + self.write_fd("-") + + csum = 0 + for c in msg: + csum += ord(c) + msg = "$"+msg+"#"+"%02x" % (csum & 0xff) + + if self.write_fd(msg) == False: + continue + if self.read_fd() != "+": + continue + + #print "KGTP write: "+msg + return True + + print "KGTP write got error" + return False + + def simple_cmd(self, cmd): + if gtp.write(cmd) == False: + return False + if gtp.read() != "OK": + return False + return True + + def tvariable_init(self): + tvariable = {} + tvariable_next_number = 0 + + if gtp.write("qTfV") == False: + return False + ret = gtp.read() + while 1: + if ret == False: + return False + if ret == "l": + return True + ret = ret.split(":") + if len(ret) < 4: + print "KGTP GDBRSP package format error" + return False + if len(ret[3]) % 2 != 0: + print "KGTP GDBRSP package format error" + return False + + #Get name + letter = "" + name = "" + for c in ret[3]: + letter += c + if len(letter) == 2: + name += chr(int("0x"+letter, 16)) + letter = "" + + number = int("0x"+ret[0], 16) + self.tvariable[name] = number + if (number >= self.tvariable_next_number): + self.tvariable_next_number = number + 1 + + if gtp.write("qTsV") == False: + return False + ret = gtp.read() + + def tvariable_val(self, number): + return self.tvariable_val_raw("qTV:"+"%x" % number) + + def tvariable_val_raw(self, buf): + if gtp.write(buf) == False: + return + ret = gtp.read() + if ret == False: + return + if ret[0] != "V": + return + + return long("0x"+ret[1:], 16) + + def tvariable_add(self, name, val): + if self.tvariable_next_number == 0: + print "Must call tvariable_init before add tvariable" + return + + buf = "QTDV:" + "%x" % self.tvariable_next_number + ":" + "%x" % val + ":0:" + for c in name: + buf += "%02x" % ord(c) + if gtp.write(buf) == False: + return + if gtp.read() != "OK": + print "Get something wrong when add tvariable to KGTP" + return + + self.tvariable_next_number += 1 + return (self.tvariable_next_number - 1) + + def qtinit(self): + return self.simple_cmd("QTinit") + + def tstart(self): + return self.simple_cmd("QTStart") + + def tstop(self): + return self.simple_cmd("QTStop") + + +def each_entry(callback): + global pe_list, cpu_number + for i in range(0, cpu_number): + for e in pe_list: + callback(i, e) + + +def init_pe(i, e): + if (len(e) < pe_list_prev + 1): + e.append([]) + e[pe_list_prev].append(0) + if (len(e) < pe_list_qtv + 1): + e.append([]) + + if in_gdb: + gdb.execute("tvariable $pc_pe_type_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i)+"="+e[pe_list_type], True, False) + gdb.execute("tvariable $pc_pe_config_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i)+"="+e[pe_list_config], True, False) + gdb.execute("tvariable $pc_pe_val_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i)+"=0", True, False) + gdb.execute("tvariable $pc_pe_en_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i)+"=1", True, False) + else: + if gtp.tvariable_add("pc_pe_type_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i), int(e[pe_list_type])) == None: + exit(0) + if gtp.tvariable_add("pc_pe_config_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i), int(e[pe_list_config])) == None: + exit(0) + number = gtp.tvariable_add("pc_pe_val_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i), 0) + if number == None: + exit(0) + if gtp.tvariable_add("pc_pe_en_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i), 1) == None: + exit(0) + e[pe_list_qtv].append("qTV:"+"%x" % number) + +def init_kgtp(): + global cpu_number + + if in_gdb: + cpu_number = int(gdb.parse_and_eval("$cpu_number")) + #Set the empty tracepoint + gdb.execute("delete tracepoints", False, False) + gdb.execute("trace *0", True, False) + else: + cpu_number = gtp.tvariable_val(gtp.tvariable["cpu_number"]) + if cpu_number == None: + exit(0) + + #Set the pe + each_entry(init_pe) + +import signal +def sigint_handler(num, e): + if in_gdb: + gdb.execute("tstop", True, False) + else: + gtp.tstop() + exit(0) + + +if in_gdb: + #close pagination + gdb.execute("set pagination off", True, False); + #Connect to KGTP if need + if str(gdb.selected_thread()) == "None": + gdb.execute("target remote /sys/kernel/debug/gtp", True, False) +else: + gtp = kgtp() + if gtp.qtinit == False: + exit(0) + if gtp.tvariable_init() == False: + exit(0) + +#Init the status to KGTP +cpu_number = 0 +init_kgtp() +signal.signal(signal.SIGINT, sigint_handler) + + +#start +if in_gdb: + gdb.execute("tstart", True, False) +else: + gtp.tstart() + + +#text gui --------------------------------------------------------------------- +#pe_list will be set to:type, config, name, prev_value_list +if gui_type == 0: + import time + def output_pe(i, e): + if in_gdb: + current_value = long(gdb.parse_and_eval("$pc_pe_val_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i))) + else: + current_value = gtp.tvariable_val_raw(e[pe_list_qtv][i]) + if current_value == None: + print "Fail when get val from KGTP" + exit(0) + print "cpu"+str(i),e[pe_list_name],current_value-e[pe_list_prev][i] + e[pe_list_prev][i] = current_value + + while 1: + each_entry(output_pe) + print + time.sleep(sleep_sec) + + +#gtk gui ---------------------------------------------------------------------- +#pe_list will be set to:0 type, 1 config, 2 name, 3 prev_value_list, +# 4 value_list, 5 x_list, 6 button_list, +# 7 button_color_list, 8 line_color_list +if gui_type == 1: + #This script need python-gtk2 + import gtk + import glib + + pe_list_value = 5 + pe_list_x = 6 + pe_list_button = 7 + pe_list_bcolor = 8 + pe_list_lcolor = 9 + + pe_color = (0xffb0ff, 0x006000) + + class PyApp(gtk.Window): + #Init ---------------------------------------------------------- + def __init__(self): + global pe_list, cpu_number + + super(PyApp, self).__init__() + + self.max_value = 0 + self.prev_width = 0 + self.prev_height = 0 + self.y_ratio = 0 + self.entry_width = 10 + self.logfd = False + + #Set the pe + each_entry(self.pe_init_callback) + + #Set the color + num = len(pe_list) * cpu_number + block = (pe_color[0] - pe_color[1]) / float(num) + color = pe_color[1] + for i in range(0, cpu_number): + for e in pe_list: + e[pe_list_bcolor].append(gtk.gdk.Color("#"+ "%06x" % int(color))) + e[pe_list_lcolor].append((((int(color) >> 16) / float(0xff) * 1), ((int(color) >> 8 & 0xff) / float(0xff) * 1), ((int(color) & 0xff) / float(0xff) * 1))) + color += block + + #Set window + self.set_title("KGTP") + self.connect("destroy", gtk.main_quit) + gtk.Window.maximize(self) + + #menubar + mb = gtk.MenuBar() + #file + filemenu = gtk.Menu() + filem = gtk.MenuItem("File") + filem.set_submenu(filemenu) + save = gtk.CheckMenuItem("Save log to a CSV file") + save.connect("activate", self.mb_save) + save.set_active(False) + exit = gtk.MenuItem("Exit") + exit.connect("activate", gtk.main_quit) + filemenu.append(save) + filemenu.append(gtk.SeparatorMenuItem()) + filemenu.append(exit) + mb.append(filem) + #set + setmenu = gtk.Menu() + setm = gtk.MenuItem("Settings") + setm.set_submenu(setmenu) + show_buttons = gtk.CheckMenuItem("Show buttons") + show_buttons.set_active(True) + show_buttons.connect("activate", self.show_buttons) + setmenu.append(show_buttons) + mb.append(setm) + + #Widget + #Creat self.darea + self.darea = gtk.DrawingArea() + self.darea.connect("expose-event", self.expose) + self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color("#FFFFFF")) + #Creat all ToggleButton for each pe + each_entry(self.pe_gtk_creat_button) + #Creat button_hboxes + self.button_hboxes = self.pe_gtk_creat_button_hboxes_first() + + #Add mb and widget to window + self.vbox = gtk.VBox(False, 0) + self.vbox.pack_start(mb, False, False, 0) + self.vbox.pack_start(self.darea, True, True, 0) + for e in self.button_hboxes: + self.vbox.pack_start(e, False, False, 0) + self.add(self.vbox) + + #First show to get the right size + self.show_all() + size = self.pe_gtk_get_size() + + #Reset the button_hboxes + each_entry(self.pe_gtk_remove_creat_button_hboxes) + for e in self.button_hboxes: + self.vbox.remove(e) + self.button_hboxes = self.pe_gtk_creat_button_hboxes_second(size) + for e in self.button_hboxes: + self.vbox.pack_start(e, False, False, 0) + self.show_all() + + #Reset the value of each button + each_entry(self.button_reset) + + #Add timer + glib.timeout_add(int(sleep_sec * 1000), self.timer_cb) + #Remove the first entry because it already record a big value + glib.timeout_add(int(sleep_sec * 1100), self.timer_remove_first_record) + + def __del__(self): + if self.logfd: + self.logfd.close() + self.logfd = False + + def pe_init_callback(self, i, e): + if (len(e) < pe_list_value + 1): + e.append([]) + e[pe_list_value].append([]) + if (len(e) < pe_list_x + 1): + e.append([]) + e[pe_list_x].append([]) + if (len(e) < pe_list_button + 1): + e.append([]) + if (len(e) < pe_list_button + 1): + e.append([]) + if (len(e) < pe_list_bcolor + 1): + e.append([]) + if (len(e) < pe_list_lcolor + 1): + e.append([]) + + def pe_gtk_creat_button(self, i, e): + e[pe_list_button].append(gtk.ToggleButton(e[pe_list_name]+":"+str(18446744073709551615))) + self.set_button_color(e[pe_list_button][i], e[pe_list_bcolor][i]) + e[pe_list_button][i].connect("clicked", self.button_click) + + def pe_gtk_creat_button_hboxes_first(self): + global pe_list, cpu_number + + hboxes = [] + self.label_list = [] + for i in range(0, cpu_number): + hboxes.append(gtk.HBox(False, 0)) + self.label_list.append(gtk.Label("CPU"+str(i))) + hboxes[i].pack_start(self.label_list[i], False, False, 0) + for e in pe_list: + hboxes[i].pack_start(e[pe_list_button][i], False, False, 0) + + return hboxes + + def pe_gtk_get_size(self): + global pe_list, cpu_number + + #0 label size 1 button size + size = ([],[]) + for i in range(0, cpu_number): + size[0].append(self.label_list[i].allocation.width) + size[1].append([]) + for e in pe_list: + size[1][i].append(e[pe_list_button][i].allocation.width) + + return size + + def pe_gtk_remove_creat_button_hboxes(self, i, e): + self.button_hboxes[i].remove(e[pe_list_button][i]) + + def pe_gtk_creat_button_hboxes_second(self, size): + global pe_list, cpu_number + + hboxes = [] + hbox_id = -1 + for i in range(0, cpu_number): + keep_going = True + prev_entry_id = 0 + while keep_going == True: + width = self.allocation.width + keep_going = False + hbox_id += 1 + hboxes.append(gtk.HBox(False, 0)) + width -= size[0][i] + hboxes[hbox_id].pack_start(gtk.Label("CPU"+str(i)), False, False, 0) + for j in range(prev_entry_id, len(pe_list)): + if width - size[1][i][j] <= 0: + prev_entry_id = j + keep_going = True + break + width -= size[1][i][j] + 200 + hboxes[hbox_id].pack_start(pe_list[j][pe_list_button][i], False, False, 0) + + return hboxes + + def button_reset(self, i, e): + e[pe_list_button][i].set_label(e[pe_list_name]+":0") + + #Dialog ------------------------------------------------------- + def dialog_error(self, msg): + md = gtk.MessageDialog(self,gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) + md.run() + md.destroy() + + #Menubar ------------------------------------------------------- + def show_buttons(self, widget): + if widget.active: + for e in self.button_hboxes: + e.show() + else: + for e in self.button_hboxes: + e.hide() + + def log_write_name(self, i, e): + self.logfd.write("CPU"+str(i)+" "+e[pe_list_name]+",") + + def mb_save(self, widget): + if widget.active: + md = gtk.FileChooserDialog(title="Save log to a CSV file", action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons = (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK, gtk.RESPONSE_OK)) + md.set_do_overwrite_confirmation(True) + md.set_current_name("pe.csv") + if md.run() == gtk.RESPONSE_OK: + try: + self.logfd = open(md.get_filename(), "w") + each_entry(self.log_write_name) + self.logfd.write("\n") + except: + self.dialog_error("Try to open file "+md.get_filename()+" got error") + widget.set_active(False) + if self.logfd: + self.logfd.close() + self.logfd = False + else: + widget.set_active(False) + md.destroy() + else: + if self.logfd: + self.logfd.close() + self.logfd = False + + #Button -------------------------------------------------------- + def refind_max_value(self, i, e): + if e[pe_list_button][i].get_active(): + return + for i in e[pe_list_value][i]: + if i > self.max_value: + self.max_value = i + self.y_ratio = 0 + + def set_button_color(self, button, color): + style = button.get_style().copy() + style.bg[gtk.STATE_NORMAL] = color + style.bg[gtk.STATE_ACTIVE] = color + style.bg[gtk.STATE_PRELIGHT] = color + style.bg[gtk.STATE_SELECTED] = color + style.bg[gtk.STATE_INSENSITIVE] = color + button.set_style(style) + + def button_click(self, widget): + if widget.get_active(): + self.set_button_color(widget, gtk.gdk.Color("#FFFFFF")) + else: + color = False + for i in range(0, cpu_number): + for e in pe_list: + if e[pe_list_button][i] == widget: + color = e[pe_list_bcolor][i] + break + if color: + break + if color: + self.set_button_color(widget, color) + each_entry(self.refind_max_value) + self.darea.queue_draw() + + #Timer --------------------------------------------------------- + def write_csv(self, msg): + try: + self.logfd.write(msg) + except: + self.dialog_error("Writ CSV file got error") + widget.set_active(False) + self.logfd.close() + self.logfd = False + + def pe_gtk_add(self, i, e): + if in_gdb: + current_value = long(gdb.parse_and_eval("$pc_pe_val_"+e[pe_list_type]+e[pe_list_config]+"_"+str(i))) + else: + current_value = gtp.tvariable_val_raw(e[pe_list_qtv][i]) + if current_value == None: + print "Fail when get val from KGTP" + exit(0) + this_value = current_value-e[pe_list_prev][i] + e[pe_list_value][i].append(this_value) + if this_value > self.max_value and not e[pe_list_button][i].get_active(): + self.max_value = this_value + self.y_ratio = 0 + e[pe_list_x][i].append(-1) + e[pe_list_prev][i] = current_value + e[pe_list_button][i].set_label(e[pe_list_name]+":"+str(this_value)) + if self.logfd: + write_csv(str(this_value)+",") + + def timer_cb(self): + each_entry(self.pe_gtk_add) + if self.logfd: + write_csv("\n") + self.darea.queue_draw() + return True + + def timer_remove_first_record(self): + if len(pe_list[0][pe_list_value][0]) >= 1: + self.pe_remove_entry_num = 1 + each_entry(self.pe_remove_entry) + return False + else: + return True + + #DrawingArea --------------------------------------------------- + def pe_gtk_line(self, i, e): + if len(e[pe_list_value][i]) < 2: + return + if e[pe_list_button][i].get_active(): + return + + self.cr.set_source_rgb(e[pe_list_lcolor][i][0], e[pe_list_lcolor][i][1], e[pe_list_lcolor][i][2]) + x = 0 + for num in range(0, len(e[pe_list_value][i])): + if e[pe_list_value][i][num] > self.line_max: + self.line_max = e[pe_list_value][i][num] + if self.height_change or e[pe_list_x][i][num] < 0: + e[pe_list_x][i][num] = self.prev_height - e[pe_list_value][i][num] * self.y_ratio + if num == 0: + self.cr.move_to(x, e[pe_list_x][i][num]) + else: + self.cr.line_to(x, e[pe_list_x][i][num]) + x += self.entry_width + self.cr.stroke() + + def pe_remove_entry(self, i, e): + del(e[pe_list_value][i][0:self.pe_remove_entry_num]) + del(e[pe_list_x][i][0:self.pe_remove_entry_num]) + + def expose(self, widget, event): + self.cr = widget.window.cairo_create() + + #y + if self.prev_height != self.darea.allocation.height: + self.height_change = True + self.prev_height = self.darea.allocation.height + else: + self.height_change = False + if self.max_value > 0 and (self.height_change or self.y_ratio == 0): + self.max_value += 100 - self.max_value % 100 + self.y_ratio = float(self.prev_height)/self.max_value + self.height_change = True + + #x + x_size = len(pe_list[0][pe_list_value][0]) + entry_number = 0 + if self.entry_width * x_size > self.darea.allocation.width: + entry_number = self.darea.allocation.width // self.entry_width + self.pe_remove_entry_num = x_size - entry_number + each_entry(self.pe_remove_entry) + + #dash + self.cr.set_source_rgb(0, 0, 0) + self.cr.set_dash((1, 5)) + #dash line for x + if entry_number == 0: + entry_number = self.darea.allocation.width // self.entry_width + x = 0 + while x < self.darea.allocation.width: + x += self.entry_width * 10 + self.cr.move_to(x, 0) + self.cr.line_to(x, self.prev_height) + #dash line for y + self.cr.move_to(0, 10) + self.cr.show_text(str(self.max_value)) + + self.cr.move_to(0, self.darea.allocation.height/4*3) + self.cr.show_text(str(self.max_value/4*3)) + self.cr.line_to(self.darea.allocation.width, self.darea.allocation.height/4*3) + + self.cr.move_to(0, self.darea.allocation.height/2) + self.cr.show_text(str(self.max_value/2)) + self.cr.line_to(self.darea.allocation.width, self.darea.allocation.height/2) + + self.cr.move_to(0, self.darea.allocation.height/4) + self.cr.show_text(str(self.max_value/4)) + self.cr.line_to(self.darea.allocation.width, self.darea.allocation.height/4) + + self.cr.stroke() + self.cr.set_dash(()) + + self.line_max = 0 + each_entry(self.pe_gtk_line) + if self.line_max > 0 and self.line_max * 2 < self.max_value: + self.max_value = self.line_max + self.y_ratio = 0 + + self.height_change = False + + PyApp() + gtk.main() + if in_gdb: + gdb.execute("tstop", True, False) + else: + gtp.tstop() + exit(0) --- /dev/null +++ b/scripts/gtp/getgtprsp.pl @@ -0,0 +1,141 @@ +#!/usr/bin/perl + +# This script to get the GDB tracepoint RSP package and save it +# to ./gtpstart and ./gtpstop file. +# GPL +# Copyright(C) Hui Zhu (teawater@gmail.com), 2010, 2011 + +binmode STDIN, ":raw"; +$| = 1; + +$status = 0; +$circular = 0; +$var_count = 0; + +while (1) { + sysread STDIN, $c, 1 or next; + if ($c eq '') { + next; + } elsif ($c eq '+' || $c eq '-') { + $c = ''; + } + + sysread STDIN, $line, 1024 or next; + print '+'; + $line = $c.$line; + + open(LOG, ">>./log"); + print LOG $line."\n"; + close (LOG); + + if ($status == 0) { + if ($line eq '$?#3f') { + print '$S05#b8'; + } elsif ($line eq '$g#67') { + print '$00000000#80'; + } elsif ($line eq '$k#6b') { + exit; + } elsif ($line =~ /^\$m/ || $line =~ /^\$p/) { + print '$00000000#80'; + } elsif ($line eq '$qTStatus#49') { + print '$T0;tnotrun:0;tframes:0;tcreated:0;tsize:'; + print '500000;tfree:500000;circular:0;disconn:0#d1'; + } elsif ($line eq '$QTBuffer:circular:1#f9') { + print '$OK#9a'; + $circular = 1; + } elsif ($line eq '$QTBuffer:circular:0#f8') { + print '$OK#9a'; + $circular = 0; + } elsif ($line eq '$QTStop#4b') { + print '$OK#9a'; + } elsif ($line =~ /^\$qSupported/) { + print '$ConditionalTracepoints+;TracepointSource+#1b'; + } elsif ($line eq '$QTinit#59') { + $status = 1; + open(STARTFILE, ">./gtpstart"); + print STARTFILE '$QTDisconnected:1#e3'."\n"; + if ($circular) { + print STARTFILE '$QTBuffer:circular:1#f9'."\n"; + } else { + print STARTFILE '$QTBuffer:circular:0#f8'."\n"; + } + } elsif ($line eq '$qTfV#81') { + print '$18:0:1:6972715f636f756e74#ca'; + } elsif ($line eq '$qTsV#8e') { + if ($var_count == 0) { + print '$17:0:1:736f66746972715f636f756e74#a6'; + } elsif ($var_count == 1) { + print '$16:0:1:686172646972715f636f756e74#70'; + } elsif ($var_count == 2) { + print '$15:0:1:6c6173745f6572726e6f#59'; + } elsif ($var_count == 3) { + print '$14:0:1:69676e6f72655f6572726f72#38'; + } elsif ($var_count == 4) { + print '$13:0:1:7874696d655f6e736563#35'; + } elsif ($var_count == 5) { + print '$12:0:1:7874696d655f736563#99'; + } elsif ($var_count == 6) { + print '$11:0:1:6b726574#48'; + } elsif ($var_count == 7) { + print '$10:0:1:70635f70655f656e#4e'; + } elsif ($var_count == 8) { + print '$f:0:1:6370755f6e756d626572#29'; + } elsif ($var_count == 9) { + print '$e:0:1:6e6f5f73656c665f7472616365#ca'; + } elsif ($var_count == 10) { + print '$d:0:1:64756d705f737461636b#22'; + } elsif ($var_count == 11) { + print '$c:0:1:7072696e746b5f666f726d6174#c7'; + } elsif ($var_count == 12) { + print '$b:8:1:7072696e746b5f6c6576656c#66'; + } elsif ($var_count == 13) { + print '$a:0:1:7072696e746b5f746d70#54'; + } elsif ($var_count == 14) { + print '$9:0:1:646973636172645f706167655f6e756d#ab'; + } elsif ($var_count == 15) { + print '$8:0:1:636f6f6b65645f7264747363#01'; + } elsif ($var_count == 16) { + print '$7:0:1:7264747363#57'; + } elsif ($var_count == 17) { + print '$6:0:1:636f6f6b65645f636c6f636b#8d'; + } elsif ($var_count == 18) { + print '$5:0:1:636c6f636b#e3'; + } elsif ($var_count == 19) { + print '$4:0:1:63757272656e745f7468726561645f696e666f#21'; + } elsif ($var_count == 20) { + print '$3:0:1:63757272656e745f7461736b#c9'; + } elsif ($var_count == 21) { + print '$2:0:1:6370755f6964#f1'; + } elsif ($var_count == 22) { + print '$1:0:1:6774705f76657273696f6e#6b'; + } elsif ($var_count == 23) { + print '$19:0:1:706970655f7472616365#cb'; + } elsif ($var_count == 24) { + print '$1a:0:1:63757272656e745f7461736b5f706964#03'; + } elsif ($var_count == 25) { + print '$1b:200:1:6274#d7'; + } else { + print '$l#6c'; + } + $var_count++; + } else { + print '$#00'; + } + } + + if ($status == 1) { + print '$OK#9a'; + + print STARTFILE $line."\n"; + + if ($line eq '$QTStart#b3') { + $status = 0; + + close(STARTFILE); + + open(STOPFILE, ">./gtpstop"); + print STOPFILE '$QTStop#4b'."\n"; + close(STOPFILE); + } + } +} --- /dev/null +++ b/scripts/gtp/getmod.py @@ -0,0 +1,148 @@ +#!/usr/bin/python + +# This script is used by GDB to load the symbols from Linux kernel modules +# GPL +# Copyright(C) KGTP team (https://code.google.com/p/kgtp/), 2011, 2012 + +#Set special mod_search_dir +#set $mod_search_dir="dir" +#Clear special mod_search_dir +#set $mod_search_dir=(void)1 +#Not ignore gtp.ko +#set $ignore_gtp_ko=0 + +import gdb +import os + +def get_pagination(): + buf = gdb.execute("show pagination", False, True) + begin = buf.find("State of pagination is ") + len("State of pagination is ") + if begin < 0: + raise NotImplementedError("Cannot get pagination") + buf = buf[begin:] + end = buf.rfind(".") + buf = buf[:end] + + return buf + +pagination = get_pagination() +gdb.execute("set pagination off", False, False) + +def format_file(name): + tmp = "" + for c in name: + if c == "_": + c = "-" + tmp += c + return tmp + +#Check if the target is available +if str(gdb.selected_thread()) == "None": + raise gdb.error("Please connect to Linux Kernel before use the script.") + +#Output the help +print "Use GDB command \"set $mod_search_dir=dir\" to set an directory for search the modules." + +ignore_gtp_ko = gdb.parse_and_eval("$ignore_gtp_ko") +if ignore_gtp_ko.type.code == gdb.TYPE_CODE_INT: + ignore_gtp_ko = int(ignore_gtp_ko) +else: + ignore_gtp_ko = 1 + +#Get the mod_search_dir +mod_search_dir_list = [] +#Get dir from $mod_search_dir +tmp_dir = gdb.parse_and_eval("$mod_search_dir") +if tmp_dir.type.code == gdb.TYPE_CODE_ARRAY: + tmp_dir = str(tmp_dir) + tmp_dir = tmp_dir[1:len(tmp_dir)] + tmp_dir = tmp_dir[0:tmp_dir.index("\"")] + mod_search_dir_list.append(tmp_dir) +#Get dir that same with current vmlinux +tmp_dir = str(gdb.execute("info files", False, True)) +tmp_dir = tmp_dir[tmp_dir.index("Symbols from \"")+len("Symbols from \""):len(tmp_dir)] +tmp_dir = tmp_dir[0:tmp_dir.index("\"")] +tmp_dir = tmp_dir[0:tmp_dir.rindex("/")] +mod_search_dir_list.append(tmp_dir) +#Get the dir of current Kernel +tmp_dir = "/lib/modules/" + str(os.uname()[2]) +if os.path.isdir(tmp_dir): + mod_search_dir_list.append(tmp_dir) +#Let user choice dir +mod_search_dir = "" +while mod_search_dir == "": + for i in range(0, len(mod_search_dir_list)): + print str(i)+". "+mod_search_dir_list[i] + try: + s = input('Select a directory for search the modules [0]:') + except SyntaxError: + s = 0 + except: + continue + if s < 0 or s >= len(mod_search_dir_list): + continue + mod_search_dir = mod_search_dir_list[s] + +mod_list_offset = long(gdb.parse_and_eval("((size_t) &(((struct module *)0)->list))")) +mod_list = long(gdb.parse_and_eval("(&modules)")) +mod_list_current = mod_list + +while 1: + mod_list_current = long(gdb.parse_and_eval("((struct list_head *) "+str(mod_list_current)+")->next")) + + #check if need break the loop + if mod_list == mod_list_current: + break + + mod = mod_list_current - mod_list_offset + + #get mod_name + mod_name = str(gdb.parse_and_eval("((struct module *)"+str(mod)+")->name")) + mod_name = mod_name[mod_name.index("\"")+1:len(mod_name)] + mod_name = mod_name[0:mod_name.index("\"")] + mod_name += ".ko" + mod_name = format_file(mod_name) + + #get mod_dir_name + mod_dir_name = "" + for root, dirs, files in os.walk(mod_search_dir): + for afile in files: + tmp_file = format_file(afile) + if tmp_file == mod_name: + mod_dir_name = os.path.join(root,afile) + break + if mod_dir_name != "": + break + + command = " " + + #Add module_core to command + command += str(gdb.parse_and_eval("((struct module *)"+str(mod)+")->module_core")) + + #Add each sect_attrs->attrs to command + #get nsections + nsections = int(gdb.parse_and_eval("((struct module *)"+str(mod)+")->sect_attrs->nsections")) + sect_attrs = long(gdb.parse_and_eval("(u64)((struct module *)"+str(mod)+")->sect_attrs")) + for i in range(0, nsections): + command += " -s" + tmp = str(gdb.parse_and_eval("((struct module_sect_attrs *)"+str(sect_attrs)+")->attrs["+str(i)+"].name")) + tmp = tmp[tmp.index("\"")+1:len(tmp)] + tmp = tmp[0:tmp.index("\"")] + command += " "+tmp + tmp = str(gdb.parse_and_eval("((struct module_sect_attrs *)"+str(sect_attrs)+")->attrs["+str(i)+"].address")) + command += " "+tmp + + if mod_dir_name == "": + print "Cannot find out",mod_name,"from directory." + print "Please use following command load the symbols from it:" + print "add-symbol-file some_dir/"+mod_name+command + else: + if ignore_gtp_ko and mod_name == "gtp.ko": + print "gtp.ko is ignored. You can use command \"set $ignore_gtp_ko=0\" to close this ignore." + print "Or you can use following command load the symbols from it:" + print "add-symbol-file "+mod_dir_name+command + else: + #print "add-symbol-file "+mod_dir_name+command + gdb.execute("add-symbol-file "+mod_dir_name+command, False, False) + +gdb.execute("set pagination " + pagination, False, False)
| |