Exemplo n.º 1
0
    def invoke(self, *args):
        self.process.set_inferior(gdb.selected_inferior(), gdb.selected_thread())

        selected_thread = gdb.selected_thread()
        if selected_thread is None:
            raise Exception("You are calling the 'NotifySyscall' function with no thread running. This should never happen because only the catchpoint-syscall should call this function and by definition those require an running thread.")

        my_id = (gdb.selected_inferior().num, selected_thread.num)
        syscall_tracer = self._syscall_tracer_by_invokation_id.get(my_id) 

        am_at_syscall_enter = syscall_tracer is None  # if None no tracing was started so we must be at the enter of a syscall

        if am_at_syscall_enter:
            syscall_tracer = PtraceSyscallPublisher(self.gdb_module, self.process, Opts())
            self._syscall_tracer_by_invokation_id[my_id] = syscall_tracer # save this tracer to be called at the syscall's exit
            syscall_tracer.enter()

        else:
            syscall_tracer = self._syscall_tracer_by_invokation_id[my_id]  # created at the syscall's enter
            syscall_tracer.exit()

            del self._syscall_tracer_by_invokation_id[my_id] # clean up

        # publish the data from the syscall's enter/exit 
        syscall_tracer.publish_syscall()

        return False
Exemplo n.º 2
0
def is_running():
    """Return True if the inferior is running."""
    # This seems good enough for now.
    # We can deal with scheduler locking and the rest later.
    if gdb.selected_thread() and gdb.selected_thread().is_running():
        return True
    return False
Exemplo n.º 3
0
def gdb_stopped():
    try:
        th = gdb.selected_thread()
        if th == None:
            return True
        return gdb.selected_thread().is_stopped()
    except:
        return True
Exemplo n.º 4
0
def get_thread_names():
    # thread_regex = re.compile("(\d+)\s+Thread\s+0x[0-9a-f]+\s+\(LWP (\d+)\)")
    thread_regex = re.compile("(\d+)\s+Thread\s\d+\.(\d+)\s0x[0-9a-f].*")
    # Capture the result of 'info threads' to a string
    thread_info = gdb.execute("info threads", False, True)

    # Store the currently-selected thread so that we can go back to it
    original_thread = gdb.selected_thread()

    if original_thread is not None:
        original_thread_num = original_thread.num
    else:
        original_thread_num = None

    for line in thread_info.split('\n'):
        line = line.strip()

        thread_match = thread_regex.search(line)

        if thread_match != None:
            thread_number = int(thread_match.group(1))
            thread_tid = int(thread_match.group(2))

            # Get a pointer to the current thread from GDB
            gdb.execute("thread %d" % (thread_number), False, True)
            current_thread = gdb.selected_thread()

            # Read this thread's stat file in /proc
            thread_stat_file = "/proc/%d/stat" % (thread_tid)

            if os.path.exists(thread_stat_file):
                with open(thread_stat_file, 'r') as fp:
                    stat_file_contents = fp.read()

                # Extract the thread's name from the stat file (it should be in
                # parens, after the thread ID itself)
                stat_file_regex = re.compile("^%d \((.*?)\)" % (thread_tid))

                stat_match = stat_file_regex.search(stat_file_contents)

                if stat_match is not None:
                    # Set the thread's name to the string extracted from stat
                    thread_name = stat_match.group(1)

                    print "Got thread name '%s' for thread %d (%d)" % (
                        thread_name, thread_number, thread_tid)
                    current_thread.name = thread_name

                else:
                    print "No thread name match for thread %d (%d)" % (
                        thread_number, thread_tid)

    # Switch back to original thread (if any)
    if original_thread_num != None:
        gdb.execute("thread %d" % (original_thread_num), False, True)
Exemplo n.º 5
0
def get_thread_names():
    # thread_regex = re.compile("(\d+)\s+Thread\s+0x[0-9a-f]+\s+\(LWP (\d+)\)")
    thread_regex = re.compile("(\d+)\s+Thread\s\d+\.(\d+)\s0x[0-9a-f].*")
    # Capture the result of 'info threads' to a string
    thread_info = gdb.execute("info threads", False, True)

    # Store the currently-selected thread so that we can go back to it
    original_thread = gdb.selected_thread()

    if original_thread is not None:
        original_thread_num = original_thread.num
    else:
        original_thread_num = None

    for line in thread_info.split('\n'):
        line = line.strip()

        thread_match = thread_regex.search(line)

        if thread_match != None:
            thread_number = int(thread_match.group(1))
            thread_tid = int(thread_match.group(2))

            # Get a pointer to the current thread from GDB
            gdb.execute("thread %d" % (thread_number), False, True)
            current_thread = gdb.selected_thread()

            # Read this thread's stat file in /proc
            thread_stat_file = "/proc/%d/stat" % (thread_tid)

            if os.path.exists(thread_stat_file):
                with open(thread_stat_file, 'r') as fp:
                    stat_file_contents = fp.read()

                # Extract the thread's name from the stat file (it should be in
                # parens, after the thread ID itself)
                stat_file_regex = re.compile("^%d \((.*?)\)" % (thread_tid))

                stat_match = stat_file_regex.search(stat_file_contents)

                if stat_match is not None:
                    # Set the thread's name to the string extracted from stat
                    thread_name = stat_match.group(1)

                    print "Got thread name '%s' for thread %d (%d)" % (
                        thread_name, thread_number, thread_tid)
                    current_thread.name = thread_name

                else:
                    print "No thread name match for thread %d (%d)" % (
                        thread_number, thread_tid)

    # Switch back to original thread (if any)
    if original_thread_num != None:
        gdb.execute("thread %d" % (original_thread_num), False, True)
Exemplo n.º 6
0
def get_current_thread(inferior_repository, inferior_factory, thread_factory):
    if gdb.selected_thread() is not None:
        thread_num = gdb.selected_thread().num

        inferior = get_current_inferior(inferior_repository, inferior_factory)
        if not inferior.has_thread(thread_num):
            thread_factory.create_thread(inferior, thread_num)

        if inferior.has_thread(thread_num):
            return inferior.thread(thread_num)

    return None
