示例#1
0
 def _getPackageName(self):
     if self.objdir:
         acname = os.path.join(self.objdir, 'config', 'autoconf.mk')
         try:
             acfile = open(acname)
             for line in acfile:
                 if 'ANDROID_PACKAGE_NAME' not in line:
                     continue
                 acfile.close()
                 pkg = line.partition('=')[2].strip()
                 print 'Using package %s.' % pkg
                 return pkg
             acfile.close()
         except OSError:
             pass
     pkgs = [x[:x.rindex('-')] for x in \
         adb.call(['shell', 'ls', '-1', '/data/app']).splitlines() \
         if x.startswith('org.mozilla.')]
     if pkgs:
         print 'Found package names:'
         for pkg in pkgs:
             print ' ' + pkg
     else:
         pkgs = ['org.mozilla.fennec_unofficial', 'org.mozilla.fennec',
                 'org.mozilla.aurora', 'org.mozilla.firefox']
     pkg = None
     while not pkg:
         pkg = readinput.call(
             'Use package (e.g. org.mozilla.fennec): ', '-l', str(pkgs))
     return pkg
示例#2
0
    def invoke(self, argument, from_tty):
        self.dont_repeat()

        interval = (self.update_interval
                    if hasattr(self, 'update_interval') else 90)
        if argument and argument.strip() == 'force':
            interval = -1
        if not interval:
            return

        self.worktree = os.path.abspath(
            os.path.join(gdb.PYTHONDIR, os.path.pardir))
        self.gitdir = os.path.join(self.worktree, '.git')
        if not os.path.isdir(self.gitdir):
            return

        marker = os.path.join(self.worktree, '.update')

        def touchUpdate():
            with open(marker, 'a'):
                os.utime(marker, None)

        if interval > 0 and not os.path.isfile(marker):
            touchUpdate()
            return

        elapsed = time.time() - os.path.getmtime(marker)
        if elapsed >= interval * 24 * 60 * 60:
            ans = '' if interval > 0 else 'y'
            while not ans or (ans[0] != 'y' and ans[0] != 'Y' and ans[0] != 'n'
                              and ans[0] != 'N'):
                print
                ans = readinput.call(
                    'Last checked for update %d days ago; '
                    'check now? [yes/no]: ' % (elapsed / 60 / 60 / 24), '-l',
                    str(['yes', 'no']))
            if ans[0] == 'y' or ans[0] == 'Y':
                self._checkUpdate()
            # update timestamp regardless of choice above
            touchUpdate()
示例#3
0
    def invoke(self, argument, from_tty):
        self.dont_repeat()

        interval = self.update_interval if hasattr(self, "update_interval") else 90
        if argument and argument.strip() == "force":
            interval = -1
        if not interval:
            return

        self.worktree = os.path.abspath(os.path.join(gdb.PYTHONDIR, os.path.pardir))
        self.gitdir = os.path.join(self.worktree, ".git")
        if not os.path.isdir(self.gitdir):
            return

        marker = os.path.join(self.worktree, ".update")

        def touchUpdate():
            with open(marker, "a"):
                os.utime(marker, None)

        if interval > 0 and not os.path.isfile(marker):
            touchUpdate()
            return

        elapsed = time.time() - os.path.getmtime(marker)
        if elapsed >= interval * 24 * 60 * 60:
            ans = "" if interval > 0 else "y"
            while not ans or (ans[0] != "y" and ans[0] != "Y" and ans[0] != "n" and ans[0] != "N"):
                print
                ans = readinput.call(
                    "Last checked for update %d days ago; " "check now? [yes/no]: " % (elapsed / 60 / 60 / 24),
                    "-l",
                    str(["yes", "no"]),
                )
            if ans[0] == "y" or ans[0] == "Y":
                self._checkUpdate()
            # update timestamp regardless of choice above
            touchUpdate()
