1 #ifdef RCSID
2 static char RCSid[] =
3 "$Header: d:/cvsroot/tads/tads3/vmwrtimg.cpp,v 1.4 1999/07/11 00:46:59 MJRoberts Exp $";
4 #endif
5 
6 /*
7  *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
8  *
9  *   Please see the accompanying license file, LICENSE.TXT, for information
10  *   on using and copying this software.
11  */
12 /*
13 Name
14   vmwrtimg.cpp - T3 Image File Writer utility functions
15 Function
16   Provides functions to write an image file
17 Notes
18 
19 Modified
20   04/04/99 MJRoberts  - Creation
21 */
22 
23 
24 #include <string.h>
25 #include <time.h>
26 
27 #include "t3std.h"
28 #include "vmfile.h"
29 #include "vmwrtimg.h"
30 #include "vmimage.h"
31 
32 /* ------------------------------------------------------------------------ */
33 /*
34  *   initialize
35  */
CVmImageWriter(CVmFile * fp)36 CVmImageWriter::CVmImageWriter(CVmFile *fp)
37 {
38     /* remember the underlying file */
39     fp_ = fp;
40 
41     /* no block is currently open */
42     block_start_ = 0;
43 }
44 
45 /*
46  *   delete
47  */
~CVmImageWriter()48 CVmImageWriter::~CVmImageWriter()
49 {
50 }
51 
52 /* ------------------------------------------------------------------------ */
53 /*
54  *   get the current seek position in the underlying file
55  */
get_pos() const56 long CVmImageWriter::get_pos() const
57 {
58     return fp_->get_pos();
59 }
60 
61 /* ------------------------------------------------------------------------ */
62 /*
63  *   Prepare the file - write the header.
64  */
prepare(uint vsn,const char tool_data[4])65 void CVmImageWriter::prepare(uint vsn, const char tool_data[4])
66 {
67     char buf[32];
68     time_t timer;
69     struct tm *tblock;
70 
71     /* write the signature */
72     fp_->write_bytes(VMIMAGE_SIG, sizeof(VMIMAGE_SIG)-1);
73 
74     /* write the version number */
75     fp_->write_int2(vsn);
76 
77     /* write the 28 reserved bytes, setting all to zero */
78     memset(buf, 0, 28);
79     fp_->write_bytes(buf, 28);
80 
81     /* write the additional 4 bytes reserved for tool use */
82     fp_->write_bytes(tool_data, 4);
83 
84     /* write the compilation timestamp */
85     timer = time(NULL);
86     tblock = localtime(&timer);
87     fp_->write_bytes(asctime(tblock), 24);
88 }
89 
90 /* ------------------------------------------------------------------------ */
91 /*
92  *   Begin a block
93  */
begin_block(const char * block_id,int mandatory)94 void CVmImageWriter::begin_block(const char *block_id, int mandatory)
95 {
96     char buf[10];
97     uint flags;
98 
99     /* if there's a block currently open, close it */
100     end_block();
101 
102     /* remember the seek location of the start of the block */
103     block_start_ = fp_->get_pos();
104 
105     /* store the type string */
106     memcpy(buf, block_id, 4);
107 
108     /* store four bytes of zeroes as a placeholder for the size */
109     memset(buf+4, 0, 4);
110 
111     /* compute the flags */
112     flags = 0;
113     if (mandatory)
114         flags |= VMIMAGE_DBF_MANDATORY;
115 
116     /* store the flags */
117     oswp2(buf+8, flags);
118 
119     /* write the header */
120     fp_->write_bytes(buf, 10);
121 }
122 
123 /* ------------------------------------------------------------------------ */
124 /*
125  *   End the current block.  If no block is open, this does nothing.
126  */
end_block()127 void CVmImageWriter::end_block()
128 {
129     long end_pos;
130     uint32 siz;
131 
132     /* if there's no block open, there's nothing we need to do */
133     if (block_start_ == 0)
134         return;
135 
136     /*
137      *   note the current file position - this will let us compute the
138      *   size of the block, and we'll need to seek back here when we're
139      *   done updating the block header
140      */
141     end_pos = fp_->get_pos();
142 
143     /*
144      *   Since the block is finished, we can now compute its size.  The
145      *   size of the data block is the end seek position minus the
146      *   starting seek position.  'block_start_' contains the seek
147      *   position of the block header, which takes up ten bytes; we want
148      *   to store the size of the block's data, excluding the header,
149      *   which is (end_pos - block_header_pos - 10).
150      */
151     siz = (uint32)(end_pos - block_start_ - 10);
152 
153     /*
154      *   Seek back to the location of the size field in the block header;
155      *   this is four bytes into the block header.  Then, update the size
156      *   field with the size of the block's data.
157      */
158     fp_->set_pos(block_start_ + 4);
159     fp_->write_int4(siz);
160 
161     /*
162      *   seek back to the end of the block, so we can resume writing data
163      *   following the block
164      */
165     fp_->set_pos(end_pos);
166 
167     /* the block is now closed, so forget about it */
168     block_start_ = 0;
169 }
170 
171 /* ------------------------------------------------------------------------ */
172 /*
173  *   Write raw bytes to the file
174  */
write_bytes(const char * ptr,uint32 siz)175 void CVmImageWriter::write_bytes(const char *ptr, uint32 siz)
176 {
177     /* write in 64k chunks, to accommodate 16-bit platforms */
178     while (siz != 0)
179     {
180         size_t cur;
181 
182         /* get the next 64k, or the remainder if less than 64k is left */
183         cur = 65535;
184         if (siz < cur)
185             cur = (size_t)siz;
186 
187         /* write this chunk */
188         fp_->write_bytes(ptr, cur);
189 
190         /* advance past this chunk */
191         ptr += cur;
192         siz -= cur;
193     }
194 }
195 
196 /* ------------------------------------------------------------------------ */
197 /*
198  *   Finish the file.  Closes the current block if one is open, and writes
199  *   the end-of-file marker to the file.
200  */
finish()201 void CVmImageWriter::finish()
202 {
203     /* if there's a block open, close it */
204     end_block();
205 
206     /*
207      *   write the EOF block - the block contains no data, so simply begin
208      *   and end it
209      */
210     begin_block("EOF ", TRUE);
211     end_block();
212 }
213 
214 /* ------------------------------------------------------------------------ */
215 /*
216  *   Write an entrypoint (ENTP) block
217  */
write_entrypt(uint32 entry_ofs,size_t method_hdr_size,size_t exc_entry_size,size_t line_entry_size,size_t dbg_hdr_size,size_t dbg_lclsym_hdr_size,int dbg_vsn_id)218 void CVmImageWriter::write_entrypt(uint32 entry_ofs, size_t method_hdr_size,
219                                    size_t exc_entry_size,
220                                    size_t line_entry_size,
221                                    size_t dbg_hdr_size,
222                                    size_t dbg_lclsym_hdr_size,
223                                    int dbg_vsn_id)
224 {
225     char buf[32];
226 
227     /* prepare the block's contents */
228     oswp4(buf, entry_ofs);
229     oswp2(buf+4, method_hdr_size);
230     oswp2(buf+6, exc_entry_size);
231     oswp2(buf+8, line_entry_size);
232     oswp2(buf+10, dbg_hdr_size);
233     oswp2(buf+12, dbg_lclsym_hdr_size);
234     oswp2(buf+14, dbg_vsn_id);
235 
236     /* open the block, write the data, and close the block */
237     begin_block("ENTP", TRUE);
238     fp_->write_bytes(buf, 16);
239     end_block();
240 }
241 
242 /* ------------------------------------------------------------------------ */
243 /*
244  *   Write a function set dependency block
245  */
write_func_dep(const char ** funcset_names,int count)246 void CVmImageWriter::write_func_dep(const char **funcset_names, int count)
247 {
248     /* write a FNSD block */
249     write_dep_block("FNSD", funcset_names, count);
250 }
251 
252 /* ------------------------------------------------------------------------ */
253 /*
254  *   begin a metaclass dependency block
255  */
begin_meta_dep(int count)256 void CVmImageWriter::begin_meta_dep(int count)
257 {
258     /* begin the dependency block */
259     begin_dep_block("MCLD", count);
260 
261     /* we're not in a property list yet */
262     mcld_propcnt_pos_ = 0;
263 }
264 
265 /*
266  *   Write a metaclass dependency block
267  */
write_meta_dep(const char ** meta_names,int count)268 void CVmImageWriter::write_meta_dep(const char **meta_names, int count)
269 {
270     /* write a MCLD block */
271     write_dep_block("MCLD", meta_names, count);
272 }
273 
274 /*
275  *   write a metaclass dependency block item
276  */
write_meta_dep_item(const char * metaclass_name)277 void CVmImageWriter::write_meta_dep_item(const char *metaclass_name)
278 {
279     /* if we didn't end the previous item's property list, end it now */
280     end_meta_prop_list();
281 
282     /* write a placeholder next record offset */
283     mcld_ofs_pos_ = fp_->get_pos();
284     fp_->write_int2(0);
285 
286     /* write the metaclass name */
287     write_dep_block_item(metaclass_name);
288 
289     /* write a placeholder property vector count */
290     mcld_propcnt_pos_ = fp_->get_pos();
291     fp_->write_int2(0);
292 
293     /* write the property record size (2 bytes) */
294     fp_->write_int2(2);
295 
296     /* no properties yet */
297     mcld_prop_cnt_ = 0;
298 }
299 
300 /*
301  *   write a metaclass dependency property list item
302  */
write_meta_item_prop(uint prop_id)303 void CVmImageWriter::write_meta_item_prop(uint prop_id)
304 {
305     /* write the property ID */
306     fp_->write_int2(prop_id);
307 
308     /* count it */
309     ++mcld_prop_cnt_;
310 }
311 
312 /*
313  *   end a metaclass prop list
314  */
end_meta_prop_list()315 void CVmImageWriter::end_meta_prop_list()
316 {
317     /* if we have a count pending, go write it */
318     if (mcld_propcnt_pos_ != 0)
319     {
320         long pos;
321 
322         /* remember the current position */
323         pos = fp_->get_pos();
324 
325         /* go back and write the property count */
326         fp_->set_pos(mcld_propcnt_pos_);
327         fp_->write_int2(mcld_prop_cnt_);
328 
329         /* we no longer have a property count fixup to apply */
330         mcld_propcnt_pos_ = 0;
331 
332         /* go back and write the next-record offset */
333         fp_->set_pos(mcld_ofs_pos_);
334         fp_->write_int2((int)(pos - mcld_ofs_pos_));
335 
336         /* go back to the end of the record */
337         fp_->set_pos(pos);
338     }
339 }
340 
341 /*
342  *   end a metaclass dependency block
343  */
end_meta_dep()344 void CVmImageWriter::end_meta_dep()
345 {
346     /* end the last metaclass item */
347     end_meta_prop_list();
348 
349     /* end the dependency block */
350     end_dep_block();
351 }
352 
353 /* ------------------------------------------------------------------------ */
354 /*
355  *   Begin a dependency block
356  */
begin_dep_block(const char * block_id,int count)357 void CVmImageWriter::begin_dep_block(const char *block_id, int count)
358 {
359     char buf[4];
360 
361     /* open the block */
362     begin_block(block_id, TRUE);
363 
364     /* write the number of entries */
365     oswp2(buf, count);
366     fp_->write_bytes(buf, 2);
367 }
368 
369 /*
370  *   Write a dependency block item
371  */
write_dep_block_item(const char * nm)372 void CVmImageWriter::write_dep_block_item(const char *nm)
373 {
374     size_t len;
375     char buf[4];
376 
377     /* get the length of this name, and truncate to 255 bytes */
378     len = strlen(nm);
379     if (len > 255)
380         len = 255;
381 
382     /* write the length, followed by the name */
383     buf[0] = (char)(uchar)len;
384     fp_->write_bytes(buf, 1);
385     fp_->write_bytes(nm, len);
386 }
387 
388 /*
389  *   End a dependency block
390  */
end_dep_block()391 void CVmImageWriter::end_dep_block()
392 {
393     /* end the block */
394     end_block();
395 }
396 
397 /* ------------------------------------------------------------------------ */
398 /*
399  *   Write a generic dependency list block
400  */
write_dep_block(const char * block_id,const char ** names,int count)401 void CVmImageWriter::write_dep_block(const char *block_id,
402                                      const char **names, int count)
403 {
404     /* open the block */
405     begin_dep_block(block_id, count);
406 
407     /* write each entry */
408     for ( ; count > 0 ; ++names, --count)
409         write_dep_block_item(*names);
410 
411     /* end the block */
412     end_dep_block();
413 }
414 
415 /* ------------------------------------------------------------------------ */
416 /*
417  *   Write a constant pool definition block
418  */
write_pool_def(uint pool_id,uint32 page_count,uint32 page_size,int mandatory)419 void CVmImageWriter::write_pool_def(uint pool_id, uint32 page_count,
420                                     uint32 page_size, int mandatory)
421 {
422     char buf[16];
423 
424     /* prepare the block's data */
425     oswp2(buf, pool_id);
426     oswp4(buf+2, page_count);
427     oswp4(buf+6, page_size);
428 
429     /* open the block, write the data, and end the block */
430     begin_block("CPDF", mandatory);
431     fp_->write_bytes(buf, 10);
432     end_block();
433 }
434 
435 /*
436  *   Fix up a pool definition block with the actual page count
437  */
fix_pool_def(long def_seek_ofs,uint32 page_count)438 void CVmImageWriter::fix_pool_def(long def_seek_ofs, uint32 page_count)
439 {
440     long old_pos;
441     char buf[4];
442 
443     /* note the file position at entry */
444     old_pos = fp_->get_pos();
445 
446     /*
447      *   seek to the original definition block location, plus the size of
448      *   the block header (10 bytes), plus the offset within the block of
449      *   the pool page count (it starts 2 bytes into the block data)
450      */
451     fp_->set_pos(def_seek_ofs + 10 + 2);
452 
453     /* write the page count */
454     oswp4(buf, page_count);
455     fp_->write_bytes(buf, 4);
456 
457     /* seek back to our location at entry */
458     fp_->set_pos(old_pos);
459 }
460 
461 
462 /* ------------------------------------------------------------------------ */
463 /*
464  *   Write a constant pool page
465  */
write_pool_page(uint pool_id,uint32 page_index,const char * page_data,uint32 page_data_size,int mandatory,uchar xor_mask)466 void CVmImageWriter::write_pool_page(uint pool_id, uint32 page_index,
467                                      const char *page_data,
468                                      uint32 page_data_size, int mandatory,
469                                      uchar xor_mask)
470 {
471     char buf[16];
472 
473     /* begin the block */
474     begin_block("CPPG", mandatory);
475 
476     /* prepare the prefix */
477     oswp2(buf, pool_id);
478     oswp4(buf+2, page_index);
479     buf[6] = xor_mask;
480 
481     /* write the prefix */
482     fp_->write_bytes(buf, 7);
483 
484     /* write the page data, XOR'ing the data with the mask byte */
485     xor_and_write_bytes(page_data, page_data_size, xor_mask);
486 
487     /* end the block */
488     end_block();
489 }
490 
491 /* ------------------------------------------------------------------------ */
492 /*
493  *   Begin writing a constant pool page.  This constructs the header and
494  *   prepares for writing the bytes making up the page.
495  */
begin_pool_page(uint pool_id,uint32 page_index,int mandatory,uchar xor_mask)496 void CVmImageWriter::begin_pool_page(uint pool_id, uint32 page_index,
497                                      int mandatory, uchar xor_mask)
498 {
499     char buf[16];
500 
501     /* begin the block */
502     begin_block("CPPG", mandatory);
503 
504     /* prepare the prefix */
505     oswp2(buf, pool_id);
506     oswp4(buf+2, page_index);
507     buf[6] = xor_mask;
508 
509     /* write the prefix */
510     fp_->write_bytes(buf, 7);
511 }
512 
513 /*
514  *   write bytes to a pool page under construction
515  */
write_pool_page_bytes(const char * buf,uint32 siz,uchar xor_mask)516 void CVmImageWriter::write_pool_page_bytes(const char *buf, uint32 siz,
517                                            uchar xor_mask)
518 {
519     /* write the page data, XOR'ing the data with the mask byte */
520     xor_and_write_bytes(buf, siz, xor_mask);
521 }
522 
523 /*
524  *   XOR and write a block of data - we will XOR each byte of the data
525  *   with the given mask byte before writing it to the file
526  */
xor_and_write_bytes(const char * mem,uint32 siz,uchar xor_mask)527 void CVmImageWriter::xor_and_write_bytes(const char *mem, uint32 siz,
528                                          uchar xor_mask)
529 {
530     /*
531      *   if there's no mask, simply write the data directly - anything XOR
532      *   zero equals the original value
533      */
534     if (xor_mask == 0)
535     {
536         /* write the data to the page */
537         fp_->write_bytes(mem, siz);
538     }
539     else
540     {
541         /*
542          *   copy the data in chunks into our buffer, XOR it with the
543          *   mask, and write the results
544          */
545         while (siz != 0)
546         {
547             char buf[1024];
548             size_t cur;
549             size_t rem;
550             char *dst;
551 
552             /*
553              *   limit this chunk to the buffer size or the remainder of
554              *   the input, whichever is smaller
555              */
556             cur = sizeof(buf);
557             if (cur > siz)
558                 cur = (size_t)siz;
559 
560             /* copy this chunk, xor'ing each byte with the mask */
561             for (dst = buf, rem = cur ; rem != 0 ; --rem, ++dst, ++mem)
562                 *dst = *mem ^ xor_mask;
563 
564             /* write out this chunk */
565             fp_->write_bytes(buf, cur);
566 
567             /* subtract this chunk from the length remaining */
568             siz -= cur;
569         }
570     }
571 }
572 
573 /*
574  *   finish writing a pool page
575  */
end_pool_page()576 void CVmImageWriter::end_pool_page()
577 {
578     /* end the block */
579     end_block();
580 }
581 
582 /* ------------------------------------------------------------------------ */
583 /*
584  *   Begin a symbolic names block
585  */
begin_sym_block()586 void CVmImageWriter::begin_sym_block()
587 {
588     char buf[4];
589 
590     /* begin the block */
591     begin_block("SYMD", FALSE);
592 
593     /* remember where our placeholder goes */
594     symd_prefix_ = fp_->get_pos();
595 
596     /* prepare the placeholder prefix, using a zero count for now */
597     oswp2(buf, 0);
598 
599     /* write the prefix */
600     fp_->write_bytes(buf, 2);
601 
602     /* we haven't written any symbolic name items yet */
603     symd_cnt_ = 0;
604 }
605 
606 /*
607  *   write a symbolic name for an object ID
608  */
write_sym_item_objid(const char * nm,size_t len,ulong obj_id)609 void CVmImageWriter::write_sym_item_objid(const char *nm, size_t len,
610                                           ulong obj_id)
611 {
612     vm_val_t val;
613 
614     /* set up the object ID value */
615     val.set_obj((vm_obj_id_t)obj_id);
616 
617     /* write it out */
618     write_sym_item(nm, len, &val);
619 }
620 
621 /*
622  *   write a symbolic name for a property ID
623  */
write_sym_item_propid(const char * nm,size_t len,uint prop_id)624 void CVmImageWriter::write_sym_item_propid(const char *nm, size_t len,
625                                            uint prop_id)
626 {
627     vm_val_t val;
628 
629     /* set up the property ID value */
630     val.set_propid((vm_prop_id_t)prop_id);
631 
632     /* write it out */
633     write_sym_item(nm, len, &val);
634 }
635 
636 /*
637  *   write a symbolic name for a function
638  */
write_sym_item_func(const char * nm,size_t len,ulong code_ofs)639 void CVmImageWriter::write_sym_item_func(const char *nm, size_t len,
640                                          ulong code_ofs)
641 {
642     vm_val_t val;
643 
644     /* set up the property ID value */
645     val.set_fnptr((pool_ofs_t)code_ofs);
646 
647     /* write it out */
648     write_sym_item(nm, len, &val);
649 }
650 
651 /*
652  *   write a symbolic name item
653  */
write_sym_item(const char * nm,size_t len,const vm_val_t * val)654 void CVmImageWriter::write_sym_item(const char *nm, size_t len,
655                                     const vm_val_t *val)
656 {
657     char buf[VMB_DATAHOLDER + 1];
658 
659     /* prepare the data holder in the prefix */
660     vmb_put_dh(buf, val);
661 
662     /* limit the length to 255 bytes */
663     if (len > 255)
664         len = 255;
665 
666     /* add the length to the prefix */
667     buf[VMB_DATAHOLDER] = (char)len;
668 
669     /* write the prefix */
670     fp_->write_bytes(buf, VMB_DATAHOLDER + 1);
671 
672     /* write the string */
673     fp_->write_bytes(nm, len);
674 
675     /* count it */
676     ++symd_cnt_;
677 }
678 
679 /*
680  *   end a symbolic names block
681  */
end_sym_block()682 void CVmImageWriter::end_sym_block()
683 {
684     long old_pos;
685     char buf[4];
686 
687     /* end the block */
688     end_block();
689 
690     /*
691      *   Go back and fix the header with the number of items we wrote.
692      *   First, remember our current position, then seek back to the count
693      *   prefix.
694      */
695     old_pos = fp_->get_pos();
696     fp_->set_pos(symd_prefix_);
697 
698     /* prepare the prefix, and write it out */
699     oswp2(buf, symd_cnt_);
700     fp_->write_bytes(buf, 2);
701 
702     /* restore the file position */
703     fp_->set_pos(old_pos);
704 }
705 
706 /* ------------------------------------------------------------------------ */
707 /*
708  *   Begin an object static data block
709  */
begin_objs_block(uint metaclass_idx,int large_objects,int trans)710 void CVmImageWriter::begin_objs_block(uint metaclass_idx, int large_objects,
711                                       int trans)
712 {
713     char buf[16];
714     uint flags;
715 
716     /* begin the block */
717     begin_block("OBJS", TRUE);
718 
719     /* prepare the flags */
720     flags = 0;
721     if (large_objects)
722         flags |= 1;
723     if (trans)
724         flags |= 2;
725 
726     /* remember where the prefix goes so we can fix it up later */
727     objs_prefix_ = fp_->get_pos();
728 
729     /*
730      *   write a placeholder object count, the metaclass dependency table
731      *   index, and the OBJS flags
732      */
733     oswp2(buf, 0);
734     oswp2(buf + 2, metaclass_idx);
735     oswp2(buf + 4, flags);
736 
737     /* write the prefix */
738     fp_->write_bytes(buf, 6);
739 }
740 
741 /*
742  *   Write bytes to an OBJS (object static data) block
743  */
write_objs_bytes(const char * buf,uint32 siz)744 void CVmImageWriter::write_objs_bytes(const char *buf, uint32 siz)
745 {
746     /* write the buffer */
747     fp_->write_bytes(buf, siz);
748 }
749 
750 /*
751  *   end an object static data block
752  */
end_objs_block(uint object_count)753 void CVmImageWriter::end_objs_block(uint object_count)
754 {
755     long pos;
756 
757     /* remember the current file write position for a moment */
758     pos = fp_->get_pos();
759 
760     /* go back and fix up the object count in the header */
761     fp_->set_pos(objs_prefix_);
762     fp_->write_int2(object_count);
763 
764     /* seek back to the original position */
765     fp_->set_pos(pos);
766 
767     /* end the block */
768     end_block();
769 }
770 
771 /* ------------------------------------------------------------------------ */
772 /*
773  *   SRCF blocks - source file descriptors
774  */
775 
776 /*
777  *   begin a SRCF block
778  */
begin_srcf_block(int count)779 void CVmImageWriter::begin_srcf_block(int count)
780 {
781     /*
782      *   begin the block - SRCF blocks are always optional, since they're
783      *   purely for debugging purposes
784      */
785     begin_block("SRCF", FALSE);
786 
787     /* write the number of entries */
788     fp_->write_int2(count);
789 
790     /* each source line record is 8 bytes in the current format */
791     fp_->write_int2(8);
792 }
793 
794 /*
795  *   begin a SRCF file entry
796  */
begin_srcf_entry(int orig_index,const char * fname)797 void CVmImageWriter::begin_srcf_entry(int orig_index, const char *fname)
798 {
799     size_t len;
800 
801     /* remember where this entry starts, so we can fix up the size later */
802     srcf_entry_pos_ = fp_->get_pos();
803 
804     /* write a placeholder size entry */
805     fp_->write_int4(0);
806 
807     /* write the original index */
808     fp_->write_int2(orig_index);
809 
810     /* write the length of the name */
811     len = get_strlen(fname);
812     fp_->write_int2(len);
813 
814     /* write the filename */
815     fp_->write_bytes(fname, len);
816 
817     /* we have no line record yet, so write a placeholder count */
818     srcf_line_pos_ = fp_->get_pos();
819     fp_->write_int4(0);
820     srcf_line_cnt_ = 0;
821 }
822 
823 /*
824  *   write a SRCF line record entry
825  */
write_srcf_line_entry(ulong linenum,ulong addr)826 void CVmImageWriter::write_srcf_line_entry(ulong linenum, ulong addr)
827 {
828     /* write the line number and address */
829     fp_->write_int4(linenum);
830     fp_->write_int4(addr);
831 
832     /* count it */
833     ++srcf_line_cnt_;
834 }
835 
836 /*
837  *   end a SRCF file entry
838  */
end_srcf_entry()839 void CVmImageWriter::end_srcf_entry()
840 {
841     ulong pos;
842 
843     /* go back and fix up the line record count */
844     pos = fp_->get_pos();
845     fp_->set_pos(srcf_line_pos_);
846     fp_->write_int4(srcf_line_cnt_);
847 
848     /* go back and fix up the total entry size record */
849     fp_->set_pos(srcf_entry_pos_);
850     fp_->write_int4(pos - srcf_entry_pos_);
851 
852     /* seek back to the end of the block */
853     fp_->set_pos(pos);
854 
855 }
856 
857 /*
858  *   end a SRCF block
859  */
end_srcf_block()860 void CVmImageWriter::end_srcf_block()
861 {
862     /* end the block using the generic mechanism */
863     end_block();
864 }
865 
866 /* ------------------------------------------------------------------------ */
867 /*
868  *   MACR blocks - global preprocess macro symbol table
869  */
870 
871 /*
872  *   begin a MACR block
873  */
begin_macr_block()874 void CVmImageWriter::begin_macr_block()
875 {
876     /*
877      *   write the header - it's an optional block since it's for the
878      *   debugger's use only
879      */
880     begin_block("MACR", FALSE);
881 }
882 
883 /*
884  *   end a MACR block
885  */
end_macr_block()886 void CVmImageWriter::end_macr_block()
887 {
888     /* end the block using the generic mechanism */
889     end_block();
890 }
891 
892 /* ------------------------------------------------------------------------ */
893 /*
894  *   GSYM blocks - global symbol table
895  */
896 
897 /*
898  *   begin a GSYM block
899  */
begin_gsym_block()900 void CVmImageWriter::begin_gsym_block()
901 {
902     /*
903      *   begin the block - GSYM blocks are always optional, since they're
904      *   purely for debugging purposes
905      */
906     begin_block("GSYM", FALSE);
907 
908     /* remember where the prefix goes so we can fix it up later */
909     gsym_prefix_ = fp_->get_pos();
910 
911     /* write a placehodler object count and the metaclass index */
912     fp_->write_int4(0);
913 }
914 
915 /*
916  *   write a GSYM entry
917  */
write_gsym_entry(const char * sym,size_t sym_len,int type_id,const char * dat,size_t dat_len)918 void CVmImageWriter::write_gsym_entry(const char *sym, size_t sym_len,
919                                       int type_id,
920                                       const char *dat, size_t dat_len)
921 {
922     /*
923      *   write the length of the symbol, length of the extra data, and the
924      *   symbol type
925      */
926     fp_->write_int2(sym_len);
927     fp_->write_int2(dat_len);
928     fp_->write_int2(type_id);
929 
930     /* write the symbol name */
931     fp_->write_bytes(sym, sym_len);
932 
933     /* write the extra data */
934     fp_->write_bytes(dat, dat_len);
935 }
936 
937 /*
938  *   end a GSYM block
939  */
end_gsym_block(ulong cnt)940 void CVmImageWriter::end_gsym_block(ulong cnt)
941 {
942     long pos;
943 
944     /* remember the current file write position for a moment */
945     pos = fp_->get_pos();
946 
947     /* go back and fix up the count in the header */
948     fp_->set_pos(gsym_prefix_);
949     fp_->write_int4(cnt);
950 
951     /* seek back to the original position */
952     fp_->set_pos(pos);
953 
954     /* end the block using the generic mechanism */
955     end_block();
956 }
957 
958 /* ------------------------------------------------------------------------ */
959 /*
960  *   MHLS blocks - method header list
961  */
962 
963 /*
964  *   begin an MHLS block
965  */
begin_mhls_block()966 void CVmImageWriter::begin_mhls_block()
967 {
968     /*
969      *   begin the block - MHLS blocks are always optional, since they're
970      *   purely for debugging purposes
971      */
972     begin_block("MHLS", FALSE);
973 
974     /* remember where the count goes so we can fix it up later */
975     mhls_cnt_pos_ = fp_->get_pos();
976 
977     /* write a placehodler count */
978     fp_->write_int4(0);
979 
980     /* there are no entries yet */
981     mhls_cnt_ = 0;
982 }
983 
984 /*
985  *   write an MHLS entry
986  */
write_mhls_entry(ulong addr)987 void CVmImageWriter::write_mhls_entry(ulong addr)
988 {
989     /* write the address */
990     fp_->write_int4(addr);
991 
992     /* count the entry */
993     ++mhls_cnt_;
994 }
995 
996 /*
997  *   end an MHLS block
998  */
end_mhls_block()999 void CVmImageWriter::end_mhls_block()
1000 {
1001     long pos;
1002 
1003     /* remember the current file write position for a moment */
1004     pos = fp_->get_pos();
1005 
1006     /* go back and fix up the count in the header */
1007     fp_->set_pos(mhls_cnt_pos_);
1008     fp_->write_int4(mhls_cnt_);
1009 
1010     /* seek back to the original position */
1011     fp_->set_pos(pos);
1012 
1013     /* end the block using the generic mechanism */
1014     end_block();
1015 }
1016 
1017 /* ------------------------------------------------------------------------ */
1018 /*
1019  *   SINI block - static initializer list
1020  */
1021 
1022 /*
1023  *   begin an SINI block
1024  */
begin_sini_block(ulong static_cs_ofs,ulong init_cnt)1025 void CVmImageWriter::begin_sini_block(ulong static_cs_ofs, ulong init_cnt)
1026 {
1027     /*
1028      *   begin the block - SINI blocks are mandatory, since the program
1029      *   depends upon static initializers being evaluated immediately
1030      *   after compilation
1031      */
1032     begin_block("SINI", TRUE);
1033 
1034     /*
1035      *   write the size of our header (including the size prefix); this
1036      *   serves as a simple versioning flag so we can tell if fields added
1037      *   at a later date are part of a given image file's data or not (if
1038      *   the header is too small to contain them, they're not present)
1039      */
1040     fp_->write_int4(12);
1041 
1042     /* write the starting static code segment offset */
1043     fp_->write_int4(static_cs_ofs);
1044 
1045     /* write the initializer count */
1046     fp_->write_int4(init_cnt);
1047 }
1048 
1049 /*
1050  *   end an SINI block
1051  */
end_sini_block()1052 void CVmImageWriter::end_sini_block()
1053 {
1054     /* end the block using the generic mechanism */
1055     end_block();
1056 }
1057 
1058