[insert project logo here (125x200px max)]

Navigator

Mailinglists

Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums.

Copyright and Licensing Information

Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL).

All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License.

All sourcecode is made publicly available.

Acknowledgement

Splash and the Splash website are hosted by SourceForge.net

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap-1.1-wjdb/lib/snap_io.c

Go to the documentation of this file.
00001 /* $Id: snap_io.c,v 1.3 2003/04/16 10:58:59 wdebruij Exp $ */
00002 
00003 #include <errno.h>
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <unistd.h>
00007 #include <netinet/in.h>
00008 #include <linux/ip.h>
00009 #include "snap.h"
00010 #include "config.h"
00011 #include "myassert.h"
00012 #include "consts.h"
00013 #include "bytecode.h"
00014 #include "io.h"
00015 #include "memalloc.h"
00016 #include "packet.h"
00017 #include "timers.h"
00018 #include "d_printf.h"
00019 #include "wassert.h"
00020 
00021 static void *scan_value(value_t *v, void *fromh, void *fromhmax,
00022             void *fromhalloc, void *fromhallocmax,
00023             void *tohmin, void *tohalloc, void *tohmax);
00024 
00025 static void *copy_heap_obj(heap_obj *hsrc, int sizeb,
00026                void *tohmin, void *tohalloc, void *tohmax);
00027 
00028 static void reset_heap(packet_t *p, void *to_heap, void *to_heap_max);
00029 
00030 /* used to verify packet integrity */
00031 #define VERIFY(e)                           \
00032   if (e);                               \
00033   else {                                \
00034     fprintf(stderr,"%s:%d: packet check failed\n",__FILE__,__LINE__);   \
00035     return NULL;                            \
00036   }
00037 
00038 /* checks if the given heap_obj ptr is within the heap bounds.
00039    side-effects sizeb to contain the object's length (word-aligned) */
00040 #define IF_IN_FROM_HEAP(ho,sizeb,hmin,hmax,hmin2,hmax2)          \
00041 if ((((void *)(ho) >= (void *)(hmin)) &&                 \
00042      ((void *)(ho) < (void *)(hmax)) &&                  \
00043      (((void *)(ho) +                            \
00044        ((sizeb) = (ho)->len + sizeof(heap_obj))) <= (void *)(hmax))) ||  \
00045     (((void *)(ho) >= (void *)(hmin2)) &&                \
00046      ((void *)(ho) < (void *)(hmax2)) &&                 \
00047      (((void *)(ho) +                            \
00048        ((sizeb) = (ho)->len + sizeof(heap_obj))) <= (void *)(hmax2)))) { \
00049   if (((sizeb) & 0x3) != 0) {                        \
00050     (sizeb) = ((sizeb) & ~0x3) + 4;                  \
00051   }
00052 
00053 #define ELSE_NOT_IN_FROM_HEAP } else
00054 
00055 #define IN_TOSPACE_HEAP(hdst,sizeb,toh,tohmax)               \
00056   (((void *)(hdst) >= (toh)) && (((void *)(hdst) + (sizeb)) <= (tohmax)))
00057 
00058 /* cache the packet_t struct */
00059 static packet_t phandle;
00060 
00061 /* given a buffer containing a packet, find pointers to the header,
00062    code, stack, and heap portions */
00063 packet_t *unmarshal_packet(char *buffer, int packet_lenb, int buf_lenb) {
00064 
00065   packet_t *p;          /* packet struct to return */
00066   void *buf_end = buffer + buf_lenb; 
00067   void *packet_end = buffer + packet_lenb; 
00068   unsigned short int code_lenb, entry_point, stack_lenb, heap_lenb;
00069 
00070   assert(sizeof(unsigned long int) == sizeof(unsigned int));
00071   assert(packet_lenb <= buf_lenb);
00072   d_printf(100,"%s:%d: unmarshal_packet, buf=0x%x, plen=%d, blen=%d\n",
00073        __FILE__,__LINE__,(unsigned int)buffer,packet_lenb,buf_lenb);
00074   print_anti_timer(7,"unmarshal_packet");
00075   p = &phandle;
00076 
00077   p->iph = (struct iphdr *)buffer;
00078   
00079   /* set up header */
00080   {
00081     struct iphdr *iph = (struct iphdr *)buffer;
00082     p->hdr = (header_t *)((void *)iph + (iph->ihl << 2));
00083   }
00084 
00085   code_lenb = ntohs(p->hdr->code_sizeb);
00086   stack_lenb = ntohs(p->hdr->stack_sizeb);
00087   heap_lenb = ntohs(p->hdr->heap_sizeb);
00088   entry_point = ntohs(p->hdr->entry_point);
00089 
00090   /* set up code */
00091   print_anti_timer(9,"unmarshal_code");
00092   p->code_min = (instr_t *)((void *)p->hdr + sizeof(header_t));
00093   p->code_max = (instr_t *)((void *)p->code_min + code_lenb);
00094   p->pc = p->code_min + entry_point;
00095   p->handler = p->code_max; /* default exception handler quits */
00096   VERIFY((entry_point * sizeof(instr_t)) <= code_lenb);
00097   print_timer(9,"unmarshal_code");
00098 
00099   /* set up heap */
00100   print_anti_timer(11,"unmarshal_heap");
00101   p->heap_min = (void *)p->code_max;
00102   p->heap_max = p->heap_min + heap_lenb;
00103   print_timer(11,"unmarshal_heap");
00104 
00105   /* set up stack */
00106   print_anti_timer(10,"unmarshal_stack");
00107   p->stack_min = (value_t *)p->heap_max;
00108   p->stack_max = (value_t *)buf_end;
00109   p->sp = (value_t *)((void *)p->stack_min + stack_lenb);
00110   VERIFY(((void *)(p->sp) <= packet_end)); 
00111   print_timer(10,"unmarshal_stack");
00112 
00113 
00114   /* top of buffer */
00115   p->h_alloc_heap_max = (void *)p->stack_max;
00116   p->is_contiguous = 1;
00117 
00118   d_printf(150,"%s:%d: @hdr = %#x\n",
00119        __FILE__,__LINE__,(uint32)p->hdr);
00120   d_printf(150,"%s:%d: @code_min = %#x, delta = %d\n",
00121        __FILE__,__LINE__,
00122        (uint32)p->code_min,(void *)p->code_min - (void *)p->hdr);
00123   d_printf(150,"%s:%d: @pc = %#x, delta = %d\n",
00124        __FILE__,__LINE__,
00125        (uint32)p->pc, (void *)p->pc - (void *)p->code_min);
00126   d_printf(150,"%s:%d: @code_max = %#x, delta = %d\n",
00127        __FILE__,__LINE__,
00128        (uint32)p->code_max, (void *)p->code_max - (void *)p->pc);
00129   d_printf(150,"%s:%d: @heap_min = %#x, delta = %d\n",
00130        __FILE__,__LINE__,
00131        (uint32)p->heap_min, (void *)p->heap_min - (void *)p->code_max);
00132   d_printf(150,"%s:%d: @heap_max = %#x, delta = %d\n",
00133        __FILE__,__LINE__,
00134        (uint32)p->heap_max, (void *)p->heap_max - (void *)p->heap_min);
00135   d_printf(150,"%s:%d: @stack_min = %#x, delta = %d\n",
00136        __FILE__,__LINE__,
00137        (uint32)p->stack_min, (void *)p->stack_min - (void *)p->heap_max);
00138   d_printf(150,"%s:%d: @sp = %#x, delta = %d\n",
00139        __FILE__,__LINE__,
00140        (uint32)p->sp, (void *)p->sp - (void *)p->stack_min);
00141   d_printf(150,"%s:%d: @stack_max = %#x, delta = %d\n",
00142        __FILE__,__LINE__,
00143        (uint32)p->stack_max, (void *)p->stack_max - (void *)p->sp);
00144   d_printf(150,"%s:%d: @h_alloc_heap_max = %#x, delta = %d\n",
00145        __FILE__,__LINE__,
00146        (uint32)p->h_alloc_heap_max, (void *)p->h_alloc_heap_max -
00147        (void *)p->stack_max);
00148 
00149   print_timer(7,"unmarshal_packet");
00150   return(p);
00151 }
00152 
00153 /* cache a 10k output buffer */
00154 static char *io_outbuf = NULL;
00155 static int io_outbuf_sizeb = 10 * 1024;
00156 
00157 /* given a packet and the amount of stack to take, marshal up a packet
00158    into a continuous block of bytes.  We assume that the packet_t
00159    structure is well-formed, but don't assume anything about the
00160    contents of the stack and the heap (there may be bogus values),
00161    so we require some extra checks. */
00162 int marshal_packet(packet_t *p, int stack_amt, buffer_t *bufstr) {
00163 
00164   int sizeb;            /* size in bytes of new buffer */
00165   instr_t *codesrc;     /* code pointer in old packet */
00166   instr_t *codedst;     /* code pointer in new packet */
00167   value_t *stacksrc;        /* stack pointer in old packet */
00168   value_t *stackdst;        /* stack pointer in new packet */
00169   void *newhmin;        /* bottom of new heap */
00170   void *newhalloc;      /* new heap allocation pointer */
00171   void *newhscan;       /* new heap scan pointer */
00172   void *newhmax;        /* high limit for new heap */
00173   header_t *newhdr;     /* header for the new packet */
00174 
00175   d_printf(150,"%s:%d: @hdr = %#x\n",
00176        __FILE__,__LINE__,(unsigned int)p->hdr);
00177   d_printf(150,"%s:%d: @code_min = %#x, delta = %d\n",
00178        __FILE__,__LINE__,
00179        (unsigned int)p->code_min,(void *)p->code_min - (void *)p->hdr);
00180   d_printf(150,"%s:%d: @pc = %#x, delta = %d\n",
00181        __FILE__,__LINE__,
00182        (unsigned int)p->pc, (void *)p->pc - (void *)p->code_min);
00183   d_printf(150,"%s:%d: @code_max = %#x, delta = %d\n",
00184        __FILE__,__LINE__,
00185        (unsigned int)p->code_max, (void *)p->code_max - (void *)p->pc);
00186   d_printf(150,"%s:%d: @heap_min = %#x, delta = %d\n",
00187        __FILE__,__LINE__,
00188        (unsigned int)p->heap_min, (void *)p->heap_min - (void *)p->code_max);
00189   d_printf(150,"%s:%d: @heap_max = %#x, delta = %d\n",
00190        __FILE__,__LINE__,
00191        (unsigned int)p->heap_max, (void *)p->heap_max - (void *)p->heap_min);
00192   d_printf(150,"%s:%d: @stack_min = %#x, delta = %d\n",
00193        __FILE__,__LINE__,
00194        (unsigned int)p->stack_min, (void *)p->stack_min - (void *)p->heap_max);
00195   d_printf(150,"%s:%d: @sp = %#x, delta = %d\n",
00196        __FILE__,__LINE__,
00197        (unsigned int)p->sp, (void *)p->sp - (void *)p->stack_min);
00198   d_printf(150,"%s:%d: @stack_max = %#x, delta = %d\n",
00199        __FILE__,__LINE__,
00200        (unsigned int)p->stack_max, (void *)p->stack_max - (void *)p->sp);
00201   d_printf(150,"%s:%d: @h_alloc_heap_max = %#x, delta = %d\n",
00202        __FILE__,__LINE__,
00203        (unsigned int)p->h_alloc_heap_max, (void *)p->h_alloc_heap_max -
00204        (void *)p->stack_max);
00205 
00206   print_anti_timer(8,"marshal_packet");
00207   /* check for valid args */
00208   assert(stack_amt >= 0);
00209   assert(p != NULL);
00210   assert(bufstr != NULL);
00211 
00212   /* see if we can reuse this buffer.  We can if the entire stack is
00213      to be transmitted and if we haven't done any further heap
00214      allocation. */
00215   /* XXX this optimization won't work in the kernel case yet unless this
00216      send is resulting from a forw or a forwto (as then we won't
00217      compute any further). Might be possible to clone the buffer,
00218      though. */
00219   if (((p->sp - p->stack_min) == stack_amt) &&
00220       (p->h_alloc_heap_max == p->stack_max) &&
00221       (p->is_contiguous)) {
00222     d_printf(100,"%s:%d: reusing old buffer during marshalling\n",
00223          __FILE__,__LINE__);
00224     p->hdr->stack_sizeb = htons(stack_amt * sizeof(value_t));
00225     bufstr->lenb = (void *)p->sp - (void *)p->iph;
00226     bufstr->s = (char *)p->iph;
00227     print_timer(8,"marshal_packet");
00228     return 0;
00229   }
00230 
00231   /* take a conservative size for the packet-- the actual heap may be
00232      smaller than the space we provide */
00233   /* XXX should be statically allocated */
00234   d_printf(100,"%s:%d: sh:%d B,cs:%d B,ss:%d B,hs1:%d B,hs2:%d B\n",
00235       __FILE__,__LINE__, sizeof(header_t), 
00236       ((void *)(p->code_max) - (void *)(p->code_min)),
00237       (stack_amt * sizeof(value_t)),
00238       ((void *)p->heap_max - (void *)p->heap_min),
00239       ((void *)p->h_alloc_heap_max - (void *)p->stack_max));
00240 
00241   sizeb = 
00242     /* IP hdr */ sizeof(struct iphdr) +
00243     /* RA option */ 4 +
00244     /* header */ sizeof(header_t) +
00245     /* code   */ ((void *)(p->code_max) - (void *)(p->code_min)) +
00246     /* stack  */ (stack_amt * sizeof(value_t)) +
00247     /* heap1  */ ((void *)p->heap_max - (void *)p->heap_min) +
00248     /* heap2  */ ((void *)p->h_alloc_heap_max - (void *)p->stack_max);
00249   d_printf(100, "%s:%d: out sizeb = %d bytes\n", 
00250        __FILE__,__LINE__,sizeb);
00251 
00252   if (io_outbuf == NULL) {
00253     if (sizeb > io_outbuf_sizeb) {
00254       io_outbuf_sizeb = sizeb;
00255     }
00256     memalloc(io_outbuf,char *,io_outbuf_sizeb);
00257   } else {
00258     if (sizeb > io_outbuf_sizeb) {
00259       io_outbuf_sizeb = sizeb;
00260       free(io_outbuf);
00261       memalloc(io_outbuf,char *,io_outbuf_sizeb);
00262     }
00263   }
00264   /* copy over the IP header from the current packet */
00265   {
00266     if (p && p->iph){
00267         unsigned char *where = io_outbuf;
00268         d_printf(250,"marshall_packet : where=%p, p->iph=%p, size of header=%u",where,p->iph, sizeof(struct iphdr));
00269         memcpy(where, p->iph, sizeof(struct iphdr));
00270         /* copy over RA option */
00271         memcpy(where + sizeof(struct iphdr),(void *)p->iph + sizeof(struct iphdr),4);
00272     }
00273     /* the following is only used by snapas (the assembler, can be found in the utils subdir) */
00274     else{
00275         d_printf(250,"creating new IP header");
00276     }
00277   }
00278   
00279   /* set up all the source and destination pointers */
00280   newhdr = (header_t *)(io_outbuf + sizeof(struct iphdr) + 4 );
00281   codesrc = p->code_min;
00282   codedst = (instr_t *)(newhdr+1);
00283   newhmin = newhscan = newhalloc =
00284     (void *)codedst + ((void *)p->code_max - (void *)p->code_min);
00285   newhmax =
00286     (void *)newhmin + 
00287     ((void *)p->heap_max - (void *)p->heap_min) +
00288     ((void *)p->h_alloc_heap_max - (void *)p->stack_max);
00289   stacksrc = p->sp - stack_amt;
00290   stackdst = (value_t *)newhmax;
00291 
00292 
00293   /* first copy the header */
00294   memcpy(newhdr,p->hdr,sizeof(header_t));
00295 
00296   /* now copy code */
00297   d_printf(150,"%s:%d: scanning code\n",__FILE__,__LINE__);
00298   {
00299     int sizeb = (int)((void *)p->code_max - (void *)codesrc);
00300     instr_t *codemax = (instr_t *)((void *)codedst + sizeb);
00301 
00302     memcpy(codedst,codesrc,sizeb);
00303     /* scan it, forwarding pointers to moved objects */
00304     while (codedst < codemax) {
00305 #ifdef SMALL_INSTRS
00306       switch (GET_OP(*codedst)) {
00307         case SVCV:
00308         case CALLS:
00309         case PSTR:
00310         case EQSTR:
00311         case NQSTR:
00312         case PTUP:
00313         case EQTUP:
00314         case NQTUP:
00315         case PADDR:
00316         case EQADR:
00317         case NQADR:
00318         case PFLT:
00319         case EQFLT:
00320         case NQFLT:
00321         case FGTI:
00322         case FGEQI:
00323         case FLEQI:
00324         case FLTI:
00325         case FADDI:
00326         case FSUBI:
00327         case FMULI:
00328         case FDIVI:
00329         case SNETI:
00330         case BCASTI: {
00331       int hoffs;
00332       heap_obj *hsrc;
00333       int sizeb;
00334 
00335       GET_LIT(hoffs,BOGUSV,*codedst);
00336       hsrc = (heap_obj *)(p->heap_min + hoffs);
00337 
00338       IF_IN_FROM_HEAP(hsrc,sizeb,p->heap_min,p->heap_max,
00339               p->stack_max,p->h_alloc_heap_max) {
00340         newhalloc = copy_heap_obj(hsrc, sizeb,
00341                       newhmin, newhalloc, newhmax);
00342         /* forward it */
00343         /* note that if copy_heap_obj doesn't copy the object
00344            because it is bogus (or a previous object was), then this
00345            will result in a bogus pointer.  This doesn't matter as
00346            we check against it later in both the GC and the
00347            interpreter. */
00348         SET_LIT(*codedst,BOGUSV,hsrc->flag - 4); /* subtract the extra
00349                             4 from the offset */
00350       } 
00351       /* bogus pointer, leave it XXX */
00352       ELSE_NOT_IN_FROM_HEAP {
00353         fprintf (stderr,"%s:%d: warning, pointer @%#x not in heap\n",
00354              __FILE__,__LINE__,(unsigned int)hsrc);
00355       }
00356       break;
00357     }
00358         default:
00359       break;
00360       } /* end switch */
00361 #else
00362       switch (GET_OP(*codedst)) {
00363 #ifdef ADDR_IN_HEAP
00364         case SNETI:
00365         case BCASTI:
00366     /* these may contain floating point values */
00367         case GTI:
00368         case GEQI:
00369         case LTI:
00370         case LEQI:
00371         case ADDI:
00372         case SUBI:
00373         case MULTI:
00374         case DIVI:
00375 #endif
00376         case PUSH:
00377         case EQI:
00378         case NEQI:
00379         case SVCV:
00380         case CALLS:
00381       newhalloc = scan_value(&(codedst->arg), 
00382                  p->heap_min, p->heap_max,
00383                  p->stack_max, p->h_alloc_heap_max,
00384                  newhmin, newhalloc, newhmax);
00385       break;
00386         default:
00387       break;
00388       } /* end switch */
00389 #endif
00390       codedst++;
00391     } /* end while */
00392   }
00393 
00394   d_printf(150,"%s:%d: done scanning code\n",__FILE__,__LINE__);
00395 
00396   /* copy stack */
00397   d_printf(150,"%s:%d: scanning stack\n",__FILE__,__LINE__);
00398   {
00399     int sizeb = (int)((void *)p->sp - (void *)stacksrc);
00400     value_t *stackmax = (value_t *)((void *)stackdst + sizeb);
00401 
00402     memcpy(stackdst,stacksrc,sizeb);
00403     while (stackdst < stackmax) {
00404       newhalloc = scan_value(stackdst, p->heap_min, p->heap_max,
00405                  p->stack_max, p->h_alloc_heap_max,
00406                  newhmin, newhalloc, newhmax);
00407       stackdst++;
00408     }
00409   }
00410   d_printf(150,"%s:%d: done scanning stack\n",__FILE__,__LINE__);
00411 
00412   /* scan the topspace heap, copying any reachable, uncopied objects */
00413   d_printf(150,"%s:%d: scanning heap, @%#x to @%#x\n",
00414        __FILE__,__LINE__,(unsigned int)newhscan,(unsigned int)newhalloc);
00415   while (newhscan < newhalloc) {
00416     heap_obj *hsrc = (heap_obj *)newhscan;
00417     int sizeb = sizeof(heap_obj) + hsrc->len; /* note that we can
00418                          assume that hsrc->len
00419                          is within the heap
00420                          since it was copied
00421                          here by the GC. */
00422     if ((sizeb & 0x3) != 0) {
00423       sizeb = (sizeb & ~0x3) + 4;
00424     }
00425 
00426     /* if contains pointers, scan the contents of the object */
00427     /* note we check for ==1 exactly in case this object is bogus
00428        (don't want to scan a bogus object, just skip it) */
00429     if (hsrc->flag == 1) {
00430       value_t *vsrc = (value_t *)hsrc->s, 
00431           *vsrcend = (value_t *)(hsrc->s + hsrc->len);
00432 
00433       while (vsrc < vsrcend) {
00434     newhalloc = scan_value(vsrc, p->heap_min, p->heap_max,
00435                    p->stack_max, p->h_alloc_heap_max,
00436                    newhmin, newhalloc, newhmax);
00437     vsrc++;
00438       }
00439     }
00440     newhscan += sizeb;
00441   }
00442   d_printf(150,"%s:%d: done scanning heap\n",__FILE__,__LINE__);
00443 
00444   /* compress the heap */
00445   if (newhalloc != newhmax) {
00446     d_printf(150,"%s:%d: compressing heap/sliding stack down\n",
00447          __FILE__,__LINE__);
00448     memmove(newhalloc,newhmax,(stack_amt * sizeof(value_t)));
00449     stackdst = (value_t *)((void *)stackdst - (newhmax - newhalloc));
00450   }
00451 
00452   /* remove forwarding pointers from current packet's heap */
00453   d_printf(150,"%s:%d: removing forwarding pointers from current packet\n",
00454        __FILE__,__LINE__);
00455   reset_heap(p,newhmin,newhalloc);
00456 
00457   /* note sizes of various things in the new packet */
00458   assert((void *)p->code_max > (void *)p->code_min);
00459   newhdr->code_sizeb = htons((void *)p->code_max - (void *)p->code_min);
00460   assert(stack_amt >= 0);
00461   newhdr->stack_sizeb = htons(stack_amt * sizeof(value_t));
00462   assert(newhalloc >= newhmin);
00463   newhdr->heap_sizeb = htons(newhalloc - newhmin);
00464 
00465   { 
00466     int actual_sizeb = sizeof(struct iphdr) + 4 +
00467       sizeof(struct snaphdr) +
00468       ntohs(newhdr->code_sizeb) + ntohs(newhdr->stack_sizeb) +
00469       ntohs(newhdr->heap_sizeb);
00470     struct iphdr *newiph = (struct iphdr *)io_outbuf;
00471     newiph->tot_len = htons(actual_sizeb);
00472   }
00473 
00474   d_printf(25,"%s:%d: newcs=%d newss=%d newhs=%d\n",__FILE__,__LINE__,
00475        ntohs(newhdr->code_sizeb), ntohs(newhdr->stack_sizeb), 
00476        ntohs(newhdr->heap_sizeb));
00477 
00478   bufstr->lenb = (void *)stackdst - (void *)io_outbuf;
00479   bufstr->s = io_outbuf;
00480   print_timer(8,"marshal_packet");
00481   return 0;
00482 }
00483 
00484 /* invariants (pre and post conditions):
00485      tohalloc and tohmax are word-aligned
00486      tohalloc <= tohmax
00487      tohalloc >= tohmin
00488      hsrc is within fromspace heap, 
00489      sizeb = hsrc->len + sizeof(heap_obj) rounded up to word boundary
00490 */
00491 static void *copy_heap_obj(heap_obj *hsrc, int sizeb,
00492                void *tohmin, void *tohalloc, void *tohmax) {
00493   heap_obj *hdst;
00494 
00495   d_printf(150,"%s:%d: heap obj @%#x (size:%d,f:%d) --",
00496        __FILE__,__LINE__,(uint32)hsrc,hsrc->len,hsrc->flag);
00497   /* check 2, rather than 4, to avoid copying heap objs
00498      that have bogus flag values of 2 and 3 */
00499   if (hsrc->flag < 2) {
00500     /* not forwarded yet, do it now */
00501     hdst = (heap_obj *)tohalloc;
00502     tohalloc += sizeb;
00503     /* this check will only succeed if we're processing a bogus object. */
00504     if (tohalloc > tohmax) {
00505       fprintf(stderr,"%s:%d: Warning, processed bogus object, @%#x\n",
00506           __FILE__,__LINE__,(unsigned int)hsrc);
00507       /* don't do the copy */
00508       return (void *)hdst;
00509     }
00510     hdst->len = hsrc->len; /* now is essentially "legal", thanks to
00511                   check */
00512     hdst->flag = hsrc->flag; /* may be bogus */
00513     memcpy(&(hdst->s),&(hsrc->s),hsrc->len);
00514     /* XXX switch to word-aligned offsets ? */
00515     assert((tohalloc - tohmin + 4) <= 65536);
00516     /* forward it, add 4 to diff from legal flag val 0 */
00517     hsrc->flag = (void *)hdst - tohmin + 4;
00518     d_printf(150,"copied to offs %d, @%#x\n", hsrc->flag - 4, 
00519          (unsigned int)hdst);
00520   }
00521 #ifndef NDEBUG
00522   else
00523     d_printf(150,"forwarded with offs %d, @%#x\n",
00524          hsrc->flag - 4,(unsigned int)(tohmin + (hsrc->flag - 4)));
00525 #endif
00526   return(tohalloc);
00527 }
00528 
00529 /* invariants (pre and post conditions):
00530      tohalloc and tohmax are word-aligned
00531      tohalloc <= tohmax
00532      tohalloc >= tohmin
00533    if the stack value is a bogus pointer (i.e., it might point outside
00534    the heap, or it might be too big), then it will also be bogus on
00535    the way out (in fact, it will be some very large integer).
00536 */
00537 static void *scan_value(value_t *v, void *fromh, void *fromhmax,
00538             void *fromhalloc, void *fromhallocmax,
00539             void *tohmin, void *tohalloc, void *tohmax) {
00540   switch(GET_TAG(*v)) {
00541     case INTV:
00542     case EXCV:
00543     default:
00544       break;
00545     case ADDRV:
00546     case FLOATV:
00547 #ifndef ADDR_IN_HEAP
00548       break;
00549 #endif
00550     case STRV:
00551     case TUPLEV: {
00552       int sizeb;
00553       heap_obj *hsrc = (heap_obj *)(fromh + GET_OFFS(*v));
00554 
00555       /* make sure it's in the fromspace heap */
00556       IF_IN_FROM_HEAP(hsrc,sizeb,fromh,fromhmax,fromhalloc,fromhallocmax) {
00557     tohalloc = copy_heap_obj(hsrc,sizeb,tohmin,tohalloc,tohmax);
00558     /* apply forwarding pointer */
00559     SET_OFFS(*v,hsrc->flag - 4); /* subtract the extra 4 from the offset */
00560     assert(GET_OFFS(*v) == (hsrc->flag - 4));
00561     wassert(GET_OFFS(*v) >= 0);
00562     wassert((GET_OFFS(*v) % 4) == 0);
00563       }
00564       /* otherwise, set the value to a NULL */
00565       ELSE_NOT_IN_FROM_HEAP {
00566     fprintf (stderr,"%s:%d: warning, pointer @%#x not in heap, NULLing\n",
00567          __FILE__,__LINE__,(unsigned int)hsrc);
00568     SET_TAG(*v,INTV);
00569     SET_INT(*v,0);
00570       }
00571       break;
00572     }
00573   }
00574   return(tohalloc);
00575 }
00576 
00577 static void clear_forw_offs(value_t *v, void *fromh, void *fromhmax,
00578                 void *fromhalloc, void *fromhallocmax,
00579                 void *toh, void *tohmax);
00580 
00581 /* invariant: hsrc is the fromspace heap
00582    postcond: hsrc->flag = 0 or 1 (prevents GC loops) */
00583 static void reset_heap_obj(heap_obj *hsrc, 
00584                void *fromh, void *fromhmax,
00585                void *fromhalloc, void *fromhallocmax,
00586                void *toh, void *tohmax) {
00587   /* check >= 2 (rather than 4) to process bogus pointers */
00588   if (hsrc->flag >= 2) {
00589     heap_obj *hdst;
00590 
00591     int sizeb = sizeof(heap_obj) + hsrc->len;
00592     if ((sizeb & 0x3) != 0) {
00593       sizeb = (sizeb & ~0x3) + 4;
00594     }
00595 
00596     wassert((hsrc->flag % 4) == 0);
00597     hdst = (heap_obj *)(toh + hsrc->flag - 4);
00598 
00599     /* make sure the object is in the tospace heap */
00600     if (IN_TOSPACE_HEAP(hdst,sizeb,toh,tohmax)) {
00601 
00602       /* restore the old flag value, removing the forwarding offs */
00603       /* note we need to set the flag to 0 here to in case the hsrc
00604      flag was bogus and happened to point to tospace. */
00605       hsrc->flag = (hdst->flag == 1 ? 1 : 0);
00606       /* scan the object, if necessary, and recurse */
00607       if (hsrc->flag) {
00608     value_t *vsrc = (value_t *)hsrc->s, 
00609             *vsrcend = (value_t *)(hsrc->s + hsrc->len);
00610 
00611     while (vsrc < vsrcend) {
00612       clear_forw_offs(vsrc, fromh, fromhmax, 
00613               fromhalloc, fromhallocmax,
00614               toh, tohmax);
00615       vsrc++;
00616     }
00617       }
00618       /* doesn't contain pointers, don't scan */
00619     }
00620     /* bogus pointer, leave it */
00621     else {
00622       fprintf (stderr,"%s:%d: warning, forw offs to @%#x not in heap\n",
00623            __FILE__,__LINE__,(unsigned int)hdst);
00624     }
00625   }
00626   /* else nothing to do */
00627 }
00628 
00629 static void clear_forw_offs(value_t *v, 
00630                 void *fromh, void *fromhmax, 
00631                 void *fromhalloc, void *fromhallocmax,
00632                 void *toh, void *tohmax) {
00633   switch(GET_TAG(*v)) {
00634     case INTV:
00635     case EXCV:
00636     default:
00637       break;
00638     case ADDRV:
00639     case FLOATV:
00640 #ifndef ADDR_IN_HEAP
00641       break;
00642 #endif
00643     case STRV:
00644     case TUPLEV: {
00645       heap_obj *hsrc = (heap_obj *)(fromh + GET_OFFS(*v));
00646       int sizeb;
00647 
00648       IF_IN_FROM_HEAP(hsrc,sizeb,fromh,fromhmax,
00649               fromhalloc,fromhallocmax)
00650     reset_heap_obj(hsrc,fromh,fromhmax,
00651                fromhalloc,fromhallocmax,
00652                toh,tohmax);
00653       ELSE_NOT_IN_FROM_HEAP {
00654         fprintf (stderr,"%s:%d: warning, pointer @%#x not in heap\n",
00655          __FILE__,__LINE__,(unsigned int)hsrc);
00656       }
00657     }
00658   }
00659 }
00660 
00661 /* clears all of the forwarding pointers left by the marshalling
00662    process */
00663 static void reset_heap(packet_t *p, void *to_heap, void *to_heap_max) {
00664   instr_t *codesrc = p->code_min;
00665   value_t *stacksrc = p->stack_min;
00666 
00667   while (codesrc < p->code_max) {
00668 #ifdef SMALL_INSTRS
00669       switch (GET_OP(*codesrc)) {
00670         case SVCV:
00671         case CALLS:
00672         case PSTR:
00673         case EQSTR:
00674         case NQSTR:
00675         case PTUP:
00676         case EQTUP:
00677         case NQTUP:
00678         case PADDR:
00679         case EQADR:
00680         case NQADR:
00681         case FGTI:
00682         case FGEQI:
00683         case FLEQI:
00684         case FLTI:
00685         case FADDI:
00686         case FSUBI:
00687         case FMULI:
00688         case FDIVI:
00689         case SNETI:
00690         case BCASTI: {
00691       int hoffs, sizeb;
00692       heap_obj *hsrc;
00693       GET_LIT(hoffs,BOGUSV,*codesrc);
00694       hsrc = (heap_obj *)(p->heap_min + hoffs);
00695       IF_IN_FROM_HEAP(hsrc,sizeb,p->heap_min,p->heap_max,
00696               p->stack_max,p->h_alloc_heap_max) {
00697         reset_heap_obj(hsrc, p->heap_min, p->heap_max, p->stack_max,
00698                p->h_alloc_heap_max, to_heap, to_heap_max);
00699       }
00700       ELSE_NOT_IN_FROM_HEAP {
00701         fprintf (stderr,"%s:%d: warning, pointer @%#x not in heap\n",
00702              __FILE__,__LINE__,(unsigned int)hsrc);     
00703       }
00704       break;
00705     }
00706     default:
00707       break;
00708       } /* end switch */
00709 #else
00710       switch (GET_OP(*codesrc)) {
00711 #ifdef ADDR_IN_HEAP
00712         case SNETI:
00713         case BCASTI:
00714     /* these may contain floating point values */
00715         case GTI:
00716         case GEQI:
00717         case LTI:
00718         case LEQI:
00719         case ADDI:
00720         case SUBI:
00721         case MULTI:
00722         case DIVI:
00723 #endif
00724         case PUSH:
00725         case EQI:
00726         case NEQI:
00727         case SVCV:
00728         case CALLS:
00729       clear_forw_offs(&(codesrc->arg), 
00730               p->heap_min, p->heap_max,
00731               p->stack_max, p->h_alloc_heap_max,
00732               to_heap, to_heap_max);
00733       break;
00734         default:
00735       break;
00736       } /* end switch */
00737 #endif
00738     codesrc++;
00739   }
00740   while (stacksrc < p->sp) {
00741     clear_forw_offs(stacksrc, p->heap_min, p->heap_max,
00742             p->stack_max, p->h_alloc_heap_max,
00743             to_heap, to_heap_max);
00744     stacksrc++;
00745   }
00746   /* no need to scan the heap; this was done recursively while
00747      scanning the stack */
00748 }
00749 
00750 int file_to_str(int fd, buffer_t *buf) {
00751   int bufinc = 1024;
00752   int newlen;
00753   char *newbuf;
00754   char *inptr;
00755   int bytes_read;
00756   int total_bytes_read = 0;
00757   
00758   memalloc(buf->s, char *, bufinc);
00759   buf->lenb = bufinc;
00760   inptr = buf->s;
00761   
00762   while(1) {
00763     int space_left = buf->lenb - (inptr - buf->s);
00764     bytes_read = read(fd,inptr,space_left);
00765     if (bytes_read == -1 && (errno == EINTR || errno == EAGAIN))
00766       continue;
00767     total_bytes_read += bytes_read;
00768     if (bytes_read == space_left) {
00769       newlen = buf->lenb + bufinc;
00770       memalloc(newbuf, char *, newlen);
00771       memcpy(newbuf,buf->s,buf->lenb);
00772       inptr = newbuf + buf->lenb;
00773       buf->lenb = newlen;
00774       free(buf->s);
00775       buf->s = newbuf;
00776       continue;
00777     }
00778     /* buf->lenb = (inptr - buf->s) + bytes_read; */
00779     break;
00780   }
00781   return total_bytes_read;
00782 }
00783 
00784