示例#4
0
def chooseDevice():
    # identify device
    devs = getDevices()

    # wait for a device if no device is found
    while not devs:
        try:
            print('ADB: waiting for device... (Ctrl+C to stop)')
            waitForDevice()
        except gdb.GdbError:
            raise gdb.GdbError(' ADB: no device')
        devs = getDevices()

    # use saved setting if possible; also allows gdbinit to set device
    dev = str(gdb.parameter('adb-device'))
    if dev and dev not in devs:
        print('feninit.default.device (%s) is not connected' % dev)
    # use only device
    if len(devs) == 1:
        dev = devs[0]
    # otherwise, let user decide
    while not dev in devs:
        print('Found multiple devices:')
        for i in range(len(devs)):
            print('%d. %s' % (i + 1, devs[i]))
        dev = readinput.call('Choose device: ', '-l', str(devs))
        if dev.isdigit() and int(dev) > 0 and int(dev) <= len(devs):
            dev = devs[int(dev) - 1]
        elif len(dev) > 0:
            matchDev = filter(
                    lambda x: x.lower().startswith(dev.lower()), devs)
            # if only one match, use it
            if len(matchDev) == 1:
                dev = matchDev[0]
    if str(gdb.parameter('adb-device')) != dev:
        gdb.execute('set adb-device ' + dev)
    return dev
示例#5
0
            raise gdb.GdbError(' ADB: no device')
        devs = getDevices()

    # use saved setting if possible; also allows gdbinit to set device
    dev = str(gdb.parameter('adb-device'))
    if dev and dev not in devs:
        print 'feninit.default.device (%s) is not connected' % dev
    # use only device
    if len(devs) == 1:
        dev = devs[0]
    # otherwise, let user decide
    while not dev in devs:
        print 'Found multiple devices:'
        for i in range(len(devs)):
            print '%d. %s' % (i + 1, devs[i])
        dev = readinput.call('Choose device: ', '-l', str(devs))
        if dev.isdigit() and int(dev) > 0 and int(dev) <= len(devs):
            dev = devs[int(dev) - 1]
        elif len(dev) > 0:
            matchDev = filter(
                    lambda x: x.lower().startswith(dev.lower()), devs)
            # if only one match, use it
            if len(matchDev) == 1:
                dev = matchDev[0]
    if str(gdb.parameter('adb-device')) != dev:
        gdb.execute('set adb-device ' + dev)
    return dev

def pull(src, dest):
    params = ['pull']
    if isinstance(src, list):
示例#6
0
    def _chooseObjdir(self):
        def scanSrcDir(objdirs, path):
            # look for 'obj*' directories, using 'dist' as a clue
            abspath = os.path.abspath(os.path.expanduser(path))
            if not os.path.isdir(abspath):
                return
            if os.path.isdir(os.path.join(abspath, 'dist')):
                objdirs.append(abspath)
                return
            for d in os.listdir(abspath):
                if not d.startswith('obj'):
                    continue
                objdir = os.path.join(abspath, d)
                if os.path.isdir(objdir) and \
                        os.path.isdir(os.path.join(objdir, 'dist')):
                    objdirs.append(objdir)

        objdir = '' # None means don't use an objdir
        objdirs = []
        # look for possible locations
        srcroot = self.srcroot if hasattr(self, 'srcroot') else '~'
        scanSrcDir(objdirs, os.path.join(srcroot, 'mozilla-central'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'central'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'mozilla-aurora'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'aurora'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'mozilla-beta'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'beta'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'mozilla-release'))
        scanSrcDir(objdirs, os.path.join(srcroot, 'release'))
        objdirs.sort()

        # use saved setting if possible; also allows gdbinit to set objdir
        if hasattr(self, 'objdir'):
            objdir = self.objdir
            if objdir:
                scanSrcDir(objdirs, objdir)
                if objdir not in objdirs:
                    print 'feninit.default.objdir (%s) is not found' % objdir
            else:
                objdir = None
                objdirs.append(objdir)
        # let user choose even if only one objdir found,
        # because the user might want to not use an objdir
        while objdir not in objdirs:
            if objdirs:
                print 'Choices for object directory to use:'
                print '0. Do not use object directory'
                for i in range(len(objdirs)):
                    print '%d. %s' % (i + 1, objdirs[i])
                print 'Choose from above or enter alternative'
                objdir = readinput.call(': ', '-d')
                if not objdir:
                    continue
                elif objdir == '0':
                    objdir = None
                    break
            else:
                print 'No object directory found. Enter path or leave blank'
                objdir = readinput.call(': ', '-d')
                if not objdir:
                    objdir = None
                    break
            if objdir.isdigit() and int(objdir) > 0 and \
                    int(objdir) <= len(objdirs):
                objdir = objdirs[int(objdir) - 1]
                break
            objdir = os.path.abspath(os.path.expanduser(objdir))
            matchObjdir = filter(lambda x:
                    x.startswith(objdir), objdirs)
            if len(matchObjdir) == 0:
                # not on list, verify objdir first
                scanSrcDir(objdirs, objdir)
            elif len(matchObjdir) == 1:
                # only one match, good to go
                objdir = matchObjdir[0]
        print 'Using object directory: %s' % str(objdir)
        self.objdir = objdir
