Top

miasm.core.ctypesmngr module

import re

from pycparser import c_parser, c_ast

RE_HASH_CMT = re.compile(r'^#\s*\d+.*$', flags=re.MULTILINE)

# Ref: ISO/IEC 9899:TC2
# http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf


def c_to_ast(parser, c_str):
    """Transform a @c_str into a C ast
    Note: will ignore lines containing code refs ie:
    # 23 "miasm.h"

    @parser: pycparser instance
    @c_str: c string
    """

    new_str = re.sub(RE_HASH_CMT, "", c_str)
    return parser.parse(new_str, filename='<stdin>')


class CTypeBase(object):
    """Object to represent the 3 forms of C type:
    * object types
    * function types
    * incomplete types
    """

    def __init__(self):
        self.__repr = str(self)
        self.__hash = hash(self.__repr)

    @property
    def _typerepr(self):
        return self.__repr

    def __eq__(self, other):
        raise NotImplementedError("Abstract method")

    def __ne__(self, other):
        return not self.__eq__(other)

    def eq_base(self, other):
        """Trivial common equality test"""
        return self.__class__ == other.__class__

    def __hash__(self):
        return self.__hash

    def __repr__(self):
        return self._typerepr


class CTypeId(CTypeBase):
    """C type id:
    int
    unsigned int
    """

    def __init__(self, *names):
        # Type specifier order does not matter
        # so the canonical form is ordered
        self.names = tuple(sorted(names))
        super(CTypeId, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.names))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.names == other.names)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Id:%s>" % ', '.join(self.names)


class CTypeArray(CTypeBase):
    """C type for array:
    typedef int XXX[4];
    """

    def __init__(self, target, size):
        assert isinstance(target, CTypeBase)
        self.target = target
        self.size = size
        super(CTypeArray, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.target, self.size))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.target == other.target and
                self.size == other.size)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Array[%s]:%s>" % (self.size, str(self.target))


class CTypePtr(CTypeBase):
    """C type for pointer:
    typedef int* XXX;
    """

    def __init__(self, target):
        assert isinstance(target, CTypeBase)
        self.target = target
        super(CTypePtr, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.target))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.target == other.target)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Ptr:%s>" % str(self.target)


class CTypeStruct(CTypeBase):
    """C type for structure"""

    def __init__(self, name, fields=None):
        assert name is not None
        self.name = name
        if fields is None:
            fields = ()
        for field_name, field in fields:
            assert field_name is not None
            assert isinstance(field, CTypeBase)
        self.fields = tuple(fields)
        super(CTypeStruct, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name, self.fields))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name and
                self.fields == other.fields)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        out = []
        out.append("<Struct:%s>" % self.name)
        for name, field in self.fields:
            out.append("\t%-10s %s" % (name, field))
        return '\n'.join(out)


class CTypeUnion(CTypeBase):
    """C type for union"""

    def __init__(self, name, fields=None):
        assert name is not None
        self.name = name
        if fields is None:
            fields = []
        for field_name, field in fields:
            assert field_name is not None
            assert isinstance(field, CTypeBase)
        self.fields = tuple(fields)
        super(CTypeUnion, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name, self.fields))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name and
                self.fields == other.fields)

    def __str__(self):
        out = []
        out.append("<Union:%s>" % self.name)
        for name, field in self.fields:
            out.append("\t%-10s %s" % (name, field))
        return '\n'.join(out)


class CTypeEnum(CTypeBase):
    """C type for enums"""

    def __init__(self, name):
        self.name = name
        super(CTypeEnum, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Enum:%s>" % self.name


class CTypeFunc(CTypeBase):
    """C type for enums"""

    def __init__(self, name, abi=None, type_ret=None, args=None):
        if type_ret:
            assert isinstance(type_ret, CTypeBase)
        if args:
            for arg_name, arg in args:
                assert isinstance(arg, CTypeBase)
            args = tuple(args)
        else:
            args = tuple()
        self.name = name
        self.abi = abi
        self.type_ret = type_ret
        self.args = args
        super(CTypeFunc, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name, self.abi,
                     self.type_ret, self.args))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name and
                self.abi == other.abi and
                self.type_ret == other.type_ret and
                self.args == other.args)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Func:%s (%s) %s(%s)>" % (self.type_ret,
                                          self.abi,
                                          self.name,
                                          ", ".join(["%s %s" % (name, arg) for (name, arg) in self.args]))


class CTypeEllipsis(CTypeBase):
    """C type for ellipsis argument (...)"""

    def __hash__(self):
        return hash((self.__class__))

    def __eq__(self, other):
        return self.eq_base(other)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Ellipsis>"


class CTypeSizeof(CTypeBase):
    """C type for sizeof"""

    def __init__(self, target):
        self.target = target
        super(CTypeSizeof, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.target))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.target == other.target)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Sizeof(%s)>" % self.target


class CTypeOp(CTypeBase):
    """C type for operator (+ * ...)"""

    def __init__(self, operator, *args):
        self.operator = operator
        self.args = tuple(args)
        super(CTypeOp, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.operator, self.args))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.operator == other.operator and
                self.args == other.args)

    def __str__(self):
        return "<CTypeOp(%s, %s)>" % (self.operator,
                                      ', '.join([str(arg) for arg in self.args]))


class FuncNameIdentifier(c_ast.NodeVisitor):
    """Visit an c_ast to find IdentifierType"""

    def __init__(self):
        super(FuncNameIdentifier, self).__init__()
        self.node_name = None

    def visit_TypeDecl(self, node):
        """Retrieve the name in a function declaration:
        Only one IdentifierType is present"""
        self.node_name = node


