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