Exemplo n.º 7
0
Arquivo: cpus.py Projeto: avagin/linux
def get_current_cpu():
    if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
        return gdb.selected_thread().num - 1
    elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
        tid = gdb.selected_thread().ptid[2]
        if tid > (0x100000000 - MAX_CPUS - 2):
            return 0x100000000 - tid - 2
        else:
            return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
    else:
        raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
                           "supported with this gdb server.")
Exemplo n.º 8
0
def get_current_cpu():
    if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
        return gdb.selected_thread().num - 1
    elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
        tid = gdb.selected_thread().ptid[2]
        if tid > (0x100000000 - MAX_CPUS - 2):
            return 0x100000000 - tid - 2
        else:
            return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
    else:
        raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
                           "supported with this gdb server.")
Exemplo n.º 9
0
def get_current_thread(inferior_repository, inferior_factory,
                       thread_factory):
    if gdb.selected_thread() is not None:
        thread_num = gdb.selected_thread().num

        inferior = get_current_inferior(inferior_repository, inferior_factory)
        if not inferior.has_thread(thread_num):
            thread_factory.create_thread(inferior, thread_num)

        if inferior.has_thread(thread_num):
            return inferior.thread(thread_num)

    return None
Exemplo n.º 10
0
    def switch_thread(self, current_thread_id=None, first_thread_id=None):
        if len(self.threads) == 0:
            TraceFunctionsI.printf("warning: no known threads, no thread switch performed.")
            return
        all_threads = sorted(self.threads.keys())
        if current_thread_id is None:
            current_thread_id = gdb.selected_thread().global_num
        if first_thread_id is None:
            first_thread_id = current_thread_id

        try:
            next_thread_idx = all_threads.index(current_thread_id) + 1
            if next_thread_idx >= len(all_threads):
                next_thread_idx = 0
        except ValueError:
            next_thread_idx = 0

        #TraceFunctionsI.printf("Attempting to switch to thread at idx %d of %s" % (next_thread_idx, all_threads))
        next_thread_id = all_threads[next_thread_idx]
        if next_thread_id == first_thread_id:
            if len(all_threads) > 0:
                TraceFunctionsI.printf("error: failed to find any next thread to execute. Not performing context switch.")
        
        next_thread = self.threads[next_thread_id]
        if next_thread.is_exited() or not next_thread.is_valid():
            TraceFunctionsI.printf("thread %s has become invalid or exited, removing from watch list." % (next_thread.ptid,))
            del self.threads[next_thread_id]
            self.switch_thread(current_thread_id, first_thread_id)
        else:
            # TODO this doesn't work at all
            gdb.execute("set scheduler-locking off", to_string=True)
            TraceFunctionsI.printf("switching to thread %s" % (next_thread.ptid,))
            next_thread.switch()
            #brk = gdb.FinishBreakpoint(gdb.newest_frame(), internal=True)
            #brk.thread = int(next_thread.global_num)

            gtid = gdb.selected_thread().global_num
            frame = gdb.newest_frame()
            sal = frame.find_sal()
            if sal.symtab:
                filename = sal.symtab.filename
            else:
                filename = None
            linenumber = sal.line
            function = frame.function()
            gdb.execute("finish", to_string=True)
            self.log("returned from", frame.pc(), function, filename, linenumber)
            gdb.execute("set scheduler-locking on", to_string=True)
            TraceFunctionsI.printf("switch to thread %s completed" % (next_thread.ptid,))
Exemplo n.º 11
0
def thread_name(name, threadnum=None):
    """Set name to thread `threadnum`.
    If threadnum is not given, set name to current thread.
    For example: threadnum('foo', 2) will set thread 2's name to 'foo'."""
    if threadnum is not None:
        threads = info_threads()
        for th in threads:
            if th[1] == threadnum:
                original_thread_num = gdb.selected_thread().num
                gdb.execute('thread %d' % th[1], to_string=True)
                current_thread = gdb.selected_thread()
                current_thread.name = name
                gdb.execute('thread %d' % original_thread_num, to_string=True)
    else:
        gdb.execute('thread name %s' % name)
Exemplo n.º 12
0
def thread_name(name, threadnum=None):
    """Set name to thread `threadnum`.
    If threadnum is not given, set name to current thread.
    For example: threadnum('foo', 2) will set thread 2's name to 'foo'."""
    if threadnum is not None:
        threads = info_threads()
        for th in threads:
            if th[1] == threadnum:
                original_thread_num = gdb.selected_thread().num
                gdb.execute('thread %d' % th[1], to_string=True)
                current_thread = gdb.selected_thread()
                current_thread.name = name
                gdb.execute('thread %d' % original_thread_num, to_string=True)
    else:
        gdb.execute('thread name %s' % name)
Exemplo n.º 13
0
 def __init__(self, thread_ctx):
     self.thread_ctx = thread_ctx
     self.old_frame = gdb.selected_frame()
     self.old_regs = self.save_regs()
     self.old_gdb_thread = gdb.selected_thread()
     self.gdb_thread = get_thread_owning_memory(thread_ctx.address)
     self.new_regs = None
Exemplo n.º 14
0
def reactor_threads():
    orig = gdb.selected_thread()
    for t in gdb.selected_inferior().threads():
        t.switch()
        if has_reactor():
            yield t
    orig.switch()
Exemplo n.º 15
0
  def invoke (self, arg, from_tty):
    thread = gdb.selected_thread()
    if thread == None:
      print 'No thread selected.'
      return

    for thread in gdb.inferiors():
      frame = gdb.newest_frame()
      while frame:
        # if that matches our regexp, select that.
        try:
          match = re.match(arg, frame.name(), flags=re.IGNORECASE)
        except Exception, e:
          print "Error: invalid regex: %s" % str(e)
          return

        if match:
          sal = frame.find_sal()
          print "Found: %s, thread %s, file %s:%s, in function %s" % (frame.name(), thread.num,sal.symtab.filename, sal.line, frame.function())
          frame.select()
          return

        frame = frame.older()
        if not frame:
          return
