Beispiel #1
0
////////////Implementation of auxiliary functions//////////////////////////////
static void*
calc_essence_alloc(size_t size)
{
    void* essence;
    if(size < sizeof(struct calc_essence*))
    {
        print_error0("Size of essence created should be greater or equal, than size of base class.");
        return NULL;
    }
    essence = kmalloc(size, GFP_KERNEL);
    if(!essence)
    {
        print_error0("Cannot allocate memory for essence.");
    }
    return essence;
}
Beispiel #2
0
kedr_calc_t*
kedr_calc_parse(const char* expr,
                int const_vec_n, const struct kedr_calc_const_vec* const_vec,
                int var_n, const char* const* var_names,
                int weak_vars_n, const struct kedr_calc_weak_var* weak_vars)
{
    struct kedr_calc* calc = NULL;
    struct parse_data parse_data;

    parse_data.expr = expr;
    parse_data.current_pos = 0;

    parse_data.const_vec_n = const_vec_n;
    parse_data.const_vec = const_vec;

    parse_data.var_n = var_n;
    parse_data.var_names = var_names;

    parse_data.weak_vars = weak_vars;
    parse_data.weak_vars_n = weak_vars_n;

    parse_data.current_token_type = token_type_start;
    //value and index undefined - shouln't be used with current token_type
    calc = kmalloc(sizeof(*calc), GFP_KERNEL);
    if(calc == NULL)
    {
        print_error0("Cannot allocate kedr_calc_t object.");
        return NULL;
    }
    calc->top_essence = parse_data_parse(&parse_data, priority_min);
    if(calc->top_essence == NULL)
    {
        kfree(calc);
        return NULL;//error already been traced in parse_data_parse()
    }
    if(parse_data.current_token_type != token_type_eof)
    {
        print_error("Unexpected symbol of type %d after expression.",
                    (int)parse_data.current_token_type);
        calc_essence_free(calc->top_essence);
        kfree(calc);
        return NULL;
    }
    calc->weak_vars = weak_vars;

    return calc;
}
Beispiel #3
0
//Create filled instance of calc_essence_2op
static struct calc_essence*
calc_essence_2op_create(enum calc_essence_type type, struct calc_essence* op1, struct calc_essence* op2)
{
    struct calc_essence_2op* result;
    // Verification, whether type really represent type of binary operation
    switch(type)
    {
    case calc_essence_type_multiply:
    case calc_essence_type_divide:
    case calc_essence_type_rest:

    case calc_essence_type_plus:
    case calc_essence_type_minus:

    case calc_essence_type_left_shift:
    case calc_essence_type_right_shift:

    case calc_essence_type_less:
    case calc_essence_type_greater:
    case calc_essence_type_less_equal:
    case calc_essence_type_greater_equal:

    case calc_essence_type_equal:
    case calc_essence_type_inequal:

    case calc_essence_type_binary_and:
    case calc_essence_type_binary_xor:
    case calc_essence_type_binary_or:

    case calc_essence_type_logical_and:
    case calc_essence_type_logical_or:
        break;
    default:
        print_error0("Unknown type of 2-operand essence");
        return NULL;
    }
    result = calc_essence_alloc(sizeof(*result));
    if(result == NULL) return NULL;
    result->base.type = type;
    result->op1 = op1;
    result->op2 = op2;
    return (struct calc_essence*)result;
}
Beispiel #4
0
//Create filled instance of calc_essence_3op
static struct calc_essence*
calc_essence_3op_create(enum calc_essence_type type,
                        struct calc_essence* op1, struct calc_essence* op2, struct calc_essence* op3)
{
    struct calc_essence_3op* result;
    // Verification, whether type really represent type of ternary operation
    switch(type)
    {
    case calc_essence_type_cond:
        break;
    default:
        print_error0("Unknown type of 3-operand essence");
        return NULL;
    }
    result = calc_essence_alloc(sizeof(*result));
    if(result == NULL) return NULL;
    result->base.type = type;
    result->op1 = op1;
    result->op2 = op2;
    result->op3 = op3;
    return (struct calc_essence*)result;
}
Beispiel #5
0
//Create filled instance of calc_essence_1op
static struct calc_essence*
calc_essence_1op_create(enum calc_essence_type type, struct calc_essence* op)
{
    struct calc_essence_1op* result;
    // Verification, whether type really represent type of unary operation
    switch(type)
    {
    case calc_essence_type_unary_plus:
    case calc_essence_type_unary_minus:
    case calc_essence_type_binary_not:
    case calc_essence_type_logical_not:
        break;
    default:
        print_error0("Unknown type of 1-operand essence");
        return NULL;
    }
    result = calc_essence_alloc(sizeof(*result));
    if(result == NULL) return NULL;
    result->base.type = type;
    result->op = op;
    return (struct calc_essence*)result;
}
Beispiel #6
0
// 'Main' function for parse string
static struct calc_essence* parse_data_parse(struct parse_data* data, int priority)
{
    struct calc_essence* result = NULL;
    // Operand
    switch(parse_data_next_token(data))
    {
    case token_type_error:
        break;//error was already been traced in parse_data_next_token()
    case token_type_eof:
        print_error0("End of file while operand expected");
        break;
    case token_type_value:
    case token_type_constant:
        result = calc_essence_val_create(data->current_token_value);
        if(result) parse_data_next_token(data);// advance to the next token
        break;
    case token_type_variable:
        result = calc_essence_var_create(data->current_token_index);
        if(result) parse_data_next_token(data);// advance to the next token
        break;
    case token_type_weak_variable:
        result = calc_essence_weak_var_create(data->current_token_index);
        if(result) parse_data_next_token(data);// advance to the next token
        break;
    case token_type_open_parenthesis:
        result = parse_data_parse(data, priority_min);
        if(!result) break;
        if(data->current_token_type != token_type_close_parenthesis)
        {
            print_error("Expected close parenthesis (')'), but token of type %d found.",
                        (int)data->current_token_type);
            // rollback result
            calc_essence_free(result);
            result = NULL;
            break;
        }
        parse_data_next_token(data);// advance to the next token
        break;
        //unary operations without left operand
#define UNARY_OP(essence_type_pure, priority_pure) {\
    struct calc_essence* op = parse_data_parse(data, priority_##priority_pure);\
    if(op == NULL) break;\
    result = calc_essence_1op_create(calc_essence_type_##essence_type_pure, op);\
    if(result == NULL) {calc_essence_free(op);}\
}
    case token_type_minus:
        UNARY_OP(unary_minus, unary_minus);
        break;
    case token_type_plus:
        UNARY_OP(unary_plus, unary_plus);
        break;
    case token_type_logical_not:
        UNARY_OP(logical_not, logical_not);
        break;
    case token_type_binary_not:
        UNARY_OP(binary_not, binary_not);
        break;
#undef UNARY_OP
    default:
        print_error("Expected operand, but token of type %d found.",
                    (int)data->current_token_type);
    }

    if(result == NULL) return NULL;
    //Determine operation and update operand in cycle, until error, delemiter or operation with lower priority is encountered
    while(1)
    {
        switch(data->current_token_type)
        {
        case token_type_error:
            calc_essence_free(result);
            return NULL;// error was already been traced in parse_data_next_token()
        // delimiters
        case token_type_eof:
        case token_type_close_parenthesis:
        case token_type_cond_second:
            return result;
            // operations with two operands
#define TWO_OPERANDS_ESSENCE(essence_type_pure, left_priority_pure, right_priority_pure) \
if(priority > priority_##left_priority_pure) return result;\
{\
    struct calc_essence* op1, *op2;\
    debug("Evaluate second operand for essence of type %d...", (int)calc_essence_type_##essence_type_pure);\
    op2 = parse_data_parse(data, priority_##right_priority_pure);\
    if(op2 == NULL) {calc_essence_free(result); return NULL;}\
    op1 = result;\
    debug0("Create essence.");\
    result = calc_essence_2op_create(calc_essence_type_##essence_type_pure, op1, op2);\
    if(result == NULL) {calc_essence_free(op1); calc_essence_free(op2); return NULL;}\
}
        case token_type_multiply:
            TWO_OPERANDS_ESSENCE(multiply, multiply_left, multiply_right);
            break;
        case token_type_divide:
            TWO_OPERANDS_ESSENCE(divide, divide_left, divide_right);
            break;
        case token_type_rest:
            TWO_OPERANDS_ESSENCE(rest, rest_left, rest_right);
            break;
        case token_type_plus:
            TWO_OPERANDS_ESSENCE(plus, plus_left, plus_right);
            break;
        case token_type_minus:
            TWO_OPERANDS_ESSENCE(minus, minus_left, minus_right);
            break;
        case token_type_left_shift:
            TWO_OPERANDS_ESSENCE(left_shift, left_shift_left, left_shift_right);
            break;
        case token_type_right_shift:
            TWO_OPERANDS_ESSENCE(right_shift, right_shift_left, right_shift_right);
            break;
        case token_type_less:
            TWO_OPERANDS_ESSENCE(less, less_left, less_right);
            break;
        case token_type_greater:
            TWO_OPERANDS_ESSENCE(greater, greater_left, greater_right);
            break;
        case token_type_less_equal:
            TWO_OPERANDS_ESSENCE(less_equal, less_equal_left, less_equal_right);
            break;
        case token_type_greater_equal:
            TWO_OPERANDS_ESSENCE(greater_equal, greater_equal_left, greater_equal_right);
            break;
        case token_type_equal:
            TWO_OPERANDS_ESSENCE(equal, equal_left, equal_right);
            break;
        case token_type_inequal:
            TWO_OPERANDS_ESSENCE(inequal, inequal_left, inequal_right);
            break;
        case token_type_binary_or:
            TWO_OPERANDS_ESSENCE(binary_or, binary_or_left, binary_or_right);
            break;
        case token_type_binary_xor:
            TWO_OPERANDS_ESSENCE(binary_xor, binary_xor_left, binary_xor_right);
            break;
        case token_type_binary_and:
            TWO_OPERANDS_ESSENCE(binary_and, binary_and_left, binary_and_right);
            break;
        case token_type_logical_or:
            TWO_OPERANDS_ESSENCE(logical_or, logical_or_left, logical_or_right);
            break;
        case token_type_logical_and:
            TWO_OPERANDS_ESSENCE(logical_and, logical_and_left, logical_and_right);
            break;
#undef TWO_OPERANDS_ESSENCE
        //Only one three operand essence, so without macro
        case token_type_cond_first:
            if(priority > priority_cond_left) return result;
            {
                struct calc_essence *op1, *op2, *op3;
                debug0("Evaluate second operand for 'a ? b : c' operation...");
                \
                op2 = parse_data_parse(data, priority_min);
                if(op2 == NULL)
                {
                    calc_essence_free(result);
                    return NULL;
                }
                if(data->current_token_type != token_type_cond_second)
                {
                    print_error("Expected ':', but token of type %d encountered.",
                                (int)data->current_token_type);
                }
                debug0("Evaluate third operand for 'a ? b : c' operation...");
                \
                op3 = parse_data_parse(data, priority_cond_right);
                if(op3 == NULL)
                {
                    calc_essence_free(op2);
                    calc_essence_free(result);
                    return NULL;
                }
                op1 = result;
                debug0("Create essence.");
                result = calc_essence_3op_create(calc_essence_type_cond, op1, op2, op3);
                if(result == NULL)
                {
                    calc_essence_free(op1);
                    calc_essence_free(op2);
                    calc_essence_free(op3);
                    return NULL;
                }
            }
            break;
        //...
        default:
            print_error("Expected operation, but token of type %d found.",
                        (int)data->current_token_type);
            calc_essence_free(result);
            return NULL;
        }
    }
    return result;
}
int main(int argc, char* const argv[], char* const envp[])
{
    int fd_trace;
    int result = 0;
    
    enum capture_trace_flags flags;
    const char* debugfs_mount_point;
    char const** file_names;
    char const** program_names;
    
    result = process_options(argc, argv,
        &flags,
        &debugfs_mount_point,
        &file_names,
        &program_names);
    if(result)
        return result;

    size_t trace_file_name_len = snprintf_trace_filename(NULL, 0,
        debugfs_mount_point);
    char* trace_file_name = malloc(trace_file_name_len + 1);
    if(trace_file_name == NULL)
    {
        print_error0("Cannot allocate memory for trace file name.");
        free(program_names);
        free(file_names);
    }
    snprintf_trace_filename(trace_file_name, trace_file_name_len + 1,
        debugfs_mount_point);
    
    fd_trace = open(trace_file_name, O_RDONLY);
    if(fd_trace == -1)
    {
        switch(errno)
        {
        case ENOENT:
            print_error("Trace file '%s' does not exist.\n"
                "Debugfs is probably not mounted to \"%s\".",
                trace_file_name, debugfs_mount_point);
        break;
        case EBUSY:
            print_error("Trace file is busy.\n"
                "Another instance of %s is probably processing it.",
                PROGRAM_NAME);
        break;
        //case EACCESS: what message should be here?
        default:
            print_error("Cannot open trace file '%s' for reading: %s.",
                trace_file_name, strerror(errno));
        }
        free(trace_file_name);
        free(program_names);
        free(file_names);
        return -1;
    }
    free(trace_file_name);
    
    if(change_fd_flags(fd_trace, FD_CLOEXEC, FD_CLOEXEC) == -1)
    {
        print_error0("Cannot set FD_CLOEXEC flag for opened trace file.");
        close(fd_trace);
        free(program_names);
        free(file_names);
        return -1;
    }
    
    if(change_fl_flags(fd_trace, O_NONBLOCK, O_NONBLOCK) == -1)
    {
        print_error0("Cannot set O_NONBLOCK flag for opened trace file.");
        close(fd_trace);
        free(program_names);
        free(file_names);
        return -1;
    }

    struct trace_consumers trace_consumers;
    trace_consumers_init(&trace_consumers);
    if(flags & capture_trace_session)
    {
        static struct target_session_barrier barrier;
        target_session_barrier_init(&barrier);
        trace_consumers_set_barrier(&trace_consumers, &barrier.barrier);
    }
    
    const char** program_name;
    for(program_name = program_names; *program_name != NULL; program_name++)
    {
        // Create another process which piped with current
        struct trace_consumer* consumer =
            trace_consumer_create_process(*program_name);
        if(consumer == NULL)
        {
            print_error("Cannot create child process \"%s\".",
                *program_name);
            trace_consumers_free(&trace_consumers);
            close(fd_trace);
            free(program_names);
            free(file_names);
            return -1;
        }
        trace_consumers_add_consumer(&trace_consumers, consumer);
    }
    free(program_names);
    
    const char** file_name;
    for(file_name = file_names; *file_name != NULL; file_name++)
    {
        // Create trace consumer as file
        struct trace_consumer* consumer =
            trace_consumer_create_file(*file_name);
        if(consumer == NULL)
        {
            print_error("Cannot open file for writing trace \"%s\".",
                *file_name);
            trace_consumers_free(&trace_consumers);
            close(fd_trace);
            free(file_names);
            return -1;
        }
        trace_consumers_add_consumer(&trace_consumers, consumer);
    }
    free(file_names);
    
    if(flags & capture_trace_blocking)
    {
        if(blocking_mode_set())
        {
            trace_consumers_free(&trace_consumers);
            close(fd_trace);
            return -1;
        }
    }

    /* Read trace until error occures or should stop for other reasons.*/
    do
    {
        char trace_buffer[READ_BUFFER_SIZE];
        ssize_t read_size;
        
        read_size = trace_read_common(fd_trace,
            trace_buffer, sizeof(trace_buffer));
        
        if(read_size == -1)
        {
            print_error("Error occures while reading trace: %s.",
                strerror(errno));
            result = -1;
            break;
        }
        else if(read_size == 0)
        {
            /* EOF */
            result = 1;
            break;
        }
        
        result = trace_consumers_process_data(&trace_consumers,
            trace_buffer, read_size);

    }while(result == 0);

    if(flags & capture_trace_blocking)
    {
        blocking_mode_clear();
    }

    close(fd_trace);
    
    if(result == -1)
    {
        trace_consumers_free(&trace_consumers);
        return -1;
    }
    else
        return trace_consumers_free_wait(&trace_consumers);
}