示例#7
0
    def _launchAndAttach(self):
        # name of child binary
        CHILD_EXECUTABLE = 'plugin-container'
        # 'file' command argument for parent process
        PARENT_FILE_PATH = os.path.join(self.libdir, 'bin', 'app_process')
        # 'file' command argument for child process
        if self.objdir:
            CHILD_FILE_PATH = os.path.join(self.objdir,
                    'dist', 'bin', CHILD_EXECUTABLE)
        else:
            CHILD_FILE_PATH = None

        # launch
        pkg = self._getPackageName()
        sys.stdout.write('Launching %s... ' % pkg)
        sys.stdout.flush()
        out = adb.call(['shell', 'am', 'start',
                '-a', 'org.mozilla.gecko.DEBUG', '-n', pkg + '/.App'])
        if 'error' in out.lower():
            print ''
            print out
            raise gdb.GdbError('Error while launching %s.' % pkg)

        # FIXME sleep for 1s to allow time to launch
        time.sleep(1)

        # wait for launch to complete
        pkgProcs = []
        while not [True for x in pkgProcs if CHILD_EXECUTABLE not in x]:
            ps = adb.call(['shell', 'ps']).splitlines()
            # get parent/child processes that are waiting ('S' state)
            pkgProcs = [x for x in ps if pkg in x and
                    ('S' in x.split() or 'T' in x.split())]
        print 'Done'

        # get parent/child(ren) pid's
        pidParent = next((x.split()[1]
                for x in pkgProcs if CHILD_EXECUTABLE not in x))
        pidChild = [x.split()[1]
                for x in pkgProcs if CHILD_EXECUTABLE in x]
        pidChildParent = pidParent

        # see if any gdbserver instance is running, and discard
        # the debuggee from our list because it's already taken
        for proc in [x.split() for x in ps if 'gdbserver' in x]:
            # get the program being debugged by examine gdbserver cmdline
            cmdline = adb.call(['shell', 'cat',
                    '/proc/' + proc[1] + '/cmdline']).split('\0')
            if '--attach' not in cmdline:
                continue
            # this should be the pid
            pid = next((x for x in reversed(cmdline) if x.isdigit()))
            if pid == pidParent:
                pidParent = None
            elif pid in pidChild:
                pidChild.remove(pid)

        if pidParent:
            # the parent is not being debugged, pick the parent
            pidAttach = pidParent
            sys.stdout.write('Attaching to parent (pid %s)... ' % pidAttach)
            sys.stdout.flush()
        elif not pidChild:
            # ok, no child is available. assume the user
            # wants to wait for child to start up
            pkgProcs = None
            print 'Waiting for child process...'
            while not pkgProcs:
                ps = adb.call(['shell', 'ps']).splitlines()
                # check for 'S' state, for right parent, and for right child
                pkgProcs = [x for x in ps if ('S' in x or 'T' in x) and \
                        pidChildParent in x and CHILD_EXECUTABLE in x]
            pidChild = [x.split()[1] for x in pkgProcs]

        # if the parent was not picked, pick the right child
        if not pidParent and len(pidChild) == 1:
            # that is easy
            pidAttach = pidChild[0]
            sys.stdout.write('Attaching to child (pid %s)... ' % pidAttach)
            sys.stdout.flush()
        elif not pidParent:
            # should not happen for now, because we only use one child
            pidAttach = None
            while pidAttach not in pidChild:
                print 'WTF multiple child processes found:'
                for i in range(len(pidChild)):
                    print '%d. pid %s' % (i + 1, pidChild[i])
                pidAttach = readinput.call('Child pid: ', '-l', str(pidChild))
                if pidAttach.isdigit() and int(pidAttach) > 0 \
                        and int(pidAttach) <= len(pidChild):
                    pidAttach = pidChild[pidAttach]
            sys.stdout.write('Attaching... ')
            sys.stdout.flush()
        self.pid = pidAttach

        # push gdbserver if it's not there
        gdbserverPath = '/data/local/tmp/gdbserver'
        if not adb.pathExists(gdbserverPath):
            adb.push(os.path.join(self.bindir, 'gdbserver'), gdbserverPath)

        # run this after fork() and before exec(gdbserver)
        # so 'adb shell gdbserver' doesn't get gdb's signals
        def gdbserverPreExec():
            os.setpgrp()

        # can we run as root?
        if 'uid=0' in adb.call(['shell', 'id']):
            gdbserverProc = adb.call(['shell',
                    gdbserverPath, '--attach', ':0', pidAttach],
                    stderr=subprocess.PIPE, async=True,
                    preexec_fn=gdbserverPreExec)
        else:
            sys.stdout.write('as non-root... ')
            sys.stdout.flush()
            gdbserverProc = adb.call(['shell', 'run-as', pkg,
                    gdbserverPath, '--attach', ':0', pidAttach],
                    stderr=subprocess.PIPE, async=True,
                    preexec_fn=gdbserverPreExec)

        # we passed ':0' to gdbserver so it'll pick a port for us
        # but that means we have to find the port from stdout
        # while this complicates things a little, it allows us to
        # have multiple gdbservers running
        port = None
        while not port:
            if gdbserverProc.poll() is not None:
                print ''
                print gdbserverProc.stdout.read()
                raise gdb.GdbError('gdbserver exited unexpectedly')
            line = gdbserverProc.stdout.readline().split()
            # kind of hacky, assume the port number comes after 'port'
            if 'port' in line:
                port = line[line.index('port') + 1]

        self.port = port
        self.gdbserver = gdbserverProc

        # collect output from gdbserver in another thread
        def makeGdbserverWait(obj, proc):
            def gdbserverWait():
                obj.gdbserverOut = proc.communicate();
            return gdbserverWait;
        threading.Thread(
                target = makeGdbserverWait(self, gdbserverProc)).start()

        # forward the port that gdbserver gave us
        adb.forward('tcp:' + port, 'tcp:' + port)
        print 'Done'

        sys.stdout.write('Setting up remote debugging... ')
        sys.stdout.flush()
        # load the right file
        gdb.execute('file ' + (PARENT_FILE_PATH
                if pidParent else CHILD_FILE_PATH), False, True)
        gdb.execute('target remote :' + port, False, True)
        print 'Done\n'

        if pidParent:
            print 'Run another gdb session to debug child process.\n'
        print 'Ready. Use "continue" to resume execution.'
示例#8
0
            raise gdb.GdbError(' ADB: no device')
        devs = getDevices()

    # use saved setting if possible; also allows gdbinit to set device
    dev = str(gdb.parameter('adb-device'))
    if dev and dev not in devs:
        print 'feninit.default.device (%s) is not connected' % dev
    # use only device
    if len(devs) == 1:
        dev = devs[0]
    # otherwise, let user decide
    while not dev in devs:
        print 'Found multiple devices:'
        for i in range(len(devs)):
            print '%d. %s' % (i + 1, devs[i])
        dev = readinput.call('Choose device: ', '-l', str(devs))
        if dev.isdigit() and int(dev) > 0 and int(dev) <= len(devs):
            dev = devs[int(dev) - 1]
        elif len(dev) > 0:
            matchDev = filter(lambda x: x.lower().startswith(dev.lower()),
                              devs)
            # if only one match, use it
            if len(matchDev) == 1:
                dev = matchDev[0]
    if str(gdb.parameter('adb-device')) != dev:
        gdb.execute('set adb-device ' + dev)
    return dev


def pull(src, dest):
    params = ['pull']