Exemplo n.º 16
0
    def get_heap_address(self, mp=None):
        """Read heap address from glibc's mp_ structure if available,
        otherwise fall back to /proc/self/maps which is unreliable.
        """

        start, end = None, None

        if mp is not None:
            from libheap.ptmalloc.malloc_par import malloc_par
            if isinstance(mp, malloc_par):
                start = mp.sbrk_base
            else:
                print_error("Please specify a valid malloc_par variable")

            # XXX: add end from arena(s).system_mem ?
        else:
            pid, task_id, thread_id = gdb.selected_thread().ptid
            maps_file = "/proc/%d/task/%d/maps"
            maps_data = open(maps_file % (pid, task_id)).readlines()
            for line in maps_data:
                if any(x.strip() == '[heap]' for x in line.split(' ')):
                    heap_range = line.split(' ')[0]
                    start, end = [int(h, 16) for h in heap_range.split('-')]
                    break

        return start, end
Exemplo n.º 17
0
    def stop(self):
        caller = gdb.newest_frame().older()
        caller_name = caller.name() if caller else 'none'
        print('{};{};{}'.format(gdb.selected_thread().num, caller_name,
                                gdb.newest_frame().name()))

        return False
Exemplo n.º 18
0
def update():
    """
    For each running thread, updates the known address range
    for its stack.
    """
    curr_thread = gdb.selected_thread()

    try:
        for thread in gdb.selected_inferior().threads():
            thread.switch()
            sp = pwndbg.regs.sp

            # If we don't already know about this thread, create
            # a new Page mapping for it.
            page = stacks.get(thread.ptid, None)
            if page is None:
                start = pwndbg.memory.find_lower_boundary(sp)
                stop  = find_upper_stack_boundary(sp)
                page  = pwndbg.memory.Page(start, stop-start, 6 if not is_executable() else 7, 0, '[stack]')
                stacks[thread.ptid] = page
                continue
            elif page.objfile is None:
                page.objfile = '[stack]'

            # If we *DO* already know about this thread, just
            # update the lower boundary.
            low = pwndbg.memory.find_lower_boundary(page.vaddr)
            if low != page.vaddr:
                page.memsz  += (page.vaddr - low)
                page.vaddr   = low
    finally:
        curr_thread.switch()
Exemplo n.º 19
0
    def save_user_state(self):
        self.pagination = gdb.parameter("pagination")
        if self.pagination:
            gdb.execute("set pagination off")

        self.user_selected_thread = gdb.selected_thread()
        self.user_selected_frame = gdb.selected_frame()
Exemplo n.º 20
0
    def _fs_gs_helper(self, regname, which):
        """Supports fetching based on segmented addressing, a la fs:[0x30].
        Requires ptrace'ing the child directly for GDB < 8."""

        # For GDB >= 8.x we can use get_register directly
        # Elsewhere we have to get the register via ptrace
        if get_register == gdb79_get_register:
            return get_register(regname)

        # We can't really do anything if the process is remote.
        if pwndbg.remote.is_remote():
            return 0

        # Use the lightweight process ID
        pid, lwpid, tid = gdb.selected_thread().ptid

        # Get the register
        ppvoid = ctypes.POINTER(ctypes.c_void_p)
        value = ppvoid(ctypes.c_void_p())
        value.contents.value = 0

        libc = ctypes.CDLL("libc.so.6")
        result = libc.ptrace(PTRACE_ARCH_PRCTL, lwpid, value, which)

        if result == 0:
            return (value.contents.value or 0) & pwndbg.arch.ptrmask

        return 0
Exemplo n.º 21
0
def find_lock_manager_holders(graph, thread_dict, show):  # pylint: disable=too-many-locals
    """Find lock manager holders."""
    frame = find_frame(r'mongo::LockerImpl\<.*\>::')
    if not frame:
        return

    frame.select()

    (_, lock_waiter_lwpid, _) = gdb.selected_thread().ptid
    lock_waiter = thread_dict[lock_waiter_lwpid]

    locker_ptr_type = gdb.lookup_type("mongo::LockerImpl<false>").pointer()
    lock_head = gdb.parse_and_eval(
        "mongo::getGlobalLockManager()->_getBucket(resId)->findOrInsert(resId)")

    granted_list = lock_head.dereference()["grantedList"]
    lock_request_ptr = granted_list["_front"]
    while lock_request_ptr:
        lock_request = lock_request_ptr.dereference()
        locker_ptr = lock_request["locker"]
        locker_ptr = locker_ptr.cast(locker_ptr_type)
        locker = locker_ptr.dereference()
        lock_holder_id = int(locker["_threadId"]["_M_thread"])
        if lock_holder_id == 0:
            locker_id = int(locker["_id"])
            lock_holder = NonExecutingThread(locker_id)
        else:
            lock_holder = find_thread(thread_dict, lock_holder_id)
        if show:
            print("MongoDB Lock at {} ({}) held by {} waited on by {}".format(
                lock_head, lock_request["mode"], lock_holder, lock_waiter))
        if graph:
            graph.add_edge(lock_waiter, Lock(long(lock_head), "MongoDB lock"))
            graph.add_edge(Lock(long(lock_head), "MongoDB lock"), lock_holder)
        lock_request_ptr = lock_request["next"]
Exemplo n.º 22
0
 def action(self, arg, from_tty):
     thread = gdb.selected_thread()
     # `global_num` was introduced in GDB 7.11
     num = getattr(thread, 'global_num',
                   None) or thread.num if thread else None
     inferior = gdbjsThreadGroup.action(arg, from_tty)
     return {"id": num or None, "group": inferior}
