Normally, you invoke objdump with the name of the problematic driver, and then parse the output based on the information printed in the call trace of the kernel oops. Here is a nice example.
Among many hexadecimal numbers and function names that are printed in the call trace of the kernel oops, the most important piece of information is the function name and the offset: for example:
vnic_login_create_2+0xd1
I wrote this script that receives the function name and offset as a pointer, and prints the source file name and line number that caused the oops.
For example:
# objdump_parser.py vnic_login_create_2+0xd1 drivers/net/mlx4_vnic/mlx4_vnic.ko
vnic_login_create_2+0xd1 = 0x6e3 => drivers/net/mlx4_vnic/vnic_data_main.c:210
########################## objdump_parser.py ##########################
#!/usr/bin/env python
# -*- python -*-
# Author: Ali Ayoub
import os
import sys
import time
SNAME = os.path.basename(sys.argv[0])
USAGE = "%s
EXAMPLE = "%s %s %s" % (SNAME, "fip_vnic_login_create_1+0x4a", "mlx4_vnic.o")
# print functions
debug = "--debug" in sys.argv
if debug:
sys.argv.remove("--debug")
def vprint(msg):
if debug:
print "-V- %s" % msg
def eprint(msg):
print "-E- %s" % msg
def iprint(msg):
print "-I- %s" % msg
def main():
if len(sys.argv[1:]) != 2:
eprint("Bad Args")
iprint("USAGE: %s" % USAGE)
iprint("EXAMPLE: %s" % EXAMPLE)
return 1
trace = sys.argv[1]
trace_func = trace.split('+')[0]
trace_off = trace.split('+')[1]
mod = sys.argv[2]
objdump_f = "/tmp/%s.%s" % (os.path.basename(mod), time.time())
if (os.system("objdump -Sld %s > %s" % (mod, objdump_f))):
eprint("objdump failed")
return 1
vprint("objdump output %s" % objdump_f)
objdump_fd = open(objdump_f)
objdump_lines = objdump_fd.readlines()
objdump_fd.seek(0)
objdump_out = objdump_fd.read()
addr = 0
index = 0
addr_index = 0
token = "<%s>:" % trace_func
vprint("looking for %s in %s" % (token, objdump_f))
for line in objdump_lines:
index = index + 1
if not line.count(token):
continue
addr_index = index
vprint("found func %s at line %s (%s+%s)" % (trace_func, line.strip(), objdump_f, addr_index))
_addr = line.split()[0]
addr = hex(int(_addr, 16) + int(trace_off, 16))
break
if addr == 0:
eprint("couldn't find func %s" % trace_func)
return 1
vprint("%s -> %s" % (trace, addr))
# look for assembly line
found_line_index = 0
for i in range(int(addr, 16) + 4, int(addr, 16) - 16, -1):
token = "%s:" % hex(i)
token = token.replace("0x", '')
vprint("looking for hex add %s" % token)
index = 0
for line in objdump_lines:
index = index + 1
if line.strip().startswith(token):
found_line_index = index
break
if found_line_index:
break
if not found_line_index:
eprint("couldn't find found_line_index: %s" % found_line_index)
return 2
# print result
found_start_index = addr_index - 1
code_line=0
for i in range(found_start_index, found_line_index):
#print objdump_lines[i].strip()
if objdump_lines[i].strip().count(".c:") or objdump_lines[i].strip().count(".h:"):
code_line = i
if code_line:
print ("%s = %s => %s" % (trace, addr, objdump_lines[code_line].strip()))
# cleanup
objdump_fd.close()
os.remove(objdump_f)
return 0
if __name__ == '__main__':
try:
rc = main()
except Exception, e:
print "-E- Exception %s" % str(e)
print "-E- Abort."
sys.exit(rc)