class CAstTypes(object):
    """Store all defined C types and typedefs"""
    INTERNAL_PREFIX = "__GENTYPE__"
    ANONYMOUS_PREFIX = "__ANONYMOUS__"

    def __init__(self, knowntypes=None, knowntypedefs=None):
        if knowntypes is None:
            knowntypes = {}
        if knowntypedefs is None:
            knowntypedefs = {}

        self._types = dict(knowntypes)
        self._typedefs = dict(knowntypedefs)
        self.cpt = 0
        self.loc_to_decl_info = {}
        self.parser = c_parser.CParser()
        self._cpt_decl = 0


        self.ast_to_typeid_rules = {
            c_ast.Struct: self.ast_to_typeid_struct,
            c_ast.Union: self.ast_to_typeid_union,
            c_ast.IdentifierType: self.ast_to_typeid_identifiertype,
            c_ast.TypeDecl: self.ast_to_typeid_typedecl,
            c_ast.Decl: self.ast_to_typeid_decl,
            c_ast.Typename: self.ast_to_typeid_typename,
            c_ast.FuncDecl: self.ast_to_typeid_funcdecl,
            c_ast.Enum: self.ast_to_typeid_enum,
            c_ast.PtrDecl: self.ast_to_typeid_ptrdecl,
            c_ast.EllipsisParam: self.ast_to_typeid_ellipsisparam,
            c_ast.ArrayDecl: self.ast_to_typeid_arraydecl,
        }

        self.ast_parse_rules = {
            c_ast.Struct: self.ast_parse_struct,
            c_ast.Union: self.ast_parse_union,
            c_ast.Typedef: self.ast_parse_typedef,
            c_ast.TypeDecl: self.ast_parse_typedecl,
            c_ast.IdentifierType: self.ast_parse_identifiertype,
            c_ast.Decl: self.ast_parse_decl,
            c_ast.PtrDecl: self.ast_parse_ptrdecl,
            c_ast.Enum: self.ast_parse_enum,
            c_ast.ArrayDecl: self.ast_parse_arraydecl,
            c_ast.FuncDecl: self.ast_parse_funcdecl,
            c_ast.FuncDef: self.ast_parse_funcdef,
            c_ast.Pragma: self.ast_parse_pragma,
        }

    def gen_uniq_name(self):
        """Generate uniq name for unnamed strucs/union"""
        cpt = self.cpt
        self.cpt += 1
        return self.INTERNAL_PREFIX + "%d" % cpt

    def gen_anon_name(self):
        """Generate name for anonymous strucs/union"""
        cpt = self.cpt
        self.cpt += 1
        return self.ANONYMOUS_PREFIX + "%d" % cpt

    def is_generated_name(self, name):
        """Return True if the name is internal"""
        return name.startswith(self.INTERNAL_PREFIX)

    def is_anonymous_name(self, name):
        """Return True if the name is anonymous"""
        return name.startswith(self.ANONYMOUS_PREFIX)

    def add_type(self, type_id, type_obj):
        """Add new C type
        @type_id: Type descriptor (CTypeBase instance)
        @type_obj: Obj* instance"""
        assert isinstance(type_id, CTypeBase)
        if type_id in self._types:
            assert self._types[type_id] == type_obj
        else:
            self._types[type_id] = type_obj

    def add_typedef(self, type_new, type_src):
        """Add new typedef
        @type_new: CTypeBase instance of the new type name
        @type_src: CTypeBase instance of the target type"""
        assert isinstance(type_src, CTypeBase)
        self._typedefs[type_new] = type_src

    def get_type(self, type_id):
        """Get ObjC corresponding to the @type_id
        @type_id: Type descriptor (CTypeBase instance)
        """
        assert isinstance(type_id, CTypeBase)
        if isinstance(type_id, CTypePtr):
            subobj = self.get_type(type_id.target)
            return CTypePtr(subobj)
        if type_id in self._types:
            return self._types[type_id]
        elif type_id in self._typedefs:
            return self.get_type(self._typedefs[type_id])
        return type_id

    def is_known_type(self, type_id):
        """Return true if @type_id is known
        @type_id: Type descriptor (CTypeBase instance)
        """
        if isinstance(type_id, CTypePtr):
            return self.is_known_type(type_id.target)
        if type_id in self._types:
            return True
        if type_id in self._typedefs:
            return self.is_known_type(self._typedefs[type_id])
        return False

    def add_c_decl_from_ast(self, ast):
        """
        Adds types from a C ast
        @ast: C ast
        """
        self.ast_parse_declarations(ast)


    def digest_decl(self, c_str):

        char_id = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"


        # Seek deck
        index_decl = []
        index = 0
        for decl in ['__cdecl__', '__stdcall__']:
            index = 0
            while True:
                index = c_str.find(decl, index)
                if index == -1:
                    break
                decl_off = index
                decl_len = len(decl)

                index = index+len(decl)
                while c_str[index] not in char_id:
                    index += 1

                id_start = index

                while c_str[index] in char_id:
                    index += 1
                id_stop = index

                name = c_str[id_start:id_stop]
                index_decl.append((decl_off, decl_len, id_start, id_stop, decl, ))

        index_decl.sort()

        # Remove decl
        off = 0
        offsets = []
        for decl_off, decl_len, id_start, id_stop, decl in index_decl:
            decl_off -= off
            c_str = c_str[:decl_off] + c_str[decl_off+decl_len:]
            off += decl_len
            offsets.append((id_start-off, id_stop-off, decl))

        index = 0
        lineno = 1

        # Index to lineno, column
        for id_start, id_stop, decl in offsets:
            nbr = c_str.count('\n', index, id_start)
            lineno += nbr
            last_cr = c_str.rfind('\n', 0, id_start)
            # column starts at 1
            column = id_start - last_cr
            index = id_start
            self.loc_to_decl_info[(lineno, column)] = decl
        return c_str


    def add_c_decl(self, c_str):
        """
        Adds types from a C string types declaring
        Note: will ignore lines containing code refs ie:
        '# 23 "miasm.h"'
        Returns the C ast
        @c_str: C string containing C types declarations
        """
        c_str = self.digest_decl(c_str)

        ast = c_to_ast(self.parser, c_str)
        self.add_c_decl_from_ast(ast)

        return ast

    def ast_eval_int(self, ast):
        """Eval a C ast object integer

        @ast: parsed pycparser.c_ast object
        """

        if isinstance(ast, c_ast.BinaryOp):
            left = self.ast_eval_int(ast.left)
            right = self.ast_eval_int(ast.right)
            is_pure_int = (isinstance(left, int) and
                           isinstance(right, int))

            if is_pure_int:
                if ast.op == '*':
                    result = left * right
                elif ast.op == '/':
                    assert left % right == 0
                    result = left // right
                elif ast.op == '+':
                    result = left + right
                elif ast.op == '-':
                    result = left - right
                elif ast.op == '<<':
                    result = left << right
                elif ast.op == '>>':
                    result = left >> right
                else:
                    raise NotImplementedError("Not implemented!")
            else:
                result = CTypeOp(ast.op, left, right)

        elif isinstance(ast, c_ast.UnaryOp):
            if ast.op == 'sizeof' and isinstance(ast.expr, c_ast.Typename):
                subobj = self.ast_to_typeid(ast.expr)
                result = CTypeSizeof(subobj)
            else:
                raise NotImplementedError("Not implemented!")

        elif isinstance(ast, c_ast.Constant):
            result = int(ast.value, 0)
        elif isinstance(ast, c_ast.Cast):
            # TODO: Can trunc integers?
            result = self.ast_eval_int(ast.expr)
        else:
            raise NotImplementedError("Not implemented!")
        return result

    def ast_to_typeid_struct(self, ast):
        """Return the CTypeBase of an Struct ast"""
        name = self.gen_uniq_name() if ast.name is None else ast.name
        args = []
        if ast.decls:
            for arg in ast.decls:
                if arg.name is None:
                    arg_name = self.gen_anon_name()
                else:
                    arg_name = arg.name
                args.append((arg_name, self.ast_to_typeid(arg)))
        decl = CTypeStruct(name, args)
        return decl

    def ast_to_typeid_union(self, ast):
        """Return the CTypeBase of an Union ast"""
        name = self.gen_uniq_name() if ast.name is None else ast.name
        args = []
        if ast.decls:
            for arg in ast.decls:
                if arg.name is None:
                    arg_name = self.gen_anon_name()
                else:
                    arg_name = arg.name
                args.append((arg_name, self.ast_to_typeid(arg)))
        decl = CTypeUnion(name, args)
        return decl

    def ast_to_typeid_identifiertype(self, ast):
        """Return the CTypeBase of an IdentifierType ast"""
        return CTypeId(*ast.names)

    def ast_to_typeid_typedecl(self, ast):
        """Return the CTypeBase of a TypeDecl ast"""
        return self.ast_to_typeid(ast.type)

    def ast_to_typeid_decl(self, ast):
        """Return the CTypeBase of a Decl ast"""
        return self.ast_to_typeid(ast.type)

    def ast_to_typeid_typename(self, ast):
        """Return the CTypeBase of a TypeName ast"""
        return self.ast_to_typeid(ast.type)

    def get_funcname(self, ast):
        """Return the name of a function declaration ast"""
        funcnameid = FuncNameIdentifier()
        funcnameid.visit(ast)
        node_name = funcnameid.node_name
        if node_name.coord is not None:
            lineno, column = node_name.coord.line, node_name.coord.column
            decl_info = self.loc_to_decl_info.get((lineno, column), None)
        else:
            decl_info = None
        return node_name.declname, decl_info

    def ast_to_typeid_funcdecl(self, ast):
        """Return the CTypeBase of an FuncDecl ast"""
        type_ret = self.ast_to_typeid(ast.type)
        name, decl_info = self.get_funcname(ast.type)
        if ast.args:
            args = []
            for arg in ast.args.params:
                typeid = self.ast_to_typeid(arg)
                if isinstance(typeid, CTypeEllipsis):
                    arg_name = None
                else:
                    arg_name = arg.name
                args.append((arg_name, typeid))
        else:
            args = []

        obj = CTypeFunc(name, decl_info, type_ret, args)
        decl = CTypeFunc(name)
        if not self.is_known_type(decl):
            self.add_type(decl, obj)
        return obj

    def ast_to_typeid_enum(self, ast):
        """Return the CTypeBase of an Enum ast"""
        name = self.gen_uniq_name() if ast.name is None else ast.name
        return CTypeEnum(name)

    def ast_to_typeid_ptrdecl(self, ast):
        """Return the CTypeBase of a PtrDecl ast"""
        return CTypePtr(self.ast_to_typeid(ast.type))

    def ast_to_typeid_ellipsisparam(self, _):
        """Return the CTypeBase of an EllipsisParam ast"""
        return CTypeEllipsis()

    def ast_to_typeid_arraydecl(self, ast):
        """Return the CTypeBase of an ArrayDecl ast"""
        target = self.ast_to_typeid(ast.type)
        if ast.dim is None:
            value = None
        else:
            value = self.ast_eval_int(ast.dim)
        return CTypeArray(target, value)

    def ast_to_typeid(self, ast):
        """Return the CTypeBase of the @ast
        @ast: pycparser.c_ast instance"""
        cls = ast.__class__
        if not cls in self.ast_to_typeid_rules:
            raise NotImplementedError("Strange type %r" % ast)
        return self.ast_to_typeid_rules[cls](ast)

    # Ast parse type declarators

    def ast_parse_decl(self, ast):
        """Parse ast Decl"""
        return self.ast_parse_declaration(ast.type)

    def ast_parse_typedecl(self, ast):
        """Parse ast Typedecl"""
        return self.ast_parse_declaration(ast.type)

    def ast_parse_struct(self, ast):
        """Parse ast Struct"""
        obj = self.ast_to_typeid(ast)
        if ast.decls and ast.name is not None:
            # Add struct to types if named
            decl = CTypeStruct(ast.name)
            if not self.is_known_type(decl):
                self.add_type(decl, obj)
        return obj

    def ast_parse_union(self, ast):
        """Parse ast Union"""
        obj = self.ast_to_typeid(ast)
        if ast.decls and ast.name is not None:
            # Add union to types if named
            decl = CTypeUnion(ast.name)
            if not self.is_known_type(decl):
                self.add_type(decl, obj)
        return obj

    def ast_parse_typedef(self, ast):
        """Parse ast TypeDef"""
        decl = CTypeId(ast.name)
        obj = self.ast_parse_declaration(ast.type)
        if (isinstance(obj, (CTypeStruct, CTypeUnion)) and
                self.is_generated_name(obj.name)):
            # Add typedef name to default name
            # for a question of clarity
            obj.name += "__%s" % ast.name
        self.add_typedef(decl, obj)
        # Typedef does not return any object
        return None

    def ast_parse_identifiertype(self, ast):
        """Parse ast IdentifierType"""
        return CTypeId(*ast.names)

    def ast_parse_ptrdecl(self, ast):
        """Parse ast PtrDecl"""
        return CTypePtr(self.ast_parse_declaration(ast.type))

    def ast_parse_enum(self, ast):
        """Parse ast Enum"""
        return self.ast_to_typeid(ast)

    def ast_parse_arraydecl(self, ast):
        """Parse ast ArrayDecl"""
        return self.ast_to_typeid(ast)

    def ast_parse_funcdecl(self, ast):
        """Parse ast FuncDecl"""
        return self.ast_to_typeid(ast)

    def ast_parse_funcdef(self, ast):
        """Parse ast FuncDef"""
        return self.ast_to_typeid(ast.decl)

    def ast_parse_pragma(self, _):
        """Prama does not return any object"""
        return None

    def ast_parse_declaration(self, ast):
        """Add one ast type declaration to the type manager
        (packed style in type manager)

        @ast: parsed pycparser.c_ast object
        """
        cls = ast.__class__
        if not cls in self.ast_parse_rules:
            raise NotImplementedError("Strange declaration %r" % cls)
        return self.ast_parse_rules[cls](ast)

    def ast_parse_declarations(self, ast):
        """Add ast types declaration to the type manager
        (packed style in type manager)

        @ast: parsed pycparser.c_ast object
        """
        for ext in ast.ext:
            ret = self.ast_parse_declaration(ext)

    def parse_c_type(self, c_str):
        """Parse a C string representing a C type and return the associated
        Miasm C object.
        @c_str: C string of a C type
        """

        new_str = "%s __MIASM_INTERNAL_%s;" % (c_str, self._cpt_decl)
        ret = self.parser.cparser.parse(input=new_str, lexer=self.parser.clex)
        self._cpt_decl += 1
        return ret

