⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 optimize.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			last[X_ATOM] = 0;			last[A_ATOM] = 0;		}		else			last[atom] = 0;	}	atom = atomdef(s);	if (atom >= 0) {		if (last[atom]) {			done = 0;			last[atom]->code = NOP;		}		last[atom] = s;	}}static voidopt_deadstores(b)	register struct block *b;{	register struct slist *s;	register int atom;	struct stmt *last[N_ATOMS];	memset((char *)last, 0, sizeof last);	for (s = b->stmts; s != 0; s = s->next)		deadstmt(&s->s, last);	deadstmt(&b->s, last);	for (atom = 0; atom < N_ATOMS; ++atom)		if (last[atom] && !ATOMELEM(b->out_use, atom)) {			last[atom]->code = NOP;			done = 0;		}}static voidopt_blk(b, do_stmts)	struct block *b;	int do_stmts;{	struct slist *s;	struct edge *p;	int i;	bpf_int32 aval, xval;#if 0	for (s = b->stmts; s && s->next; s = s->next)		if (BPF_CLASS(s->s.code) == BPF_JMP) {			do_stmts = 0;			break;		}#endif	/*	 * Initialize the atom values.	 */	p = b->in_edges;	if (p == 0) {		/*		 * We have no predecessors, so everything is undefined		 * upon entry to this block.		 */		memset((char *)b->val, 0, sizeof(b->val));	} else {		/*		 * Inherit values from our predecessors.		 *		 * First, get the values from the predecessor along the		 * first edge leading to this node.		 */		memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));		/*		 * Now look at all the other nodes leading to this node.		 * If, for the predecessor along that edge, a register		 * has a different value from the one we have (i.e.,		 * control paths are merging, and the merging paths		 * assign different values to that register), give the		 * register the undefined value of 0.		 */		while ((p = p->next) != NULL) {			for (i = 0; i < N_ATOMS; ++i)				if (b->val[i] != p->pred->val[i])					b->val[i] = 0;		}	}	aval = b->val[A_ATOM];	xval = b->val[X_ATOM];	for (s = b->stmts; s; s = s->next)		opt_stmt(&s->s, b->val, do_stmts);	/*	 * This is a special case: if we don't use anything from this	 * block, and we load the accumulator or index register with a	 * value that is already there, or if this block is a return,	 * eliminate all the statements.	 *	 * XXX - what if it does a store?	 *	 * XXX - why does it matter whether we use anything from this	 * block?  If the accumulator or index register doesn't change	 * its value, isn't that OK even if we use that value?	 *	 * XXX - if we load the accumulator with a different value,	 * and the block ends with a conditional branch, we obviously	 * can't eliminate it, as the branch depends on that value.	 * For the index register, the conditional branch only depends	 * on the index register value if the test is against the index	 * register value rather than a constant; if nothing uses the	 * value we put into the index register, and we're not testing	 * against the index register's value, and there aren't any	 * other problems that would keep us from eliminating this	 * block, can we eliminate it?	 */	if (do_stmts &&	    ((b->out_use == 0 && aval != 0 && b->val[A_ATOM] == aval &&	      xval != 0 && b->val[X_ATOM] == xval) ||	     BPF_CLASS(b->s.code) == BPF_RET)) {		if (b->stmts != 0) {			b->stmts = 0;			done = 0;		}	} else {		opt_peep(b);		opt_deadstores(b);	}	/*	 * Set up values for branch optimizer.	 */	if (BPF_SRC(b->s.code) == BPF_K)		b->oval = K(b->s.k);	else		b->oval = b->val[X_ATOM];	b->et.code = b->s.code;	b->ef.code = -b->s.code;}/* * Return true if any register that is used on exit from 'succ', has * an exit value that is different from the corresponding exit value * from 'b'. */static intuse_conflict(b, succ)	struct block *b, *succ;{	int atom;	atomset use = succ->out_use;	if (use == 0)		return 0;	for (atom = 0; atom < N_ATOMS; ++atom)		if (ATOMELEM(use, atom))			if (b->val[atom] != succ->val[atom])				return 1;	return 0;}static struct block *fold_edge(child, ep)	struct block *child;	struct edge *ep;{	int sense;	int aval0, aval1, oval0, oval1;	int code = ep->code;	if (code < 0) {		code = -code;		sense = 0;	} else		sense = 1;	if (child->s.code != code)		return 0;	aval0 = child->val[A_ATOM];	oval0 = child->oval;	aval1 = ep->pred->val[A_ATOM];	oval1 = ep->pred->oval;	if (aval0 != aval1)		return 0;	if (oval0 == oval1)		/*		 * The operands of the branch instructions are		 * identical, so the result is true if a true		 * branch was taken to get here, otherwise false.		 */		return sense ? JT(child) : JF(child);	if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))		/*		 * At this point, we only know the comparison if we		 * came down the true branch, and it was an equality		 * comparison with a constant.		 *		 * I.e., if we came down the true branch, and the branch		 * was an equality comparison with a constant, we know the		 * accumulator contains that constant.  If we came down		 * the false branch, or the comparison wasn't with a		 * constant, we don't know what was in the accumulator.		 *		 * We rely on the fact that distinct constants have distinct		 * value numbers.		 */		return JF(child);	return 0;}static voidopt_j(ep)	struct edge *ep;{	register int i, k;	register struct block *target;	if (JT(ep->succ) == 0)		return;	if (JT(ep->succ) == JF(ep->succ)) {		/*		 * Common branch targets can be eliminated, provided		 * there is no data dependency.		 */		if (!use_conflict(ep->pred, ep->succ->et.succ)) {			done = 0;			ep->succ = JT(ep->succ);		}	}	/*	 * For each edge dominator that matches the successor of this	 * edge, promote the edge successor to the its grandchild.	 *	 * XXX We violate the set abstraction here in favor a reasonably	 * efficient loop.	 */ top:	for (i = 0; i < edgewords; ++i) {		register bpf_u_int32 x = ep->edom[i];		while (x != 0) {			k = ffs(x) - 1;			x &=~ (1 << k);			k += i * BITS_PER_WORD;			target = fold_edge(ep->succ, edges[k]);			/*			 * Check that there is no data dependency between			 * nodes that will be violated if we move the edge.			 */			if (target != 0 && !use_conflict(ep->pred, target)) {				done = 0;				ep->succ = target;				if (JT(target) != 0)					/*					 * Start over unless we hit a leaf.					 */					goto top;				return;			}		}	}}static voidor_pullup(b)	struct block *b;{	int val, at_top;	struct block *pull;	struct block **diffp, **samep;	struct edge *ep;	ep = b->in_edges;	if (ep == 0)		return;	/*	 * Make sure each predecessor loads the same value.	 * XXX why?	 */	val = ep->pred->val[A_ATOM];	for (ep = ep->next; ep != 0; ep = ep->next)		if (val != ep->pred->val[A_ATOM])			return;	if (JT(b->in_edges->pred) == b)		diffp = &JT(b->in_edges->pred);	else		diffp = &JF(b->in_edges->pred);	at_top = 1;	while (1) {		if (*diffp == 0)			return;		if (JT(*diffp) != JT(b))			return;		if (!SET_MEMBER((*diffp)->dom, b->id))			return;		if ((*diffp)->val[A_ATOM] != val)			break;		diffp = &JF(*diffp);		at_top = 0;	}	samep = &JF(*diffp);	while (1) {		if (*samep == 0)			return;		if (JT(*samep) != JT(b))			return;		if (!SET_MEMBER((*samep)->dom, b->id))			return;		if ((*samep)->val[A_ATOM] == val)			break;		/* XXX Need to check that there are no data dependencies		   between dp0 and dp1.  Currently, the code generator		   will not produce such dependencies. */		samep = &JF(*samep);	}#ifdef notdef	/* XXX This doesn't cover everything. */	for (i = 0; i < N_ATOMS; ++i)		if ((*samep)->val[i] != pred->val[i])			return;#endif	/* Pull up the node. */	pull = *samep;	*samep = JF(pull);	JF(pull) = *diffp;	/*	 * At the top of the chain, each predecessor needs to point at the	 * pulled up node.  Inside the chain, there is only one predecessor	 * to worry about.	 */	if (at_top) {		for (ep = b->in_edges; ep != 0; ep = ep->next) {			if (JT(ep->pred) == b)				JT(ep->pred) = pull;			else				JF(ep->pred) = pull;		}	}	else		*diffp = pull;	done = 0;}static voidand_pullup(b)	struct block *b;{	int val, at_top;	struct block *pull;	struct block **diffp, **samep;	struct edge *ep;	ep = b->in_edges;	if (ep == 0)		return;	/*	 * Make sure each predecessor loads the same value.	 */	val = ep->pred->val[A_ATOM];	for (ep = ep->next; ep != 0; ep = ep->next)		if (val != ep->pred->val[A_ATOM])			return;	if (JT(b->in_edges->pred) == b)		diffp = &JT(b->in_edges->pred);	else		diffp = &JF(b->in_edges->pred);	at_top = 1;	while (1) {		if (*diffp == 0)			return;		if (JF(*diffp) != JF(b))			return;		if (!SET_MEMBER((*diffp)->dom, b->id))			return;		if ((*diffp)->val[A_ATOM] != val)			break;		diffp = &JT(*diffp);		at_top = 0;	}	samep = &JT(*diffp);	while (1) {		if (*samep == 0)			return;		if (JF(*samep) != JF(b))			return;		if (!SET_MEMBER((*samep)->dom, b->id))			return;		if ((*samep)->val[A_ATOM] == val)			break;		/* XXX Need to check that there are no data dependencies		   between diffp and samep.  Currently, the code generator		   will not produce such dependencies. */		samep = &JT(*samep);	}#ifdef notdef	/* XXX This doesn't cover everything. */	for (i = 0; i < N_ATOMS; ++i)		if ((*samep)->val[i] != pred->val[i])			return;#endif	/* Pull up the node. */	pull = *samep;	*samep = JT(pull);	JT(pull) = *diffp;	/*	 * At the top of the chain, each predecessor needs to point at the	 * pulled up node.  Inside the chain, there is only one predecessor	 * to worry about.	 */	if (at_top) {		for (ep = b->in_edges; ep != 0; ep = ep->next) {			if (JT(ep->pred) == b)				JT(ep->pred) = pull;			else				JF(ep->pred) = pull;		}	}	else		*diffp = pull;	done = 0;}static voidopt_blks(root, do_stmts)	struct block *root;	int do_stmts;{	int i, maxlevel;	struct block *p;	init_val();	maxlevel = root->level;	find_inedges(root);	for (i = maxlevel; i >= 0; --i)		for (p = levels[i]; p; p = p->link)			opt_blk(p, do_stmts);	if (do_stmts)		/*		 * No point trying to move branches; it can't possibly		 * make a difference at this point.		 */		return;	for (i = 1; i <= maxlevel; ++i) {		for (p = levels[i]; p; p = p->link) {			opt_j(&p->et);			opt_j(&p->ef);		}	}	find_inedges(root);	for (i = 1; i <= maxlevel; ++i) {		for (p = levels[i]; p; p = p->link) {			or_pullup(p);			and_pullup(p);		}	}}static inline voidlink_inedge(parent, child)	struct edge *parent;	struct block *child;{	parent->next = child->in_edges;	child->in_edges = parent;}static voidfind_inedges(root)	struct block *root;{	int i;	struct block *b;	for (i = 0; i < n_blocks; ++i)		blocks[i]->in_edges = 0;	/*	 * Traverse the graph, adding each edge to the predecessor	 * list of its successors.  Skip the leaves (i.e. level 0).	 */	for (i = root->level; i > 0; --i) {		for (b = levels[i]; b != 0; b = b->link) {			link_inedge(&b->et, JT(b));			link_inedge(&b->ef, JF(b));		}	}}static voidopt_root(b)	struct block **b;{	struct slist *tmp, *s;	s = (*b)->stmts;	(*b)->stmts = 0;	while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))		*b = JT(*b);	tmp = (*b)->stmts;	if (tmp != 0)		sappend(s, tmp);	(*b)->stmts = s;	/*	 * If the root node is a return, then there is no	 * point executing any statements (since the bpf machine	 * has no side effects).	 */	if (BPF_CLASS((*b)->s.code) == BPF_RET)		(*b)->stmts = 0;}static voidopt_loop(root, do_stmts)	struct block *root;	int do_stmts;{#ifdef BDEBUG	if (dflag > 1) {		printf("opt_loop(root, %d) begin\n", do_stmts);		opt_dump(root);	}#endif	do {		done = 1;		find_levels(root);		find_dom(root);		find_closure(root);		find_ud(root);		find_edom(root);		opt_blks(root, do_stmts);#ifdef BDEBUG		if (dflag > 1) {			printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done);			opt_dump(root);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -