*/
#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.60 1999-10-07 23:46:40 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.67 2000-11-19 13:37:20 itojun Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <memory.h>
+#include <errno.h>
+
#include "pcap-int.h"
#include "gencode.h"
-#include "gnuc.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
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.
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);
opt_j(&p->ef);
}
}
+
+ find_inedges(root);
for (i = 1; i <= maxlevel; ++i) {
for (p = levels[i]; p; p = p->link) {
or_pullup(p);
find_levels(root);
find_dom(root);
find_closure(root);
- find_inedges(root);
find_ud(root);
find_edom(root);
opt_blks(root, do_stmts);
/*
* Return the number of stmts in the flowgraph reachable by 'p'.
* The nodes should be unmarked before calling.
+ *
+ * Note that "stmts" means "instructions", and that this includes
+ *
+ * side-effect statements in 'p' (slength(p->stmts));
+ *
+ * statements in the true branch from 'p' (count_stmts(JT(p)));
+ *
+ * statements in the false branch from 'p' (count_stmts(JF(p)));
+ *
+ * the conditional jump itself (1);
+ *
+ * an extra long jump if the true branch requires it (p->longjt);
+ *
+ * an extra long jump if the false branch requires it (p->longjf).
*/
static int
count_stmts(p)
return 0;
Mark(p);
n = count_stmts(JT(p)) + count_stmts(JF(p));
- return slength(p->stmts) + n + 1;
+ return slength(p->stmts) + n + 1 + p->longjt + p->longjf;
}
/*
*/
maxval = 3 * max_stmts;
vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap));
- vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap));
+ vnode_base = (struct valnode *)malloc(maxval * sizeof(*vnode_base));
}
/*
int slen;
u_int off;
int extrajmps; /* number of extra jumps inserted */
+ struct slist **offset = NULL;
if (p == 0 || isMarked(p))
return (1);
p->offset = dst - fstart;
+ /* generate offset[] for convenience */
+ if (slen) {
+ 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;
}
+ if (offset)
+ free(offset);
+
#ifdef BDEBUG
bids[dst - fstart] = p->id + 1;
#endif
return fp;
}
+/*
+ * Make a copy of a BPF program and put it in the "fcode" member of
+ * a "pcap_t".
+ *
+ * If we fail to allocate memory for the copy, fill in the "errbuf"
+ * member of the "pcap_t" with an error message, and return -1;
+ * otherwise, return 0.
+ */
+int
+install_bpf_program(pcap_t *p, struct bpf_program *fp)
+{
+ size_t prog_size;
+
+ /*
+ * Free up any already installed program.
+ */
+ pcap_freecode(&p->fcode);
+
+ prog_size = sizeof(*fp->bf_insns) * fp->bf_len;
+ p->fcode.bf_len = fp->bf_len;
+ p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
+ if (p->fcode.bf_insns == NULL) {
+ snprintf(p->errbuf, sizeof(p->errbuf),
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
+ return (0);
+}
+
#ifdef BDEBUG
static void
opt_dump(root)