Module variables

var RE_HASH_CMT

Functions

def c_to_ast(

parser, c_str)

Transform a @c_str into a C ast Note: will ignore lines containing code refs ie:

23 "miasm.h"

@parser: pycparser instance @c_str: c string

def c_to_ast(parser, c_str):
    """Transform a @c_str into a C ast
    Note: will ignore lines containing code refs ie:
    # 23 "miasm.h"

    @parser: pycparser instance
    @c_str: c string
    """

    new_str = re.sub(RE_HASH_CMT, "", c_str)
    return parser.parse(new_str, filename='<stdin>')

Classes

class CAstTypes

Store all defined C types and typedefs

class CAstTypes(object):
    """Store all defined C types and typedefs"""
    INTERNAL_PREFIX = "__GENTYPE__"
    ANONYMOUS_PREFIX = "__ANONYMOUS__"

    def __init__(self, knowntypes=None, knowntypedefs=None):
        if knowntypes is None:
            knowntypes = {}
        if knowntypedefs is None:
            knowntypedefs = {}

        self._types = dict(knowntypes)
        self._typedefs = dict(knowntypedefs)
        self.cpt = 0
        self.loc_to_decl_info = {}
        self.parser = c_parser.CParser()
        self._cpt_decl = 0


        self.ast_to_typeid_rules = {
            c_ast.Struct: self.ast_to_typeid_struct,
            c_ast.Union: self.ast_to_typeid_union,
            c_ast.IdentifierType: self.ast_to_typeid_identifiertype,
            c_ast.TypeDecl: self.ast_to_typeid_typedecl,
            c_ast.Decl: self.ast_to_typeid_decl,
            c_ast.Typename: self.ast_to_typeid_typename,
            c_ast.FuncDecl: self.ast_to_typeid_funcdecl,
            c_ast.Enum: self.ast_to_typeid_enum,
            c_ast.PtrDecl: self.ast_to_typeid_ptrdecl,
            c_ast.EllipsisParam: self.ast_to_typeid_ellipsisparam,
            c_ast.ArrayDecl: self.ast_to_typeid_arraydecl,
        }

        self.ast_parse_rules = {
            c_ast.Struct: self.ast_parse_struct,
            c_ast.Union: self.ast_parse_union,
            c_ast.Typedef: self.ast_parse_typedef,
            c_ast.TypeDecl: self.ast_parse_typedecl,
            c_ast.IdentifierType: self.ast_parse_identifiertype,
            c_ast.Decl: self.ast_parse_decl,
            c_ast.PtrDecl: self.ast_parse_ptrdecl,
            c_ast.Enum: self.ast_parse_enum,
            c_ast.ArrayDecl: self.ast_parse_arraydecl,
            c_ast.FuncDecl: self.ast_parse_funcdecl,
            c_ast.FuncDef: self.ast_parse_funcdef,
            c_ast.Pragma: self.ast_parse_pragma,
        }

    def gen_uniq_name(self):
        """Generate uniq name for unnamed strucs/union"""
        cpt = self.cpt
        self.cpt += 1
        return self.INTERNAL_PREFIX + "%d" % cpt

    def gen_anon_name(self):
        """Generate name for anonymous strucs/union"""
        cpt = self.cpt
        self.cpt += 1
        return self.ANONYMOUS_PREFIX + "%d" % cpt

    def is_generated_name(self, name):
        """Return True if the name is internal"""
        return name.startswith(self.INTERNAL_PREFIX)

    def is_anonymous_name(self, name):
        """Return True if the name is anonymous"""
        return name.startswith(self.ANONYMOUS_PREFIX)

    def add_type(self, type_id, type_obj):
        """Add new C type
        @type_id: Type descriptor (CTypeBase instance)
        @type_obj: Obj* instance"""
        assert isinstance(type_id, CTypeBase)
        if type_id in self._types:
            assert self._types[type_id] == type_obj
        else:
            self._types[type_id] = type_obj

    def add_typedef(self, type_new, type_src):
        """Add new typedef
        @type_new: CTypeBase instance of the new type name
        @type_src: CTypeBase instance of the target type"""
        assert isinstance(type_src, CTypeBase)
        self._typedefs[type_new] = type_src

    def get_type(self, type_id):
        """Get ObjC corresponding to the @type_id
        @type_id: Type descriptor (CTypeBase instance)
        """
        assert isinstance(type_id, CTypeBase)
        if isinstance(type_id, CTypePtr):
            subobj = self.get_type(type_id.target)
            return CTypePtr(subobj)
        if type_id in self._types:
            return self._types[type_id]
        elif type_id in self._typedefs:
            return self.get_type(self._typedefs[type_id])
        return type_id

    def is_known_type(self, type_id):
        """Return true if @type_id is known
        @type_id: Type descriptor (CTypeBase instance)
        """
        if isinstance(type_id, CTypePtr):
            return self.is_known_type(type_id.target)
        if type_id in self._types:
            return True
        if type_id in self._typedefs:
            return self.is_known_type(self._typedefs[type_id])
        return False

    def add_c_decl_from_ast(self, ast):
        """
        Adds types from a C ast
        @ast: C ast
        """
        self.ast_parse_declarations(ast)


    def digest_decl(self, c_str):

        char_id = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"


        # Seek deck
        index_decl = []
        index = 0
        for decl in ['__cdecl__', '__stdcall__']:
            index = 0
            while True:
                index = c_str.find(decl, index)
                if index == -1:
                    break
                decl_off = index
                decl_len = len(decl)

                index = index+len(decl)
                while c_str[index] not in char_id:
                    index += 1

                id_start = index

                while c_str[index] in char_id:
                    index += 1
                id_stop = index

                name = c_str[id_start:id_stop]
                index_decl.append((decl_off, decl_len, id_start, id_stop, decl, ))

        index_decl.sort()

        # Remove decl
        off = 0
        offsets = []
        for decl_off, decl_len, id_start, id_stop, decl in index_decl:
            decl_off -= off
            c_str = c_str[:decl_off] + c_str[decl_off+decl_len:]
            off += decl_len
            offsets.append((id_start-off, id_stop-off, decl))

        index = 0
        lineno = 1

        # Index to lineno, column
        for id_start, id_stop, decl in offsets:
            nbr = c_str.count('\n', index, id_start)
            lineno += nbr
            last_cr = c_str.rfind('\n', 0, id_start)
            # column starts at 1
            column = id_start - last_cr
            index = id_start
            self.loc_to_decl_info[(lineno, column)] = decl
        return c_str


    def add_c_decl(self, c_str):
        """
        Adds types from a C string types declaring
        Note: will ignore lines containing code refs ie:
        '# 23 "miasm.h"'
        Returns the C ast
        @c_str: C string containing C types declarations
        """
        c_str = self.digest_decl(c_str)

        ast = c_to_ast(self.parser, c_str)
        self.add_c_decl_from_ast(ast)

        return ast

    def ast_eval_int(self, ast):
        """Eval a C ast object integer

        @ast: parsed pycparser.c_ast object
        """

        if isinstance(ast, c_ast.BinaryOp):
            left = self.ast_eval_int(ast.left)
            right = self.ast_eval_int(ast.right)
            is_pure_int = (isinstance(left, int) and
                           isinstance(right, int))

            if is_pure_int:
                if ast.op == '*':
                    result = left * right
                elif ast.op == '/':
                    assert left % right == 0
                    result = left // right
                elif ast.op == '+':
                    result = left + right
                elif ast.op == '-':
                    result = left - right
                elif ast.op == '<<':
                    result = left << right
                elif ast.op == '>>':
                    result = left >> right
                else:
                    raise NotImplementedError("Not implemented!")
            else:
                result = CTypeOp(ast.op, left, right)

        elif isinstance(ast, c_ast.UnaryOp):
            if ast.op == 'sizeof' and isinstance(ast.expr, c_ast.Typename):
                subobj = self.ast_to_typeid(ast.expr)
                result = CTypeSizeof(subobj)
            else:
                raise NotImplementedError("Not implemented!")

        elif isinstance(ast, c_ast.Constant):
            result = int(ast.value, 0)
        elif isinstance(ast, c_ast.Cast):
            # TODO: Can trunc integers?
            result = self.ast_eval_int(ast.expr)
        else:
            raise NotImplementedError("Not implemented!")
        return result

    def ast_to_typeid_struct(self, ast):
        """Return the CTypeBase of an Struct ast"""
        name = self.gen_uniq_name() if ast.name is None else ast.name
        args = []
        if ast.decls:
            for arg in ast.decls:
                if arg.name is None:
                    arg_name = self.gen_anon_name()
                else:
                    arg_name = arg.name
                args.append((arg_name, self.ast_to_typeid(arg)))
        decl = CTypeStruct(name, args)
        return decl

    def ast_to_typeid_union(self, ast):
        """Return the CTypeBase of an Union ast"""
        name = self.gen_uniq_name() if ast.name is None else ast.name
        args = []
        if ast.decls:
            for arg in ast.decls:
                if arg.name is None:
                    arg_name = self.gen_anon_name()
                else:
                    arg_name = arg.name
                args.append((arg_name, self.ast_to_typeid(arg)))
        decl = CTypeUnion(name, args)
        return decl

    def ast_to_typeid_identifiertype(self, ast):
        """Return the CTypeBase of an IdentifierType ast"""
        return CTypeId(*ast.names)

    def ast_to_typeid_typedecl(self, ast):
        """Return the CTypeBase of a TypeDecl ast"""
        return self.ast_to_typeid(ast.type)

    def ast_to_typeid_decl(self, ast):
        """Return the CTypeBase of a Decl ast"""
        return self.ast_to_typeid(ast.type)

    def ast_to_typeid_typename(self, ast):
        """Return the CTypeBase of a TypeName ast"""
        return self.ast_to_typeid(ast.type)

    def get_funcname(self, ast):
        """Return the name of a function declaration ast"""
        funcnameid = FuncNameIdentifier()
        funcnameid.visit(ast)
        node_name = funcnameid.node_name
        if node_name.coord is not None:
            lineno, column = node_name.coord.line, node_name.coord.column
            decl_info = self.loc_to_decl_info.get((lineno, column), None)
        else:
            decl_info = None
        return node_name.declname, decl_info

    def ast_to_typeid_funcdecl(self, ast):
        """Return the CTypeBase of an FuncDecl ast"""
        type_ret = self.ast_to_typeid(ast.type)
        name, decl_info = self.get_funcname(ast.type)
        if ast.args:
            args = []
            for arg in ast.args.params:
                typeid = self.ast_to_typeid(arg)
                if isinstance(typeid, CTypeEllipsis):
                    arg_name = None
                else:
                    arg_name = arg.name
                args.append((arg_name, typeid))
        else:
            args = []

        obj = CTypeFunc(name, decl_info, type_ret, args)
        decl = CTypeFunc(name)
        if not self.is_known_type(decl):
            self.add_type(decl, obj)
        return obj

    def ast_to_typeid_enum(self, ast):
        """Return the CTypeBase of an Enum ast"""
        name = self.gen_uniq_name() if ast.name is None else ast.name
        return CTypeEnum(name)

    def ast_to_typeid_ptrdecl(self, ast):
        """Return the CTypeBase of a PtrDecl ast"""
        return CTypePtr(self.ast_to_typeid(ast.type))

    def ast_to_typeid_ellipsisparam(self, _):
        """Return the CTypeBase of an EllipsisParam ast"""
        return CTypeEllipsis()

    def ast_to_typeid_arraydecl(self, ast):
        """Return the CTypeBase of an ArrayDecl ast"""
        target = self.ast_to_typeid(ast.type)
        if ast.dim is None:
            value = None
        else:
            value = self.ast_eval_int(ast.dim)
        return CTypeArray(target, value)

    def ast_to_typeid(self, ast):
        """Return the CTypeBase of the @ast
        @ast: pycparser.c_ast instance"""
        cls = ast.__class__
        if not cls in self.ast_to_typeid_rules:
            raise NotImplementedError("Strange type %r" % ast)
        return self.ast_to_typeid_rules[cls](ast)

    # Ast parse type declarators

    def ast_parse_decl(self, ast):
        """Parse ast Decl"""
        return self.ast_parse_declaration(ast.type)

    def ast_parse_typedecl(self, ast):
        """Parse ast Typedecl"""
        return self.ast_parse_declaration(ast.type)

    def ast_parse_struct(self, ast):
        """Parse ast Struct"""
        obj = self.ast_to_typeid(ast)
        if ast.decls and ast.name is not None:
            # Add struct to types if named
            decl = CTypeStruct(ast.name)
            if not self.is_known_type(decl):
                self.add_type(decl, obj)
        return obj

    def ast_parse_union(self, ast):
        """Parse ast Union"""
        obj = self.ast_to_typeid(ast)
        if ast.decls and ast.name is not None:
            # Add union to types if named
            decl = CTypeUnion(ast.name)
            if not self.is_known_type(decl):
                self.add_type(decl, obj)
        return obj

    def ast_parse_typedef(self, ast):
        """Parse ast TypeDef"""
        decl = CTypeId(ast.name)
        obj = self.ast_parse_declaration(ast.type)
        if (isinstance(obj, (CTypeStruct, CTypeUnion)) and
                self.is_generated_name(obj.name)):
            # Add typedef name to default name
            # for a question of clarity
            obj.name += "__%s" % ast.name
        self.add_typedef(decl, obj)
        # Typedef does not return any object
        return None

    def ast_parse_identifiertype(self, ast):
        """Parse ast IdentifierType"""
        return CTypeId(*ast.names)

    def ast_parse_ptrdecl(self, ast):
        """Parse ast PtrDecl"""
        return CTypePtr(self.ast_parse_declaration(ast.type))

    def ast_parse_enum(self, ast):
        """Parse ast Enum"""
        return self.ast_to_typeid(ast)

    def ast_parse_arraydecl(self, ast):
        """Parse ast ArrayDecl"""
        return self.ast_to_typeid(ast)

    def ast_parse_funcdecl(self, ast):
        """Parse ast FuncDecl"""
        return self.ast_to_typeid(ast)

    def ast_parse_funcdef(self, ast):
        """Parse ast FuncDef"""
        return self.ast_to_typeid(ast.decl)

    def ast_parse_pragma(self, _):
        """Prama does not return any object"""
        return None

    def ast_parse_declaration(self, ast):
        """Add one ast type declaration to the type manager
        (packed style in type manager)

        @ast: parsed pycparser.c_ast object
        """
        cls = ast.__class__
        if not cls in self.ast_parse_rules:
            raise NotImplementedError("Strange declaration %r" % cls)
        return self.ast_parse_rules[cls](ast)

    def ast_parse_declarations(self, ast):
        """Add ast types declaration to the type manager
        (packed style in type manager)

        @ast: parsed pycparser.c_ast object
        """
        for ext in ast.ext:
            ret = self.ast_parse_declaration(ext)

    def parse_c_type(self, c_str):
        """Parse a C string representing a C type and return the associated
        Miasm C object.
        @c_str: C string of a C type
        """

        new_str = "%s __MIASM_INTERNAL_%s;" % (c_str, self._cpt_decl)
        ret = self.parser.cparser.parse(input=new_str, lexer=self.parser.clex)
        self._cpt_decl += 1
        return ret

