1133123Sjmg#!/usr/local/bin/python 2133123Sjmg# 3133123Sjmg# Copyright 2004 John-Mark Gurney 4133123Sjmg# All rights reserved. 5133123Sjmg# 6133123Sjmg# Redistribution and use in source and binary forms, with or without 7133123Sjmg# modification, are permitted provided that the following conditions 8133123Sjmg# are met: 9133123Sjmg# 1. Redistributions of source code must retain the above copyright 10133123Sjmg# notice, this list of conditions and the following disclaimer. 11133123Sjmg# 2. Redistributions in binary form must reproduce the above copyright 12133123Sjmg# notice, this list of conditions and the following disclaimer in the 13133123Sjmg# documentation and/or other materials provided with the distribution. 14133123Sjmg# 15133123Sjmg# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16133123Sjmg# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17133123Sjmg# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18133123Sjmg# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19133123Sjmg# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20133123Sjmg# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21133123Sjmg# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22133123Sjmg# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23133123Sjmg# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24133123Sjmg# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25133123Sjmg# SUCH DAMAGE. 26133123Sjmg# 27133123Sjmg# $FreeBSD$ 28133123Sjmg 29133123Sjmgimport sys 30133123Sjmgimport os 31133123Sjmgimport popen2 32133123Sjmgimport re 33133123Sjmg 34143864Sjmggdb_cmd = 'kgdb %(p)s/kernel.debug %(core)s | tee /tmp/gdb.log' 35133123Sjmg#GDB regex 36133123Sjmgfilenamere = re.compile(r'filename\s+=\s+0x[0-9a-f]+\s("(?P<fn>[^"]+)"|(?P<error><[^>]*>))', re.M) 37133123Sjmgaddressre = re.compile(r'address\s+=\s+(?P<ad>0x[0-9a-f]+)', re.M) 38133123Sjmgnextre = re.compile(r'tqe_next\s+=\s+(?P<ad>0x[0-9a-f]+)', re.M) 39133123Sjmgprintre = re.compile(r'\$\d+\s+=\s+') 40133123Sjmg 41133123Sjmg#Paths to search for ko's/debugs 42133123Sjmgkld_debug_paths = [] 43133123Sjmg 44133123Sjmgif len(sys.argv[1:]) < 2: 45133123Sjmg print 'Usage: prog <kerncomp> <core> [<paths>]' 46133123Sjmg sys.exit(1) 47133123Sjmg 48133123Sjmg#Get the base modules path 49133123Sjmgpfs = sys.argv[1].split('/') 50133123Sjmgtry: 51133123Sjmg i = 0 52133123Sjmg while 1: 53133123Sjmg i = i + pfs[i:].index('sys') + 1 54133123Sjmgexcept: 55133123Sjmg pass 56133123Sjmg 57133123Sjmgif i == -1: 58133123Sjmg sys.stderr.write("No sys dir in kernel source path: %s\n" % sys.argv[1]) 59133123Sjmg sys.exit(0) 60133123Sjmg 61133123Sjmgkld_debug_paths.append('/'.join(pfs[:i] + ['modules'])) 62133123Sjmgkld_debug_paths.append(sys.argv[1]) 63133123Sjmg#kld_debug_paths.append(sys.argv[3:]) 64143864Sjmggdb_cmd = gdb_cmd % {'p': sys.argv[1], 'core': sys.argv[2] } 65133123Sjmg 66133123Sjmg#Start gdb 67133123Sjmggdb = popen2.popen4(gdb_cmd) 68133123Sjmg 69133123Sjmgdef searchfor(inp, re, j = 0, l = None): 70133123Sjmg """searchfor(inp, re, j, l): Searches for regex re in inp. It will 71228975Suqsautomatically add more lines. If j is set, the lines will be joined together. 72133123Sjmgl can provide a starting line to help search against. Return value is a 73228975Suqstuple of the last line, and the match if any.""" 74133123Sjmg ret = None 75133123Sjmg if not l: 76133123Sjmg l = inp.readline() 77133123Sjmg ret = re.search(l) 78133123Sjmg while l and not ret: 79133123Sjmg if j: 80133123Sjmg l += inp.readline() 81133123Sjmg else: 82133123Sjmg l = inp.readline() 83133123Sjmg ret = re.search(l) 84133123Sjmg 85133123Sjmg return (l, ret) 86133123Sjmg 87133123Sjmgdef get_addresses(inp, out): 88133123Sjmg """get_addresses(inp, out): It will search for addresses from gdb. 89133123Sjmginp and out, are the gdb input and output respectively. Return value is 90228975Suqsa list of tuples. The tuples contain the filename and the address the 91133123Sjmgfilename was loaded.""" 92133123Sjmg addr = [] 93133123Sjmg nxad = 1 94133123Sjmg while nxad: 95133123Sjmg if nxad == 1: 96133123Sjmg out.write("print linker_files.tqh_first[0]\n") 97133123Sjmg else: 98133123Sjmg out.write("print *(struct linker_file *)%d\n" % nxad) 99133123Sjmg out.flush() 100133123Sjmg l = searchfor(inp, printre)[0] 101133123Sjmg l, fn = searchfor(inp, filenamere, 1, l) 102133123Sjmg if not fn.group('fn'): 103133123Sjmg sys.stderr.write("got error: %s\n" % fn.group('error')) 104133123Sjmg nxad = 0 105133123Sjmg else: 106133123Sjmg l, ad = searchfor(inp, addressre, 1, l) 107133123Sjmg l, nx = searchfor(inp, nextre, 1, l) 108133123Sjmg addr.append((fn.group('fn'), long(ad.group('ad'), 16))) 109133123Sjmg nxad = long(nx.group('ad'), 16) 110133123Sjmg 111133123Sjmg return addr 112133123Sjmg 113133123Sjmg#Get the addresses 114133123Sjmgaddr = get_addresses(gdb[0], gdb[1]) 115133123Sjmg 116133123Sjmg#Pass through the resulting addresses, skipping the kernel. 117133123Sjmgfor i in addr[1:]: 118133123Sjmg for j in kld_debug_paths: 119133123Sjmg #Try .debug first. 120133123Sjmg p = popen2.popen4('find %s -type f -name "%s.debug"' % (j, i[0]))[0].read().strip() 121133123Sjmg if p: 122133123Sjmg break 123133123Sjmg #Try just .ko if .debug wasn't found. 124133123Sjmg p = popen2.popen4('find %s -type f -name "%s"' % (j, i[0]))[0].read().strip() 125133123Sjmg if p: 126133123Sjmg break 127133123Sjmg 128133123Sjmg if not p: 129133123Sjmg #Tell our user that we couldn't find it. 130133123Sjmg a = i[1] 131133123Sjmg sys.stderr.write("Can't find module: %s (addr: %d + header)\n" % (i[0], a)) 132133123Sjmg print '#add-symbol-file <file>', a, '#add header' 133133123Sjmg continue 134133123Sjmg 135133123Sjmg #j = popen2.popen4('objdump --section-headers /boot/kernel/%s | grep "\.text"' % i[0])[0].read().strip().split() 136133123Sjmg #Output the necessary information 137133123Sjmg j = popen2.popen4('objdump --section-headers "%s" | grep "\.text"' % p)[0].read().strip().split() 138133123Sjmg try: 139133123Sjmg a = int(j[5], 16) 140133123Sjmg print 'add-symbol-file', p, i[1] + a 141133123Sjmg except IndexError: 142133123Sjmg sys.stderr.write('Bad file: %s, address: %d\n' % (i[0], i[1])) 143