[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 |
Splash - DocumentationSNMP Plus a Lightweight API for SNAP Handlingsnap-1.1-wjdb/lib/snap_io.cGo 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 |