Ancestors (in MRO)

Class variables

var ANONYMOUS_PREFIX

var INTERNAL_PREFIX

Static methods

def __init__(

self, knowntypes=None, knowntypedefs=None)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, knowntypes=None, knowntypedefs=None):
    if knowntypes is None:
        knowntypes = {}
    if knowntypedefs is None:
        knowntypedefs = {}
    self._types = dict(knowntypes)
    self._typedefs = dict(knowntypedefs)
    self.cpt = 0
    self.loc_to_decl_info = {}
    self.parser = c_parser.CParser()
    self._cpt_decl = 0
    self.ast_to_typeid_rules = {
        c_ast.Struct: self.ast_to_typeid_struct,
        c_ast.Union: self.ast_to_typeid_union,
        c_ast.IdentifierType: self.ast_to_typeid_identifiertype,
        c_ast.TypeDecl: self.ast_to_typeid_typedecl,
        c_ast.Decl: self.ast_to_typeid_decl,
        c_ast.Typename: self.ast_to_typeid_typename,
        c_ast.FuncDecl: self.ast_to_typeid_funcdecl,
        c_ast.Enum: self.ast_to_typeid_enum,
        c_ast.PtrDecl: self.ast_to_typeid_ptrdecl,
        c_ast.EllipsisParam: self.ast_to_typeid_ellipsisparam,
        c_ast.ArrayDecl: self.ast_to_typeid_arraydecl,
    }
    self.ast_parse_rules = {
        c_ast.Struct: self.ast_parse_struct,
        c_ast.Union: self.ast_parse_union,
        c_ast.Typedef: self.ast_parse_typedef,
        c_ast.TypeDecl: self.ast_parse_typedecl,
        c_ast.IdentifierType: self.ast_parse_identifiertype,
        c_ast.Decl: self.ast_parse_decl,
        c_ast.PtrDecl: self.ast_parse_ptrdecl,
        c_ast.Enum: self.ast_parse_enum,
        c_ast.ArrayDecl: self.ast_parse_arraydecl,
        c_ast.FuncDecl: self.ast_parse_funcdecl,
        c_ast.FuncDef: self.ast_parse_funcdef,
        c_ast.Pragma: self.ast_parse_pragma,
    }

