Beispiel #1
0
    def __init__(self,
                 default_context=None,
                 code_segment=None,
                 data_segment=None,
                 symbolic=True,
                 absolute=False):
        """

        :param default_context:  (Default value = None)
        :param code_segment:  (Default value = None)
        :param data_segment:  (Default value = None)
        :param symbolic:  (Default value = True)

        """

        self._reserved_registers = RejectingDict()
        self._register_values = [{}, {}]
        self._memory_values = [{}, {}]

        self._data_segment = data_segment
        self._code_segment = code_segment
        self._symbolic = symbolic
        self._fabsolute = absolute

        self._dat = None

        if default_context is not None:
            self = default_context.copy()
Beispiel #2
0
 def __init__(self, strict=False, instructions=None):
     """ """
     super(ResolveSymbolicReferencesPass, self).__init__()
     self._description = "Translate labels of address into values"
     self._labels = RejectingDict()
     self._strict = strict
     self._instructions = []
     if instructions is not None:
         self._instructions = instructions
Beispiel #3
0
def _interpret_decorators(str_decorators):

    decorators = RejectingDict()

    if str_decorators is None:
        return decorators

    for decorator_def in str_decorators.split(" "):
        if decorator_def == '':
            continue

        key = decorator_def.split("=")[0].upper()
        lvalue = (decorator_def + "=").split("=")[1].split(",")

        for idx, value in enumerate(lvalue):

            if os.path.isfile(value):
                print(value)
                exit(-1)
            else:
                origvalue = value
                value = value.upper()

            if value == '':
                value = None
            elif value == 'ON':
                value = True
            elif value == 'OFF':
                value = False
            elif value == 'TRUE':
                value = True
            elif value == 'FALSE':
                value = False
            elif value.isdigit():
                value = int(value)
            elif value.startswith("0X"):
                try:
                    value = int(value, 16)
                except ValueError:
                    value = origvalue
            else:
                value = origvalue

            lvalue[idx] = value

        try:
            if len(lvalue) == 1:
                decorators[key] = lvalue[0]
            else:
                decorators[key] = lvalue

        except MicroprobeDuplicatedValueError:
            raise MicroprobeAsmError(
                "Decorator with key '%s' specified twice for the same "
                "instruction." % key)

    return decorators
Beispiel #4
0
    def __init__(self, target, **kwargs):
        """ """
        super(GenericDynamicAddressTranslation,
              self).__init__(target, **kwargs)

        self._map = RejectingDict()
        self._target = target
        self._control = self._control_keys.copy()
        self._control.update(kwargs)

        tmaps = kwargs.pop('dat_map', False)
        if tmaps:
            for tmap in tmaps:
                self.add_mapping(tmap[0], tmap[1], tmap[2])
Beispiel #5
0
 def _init_properties(self):
     """ """
     if self.__dict__.get("_properties", None) is None:
         # pylint: disable=attribute-defined-outside-init
         self._properties = RejectingDict()
Beispiel #6
0
class PropertyHolder(object):
    """Class to represent an object containing properties"""

    def _init_properties(self):
        """ """
        if self.__dict__.get("_properties", None) is None:
            # pylint: disable=attribute-defined-outside-init
            self._properties = RejectingDict()
            # pylint: enable=attribute-defined-outside-init

    def register_property(self, prop, force=False):
        """

        :param prop:

        """

        self._init_properties()

        LOG.debug("Registering '%s' in '%s' (Force: '%s')", prop, self, force)

        if prop.name not in self._properties:
            self._properties[prop.name] = prop
        elif not prop.default:
            if force or self._properties[prop.name].default:
                del self._properties[prop.name]
                self._properties[prop.name] = prop
            else:
                self._properties[prop.name] = prop

        # Remove memoization at property registration
        if hasattr(self, prop.name):
            delattr(self, prop.name)

        # Memoize by accessing
        getattr(self, prop.name)

    def unregister_property(self, prop):
        """

        :param prop:

        """

        self._init_properties()
        del self._properties[prop.name]

    def list_properties(self, tabs=0):
        """ """

        self._init_properties()
        rstr = ""

        if len(self._properties) == 0:
            rstr += "    No properties \n"
            return rstr

        maxname = max(
            [
                len(str(value.name)) for value in
                six.itervalues(self._properties)
            ]
        ) + 2
        maxvalue = max(
            [
                len(str(value.value)) for value in
                six.itervalues(self._properties)
            ]
        )
        maxdesc = max(
            [
                len(str(value.description))
                for value in six.itervalues(self._properties)
            ]
        )

        strfmt = "\t" * tabs
        strfmt += "%%-%ds:\t%%-%ds\t(%%-%ds)\n" % (maxname, maxvalue, maxdesc)

        for key in sorted(six.iterkeys(self._properties)):
            value = self._properties[key]
            rstr += strfmt % (value.name, value.value, value.description)
        return rstr

    @property
    def properties(self):
        """

        """
        return self._properties.copy()

    def __getattr__(self, name):
        """

        :param name:

        """

        self._init_properties()
        if name in self._properties:
            # Memoize properties
            # They can not change over the execution
            value = self._properties[name].value
            setattr(self, name, value)
            return value

        raise AttributeError(
            "'%s' object has no attribute '%s'" %
            (self.__class__.__name__, name)
        )
