| 1 | # Copyright (c) 2013 Adrian Negreanu <groleo@gmail.com> |
| 2 | |
| 3 | # This program is free software; you can redistribute it and/or modify |
| 4 | # it under the terms of the GNU General Public License as published by |
| 5 | # the Free Software Foundation; either version 3 of the License, or |
| 6 | # (at your option) any later version. |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | # GNU General Public License for more details. |
| 12 | # |
| 13 | # You should have received a copy of the GNU General Public License |
| 14 | # along with this program. If not, see <http://www.gnu.org/licenses/> |
| 15 | |
| 16 | import os |
| 17 | import re |
| 18 | import subprocess |
| 19 | |
| 20 | class LoadSymFiles(gdb.Command): |
| 21 | """Add symbol files for files in /proc/pid/maps: load-sym-file [symbols-directory] [lib-directory]""" |
| 22 | """Usage example: |
| 23 | start # breakpoint 1 |
| 24 | set confirm off |
| 25 | b dlfcn.c:56 # breakpoint 2, android_dlopen |
| 26 | commands 2 # commands to run when breakpoint 2 is hit |
| 27 | source ../utils/load_sym_files.py |
| 28 | load-sym-files |
| 29 | continue |
| 30 | end # end of commands for bkpt 2 |
| 31 | """ |
| 32 | def __init__(self): |
| 33 | gdb.Command.__init__(self, "load-sym-files", gdb.COMMAND_FILES, gdb.COMPLETE_FILENAME, True) |
| 34 | |
| 35 | def invoke(self, arg, from_tty): |
| 36 | arg_list = gdb.string_to_argv(arg) |
| 37 | symdir = "/system/symbols" |
| 38 | libdir = "/system/lib" |
| 39 | |
| 40 | if len(arg_list) == 1: |
| 41 | symdir = arg_list[0] |
| 42 | if not os.path.isdir(symdir): |
| 43 | print "error: invalid symbol directory(%s)"%symdir |
| 44 | print "usage: load-sym-files [symbols-dir] [lib-dir]" |
| 45 | return |
| 46 | |
| 47 | if len(arg_list) == 2: |
| 48 | libdir = arg_list[1] |
| 49 | if not os.path.isdir(libdir): |
| 50 | print "error: invalid library directory(%s)"%libdir |
| 51 | print "usage: load-sym-files [symbols-dir] [lib-dir]" |
| 52 | return |
| 53 | try: |
| 54 | pid = gdb.selected_inferior().pid |
| 55 | except AttributeError: |
| 56 | # in case gdb-version < 7.4 |
| 57 | # the array can have more than one element, |
| 58 | # but it's good enough when debugging test_egl |
| 59 | if len(gdb.inferiors()) == 1: |
| 60 | pid = gdb.inferiors()[0].pid |
| 61 | else: |
| 62 | print "error: no gdb support for more than 1 inferior" |
| 63 | return |
| 64 | |
| 65 | if pid == 0: |
| 66 | print "error: debugee not started yet" |
| 67 | return |
| 68 | |
| 69 | maps = open("/proc/%d/maps"%pid,"rb") |
| 70 | for line in maps: |
| 71 | # b7fc9000-b7fcf000 r-xp 00000000 08:01 1311443 /system/lib/liblog.so |
| 72 | m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\s+r-xp.*(%s.*)"%libdir,line) |
| 73 | if not m: |
| 74 | continue |
| 75 | |
| 76 | start_addr = int(m.group(1),16) |
| 77 | lib = m.group(2) |
| 78 | text_addr = 0 |
| 79 | |
| 80 | p = subprocess.Popen("objdump -h "+lib , shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
| 81 | for header in p.stdout.read().split("\n"): |
| 82 | #6 .text 00044ef7 00017f80 00017f80 00017f80 2**4 |
| 83 | t = re.match("\s*[0-9]+\s+\.text\s+([0-9A-Fa-f]+\s+){3}([0-9A-Fa-f]+)",header) |
| 84 | if t: |
| 85 | text_addr = int(t.group(2),16) |
| 86 | break |
| 87 | symfile = symdir + lib |
| 88 | if os.path.isfile(symfile): |
| 89 | gdb.execute("add-symbol-file %s 0x%X" % (symfile, start_addr+text_addr)) |
| 90 | |
| 91 | |
| 92 | LoadSymFiles() |