Beispiel #1
0
    def __init__(self, s):
        cmd.Cmd.__init__(self)

        self.s = s
        self.prompt_default = '> '
        self.prompt = self.prompt_default
        self.ruler = ''

        # Start the socket read loop, responses and events will come in
        self.callbacks = UniqueDict({'_lock': threading.Lock()})
        # Also maintain a list of event subscribers
        self.event_listeners = {'_lock': threading.Lock()}
        self.event_listeners.update(
            {k: {}
             for k in EventKindConstants.keys() if isinstance(k, int)})
        # Maintain a deferred packet list and init state
        self.initted = False
        self.deferred = []

        self.active = True
        self.reader = threading.Thread(target=self.poll)
        self.reader.start()

        self.vm = jdwp.misc.VM()
        self.init_vm_info()  # Get some data
Beispiel #2
0
	def __init__( self, s ):
		cmd.Cmd.__init__( self )

		self.s = s
		self.prompt_default = '> '
		self.prompt = self.prompt_default
		self.ruler = ''

		# Start the socket read loop, responses and events will come in
		self.callbacks = UniqueDict( { '_lock': threading.Lock() } )
		# Also maintain a list of event subscribers
		self.event_listeners = { '_lock': threading.Lock() }
		self.event_listeners.update( { k: {} for k in EventKindConstants.keys() if isinstance( k, int ) } )
		# Maintain a deferred packet list and init state
		self.initted = False
		self.deferred = []

		self.active = True
		self.reader = threading.Thread( target=self.poll )
		self.reader.start()

		self.vm = jdwp.misc.VM()
		self.init_vm_info() # Get some data