def add_c_decl(

self, c_str)

Adds types from a C string types declaring Note: will ignore lines containing code refs ie: '# 23 "miasm.h"' Returns the C ast @c_str: C string containing C types declarations

def add_c_decl(self, c_str):
    """
    Adds types from a C string types declaring
    Note: will ignore lines containing code refs ie:
    '# 23 "miasm.h"'
    Returns the C ast
    @c_str: C string containing C types declarations
    """
    c_str = self.digest_decl(c_str)
    ast = c_to_ast(self.parser, c_str)
    self.add_c_decl_from_ast(ast)
    return ast

def add_c_decl_from_ast(

self, ast)

Adds types from a C ast @ast: C ast

def add_c_decl_from_ast(self, ast):
    """
    Adds types from a C ast
    @ast: C ast
    """
    self.ast_parse_declarations(ast)

def add_type(

self, type_id, type_obj)

Add new C type @type_id: Type descriptor (CTypeBase instance) @type_obj: Obj* instance

def add_type(self, type_id, type_obj):
    """Add new C type
    @type_id: Type descriptor (CTypeBase instance)
    @type_obj: Obj* instance"""
    assert isinstance(type_id, CTypeBase)
    if type_id in self._types:
        assert self._types[type_id] == type_obj
    else:
        self._types[type_id] = type_obj

def add_typedef(

self, type_new, type_src)

Add new typedef @type_new: CTypeBase instance of the new type name @type_src: CTypeBase instance of the target type

def add_typedef(self, type_new, type_src):
    """Add new typedef
    @type_new: CTypeBase instance of the new type name
    @type_src: CTypeBase instance of the target type"""
    assert isinstance(type_src, CTypeBase)
    self._typedefs[type_new] = type_src

def ast_eval_int(

self, ast)

Eval a C ast object integer

@ast: parsed pycparser.c_ast object

