diff options
Diffstat (limited to 'lib/libpcap/optimize.c')
| -rw-r--r-- | lib/libpcap/optimize.c | 93 |
1 files changed, 87 insertions, 6 deletions
diff --git a/lib/libpcap/optimize.c b/lib/libpcap/optimize.c index e1274a357d3..7dade84f93d 100644 --- a/lib/libpcap/optimize.c +++ b/lib/libpcap/optimize.c @@ -1,4 +1,4 @@ -/* $NetBSD: optimize.c,v 1.7 1997/10/03 15:53:11 christos Exp $ */ +/* $NetBSD: optimize.c,v 1.8 1999/07/02 10:05:22 itojun Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 @@ -28,7 +28,7 @@ static const char rcsid[] = "@(#) Header: optimize.c,v 1.60 96/09/26 23:28:14 leres Exp (LBL)"; #else -__RCSID("$NetBSD: optimize.c,v 1.7 1997/10/03 15:53:11 christos Exp $"); +__RCSID("$NetBSD: optimize.c,v 1.8 1999/07/02 10:05:22 itojun Exp $"); #endif #endif @@ -1111,6 +1111,14 @@ opt_blk(b, do_stmts) int i; bpf_int32 aval; +#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. * If we have no predecessors, everything is undefined. @@ -1480,8 +1488,6 @@ opt_blks(root, do_stmts) 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); @@ -1499,8 +1505,6 @@ opt_blks(root, do_stmts) opt_j(&p->ef); } } - - find_inedges(root); for (i = 1; i <= maxlevel; ++i) { for (p = levels[i]; p; p = p->link) { or_pullup(p); @@ -1580,6 +1584,7 @@ opt_loop(root, do_stmts) find_levels(root); find_dom(root); find_closure(root); + find_inedges(root); find_ud(root); find_edom(root); opt_blks(root, do_stmts); @@ -1896,6 +1901,7 @@ convert_code_r(p) int slen; u_int off; int extrajmps; /* number of extra jumps inserted */ + struct slist **offset; if (p == 0 || isMarked(p)) return (1); @@ -1912,13 +1918,88 @@ convert_code_r(p) p->offset = dst - fstart; + /* generate offset[] for convenience */ + offset = (struct slist **)calloc(sizeof(struct slist *), slen); + if (!offset) { + bpf_error("not enough core"); + /*NOTREACHED*/ + } + src = p->stmts; + for (off = 0; off < slen && src; off++) { +#if 0 + printf("off=%d src=%x\n", off, src); +#endif + offset[off] = src; + src = src->next; + } + + off = 0; for (src = p->stmts; src; src = src->next) { if (src->s.code == NOP) continue; dst->code = (u_short)src->s.code; dst->k = src->s.k; + + /* fill block-local relative jump */ + if (BPF_CLASS(src->s.code) != BPF_JMP + || src->s.code == (BPF_JMP|BPF_JA)) { +#if 0 + if (src->s.jt || src->s.jf) { + bpf_error("illegal jmp destination"); + /*NOTREACHED*/ + } +#endif + goto filled; + } + if (off == slen - 2) /*???*/ + goto filled; + + { + int i; + int jt, jf; + char *ljerr = "%s for block-local relative jump: off=%d"; + +#if 0 + printf("code=%x off=%d %x %x\n", src->s.code, + off, src->s.jt, src->s.jf); +#endif + + if (!src->s.jt || !src->s.jf) { + bpf_error(ljerr, "no jmp destination", off); + /*NOTREACHED*/ + } + + jt = jf = 0; + for (i = 0; i < slen; i++) { + if (offset[i] == src->s.jt) { + if (jt) { + bpf_error(ljerr, "multiple matches", off); + /*NOTREACHED*/ + } + + dst->jt = i - off - 1; + jt++; + } + if (offset[i] == src->s.jf) { + if (jf) { + bpf_error(ljerr, "multiple matches", off); + /*NOTREACHED*/ + } + dst->jf = i - off - 1; + jf++; + } + } + if (!jt || !jf) { + bpf_error(ljerr, "no destination found", off); + /*NOTREACHED*/ + } + } +filled: ++dst; + ++off; } + free(offset); + #ifdef BDEBUG bids[dst - fstart] = p->id + 1; #endif |