Beispiel #7
0
def _interpret_decorators(str_decorators):

    decorators = RejectingDict()

    if str_decorators is None:
        return decorators

    for decorator_def in str_decorators.split(" "):
        if decorator_def == '':
            continue

        key = decorator_def.split("=")[0].upper()
        lvalue = (decorator_def + "=").split("=")[1].split(",")

        nvalue = []

        for idx, value in enumerate(lvalue):

            if value == '':
                continue

            if os.path.isfile(value):
                print(value)
                raise NotImplementedError
            else:
                origvalue = value
                value = value.upper()

            if value == '':
                value = None
            elif value == 'ON':
                value = True
            elif value == 'OFF':
                value = False
            elif value == 'TRUE':
                value = True
            elif value == 'FALSE':
                value = False
            elif value.isdigit():
                value = int(value)
            elif value.startswith("0X"):
                if value.count("-") > 1:
                    value = range_to_sequence(*value.split("-"))
                else:
                    try:
                        value = int(value, 16)
                    except ValueError:
                        value = origvalue
            else:
                value = origvalue

            if isinstance(value, list):
                nvalue.extend(value)
            else:
                nvalue.append(value)

        try:
            if len(lvalue) == 1:
                decorators[key] = nvalue[0]
            else:
                decorators[key] = nvalue

        except MicroprobeDuplicatedValueError:
            raise MicroprobeAsmError(
                "Decorator with key '%s' specified twice for the same "
                "instruction." % key)

    return decorators
Beispiel #8
0
import microprobe.code.ins
from microprobe import MICROPROBE_RC
from microprobe.code.address import Address, InstructionAddress
from microprobe.exceptions import MicroprobeAsmError, \
    MicroprobeCodeGenerationError, MicroprobeDuplicatedValueError, \
    MicroprobeValueError
from microprobe.target.isa.operand import InstructionAddressRelativeOperand, \
    OperandConst, OperandImmRange, OperandValueSet
from microprobe.utils.bin import interpret_bin
from microprobe.utils.logger import get_logger
from microprobe.utils.misc import Progress, RejectingDict, twocs_to_int, \
    range_to_sequence

# Constants
LOG = get_logger(__name__)
_ASM_CACHE = RejectingDict()
_DECORATOR_CACHE = RejectingDict()
__all__ = [
    "interpret_asm", "MicroprobeAsmInstructionDefinition",
    "instruction_to_asm_definition"
]


# Functions
def interpret_asm(code,
                  target,
                  labels,
                  log=True,
                  show_progress=False,
                  parallel=True,
                  queue=None):
Beispiel #9
0
from six.moves import range, zip

# Own modules
import microprobe.code.ins
from microprobe import MICROPROBE_RC
from microprobe.exceptions import MicroprobeBinaryError, \
    MicroprobeCodeGenerationError, MicroprobeValueError
from microprobe.target.isa.instruction import instruction_type_from_bin
from microprobe.utils.logger import get_logger
from microprobe.utils.misc import Progress, \
    RejectingDict, int_to_twocs, twocs_to_int


# Constants
LOG = get_logger(__name__)
_BIN_CACHE = RejectingDict()
_CODE_CACHE = RejectingDict()
_DATA_CACHE = RejectingDict()
_DATA_CACHE_LENGTHS = []
_DATA_CACHE_ENABLED = True
_CODE_CACHE_ENABLED = True
_BIN_CACHE_ENABLED = True

__all__ = ["interpret_bin",
           "MicroprobeBinInstructionStream", ]


