Exemplo n.º 1
0
/* Parse an entity, returning the reg that it gets put into.
 * p_jmp will be set if it has to be set by the calling code; it should
 * be set to the place to jump to, to return to the calling code,
 * if the load of a field from the proto_tree fails. */
static int
gen_entity(dfwork_t *dfw, stnode_t *st_arg, dfvm_value_t **p_jmp)
{
	sttype_id_t       e_type;
	dfvm_insn_t       *insn;
	header_field_info *hfinfo;
	int reg = -1;
	e_type = stnode_type_id(st_arg);

	if (e_type == STTYPE_FIELD) {
		hfinfo = (header_field_info*)stnode_data(st_arg);
		reg = dfw_append_read_tree(dfw, hfinfo);

		insn = dfvm_insn_new(IF_FALSE_GOTO);
		g_assert(p_jmp);
		*p_jmp = dfvm_value_new(INSN_NUMBER);
		insn->arg1 = *p_jmp;
		dfw_append_insn(dfw, insn);
	}
	else if (e_type == STTYPE_FVALUE) {
		reg = dfw_append_put_fvalue(dfw, (fvalue_t *)stnode_data(st_arg));
	}
	else if (e_type == STTYPE_RANGE) {
		reg = dfw_append_mk_range(dfw, st_arg);
	}
	else if (e_type == STTYPE_FUNCTION) {
		reg = dfw_append_function(dfw, st_arg, p_jmp);
	}
	else {
		printf("sttype_id is %u\n", e_type);
		g_assert_not_reached();
	}
	return reg;
}
Exemplo n.º 2
0
static void
gen_relation(dfwork_t *dfw, dfvm_opcode_t op, stnode_t *st_arg1, stnode_t *st_arg2)
{
	dfvm_insn_t	*insn;
	dfvm_value_t	*val1, *val2;
	dfvm_value_t	*jmp1 = NULL, *jmp2 = NULL;
	int		reg1 = -1, reg2 = -1;

    /* Create code for the LHS and RHS of the relation */
    reg1 = gen_entity(dfw, st_arg1, &jmp1);
    reg2 = gen_entity(dfw, st_arg2, &jmp2);

    /* Then combine them in a DFVM insruction */
	insn = dfvm_insn_new(op);
	val1 = dfvm_value_new(REGISTER);
	val1->value.numeric = reg1;
	val2 = dfvm_value_new(REGISTER);
	val2->value.numeric = reg2;
	insn->arg1 = val1;
	insn->arg2 = val2;
	dfw_append_insn(dfw, insn);

    /* If either of the relation argumnents need an "exit" instruction
     * to jump to (on failure), mark them */
	if (jmp1) {
		jmp1->value.numeric = dfw->next_insn_id;
	}

	if (jmp2) {
		jmp2->value.numeric = dfw->next_insn_id;
	}
}
Exemplo n.º 3
0
/* returns register number */
static int
dfw_append_mk_range(dfwork_t *dfw, stnode_t *node)
{
	int			hf_reg, reg;
	header_field_info	*hfinfo;
	dfvm_insn_t		*insn;
	dfvm_value_t		*val;

	hfinfo = sttype_range_hfinfo(node);
	hf_reg = dfw_append_read_tree(dfw, hfinfo);

	insn = dfvm_insn_new(MK_RANGE);

	val = dfvm_value_new(REGISTER);
	val->value.numeric = hf_reg;
	insn->arg1 = val;

	val = dfvm_value_new(REGISTER);
	reg =dfw->next_register++;
	val->value.numeric = reg;
	insn->arg2 = val;

	val = dfvm_value_new(DRANGE);
	val->value.drange = sttype_range_drange(node);
	insn->arg3 = val;

	sttype_range_remove_drange(node);

	dfw_append_insn(dfw, insn);

	return reg;
}
Exemplo n.º 4
0
/* returns register number */
static int
dfw_append_mk_range(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp)
{
	int			hf_reg, reg;
	stnode_t                *entity;
	dfvm_insn_t		*insn;
	dfvm_value_t		*val;

	entity = sttype_range_entity(node);

	/* XXX, check if p_jmp logic is OK */
	hf_reg = gen_entity(dfw, entity, p_jmp);

	insn = dfvm_insn_new(MK_RANGE);

	val = dfvm_value_new(REGISTER);
	val->value.numeric = hf_reg;
	insn->arg1 = val;

	val = dfvm_value_new(REGISTER);
	reg =dfw->next_register++;
	val->value.numeric = reg;
	insn->arg2 = val;

	val = dfvm_value_new(DRANGE);
	val->value.drange = sttype_range_drange(node);
	insn->arg3 = val;

	sttype_range_remove_drange(node);

	dfw_append_insn(dfw, insn);

	return reg;
}
Exemplo n.º 5
0
/* returns register number */
static int
dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo)
{
	dfvm_insn_t	*insn;
	dfvm_value_t	*val1, *val2;
	int		reg = -1;
	gboolean	added_new_hfinfo = FALSE;

	/* Rewind to find the first field of this name. */
	while (hfinfo->same_name_prev) {
		hfinfo = hfinfo->same_name_prev;
	}

	/* Keep track of which registers
	 * were used for which hfinfo's so that we
	 * can re-use registers. */
	reg = GPOINTER_TO_UINT(
			g_hash_table_lookup(dfw->loaded_fields, hfinfo));
	if (reg) {
		/* Reg's are stored in has as reg+1, so
		 * that the non-existence of a hfinfo in
		 * the hash, or 0, can be differentiated from
		 * a hfinfo being loaded into register #0. */
		reg--;
	}
	else {
		reg = dfw->next_register++;
		g_hash_table_insert(dfw->loaded_fields,
			hfinfo, GUINT_TO_POINTER(reg + 1));

		added_new_hfinfo = TRUE;
	}

	insn = dfvm_insn_new(READ_TREE);
	val1 = dfvm_value_new(HFINFO);
	val1->value.hfinfo = hfinfo;
	val2 = dfvm_value_new(REGISTER);
	val2->value.numeric = reg;

	insn->arg1 = val1;
	insn->arg2 = val2;
	dfw_append_insn(dfw, insn);

	if (added_new_hfinfo) {
		while (hfinfo) {
			/* Record the FIELD_ID in hash of interesting fields. */
			g_hash_table_insert(dfw->interesting_fields,
			    GINT_TO_POINTER(hfinfo->id),
			    GUINT_TO_POINTER(TRUE));
			hfinfo = hfinfo->same_name_next;
		}
	}

	return reg;
}
Exemplo n.º 6
0
void
dfw_gencode(dfwork_t *dfw)
{
	int		id, id1, length;
	dfvm_insn_t	*insn, *insn1, *prev;
	dfvm_value_t	*arg1;

	dfw->insns = g_ptr_array_new();
	dfw->consts = g_ptr_array_new();
	dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
	dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
	gencode(dfw, dfw->st_root);
	dfw_append_insn(dfw, dfvm_insn_new(RETURN));

	/* fixup goto */
	length = dfw->insns->len;

	for (id = 0, prev = NULL; id < length; prev = insn, id++) {
		insn = (dfvm_insn_t	*)g_ptr_array_index(dfw->insns, id);
		arg1 = insn->arg1;
		if (insn->op == IF_TRUE_GOTO || insn->op == IF_FALSE_GOTO) {
			dfvm_opcode_t revert = (insn->op == IF_FALSE_GOTO)?IF_TRUE_GOTO:IF_FALSE_GOTO;
			id1 = arg1->value.numeric;
			do {
				insn1 = (dfvm_insn_t*)g_ptr_array_index(dfw->insns, id1);
				if (insn1->op == revert) {
					/* this one is always false and the branch is not taken*/
					id1 = id1 +1;
					continue;
				}
				else if (insn1->op == READ_TREE && prev && prev->op == READ_TREE &&
						prev->arg2->value.numeric == insn1->arg2->value.numeric) {
					/* hack if it's the same register it's the same field
					 * and it returns the same value
					 */
					id1 = id1 +1;
					continue;
				}
				else if (insn1->op != insn->op) {
					/* bail out */
					arg1 = insn->arg1;
					arg1->value.numeric = id1;
					break;
				}
				arg1 = insn1->arg1;
				id1 = arg1->value.numeric;
			} while (1);
		}
	}

	/* move constants after registers*/
	if (dfw->first_constant == -1) {
		/* NONE */
		dfw->first_constant = dfw->next_register;
		return;
	}

	id = -dfw->first_constant -1;
        dfw->first_constant = dfw->next_register;
        dfw->next_register += id;

	length = dfw->consts->len;
	for (id = 0; id < length; id++) {
		insn = (dfvm_insn_t	*)g_ptr_array_index(dfw->consts, id);
		if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
			insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1;
	}

	length = dfw->insns->len;
	for (id = 0; id < length; id++) {
		insn = (dfvm_insn_t	*)g_ptr_array_index(dfw->insns, id);
		if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 )
			insn->arg1->value.numeric = dfw->first_constant - insn->arg1->value.numeric -1;

		if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
			insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1;

		if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 )
			insn->arg3->value.numeric = dfw->first_constant - insn->arg3->value.numeric -1;

		if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 )
			insn->arg4->value.numeric = dfw->first_constant - insn->arg4->value.numeric -1;
	}


}
Exemplo n.º 7
0
static void
gen_test(dfwork_t *dfw, stnode_t *st_node)
{
	test_op_t	st_op;
	stnode_t	*st_arg1, *st_arg2;
	dfvm_value_t	*val1;
	dfvm_insn_t	*insn;

	header_field_info	*hfinfo;

	sttype_test_get(st_node, &st_op, &st_arg1, &st_arg2);

	switch (st_op) {
		case TEST_OP_UNINITIALIZED:
			g_assert_not_reached();
			break;

		case TEST_OP_EXISTS:
			val1 = dfvm_value_new(HFINFO);
			hfinfo = (header_field_info*)stnode_data(st_arg1);

			/* Rewind to find the first field of this name. */
			while (hfinfo->same_name_prev) {
				hfinfo = hfinfo->same_name_prev;
			}
			val1->value.hfinfo = hfinfo;
			insn = dfvm_insn_new(CHECK_EXISTS);
			insn->arg1 = val1;
			dfw_append_insn(dfw, insn);

			/* Record the FIELD_ID in hash of interesting fields. */
			while (hfinfo) {
				g_hash_table_insert(dfw->interesting_fields,
					GINT_TO_POINTER(hfinfo->id),
					GUINT_TO_POINTER(TRUE));
				hfinfo = hfinfo->same_name_next;
			}

			break;

		case TEST_OP_NOT:
			gencode(dfw, st_arg1);
			insn = dfvm_insn_new(NOT);
			dfw_append_insn(dfw, insn);
			break;

		case TEST_OP_AND:
			gencode(dfw, st_arg1);

			insn = dfvm_insn_new(IF_FALSE_GOTO);
			val1 = dfvm_value_new(INSN_NUMBER);
			insn->arg1 = val1;
			dfw_append_insn(dfw, insn);

			gencode(dfw, st_arg2);
			val1->value.numeric = dfw->next_insn_id;
			break;

		case TEST_OP_OR:
			gencode(dfw, st_arg1);

			insn = dfvm_insn_new(IF_TRUE_GOTO);
			val1 = dfvm_value_new(INSN_NUMBER);
			insn->arg1 = val1;
			dfw_append_insn(dfw, insn);

			gencode(dfw, st_arg2);
			val1->value.numeric = dfw->next_insn_id;
			break;

		case TEST_OP_EQ:
			gen_relation(dfw, ANY_EQ, st_arg1, st_arg2);
			break;

		case TEST_OP_NE:
			gen_relation(dfw, ANY_NE, st_arg1, st_arg2);
			break;

		case TEST_OP_GT:
			gen_relation(dfw, ANY_GT, st_arg1, st_arg2);
			break;

		case TEST_OP_GE:
			gen_relation(dfw, ANY_GE, st_arg1, st_arg2);
			break;

		case TEST_OP_LT:
			gen_relation(dfw, ANY_LT, st_arg1, st_arg2);
			break;

		case TEST_OP_LE:
			gen_relation(dfw, ANY_LE, st_arg1, st_arg2);
			break;

		case TEST_OP_BITWISE_AND:
			gen_relation(dfw, ANY_BITWISE_AND, st_arg1, st_arg2);
			break;

		case TEST_OP_CONTAINS:
			gen_relation(dfw, ANY_CONTAINS, st_arg1, st_arg2);
			break;

		case TEST_OP_MATCHES:
			gen_relation(dfw, ANY_MATCHES, st_arg1, st_arg2);
			break;
	}
}
Exemplo n.º 8
0
/* returns register number that the functions's result will be in. */
static int
dfw_append_function(dfwork_t *dfw, stnode_t *node, dfvm_value_t **p_jmp)
{
	GSList *params;
	int i, num_params, reg;
	dfvm_value_t **jmps;
	dfvm_insn_t	*insn;
	dfvm_value_t	*val1, *val2, *val;

	params = sttype_function_params(node);
	num_params = g_slist_length(params);

	/* Array to hold the instructions that need to jump to
	 * an instruction if they fail. */
	jmps = (dfvm_value_t **)g_malloc(num_params * sizeof(dfvm_value_t*));

	/* Create the new DFVM instruction */
	insn = dfvm_insn_new(CALL_FUNCTION);

	val1 = dfvm_value_new(FUNCTION_DEF);
	val1->value.funcdef = sttype_function_funcdef(node);
	insn->arg1 = val1;
	val2 = dfvm_value_new(REGISTER);
	val2->value.numeric = dfw->next_register++;
	insn->arg2 = val2;
	insn->arg3 = NULL;
	insn->arg4 = NULL;

	i = 0;
	while (params) {
		jmps[i] = NULL;
		reg = gen_entity(dfw, (stnode_t *)params->data, &jmps[i]);

		val = dfvm_value_new(REGISTER);
		val->value.numeric = reg;

		switch(i) {
			case 0:
				insn->arg3 = val;
				break;
			case 1:
				insn->arg4 = val;
				break;
			default:
				g_assert_not_reached();
		}

		params = params->next;
		i++;
	}

	dfw_append_insn(dfw, insn);

	/* If any of our parameters failed, send them to
	 * our own failure instruction. This *has* to be done
	 * after we caled dfw_append_insn above so that
	 * we know what the next DFVM insruction is, via
	 * dfw->next_insn_id */
	for (i = 0; i < num_params; i++) {
		if (jmps[i]) {
			jmps[i]->value.numeric = dfw->next_insn_id;
		}
	}

	/* We need another instruction to jump to another exit
	 * place, if the call() of our function failed for some reaosn */
	insn = dfvm_insn_new(IF_FALSE_GOTO);
	g_assert(p_jmp);
	*p_jmp = dfvm_value_new(INSN_NUMBER);
	insn->arg1 = *p_jmp;
	dfw_append_insn(dfw, insn);

	g_free(jmps);

	return val2->value.numeric;
}