CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
symbols.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 
3 from __future__ import print_function
4 import networkx as nx
5 import collections
6 import os
7 import re
8 import subprocess
9 
10 addr_re = r"(?P<address>[0-9a-f]{1,16})?"
11 code_re = r"(?P<code>[a-zA-Z])"
12 symbol_re = r"(?P<symbol>[a-zA-Z0-9_.$@]+)"
13 symbol_demunged_re = r"(?P<symbol>[a-zA-Z0-9_.$@:&()<>{}\[\]|^!%,~*+-=# ]+)"
14 symbols_re_skip = re.compile("(@@)")
15 nm_line_re = re.compile(r"\s+".join([addr_re, code_re, symbol_re]) + r"\s*$",
16  re.I)
17 ldd_line_re = re.compile(r"\s+(.*) => (.*) \(0x")
18 
19 requires = collections.defaultdict(set)
20 provides = collections.defaultdict(set)
21 dependencies = collections.defaultdict(set)
22 libraries = collections.defaultdict(set)
23 
24 
25 def get_symbols(fname):
26  lines = subprocess.check_output(["nm", "-g", fname])
27  for line in lines.splitlines():
28  m = nm_line_re.match(line)
29  if not m:
30  continue
31  symbol = m.group('symbol')
32  if m.group('code') == 'U':
33  requires[os.path.basename(fname)].add(symbol)
34  else:
35  provides[symbol].add(os.path.basename(fname))
36 
37 
38 def get_libraries(fname):
39  lines = subprocess.check_output(["ldd", fname])
40  for line in lines.splitlines():
41  m = ldd_line_re.match(line)
42  if not m:
43  continue
44  library = m.group(2)
45  libraries[os.path.basename(fname)].add(
46  os.path.basename(library.rstrip('\r\n')))
47 
48 
49 paths = os.environ['LD_LIBRARY_PATH'].split(':')
50 
51 for p in paths:
52  for dirpath, dirnames, filenames in os.walk(p):
53  for f in filenames:
54  fpth = os.path.realpath(os.path.join(dirpath, f))
55  filetype = subprocess.check_output(["file", fpth])
56  if filetype.find("dynamically linked") >= 0:
57  get_symbols(fpth)
58  get_libraries(fpth)
59 
60 for fname, symbols in requires.items():
61  deps = set()
62  for library in libraries[fname]:
63  for s in symbols:
64  if library in provides[s]:
65  deps.add(library)
66  dependencies[fname] = deps
67  print(fname + ' : primary dependencies : ' +
68  ', '.join(sorted(dependencies[fname]))+'\n')
69  unmet = set()
70  demangled = set()
71  for s in symbols:
72  if s not in provides and not symbols_re_skip.search(s):
73  unmet.add(s)
74  for u in sorted(unmet):
75  dm = subprocess.check_output(["c++filt", u])
76  demangled.add(dm.rstrip('\r\n'))
77  if demangled:
78  print(fname + ': undefined : ' + ', '.join(sorted(demangled)))
79 
80 G = nx.DiGraph()
81 for key, values in dependencies.items():
82  G.add_node(key)
83  for val in values:
84  G.add_edge(key, val)
85 
86 for node in nx.nodes_iter(G):
87  s = nx.dfs_successors(G, node)
88  deps = set()
89  if s:
90  for key, vals in s.items():
91  if key != node:
92  deps.add(key)
93  for v in vals:
94  deps.add(v)
95  print(node + ': primary and secondary dependencies :' + ', '.join(sorted(deps)))
96 
97 
98 H = nx.DiGraph()
99 for key, values in dependencies.items():
100  H.add_node(os.path.basename(key))
101  for val in values:
102  H.add_edge(os.path.basename(key), os.path.basename(val))
103 for node in nx.nodes_iter(H):
104  T = nx.dfs_tree(H, node)
105  name = node + ".dot"
106  nx.write_dot(T, name)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
void add(std::map< std::string, TH1 * > &h, TH1 *hist)
static std::string join(char **cmd)
Definition: RemoteFile.cc:19
def get_symbols
Definition: symbols.py:25
def get_libraries
Definition: symbols.py:38