1 from collections
import defaultdict
7 from constants
import (
13 hardcode_syscall_read_fields
,
14 hardcode_syscall_write_fields
,
20 impl_dep_file_str
=IMPL_DEP_FILE_STR
,
21 output_file_str
=OUTPUT_FILE_STR
,
26 self
.impl_dep_file
= file(impl_dep_file_str
, 'r')
27 self
.output_file
= file(output_file_str
+ '.json', 'w+')
29 self
.output_file_verbose
= file(output_file_str
+ '_verbose.json', 'w+')
31 self
.pretty_output_file
= file(output_file_str
+ '.pretty', 'w+')
32 self
.pretty_output_file_verbose
= file(output_file_str
+ '_verbose.pretty', 'w+')
34 sys
.stderr
.write("ERROR: Cannot open files %s %s.\n" % (impl_dep_file_str
, output_file_str
))
36 self
.verbose
= verbose
38 self
.syscall_read_fields
= defaultdict(set)
39 self
.syscall_write_fields
= defaultdict(set)
40 self
.implicit_dependencies
= defaultdict(set)
41 self
.verbose_impl_dep
= defaultdict(list)
42 self
.deref_counter
= defaultdict(int) # count which struct->members are most common
44 for syscall
,fields
in hardcode_syscall_read_fields
.iteritems():
45 self
.syscall_read_fields
[syscall
].update(set(fields
))
47 for syscall
,fields
in hardcode_syscall_write_fields
.iteritems():
48 self
.syscall_write_fields
[syscall
].update(set(fields
))
50 def _sanitize_syscall(self
, syscall
):
51 for prefix
in SYSCALL_PREFIXES
:
52 if syscall
.startswith(prefix
):
53 return syscall
[len(prefix
):]
56 def _deref_to_tuple(self
, deref
):
57 """ (struct a)->b ==> (a,b) """
58 struct
, member
= deref
.split('->')
59 struct
= struct
[1:-1] # strip parens
60 struct
= struct
.split(' ')[1] # drop struct keyword
61 return (struct
, member
)
63 def _split_field(self
, field
):
65 field
= field
[1: -1] # strip square brackets
66 derefs
= [struct
.strip() for struct
in field
.strip().split(',') if struct
]
68 lambda deref
: self
._deref
_to
_tuple
(deref
),
72 def _sanitize_line(self
, line
):
73 syscall_and_listtype
, field
= line
.split(':')
74 syscall
, list_type
= syscall_and_listtype
.split(' ')
75 syscall
= self
._sanitize
_syscall
(syscall
)
76 derefs
= self
._split
_field
(field
)
77 return syscall
, list_type
, derefs
79 def _add_fields(self
, syscall
, list_type
, derefs
):
80 if list_type
== ListType
.READ
:
81 d
= self
.syscall_read_fields
82 elif list_type
== ListType
.WRITE
:
83 d
= self
.syscall_write_fields
85 if deref
in GLOBAL_BLACKLIST
: # ignore spammy structs
89 def _construct_implicit_deps(self
):
90 """ just do a naive O(n^2) loop to see intersections between write_list and read_list """
91 for this_call
,read_fields
in self
.syscall_read_fields
.iteritems():
92 for that_call
,write_fields
in self
.syscall_write_fields
.iteritems():
93 if that_call
== this_call
: # calls are obviously dependent on themselves. ignore.
95 intersection
= read_fields
& write_fields
97 self
.implicit_dependencies
[this_call
].add(that_call
)
98 if intersection
and self
.verbose
:
99 self
.verbose_impl_dep
[this_call
].append({
101 'reason': intersection
,
103 for deref
in intersection
:
104 self
.deref_counter
[deref
] += 1
107 for line
in self
.impl_dep_file
:
108 syscall
, list_type
, derefs
= self
._sanitize
_line
(line
)
109 self
._add
_fields
(syscall
, list_type
, derefs
)
110 # pprint.pprint(dict(self.syscall_write_fields))
111 # pprint.pprint(dict(self.syscall_read_fields))
112 self
._construct
_implicit
_deps
()
113 # pprint.pprint(dict(self.implicit_dependencies))
114 # pprint.pprint(dict(self.verbose_impl_dep))
116 def _listify_verbose_reason(self
, reason
):
117 r
= copy
.deepcopy(reason
)
118 r
['reason'] = list(r
['reason'])
120 lambda (struct
,field
): struct
+ '->' + field
,
125 def _get_json_dependencies(self
):
126 implicit_dependencies
= {}
127 verbose_impl_dep
= {}
128 for call
, dep_set
in self
.implicit_dependencies
.iteritems():
129 implicit_dependencies
[call
] = list(dep_set
)
130 for call
, call_reasons
in self
.verbose_impl_dep
.iteritems():
131 verbose_impl_dep
[call
] = map(
132 lambda reason
: self
._listify
_verbose
_reason
(reason
),
135 return implicit_dependencies
, verbose_impl_dep
138 implicit_dependencies
, verbose_impl_dep
= self
._get
_json
_dependencies
()
139 json
.dump(implicit_dependencies
, self
.output_file
)
141 json
.dump(verbose_impl_dep
, self
.output_file_verbose
)
143 pprint
.pprint(dict(self
.implicit_dependencies
), self
.pretty_output_file
)
144 pprint
.pprint(dict(self
.verbose_impl_dep
), self
.pretty_output_file_verbose
)
145 for deref
, count
in sorted(self
.deref_counter
.iteritems(), key
=lambda (k
,v
): (v
,k
)):
146 print "%s: %d" % (deref
, count
)
149 self
.output_file
.close()
150 self
.impl_dep_file
.close()
152 self
.output_file_verbose
.close()