Merge changes Ie9fa31da,I32d0d54f
am: e652b75dc4
Change-Id: Ied2b3e94922367c19a5b10d51eb10d50c84f31dd
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
let document;
|
let document;
|
||||||
let strsData, mods, tagIds;
|
let strsData, mods, tagIds;
|
||||||
let domPathInput;
|
let domPathInput, domFuzzyMatch;
|
||||||
let domTBody;
|
let domTBody;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
@@ -279,6 +279,16 @@
|
|||||||
domBtn.value = 'Add';
|
domBtn.value = 'Add';
|
||||||
domForm.appendChild(domBtn);
|
domForm.appendChild(domBtn);
|
||||||
|
|
||||||
|
domFuzzyMatch = domNewElem('input');
|
||||||
|
domFuzzyMatch.setAttribute('id', 'fuzzy_match');
|
||||||
|
domFuzzyMatch.setAttribute('type', 'checkbox');
|
||||||
|
domFuzzyMatch.setAttribute('checked', 'checked');
|
||||||
|
domForm.appendChild(domFuzzyMatch);
|
||||||
|
|
||||||
|
let domFuzzyMatchLabel = domNewElem('label', 'Fuzzy Match');
|
||||||
|
domFuzzyMatchLabel.setAttribute('for', 'fuzzy_match');
|
||||||
|
domForm.appendChild(domFuzzyMatchLabel);
|
||||||
|
|
||||||
let domTr = domNewElem('tr',
|
let domTr = domNewElem('tr',
|
||||||
createControlLabelTdDom('Add by Path:'),
|
createControlLabelTdDom('Add by Path:'),
|
||||||
domNewElem('td', domForm));
|
domNewElem('td', domForm));
|
||||||
@@ -343,11 +353,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showModulesByFilter(pred) {
|
function showModulesByFilter(pred) {
|
||||||
|
let numMatched = 0;
|
||||||
for (let mod of mods) {
|
for (let mod of mods) {
|
||||||
if (pred(mod)) {
|
if (pred(mod)) {
|
||||||
mod.showDom();
|
mod.showDom();
|
||||||
|
++numMatched;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return numMatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showModulesByTagId(tagId) {
|
function showModulesByTagId(tagId) {
|
||||||
@@ -367,13 +380,33 @@
|
|||||||
let path = domPathInput.value;
|
let path = domPathInput.value;
|
||||||
domPathInput.value = '';
|
domPathInput.value = '';
|
||||||
|
|
||||||
for (let mod of mods) {
|
function escapeRegExp(pattern) {
|
||||||
if (mod.path == path) {
|
return pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
|
||||||
mod.showDom();
|
}
|
||||||
return;
|
|
||||||
}
|
function createFuzzyMatcher() {
|
||||||
|
let parts = path.split(/\/+/g);
|
||||||
|
let pattern = '';
|
||||||
|
for (let part of parts) {
|
||||||
|
pattern += escapeRegExp(part) + '(?:/[^\/]*)*';
|
||||||
|
}
|
||||||
|
pattern = RegExp(pattern);
|
||||||
|
|
||||||
|
return function (mod) {
|
||||||
|
return pattern.test(mod.path);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function exactMatcher(mod) {
|
||||||
|
return mod.path == path;
|
||||||
|
}
|
||||||
|
|
||||||
|
let numMatched = showModulesByFilter(
|
||||||
|
domFuzzyMatch.checked ? createFuzzyMatcher() : exactMatcher);
|
||||||
|
|
||||||
|
if (numMatched == 0) {
|
||||||
|
alert('No matching modules: ' + path);
|
||||||
}
|
}
|
||||||
alert('Path not found: ' + path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAddAll(evt) {
|
function onAddAll(evt) {
|
||||||
|
|||||||
@@ -83,6 +83,22 @@ class ELFLinkDataTest(unittest.TestCase):
|
|||||||
self.assertTrue(self.x.is_system_lib())
|
self.assertTrue(self.x.is_system_lib())
|
||||||
self.assertFalse(self.v.is_system_lib())
|
self.assertFalse(self.v.is_system_lib())
|
||||||
|
|
||||||
|
def test_get_dep_linked_symbols(self):
|
||||||
|
self.x.linked_symbols['c'] = self.y
|
||||||
|
self.x.linked_symbols['b'] = self.y
|
||||||
|
self.x.linked_symbols['a'] = self.y
|
||||||
|
|
||||||
|
self.x.linked_symbols['w'] = self.z
|
||||||
|
self.x.linked_symbols['z'] = self.z
|
||||||
|
self.x.linked_symbols['y'] = self.z
|
||||||
|
self.x.linked_symbols['x'] = self.z
|
||||||
|
|
||||||
|
self.assertEqual(['a', 'b', 'c'],
|
||||||
|
self.x.get_dep_linked_symbols(self.y))
|
||||||
|
|
||||||
|
self.assertEqual(['w', 'x', 'y', 'z'],
|
||||||
|
self.x.get_dep_linked_symbols(self.z))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
39
vndk/tools/definition-tool/tests/test_module_info.py
Executable file
39
vndk/tools/definition-tool/tests/test_module_info.py
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from vndk_definition_tool import ModuleInfo
|
||||||
|
|
||||||
|
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleInfoTest(unittest.TestCase):
|
||||||
|
def test_default(self):
|
||||||
|
m = ModuleInfo()
|
||||||
|
self.assertEqual([], m.get_module_path('/system/lib64/libA.so'))
|
||||||
|
|
||||||
|
def test_get_module_path(self):
|
||||||
|
m = ModuleInfo(os.path.join(SCRIPT_DIR, 'testdata', 'test_module_info',
|
||||||
|
'module-info.json'))
|
||||||
|
|
||||||
|
self.assertEqual(['system/core/libA'],
|
||||||
|
m.get_module_path('/system/lib64/libA.so'))
|
||||||
|
self.assertEqual(['frameworks/base/libB'],
|
||||||
|
m.get_module_path('/system/lib64/libB.so'))
|
||||||
|
self.assertEqual(['frameworks/base/libC'],
|
||||||
|
m.get_module_path('/system/lib64/libC.so'))
|
||||||
|
self.assertEqual(['frameworks/base/libC'],
|
||||||
|
m.get_module_path('/system/lib64/hw/libC.so'))
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[], m.get_module_path('/system/lib64/libdoes_not_exist.so'))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
5
vndk/tools/definition-tool/tests/testdata/test_module_info/module-info.json
vendored
Normal file
5
vndk/tools/definition-tool/tests/testdata/test_module_info/module-info.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"libA": { "path": ["system/core/libA"], "installed": ["out/target/product/generic_arm64/system/lib64/libA.so"] },
|
||||||
|
"libB": { "path": ["frameworks/base/libB"], "installed": ["out/target/product/generic_arm64/system/lib64/libB.so"] },
|
||||||
|
"libC": { "path": ["frameworks/base/libC"], "installed": ["out/target/product/generic_arm64/system/lib64/libC.so", "out/target/product/generic_arm64/system/lib64/hw/libC.so"] }
|
||||||
|
}
|
||||||
@@ -792,6 +792,13 @@ class ELFLinkData(object):
|
|||||||
def is_system_lib(self):
|
def is_system_lib(self):
|
||||||
return self.partition == PT_SYSTEM
|
return self.partition == PT_SYSTEM
|
||||||
|
|
||||||
|
def get_dep_linked_symbols(self, dep):
|
||||||
|
symbols = set()
|
||||||
|
for symbol, exp_lib in self.linked_symbols.items():
|
||||||
|
if exp_lib == dep:
|
||||||
|
symbols.add(symbol)
|
||||||
|
return sorted(symbols)
|
||||||
|
|
||||||
|
|
||||||
def sorted_lib_path_list(libs):
|
def sorted_lib_path_list(libs):
|
||||||
libs = [lib.path for lib in libs]
|
libs = [lib.path for lib in libs]
|
||||||
@@ -2102,16 +2109,12 @@ class DepsCommand(ELFGraphCommand):
|
|||||||
results = []
|
results = []
|
||||||
for partition in range(NUM_PARTITIONS):
|
for partition in range(NUM_PARTITIONS):
|
||||||
for name, lib in graph.lib_pt[partition].items():
|
for name, lib in graph.lib_pt[partition].items():
|
||||||
if not args.symbols:
|
if args.symbols:
|
||||||
def collect_symbols(user, definer):
|
def collect_symbols(user, definer):
|
||||||
return ()
|
return user.get_dep_linked_symbols(definer)
|
||||||
else:
|
else:
|
||||||
def collect_symbols(user, definer):
|
def collect_symbols(user, definer):
|
||||||
symbols = set()
|
return ()
|
||||||
for symbol, exp_lib in user.linked_symbols.items():
|
|
||||||
if exp_lib == definer:
|
|
||||||
symbols.add(symbol)
|
|
||||||
return sorted(symbols)
|
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
if args.revert:
|
if args.revert:
|
||||||
@@ -2186,6 +2189,21 @@ TAGGED_LIB_DICT_FIELDS = ('ll_ndk', 'sp_ndk', 'sp_ndk_indirect', 'hl_ndk',
|
|||||||
|
|
||||||
TaggedLibDict = collections.namedtuple('TaggedLibDict', TAGGED_LIB_DICT_FIELDS)
|
TaggedLibDict = collections.namedtuple('TaggedLibDict', TAGGED_LIB_DICT_FIELDS)
|
||||||
|
|
||||||
|
class ModuleInfo(object):
|
||||||
|
def __init__(self, module_info_path=None):
|
||||||
|
if not module_info_path:
|
||||||
|
self.json = dict()
|
||||||
|
else:
|
||||||
|
with open(module_info_path, 'r') as f:
|
||||||
|
self.json = json.load(f)
|
||||||
|
|
||||||
|
def get_module_path(self, installed_path):
|
||||||
|
for name, module in self.json.items():
|
||||||
|
if any(path.endswith(installed_path)
|
||||||
|
for path in module['installed']):
|
||||||
|
return module['path']
|
||||||
|
return []
|
||||||
|
|
||||||
class CheckDepCommand(ELFGraphCommand):
|
class CheckDepCommand(ELFGraphCommand):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(CheckDepCommand, self).__init__(
|
super(CheckDepCommand, self).__init__(
|
||||||
@@ -2196,6 +2214,8 @@ class CheckDepCommand(ELFGraphCommand):
|
|||||||
|
|
||||||
parser.add_argument('--tag-file', required=True)
|
parser.add_argument('--tag-file', required=True)
|
||||||
|
|
||||||
|
parser.add_argument('--module-info')
|
||||||
|
|
||||||
def _load_tag_file(self, tag_file_path):
|
def _load_tag_file(self, tag_file_path):
|
||||||
res = TaggedLibDict(set(), set(), set(), set(), set(), set(), set(),
|
res = TaggedLibDict(set(), set(), set(), set(), set(), set(), set(),
|
||||||
set())
|
set())
|
||||||
@@ -2230,7 +2250,17 @@ class CheckDepCommand(ELFGraphCommand):
|
|||||||
res[i].add(lib)
|
res[i].add(lib)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _check_eligible_vndk_dep(self, graph, tagged_libs):
|
@staticmethod
|
||||||
|
def _dump_dep(lib, bad_deps, module_info):
|
||||||
|
print(lib.path)
|
||||||
|
for module_path in module_info.get_module_path(lib.path):
|
||||||
|
print('\tMODULE_PATH:', module_path)
|
||||||
|
for dep in bad_deps:
|
||||||
|
print('\t' + dep.path)
|
||||||
|
for symbol in lib.get_dep_linked_symbols(dep):
|
||||||
|
print('\t\t' + symbol)
|
||||||
|
|
||||||
|
def _check_eligible_vndk_dep(self, graph, tagged_libs, module_info):
|
||||||
"""Check whether eligible sets are self-contained."""
|
"""Check whether eligible sets are self-contained."""
|
||||||
num_errors = 0
|
num_errors = 0
|
||||||
|
|
||||||
@@ -2242,27 +2272,32 @@ class CheckDepCommand(ELFGraphCommand):
|
|||||||
|
|
||||||
# Check eligible vndk is self-contained.
|
# Check eligible vndk is self-contained.
|
||||||
for lib in eligible_libs:
|
for lib in eligible_libs:
|
||||||
|
bad_deps = []
|
||||||
for dep in lib.deps:
|
for dep in lib.deps:
|
||||||
if dep not in eligible_libs and dep not in indirect_libs:
|
if dep not in eligible_libs and dep not in indirect_libs:
|
||||||
print('error: eligible-lib: {}: eligible lib "{}" should '
|
print('error: eligible lib "{}" should not depend on '
|
||||||
'not depend on non-eligible lib "{}".'
|
'non-eligible lib "{}".'.format(lib.path, dep.path),
|
||||||
.format(lib.path, lib.path, dep.path),
|
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
|
bad_deps.append(dep)
|
||||||
num_errors += 1
|
num_errors += 1
|
||||||
|
if bad_deps:
|
||||||
|
self._dump_dep(lib, bad_deps, module_info)
|
||||||
|
|
||||||
# Check the libbinder dependencies.
|
# Check the libbinder dependencies.
|
||||||
for lib in eligible_libs:
|
for lib in eligible_libs:
|
||||||
|
bad_deps = []
|
||||||
for dep in lib.deps:
|
for dep in lib.deps:
|
||||||
if os.path.basename(dep.path) == 'libbinder.so':
|
if os.path.basename(dep.path) == 'libbinder.so':
|
||||||
print('error: eligible-lib: {}: eligible lib "{}" should '
|
print('error: eligible lib "{}" should not depend on '
|
||||||
'not depend on libbinder.so.'
|
'libbinder.so.'.format(lib.path), file=sys.stderr)
|
||||||
.format(lib.path, lib.path),
|
bad_deps.append(dep)
|
||||||
file=sys.stderr)
|
|
||||||
num_errors += 1
|
num_errors += 1
|
||||||
|
if bad_deps:
|
||||||
|
self._dump_dep(lib, bad_deps, module_info)
|
||||||
|
|
||||||
return num_errors
|
return num_errors
|
||||||
|
|
||||||
def _check_vendor_dep(self, graph, tagged_libs):
|
def _check_vendor_dep(self, graph, tagged_libs, module_info):
|
||||||
"""Check whether vendor libs are depending on non-eligible libs."""
|
"""Check whether vendor libs are depending on non-eligible libs."""
|
||||||
num_errors = 0
|
num_errors = 0
|
||||||
|
|
||||||
@@ -2273,13 +2308,16 @@ class CheckDepCommand(ELFGraphCommand):
|
|||||||
tagged_libs.vndk | tagged_libs.vndk_indirect)
|
tagged_libs.vndk | tagged_libs.vndk_indirect)
|
||||||
|
|
||||||
for lib in vendor_libs:
|
for lib in vendor_libs:
|
||||||
|
bad_deps = []
|
||||||
for dep in lib.deps:
|
for dep in lib.deps:
|
||||||
if dep not in vendor_libs and dep not in eligible_libs:
|
if dep not in vendor_libs and dep not in eligible_libs:
|
||||||
print('error: vendor-lib: {}: vendor lib "{}" depends on '
|
print('error: vendor lib "{}" depends on non-eligible '
|
||||||
'non-eligible lib "{}".'
|
'lib "{}".'.format(lib.path, dep.path),
|
||||||
.format(lib.path, lib.path, dep.path),
|
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
|
bad_deps.append(dep)
|
||||||
num_errors += 1
|
num_errors += 1
|
||||||
|
if bad_deps:
|
||||||
|
self._dump_dep(lib, bad_deps, module_info)
|
||||||
|
|
||||||
return num_errors
|
return num_errors
|
||||||
|
|
||||||
@@ -2291,8 +2329,11 @@ class CheckDepCommand(ELFGraphCommand):
|
|||||||
tags = self._load_tag_file(args.tag_file)
|
tags = self._load_tag_file(args.tag_file)
|
||||||
tagged_libs = self._get_tagged_libs(graph, tags)
|
tagged_libs = self._get_tagged_libs(graph, tags)
|
||||||
|
|
||||||
num_errors = self._check_eligible_vndk_dep(graph, tagged_libs)
|
module_info = ModuleInfo(args.module_info)
|
||||||
num_errors += self._check_vendor_dep(graph, tagged_libs)
|
|
||||||
|
num_errors = self._check_eligible_vndk_dep(graph, tagged_libs,
|
||||||
|
module_info)
|
||||||
|
num_errors += self._check_vendor_dep(graph, tagged_libs, module_info)
|
||||||
|
|
||||||
return 0 if num_errors == 0 else 1
|
return 0 if num_errors == 0 else 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user