Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8ce7d62
Move show.py to c_analyzer_common.
ericsnowcurrently Sep 27, 2019
c40c247
Small cleanups around _check_results().
ericsnowcurrently Sep 27, 2019
bf3bd21
Merge c_parser.info into c_analyzer_common.info.
ericsnowcurrently Sep 27, 2019
52113ae
c_symbols.binary -> c_symbols.find.
ericsnowcurrently Sep 27, 2019
dc8333f
Add ID.match().
ericsnowcurrently Sep 30, 2019
9b47596
Add known.look_up_variable().
ericsnowcurrently Sep 30, 2019
67eea78
Add c_parser.find module.
ericsnowcurrently Sep 30, 2019
b61b704
Add c_symbols.find module.
ericsnowcurrently Sep 30, 2019
a041e4a
Avoid variable resolution in _nm.iter_symbols().
ericsnowcurrently Sep 30, 2019
b9b0499
Add c_analyzer_common.find module.
ericsnowcurrently Sep 30, 2019
15b60db
Use the new modules in __main__.
ericsnowcurrently Sep 30, 2019
2f9958f
Drop the old code.
ericsnowcurrently Sep 30, 2019
b05272c
Specify "preprocessed" option as an arg.
ericsnowcurrently Sep 30, 2019
80d299c
Add a TODO.
ericsnowcurrently Sep 30, 2019
15c1226
Use declarations.iter_all() instead of iter_variables().
ericsnowcurrently Sep 30, 2019
e08bad5
Make sure "resolve()" is used properly.
ericsnowcurrently Oct 1, 2019
fa6f1b5
Move extract_storage() to c_parser.declarations.
ericsnowcurrently Oct 4, 2019
6531014
Move the generic code under a top-level c_analyzer package.
ericsnowcurrently Oct 4, 2019
15f010b
Move some code to a new c_analyzer.variables package.
ericsnowcurrently Oct 4, 2019
c399dc0
c_global -> cpython.
ericsnowcurrently Oct 4, 2019
025e8c3
Do not use Variable in symbols or parser packages.
ericsnowcurrently Oct 15, 2019
f60551e
Drop "INCLUDES" from SOURCE_DIRS.
ericsnowcurrently Oct 18, 2019
4beba49
Process files more cleanly.
ericsnowcurrently Oct 18, 2019
9e5c09b
Fix a typo.
ericsnowcurrently Oct 18, 2019
6e14276
Call check_filename() properly.
ericsnowcurrently Oct 18, 2019
0ce0cd1
Fix one last import.
ericsnowcurrently Oct 18, 2019
264d698
Fix whitespace.
ericsnowcurrently Oct 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add c_symbols.find module.
  • Loading branch information
