Exemplo n.º 1
0
def __generate_alias(process, name, file, int_retval=False):
    new_name = "ldv_emg_{}".format(name)
    code = ["{}();".format("return {}".format(name) if int_retval else name)]
    # Add definition
    func = Function(
        new_name, "{}(void)".format("int {}".format(new_name) if int_retval
                                    else "void {}".format(new_name)))
    func.body = code
    process.add_definition(file, name, func.define())
    process.add_declaration(
        'environment model', name,
        'extern {} {}(void);\n'.format("int" if int_retval else "void",
                                       new_name))

    return new_name
Exemplo n.º 2
0
def __generate_insmod_process(logger, conf, source, inits, exits,
                              kernel_initializations):
    logger.info(
        "Generate artificial process description to call Init and Exit module functions 'insmod'"
    )
    ep = Process("insmod")
    ep.category = 'linux'
    ep.comment = "Initialize or exit module."
    ep.self_parallelism = False
    ep.identifier = 0
    ep.process = ''
    ep.pretty_id = 'linux/initialization'

    if len(kernel_initializations) > 0:
        body = ["int ret;"]
        label_name = 'ldv_kernel_initialization_exit'

        # Generate kernel initializations
        for name, calls in kernel_initializations:
            for filename, func_name in calls:
                func = source.get_source_function(func_name, filename)
                if func:
                    retval = False if func.declaration.return_value.identifier == 'void' else True
                else:
                    raise RuntimeError(
                        "Cannot resolve function {!r} in file {!r}".format(
                            name, filename))
                new_name = __generate_alias(ep, func_name, filename, retval)
                statements = [
                    model_comment('callback', func_name,
                                  {'call': "{}();".format(func_name)}),
                ]
                if retval:
                    statements.extend([
                        "ret = {}();".format(new_name),
                        "ret = ldv_post_init(ret);", "if (ret)",
                        "\tgoto {};".format(label_name)
                    ])
                else:
                    statements.append("{}();".format(new_name))

                body.extend(statements)
        body.extend(["{}:".format(label_name), "return ret;"])
        func = Function('ldv_kernel_init', 'int ldv_kernel_init(void)')
        func.body = body
        addon = func.define()
        ep.add_definition('environment model', 'ldv_kernel_init', addon)
        ki_subprocess = ep.add_condition('kernel_initialization', [],
                                         ["%ret% = ldv_kernel_init();"],
                                         'Kernel initialization stage.')
        ki_subprocess.trace_relevant = True
        ki_success = ep.add_condition('kerninit_success', ["%ret% == 0"], [],
                                      "Kernel initialization is successful.")
        ki_failed = ep.add_condition('kerninit_failed', ["%ret% != 0"], [],
                                     "Kernel initialization is unsuccessful.")
    if len(inits) > 0:
        # Generate init subprocess
        for filename, init_name in inits:
            new_name = __generate_alias(ep, init_name, filename, True)
            init_subprocess = Condition(init_name)
            init_subprocess.comment = 'Initialize the module after insmod with {!r} function.'.format(
                init_name)
            init_subprocess.statements = [
                model_comment('callback', init_name,
                              {'call': "{}();".format(init_name)}),
                "%ret% = {}();".format(new_name),
                "%ret% = ldv_post_init(%ret%);"
            ]
            init_subprocess.trace_relevant = True
            logger.debug("Found init function {}".format(init_name))
            ep.actions[init_subprocess.name] = init_subprocess

    # Add ret label
    ep.add_label('ret', import_declaration("int label"))

    # Generate exit subprocess
    if len(exits) == 0:
        logger.debug("There is no exit function found")
    else:
        for filename, exit_name in exits:
            new_name = __generate_alias(ep, exit_name, filename, False)
            exit_subprocess = Condition(exit_name)
            exit_subprocess.comment = 'Exit the module before its unloading with {!r} function.'.format(
                exit_name)
            exit_subprocess.statements = [
                model_comment('callback', exit_name,
                              {'call': "{}();".format(exit_name)}),
                "{}();".format(new_name)
            ]
            exit_subprocess.trace_relevant = True
            logger.debug("Found exit function {}".format(exit_name))
            ep.actions[exit_subprocess.name] = exit_subprocess

    # Generate conditions
    success = ep.add_condition('init_success', ["%ret% == 0"], [],
                               "Module has been initialized.")
    ep.actions[success.name] = success
    # Generate else branch
    failed = ep.add_condition('init_failed', ["%ret% != 0"], [],
                              "Failed to initialize the module.")
    ep.actions[failed.name] = failed

    # Add subprocesses finally
    process = ''
    for i, pair in enumerate(inits):
        process += "<{0}>.(<init_failed>".format(pair[1])
        for j, pair2 in enumerate(exits[::-1]):
            if pair2[0] == pair[0]:
                break
        j = 1
        for _, exit_name in exits[:j - 1:-1]:
            process += ".<{}>".format(exit_name)
        process += "|<init_success>."

    for _, exit_name in exits:
        process += "<{}>.".format(exit_name)
    # Remove the last dot
    process = process[:-1]

    process += ")" * len(inits)

    if len(kernel_initializations) > 0 and len(inits) > 0:
        ep.process += "<{}>.(<{}> | <{}>.({}))".format(ki_subprocess.name,
                                                       ki_failed.name,
                                                       ki_success.name,
                                                       process)
    elif len(kernel_initializations) == 0 and len(inits) > 0:
        ep.process += process
    elif len(kernel_initializations) > 0 and len(inits) == 0:
        ep.process += "<{}>.(<{}> | <{}>)".format(ki_subprocess.name,
                                                  ki_failed.name,
                                                  ki_success.name, process)
    else:
        raise NotImplementedError(
            "There is no both kernel initilization functions and module initialization functions"
        )
    return ep