def ast_eval_int(self, ast):
    """Eval a C ast object integer
    @ast: parsed pycparser.c_ast object
    """
    if isinstance(ast, c_ast.BinaryOp):
        left = self.ast_eval_int(ast.left)
        right = self.ast_eval_int(ast.right)
        is_pure_int = (isinstance(left, int) and
                       isinstance(right, int))
        if is_pure_int:
            if ast.op == '*':
                result = left * right
            elif ast.op == '/':
                assert left % right == 0
                result = left // right
            elif ast.op == '+':
                result = left + right
            elif ast.op == '-':
                result = left - right
            elif ast.op == '<<':
                result = left << right
            elif ast.op == '>>':
                result = left >> right
            else:
                raise NotImplementedError("Not implemented!")
        else:
            result = CTypeOp(ast.op, left, right)
    elif isinstance(ast, c_ast.UnaryOp):
        if ast.op == 'sizeof' and isinstance(ast.expr, c_ast.Typename):
            subobj = self.ast_to_typeid(ast.expr)
            result = CTypeSizeof(subobj)
        else:
            raise NotImplementedError("Not implemented!")
    elif isinstance(ast, c_ast.Constant):
        result = int(ast.value, 0)
    elif isinstance(ast, c_ast.Cast):
        # TODO: Can trunc integers?
        result = self.ast_eval_int(ast.expr)
    else:
        raise NotImplementedError("Not implemented!")
    return result

def ast_parse_arraydecl(

self, ast)

Parse ast ArrayDecl

def ast_parse_arraydecl(self, ast):
    """Parse ast ArrayDecl"""
    return self.ast_to_typeid(ast)

def ast_parse_decl(

self, ast)

Parse ast Decl

def ast_parse_decl(self, ast):
    """Parse ast Decl"""
    return self.ast_parse_declaration(ast.type)

def ast_parse_declaration(

self, ast)

Add one ast type declaration to the type manager (packed style in type manager)

@ast: parsed pycparser.c_ast object

def ast_parse_declaration(self, ast):
    """Add one ast type declaration to the type manager
    (packed style in type manager)
    @ast: parsed pycparser.c_ast object
    """
    cls = ast.__class__
    if not cls in self.ast_parse_rules:
        raise NotImplementedError("Strange declaration %r" % cls)
    return self.ast_parse_rules[cls](ast)

def ast_parse_declarations(

self, ast)

Add ast types declaration to the type manager (packed style in type manager)

@ast: parsed pycparser.c_ast object

def ast_parse_declarations(self, ast):
    """Add ast types declaration to the type manager
    (packed style in type manager)
    @ast: parsed pycparser.c_ast object
    """
    for ext in ast.ext:
        ret = self.ast_parse_declaration(ext)

def ast_parse_enum(

self, ast)

Parse ast Enum

def ast_parse_enum(self, ast):
    """Parse ast Enum"""
    return self.ast_to_typeid(ast)

def ast_parse_funcdecl(

self, ast)

Parse ast FuncDecl

def ast_parse_funcdecl(self, ast):
    """Parse ast FuncDecl"""
    return self.ast_to_typeid(ast)

def ast_parse_funcdef(

self, ast)

Parse ast FuncDef

def ast_parse_funcdef(self, ast):
    """Parse ast FuncDef"""
    return self.ast_to_typeid(ast.decl)

def ast_parse_identifiertype(

self, ast)

Parse ast IdentifierType

def ast_parse_identifiertype(self, ast):
    """Parse ast IdentifierType"""
    return CTypeId(*ast.names)

def ast_parse_pragma(

self, _)

Prama does not return any object

def ast_parse_pragma(self, _):
    """Prama does not return any object"""
    return None

def ast_parse_ptrdecl(

self, ast)

Parse ast PtrDecl

def ast_parse_ptrdecl(self, ast):
    """Parse ast PtrDecl"""
    return CTypePtr(self.ast_parse_declaration(ast.type))

def ast_parse_struct(

self, ast)

Parse ast Struct

def ast_parse_struct(self, ast):
    """Parse ast Struct"""
    obj = self.ast_to_typeid(ast)
    if ast.decls and ast.name is not None:
        # Add struct to types if named
        decl = CTypeStruct(ast.name)
        if not self.is_known_type(decl):
            self.add_type(decl, obj)
    return obj

def ast_parse_typedecl(

self, ast)

Parse ast Typedecl

def ast_parse_typedecl(self, ast):
    """Parse ast Typedecl"""
    return self.ast_parse_declaration(ast.type)

def ast_parse_typedef(

self, ast)

Parse ast TypeDef

def ast_parse_typedef(self, ast):
    """Parse ast TypeDef"""
    decl = CTypeId(ast.name)
    obj = self.ast_parse_declaration(ast.type)
    if (isinstance(obj, (CTypeStruct, CTypeUnion)) and
            self.is_generated_name(obj.name)):
        # Add typedef name to default name
        # for a question of clarity
        obj.name += "__%s" % ast.name
    self.add_typedef(decl, obj)
    # Typedef does not return any object
    return None

def ast_parse_union(

self, ast)

Parse ast Union

def ast_parse_union(self, ast):
    """Parse ast Union"""
    obj = self.ast_to_typeid(ast)
    if ast.decls and ast.name is not None:
        # Add union to types if named
        decl = CTypeUnion(ast.name)
        if not self.is_known_type(decl):
            self.add_type(decl, obj)
    return obj

def ast_to_typeid(

self, ast)

Return the CTypeBase of the @ast @ast: pycparser.c_ast instance

def ast_to_typeid(self, ast):
    """Return the CTypeBase of the @ast
    @ast: pycparser.c_ast instance"""
    cls = ast.__class__
    if not cls in self.ast_to_typeid_rules:
        raise NotImplementedError("Strange type %r" % ast)
    return self.ast_to_typeid_rules[cls](ast)

def ast_to_typeid_arraydecl(

self, ast)

Return the CTypeBase of an ArrayDecl ast

def ast_to_typeid_arraydecl(self, ast):
    """Return the CTypeBase of an ArrayDecl ast"""
    target = self.ast_to_typeid(ast.type)
    if ast.dim is None:
        value = None
    else:
        value = self.ast_eval_int(ast.dim)
    return CTypeArray(target, value)

def ast_to_typeid_decl(

self, ast)

Return the CTypeBase of a Decl ast

def ast_to_typeid_decl(self, ast):
    """Return the CTypeBase of a Decl ast"""
    return self.ast_to_typeid(ast.type)

def ast_to_typeid_ellipsisparam(

self, _)

Return the CTypeBase of an EllipsisParam ast

def ast_to_typeid_ellipsisparam(self, _):
    """Return the CTypeBase of an EllipsisParam ast"""
    return CTypeEllipsis()

def ast_to_typeid_enum(

self, ast)

Return the CTypeBase of an Enum ast

def ast_to_typeid_enum(self, ast):
    """Return the CTypeBase of an Enum ast"""
    name = self.gen_uniq_name() if ast.name is None else ast.name
    return CTypeEnum(name)

def ast_to_typeid_funcdecl(

self, ast)

Return the CTypeBase of an FuncDecl ast

def ast_to_typeid_funcdecl(self, ast):
    """Return the CTypeBase of an FuncDecl ast"""
    type_ret = self.ast_to_typeid(ast.type)
    name, decl_info = self.get_funcname(ast.type)
    if ast.args:
        args = []
        for arg in ast.args.params:
            typeid = self.ast_to_typeid(arg)
            if isinstance(typeid, CTypeEllipsis):
                arg_name = None
            else:
                arg_name = arg.name
            args.append((arg_name, typeid))
    else:
        args = []
    obj = CTypeFunc(name, decl_info, type_ret, args)
    decl = CTypeFunc(name)
    if not self.is_known_type(decl):
        self.add_type(decl, obj)
    return obj

def ast_to_typeid_identifiertype(

self, ast)

Return the CTypeBase of an IdentifierType ast

def ast_to_typeid_identifiertype(self, ast):
    """Return the CTypeBase of an IdentifierType ast"""
    return CTypeId(*ast.names)

def ast_to_typeid_ptrdecl(

self, ast)