# Functions
def interpret_bin(code, target, fmt="hex", safe=None):
    """
    Return the list of :class:`~.MicroprobeInstructionDefinition` objects
Beispiel #10
0
def dump_dma(arguments):
    """

    :param target:
    :type target:
    :param arguments:
    :type arguments:
    """

    ifile = open(arguments['input_objdump_file'], 'r')
    inputlines = ifile.readlines()
    ifile.close()

    progress = Progress(len(inputlines), msg="Lines parsed:")
    lines_dict = {}
    caddress = None
    displace = 0
    for idx, line in enumerate(inputlines):

        idx = idx + 1
        progress()

        line = line.strip()

        if line == "" or "file format" in line or line.startswith("Disass"):
            continue

        tsplit = line.split("\t")

        if len(tsplit) not in [1, 3, 4]:
            raise MicroprobeObjdumpError("Unable to parse '%s' at line '%s'" %
                                         (line, idx))
        if len(tsplit) == 1:

            space_split = tsplit[0].split(" ")

            if len(space_split) != 2:
                raise MicroprobeObjdumpError(
                    "Unable to parse '%s' at line '%s'" % (line, idx))

            address, label = space_split

            if not label.endswith('>:') or label[0] != '<':
                raise MicroprobeObjdumpError(
                    "Unable to parse '%s' at line '%s'" % (line, idx))

            try:
                new_address = int(address, 16)
            except ValueError:
                raise MicroprobeObjdumpError(
                    "Unable to parse '%s' at line '%s'" % (line, idx))

            if caddress is None:
                caddress = new_address
            elif new_address != (caddress + displace):
                caddress = new_address
                displace = 0

            continue

        if len(tsplit) in [3, 4] and caddress is None:
            raise MicroprobeObjdumpError(
                "Unable to know the address of '%s' at line '%s'" %
                (line, idx))

        if not tsplit[0].endswith(":"):
            raise MicroprobeObjdumpError("Unable to parse '%s' at line '%s'" %
                                         (line, idx))

        if (caddress + displace) < int(tsplit[0][:-1], 16):

            caddress = int(tsplit[0][:-1], 16)
            displace = 0

        elif (caddress + displace) > int(tsplit[0][:-1], 16):

            raise MicroprobeObjdumpError(
                "Conflicting addresses in '%s' at line '%s'" % (line, idx))

        value = "".join(tsplit[1].split(' ')).lower()
        if caddress in lines_dict:
            lines_dict[caddress] += value
            displace += len(value) // 2
        else:
            lines_dict[caddress] = value
            displace = len(value) // 2

    used_addresses = RejectingDict()
    progress = Progress(len(list(lines_dict.keys())), msg="Writing output")

    with open(arguments['output_dma_file'], 'w') as fdout:

        for caddress in sorted(lines_dict):

            value = lines_dict[caddress]

            progress()

            if caddress % 8 != 0:

                contents = value[0:((caddress % 8) * 2)]
                value = value[((caddress % 8) * 2):]
                contents = "0" * (16 - len(contents)) + contents
                caddress = (caddress // 8) * 8

                line = "D %016x %s\n" % (caddress, contents)
                used_addresses[caddress] = line
                fdout.write(line)
                caddress += 8

            for idx in range(0, len(value), 16):

                contents = value[idx:idx + 16]
                contents += "0" * (16 - len(contents))

                line = "D %016x %s\n" % (caddress, contents)
                used_addresses[caddress] = line
                fdout.write(line)
                caddress += 8
Beispiel #11
0
import six

# Own modules
import microprobe.code.wrapper
from microprobe.code.address import Address
from microprobe.code.context import Context
from microprobe.utils.cmdline import print_info
from microprobe.utils.logger import get_logger
from microprobe.utils.misc import RejectingDict

# Constants
LOG = get_logger(__name__)
__all__ = [
    "QTrace",
]
_INSTR_CACHE = RejectingDict()

# Functions


# Classes
class QTrace(microprobe.code.wrapper.Wrapper):
    """:class:`Wrapper` to generate QT files (.qt).

    """
    def __init__(
        self,
        init_code_address=0x01500000,
        init_data_address=0x01600000,
        reset=False,
    ):
Beispiel #12
0
def dump_objdump(target, arguments):
    """

    :param target:
    :type target:
    :param arguments:
    :type arguments:
    """

    ifile = open(arguments['input_dma_file'], 'r')
    dataw = arguments['width_bytes']
    inputlines = ifile.readlines()
    ifile.close()

    progress = Progress(len(inputlines), msg="Lines parsed:")
    lines_dict = {}
    for idx, line in enumerate(inputlines):
        splitline = line.upper().split(" ")

        if len(splitline) != 3:
            raise MicroprobeDMAFormatError("Unable to parse line %d: %s" %
                                           (idx, line))

        if (splitline[0] != "D" or len(splitline[1]) != 16
                or len(splitline[1]) != 16):
            raise MicroprobeDMAFormatError("Unable to parse line %d: %s" %
                                           (idx, line))

        key = int(splitline[1], base=16)
        if key in lines_dict:
            print_warning("Address (%s) in line %d overwrites previous entry" %
                          (splitline[1], idx))

        lines_dict[key] = splitline[2][:-1]
        progress()

    current_key = None
    progress = Progress(len(list(lines_dict.keys())),
                        msg="Detecting segments:")
    for key in sorted(lines_dict):

        progress()

        if current_key is None:
            current_key = key
            continue

        current_address = current_key + (len(lines_dict[current_key]) // 2)

        if current_address == key:
            lines_dict[current_key] += lines_dict[key]
            lines_dict.pop(key)
        else:
            current_key = key

    instrs = []
    progress = Progress(len(list(lines_dict.keys())),
                        msg="Interpreting segments:")

    for key in sorted(lines_dict):
        progress()
        current_instrs = interpret_bin(lines_dict[key],
                                       target,
                                       safe=not arguments['strict'])
        current_instrs[0].address = Address(base_address='code',
                                            displacement=key)
        instrs += current_instrs

    maxlen = max([ins.format.length
                  for ins in target.instructions.values()] + [dataw]) * 2
    maxlen += maxlen // 2

    counter = 0
    label_dict = RejectingDict()
    instr_dict = RejectingDict()
    range_num = 1

    progress = Progress(len(instrs), msg="Computing labels:")
    for instr_def in instrs:
        progress()

        if instr_def.address is not None:
            counter = instr_def.address.displacement

        if instr_def.instruction_type is None:

            for idx in range(0, len(instr_def.asm), dataw * 2):

                label = None
                if instr_def.address is not None and idx == 0:
                    label = ".range_%x" % range_num
                    label_dict[counter] = label
                    range_num += 1
                elif counter in label_dict:
                    label = label_dict[counter]

                idx2 = min(idx + (dataw * 2), len(instr_def.asm))

                masm = instr_def.asm[idx:idx2].lower()
                binary = " ".join([
                    str(masm)[i:i + 2] for i in range(0, len(masm), 2)
                ]).lower()
                instr_dict[counter] = [binary, "0x" + masm, label, None, None]

                counter += (idx2 - idx) // 2

            continue

        instr = instruction_from_definition(instr_def, fix_relative=False)
        asm = instr.assembly().lower()

        relative = None
        absolute = None
        if instr.branch:

            for memoperand in instr.memory_operands():

                if not memoperand.descriptor.is_branch_target:
                    continue

                for operand in memoperand.operands:
                    if operand.type.address_relative:
                        relative = operand.value

                    if operand.type.address_absolute:
                        absolute = operand.value

        masm = instr_def.asm[2:]
        if len(masm) % 2 != 0:
            masm = "0" + masm

        binary = " ".join([str(masm)[i:i + 2] for i in range(0, len(masm), 2)])

        label = None
        if instr_def.address is not None:
            if counter not in label_dict:
                label = ".range_%x" % range_num
                label_dict[counter] = label
                range_num += 1
            else:
                label = label_dict[counter]
        elif counter in label_dict:
            label = label_dict[counter]

        rtarget = None
        atarget = None
        if relative is not None or absolute is not None:

            if relative is not None:
                assert absolute is None

                if isinstance(relative, int):
                    target_addr = counter + relative
                    rtarget = relative

                elif isinstance(relative, Address):
                    target_addr = counter + relative.displacement
                    rtarget = relative.displacement
                else:
                    raise NotImplementedError

            if absolute is not None:
                assert relative is None

                if isinstance(absolute, int):
                    target_addr = absolute
                    atarget = absolute
                elif isinstance(absolute, Address):
                    target_addr = absolute.displacement
                    atarget = absolute.displacement
                else:
                    raise NotImplementedError

            if target_addr not in label_dict:
                label_dict[target_addr] = "branch_%x" % target_addr

            if target_addr in instr_dict:
                instr_dict[target_addr][2] = label_dict[target_addr]

        instr_dict[counter] = [binary, asm, label, rtarget, atarget]
        counter = counter + (len(masm) // 2)

    print("")
    print("%s:\tfile format raw %s" %
          (os.path.basename(arguments['input_dma_file']), target.isa.name))
    print("")
    print("")
    print("Disassembly of section .code:")
    print("")

    str_format = "%8s:\t%-" + str(maxlen) + "s\t%s"
    for counter in sorted(instr_dict.keys()):

        binary, asm, label, rtarget, atarget = instr_dict[counter]

        if label is not None:
            print("%016x <%s>:" % (counter, label))

        cformat = str_format
        if rtarget is not None:
            cformat = str_format + "\t <%s>" % (label_dict[counter + rtarget])
        elif atarget is not None:
            cformat = str_format + "\t <%s>" % (label_dict[atarget])

        print(cformat % (hex(counter)[2:], binary, asm))
Beispiel #13
0
def import_properties(filename, objects):
    """

    :param filename:
    :param objects:

    """
    LOG.info("Start importing object properties")
    dirname = filename[::-1].replace('lmay.', 'sporp_', 1)[::-1]

    if not os.path.isdir(dirname):
        return

    for filename in os.listdir(dirname):

        if filename.startswith(".") or filename.endswith(".cache"):
            continue

        if not filename.endswith(".yaml"):
            continue

        property_definitions = read_yaml(
            os.path.join(
                dirname, filename
            ), SCHEMA
        )

        for property_def in property_definitions:
            property_objs = RejectingDict()
            property_name = property_def["Name"]
            property_description = property_def.get(
                "Description", "No description"
            )

            property_override = property_def.get("Override", False)

            property_default_value = property_def.get("Default", "__unset__")
            property_values = property_def.get("Values", {})

            property_class = Property

            LOG.debug(
                "Importing property '%s - %s'", property_name,
                property_description
            )

            if "Value" in property_def:
                # Single value
                property_value = property_def["Value"]
                default_property = property_class(
                    property_name, property_description, property_value
                )
                for obj in objects.values():
                    obj.register_property(
                        default_property,
                        force=property_override
                    )

                LOG.debug("Single value property")
                continue

            if (
                property_default_value != "__unset__" and
                property_default_value != "NO_DEFAULT"
            ):
                default_property = property_class(
                    property_name,
                    property_description,
                    property_default_value,
                    default=True
                )
                LOG.debug("Default value: %s", property_default_value)
            else:
                default_property = None
                LOG.debug("Default value: No default value set")

            for key, obj in objects.items():

                if key not in property_values:

                    if property_default_value == "NO_DEFAULT":
                        continue

                    if default_property is None:
                        raise MicroprobeArchitectureDefinitionError(
                            "Wrong property '%s' definition in file '%s'. "
                            "Value for '%s' is not provided and a default "
                            "value is not defined" % (
                                property_name, filename, key
                            )
                        )

                    obj.register_property(
                        default_property,
                        force=property_override
                    )

                else:

                    property_value = property_values[key]
                    del property_values[key]

                    property_value_key = property_value
                    if isinstance(property_value, list):
                        property_value_key = str(property_value)

                    if property_value_key in property_objs:
                        obj.register_property(
                            property_objs[property_value_key],
                            force=property_override
                        )
                    else:
                        new_property = property_class(
                            property_name,
                            property_description,
                            property_value,
                            default=False
                        )
                        obj.register_property(
                            new_property, force=property_override
                        )
                        property_objs[property_value_key] = new_property

            for key, value in property_values.items():
                LOG.warning(
                    "'%s' not found. Property '%s' not set to '%s'", key,
                    property_name, value
                )

            LOG.info("Property '%s' imported", property_name)

    LOG.info("End importing object properties")
Beispiel #14
0
class ResolveSymbolicReferencesPass(microprobe.passes.Pass):
    """ResolveSymbolicReferencesPass pass.

    """
    def __init__(self, strict=False, instructions=None):
        """ """
        super(ResolveSymbolicReferencesPass, self).__init__()
        self._description = "Translate labels of address into values"
        self._labels = RejectingDict()
        self._strict = strict
        self._instructions = []
        if instructions is not None:
            self._instructions = instructions

    def __call__(self, building_block, dummy_target):
        """

        :param building_block:
        :param dummy_target:

        """

        for instr in (elem for elem in building_block.init
                      if elem.label is not None):
            self._register_label(instr)

        for bbl in building_block.cfg.bbls:
            if MICROPROBE_RC['verbose']:
                progress = Progress(len(bbl.instrs), "Registering labels:")
            for instr in (elem for elem in bbl.instrs
                          if elem.label is not None):
                self._register_label(instr)

                if MICROPROBE_RC['verbose']:
                    progress()

        for instr in (elem for elem in building_block.fini
                      if elem.label is not None):
            self._register_label(instr)

        for instr in building_block.init:
            self._translate_label(instr, building_block.context)

        for bbl in building_block.cfg.bbls:
            if MICROPROBE_RC['verbose']:
                progress = Progress(len(bbl.instrs), "Translating labels:")
            for instr in bbl.instrs:
                self._translate_label(instr, building_block.context)
                if MICROPROBE_RC['verbose']:
                    progress()

        for instr in building_block.fini:
            self._translate_label(instr, building_block.context)

        return []

    def _register_label(self, instruction):
        """

        :param instruction:

        """
        if instruction.label is None:
            return
        else:
            self._labels[instruction.label.upper()] = instruction

    def _translate_label(self, instruction, context):
        """

        :param instruction:
        :param context:

        """

        if self._instructions != []:
            if instruction.name not in self._instructions:
                return

        for operand in instruction.operands():
            if operand.value is None:
                continue

            if not isinstance(operand.value, Address):
                continue

            address = operand.value
            LOG.debug("Translating label: '%s' of instruction '%s'", address,
                      instruction.name)

            if isinstance(address, InstructionAddress):

                if address.target_instruction is not None:

                    target_address = address.target_instruction.address
                    comment = "Reference to instruction at"

                elif (isinstance(address.base_address, str)
                      and address.base_address.upper() in list(
                          self._labels.keys())):

                    target_address = self._labels[
                        address.base_address.upper()].address + \
                        address.displacement
                    comment = "Reference to %s at" % address

                elif (isinstance(address.base_address, str)
                      and address.base_address.upper() == "CODE"):

                    target_address = address
                    comment = "Reference to %s at" % address

                else:

                    LOG.critical(address.base_address)
                    LOG.critical(address)
                    LOG.critical(list(self._labels.keys()))
                    raise NotImplementedError

                if operand.type.address_relative:

                    if context.code_segment is not None:
                        instruction.add_comment(
                            "%s %s" % (comment,
                                       hex(context.code_segment +
                                           target_address.displacement)))

                    relative_offset = target_address - instruction.address
                    operand.set_value(relative_offset, check=self._strict)

                else:

                    raise NotImplementedError

            elif isinstance(address.base_address, Variable):

                target_address = Address(
                    base_address=address.base_address.address,
                    displacement=address.displacement)

                if operand.type.address_relative:

                    # Code referencing data, fix address taking into account
                    # code and data offsets
                    if instruction.address.base_address == "code" and \
                            target_address.base_address == "data" and \
                            context.data_segment is not None and \
                            context.code_segment is not None:

                        instruction_address = Address(
                            base_address="temp",
                            displacement=context.code_segment +
                            instruction.address.displacement)

                        data_address = Address(
                            base_address="temp",
                            displacement=context.data_segment +
                            target_address.displacement)

                        # instruction_address = Address(base_address="data",
                        #        displacement=instruction.address.displacement)

                        relative_offset = data_address - instruction_address

                        try:
                            operand.set_value(relative_offset)
                        except MicroprobeValueError:
                            raise MicroprobeCodeGenerationError(
                                "Unable to codify the relative offset from "
                                "instruction at 0x%x to data at 0x%x. "
                                "Review the correctness of the addresses and "
                                "change them." %
                                (instruction_address.displacement,
                                 data_address.displacement))

                        comment = "Reference to var '%s' at" \
                            % address.base_address.name
                        instruction.add_comment(
                            "%s %s" %
                            (comment, hex(data_address.displacement)))

                    else:

                        LOG.critical(instruction.address.base_address)
                        LOG.critical(target_address.base_address)
                        LOG.critical(context.data_segment)
                        LOG.critical(context.code_segment)
                        LOG.critical(context.symbolic)

                        LOG.critical(target_address)

                        LOG.critical(instruction)
                        LOG.critical(operand)

                        raise NotImplementedError

                else:
                    raise NotImplementedError
            else:
                LOG.critical(instruction, instruction.address, address)
                LOG.critical(address.base_address, type(address.base_address))
                raise NotImplementedError
Beispiel #15
0
 def __init__(self):
     """ """
     super(NormalizeBranchTargetsPass, self).__init__()
     self._description = "Normalize branch targets to remove the usage" \
         "of labels"
     self._labels = RejectingDict()
Beispiel #16
0
class NormalizeBranchTargetsPass(Pass):
    """NormalizeBranchTargetsPass pass.

    """
    def __init__(self):
        """ """
        super(NormalizeBranchTargetsPass, self).__init__()
        self._description = "Normalize branch targets to remove the usage" \
            "of labels"
        self._labels = RejectingDict()

    def __call__(self, building_block, dummy_target):
        """

        :param building_block:
        :param dummy_target:

        """

        for instr in (elem for elem in building_block.init
                      if elem.label is not None):
            self._register_label(instr)

        for bbl in building_block.cfg.bbls:
            for instr in (elem for elem in bbl.instrs
                          if elem.label is not None):
                self._register_label(instr)

        for instr in (elem for elem in building_block.fini
                      if elem.label is not None):
            self._register_label(instr)

        for instr in building_block.init:
            self._normalize_label(instr)

        for bbl in building_block.cfg.bbls:
            for instr in bbl.instrs:
                self._normalize_label(instr)

        for instr in building_block.fini:
            self._normalize_label(instr)

        return []

    def _register_label(self, instruction):
        """

        :param instruction:

        """
        if instruction.label is None:
            return
        else:
            self._labels[instruction.label.upper()] = instruction

    def _normalize_label(self, instruction):
        """

        :param instruction:
        :param context:

        """

        for operand in instruction.operands():

            if operand.value is None:
                continue

            if not isinstance(operand.value, InstructionAddress):
                continue

            address = operand.value
            LOG.debug("Normalizing label: '%s' of instruction '%s'", address,
                      instruction.name)

            if address.target_instruction is not None:

                target_address = address.target_instruction.address

            elif (isinstance(address.base_address, str) and
                  address.base_address.upper() in list(self._labels.keys())):

                target_address = self._labels[
                    address.base_address.upper()].address + \
                    address.displacement

            else:
                LOG.critical(address.base_address)
                LOG.critical(address)
                LOG.critical(list(self._labels.keys()))
                raise NotImplementedError

            operand.set_value(target_address)

        for moperand in instruction.memory_operands():

            if moperand.address is None:
                continue

            if not isinstance(moperand.address, InstructionAddress):
                continue

            address = moperand.address
            LOG.debug("Normalizing label: '%s' of instruction '%s'", address,
                      instruction.name)

            if address.target_instruction is not None:

                target_address = address.target_instruction.address

            elif (isinstance(address.base_address, str) and
                  address.base_address.upper() in list(self._labels.keys())):

                target_address = self._labels[
                    address.base_address.upper()].address + \
                    address.displacement

            else:
                LOG.critical(address.base_address)
                LOG.critical(address)
                LOG.critical(list(self._labels.keys()))
                raise NotImplementedError

            moperand.update_address(target_address)
Beispiel #17
0
class Context(object):  # pylint: disable=too-many-public-methods
    """Class to represent the execution context (e.g. register values, etc ...
    on each benchmark building block)


    """
    def __init__(self,
                 default_context=None,
                 code_segment=None,
                 data_segment=None,
                 symbolic=True,
                 absolute=False):
        """

        :param default_context:  (Default value = None)
        :param code_segment:  (Default value = None)
        :param data_segment:  (Default value = None)
        :param symbolic:  (Default value = True)

        """

        self._reserved_registers = RejectingDict()
        self._register_values = [{}, {}]
        self._memory_values = [{}, {}]

        self._data_segment = data_segment
        self._code_segment = code_segment
        self._symbolic = symbolic
        self._fabsolute = absolute

        self._dat = None

        if default_context is not None:
            self = default_context.copy()

    def copy(self):
        """Returns a copy of the current context."""

        newcontext = Context()

        # pylint: disable=protected-access
        newcontext._reserved_registers = smart_copy_dict(
            self._reserved_registers)
        newcontext._register_values[0] = smart_copy_dict(
            self._register_values[0])
        newcontext._register_values[1] = smart_copy_dict(
            self._register_values[1])
        newcontext._memory_values[0] = smart_copy_dict(self._memory_values[0])
        newcontext._memory_values[1] = smart_copy_dict(
            self._register_values[1])

        if self._dat is not None:
            newcontext.set_dat(self._dat.copy())

        newcontext.set_code_segment(self.code_segment)
        newcontext.set_data_segment(self.data_segment)
        newcontext.set_symbolic(self.symbolic)
        newcontext.set_absolute(self.force_absolute)

        return newcontext

    def add_reserved_registers(self, rregs):
        """Add the provided registers into the reserved register list.

        :param rregs: Registers to reserve
        :type rregs: :class:`~.list` of :class:`~.Register`

        """

        for reg in rregs:
            self._reserved_registers[reg.name] = reg

    def remove_reserved_registers(self, rregs):
        """Remove the provided registers from the reserved register list.

        :param rregs: Registers to un-reserve
        :type rregs: :class:`~.list` of :class:`~.Register`

        """

        for reg in rregs:
            del self._reserved_registers[reg.name]

    def set_register_value(self, register, value):
        """Set the provided register to the specified value.

        :param register: Register to set
        :type register: :class:`~.Register`
        :param value: Value to assign
        :type value: :class:`~.int`, :class:`~.float`, :class:`~.long`,
             :class:`~.Address` or :class:`~.str`

        """

        LOG.debug("Setting %s to %s", register.name, value)

        assert isinstance(
            value,
            tuple(
                list(six.integer_types) +
                [float, Address, InstructionAddress, str])), type(value)

        if isinstance(value, str):
            assert len(value.split("_")) == 2

        if self.get_register_value(register) is not None:
            self.unset_register(register)

        self._register_values[0][register] = value

        if value in self._register_values[1]:
            if register not in self._register_values[1][value]:
                self._register_values[1][value].append(register)
        else:
            self._register_values[1][value] = [register]

        # assert self.get_register_value(register) == value
        # assert value in self._register_values[1].keys()
        # assert self._register_values[0][register] == value

    def get_closest_address_value(self, address):
        """Returns the closest address to the given address.

        Returns the closest address to the given address. If there are
        not addresses registered, `None` is returned.

        :param address: Address to look for
        :type address: :class:`~.Address`

        """

        possible_regs = []

        for reg, value in self._register_values[0].items():

            if not isinstance(value, Address):
                continue

            if Address(base_address=value.base_address) == \
                    Address(base_address=address.base_address):
                possible_regs.append((reg, value))

        possible_regs = sorted(
            possible_regs,
            key=lambda x: abs(x[1].displacement - address.displacement))
        if possible_regs:
            return possible_regs[0]

        return None

    def get_register_closest_value(self, value):
        """Returns the register with the closest value to the given value.

        Returns the register with the closest value to the given value.
        If there are not values registered, `None` is returned.
        Address values are ignored.

        :param value: Value to look for
        :type value: :class:`~.int`, :class:`~.float`, :class:`~.long`,
             :class:`~.Address` or :class:`~.str`

        """

        possible_regs = []

        for reg, reg_value in self._register_values[0].items():

            if isinstance(value, Address):
                continue

            if not isinstance(reg_value, type(value)):
                continue

            if isinstance(reg_value, str):
                if reg_value.split("_")[1] != value.split(" ")[1]:
                    continue

            possible_regs.append((reg, reg_value))

        if not isinstance(value, str):
            possible_regs = sorted(possible_regs, key=lambda x: abs(x - value))
        else:
            possible_regs = sorted(
                possible_regs,
                key=lambda x: abs(
                    int(x.split("_")[0]) - int(value.split("_")[0])))

        if possible_regs:
            return possible_regs[0]

        return None

    def get_register_value(self, register):
        """Returns the register value. `None` if not found.

        :param register: Register to get its value
        :type register: :class:`~.Register`

        """

        value = self._register_values[0].get(register, None)
        if value is not None:
            assert value in self._register_values[1].keys()

        return value

    def get_registername_value(self, register_name):
        """Returns the register value. `None` if not found.

        :param register: Register name to get its value
        :type register: :class:`~.str`
        :param register_name:

        """
        assert isinstance(register_name, str)

        register_names = [reg.name for reg in self._register_values[0]]
        if register_name not in register_names:
            return None

        register = [
            reg for reg in self._register_values[0]
            if reg.name == register_name
        ][0]

        return self._register_values[0].get(register, None)

    def unset_registers(self, registers):
        """Removes the values from registers.

        :param registers: List of registers
        :type registers: :class:`~.list` of :class:`~.Register`

        """
        for reg in registers:
            self.unset_register(reg)

    def unset_register(self, register):
        """Remove the value from a register.

        :param register: Registers
        :type register: :class:`~.Register`

        """

        assert self._register_values[0][register] is not None

        value = self._register_values[0][register]
        self._register_values[1][value].remove(register)

        if not self._register_values[1][value]:
            del self._register_values[1][value]

        self._register_values[0][register] = None

    def set_memory_value(self, mem_value):
        """Sets a memory value.

        :param mem_value: Memory value to set.
        :type mem_value: :class:`~.MemoryValue`

        """

        LOG.debug("Start set memory value: %s", mem_value)

        self.unset_memory(mem_value.address, mem_value.length)
        self._memory_values[0][mem_value.address] = mem_value

        if mem_value.value in self._memory_values[0]:

            if mem_value not in self._memory_values[1][mem_value.value]:

                self._memory_values[1][mem_value.value].append(mem_value)
                LOG.debug("Values inv %s: %s", mem_value.value,
                          self._memory_values[1][mem_value.value])

            else:
                LOG.debug("Already in inv dictionary")

        else:

            self._memory_values[1][mem_value.value] = [mem_value]
            LOG.debug("Values inv %s: %s", mem_value.value, [mem_value])

        assert self._memory_values[0][mem_value.address] == mem_value
        assert mem_value in self._memory_values[1][mem_value.value]

        LOG.debug("End set memory value: %s", mem_value)

    def get_memory_value(self, address):
        """Gets a memory value.

        :param address: Address to look for
        :type address: :class:`~.Address`

        """

        if address in self._memory_values[0]:
            return self._memory_values[0][address]

        return None

    def unset_memory(self, address, length):
        """Unsets a memory region.

        :param address: Start address of the region
        :type address: :class:`~.Address`
        :param length: Length in bytes of the region
        :type length: :class:`~.int`

        """

        LOG.debug("Start unset address: %s (length: %s)", address, length)

        possible_addresses = [
            addr for addr in self._memory_values[0]
            if addr.base_address == address.base_address
        ]

        # LOG.debug("Possible addresses: %s", possible_addresses)

        for paddr in possible_addresses:

            diff = paddr - address
            diff2 = address - paddr
            length2 = self._memory_values[0][paddr].length

            if ((diff >= 0 and diff < length)
                    or (diff2 >= 0 and diff2 < length2)):

                LOG.debug("Address overlap: %s", paddr)
                mem_value = self._memory_values[0].pop(paddr)

                LOG.debug("Memory value: %s", mem_value)

                if mem_value in self._memory_values[1][mem_value.value]:
                    self._memory_values[1][mem_value.value].remove(mem_value)

        LOG.debug("Finish unset address: %s (length: %s)", address, length)

    def register_has_value(self, value):
        """Returns if a value is in a register.

        :param value: Value to look for
        :type value: :class:`~.bool`

        """
        return value in list([
            elem for elem in self._register_values[1].keys()
            if type(elem) == type(value)
        ])

    def registers_get_value(self, value):
        """Gets a list of registers containing the specified value.

        :param value: Value to look for
        :type value: :class:`~.int` or :class:`~.float` or :class:`~.Address`

        """

        keyl = [key for key in self._register_values[1] if key == value]

        if len(keyl) != 1:
            assert keyl == 1

        return self._register_values[1][keyl[0]]

    @property
    def register_values(self):
        """Dictionary of register, value pairs (:class:`~.dict`)"""
        return self._register_values[0]

    @property
    def reserved_registers(self):
        """List of reserved registers (:class:`~.list`)"""
        return list(self._reserved_registers.values())

    @property
    def data_segment(self):
        """Address starting the data segment (::class:`~.int`)"""
        return self._data_segment

    def set_data_segment(self, value):
        """Sets the data segment start address.

        :param value: Start address.
        :type value: ::class:`~.int`

        """
        self._data_segment = value

    @property
    def dat(self):
        """DAT object (:class:`~.DynamicAddressTranslation`"""
        return self._dat

    def set_dat(self, dat):
        """Sets the dynamic address translation object.

        :param dat: DAT object.
        :type dat: :class:`~.DynamicAddressTranslation`

        """
        self._dat = dat

    @property
    def code_segment(self):
        """Address starting the code segment (::class:`~.int`)"""
        return self._code_segment

    def set_code_segment(self, value):
        """Sets the code segment start address.

        :param value: Start address.
        :type value: :class:`~.int`

        """
        self._code_segment = value

    @property
    def symbolic(self):
        """Boolean indicating if the context allows symbol labels

        Boolean indicating if the context allows symbol labels
        (:class:`~.bool`)
        """
        return self._symbolic

    def set_symbolic(self, value):
        """Sets the symbolic property.

        :param value: Boolean indicating if the context allows symbol labels
        :type value: :class:`~.bool`

        """
        self._symbolic = value

    @property
    def force_absolute(self):
        """Boolean indicating if absolute addresses are needed.

        Boolean indicating if absolute addresses are needed
        (:class:`~.bool`)
        """
        return self._fabsolute

    def set_absolute(self, value):
        """Sets the force_absolute property.

        :param value: Boolean indicating if absolute addresses are needed
        :type value: :class:`~.bool`

        """
        self._fabsolute = value

    # def _validate(self):
    #     for register in self._register_values[0]:
    #        value = self._register_values[0][register]
    #        if value is not None:
    #            assert register in self._register_values[1][value]

    def dump(self):
        """Return a dump of the current context status.

        Return a dump of the current context status. Very useful for pass
        debugging purposes.


        """

        mstr = []
        mstr.append("-" * 80)
        mstr.append("Context status:")
        mstr.append("Reserved Registers:")

        for key, value in sorted(self._reserved_registers.items()):
            mstr.append("Idx:\t%s\tValue:\t%s" % (key, value))

        mstr.append("Registers values:")
        for key, value in sorted(self._register_values[0].items()):
            mstr.append("Idx:\t%s\tRaw Value:\t%s" % (key, value))

        mstr.append("Registers values inverted:")
        for key, value in sorted(self._register_values[1].items()):
            mstr.append("Idx:\t%s\tValue:\t%s" % (key, value))

        mstr.append("Memory values:")
        for key, value in sorted(self._memory_values[0].items()):
            mstr.append("Idx:\t%s\tRaw Value:\t%s" % (key, value))

        mstr.append("Memory values inverted:")
        for key, value in sorted(self._memory_values[1].items()):
            mstr.append("Idx:\t%s\tValue:\t%s" % (key, value))

        mstr.append("Code segment: %s" % self._code_segment)
        mstr.append("Data segment: %s" % self._data_segment)
        mstr.append("Symbolic context: %s" % self._symbolic)

        mstr.append("-" * 80)

        return "\n".join(mstr)
Beispiel #18
0

# Constants
LOG = get_logger(__name__)

_BIN_CACHE_ENABLED = True
_BIN_CACHE_FILE = __file__ + ".bin"
_BIN_CACHE = None
_BIN_CACHE_USED = False
_BIN_CACHE_SIZE = 16*1024
_CODE_CACHE_ENABLED = True
_CODE_CACHE_FILE = __file__ + ".code"
_CODE_CACHE = None
_CODE_CACHE_USED = False
_CODE_CACHE_SIZE = 16*1024
_DATA_CACHE = RejectingDict()
_DATA_CACHE_LENGTHS = []
_DATA_CACHE_ENABLED = True

__all__ = ["interpret_bin",
           "MicroprobeBinInstructionStream", ]


# Functions
def interpret_bin(
        code, target, fmt="hex", safe=None,
        single=False, little_endian=None, word_length=None
        ):
    """
    Return the list of :class:`~.MicroprobeInstructionDefinition` objects
    that results from interpreting the *code* (a binary stream).
Beispiel #19
0
def import_definition(cls, filenames, element_types):
    """ """
    LOG.debug("Start importing microarchitecture elements")

    elements = RejectingDict()
    elements_subelements = RejectingDict()

    for filename in filenames:
        element_data = read_yaml(filename, SCHEMA)

        if element_data is None:
            continue

        for elem in element_data:
            name = elem["Name"]
            parent = elem.get("Parent", None)
            subelements = elem.get("Subelements", [])
            repeat = elem.get("Repeat", None)
            rfrom = 0
            rto = 0
            replace = "0"

            try:
                elem_type = element_types[elem["Type"]]
            except KeyError:
                raise MicroprobeArchitectureDefinitionError(
                    "Unknown "
                    "microarchitecture element type in "
                    "microarchitecture element definition "
                    " '%s' found in '%s'" % (name, filename))
            descr = elem.get("Description", elem_type.description)

            if repeat:
                rfrom = repeat["From"]
                replace = "%s" % rfrom
                rto = repeat["To"]

            for index in range(rfrom, rto + 1):
                cname = name.replace(replace, "%d" % index)
                cdescr = descr.replace(replace, "%d" % index)
                element = cls(cname, cdescr, elem_type)

                try:
                    elements[cname] = element
                    elements_subelements[cname] = subelements
                except ValueError:
                    raise MicroprobeArchitectureDefinitionError(
                        "Duplicated microarchitecture element "
                        "definition '%s' found in '%s'" % (name, filename))

            LOG.debug(element)

    for filename in filenames:
        import_properties(filename, elements)

    for elem, subelements in elements_subelements.items():
        try:
            subelements_instances = [elements[item] for item in subelements]
        except KeyError as exc:
            raise MicroprobeArchitectureDefinitionError(
                "Undefined sub-element '%s' in element "
                "definition '%s'. Check following "
                "files: %s" % (exc, elem, filenames))

        elements[elem].set_subelements(subelements_instances)

    element_list = list(elements.values())
    fixing_hierarchy = True

    LOG.info("Start building element hierarchy...")
    fix_pass = 0
    while fixing_hierarchy:
        fix_pass += 1
        LOG.debug("Start building element hierarchy... pass %d", fix_pass)
        fixing_hierarchy = False
        for element in element_list:
            parents = [
                item for item in element_list if element in item.subelements
            ]

            if len(parents) > 1:
                # needs duplication

                LOG.debug("Element %s has %d parents", element, len(parents))

                for parent in sorted(parents):
                    LOG.debug("Duplicating for parent: %s", parent)
                    # Create a new copy
                    new_element = cls(element.name, element.description,
                                      element.type)
                    new_element.set_subelements(element.subelements)
                    element_list.append(new_element)

                    # Update parent to point to the new copy
                    new_subelements = parent.subelements
                    new_subelements.remove(element)
                    new_subelements.append(new_element)
                    parent.set_subelements(new_subelements)
                    fixing_hierarchy = True

                element_list.remove(element)

    LOG.info("Finish building element hierarchy")

    # Check correctness of the structure and set parents
    LOG.info("Checking element hierarchy...")
    top_element = None
    for element in element_list:
        parents = [
            item for item in element_list if element in item.subelements
        ]

        if len(parents) > 1:
            raise MicroprobeArchitectureDefinitionError(
                "Wrong hierarchy of microarchitecture "
                "elements. The definition of element"
                " '%s' has multiple parents: '%s'." %
                (element, [str(elem) for elem in parents]))
        elif len(parents) == 0:
            if top_element is not None:
                raise MicroprobeArchitectureDefinitionError(
                    "Wrong hierarchy of microarchitecture "
                    "elements. There are at least two top "
                    "elements: '%s' and '%s'. Define a single "
                    "parent element for all the hierarchy." %
                    (element, top_element))
            top_element = element
        else:
            element.set_parent_element(parents[0])

    if top_element is None:
        raise MicroprobeArchitectureDefinitionError(
            "Wrong hierarchy of microarchitecture "
            "elements. There is not a top element."
            " Define a single parent element for all "
            "the hierarchy.")

    LOG.info("Element hierarchy correct")

    elem_dict = dict([(element.full_name, element)
                      for element in element_list])

    for filename in filenames:
        import_properties(filename, elem_dict)

    LOG.info("End importing elements")
    return elem_dict