Exemplo n.º 3
0
def __generate_call(emg, conf, ep, func, obj):
    # Add declaration of caller
    caller_func = Function("ldv_emg_{}_caller".format(func), "void a(void)")
    ep.add_declaration("environment model", caller_func.name,
                       caller_func.declare(True)[0])
    expression = ""
    body = []
    initializations = []

    # Check retval and cast to void call
    if obj.declaration.return_value and obj.declaration.return_value.identifier != 'void':
        expression += "(void) "

    # Get arguments and allocate memory for them
    args = []
    free_args = []
    for index, arg in enumerate(obj.declaration.parameters):
        if not isinstance(arg, str):
            argvar = Variable("ldv_arg_{}".format(index), arg)
            body.append(argvar.declare() + ";")
            args.append(argvar.name)
            if isinstance(arg, Pointer):
                elements = get_conf_property(
                    conf, "initialize strings as null terminated")
                if elements and arg.identifier == 'char **':
                    if isinstance(elements, int) or elements.isnumeric():
                        elements = int(elements)
                    else:
                        elements = 'ldv_undef_int()'
                    argvar_len = Variable(argvar.name + '_len', 'int')
                    # Define explicitly number of arguments, since undef value is too difficult sometimes
                    initializations.append("int {} = {};".format(
                        argvar_len.name, elements))
                    initializations.append(
                        "{} = (char **) ldv_xmalloc({} * sizeof(char *));".
                        format(argvar.name, argvar_len.name))
                    # Initialize all elements but the last one
                    initializations.append(
                        "for (int i = 0; i < {} - 1; i++)".format(
                            argvar_len.name))
                    # Some undefined data
                    initializations.append(
                        "\t{}[i] = (char *) external_allocated_data();".format(
                            argvar.name))
                    # The last element is a string
                    initializations.append("{}[{}] = (char * ) 0;".format(
                        argvar.name, elements - 1))
                    free_args.append(argvar.name)
                elif get_necessary_conf_property(
                        emg.conf["translation options"], "allocate external"):
                    value = "external_allocated_data();"
                    initializations.append("{} = {}".format(
                        argvar.name, value))
                else:
                    if get_necessary_conf_property(
                            emg.conf["translation options"],
                            "allocate with sizeof"):
                        apt = arg.points.to_string(
                            '', typedef='complex_and_params')
                        value = "ldv_xmalloc(sizeof({}));".\
                            format(apt if apt != 'void' else apt + '*')
                    else:
                        value = "ldv_xmalloc_unknown_size(0);"
                    free_args.append(argvar.name)
                    initializations.append("{} = {}".format(
                        argvar.name, value))

    # Generate call
    expression += "{}({});".format(func, ", ".join(args))

    # Generate function body
    body += initializations + [expression]

    # Free memory
    for arg in free_args:
        body.append("ldv_free({});".format(arg))

    caller_func.body = body

    # Add definition of caller
    ep.add_definition(obj.definition_file, caller_func.name,
                      caller_func.define() + ["\n"])

    # Return call expression
    return "{}();".format(caller_func.name)