Return the CTypeBase of a PtrDecl ast

def ast_to_typeid_ptrdecl(self, ast):
    """Return the CTypeBase of a PtrDecl ast"""
    return CTypePtr(self.ast_to_typeid(ast.type))

def ast_to_typeid_struct(

self, ast)

Return the CTypeBase of an Struct ast

def ast_to_typeid_struct(self, ast):
    """Return the CTypeBase of an Struct ast"""
    name = self.gen_uniq_name() if ast.name is None else ast.name
    args = []
    if ast.decls:
        for arg in ast.decls:
            if arg.name is None:
                arg_name = self.gen_anon_name()
            else:
                arg_name = arg.name
            args.append((arg_name, self.ast_to_typeid(arg)))
    decl = CTypeStruct(name, args)
    return decl

def ast_to_typeid_typedecl(

self, ast)

Return the CTypeBase of a TypeDecl ast

def ast_to_typeid_typedecl(self, ast):
    """Return the CTypeBase of a TypeDecl ast"""
    return self.ast_to_typeid(ast.type)

def ast_to_typeid_typename(

self, ast)

Return the CTypeBase of a TypeName ast

def ast_to_typeid_typename(self, ast):
    """Return the CTypeBase of a TypeName ast"""
    return self.ast_to_typeid(ast.type)

def ast_to_typeid_union(

self, ast)

Return the CTypeBase of an Union ast

def ast_to_typeid_union(self, ast):
    """Return the CTypeBase of an Union ast"""
    name = self.gen_uniq_name() if ast.name is None else ast.name
    args = []
    if ast.decls:
        for arg in ast.decls:
            if arg.name is None:
                arg_name = self.gen_anon_name()
            else:
                arg_name = arg.name
            args.append((arg_name, self.ast_to_typeid(arg)))
    decl = CTypeUnion(name, args)
    return decl

def digest_decl(

self, c_str)

def digest_decl(self, c_str):
    char_id = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
    # Seek deck
    index_decl = []
    index = 0
    for decl in ['__cdecl__', '__stdcall__']:
        index = 0
        while True:
            index = c_str.find(decl, index)
            if index == -1:
                break
            decl_off = index
            decl_len = len(decl)
            index = index+len(decl)
            while c_str[index] not in char_id:
                index += 1
            id_start = index
            while c_str[index] in char_id:
                index += 1
            id_stop = index
            name = c_str[id_start:id_stop]
            index_decl.append((decl_off, decl_len, id_start, id_stop, decl, ))
    index_decl.sort()
    # Remove decl
    off = 0
    offsets = []
    for decl_off, decl_len, id_start, id_stop, decl in index_decl:
        decl_off -= off
        c_str = c_str[:decl_off] + c_str[decl_off+decl_len:]
        off += decl_len
        offsets.append((id_start-off, id_stop-off, decl))
    index = 0
    lineno = 1
    # Index to lineno, column
    for id_start, id_stop, decl in offsets:
        nbr = c_str.count('\n', index, id_start)
        lineno += nbr
        last_cr = c_str.rfind('\n', 0, id_start)
        # column starts at 1
        column = id_start - last_cr
        index = id_start
        self.loc_to_decl_info[(lineno, column)] = decl
    return c_str

def gen_anon_name(

self)

Generate name for anonymous strucs/union

def gen_anon_name(self):
    """Generate name for anonymous strucs/union"""
    cpt = self.cpt
    self.cpt += 1
    return self.ANONYMOUS_PREFIX + "%d" % cpt

def gen_uniq_name(

self)

Generate uniq name for unnamed strucs/union

def gen_uniq_name(self):
    """Generate uniq name for unnamed strucs/union"""
    cpt = self.cpt
    self.cpt += 1
    return self.INTERNAL_PREFIX + "%d" % cpt

def get_funcname(

self, ast)

Return the name of a function declaration ast

def get_funcname(self, ast):
    """Return the name of a function declaration ast"""
    funcnameid = FuncNameIdentifier()
    funcnameid.visit(ast)
    node_name = funcnameid.node_name
    if node_name.coord is not None:
        lineno, column = node_name.coord.line, node_name.coord.column
        decl_info = self.loc_to_decl_info.get((lineno, column), None)
    else:
        decl_info = None
    return node_name.declname, decl_info

def get_type(

self, type_id)

Get ObjC corresponding to the @type_id @type_id: Type descriptor (CTypeBase instance)

def get_type(self, type_id):
    """Get ObjC corresponding to the @type_id
    @type_id: Type descriptor (CTypeBase instance)
    """
    assert isinstance(type_id, CTypeBase)
    if isinstance(type_id, CTypePtr):
        subobj = self.get_type(type_id.target)
        return CTypePtr(subobj)
    if type_id in self._types:
        return self._types[type_id]
    elif type_id in self._typedefs:
        return self.get_type(self._typedefs[type_id])
    return type_id

def is_anonymous_name(

self, name)

Return True if the name is anonymous

def is_anonymous_name(self, name):
    """Return True if the name is anonymous"""
    return name.startswith(self.ANONYMOUS_PREFIX)

def is_generated_name(

self, name)

Return True if the name is internal

def is_generated_name(self, name):
    """Return True if the name is internal"""
    return name.startswith(self.INTERNAL_PREFIX)

def is_known_type(

self, type_id)

Return true if @type_id is known @type_id: Type descriptor (CTypeBase instance)

def is_known_type(self, type_id):
    """Return true if @type_id is known
    @type_id: Type descriptor (CTypeBase instance)
    """
    if isinstance(type_id, CTypePtr):
        return self.is_known_type(type_id.target)
    if type_id in self._types:
        return True
    if type_id in self._typedefs:
        return self.is_known_type(self._typedefs[type_id])
    return False

def parse_c_type(

self, c_str)

Parse a C string representing a C type and return the associated Miasm C object. @c_str: C string of a C type

def parse_c_type(self, c_str):
    """Parse a C string representing a C type and return the associated
    Miasm C object.
    @c_str: C string of a C type
    """
    new_str = "%s __MIASM_INTERNAL_%s;" % (c_str, self._cpt_decl)
    ret = self.parser.cparser.parse(input=new_str, lexer=self.parser.clex)
    self._cpt_decl += 1
    return ret

Instance variables

var ast_parse_rules

var ast_to_typeid_rules

var cpt

var loc_to_decl_info

var parser

class CTypeArray

C type for array: typedef int XXX[4];

class CTypeArray(CTypeBase):
    """C type for array:
    typedef int XXX[4];
    """

    def __init__(self, target, size):
        assert isinstance(target, CTypeBase)
        self.target = target
        self.size = size
        super(CTypeArray, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.target, self.size))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.target == other.target and
                self.size == other.size)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Array[%s]:%s>" % (self.size, str(self.target))

Ancestors (in MRO)

Static methods

def __init__(

self, target, size)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, target, size):
    assert isinstance(target, CTypeBase)
    self.target = target
    self.size = size
    super(CTypeArray, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var size

var target

class CTypeBase

Object to represent the 3 forms of C type: object types function types * incomplete types

class CTypeBase(object):
    """Object to represent the 3 forms of C type:
    * object types
    * function types
    * incomplete types
    """

    def __init__(self):
        self.__repr = str(self)
        self.__hash = hash(self.__repr)

    @property
    def _typerepr(self):
        return self.__repr

    def __eq__(self, other):
        raise NotImplementedError("Abstract method")

    def __ne__(self, other):
        return not self.__eq__(other)

    def eq_base(self, other):
        """Trivial common equality test"""
        return self.__class__ == other.__class__

    def __hash__(self):
        return self.__hash

    def __repr__(self):
        return self._typerepr

Ancestors (in MRO)

Static methods

def __init__(

self)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self):
    self.__repr = str(self)
    self.__hash = hash(self.__repr)

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

class CTypeEllipsis

C type for ellipsis argument (...)

class CTypeEllipsis(CTypeBase):
    """C type for ellipsis argument (...)"""

    def __hash__(self):
        return hash((self.__class__))

    def __eq__(self, other):
        return self.eq_base(other)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Ellipsis>"