Beispiel #3
0
class PyJDBCmd(cmd.Cmd):
    """The main debugging command line"""
    def __init__(self, s):
        cmd.Cmd.__init__(self)

        self.s = s
        self.prompt_default = '> '
        self.prompt = self.prompt_default
        self.ruler = ''

        # Start the socket read loop, responses and events will come in
        self.callbacks = UniqueDict({'_lock': threading.Lock()})
        # Also maintain a list of event subscribers
        self.event_listeners = {'_lock': threading.Lock()}
        self.event_listeners.update(
            {k: {}
             for k in EventKindConstants.keys() if isinstance(k, int)})
        # Maintain a deferred packet list and init state
        self.initted = False
        self.deferred = []

        self.active = True
        self.reader = threading.Thread(target=self.poll)
        self.reader.start()

        self.vm = jdwp.misc.VM()
        self.init_vm_info()  # Get some data

    def init_vm_info(self):
        """Initializes target VM information"""
        from jdwp.commands.virtualmachine import VersionCommand
        from jdwp.responses.virtualmachine import VersionResponse

        def set_vm_version(self, data):
            response = VersionResponse(data)
            self.vm.description = response.description
            self.vm.name = response.vm_name
            self.vm.jdwp = response.jdwp
            self.vm.version = response.vm_version

        command = VersionCommand()
        with self.callbacks['_lock']:
            self.callbacks[command.id] = set_vm_version
        self.s.send(command.assemble())

        from jdwp.commands.virtualmachine import IDSizesCommand
        from jdwp.responses.virtualmachine import IDSizesResponse

        def set_vm_sizes(self, data):
            response = IDSizesResponse(data)
            self.vm.field_size = response.field
            self.vm.method_size = response.method
            self.vm.object_size = response.object
            self.vm.reference_size = response.reference
            self.vm.frame = response.frame

            self.initted = True
            for packet in self.deferred:
                self.received(packet)
                self.deferred = []

        command = IDSizesCommand()
        with self.callbacks['_lock']:
            self.callbacks[command.id] = set_vm_sizes
        self.s.send(command.assemble())

    def lock(self):
        self.prompt = ''

    def unlock(self):
        self.prompt = self.prompt_default
        sys.stdout.write(self.prompt_default)
        sys.stdout.flush()

    def onecmd(self, line):
        try:
            return cmd.Cmd.onecmd(self, line)
        except Exception as e:
            traceback.print_exc()

    def poll(self):
        while self.active:
            # Read thread
            try:
                if not self.s in select.select([self.s], [], [], 0.25)[0]:
                    continue
            except Exception:
                self.active = False
                continue  # Socket has gone away

            length = self.s.recv(4)  # When we don't know how much to read
            remaining = struct.unpack('>I', length)[0] - 4  # 4 byte header
            data = ''
            while remaining:  # Munch up all the data
                _buffer = self.s.recv(remaining)
                remaining = remaining - len(_buffer)
                data = data + _buffer
            data = length + data  # Reconstruct as plain string

            try:
                self.received(data)
            except Exception as e:  # A JDWP Exception
                traceback.print_exc()
                self.unlock()

    def received(self, data):
        response_id = struct.unpack('>I', data[4:8])[0]  # Get the ID
        if not response_id:
            if not self.initted:
                self.deferred.append(data)
                return  # Take care of later, we have not initialized yet
                # ...in particular, we require VM IDSizes

            # This is assumed to be an automatically generated Event
            # all Events are delivered inside a CompositeEvent packet
            from jdwp.events import CompositeEvent
            composite = CompositeEvent(data, self.vm)
            for event in composite.events:
                self.lock()
                print '* received EventType.%s' % EventKindConstants[
                    event.kind]
                self.unlock()
                for listener in self.event_listeners[event.kind]:
                    listener(event)  # Notify all listeners for this event kind
            return
        with self.callbacks['_lock']:
            callback = self.callbacks.get(response_id, None)
            if callback:
                del self.callbacks[response_id]  # Pop it off
        if callback:
            if isinstance(callback, tuple):
                callback[0](self, data, **callback[1])
            else:
                callback(self, data)

    def default(self, line):
        if line == 'EOF': return self.do_exit(line)

        print 'Unrecognized command: \'%s\'. Try help...' % line

    def do_version(self, args):
        """Print version information"""
        print '%s (%s)\nJDWP %d.%d; JRE %s' % \
         ( self.vm.description, self.vm.name,
         self.vm.jdwp[0], self.vm.jdwp[1], self.vm.version )

    def do_classes(self, args):
        """List currently known classes, takes an optional filter argument"""

        from jdwp.commands.virtualmachine import AllClassesWithGenericCommand
        from jdwp.responses.virtualmachine import AllClassesWithGenericResponse

        def print_classes(self, data, args=None):
            response = AllClassesWithGenericResponse(data, self.vm)

            for classname in sorted(
                [str(classname) for classname in response.classes]):
                if not args or args in classname:
                    print classname  # Filter things out

            self.unlock()

        command = AllClassesWithGenericCommand()
        with self.callbacks['_lock']:
            self.callbacks[command.id] = (print_classes, {'args': args})
        self.lock()
        self.s.send(command.assemble())

    def do_threads(self, args):
        """List threads, optionally filtered by threadgroup"""

        from jdwp.commands.virtualmachine import AllThreadsCommand
        from jdwp.responses.virtualmachine import AllThreadsResponse

        from jdwp.misc import JavaThread
        threads = []
        threads_to_process = []
        release_lock = threading.Lock()

        from jdwp.commands.threadreference import NameCommand
        from jdwp.responses.threadreference import NameResponse
        from jdwp.commands.threadreference import StatusCommand
        from jdwp.responses.threadreference import StatusResponse

        from jdwp.misc import ThreadStatusConstants

        def print_threads(self, data, args=None):
            response = AllThreadsResponse(data, self.vm)
            with release_lock:
                threads_to_process.extend(response.ids)

            # Retrieve all thread data available for each thread
            for thread_id in response.ids:
                thread = JavaThread(thread_id)

                command = NameCommand(thread.id, self.vm)
                with self.callbacks['_lock']:
                    self.callbacks[command.id] = (get_thread_name, {
                        'thread': thread
                    })
                self.s.send(command.assemble())

        def get_thread_name(self, data, thread):
            response = NameResponse(data)
            thread.name = response.name

            command = StatusCommand(thread.id, self.vm)
            with self.callbacks['_lock']:
                self.callbacks[command.id] = (get_thread_status, {
                    'thread': thread
                })
            self.s.send(command.assemble())

        def get_thread_status(self, data, thread):
            response = StatusResponse(data)
            thread.status = response.status

            # When all has been acquired
            with release_lock:
                threads.append(thread)
                threads_to_process.pop(
                )  # Decrease the number of threads to process
                if not len(threads_to_process):
                    for thread in threads:
                        status = ThreadStatusConstants.get(
                            thread.status, 'unknown')
                        print '%s ( %s ) %s' % (thread.name, hex(
                            thread.id)[:-1], status)
                    self.unlock()

        command = AllThreadsCommand()
        with self.callbacks['_lock']:
            self.callbacks[command.id] = (print_threads, {'args': args})
        self.lock()
        self.s.send(command.assemble())

    def do_exit(self, args):
        """Exit debugger"""
        self.active = False
        self.reader.join()
        return True  # Stop

    def do_quit(self, args):
        """Exit debugger"""
        return self.do_exit(args)

    def help_help(self):
        print '...uhm, really?'
Beispiel #4
0
 def __init__(self, columns):
     """Initializes Columns instance with names and data types."""
     self.__column_index = 1
     self.__column_names = UniqueDict()
     for name, data_type in columns:
         self.add(name, data_type)