Exemplo n.º 23
0
 def valcache(self, value_or_path, **kwargs):
     '''return value from cache if exists else return argument value'''
     if type(value_or_path) in (str, unicode):
         path = value_or_path
         frnum = get_this_frame_num()
         th = gdb.selected_thread()
         if frnum == None or th == None:
             valcache1 = None
         else:
             key = (frnum, path, th.global_num)
             valcache1 = self.value_str_cache.get(key)
         if valcache1 == None:
             valcache1 = gdb.parse_and_eval(path)
             self.value_cache[key] = valcache1
             self.add_valcache_byaddr(valcache1)
     else:
         value = value_or_path
         if value.is_optimized_out:
             #can't cache this value
             return value
         addr = valueaddress_to_ulong(value.address)
         if addr == None:
             return value
         key = (addr, str(value.type))
         valcache1 = self.value_cache.get(key)
         if valcache1 == None:
             self.add_valcache_byaddr(value)
             valcache1 = value
     return valcache1
Exemplo n.º 24
0
    def _Inject(self, position, call):
        """Injects evaluation of 'call' in a safe location in the inferior.

    Due to the way these injected function calls work, gdb must not be killed
    until the call has returned. If that happens, the inferior will be sent
    SIGTRAP upon attempting to return from the dummy frame gdb constructs for
    us, and will most probably crash.
    Args:
      position: array of pid, tid, framedepth specifying the requested position.
      call: Any expression gdb can evaluate. Usually a function call.
    Raises:
      RuntimeError: if gdb is not being run in synchronous exec mode.
    """
        self.EnsureGdbPosition(position[0], position[1], None)
        self.ClearBreakpoints()
        self._AddThreadSpecificBreakpoint(position)
        gdb.parse_and_eval('%s = 1' % GdbCache.PENDINGCALLS_TO_DO)
        gdb.parse_and_eval('%s = 1' % GdbCache.PENDINGBUSY)
        try:
            # We're "armed", risk the blocking call to Continue
            self.Continue(position)
            # Breakpoint was hit!
            if not gdb.selected_thread().is_stopped():
                # This should not happen. Depending on how gdb is being used, the
                # semantics of self.Continue change, so I'd rather leave this check in
                # here, in case we ever *do* end up changing to async mode.
                raise RuntimeError(
                    'Gdb is not acting as expected, is it being run in '
                    'async mode?')
        finally:
            gdb.parse_and_eval('%s = 0' % GdbCache.PENDINGBUSY)
        self.Call(position, call)
Exemplo n.º 25
0
    def invoke(self, basevar, cpu=None):
        if not (basevar.type.tag and
                basevar.type.tag.startswith('static_percpu<')):
            raise gdb.GdbError('Not a static_percpu')

        if cpu is None:
            cpu = gdb.selected_thread().num - 1
        else:
            cpu = int(cpu)

        # Get the key.  Unfortunately, G++ optimizes out the second
        # template argument, so we have to do this the dumb way.
        m = re.search(r'&([^ ,]+_key),', str(basevar.type))
        if not m:
            raise gdb.GdbError('Failed to parse type string %r' %
                               str(basevar.type))
        key = gdb.lookup_global_symbol(m.group(1))
        if key is None:
            raise gdb.GdbError('Failed to find per-cpu key %r' % m.group(1))

        # Compute the offset
        start = gdb.lookup_global_symbol('__percpu_start')
        offset = int(key.value().address) - int(start.value().address)

        # Get CPU's base
        cpubase = gdb.lookup_global_symbol('percpu_offsets').value()[cpu]

        # Put together new pointer
        return (cpubase + offset).cast(key.type.pointer()).dereference()
Exemplo n.º 26
0
def saveCurrentState(state):
    curr_thread = gdb.selected_thread()
    for thread in gdb.selected_inferior().threads():
        if not thread.num in state:
            thread.switch()
            state[thread.num] = HermitTaskState()
    curr_thread.switch()
Exemplo n.º 27
0
    def _fs_gs_helper(self, which):
        """Supports fetching based on segmented addressing, a la fs:[0x30].

        Requires ptrace'ing the child directly."""

        # We can't really do anything if the process is remote.
        if pwndbg.remote.is_remote(): return 0

        # Use the lightweight process ID
        pid, lwpid, tid = gdb.selected_thread().ptid

        # Get the register
        ppvoid = ctypes.POINTER(ctypes.c_void_p)
        value  = ppvoid(ctypes.c_void_p())
        value.contents.value = 0

        libc  = ctypes.CDLL('libc.so.6')
        result = libc.ptrace(PTRACE_ARCH_PRCTL,
                             lwpid,
                             value,
                             which)

        if result == 0:
            return (value.contents.value or 0) & pwndbg.arch.ptrmask

        return 0
Exemplo n.º 28
0
    def get_heap_address(self, mp=None):
        """Read heap address from glibc's mp_ structure if available,
        otherwise fall back to /proc/self/maps which is unreliable.
        """

        start, end = None, None

        if mp is not None:
            from libheap.ptmalloc.malloc_par import malloc_par
            if isinstance(mp, malloc_par):
                start = mp.sbrk_base
            else:
                print_error("Please specify a valid malloc_par variable")

            # XXX: add end from arena(s).system_mem ?
        else:
            pid, task_id, thread_id = gdb.selected_thread().ptid
            maps_file = "/proc/%d/task/%d/maps"
            maps_data = open(maps_file % (pid, task_id)).readlines()
            for line in maps_data:
                if any(x.strip() == '[heap]' for x in line.split(' ')):
                    heap_range = line.split(' ')[0]
                    start, end = [int(h, 16) for h in heap_range.split('-')]
                    break

        return start, end
Exemplo n.º 29
0
    def invoke(self, arg, from_tty):
        if self.tunnel and not self.tunnel.is_up():
            self.tunnel = None

        if not self.tunnel:
            if arg == "":
                arg = self.cfg.host

            self.tunnel = Tunnel(arg, self.cfg.port)
            if not self.tunnel.is_up():
                rs_log("sync failed")
                return

            id = self.identity()
            self.tunnel.send(
                "[notice]{\"type\":\"new_dbg\",\"msg\":\"dbg connect - %s\",\"dialect\":\"gdb\"}\n"
                % id)
            rs_log("sync is now enabled with host %s" % str(arg))

            # make sure there is an active thread before running the Poller
            if gdb.selected_thread():
                self.create_poll_timer()
        else:
            print('(update)')

        if self.poller:
            self.poller.enable()
