Example #1
0
int main()
{
	adam_init();
	
	sexpression_t* svoid;
	assert(NULL != sexp_parse("void", &svoid));
	tvoid = dalvik_type_from_sexp(svoid);
	sexp_free(svoid);
	assert(NULL != tvoid);
	/* load package */
	dalvik_loader_from_directory("test/cases/block_analyzer");
	
	
	/* run test cases */
	case1();

	case2();

	case3();

	dalvik_type_free(tvoid);
	/* finalize */
	adam_finalize();
	return 0;
}
Example #2
0
dalvik_field_t* dalvik_field_from_sexp(const sexpression_t* sexp, const char* class_path, const char* file_name)
{
#ifdef PARSER_COUNT
    dalvik_field_count ++;
#endif

    dalvik_field_t* ret = NULL;
    if(SEXP_NIL == sexp) goto ERR;
    if(NULL == class_path) class_path = "(undefined)";
    if(NULL== file_name)   file_name = "(undefined)";
    const char* name;
    sexpression_t *attr_list , *type_sexp;
    if(!sexp_match(sexp, "(L=C?L?_?A", DALVIK_TOKEN_FIELD, &attr_list, &name, &type_sexp, &sexp))
    {
        LOG_ERROR("bad field definition");
        goto ERR;
    }
    
    ret = (dalvik_field_t*)malloc(sizeof(dalvik_field_t));
    
    ret->name = name;
    ret->path = class_path;
    ret->file = file_name;

    if(NULL == (ret->type = dalvik_type_from_sexp(type_sexp))) 
    {
        LOG_ERROR("can't parse type");
        LOG_DEBUG("type is %s", sexp_to_string(type_sexp,NULL));
        goto ERR;
    }

    if(-1 == (ret->attrs = dalvik_attrs_from_sexp(attr_list))) 
    {
        LOG_ERROR("can't parse attribute");
        goto ERR;
    }

    if(SEXP_NIL != sexp)
    {
        /* it has a defualt value */
        if(!sexp_match(sexp, "(A", &ret->defualt_value)) 
        {
            LOG_ERROR("can't parse default value");
            goto ERR;
        }
        LOG_NOTICE("fixme: parse default value of a field");
    }
    return ret;
ERR:
    dalvik_field_free(ret);
    return NULL;
}
Example #3
0
dalvik_method_t* dalvik_method_from_sexp(const sexpression_t* sexp, const char* class_path,const char* file)
{

#ifdef PARSER_COUNT
    dalvik_method_count ++;
#endif

    dalvik_method_t* method = NULL;

    if(SEXP_NIL == sexp) return NULL;
    
    if(NULL == class_path) class_path = "(undefined)";
    if(NULL == file) file = "(undefined)";

    const char* name;
    sexpression_t *attrs, *arglist, *ret, *body;
    /* matches (method (attribute-list) method-name (arg-list) return-type body) */
    if(!sexp_match(sexp, "(L=C?L?C?_?A", DALVIK_TOKEN_METHOD, &attrs, &name, &arglist, &ret, &body))
    {
        LOG_ERROR("bad method defination"); 
        return NULL;
    }

    /* get attributes */
    int attrnum;
    if((attrnum = dalvik_attrs_from_sexp(attrs)) < 0)
    {
        LOG_ERROR("can not parse attributes");
        return NULL;
    }

    /* get number of arguments */
    int num_args;
    num_args = sexp_length(arglist);

    /* Now we know the size we have to allocate for this method */
    method = (dalvik_method_t*)malloc(sizeof(dalvik_method_t) + sizeof(dalvik_type_t*) * (num_args + 1));
    if(NULL == method) 
    {
        LOG_ERROR("can not allocate memory for method argument list");
        return NULL;
    }
    memset(method->args_type, 0, sizeof(dalvik_type_t*) * (num_args + 1));

    method->num_args = num_args;
    method->path = class_path;
    method->file = file;
    method->name = name;

    /* Setup the type of argument list */
    int i;
    for(i = 0;arglist != SEXP_NIL && i < num_args; i ++)
    {
        sexpression_t *this_arg;
        if(!sexp_match(arglist, "(_?A", &this_arg, &arglist))
        {
            LOG_ERROR("invalid argument list");
            goto ERR;
        }
        if(NULL == (method->args_type[i] = dalvik_type_from_sexp(this_arg)))
        {
            LOG_ERROR("invalid argument type @ #%d", i);
            goto ERR;
        }
    }

    /* Setup the return type */
    if(NULL == (method->return_type = dalvik_type_from_sexp(ret)))
    {
        LOG_ERROR("invalid return type");
        goto ERR;
    }

    /* Now fetch the body */
    
    //TODO: process other parts of a method
    int current_line_number = 0;    /* Current Line Number */
    uint32_t last = DALVIK_INSTRUCTION_INVALID;
    //int last_label = -1;
    int label_stack[DALVIK_METHOD_LABEL_STACK_SIZE];  /* how many label can one isntruction assign to */
    int label_sp;
    int from_label[DALVIK_MAX_CATCH_BLOCK];    /* NOTICE: the maximum number of catch block is limited to this constant */
    int to_label  [DALVIK_MAX_CATCH_BLOCK];
    int label_st  [DALVIK_MAX_CATCH_BLOCK];    /* 0: haven't seen any label related to the label. 
                                                * 1: seen from label before
                                                * 2: seen from and to label
                                                */
    label_sp  = 0;
    dalvik_exception_handler_t* excepthandler[DALVIK_MAX_CATCH_BLOCK] = {};
    dalvik_exception_handler_set_t* current_ehset = NULL;
    int number_of_exception_handler = 0;
    for(;body != SEXP_NIL;)
    {
        sexpression_t *this_smt;
        if(!sexp_match(body, "(C?A", &this_smt, &body))
        {
            LOG_ERROR("invalid method body");
            goto ERR;
        }
        /* First check if the statement is a psuedo-instruction */
        const char* arg;
#if LOG_LEVEL >= 6
        char buf[40906];
        static int counter = 0;
#endif
        LOG_DEBUG("#%d current instruction : %s",(++counter) ,sexp_to_string(this_smt, buf) );
        if(sexp_match(this_smt, "(L=L=L?", DALVIK_TOKEN_LIMIT, DALVIK_TOKEN_REGISTERS, &arg))
        {
            /* (limit-registers k) */
            method->num_regs = atoi(arg);
            LOG_DEBUG("uses %d registers", method->num_regs);
        }
        else if(sexp_match(this_smt, "(L=L?", DALVIK_TOKEN_LINE, &arg))
        {
            /* (line arg) */
            current_line_number = atoi(arg);
        }
        else if(sexp_match(this_smt, "(L=L?", DALVIK_TOKEN_LABEL, &arg))
        {
            /* (label arg) */
            int lid = dalvik_label_get_label_id(arg);
            int i;
            if(lid == -1) 
            {
                LOG_ERROR("can not create label for %s", arg);
                goto ERR;
            }
            //last_label = lid;
            if(label_sp < DALVIK_METHOD_LABEL_STACK_SIZE)
                label_stack[label_sp++] = lid;
            else
                LOG_WARNING("label stack overflow, might loss some label here");
            int enbaled_count = 0;
            dalvik_exception_handler_t* exceptionset[DALVIK_MAX_CATCH_BLOCK];
            for(i = 0; i < number_of_exception_handler; i ++)
            {
                if(lid == from_label[i] && label_st[i] == 0)
                    label_st[i] = 1;
                else if(lid == to_label[i] && label_st[i] == 1)
                    label_st[i] = 2;
                else if(lid == from_label[i] && label_st[i] != 0)
                    LOG_WARNING("meet from label twice, it might be a mistake");
                else if(lid == to_label[i] && label_st[i] != 1)
                    LOG_WARNING("to label is before from label, it might be a mistake");
                
                if(label_st[i] == 1)
                    exceptionset[enbaled_count++] = excepthandler[i];
            }
            current_ehset = dalvik_exception_new_handler_set(enbaled_count, exceptionset);
        }
        else if(sexp_match(this_smt, "(L=A", DALVIK_TOKEN_ANNOTATION, &arg))
        {
            /* Simplely ignore */
            LOG_INFO("fixme: ignored psuedo-insturction (annotation)");
        }
        else if(sexp_match(this_smt, "(L=L=A", DALVIK_TOKEN_DATA, DALVIK_TOKEN_ARRAY, &arg))
        {
            /* TODO: what is (data-array ....)statement currently ignored */
            LOG_INFO("fixme: (data-array) psuedo-insturction is to be implemented");
        }
        else if(sexp_match(this_smt, "(L=A", DALVIK_TOKEN_CATCH, &arg) || 
                sexp_match(this_smt, "(L=A", DALVIK_TOKEN_CATCHALL, &arg))
        {
            excepthandler[number_of_exception_handler] = 
                dalvik_exception_handler_from_sexp(
                        this_smt, 
                        from_label + number_of_exception_handler, 
                        to_label + number_of_exception_handler);
            if(excepthandler[number_of_exception_handler] == NULL)
            {
                LOG_WARNING("invalid exception handler %s", sexp_to_string(this_smt, NULL));
                continue;
            }
            LOG_DEBUG("exception %s is handlered in label #%d", 
                      excepthandler[number_of_exception_handler]->exception, 
                      excepthandler[number_of_exception_handler]->handler_label);
            //label_st[number_of_exception_handler] = 0;   /* TODO: verify this is a bug */
            number_of_exception_handler ++;
        }
        else if(sexp_match(this_smt, "(L=A", DALVIK_TOKEN_FILL, &arg))
        {
            //TODO: fill-array-data psuedo-instruction
            LOG_INFO("fixme: (fill-array-data) is to be implemented");
        }
        else
        {
            dalvik_instruction_t* inst = dalvik_instruction_new();
            if(NULL == inst) 
            {
                LOG_ERROR("can not create new instruction");
                goto ERR;
            }
            if(dalvik_instruction_from_sexp(this_smt, inst, current_line_number) < 0)
            {
                LOG_ERROR("can not recognize instuction %s", sexp_to_string(this_smt, NULL));
                goto ERR;
            }
            if(DALVIK_INSTRUCTION_INVALID == last) 
                method->entry = dalvik_instruction_get_index(inst);
            else
                dalvik_instruction_set_next(last, inst);
            last = dalvik_instruction_get_index(inst);
            inst->handler_set = current_ehset; 
            if(label_sp > 0)
            {
                int i;
                for(i = 0; i < label_sp; i++)
                {
                    LOG_DEBUG("assigned instruction@%p to label #%d", inst, label_stack[i]);
                    dalvik_label_jump_table[label_stack[i]] = dalvik_instruction_get_index(inst);
                }
                label_sp = 0;
            }
        }
    }
    return method;
ERR:
    dalvik_method_free(method);
    return NULL;
}
Example #4
0
int main()
{
	adam_init();

	/* Runnability test */
	assert(dalvik_loader_from_directory("test/data/AndroidAntlr") >= 0);
	sexpression_t* sexp;
	sexp_parse("[object java/lang/String]", &sexp);
	dalvik_type_t *type = dalvik_type_from_sexp(sexp);
	sexp_free(sexp);
	const char* classname = stringpool_query("antlr/ANTLRParser");
	const char* methodname = stringpool_query("treeParserSpec");
	dalvik_type_t* arglist[] = {NULL ,NULL};
	arglist[0] = type;
	
	sexpression_t* svoid;
	assert(NULL != sexp_parse("void", &svoid));
	dalvik_type_t* tvoid = dalvik_type_from_sexp(svoid);
	sexp_free(svoid);
	
	dalvik_block_t* block = dalvik_block_from_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	dalvik_type_free(type);
	assert(NULL != block);

	/* setup function test */
	assert(dalvik_loader_from_directory("test/cases/dalvik_block") >= 0);
	arglist[0] = NULL;
	classname = stringpool_query("TestClass");
	
	/* Case 1 */
	methodname = stringpool_query("case1");
	block = dalvik_block_from_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	const dalvik_method_t* method = dalvik_memberdict_get_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	assert(NULL != method);
	assert(NULL != block);
	assert(block->begin == method->entry);
	assert(block->end == method->entry + 3);
	assert(block->nbranches == 1);
	assert(block->branches[0].conditional == 0);
	assert(DALVIK_BLOCK_BRANCH_UNCOND_TYPE_IS_JUMP(block->branches[0]));
	dalvik_block_t* retblk = block->branches[0].block;
	assert(NULL != retblk);
	assert(1 == retblk->nbranches);
	assert(DALVIK_BLOCK_BRANCH_UNCOND_TYPE_IS_RETURN(retblk->branches[0]));

	/* Case 2 */
	methodname = stringpool_query("case2");
	block = dalvik_block_from_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	method = dalvik_memberdict_get_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	assert(NULL != block);
	assert(NULL != method);
	/* verify block0 */
	assert(block->begin == method->entry);
	assert(block->end   == method->entry + 2);
	assert(block->nbranches == 2);
	assert(block->branches[0].disabled == 0);
	assert(block->branches[0].linked == 1);
	assert(block->branches[0].conditional == 1);
	assert(block->branches[0].eq == 1);
	assert(block->branches[0].lt == 0);
	assert(block->branches[0].gt == 0);
	assert(block->branches[0].left_inst == 0);
	assert(block->branches[0].left->header.flags == 0);
	assert(block->branches[0].left->payload.uint16 == 1);
	assert(block->branches[0].right->header.flags == 0);
	assert(block->branches[0].right->payload.uint16 == 2);
	assert(block->branches[0].block != NULL);
	assert(block->branches[1].disabled == 0);
	assert(block->branches[1].linked == 1);
	assert(block->branches[1].conditional == 0);
	assert(block->branches[1].block != NULL);
	/* verify block2 */
	dalvik_block_t* block2 = block->branches[0].block;
	assert(block2->begin == method->entry + 5);
	assert(block2->end == method->entry + 6);
	assert(block2->nbranches == 1);
	assert(block2->branches[0].disabled == 0);
	assert(block2->branches[0].linked == 1);
	assert(block2->branches[0].conditional == 0);
	assert(block2->branches[0].block != NULL);
	/* verify block1 */
	dalvik_block_t* block1 = block->branches[1].block;
	assert(block1->begin == method->entry + 3);
	assert(block1->end == method->entry + 4);
	assert(block1->nbranches == 1);
	assert(block1->branches[0].disabled == 0);
	assert(block1->branches[0].linked == 1);
	assert(block1->branches[0].conditional == 0);
	assert(block1->branches[0].block != NULL);
	assert(block1->branches[0].block == block2->branches[0].block);
	/* verify block3 */
	dalvik_block_t* block3 = block1->branches[0].block;
	assert(block3->begin == method->entry + 6);
	assert(block3->end == method->entry + 6);
	assert(block3->nbranches == 1);
	assert(DALVIK_BLOCK_BRANCH_UNCOND_TYPE_IS_RETURN(block3->branches[0]));
	assert(block3->branches[0].block == NULL);
	assert(block3->branches[0].left->payload.uint16 == 1);
	assert(block3->branches[0].block == NULL);

	/* Case 3 */
	methodname = stringpool_query("case3");
	block = dalvik_block_from_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	method = dalvik_memberdict_get_method(classname, methodname, (const dalvik_type_t**)arglist, tvoid);
	assert(NULL != block);
	assert(NULL != method);
	/* verify block 1 */
	assert(block->begin == method->entry + 0);
	assert(block->end == method->entry + 2);
	assert(block->nbranches == 1);
	assert(block->branches[0].linked == 1);
	assert(block->branches[0].disabled == 0);
	assert(block->branches[0].conditional == 0);
	assert(block->branches[0].block != NULL);
	/* verify block 3*/
	block3 = block->branches[0].block;
	assert(block3->begin == method->entry + 6);
	assert(block3->end == method->entry + 7);
	assert(block3->nbranches == 1);
	assert(block3->branches[0].linked == 1);
	assert(block3->branches[0].disabled == 0);
	assert(DALVIK_BLOCK_BRANCH_UNCOND_TYPE_IS_JUMP(block3->branches[0]));

	/*verify block 4 */
	dalvik_block_t* block4 = block3->branches[0].block;
	assert(block4->begin == method->entry + 7);
	assert(block4->end == method->entry + 7);
	assert(block4->nbranches == 1);
	assert(DALVIK_BLOCK_BRANCH_UNCOND_TYPE_IS_RETURN(block4->branches[0]));
	assert(block4->branches[0].left->payload.uint16 == 9);
	assert(block4->branches[0].block == NULL);

	/* Case 4 */
	methodname = stringpool_query("case4");
	block = dalvik_block_from_method(classname, methodname, (const dalvik_type_t**) arglist, tvoid);
	method = dalvik_memberdict_get_method(classname, methodname, (const dalvik_type_t**) arglist, tvoid);
	assert(NULL != block);
	assert(NULL != method);
	/* verify block 1 */
	assert(block->begin == method->entry + 0);
	assert(block->end == method->entry + 1);
	assert(block->nbranches == 1);
	assert(block->branches[0].linked == 1);
	assert(block->branches[0].disabled == 0);
	assert(block->branches[0].conditional == 0);
	assert(block->branches[0].block != NULL);
	/* verify block 2 */
	block2 = block->branches[0].block;
	assert(block2->begin == method->entry + 1);
	assert(block2->end == method->entry + 2);
	assert(block2->nbranches == 1);
	assert(block2->branches[0].linked == 1);
	assert(block2->branches[0].conditional == 0);
	assert(block2->branches[0].disabled == 0);
	assert(block2->branches[0].block != NULL);
	/* verify block3 */
	block3 = block2->branches[0].block;
	assert(block3->begin == method->entry + 2);
	assert(block3->end == method->entry + 3);
	assert(block3->nbranches == 1);
	assert(block3->branches[0].linked == 1);
	assert(block3->branches[0].conditional == 0);
	assert(block3->branches[0].disabled == 0);
	
	block4 = block3->branches[0].block;
	assert(NULL != block4);
	assert(DALVIK_BLOCK_BRANCH_UNCOND_TYPE_IS_RETURN(block4->branches[0]));
	assert(block4->branches[0].block == NULL);

	/* Case 5 */
	methodname = stringpool_query("case5");
	block = dalvik_block_from_method(classname, methodname, (const dalvik_type_t**) arglist, tvoid);
	method = dalvik_memberdict_get_method(classname, methodname, (const dalvik_type_t**) arglist, tvoid);
	assert(NULL != block);
	assert(NULL != method);

	adam_finalize();
	return 0;
}