Beispiel #5
0
class _Columns:
    """_Columns(columns) -> _Columns"""

    __slots__ = slots("column_index column_names")

    def __init__(self, columns):
        """Initializes Columns instance with names and data types."""
        self.__column_index = 1
        self.__column_names = UniqueDict()
        for name, data_type in columns:
            self.add(name, data_type)

    def __contains__(self, name):
        """Checks if the named column already exists."""
        return name in self.__column_names

    def __len__(self):
        """Returns the number of columns recognizes."""
        return len(self.__column_names)

    def __iter__(self):
        """Iterates over columns in sorted order."""
        cache = []
        for name, (data_type, index) in self.__column_names.items():
            cache.append((index, name, data_type))
        for item in sorted(cache):
            yield item

    def __getitem__(self, name):
        """Returns requested information on the given column name."""
        return self.__column_names[name]

    def __getstate__(self):
        """Provides support for class instances to be pickled."""
        return self.__column_index, self.__column_names

    def __setstate__(self, state):
        """Sets the state while object in being unpickled."""
        self.__column_index, self.__column_names = state

    def copy(self):
        """Creates a copy of the known columns."""
        copy = type(self)([])
        copy.__column_index = self.__column_index
        copy.__column_names = self.__column_names.copy()
        return copy

    def add(self, name, data_type):
        """Adds a column name with data type and assigns an index."""
        index = self.__column_index
        self.__column_names[name] = data_type, index
        self.__column_index += 1
        return index

    def drop(self, name):
        """Removes all information regarding the named column."""
        index = self.__column_names[name][1]
        del self.__column_names[name]
        return index

    def alter(self, name, data_type):
        """Changes the data type of the named column."""
        index = self.__column_names[name][1]
        self.__column_names.replace(name, (data_type, index))
        return index

    def rename(self, old, new):
        """Renames a column from old name to new name."""
        self.__column_names[new] = self.__column_names[old]
        del self.__column_names[old]