Exemplo n.º 30
0
  def update_symbols(self, current_thread_only):
    """Updates the mapping between symbols as seen from GDB and local library
    files.

    If current_thread_only is True, only update symbols for the current thread.
    """
    logging.info("Updating symbols")
    mapped_files = _get_mapped_files()
    # Map all symbols from native libraries packages with the APK.
    for file_mappings in mapped_files:
      filename = file_mappings[0].filename
      if ((filename.startswith('/data/data/') or
           filename.startswith('/data/app')) and
          not filename.endswith('.apk') and
          not filename.endswith('.dex')):
        logging.info('Pre-mapping: %s' % file_mappings[0].filename)
        self._try_to_map(file_mappings)

    if current_thread_only:
      self._map_symbols_on_current_thread(mapped_files)
    else:
      logging.info('Updating all threads\' symbols')
      current_thread = gdb.selected_thread()
      nb_threads = len(_gdb_execute("info threads").split("\n")) - 2
      for i in xrange(nb_threads):
        try:
          _gdb_execute("thread %d" % (i + 1))
          self._map_symbols_on_current_thread(mapped_files)
        except gdb.error:
          traceback.print_exc()
      current_thread.switch()
Exemplo n.º 31
0
 def need_update(self):
     pkgs = []
     threads_info = self.get_threads_info()
     exited_threads = set(self.saved_threads_info.keys()) - set(
         threads_info.keys())
     rm_rowids = []
     for global_num in exited_threads:  #remove from GUI win exited threads
         rm_rowids.append(self.id_threadrow(global_num))
     if rm_rowids:
         pkgs.append(self.pkg_drop_rows(rm_rowids))
     new_threads = []
     append_rows = []
     for global_num in threads_info:
         thread_info = threads_info[global_num]
         if global_num not in self.saved_threads_info:
             #появился новый поток
             row = self.new_threadrow(thread_info)
             append_rows.append(row)  #добавляем для него строку
         else:
             saved_thread_info = self.saved_threads_info[global_num]
             pkgs.append(
                 self.compare_infos(global_num,
                                    old=saved_thread_info,
                                    new=thread_info))
     if append_rows:
         pkgs.append(self.pkg_append_rows(append_rows))
     self.saved_threads_info = threads_info
     self.selected_global_num = gdb.selected_thread().global_num
     return pkgs
Exemplo n.º 32
0
def find_lock_manager_holders(graph, thread_dict, show):
    frame = find_frame(r'mongo::LockerImpl\<.*\>::')
    if not frame:
        return

    frame.select()

    (_, lwpid, _) = gdb.selected_thread().ptid

    locker_ptr_type = gdb.lookup_type("mongo::LockerImpl<false>").pointer()
    lock_head = gdb.parse_and_eval(
        "mongo::getGlobalLockManager()->_getBucket(resId)->findOrInsert(resId)")

    grantedList = lock_head.dereference()["grantedList"]
    lock_request_ptr = grantedList["_front"]
    while lock_request_ptr:
        lock_request = lock_request_ptr.dereference()
        locker_ptr = lock_request["locker"]
        locker_ptr = locker_ptr.cast(locker_ptr_type)
        locker = locker_ptr.dereference()
        lock_thread_id = int(locker["_threadId"]["_M_thread"])
        lock_thread_lwpid = find_lwpid(thread_dict, lock_thread_id)
        if show:
            print("MongoDB Lock at {} ({}) held by thread id 0x{:x} (LWP {})".format(
                lock_head, lock_request["mode"], lock_thread_id, lock_thread_lwpid) +
                " waited on by thread 0x{:x} (LWP {})".format(thread_dict[lwpid], lwpid))
        if graph:
            graph.add_edge(Thread(thread_dict[lwpid], lwpid), Lock(long(lock_head), "MongoDB lock"))
            graph.add_edge(Lock(long(lock_head), "MongoDB lock"),
                           Thread(lock_thread_id, lock_thread_lwpid))
        lock_request_ptr = lock_request["next"]
Exemplo n.º 33
0
    def pkg_update_bps(self, bps):
        bps_data = []
        for bp in bps:
            if not bp.is_valid(
            ) or not bp.visible or bp.type != gdb.BP_BREAKPOINT:
                continue
            bp_data = {}
            for name in [
                    'silent', 'thread', 'ignore_count', 'number', 'temporary',
                    'hit_count', 'condition', 'commands', 'enabled'
            ]:
                value = getattr(bp, name)
                bp_data[name] = value
            external_id = self.bp_gdb_mc.get(bp.number)
            if external_id is not None:
                bp_data['external_id'] = external_id
            else:
                self.bp_gdb_mc[bp.number] = None
            bp_data['locations'] = map(
                lambda fl: {
                    'filename': fl[0],
                    'line': fl[1]
                }, get_bp_locations(bp))
            bps_data.append(bp_data)

        if len(bps_data) == 0:
            return
        sel_th = gdb.selected_thread()
        return {
            'cmd': 'bpsupd',
            'bps_data': bps_data,
        }
Exemplo n.º 34
0
 def get_current_slab_cache_cpu(self, slab_cache):
     void = gdb.lookup_type("void").pointer()
     kmem_cache_cpu = gdb.lookup_type("struct kmem_cache_cpu")
     current_cpu = gdb.selected_thread().num - 1
     cpu_offset = self.per_cpu_offset[current_cpu]
     cpu_slab = gdb.Value(slab_cache["cpu_slab"].cast(void) + cpu_offset)
     return cpu_slab.cast(kmem_cache_cpu.pointer()).dereference()