Ancestors (in MRO)

Static methods

def __init__(

self)

Inheritance: CTypeBase.__init__

Initialize self. See help(type(self)) for accurate signature.

def __init__(self):
    self.__repr = str(self)
    self.__hash = hash(self.__repr)

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

class CTypeEnum

C type for enums

class CTypeEnum(CTypeBase):
    """C type for enums"""

    def __init__(self, name):
        self.name = name
        super(CTypeEnum, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Enum:%s>" % self.name

Ancestors (in MRO)

Static methods

def __init__(

self, name)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, name):
    self.name = name
    super(CTypeEnum, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var name

class CTypeFunc

C type for enums

class CTypeFunc(CTypeBase):
    """C type for enums"""

    def __init__(self, name, abi=None, type_ret=None, args=None):
        if type_ret:
            assert isinstance(type_ret, CTypeBase)
        if args:
            for arg_name, arg in args:
                assert isinstance(arg, CTypeBase)
            args = tuple(args)
        else:
            args = tuple()
        self.name = name
        self.abi = abi
        self.type_ret = type_ret
        self.args = args
        super(CTypeFunc, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name, self.abi,
                     self.type_ret, self.args))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name and
                self.abi == other.abi and
                self.type_ret == other.type_ret and
                self.args == other.args)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Func:%s (%s) %s(%s)>" % (self.type_ret,
                                          self.abi,
                                          self.name,
                                          ", ".join(["%s %s" % (name, arg) for (name, arg) in self.args]))

Ancestors (in MRO)

Static methods

def __init__(

self, name, abi=None, type_ret=None, args=None)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, name, abi=None, type_ret=None, args=None):
    if type_ret:
        assert isinstance(type_ret, CTypeBase)
    if args:
        for arg_name, arg in args:
            assert isinstance(arg, CTypeBase)
        args = tuple(args)
    else:
        args = tuple()
    self.name = name
    self.abi = abi
    self.type_ret = type_ret
    self.args = args
    super(CTypeFunc, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var abi

var args

var name

var type_ret

class CTypeId

C type id: int unsigned int

class CTypeId(CTypeBase):
    """C type id:
    int
    unsigned int
    """

    def __init__(self, *names):
        # Type specifier order does not matter
        # so the canonical form is ordered
        self.names = tuple(sorted(names))
        super(CTypeId, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.names))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.names == other.names)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Id:%s>" % ', '.join(self.names)

Ancestors (in MRO)

Static methods

def __init__(

self, *names)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, *names):
    # Type specifier order does not matter
    # so the canonical form is ordered
    self.names = tuple(sorted(names))
    super(CTypeId, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var names

class CTypeOp

C type for operator (+ * ...)

class CTypeOp(CTypeBase):
    """C type for operator (+ * ...)"""

    def __init__(self, operator, *args):
        self.operator = operator
        self.args = tuple(args)
        super(CTypeOp, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.operator, self.args))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.operator == other.operator and
                self.args == other.args)

    def __str__(self):
        return "<CTypeOp(%s, %s)>" % (self.operator,
                                      ', '.join([str(arg) for arg in self.args]))

Ancestors (in MRO)

Static methods

def __init__(

self, operator, *args)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, operator, *args):
    self.operator = operator
    self.args = tuple(args)
    super(CTypeOp, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var args

var operator

class CTypePtr

C type for pointer: typedef int* XXX;

class CTypePtr(CTypeBase):
    """C type for pointer:
    typedef int* XXX;
    """

    def __init__(self, target):
        assert isinstance(target, CTypeBase)
        self.target = target
        super(CTypePtr, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.target))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.target == other.target)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Ptr:%s>" % str(self.target)

Ancestors (in MRO)

Static methods

def __init__(

self, target)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, target):
    assert isinstance(target, CTypeBase)
    self.target = target
    super(CTypePtr, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var target

class CTypeSizeof

C type for sizeof

class CTypeSizeof(CTypeBase):
    """C type for sizeof"""

    def __init__(self, target):
        self.target = target
        super(CTypeSizeof, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.target))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.target == other.target)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        return "<Sizeof(%s)>" % self.target

Ancestors (in MRO)

Static methods

def __init__(

self, target)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, target):
    self.target = target
    super(CTypeSizeof, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var target

class CTypeStruct

C type for structure

class CTypeStruct(CTypeBase):
    """C type for structure"""

    def __init__(self, name, fields=None):
        assert name is not None
        self.name = name
        if fields is None:
            fields = ()
        for field_name, field in fields:
            assert field_name is not None
            assert isinstance(field, CTypeBase)
        self.fields = tuple(fields)
        super(CTypeStruct, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name, self.fields))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name and
                self.fields == other.fields)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __str__(self):
        out = []
        out.append("<Struct:%s>" % self.name)
        for name, field in self.fields:
            out.append("\t%-10s %s" % (name, field))
        return '\n'.join(out)

Ancestors (in MRO)

Static methods

def __init__(

self, name, fields=None)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, name, fields=None):
    assert name is not None
    self.name = name
    if fields is None:
        fields = ()
    for field_name, field in fields:
        assert field_name is not None
        assert isinstance(field, CTypeBase)
    self.fields = tuple(fields)
    super(CTypeStruct, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var fields

var name

class CTypeUnion

C type for union

class CTypeUnion(CTypeBase):
    """C type for union"""

    def __init__(self, name, fields=None):
        assert name is not None
        self.name = name
        if fields is None:
            fields = []
        for field_name, field in fields:
            assert field_name is not None
            assert isinstance(field, CTypeBase)
        self.fields = tuple(fields)
        super(CTypeUnion, self).__init__()

    def __hash__(self):
        return hash((self.__class__, self.name, self.fields))

    def __eq__(self, other):
        return (self.eq_base(other) and
                self.name == other.name and
                self.fields == other.fields)

    def __str__(self):
        out = []
        out.append("<Union:%s>" % self.name)
        for name, field in self.fields:
            out.append("\t%-10s %s" % (name, field))
        return '\n'.join(out)

Ancestors (in MRO)

Static methods

def __init__(

self, name, fields=None)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, name, fields=None):
    assert name is not None
    self.name = name
    if fields is None:
        fields = []
    for field_name, field in fields:
        assert field_name is not None
        assert isinstance(field, CTypeBase)
    self.fields = tuple(fields)
    super(CTypeUnion, self).__init__()

def eq_base(

self, other)

Trivial common equality test

def eq_base(self, other):
    """Trivial common equality test"""
    return self.__class__ == other.__class__

Instance variables

var fields

var name

class FuncNameIdentifier

Visit an c_ast to find IdentifierType

class FuncNameIdentifier(c_ast.NodeVisitor):
    """Visit an c_ast to find IdentifierType"""

    def __init__(self):
        super(FuncNameIdentifier, self).__init__()
        self.node_name = None

    def visit_TypeDecl(self, node):
        """Retrieve the name in a function declaration:
        Only one IdentifierType is present"""
        self.node_name = node

Ancestors (in MRO)

Static methods

def __init__(

self)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self):
    super(FuncNameIdentifier, self).__init__()
    self.node_name = None

def generic_visit(

self, node)

Called if no explicit visitor function exists for a node. Implements preorder visiting of the node.

def generic_visit(self, node):
    """ Called if no explicit visitor function exists for a
        node. Implements preorder visiting of the node.
    """
    for c_name, c in node.children():
        self.visit(c)

def visit(

self, node)

Visit a node.

def visit(self, node):
    """ Visit a node.
    """
    method = 'visit_' + node.__class__.__name__
    visitor = getattr(self, method, self.generic_visit)
    return visitor(node)

def visit_TypeDecl(

self, node)

Retrieve the name in a function declaration: Only one IdentifierType is present

def visit_TypeDecl(self, node):
    """Retrieve the name in a function declaration:
    Only one IdentifierType is present"""
    self.node_name = node

Instance variables

var node_name