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

📄 optimize.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * *  Optimization module for tcpdump intermediate representation. */#ifndef lintstatic const char rcsid[] _U_ =    "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.85 2005/04/04 08:42:18 guy Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <memory.h>#include <string.h>#include <errno.h>#include "pcap-int.h"#include "gencode.h"#ifdef HAVE_OS_PROTO_H#include "os-proto.h"#endif#ifdef BDEBUGextern int dflag;#endif#if defined(MSDOS) && !defined(__DJGPP__)extern int _w32_ffs (int mask);#define ffs _w32_ffs#endif/* * Represents a deleted instruction. */#define NOP -1/* * Register numbers for use-def values. * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory * location.  A_ATOM is the accumulator and X_ATOM is the index * register. */#define A_ATOM BPF_MEMWORDS#define X_ATOM (BPF_MEMWORDS+1)/* * This define is used to represent *both* the accumulator and * x register in use-def computations. * Currently, the use-def code assumes only one definition per instruction. */#define AX_ATOM N_ATOMS/* * A flag to indicate that further optimization is needed. * Iterative passes are continued until a given pass yields no * branch movement. */static int done;/* * A block is marked if only if its mark equals the current mark. * Rather than traverse the code array, marking each item, 'cur_mark' is * incremented.  This automatically makes each element unmarked. */static int cur_mark;#define isMarked(p) ((p)->mark == cur_mark)#define unMarkAll() cur_mark += 1#define Mark(p) ((p)->mark = cur_mark)static void opt_init(struct block *);static void opt_cleanup(void);static void make_marks(struct block *);static void mark_code(struct block *);static void intern_blocks(struct block *);static int eq_slist(struct slist *, struct slist *);static void find_levels_r(struct block *);static void find_levels(struct block *);static void find_dom(struct block *);static void propedom(struct edge *);static void find_edom(struct block *);static void find_closure(struct block *);static int atomuse(struct stmt *);static int atomdef(struct stmt *);static void compute_local_ud(struct block *);static void find_ud(struct block *);static void init_val(void);static int F(int, int, int);static inline void vstore(struct stmt *, int *, int, int);static void opt_blk(struct block *, int);static int use_conflict(struct block *, struct block *);static void opt_j(struct edge *);static void or_pullup(struct block *);static void and_pullup(struct block *);static void opt_blks(struct block *, int);static inline void link_inedge(struct edge *, struct block *);static void find_inedges(struct block *);static void opt_root(struct block **);static void opt_loop(struct block *, int);static void fold_op(struct stmt *, int, int);static inline struct slist *this_op(struct slist *);static void opt_not(struct block *);static void opt_peep(struct block *);static void opt_stmt(struct stmt *, int[], int);static void deadstmt(struct stmt *, struct stmt *[]);static void opt_deadstores(struct block *);static struct block *fold_edge(struct block *, struct edge *);static inline int eq_blk(struct block *, struct block *);static int slength(struct slist *);static int count_blocks(struct block *);static void number_blks_r(struct block *);static int count_stmts(struct block *);static int convert_code_r(struct block *);#ifdef BDEBUGstatic void opt_dump(struct block *);#endifstatic int n_blocks;struct block **blocks;static int n_edges;struct edge **edges;/* * A bit vector set representation of the dominators. * We round up the set size to the next power of two. */static int nodewords;static int edgewords;struct block **levels;bpf_u_int32 *space;#define BITS_PER_WORD (8*sizeof(bpf_u_int32))/* * True if a is in uset {p} */#define SET_MEMBER(p, a) \((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))/* * Add 'a' to uset p. */#define SET_INSERT(p, a) \(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))/* * Delete 'a' from uset p. */#define SET_DELETE(p, a) \(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))/* * a := a intersect b */#define SET_INTERSECT(a, b, n)\{\	register bpf_u_int32 *_x = a, *_y = b;\	register int _n = n;\	while (--_n >= 0) *_x++ &= *_y++;\}/* * a := a - b */#define SET_SUBTRACT(a, b, n)\{\	register bpf_u_int32 *_x = a, *_y = b;\	register int _n = n;\	while (--_n >= 0) *_x++ &=~ *_y++;\}/* * a := a union b */#define SET_UNION(a, b, n)\{\	register bpf_u_int32 *_x = a, *_y = b;\	register int _n = n;\	while (--_n >= 0) *_x++ |= *_y++;\}static uset all_dom_sets;static uset all_closure_sets;static uset all_edge_sets;#ifndef MAX#define MAX(a,b) ((a)>(b)?(a):(b))#endifstatic voidfind_levels_r(b)	struct block *b;{	int level;	if (isMarked(b))		return;	Mark(b);	b->link = 0;	if (JT(b)) {		find_levels_r(JT(b));		find_levels_r(JF(b));		level = MAX(JT(b)->level, JF(b)->level) + 1;	} else		level = 0;	b->level = level;	b->link = levels[level];	levels[level] = b;}/* * Level graph.  The levels go from 0 at the leaves to * N_LEVELS at the root.  The levels[] array points to the * first node of the level list, whose elements are linked * with the 'link' field of the struct block. */static voidfind_levels(root)	struct block *root;{	memset((char *)levels, 0, n_blocks * sizeof(*levels));	unMarkAll();	find_levels_r(root);}/* * Find dominator relationships. * Assumes graph has been leveled. */static voidfind_dom(root)	struct block *root;{	int i;	struct block *b;	bpf_u_int32 *x;	/*	 * Initialize sets to contain all nodes.	 */	x = all_dom_sets;	i = n_blocks * nodewords;	while (--i >= 0)		*x++ = ~0;	/* Root starts off empty. */	for (i = nodewords; --i >= 0;)		root->dom[i] = 0;	/* root->level is the highest level no found. */	for (i = root->level; i >= 0; --i) {		for (b = levels[i]; b; b = b->link) {			SET_INSERT(b->dom, b->id);			if (JT(b) == 0)				continue;			SET_INTERSECT(JT(b)->dom, b->dom, nodewords);			SET_INTERSECT(JF(b)->dom, b->dom, nodewords);		}	}}static voidpropedom(ep)	struct edge *ep;{	SET_INSERT(ep->edom, ep->id);	if (ep->succ) {		SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords);		SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords);	}}/* * Compute edge dominators. * Assumes graph has been leveled and predecessors established. */static voidfind_edom(root)	struct block *root;{	int i;	uset x;	struct block *b;	x = all_edge_sets;	for (i = n_edges * edgewords; --i >= 0; )		x[i] = ~0;	/* root->level is the highest level no found. */	memset(root->et.edom, 0, edgewords * sizeof(*(uset)0));	memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0));	for (i = root->level; i >= 0; --i) {		for (b = levels[i]; b != 0; b = b->link) {			propedom(&b->et);			propedom(&b->ef);		}	}}/* * Find the backwards transitive closure of the flow graph.  These sets * are backwards in the sense that we find the set of nodes that reach * a given node, not the set of nodes that can be reached by a node. * * Assumes graph has been leveled. */static voidfind_closure(root)	struct block *root;{	int i;	struct block *b;	/*	 * Initialize sets to contain no nodes.	 */	memset((char *)all_closure_sets, 0,	      n_blocks * nodewords * sizeof(*all_closure_sets));	/* root->level is the highest level no found. */	for (i = root->level; i >= 0; --i) {		for (b = levels[i]; b; b = b->link) {			SET_INSERT(b->closure, b->id);			if (JT(b) == 0)				continue;			SET_UNION(JT(b)->closure, b->closure, nodewords);			SET_UNION(JF(b)->closure, b->closure, nodewords);		}	}}/* * Return the register number that is used by s.  If A and X are both * used, return AX_ATOM.  If no register is used, return -1. * * The implementation should probably change to an array access. */static intatomuse(s)	struct stmt *s;{	register int c = s->code;	if (c == NOP)		return -1;	switch (BPF_CLASS(c)) {	case BPF_RET:		return (BPF_RVAL(c) == BPF_A) ? A_ATOM :			(BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;	case BPF_LD:	case BPF_LDX:		return (BPF_MODE(c) == BPF_IND) ? X_ATOM :			(BPF_MODE(c) == BPF_MEM) ? s->k : -1;	case BPF_ST:		return A_ATOM;	case BPF_STX:		return X_ATOM;	case BPF_JMP:	case BPF_ALU:		if (BPF_SRC(c) == BPF_X)			return AX_ATOM;		return A_ATOM;	case BPF_MISC:		return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;	}	abort();	/* NOTREACHED */}/* * Return the register number that is defined by 's'.  We assume that * a single stmt cannot define more than one register.  If no register * is defined, return -1. * * The implementation should probably change to an array access. */static intatomdef(s)	struct stmt *s;{	if (s->code == NOP)		return -1;	switch (BPF_CLASS(s->code)) {	case BPF_LD:	case BPF_ALU:		return A_ATOM;	case BPF_LDX:		return X_ATOM;	case BPF_ST:	case BPF_STX:		return s->k;	case BPF_MISC:		return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;	}	return -1;}/* * Compute the sets of registers used, defined, and killed by 'b'. * * "Used" means that a statement in 'b' uses the register before any * statement in 'b' defines it, i.e. it uses the value left in * that register by a predecessor block of this block. * "Defined" means that a statement in 'b' defines it. * "Killed" means that a statement in 'b' defines it before any * statement in 'b' uses it, i.e. it kills the value left in that * register by a predecessor block of this block. */static voidcompute_local_ud(b)	struct block *b;{	struct slist *s;	atomset def = 0, use = 0, kill = 0;	int atom;	for (s = b->stmts; s; s = s->next) {		if (s->s.code == NOP)			continue;		atom = atomuse(&s->s);		if (atom >= 0) {			if (atom == AX_ATOM) {				if (!ATOMELEM(def, X_ATOM))					use |= ATOMMASK(X_ATOM);				if (!ATOMELEM(def, A_ATOM))					use |= ATOMMASK(A_ATOM);			}			else if (atom < N_ATOMS) {				if (!ATOMELEM(def, atom))					use |= ATOMMASK(atom);			}			else				abort();		}		atom = atomdef(&s->s);		if (atom >= 0) {			if (!ATOMELEM(use, atom))				kill |= ATOMMASK(atom);			def |= ATOMMASK(atom);		}	}	if (BPF_CLASS(b->s.code) == BPF_JMP) {		/*		 * XXX - what about RET?		 */		atom = atomuse(&b->s);		if (atom >= 0) {			if (atom == AX_ATOM) {				if (!ATOMELEM(def, X_ATOM))					use |= ATOMMASK(X_ATOM);				if (!ATOMELEM(def, A_ATOM))					use |= ATOMMASK(A_ATOM);			}			else if (atom < N_ATOMS) {				if (!ATOMELEM(def, atom))					use |= ATOMMASK(atom);			}			else				abort();		}	}	b->def = def;	b->kill = kill;	b->in_use = use;}/* * Assume graph is already leveled. */static voidfind_ud(root)	struct block *root;{	int i, maxlevel;	struct block *p;	/*	 * root->level is the highest level no found;	 * count down from there.	 */	maxlevel = root->level;	for (i = maxlevel; i >= 0; --i)		for (p = levels[i]; p; p = p->link) {			compute_local_ud(p);			p->out_use = 0;		}	for (i = 1; i <= maxlevel; ++i) {		for (p = levels[i]; p; p = p->link) {			p->out_use |= JT(p)->in_use | JF(p)->in_use;			p->in_use |= p->out_use &~ p->kill;		}	}}/* * These data structures are used in a Cocke and Shwarz style * value numbering scheme.  Since the flowgraph is acyclic, * exit values can be propagated from a node's predecessors * provided it is uniquely defined. */struct valnode {	int code;	int v0, v1;	int val;	struct valnode *next;};#define MODULUS 213static struct valnode *hashtbl[MODULUS];static int curval;static int maxval;/* Integer constants mapped with the load immediate opcode. */#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L)struct vmapinfo {	int is_const;	bpf_int32 const_val;};struct vmapinfo *vmap;struct valnode *vnode_base;struct valnode *next_vnode;static voidinit_val(){	curval = 0;	next_vnode = vnode_base;	memset((char *)vmap, 0, maxval * sizeof(*vmap));	memset((char *)hashtbl, 0, sizeof hashtbl);}

⌨️ 快捷键说明

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