cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kernel_feat.py (4904B)


      1# coding=utf-8
      2# SPDX-License-Identifier: GPL-2.0
      3#
      4u"""
      5    kernel-feat
      6    ~~~~~~~~~~~
      7
      8    Implementation of the ``kernel-feat`` reST-directive.
      9
     10    :copyright:  Copyright (C) 2016  Markus Heiser
     11    :copyright:  Copyright (C) 2016-2019  Mauro Carvalho Chehab
     12    :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
     13    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
     14
     15    The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
     16    scripts/get_feat.pl script to parse the Kernel ABI files.
     17
     18    Overview of directive's argument and options.
     19
     20    .. code-block:: rst
     21
     22        .. kernel-feat:: <ABI directory location>
     23            :debug:
     24
     25    The argument ``<ABI directory location>`` is required. It contains the
     26    location of the ABI files to be parsed.
     27
     28    ``debug``
     29      Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
     30      what reST is generated.
     31
     32"""
     33
     34import codecs
     35import os
     36import re
     37import subprocess
     38import sys
     39
     40from os import path
     41
     42from docutils import nodes, statemachine
     43from docutils.statemachine import ViewList
     44from docutils.parsers.rst import directives, Directive
     45from docutils.utils.error_reporting import ErrorString
     46from sphinx.util.docutils import switch_source_input
     47
     48__version__  = '1.0'
     49
     50def setup(app):
     51
     52    app.add_directive("kernel-feat", KernelFeat)
     53    return dict(
     54        version = __version__
     55        , parallel_read_safe = True
     56        , parallel_write_safe = True
     57    )
     58
     59class KernelFeat(Directive):
     60
     61    u"""KernelFeat (``kernel-feat``) directive"""
     62
     63    required_arguments = 1
     64    optional_arguments = 2
     65    has_content = False
     66    final_argument_whitespace = True
     67
     68    option_spec = {
     69        "debug"     : directives.flag
     70    }
     71
     72    def warn(self, message, **replace):
     73        replace["fname"]   = self.state.document.current_source
     74        replace["line_no"] = replace.get("line_no", self.lineno)
     75        message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
     76        self.state.document.settings.env.app.warn(message, prefix="")
     77
     78    def run(self):
     79
     80        doc = self.state.document
     81        if not doc.settings.file_insertion_enabled:
     82            raise self.warning("docutils: file insertion disabled")
     83
     84        env = doc.settings.env
     85        cwd = path.dirname(doc.current_source)
     86        cmd = "get_feat.pl rest --enable-fname --dir "
     87        cmd += self.arguments[0]
     88
     89        if len(self.arguments) > 1:
     90            cmd += " --arch " + self.arguments[1]
     91
     92        srctree = path.abspath(os.environ["srctree"])
     93
     94        fname = cmd
     95
     96        # extend PATH with $(srctree)/scripts
     97        path_env = os.pathsep.join([
     98            srctree + os.sep + "scripts",
     99            os.environ["PATH"]
    100        ])
    101        shell_env = os.environ.copy()
    102        shell_env["PATH"]    = path_env
    103        shell_env["srctree"] = srctree
    104
    105        lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
    106
    107        line_regex = re.compile("^\.\. FILE (\S+)$")
    108
    109        out_lines = ""
    110
    111        for line in lines.split("\n"):
    112            match = line_regex.search(line)
    113            if match:
    114                fname = match.group(1)
    115
    116                # Add the file to Sphinx build dependencies
    117                env.note_dependency(os.path.abspath(fname))
    118            else:
    119                out_lines += line + "\n"
    120
    121        nodeList = self.nestedParse(out_lines, fname)
    122        return nodeList
    123
    124    def runCmd(self, cmd, **kwargs):
    125        u"""Run command ``cmd`` and return its stdout as unicode."""
    126
    127        try:
    128            proc = subprocess.Popen(
    129                cmd
    130                , stdout = subprocess.PIPE
    131                , stderr = subprocess.PIPE
    132                , **kwargs
    133            )
    134            out, err = proc.communicate()
    135
    136            out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
    137
    138            if proc.returncode != 0:
    139                raise self.severe(
    140                    u"command '%s' failed with return code %d"
    141                    % (cmd, proc.returncode)
    142                )
    143        except OSError as exc:
    144            raise self.severe(u"problems with '%s' directive: %s."
    145                              % (self.name, ErrorString(exc)))
    146        return out
    147
    148    def nestedParse(self, lines, fname):
    149        content = ViewList()
    150        node    = nodes.section()
    151
    152        if "debug" in self.options:
    153            code_block = "\n\n.. code-block:: rst\n    :linenos:\n"
    154            for l in lines.split("\n"):
    155                code_block += "\n    " + l
    156            lines = code_block + "\n\n"
    157
    158        for c, l in enumerate(lines.split("\n")):
    159            content.append(l, fname, c)
    160
    161        buf  = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
    162
    163        with switch_source_input(self.state, content):
    164            self.state.nested_parse(content, 0, node, match_titles=1)
    165
    166        return node.children