Exemplo n.º 35
0
def find_mutex_holder(graph, thread_dict, show):
    frame = find_frame(r'std::mutex::lock\(\)')
    if frame is None:
        return

    frame.select()

    # Waiting for mutex locking!
    mutex_this, _ = gdb.lookup_symbol("this", frame.block())
    mutex_value = mutex_this.value(frame)
    # The mutex holder is a LWPID
    mutex_holder = int(mutex_value["_M_mutex"]["__data"]["__owner"])
    mutex_holder_id = thread_dict[mutex_holder]

    (_, mutex_waiter_lwpid, _) = gdb.selected_thread().ptid
    mutex_waiter_id = thread_dict[mutex_waiter_lwpid]
    if show:
        print("Mutex at {} held by thread 0x{:x} (LWP {}) "
              " waited on by thread 0x{:x} (LWP {})".format(mutex_value,
                                                            mutex_holder_id,
                                                            mutex_holder,
                                                            mutex_waiter_id,
                                                            mutex_waiter_lwpid))
    if graph:
        graph.add_edge(Thread(mutex_waiter_id, mutex_waiter_lwpid),
                       Lock(long(mutex_value), "Mutex"))
        graph.add_edge(Lock(long(mutex_value), "Mutex"), Thread(mutex_holder_id, mutex_holder))
Exemplo n.º 36
0
def saveCurrentState(state):
    curr_thread = gdb.selected_thread()
    for thread in gdb.selected_inferior().threads():
        if not thread.num in state:
            thread.switch()
            state[thread.num] = HermitTaskState()
    curr_thread.switch()
Exemplo n.º 37
0
    def invoke(self, basevar, cpu=None):
        if not (basevar.type.tag
                and basevar.type.tag.startswith('static_percpu<')):
            raise gdb.GdbError('Not a static_percpu')

        if cpu is None:
            cpu = gdb.selected_thread().num - 1
        else:
            cpu = int(cpu)

        # Get the key.  Unfortunately, G++ optimizes out the second
        # template argument, so we have to do this the dumb way.
        m = re.search(r'&([^ ,]+_key),', str(basevar.type))
        if not m:
            raise gdb.GdbError('Failed to parse type string %r' %
                               str(basevar.type))
        key = gdb.lookup_global_symbol(m.group(1))
        if key is None:
            raise gdb.GdbError('Failed to find per-cpu key %r' % m.group(1))

        # Compute the offset
        start = gdb.lookup_global_symbol('__percpu_start')
        offset = int(key.value().address) - int(start.value().address)

        # Get CPU's base
        cpubase = gdb.lookup_global_symbol('percpu_offsets').value()[cpu]

        # Put together new pointer
        return (cpubase + offset).cast(key.type.pointer()).dereference()
Exemplo n.º 38
0
def find_lock_manager_holders(graph, thread_dict, show):
    frame = find_frame(r'mongo::LockerImpl\<.*\>::')
    if not frame:
        return

    frame.select()

    (_, lwpid, _) = gdb.selected_thread().ptid

    locker_ptr_type = gdb.lookup_type("mongo::LockerImpl<false>").pointer()
    lock_head = gdb.parse_and_eval(
        "mongo::getGlobalLockManager()->_getBucket(resId)->findOrInsert(resId)"
    )

    grantedList = lock_head.dereference()["grantedList"]
    lock_request_ptr = grantedList["_front"]
    while lock_request_ptr:
        lock_request = lock_request_ptr.dereference()
        locker_ptr = lock_request["locker"]
        locker_ptr = locker_ptr.cast(locker_ptr_type)
        locker = locker_ptr.dereference()
        lock_thread_id = int(locker["_threadId"]["_M_thread"])
        lock_thread_lwpid = find_lwpid(thread_dict, lock_thread_id)
        if show:
            print("MongoDB Lock at {} ({}) held by thread id 0x{:x} (LWP {})".
                  format(lock_head, lock_request["mode"], lock_thread_id,
                         lock_thread_lwpid) +
                  " waited on by thread 0x{:x} (LWP {})".format(
                      thread_dict[lwpid], lwpid))
        if graph:
            graph.add_edge(Thread(thread_dict[lwpid], lwpid),
                           Lock(long(lock_head), "MongoDB lock"))
            graph.add_edge(Lock(long(lock_head), "MongoDB lock"),
                           Thread(lock_thread_id, lock_thread_lwpid))
        lock_request_ptr = lock_request["next"]
Exemplo n.º 39
0
def find_mutex_holder(graph, thread_dict, show):
    """Find mutex holder."""
    frame = find_frame(r'std::mutex::lock\(\)')
    if frame is None:
        return

    frame.select()

    # Waiting for mutex locking!
    mutex_this, _ = gdb.lookup_symbol("this", frame.block())
    mutex_value = mutex_this.value(frame)
    # The mutex holder is a LWPID
    mutex_holder_lwpid = int(mutex_value["_M_mutex"]["__data"]["__owner"])

    # At time thread_dict was initialized, the mutex holder may not have been found.
    # Use the thread LWP as a substitute for showing output or generating the graph.
    if mutex_holder_lwpid not in thread_dict:
        print("Warning: Mutex at {} held by thread with LWP {}"
              " not found in thread_dict. Using LWP to track thread.".format(
                  mutex_value, mutex_holder_lwpid))
        mutex_holder = Thread(mutex_holder_lwpid, mutex_holder_lwpid, '"[unknown]"')
    else:
        mutex_holder = thread_dict[mutex_holder_lwpid]

    (_, mutex_waiter_lwpid, _) = gdb.selected_thread().ptid
    mutex_waiter = thread_dict[mutex_waiter_lwpid]
    if show:
        print("Mutex at {} held by {} waited on by {}".format(mutex_value, mutex_holder,
                                                              mutex_waiter))
    if graph:
        graph.add_edge(mutex_waiter, Lock(long(mutex_value), "Mutex"))
        graph.add_edge(Lock(long(mutex_value), "Mutex"), mutex_holder)
