1#!/usr/bin/env python3
2
3import os
4import sys
5
6sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
7
8from compat import StringIO
9from vndk_definition_tool import (
10        ELF, ELFLinker, PT_SYSTEM, PT_VENDOR, VNDKLibDir)
11
12
13class GraphBuilder(object):
14    _PARTITION_NAMES = {
15        PT_SYSTEM: 'system',
16        PT_VENDOR: 'vendor',
17    }
18
19    _LIB_DIRS = {
20        ELF.ELFCLASS32: 'lib',
21        ELF.ELFCLASS64: 'lib64',
22    }
23
24    def __init__(self):
25        self.graph = ELFLinker()
26
27    def add_lib(self, partition, klass, name, dt_needed=[],
28                exported_symbols=set(), imported_symbols=set(),
29                extra_dir=None):
30        """Create and add a shared library to ELFLinker."""
31
32        lib_dir = os.path.join('/', self._PARTITION_NAMES[partition],
33                               self._LIB_DIRS[klass])
34        if extra_dir:
35            lib_dir = os.path.join(lib_dir, extra_dir)
36
37        path = os.path.join(lib_dir, name + '.so')
38
39        elf = ELF(klass, ELF.ELFDATA2LSB, dt_needed=dt_needed,
40                  exported_symbols=exported_symbols,
41                  imported_symbols=imported_symbols)
42
43        lib = self.graph.add_lib(partition, path, elf)
44        setattr(self, name + '_' + elf.elf_class_name, lib)
45        return lib
46
47    def add_lib32(self, partition, name, dt_needed=[],
48                  exported_symbols=set(), imported_symbols=set(),
49                  extra_dir=None):
50        return self.add_lib(partition, ELF.ELFCLASS32, name, dt_needed,
51                            exported_symbols, imported_symbols, extra_dir)
52
53    def add_lib64(self, partition, name, dt_needed=[],
54                  exported_symbols=set(), imported_symbols=set(),
55                  extra_dir=None):
56        return self.add_lib(partition, ELF.ELFCLASS64, name, dt_needed,
57                            exported_symbols, imported_symbols, extra_dir)
58
59    def add_multilib(self, partition, name, dt_needed=[],
60                     exported_symbols=set(), imported_symbols=set(),
61                     extra_dir=None):
62        """Add 32-bit / 64-bit shared libraries to ELFLinker."""
63        return (
64            self.add_lib(partition, ELF.ELFCLASS32, name, dt_needed,
65                         exported_symbols, imported_symbols, extra_dir),
66            self.add_lib(partition, ELF.ELFCLASS64, name, dt_needed,
67                         exported_symbols, imported_symbols, extra_dir)
68        )
69
70    def resolve(self, vndk_lib_dirs=None, ro_vndk_version=None):
71        if vndk_lib_dirs is not None:
72            self.graph.vndk_lib_dirs = vndk_lib_dirs
73        if ro_vndk_version is not None:
74            self.graph.ro_vndk_version = ro_vndk_version
75        self.graph.resolve_deps()
76