ericsnowcurrently committed Sep 30, 2019
commit b61b704bd2877731e032faa7dd9fb78b9103a022
4 changes: 2 additions & 2 deletions Tools/c-analyzer/c_globals/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def globals_from_binary(binfile=PYTHON, *,
knownvars=None,
dirnames=None,
_iter_symbols=b_symbols.iter_symbols,
_iter_symbols=b_symbols.symbols,
_resolve=resolve.symbols_to_variables,
_get_symbol_resolver=resolve.get_resolver,
):
Expand Down Expand Up @@ -50,7 +50,7 @@ def iter_variables(kind='platform', *,
dirnames=None,
_resolve_symbols=resolve.symbols_to_variables,
_get_symbol_resolver=resolve.get_resolver,
_symbols_from_binary=b_symbols.iter_symbols,
_symbols_from_binary=b_symbols.symbols,
_symbols_from_source=s_symbols.iter_symbols,
_iter_raw=declarations.iter_all,
_iter_preprocessed=declarations.iter_preprocessed,
Expand Down
140 changes: 120 additions & 20 deletions Tools/c-analyzer/c_symbols/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,141 @@
import os.path
import shutil

from c_analyzer_common import PYTHON
from c_analyzer_common import PYTHON, known, files
from c_analyzer_common.info import UNKNOWN, Variable
from c_parser import find as p_find

from . import _nm, source
from . import _nm
from .info import Symbol

# XXX need tests:
# * iter_symbols
# * get_resolver
# * symbol
# * symbols
# * variables


def _resolve_known(symbol, knownvars):
for varid in knownvars:
if symbol.match(varid):
break
else:
return None
return knownvars.pop(varid)


def get_resolver(known=None, dirnames=(), *,
filenames=None,
perfilecache=None,
_iter_files=files.iter_files_by_suffix,
# _look_up_known=known.look_up_variable,
_from_source=p_find.variable_from_id,
):
"""Return a "resolver" func for the given known vars/types and filenames.

The returned func takes a single Symbol and returns a corresponding
Variable. If the symbol was located then the variable will be
valid, populated with the corresponding information. Otherwise None
is returned.
"""
knownvars = (known or {}).get('variables')
if filenames:
filenames = list(filenames)
def check_filename(filename):
return filename in filenames
elif dirnames:
dirnames = [d if d.endswith(os.path.sep) else d + os.path.sep
for d in dirnames]
filenames = list(_iter_files(dirnames, ('.c', '.h')))
def check_filename(filename):
for dirname in dirnames:
if filename.startswith(dirname):
return True
else:
return False

if knownvars:
knownvars = dict(knownvars) # a copy
if filenames:
def resolve(symbol):
# XXX Check "found" instead?
if not check_filename(symbol.filename):
return None
found = _resolve_known(symbol, knownvars)
if found is None:
#return None
found = _from_source(symbol, filenames,
perfilecache=perfilecache,
)
return found
else:
def resolve(symbol):
return _resolve_known(symbol, knownvars)
elif filenames:
def resolve(symbol):
return _from_source(symbol, filenames,
perfilecache=perfilecache,
)
else:
def resolve(symbol):
return None
return resolve


def symbol(symbol, filenames, known=None, *,
perfilecache=None,
_get_resolver=get_resolver,
):
"""Return the Variable matching the given symbol.

"symbol" can be one of several objects:

* Symbol - use the contained info
* name (str) - look for a global variable with that name
* (filename, name) - look for named global in file
* (filename, funcname, name) - look for named local in file

A name is always required. If the filename is None, "", or
"UNKNOWN" then all files will be searched. If the funcname is
"" or "UNKNOWN" then only local variables will be searched for.
"""
resolve = _get_resolver(known, filenames,
perfilecache=perfilecache,
)
return resolve(symbol)


def _get_platform_tool():
if os.name == 'nt':
# XXX Support this.
raise NotImplementedError
elif nm := shutil.which('nm'):
return lambda b, fls: _nm.iter_symbols(b, fls, nm=nm)
return lambda b: _nm.iter_symbols(b, nm=nm)
else:
raise NotImplementedError


def iter_symbols(binfile=PYTHON, dirnames=None, *,
# Alternately, use look_up_known_symbol()
# from c_globals.supported.
find_local_symbol=source.find_symbol,
_file_exists=os.path.exists,
_get_platform_tool=_get_platform_tool,
):
"""Yield a Symbol for each symbol found in the binary."""
def symbols(binfile=PYTHON, *,
_file_exists=os.path.exists,
_get_platform_tool=_get_platform_tool,
):
"""Yield a Symbol for each one found in the binary."""
if not _file_exists(binfile):
raise Exception('executable missing (need to build it first?)')

if find_local_symbol:
cache = {}
def find_local_symbol(name, *, _find=find_local_symbol):
return _find(name, dirnames, _perfilecache=cache)
else:
find_local_symbol = None

_iter_symbols = _get_platform_tool()
yield from _iter_symbols(binfile, find_local_symbol)
yield from _iter_symbols(binfile)


def variables(binfile=PYTHON, *,
resolve=(lambda s: symbol(s, ())),
_iter_symbols=symbols,
):
"""Yield (Variable, Symbol) for each found symbol."""
for symbol in _iter_symbols(binfile):
if symbol.kind != Symbol.KIND.VARIABLE:
continue
var = resolve(symbol)
#if var is None:
# var = Variable(symbol.id, UNKNOWN)
yield var, symbol