예제 #1
0
    def _determine_units(self, program):
        """
        Create a module from all files compiled in .ko loadable module and files from directories compiled in modules
        build-in files also separate in units.

        :param program: Program object.
        """
        for desc in program.clade.get_all_cmds_by_type("LD"):
            identifier = desc['id']
            # This shouldn't happen ever, but let's fail otherwise.
            if len(desc['out']) != 1:
                self.logger.warning(
                    "LD commands with several out files are not supported, skip commands: {!r}"
                    .format(identifier))
                continue

            out = desc['out'][0]
            if out.endswith('.ko') or out.endswith('built-in.o'):
                rel_object_path = make_relative_path(self.source_paths, out)
                name = rel_object_path
                fragment = program.create_fragment_from_linker_cmds(
                    identifier, desc, name,
                    out.endswith('built-in.o') and self._separate_nested)
                if (not self._max_size or fragment.size <= self._max_size
                    ) and len(fragment.files) != 0:
                    program.add_fragment(fragment)
                else:
                    self.logger.debug(
                        'Fragment {!r} is rejected since it exceeds maximum size or does not contain '
                        'files {!r}'.format(fragment.name, fragment.size))
예제 #2
0
    def __prepare_data_files(self, grps, tactic, fragmentation_set):
        """
        Prepare data files that describe program fragments content.

        :param grps: Dictionary with program fragments with dependencies.
        :param tactic: Name of the tactic.
        :param grps: Name of the fragmentation set.
        :return: Attributes and dict a list of data files.
        """
        data = dict()
        for name, main_and_frgs in grps.items():
            main, frags = main_and_frgs
            data[name] = {
                "files": [make_relative_path(self.source_paths, l.name) for f in frags for l in f.files],
                "size": str(sum(int(f.size) for f in frags))
            }

        with open('aggregations description.json', 'w', encoding='utf-8') as fp:
            ujson.dump(data, fp, sort_keys=True, indent=4, ensure_ascii=False,
                       escape_forward_slashes=False)

        return [{
            'name': 'Program fragmentation',
            'value': [
                {
                    'name': 'tactic',
                    'value': tactic
                },
                {
                    'name': 'set',
                    'value': fragmentation_set
                }
            ]
        }], 'aggregations description.json'
예제 #3
0
    def _determine_units(self, program):
        """
        Find all files that has \w+_main function and add dependencies files except that ones that stored in libbb dir.
        All files from the libbb directory add to the specific unit with the libbb name.

        :param program: Program object.
        """
        main_func = re.compile("\\w+main")

        libbb = set()
        applets = dict()
        for file in program.files:
            rel_path = make_relative_path(self.source_paths, str(file))
            if os.path.commonpath(['libbb', rel_path]):
                libbb.add(file)
            else:
                for func in file.export_functions:
                    if main_func.match(func):
                        path, name = os.path.split(rel_path)
                        name = os.path.splitext(name)[0]
                        applets[name] = {file}
                        if self._incorporate_libbb:
                            dfiles = program.collect_dependencies({file})
                        else:
                            dfiles = program.collect_dependencies(
                                {file},
                                filter_func=lambda x: not os.path.commonpath([
                                    'libbb',
                                    make_relative_path(self.source_paths, x.
                                                       name)
                                ]))
                        applets[name].update(dfiles)

        # Create fragments for found applets and libbb
        for name, files in applets.items():
            program.create_fragment(name, files, add=True)

            for file in files:
                if file.name not in self._match_files:
                    self._match_files[file.name] = 0
                else:
                    self._match_files[file.name] += 1

        program.create_fragment('libbb', libbb, add=True)

        self.logger.info('Found {} applets: {}'.format(len(applets),
                                                       ', '.join(applets)))
예제 #4
0
    def _determine_units(self, program):
        """
        Consider all program source files as independent program fragments.

        :param program: Program object.
        """
        for file in program.files:
            name = make_relative_path(self.source_paths, file.name)
            program.create_fragment(name, {file}, add=True)
예제 #5
0
    def __describe_program_fragment(self, program, name, grp):
        """
        Create the JSON file for the given program fragment with dependencies.

        :param program: Program object.
        :param name: Name of the fragment.
        :param grp: Set of fragments with dependencies.
        :return: The name of the created file.
        """
        # Determine fragment name
        main_fragment, fragments = grp
        self.logger.info('Generate fragment description {!r}'.format(name))

        pf_desc = {
            'id': name,
            'fragment': name,
            'targets': sorted([str(f) for f in main_fragment.target_files]),
            'grps': list(),
            'deps': dict(),
            'size': str(sum((int(f.size) for f in fragments)))
        }

        for frag in fragments:
            fragment_description = {
                'id': frag.name,
                'Extra CCs': [
                    {"CC": [file.cmd_id, file.cmd_type], "in file": str(file)} for file in frag.files
                ],
                'files': sorted(make_relative_path(self.source_paths, str(f)) for f in frag.files),
                'abs files': sorted(str(f) for f in frag.files)
            }
            pf_desc['grps'].append(fragment_description)
            pf_desc['deps'][frag.name] = [succ.name for succ in program.get_fragment_successors(frag)
                                          if succ in fragments]
        self.logger.debug('Program fragment dependencies are {}'.format(pf_desc['deps']))

        pf_desc_file = os.path.join(self.pf_dir, pf_desc['fragment'] + '.json')
        if os.path.isfile(pf_desc_file):
            raise FileExistsError('Program fragment description file {!r} already exists'.format(pf_desc_file))
        self.logger.debug('Dump program fragment description {!r} to file {!r}'.format(pf_desc['fragment'], pf_desc_file))
        dir_path = os.path.dirname(pf_desc_file).encode('utf-8')
        if dir_path:
            os.makedirs(dir_path, exist_ok=True)

        with open(pf_desc_file, 'w', encoding='utf-8') as fp:
            ujson.dump(pf_desc, fp, sort_keys=True, indent=4, ensure_ascii=False, escape_forward_slashes=False)
        return pf_desc_file
예제 #6
0
    def __draw_fragment(self, fragment):
        """
        Print a graph with files and dependencies between them for a fragment.

        :param fragment: Fragment object.
        """
        g = Digraph(graph_attr={'rankdir': 'LR'}, node_attr={'shape': 'rectangle'})
        for file in fragment.files:
            g.node(file.name,
                   make_relative_path(self.source_paths, file.name) + (' (target)' if fragment.target else ''))

        for file in fragment.files:
            for suc in file.successors:
                if suc in fragment.files:
                    g.edge(fragment.name, suc.name)
        if not os.path.exists('fragments'):
            os.makedirs('fragments')
        g.render(os.path.join('fragments', fragment.name))