Beispiel #6
0
class PyJDBCmd( cmd.Cmd ):
	"""The main debugging command line"""

	def __init__( self, s ):
		cmd.Cmd.__init__( self )

		self.s = s
		self.prompt_default = '> '
		self.prompt = self.prompt_default
		self.ruler = ''

		# Start the socket read loop, responses and events will come in
		self.callbacks = UniqueDict( { '_lock': threading.Lock() } )
		# Also maintain a list of event subscribers
		self.event_listeners = { '_lock': threading.Lock() }
		self.event_listeners.update( { k: {} for k in EventKindConstants.keys() if isinstance( k, int ) } )
		# Maintain a deferred packet list and init state
		self.initted = False
		self.deferred = []

		self.active = True
		self.reader = threading.Thread( target=self.poll )
		self.reader.start()

		self.vm = jdwp.misc.VM()
		self.init_vm_info() # Get some data

	def init_vm_info( self ):
		"""Initializes target VM information"""
		from jdwp.commands.virtualmachine import VersionCommand
		from jdwp.responses.virtualmachine import VersionResponse

		def set_vm_version( self, data ):
			response = VersionResponse( data )	
			self.vm.description = response.description
			self.vm.name = response.vm_name
			self.vm.jdwp = response.jdwp
			self.vm.version = response.vm_version

		command = VersionCommand()
		with self.callbacks['_lock']:
			self.callbacks[command.id] = set_vm_version
		self.s.send( command.assemble() )

		from jdwp.commands.virtualmachine import IDSizesCommand
		from jdwp.responses.virtualmachine import IDSizesResponse
		
		def set_vm_sizes( self, data ):
			response = IDSizesResponse( data )
			self.vm.field_size = response.field
			self.vm.method_size = response.method
			self.vm.object_size = response.object
			self.vm.reference_size = response.reference
			self.vm.frame = response.frame

			self.initted = True
			for packet in self.deferred:
				self.received( packet )
				self.deferred = []

		command = IDSizesCommand()
		with self.callbacks['_lock']:
			self.callbacks[command.id] = set_vm_sizes
		self.s.send( command.assemble() )
	
	def lock( self ):
		self.prompt = ''

	def unlock( self ):	
		self.prompt = self.prompt_default
		sys.stdout.write( self.prompt_default )
		sys.stdout.flush()
	
	def onecmd( self, line ):
		try:
			return cmd.Cmd.onecmd( self, line )
		except Exception as e:
			traceback.print_exc()

	def poll( self ):
		while self.active:
			# Read thread
			try:
				if not self.s in select.select( [ self.s ], [], [], 0.25 )[0]:
					continue
			except Exception:	
				self.active = False
				continue # Socket has gone away

			length = self.s.recv( 4 ) # When we don't know how much to read
			remaining = struct.unpack( '>I', length )[0] - 4 # 4 byte header
			data = ''
			while remaining: # Munch up all the data
				_buffer = self.s.recv( remaining )
				remaining = remaining - len( _buffer )
				data = data + _buffer
			data = length + data # Reconstruct as plain string

			try:
				self.received( data )
			except Exception as e: # A JDWP Exception
				traceback.print_exc()
				self.unlock()

	def received( self, data ):
		response_id = struct.unpack( '>I', data[4:8] )[0] # Get the ID
		if not response_id:
			if not self.initted:
				self.deferred.append( data )
				return # Take care of later, we have not initialized yet
				# ...in particular, we require VM IDSizes

			# This is assumed to be an automatically generated Event
			# all Events are delivered inside a CompositeEvent packet
			from jdwp.events import CompositeEvent
			composite = CompositeEvent( data, self.vm )
			for event in composite.events:
				self.lock()
				print '* received EventType.%s' % EventKindConstants[event.kind]
				self.unlock()
				for listener in self.event_listeners[ event.kind ]:
					listener( event ) # Notify all listeners for this event kind
			return
		with self.callbacks['_lock']:
			callback = self.callbacks.get( response_id, None )
			if callback:
				del self.callbacks[response_id] # Pop it off
		if callback:
			if isinstance( callback, tuple ):
				callback[0]( self, data, **callback[1] )
			else:
				callback( self, data )

	def default( self, line ):
		if line == 'EOF': return self.do_exit( line )

		print 'Unrecognized command: \'%s\'. Try help...' % line

	def do_version( self, args ):
		"""Print version information"""
		print '%s (%s)\nJDWP %d.%d; JRE %s' % \
			( self.vm.description, self.vm.name,
			self.vm.jdwp[0], self.vm.jdwp[1], self.vm.version )

	def do_classes( self, args ):
		"""List currently known classes, takes an optional filter argument"""

		from jdwp.commands.virtualmachine import AllClassesWithGenericCommand
		from jdwp.responses.virtualmachine import AllClassesWithGenericResponse

		def print_classes( self, data, args=None ):
			response = AllClassesWithGenericResponse( data, self.vm )

			for classname in sorted( [ str( classname ) for classname in response.classes ] ):
				if not args or args in classname:
					print classname # Filter things out

			self.unlock()

		command = AllClassesWithGenericCommand()
		with self.callbacks['_lock']:
			self.callbacks[command.id] = ( print_classes, { 'args': args } )
		self.lock()
		self.s.send( command.assemble() )
	
	def do_threads( self, args ):
		"""List threads, optionally filtered by threadgroup"""

		from jdwp.commands.virtualmachine import AllThreadsCommand
		from jdwp.responses.virtualmachine import AllThreadsResponse

		from jdwp.misc import JavaThread
		threads = []
		threads_to_process = []
		release_lock = threading.Lock()

		from jdwp.commands.threadreference import NameCommand
		from jdwp.responses.threadreference import NameResponse
		from jdwp.commands.threadreference import StatusCommand
		from jdwp.responses.threadreference import StatusResponse

		from jdwp.misc import ThreadStatusConstants

		def print_threads( self, data, args=None ):
			response = AllThreadsResponse( data, self.vm )
			with release_lock:
				threads_to_process.extend( response.ids )

			# Retrieve all thread data available for each thread
			for thread_id in response.ids:
				thread = JavaThread( thread_id )

				command = NameCommand( thread.id, self.vm )
				with self.callbacks['_lock']:
					self.callbacks[command.id] = ( get_thread_name, { 'thread': thread } )
				self.s.send( command.assemble() )
			
		def get_thread_name( self, data, thread ):
			response = NameResponse( data )
			thread.name = response.name

			command = StatusCommand( thread.id, self.vm )
			with self.callbacks['_lock']:
				self.callbacks[command.id] = ( get_thread_status, { 'thread': thread } )
			self.s.send( command.assemble() )

		def get_thread_status( self, data, thread ):
			response = StatusResponse( data )
			thread.status = response.status
		
			# When all has been acquired
			with release_lock:
				threads.append( thread )
				threads_to_process.pop() # Decrease the number of threads to process
				if not len( threads_to_process ):
					for thread in threads:
						status = ThreadStatusConstants.get( thread.status, 'unknown' )
						print '%s ( %s ) %s' % ( thread.name, hex( thread.id )[:-1], status )
					self.unlock()

		command = AllThreadsCommand()
		with self.callbacks['_lock']:
			self.callbacks[command.id] = ( print_threads, { 'args': args } )
		self.lock()
		self.s.send( command.assemble() )

	def do_exit( self, args ):
		"""Exit debugger"""
		self.active = False
		self.reader.join()
		return True # Stop
	def do_quit( self, args ):
		"""Exit debugger"""
		return self.do_exit( args )

	def help_help( self ):
		print '...uhm, really?'