Exemplo n.º 40
0
def find_mutex_holder(graph, thread_dict, show):
    """Find mutex holder."""
    frame = find_frame(r'std::mutex::lock\(\)')
    if frame is None:
        return

    frame.select()

    # Waiting for mutex locking!
    mutex_this, _ = gdb.lookup_symbol("this", frame.block())
    mutex_value = mutex_this.value(frame)
    # The mutex holder is a LWPID
    mutex_holder_lwpid = int(mutex_value["_M_mutex"]["__data"]["__owner"])

    # At time thread_dict was initialized, the mutex holder may not have been found.
    # Use the thread LWP as a substitute for showing output or generating the graph.
    if mutex_holder_lwpid not in thread_dict:
        print("Warning: Mutex at {} held by thread with LWP {}"
              " not found in thread_dict. Using LWP to track thread.".format(
                  mutex_value, mutex_holder_lwpid))
        mutex_holder = Thread(mutex_holder_lwpid, mutex_holder_lwpid,
                              '"[unknown]"')
    else:
        mutex_holder = thread_dict[mutex_holder_lwpid]

    (_, mutex_waiter_lwpid, _) = gdb.selected_thread().ptid
    mutex_waiter = thread_dict[mutex_waiter_lwpid]
    if show:
        print("Mutex at {} held by {} waited on by {}".format(
            mutex_value, mutex_holder, mutex_waiter))
    if graph:
        graph.add_edge(mutex_waiter, Lock(long(mutex_value), "Mutex"))
        graph.add_edge(Lock(long(mutex_value), "Mutex"), mutex_holder)
Exemplo n.º 41
0
def reactor_threads():
    orig = gdb.selected_thread()
    for t in gdb.selected_inferior().threads():
        t.switch()
        if has_reactor():
            yield t
    orig.switch()
Exemplo n.º 42
0
 def __init__(self, thread_ctx):
     self.thread_ctx = thread_ctx
     self.old_frame = gdb.selected_frame()
     self.old_regs = self.save_regs()
     self.old_gdb_thread = gdb.selected_thread()
     self.gdb_thread = get_thread_owning_memory(thread_ctx.address)
     self.new_regs = None
Exemplo n.º 43
0
def chooseThreadFlip():
    tag = "chooseThreadFlip"
    bufLog = ""
    try:
        inferior = gdb.selected_inferior()

        for inf in gdb.inferiors():
            logging.debug("Inferior PID: " + str(inf.pid))
            logging.debug("Inferior is valid: " + str(inf.is_valid()))
            logging.debug("Inferior #threads: " + str(len(inf.threads())))
        th = gdb.selected_thread()
        bufLog += str("Backtrace BEGIN:")
        bufLog += "\n"
        bt = gdb.execute("bt", to_string=True)
        sourceLines = gdb.execute("list", to_string=True)
        bufLog += str(bt)
        bufLog += "\n"
        bufLog += str(sourceLines)
        bufLog += "\n"
        bufLog += str("Backtrace END")
        bufLog += "\n"
        threadsSymbols = list()
        for th in inferior.threads():
            try:
                th.switch()
                thSymbols = getAllValidSymbols()
                if len(thSymbols) > 0:
                    threadsSymbols.append([th, thSymbols])
            except:
                continue
        thLen = len(threadsSymbols)
        if thLen <= 0:
            logging.debug(str("No Threads with symbols"))
            return False
        thPos = random.randint(0, thLen - 1)
        curThread = threadsSymbols[thPos][0]
        logging.debug("Thread name: " + str(curThread.name))
        logging.debug("Thread num: " + str(curThread.num))
        logging.debug("Thread ptid: " + str(curThread.ptid))
        bufLogFFText = ""
        (r, bufLogFFText) = chooseFrameFlip(threadsSymbols[thPos][1])
        while r is False:
            threadsSymbols.pop(thPos)
            thLen -= 1
            if (thLen <= 0):
                break
            thPos = random.randint(0, thLen - 1)
            try:
                (r, bufLogFFText) = chooseFrameFlip(threadsSymbols[thPos][1])
            except:
                r = False
        bufLog += bufLogFFText
        if r or conf.getboolean("DEFAULT", "debug"):
            logging.info(bufLog)
        return r
    except Exception as err:
        logging.exception("pythonException: " + str(err))
        if conf.getboolean("DEFAULT", "debug"):
            logging.info(bufLog)
        return False
Exemplo n.º 44
0
    def update_symbols(self, current_thread_only):
        """Updates the mapping between symbols as seen from GDB and local library
    files.

    If current_thread_only is True, only update symbols for the current thread.
    """
        logging.info("Updating symbols")
        mapped_files = _get_mapped_files()
        # Map all symbols from native libraries packages with the APK.
        for file_mappings in mapped_files:
            filename = file_mappings[0].filename
            if (
                (filename.startswith("/data/data/") or filename.startswith("/data/app"))
                and not filename.endswith(".apk")
                and not filename.endswith(".dex")
            ):
                logging.info("Pre-mapping: %s" % file_mappings[0].filename)
                self._try_to_map(file_mappings)

        if current_thread_only:
            self._map_symbols_on_current_thread(mapped_files)
        else:
            logging.info("Updating all threads' symbols")
            current_thread = gdb.selected_thread()
            nb_threads = len(_gdb_execute("info threads").split("\n")) - 2
            for i in xrange(nb_threads):
                try:
                    _gdb_execute("thread %d" % (i + 1))
                    self._map_symbols_on_current_thread(mapped_files)
                except gdb.error:
                    traceback.print_exc()
            current_thread.switch()
Exemplo n.º 45
0
def find_mutex_holder(graph, thread_dict, show):
    frame = find_frame(r'std::mutex::lock\(\)')
    if frame is None:
        return

    frame.select()

    # Waiting for mutex locking!
    mutex_this, _ = gdb.lookup_symbol("this", frame.block())
    mutex_value = mutex_this.value(frame)
    # The mutex holder is a LWPID
    mutex_holder = int(mutex_value["_M_mutex"]["__data"]["__owner"])
    mutex_holder_id = thread_dict[mutex_holder]

    (_, mutex_waiter_lwpid, _) = gdb.selected_thread().ptid
    mutex_waiter_id = thread_dict[mutex_waiter_lwpid]
    if show:
        print("Mutex at {} held by thread 0x{:x} (LWP {}) "
              " waited on by thread 0x{:x} (LWP {})".format(
                  mutex_value, mutex_holder_id, mutex_holder, mutex_waiter_id,
                  mutex_waiter_lwpid))
    if graph:
        graph.add_edge(Thread(mutex_waiter_id, mutex_waiter_lwpid),
                       Lock(long(mutex_value), "Mutex"))
        graph.add_edge(Lock(long(mutex_value), "Mutex"),
                       Thread(mutex_holder_id, mutex_holder))
