1 /* $Header: d:/cvsroot/tads/tads3/vmwrtimg.h,v 1.4 1999/07/11 00:46:59 MJRoberts Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2002 Michael J. Roberts. All Rights Reserved. 5 * 6 * Please see the accompanying license file, LICENSE.TXT, for information 7 * on using and copying this software. 8 */ 9 /* 10 Name 11 vmwrtimg.h - T3 Image File Writer utility functions 12 Function 13 14 Notes 15 16 Modified 17 04/04/99 MJRoberts - Creation 18 */ 19 20 #ifndef VMWRTIMG_H 21 #define VMWRTIMG_H 22 23 #include "t3std.h" 24 #include "vmtype.h" 25 26 27 class CVmImageWriter 28 { 29 public: 30 /* create an image writer with a given output file */ 31 CVmImageWriter(class CVmFile *fp); 32 33 /* delete the image writer */ 34 ~CVmImageWriter(); 35 36 /* get the current seek location in the underlying file */ 37 long get_pos() const; 38 39 /* 40 * Prepare the file: write out the fixed header information. This 41 * should be called once, before doing any other writing. 'vsn' is 42 * the image file version number to store in the file. 43 */ 44 void prepare(uint vsn, const char tool_data[4]); 45 46 /* 47 * Begin a block with the specified ID (a four-byte string). Writes 48 * the block header, and remembers where the block starts so that 49 * the size prefix can be stored when the block is finished. Blocks 50 * cannot be nested; starting a new block automatically ends the 51 * previous block. 52 */ 53 void begin_block(const char *block_id, int mandatory); 54 55 /* 56 * End the current block. 57 */ 58 void end_block(); 59 60 /* write raw bytes to the image file */ 61 void write_bytes(const char *ptr, uint32 siz); 62 63 /* 64 * Write a complete entrypoint block, given the code offset of the 65 * entrypoint and the various table entry sizes. If a block is in 66 * progress, this will terminate it. 67 */ 68 void write_entrypt(uint32 entry_ofs, size_t method_header_size, 69 size_t exc_entry_size, size_t line_entry_size, 70 size_t dbg_hdr_size, size_t dbg_lclsym_hdr_size, 71 int dbg_vsn_id); 72 73 /* 74 * Write a complete function set dependency block, given an array of 75 * function set names. If a block is in progress, this will 76 * terminate it. 77 */ 78 void write_func_dep(const char **funcset_names, int count); 79 80 /* 81 * Write a complete metaclass dependency block, given an array of 82 * metaclass names. If a block is in progress, this will terminate 83 * it. 84 */ 85 void write_meta_dep(const char **metaclass_names, int count); 86 87 /* 88 * Write a metaclass dependency block in pieces. Call 89 * begin_meta_dep() with the number of metaclasses, then call 90 * write_meta_dep_item() to write each item, and finally call 91 * end_meta_dep() to finish the block. 92 */ 93 void begin_meta_dep(int count); 94 void write_meta_dep_item(const char *metaclass_name); 95 void write_meta_item_prop(uint prop_id); 96 void end_meta_prop_list(); 97 void end_meta_dep(); 98 99 /* 100 * Write a function set dependency block in pieces 101 */ begin_func_dep(int count)102 void begin_func_dep(int count) 103 { begin_dep_block("FNSD", count); } write_func_dep_item(const char * funcset_name)104 void write_func_dep_item(const char *funcset_name) 105 { write_dep_block_item(funcset_name); } end_func_dep()106 void end_func_dep() 107 { end_dep_block(); } 108 109 /* 110 * Write a constant pool definition block. 111 */ 112 void write_pool_def(uint pool_id, uint32 page_count, uint32 page_size, 113 int mandatory); 114 115 /* 116 * Fix up a constant pool definition block with the actual number of 117 * pages. This can be used, if desired, to wait to determine the 118 * actual number of pages in a given constant pool until after 119 * writing the pages. Since the pool definition block must precede 120 * the pool's first page block in the image file, it's impossible to 121 * wait until after writing all of the pages to write the definition 122 * block. Instead, the caller must write the pool definition block 123 * first, using a temporary placeholder value for the page_count (0 124 * will suffice), then write the pool pages, then use this to fix up 125 * the pool definition block with the actual number of pages. The 126 * caller must note the seek position prior to writing the pool 127 * definition block, so that we can seek back to that position to 128 * fix up the definition block. 129 * 130 * Callers need not use this function if they know the actual number 131 * of pages in the pool when writing the original pool definition 132 * block. 133 */ 134 void fix_pool_def(long def_seek_ofs, uint32 page_count); 135 136 /* 137 * Write a constant/code pool page. This writes the entire page 138 * with its header and data in a single operation; this is the 139 * easiest way to write a page when the page has been fully 140 * constructed in a single memory block in advance. 141 */ 142 void write_pool_page(uint pool_id, uint32 page_index, 143 const char *page_data, uint32 page_data_size, 144 int mandatory, uchar xor_mask); 145 146 /* 147 * Write a constant/code pool page in pieces. These routines can be 148 * used when the data in the page are not contiguous in memory and 149 * must be written in pieces. Start by calling begin_pool_page(), 150 * then call write_pool_page_bytes() for each item; the items are 151 * written contiguously to the page. Finish by calling 152 * end_pool_page(). 153 */ 154 void begin_pool_page(uint pool_id, uint32 page_index, int mandatory, 155 uchar xor_mask); 156 void write_pool_page_bytes(const char *buf, uint32 siz, uchar xor_mask); 157 void end_pool_page(); 158 159 /* 160 * Write items in the symbolic names block. Start with 161 * begin_sym_block(), then call the write_sym_item_xxx() functions 162 * to write the names. Finally, call end_sym_block() when done. 163 */ 164 void begin_sym_block(); 165 166 void write_sym_item_objid(const char *nm, size_t len, ulong obj_id); 167 void write_sym_item_propid(const char *nm, size_t len, uint prop_id); 168 void write_sym_item_func(const char *nm, size_t len, ulong code_ofs); 169 void write_sym_item(const char *nm, size_t nmlen, 170 const struct vm_val_t *val); 171 write_sym_item_objid(const char * nm,ulong obj_id)172 void write_sym_item_objid(const char *nm, ulong obj_id) 173 { write_sym_item_objid(nm, get_strlen(nm), obj_id); } write_sym_item_propid(const char * nm,uint prop_id)174 void write_sym_item_propid(const char *nm, uint prop_id) 175 { write_sym_item_propid(nm, get_strlen(nm), prop_id); } write_sym_item(const char * nm,const struct vm_val_t * val)176 void write_sym_item(const char *nm, const struct vm_val_t *val) 177 { write_sym_item(nm, get_strlen(nm), val); } 178 179 void end_sym_block(); 180 181 182 /* 183 * Write items in an OBJS (static object data) block. Start with 184 * begin_objs_block(), then call write_objs_bytes() repeatedly to 185 * write the bytes. Finally, call end_objs_block() when done. 186 * 187 * If the 'large_objects' field is set, the objects in the block use 188 * 32-bit size fields; otherwise the objects use 16-bit size fields. 189 * 190 * If 'trans' is true, the objects in this block are transient; 191 * otherwise, the objects are non-transient (i.e., persistent). 192 */ 193 void begin_objs_block(uint metaclass_idx, int large_objects, int trans); 194 void write_objs_bytes(const char *buf, uint32 siz); 195 void end_objs_block(uint object_count); 196 197 /* 198 * Write the items in a SRCF (source file descriptor) block. Start 199 * with begin_srcf_block(), then write the file entries. For each 200 * entry, call begin_src_entry(), then call write_src_line_entry() 201 * for each source line debug record, then call end_srcf_entry(). 202 * Call end_srcf_block() when done with all file entries. 203 */ 204 void begin_srcf_block(int count); 205 void begin_srcf_entry(int orig_index, const char *fname); 206 void write_srcf_line_entry(ulong linenum, ulong addr); 207 void end_srcf_entry(); 208 void end_srcf_block(); 209 210 /* 211 * Write the items in a GSYM (global symbol table) block. Start 212 * with begin_gsym_block(), then call write_gsym_entry() repeatedly 213 * to write the entries. Call end_gsym_block() when done. 214 */ 215 void begin_gsym_block(); 216 void write_gsym_entry(const char *sym, size_t sym_len, 217 int type_id, const char *dat, size_t dat_len); 218 void end_gsym_block(ulong count); 219 220 /* 221 * Begin MHLS block, write an item, and end the block 222 */ 223 void begin_mhls_block(); 224 void write_mhls_entry(ulong code_addr); 225 void end_mhls_block(); 226 227 /* 228 * Begin/end SINI block. static_cs_ofs is the offset in the code 229 * segment of the first static initializer; this is useful in the 230 * image file because we can delete all of the code pages starting 231 * at this point after pre-initialization is complete. 232 */ 233 void begin_sini_block(ulong static_cs_ofs, ulong init_cnt); 234 void end_sini_block(); 235 236 /* begin/end a MACR (macro symbols) block */ 237 void begin_macr_block(); 238 void end_macr_block(); 239 240 /* 241 * Finish the file. Automatically ends the current block if a block 242 * is open, and writes the end-of-file marker. 243 */ 244 void finish(); 245 246 /* 247 * get the underlying file object; for some types of blocks, it's 248 * simplest for the caller to write the data directly to the underlying 249 * file stream without any help from us 250 */ get_fp()251 class CVmFile *get_fp() const { return fp_; } 252 253 private: 254 /* write a generic dependency (function set, metaclass) block */ 255 void write_dep_block(const char *block_id, const char **names, int count); 256 257 /* write a dependency block in pieces */ 258 void begin_dep_block(const char *block_id, int count); 259 void write_dep_block_item(const char *nm); 260 void end_dep_block(); 261 262 /* XOR a block of bytes with a mask and write the results to the file */ 263 void xor_and_write_bytes(const char *p, uint32 len, uchar xor_mask); 264 265 /* underlying file */ 266 class CVmFile *fp_; 267 268 /* 269 * Seek position of start of current block. If this is zero, no 270 * block is currently open. 271 */ 272 long block_start_; 273 274 /* count of symbolic names written so far (for writing SYMD block) */ 275 int symd_cnt_; 276 277 /* location of metaclass entry next-record offset */ 278 long mcld_ofs_pos_; 279 280 /* location of metaclass property list count prefix */ 281 long mcld_propcnt_pos_; 282 283 /* count of properties writeen in a metaclass prop list so far */ 284 int mcld_prop_cnt_; 285 286 /* seek location of SYMD count prefix, for fixing up at end of block */ 287 long symd_prefix_; 288 289 /* seek location of OBJS count prefix, for fixup up at end of block */ 290 long objs_prefix_; 291 292 /* seek location of GSYM count prefix, for fixup at end of block */ 293 long gsym_prefix_; 294 295 /* start of current SRCF file entry */ 296 long srcf_entry_pos_; 297 298 /* count of SRCF line entries */ 299 long srcf_line_cnt_; 300 301 /* position of SRCF line entry for the current file */ 302 long srcf_line_pos_; 303 304 /* position of MHLS block count entry, and MHLS entry count so far */ 305 long mhls_cnt_pos_; 306 ulong mhls_cnt_; 307 }; 308 309 #endif /* VMWRTIMG_H */ 310 311