Implement logging presets (#445)
* logging template nits * moved logging outside Manticore * naming fix and exposed API call * logging -> log renaming * fix for verbosity test * restored setter/getter for verbosity * fixes for warnings in 0 mode and exteneed test_cli_verbosity * removed print * relative import, fork message to executor, init function * verbosity docstring fix * docstring nit
This commit is contained in:
parent
1d8e051522
commit
09bb702fac
@ -70,7 +70,6 @@ def main():
|
||||
args = parse_arguments()
|
||||
|
||||
m = Manticore(args.programs[0], args.programs[1:])
|
||||
|
||||
m.policy = args.policy
|
||||
m.args = args
|
||||
|
||||
|
||||
@ -315,6 +315,10 @@ class Executor(Eventful):
|
||||
#Find a set of solutions for expression
|
||||
solutions = state.concretize(expression, policy)
|
||||
|
||||
logger.info("Forking, about to store. (policy: %s, values: %s)",
|
||||
policy,
|
||||
', '.join('0x{:x}'.format(sol) for sol in solutions))
|
||||
|
||||
self.publish('will_fork_state', state, expression, solutions, policy)
|
||||
|
||||
#Build and enqueue a state for each solution
|
||||
@ -334,7 +338,7 @@ class Executor(Eventful):
|
||||
#maintain a list of childres for logging purpose
|
||||
children.append(state_id)
|
||||
|
||||
logger.debug("Forking current state into states %r",children)
|
||||
logger.debug("Forking current state into states %r", children)
|
||||
return None
|
||||
|
||||
def run(self):
|
||||
|
||||
@ -24,10 +24,10 @@ from .core.smtlib import solver, ConstraintSet
|
||||
from .platforms import linux, decree, windows
|
||||
from .utils.helpers import issymbolic
|
||||
from .utils.nointerrupt import WithKeyboardInterruptAs
|
||||
from .utils import log
|
||||
|
||||
logger = logging.getLogger('MANTICORE')
|
||||
|
||||
|
||||
def makeDecree(program, concrete_data=''):
|
||||
constraints = ConstraintSet()
|
||||
platform = decree.SDecree(constraints, program)
|
||||
@ -131,6 +131,7 @@ def binary_type(path):
|
||||
else:
|
||||
raise NotImplementedError("Binary {} not supported. Magic bytes: 0x{}".format(path, binascii.hexlify(magic)))
|
||||
|
||||
|
||||
class Manticore(object):
|
||||
'''
|
||||
The central analysis object.
|
||||
@ -170,7 +171,6 @@ class Manticore(object):
|
||||
self._dumpafter = 0
|
||||
self._maxstates = 0
|
||||
self._maxstorage = 0
|
||||
self._verbosity = 0
|
||||
self._symbolic_files = [] # list of string
|
||||
self._executor = None
|
||||
#Executor wide shared context
|
||||
@ -181,7 +181,7 @@ class Manticore(object):
|
||||
if self._binary_type == 'ELF':
|
||||
self._binary_obj = ELFFile(file(self._binary))
|
||||
|
||||
self._init_logging()
|
||||
log.init_logging()
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
@ -220,30 +220,6 @@ class Manticore(object):
|
||||
yield ctx
|
||||
context[key] = ctx
|
||||
|
||||
def _init_logging(self):
|
||||
|
||||
def loggerSetState(logger, stateid):
|
||||
logger.filters[0].stateid = stateid
|
||||
|
||||
class ContextFilter(logging.Filter):
|
||||
'''
|
||||
This is a filter which injects contextual information into the log.
|
||||
'''
|
||||
def filter(self, record):
|
||||
if hasattr(self, 'stateid') and isinstance(self.stateid, int):
|
||||
record.stateid = '[%d]' % self.stateid
|
||||
else:
|
||||
record.stateid = ''
|
||||
return True
|
||||
|
||||
ctxfilter = ContextFilter()
|
||||
|
||||
logging.basicConfig(format='%(asctime)s: [%(process)d]%(stateid)s %(name)s:%(levelname)s: %(message)s', stream=sys.stdout, level=logging.ERROR)
|
||||
|
||||
for loggername in ['MANTICORE', 'VISITOR', 'EXECUTOR', 'CPU', 'REGISTERS', 'SMT', 'MEMORY', 'PLATFORM']:
|
||||
logging.getLogger(loggername).addFilter(ctxfilter)
|
||||
logging.getLogger(loggername).setState = types.MethodType(loggerSetState, logging.getLogger(loggername))
|
||||
|
||||
# XXX(yan): args is a temporary hack to include while we continue moving
|
||||
# non-Linux platforms to new-style arg handling.
|
||||
@property
|
||||
@ -290,40 +266,23 @@ class Manticore(object):
|
||||
def maxstorage(self):
|
||||
return self._maxstorage
|
||||
|
||||
@maxstorage.setter
|
||||
def maxstorage(self, max_storage):
|
||||
self._maxstorage = max_storage
|
||||
|
||||
@property
|
||||
def verbosity(self):
|
||||
'''
|
||||
Convenience interface for setting logging verbosity to one of several predefined
|
||||
logging presets. Valid values: 0-5
|
||||
'''
|
||||
return self._verbosity
|
||||
"""Convenience interface for setting logging verbosity to one of
|
||||
several predefined logging presets. Valid values: 0-5.
|
||||
"""
|
||||
return log.manticore_verbosity
|
||||
|
||||
@verbosity.setter
|
||||
def verbosity(self, setting):
|
||||
zero = map(lambda x: (x, logging.ERROR),
|
||||
['MANTICORE', 'VISITOR', 'EXECUTOR', 'CPU', 'REGISTERS', 'SMT', 'MEMORY', 'PLATFORM'])
|
||||
levels = [zero,
|
||||
[('MANTICORE', logging.INFO), ('EXECUTOR', logging.INFO)],
|
||||
[('PLATFORM', logging.DEBUG)],
|
||||
[('MEMORY', logging.DEBUG), ('CPU', logging.DEBUG)],
|
||||
[('REGISTERS', logging.DEBUG)],
|
||||
[('SMT', logging.DEBUG)]]
|
||||
"""A call used to modify the level of output verbosity
|
||||
:param int setting: the level of verbosity to be used
|
||||
"""
|
||||
log.set_verbosity(setting)
|
||||
|
||||
# Takes a value and ensures it's in a certain range
|
||||
def clamp(val, minimum, maximum):
|
||||
return sorted((minimum, val, maximum))[1]
|
||||
|
||||
clamped = clamp(setting, 0, len(levels) - 1)
|
||||
if clamped != setting:
|
||||
logger.debug("%s not between 0 and %d, forcing to %d", setting, len(levels) - 1, clamped)
|
||||
for level in range(clamped + 1):
|
||||
for log_type, log_level in levels[level]:
|
||||
logging.getLogger(log_type).setLevel(log_level)
|
||||
self._verbosity = clamped
|
||||
@maxstorage.setter
|
||||
def maxstorage(self, max_storage):
|
||||
self._maxstorage = max_storage
|
||||
|
||||
def hook(self, pc):
|
||||
'''
|
||||
@ -552,7 +511,7 @@ class Manticore(object):
|
||||
|
||||
def _terminate_state_callback(self, state, state_id, ex):
|
||||
#aggregates state statistics into exceutor statistics. FIXME split
|
||||
logger.info("Terminate state %r %r ", state, state_id)
|
||||
logger.debug("Terminate state %r %r ", state, state_id)
|
||||
if state is None:
|
||||
return
|
||||
state_visited = state.context.get('visited_since_last_fork', set())
|
||||
@ -574,9 +533,6 @@ class Manticore(object):
|
||||
manticore_context['visited'] = manticore_visited.union(state_visited)
|
||||
state.context['visited_since_last_fork'] = set()
|
||||
|
||||
logger.info("Forking, about to store. (policy: %s, values: %s)", policy,
|
||||
', '.join('0x{:x}'.format(pc) for pc in values))
|
||||
|
||||
def _read_register_callback(self, state, reg_name, value):
|
||||
logger.debug("Read Register %r %r", reg_name, value)
|
||||
|
||||
@ -706,7 +662,6 @@ class Manticore(object):
|
||||
ws_path = None
|
||||
|
||||
self._output = ManticoreOutput(ws_path)
|
||||
|
||||
self._executor = Executor(initial_state,
|
||||
workspace=self._output.descriptor,
|
||||
policy=self._policy,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
import logging
|
||||
import inspect
|
||||
|
||||
|
||||
80
manticore/utils/log.py
Normal file
80
manticore/utils/log.py
Normal file
@ -0,0 +1,80 @@
|
||||
import logging
|
||||
import sys
|
||||
import types
|
||||
|
||||
class ContextFilter(logging.Filter):
|
||||
'''
|
||||
This is a filter which injects contextual information into the log.
|
||||
'''
|
||||
def filter(self, record):
|
||||
if hasattr(self, 'stateid') and isinstance(self.stateid, int):
|
||||
record.stateid = '[%d]' % self.stateid
|
||||
else:
|
||||
record.stateid = ''
|
||||
return True
|
||||
|
||||
loggers = ['MANTICORE',
|
||||
'VISITOR',
|
||||
'EXECUTOR',
|
||||
'CPU',
|
||||
'REGISTERS',
|
||||
'SMT',
|
||||
'MEMORY',
|
||||
'PLATFORM']
|
||||
manticore_verbosity = 0
|
||||
|
||||
def init_logging():
|
||||
ctxfilter = ContextFilter()
|
||||
logfmt = ("%(asctime)s: [%(process)d]%(stateid)s %(name)s:%(levelname)s:"
|
||||
" %(message)s")
|
||||
logging.basicConfig(format=logfmt, stream=sys.stdout, level=logging.ERROR)
|
||||
for l in loggers:
|
||||
logging.getLogger(l).setLevel(logging.WARNING)
|
||||
logging.getLogger(l).addFilter(ctxfilter)
|
||||
logging.getLogger(l).setState = types.MethodType(loggerSetState,
|
||||
logging.getLogger(l))
|
||||
|
||||
def loggerSetState(logger, stateid):
|
||||
logger.filters[0].stateid = stateid
|
||||
|
||||
def set_verbosity(setting):
|
||||
global manticore_verbosity
|
||||
zero = map(lambda x: (x, logging.WARNING), loggers)
|
||||
levels = [
|
||||
# 0
|
||||
zero,
|
||||
# 1
|
||||
[
|
||||
('MANTICORE', logging.INFO)
|
||||
],
|
||||
# 2 (-v)
|
||||
[
|
||||
('EXECUTOR', logging.INFO),
|
||||
('PLATFORM', logging.DEBUG)
|
||||
],
|
||||
# 3 (-vv)
|
||||
[
|
||||
('CPU', logging.DEBUG)
|
||||
],
|
||||
# 4 (-vvv)
|
||||
[
|
||||
('MEMORY', logging.DEBUG),
|
||||
('CPU', logging.DEBUG),
|
||||
('REGISTERS', logging.DEBUG)
|
||||
],
|
||||
# 5 (-vvvv)
|
||||
[
|
||||
('MANTICORE', logging.DEBUG),
|
||||
('SMT', logging.DEBUG)
|
||||
]
|
||||
]
|
||||
|
||||
# Takes a value and ensures it's in a certain range
|
||||
def clamp(val, minimum, maximum):
|
||||
return sorted((minimum, val, maximum))[1]
|
||||
|
||||
clamped = clamp(setting, 0, len(levels) - 1)
|
||||
for level in range(clamped + 1):
|
||||
for log_type, log_level in levels[level]:
|
||||
logging.getLogger(log_type).setLevel(log_level)
|
||||
manticore_verbosity = clamped
|
||||
@ -72,7 +72,13 @@ class IntegrationTest(unittest.TestCase):
|
||||
dirname = os.path.dirname(__file__)
|
||||
filename = os.path.join(dirname, 'binaries/basic_linux_amd64')
|
||||
output = subprocess.check_output(['python', '-m', 'manticore', filename])
|
||||
self.assertLessEqual(len(output.splitlines()), 25)
|
||||
self.assertLessEqual(len(output.splitlines()), 60)
|
||||
output = subprocess.check_output(['python', '-m', 'manticore', filename, "-v"])
|
||||
self.assertLessEqual(len(output.splitlines()), 80)
|
||||
output = subprocess.check_output(['python', '-m', 'manticore', filename, "-vvv"])
|
||||
self.assertGreaterEqual(len(output.splitlines()), 435000)
|
||||
output = subprocess.check_output(['python', '-m', 'manticore', filename, "-vvvv"])
|
||||
self.assertGreaterEqual(len(output.splitlines()), 950000)
|
||||
|
||||
def testArgumentsAssertions(self):
|
||||
dirname = os.path.dirname(__file__)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user