Exemplo n.º 46
0
    def _fs_gs_helper(self, which):
        """Supports fetching based on segmented addressing, a la fs:[0x30].

        Requires ptrace'ing the child directly."""

        # We can't really do anything if the process is remote.
        if pwndbg.remote.is_remote(): return 0

        # Use the lightweight process ID
        pid, lwpid, tid = gdb.selected_thread().ptid

        # Get the register
        ppvoid = ctypes.POINTER(ctypes.c_void_p)
        value  = ppvoid(ctypes.c_void_p())
        value.contents.value = 0

        libc  = ctypes.CDLL('libc.so.6')
        result = libc.ptrace(PTRACE_ARCH_PRCTL,
                             lwpid,
                             value,
                             which)

        if result == 0:
            return (value.contents.value or 0) & pwndbg.arch.ptrmask

        return 0
Exemplo n.º 47
0
  def _Inject(self, position, call):
    """Injects evaluation of 'call' in a safe location in the inferior.

    Due to the way these injected function calls work, gdb must not be killed
    until the call has returned. If that happens, the inferior will be sent
    SIGTRAP upon attempting to return from the dummy frame gdb constructs for
    us, and will most probably crash.
    Args:
      position: array of pid, tid, framedepth specifying the requested position.
      call: Any expression gdb can evaluate. Usually a function call.
    Raises:
      RuntimeError: if gdb is not being run in synchronous exec mode.
    """
    self.EnsureGdbPosition(position[0], position[1], None)
    self.ClearBreakpoints()
    self._AddThreadSpecificBreakpoint(position)
    gdb.parse_and_eval('%s = 1' % GdbCache.PENDINGCALLS_TO_DO)
    gdb.parse_and_eval('%s = 1' % GdbCache.PENDINGBUSY)
    try:
      # We're "armed", risk the blocking call to Continue
      self.Continue(position)
      # Breakpoint was hit!
      if not gdb.selected_thread().is_stopped():
        # This should not happen. Depending on how gdb is being used, the
        # semantics of self.Continue change, so I'd rather leave this check in
        # here, in case we ever *do* end up changing to async mode.
        raise RuntimeError('Gdb is not acting as expected, is it being run in '
                           'async mode?')
    finally:
      gdb.parse_and_eval('%s = 0' % GdbCache.PENDINGBUSY)
    self.Call(position, call)
Exemplo n.º 48
0
def restoreCurrentState(state):
    curr_thread = gdb.selected_thread()
    for thread in gdb.selected_inferior().threads():
        if thread.num in state:
            thread.switch()
            state[thread.num].switch()
    curr_thread.switch()
    state = {}
Exemplo n.º 49
0
    def on_new_objfile(self):
        if self.running or not gdb.selected_thread():
            return

        self.running = True

        for function in self.registered:
            function()
Exemplo n.º 50
0
    def on_new_objfile(self):
        if self.running or not gdb.selected_thread():
            return

        self.running = True

        for function in self.registered:
            function()
Exemplo n.º 51
0
def reactors():
    orig = gdb.selected_thread()
    for t in gdb.selected_inferior().threads():
        t.switch()
        reactor = gdb.parse_and_eval('local_engine')
        if reactor:
            yield reactor.dereference()
    orig.switch()
Exemplo n.º 52
0
def prompt_hook(*a):
    global cur
    new = (gdb.selected_inferior(), gdb.selected_thread())

    if cur != new:
        pwndbg.events.after_reload()
        cur = new

    prompt_hook_on_stop(*a)
Exemplo n.º 53
0
  def save_context(self, ctx):
    if self.context is None:
      self.context = {}

    os_thread = gdb.selected_thread().num
    if os_thread in self.context:
      return

    self.context[os_thread] = ctx
Exemplo n.º 54
0
			def stop(self):
				thread_id = int(gdb.selected_thread().num)
				assert thread_id in threads
				fn_result = get_result()
				fn_name, fn_args, fn_stacktrace = threads[thread_id]
				assert fn_name == self.on_enter.fn_name
				add_call(allocs, free_stats, call_stats, fn_name, fn_args, fn_stacktrace, fn_result)
				del threads[thread_id]
				return False
Exemplo n.º 55
0
    def tid(self):
        if pwndbg.qemu.is_qemu_usermode():
            return pwndbg.qemu.pid()

        i = gdb.selected_thread()
        if i is not None:
            return i.ptid[1]

        return self.pid
Exemplo n.º 56
0
def print_thread(thr, mut, owns=[]):
    "A helper function to nicely print a gdb.Thread."
    (pid, lwp, tid) = thr.ptid
    out = "* " if thr == gdb.selected_thread() else "  "
    out += "Owner  " if mut in owns else "Thread "
    out += "%2d (LWP %d) " % (thr.num, lwp)
    if owns:
        out += " owns: %s" % (" ".join(map(lambda addr: ("0x%x" % addr) if addr != mut else "this", owns)))
    print(out)
Exemplo n.º 57
0
 def __init__(self, typecache):
     self.next_sp = None
     self.next_type = None
     self.activation = None
     # An unwinder instance is specific to a thread.  Record the
     # selected thread for later verification.
     self.thread = gdb.selected_thread()
     self.frame_map = {}
     self.proc_mappings = parse_proc_maps()
     self.typecache = typecache
Exemplo n.º 58
0
 def _get_current_thread_name(self):
     fallback_name = '"%s"' % (gdb.selected_thread().name or '')
     try:
         # This goes through the pretty printer for StringData which adds "" around the name.
         name = str(gdb.parse_and_eval("mongo::for_debuggers::threadName"))
         if name == '""':
             return fallback_name
         return name
     except gdb.error:
         return fallback_name