[t] Refactor some namespace pmc tests to use throws_like
[parrot.git] / src / exec_save.c
blobde83e254d20370b74021217dc0b92ce2d8b1c25a
1 /*
2 Copyright (C) 2001-2008, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/exec_save.c - Save object file in native format
9 =head1 DESCRIPTION
11 Save the C<Parrot_exec_objfile_t> to the native format.
13 =head2 Functions
15 =over 4
17 =cut
21 /* HEADERIZER HFILE: none */
22 /* HEADERIZER STOP */
24 #include <parrot/parrot.h>
25 #include "parrot/exec.h"
26 #include "exec_save.h"
28 static void save_zero(FILE *fp);
29 static void save_int(FILE *fp, int i);
30 static void save_short(FILE *fp, short s);
31 static void save_struct(FILE *fp, void *sp, size_t size);
33 #ifdef EXEC_A_OUT
35 # include <a.out.h>
36 # include <link.h>
40 =item C<void
41 Parrot_exec_save(PARROT_INTERP, Parrot_exec_objfile_t *obj, const char *file)>
43 Save the C<Parrot_exec_objfile_t> to C<file>.
45 =cut
49 void
50 Parrot_exec_save(PARROT_INTERP, Parrot_exec_objfile_t *obj, const char *file)
52 FILE * const fp = fopen(file, "w");
53 int i;
54 struct exec header;
55 struct relocation_info rellocation;
56 struct nlist symlst;
59 header.a_midmag = 0x07018600;
60 header.a_text = obj->text.size;
61 header.a_data = obj->data.size;
62 header.a_bss = obj->bss.size;
63 header.a_syms = obj->symbol_count * sizeof (struct nlist);
64 header.a_entry = 0;
65 header.a_trsize = obj->text_rellocation_count
66 * sizeof (struct relocation_info);
67 header.a_drsize = obj->data_rellocation_count
68 * sizeof (struct relocation_info);
69 save_struct(fp, &header, sizeof (struct exec));
70 /* Text */
71 for (i = 0; i < obj->text.size; i++)
72 fprintf(fp, "%c", obj->text.code[i]);
73 /* Data */
74 for (i = 0; i < obj->data.size; i++)
75 fprintf(fp, "%c", obj->data.code[i]);
76 /* Text rellocations */
77 for (i = obj->text_rellocation_count - 1; i >= 0; i--) {
78 memset(&rellocation, 0, sizeof (struct relocation_info));
79 rellocation.r_address = obj->text_rellocation_table[i].offset;
80 rellocation.r_symbolnum = obj->text_rellocation_table[i].symbol_number;
81 switch (obj->text_rellocation_table[i].type) {
82 case RTYPE_FUNC:
83 rellocation.r_pcrel = 1;
84 rellocation.r_length = 2;
85 rellocation.r_extern = 1;
86 break;
87 case RTYPE_COM:
88 case RTYPE_DATA:
89 rellocation.r_length = 2;
90 rellocation.r_extern = 1;
91 break;
92 default:
93 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
94 "Unknown text rellocation type: %d\n",
95 obj->text_rellocation_table[i].type);
96 break;
98 save_struct(fp, &rellocation, sizeof (struct relocation_info));
100 /* Symbol table */
101 for (i = 0; i < obj->symbol_count; i++) {
102 memset(&symlst, 0, sizeof (struct nlist));
103 symlst.n_un.n_strx = obj->symbol_table[i].offset_list;
104 switch (obj->symbol_table[i].type) {
105 case STYPE_FUNC:
106 symlst.n_type = N_EXT | N_TEXT;
107 symlst.n_other = AUX_FUNC;
108 break;
109 case STYPE_GDATA:
110 symlst.n_type = N_EXT | N_DATA;
111 symlst.n_other = AUX_OBJECT;
112 symlst.n_value = obj->symbol_table[i].value;
113 break;
114 case STYPE_COM:
115 symlst.n_type = N_EXT;
116 symlst.n_value = obj->symbol_table[i].value;
117 break;
118 case STYPE_UND:
119 symlst.n_type = N_EXT;
120 break;
121 default:
122 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
123 "Unknown symbol type: %d\n", obj->symbol_table[i].type);
124 break;
126 save_struct(fp, &symlst, sizeof (struct nlist));
128 /* String table size */
129 save_int(fp, obj->symbol_list_size);
130 /* String table */
131 for (i = 0; i < obj->symbol_count; i++) {
132 if (obj->symbol_table[i].type != STYPE_GCC)
133 fprintf(fp, "_%s", obj->symbol_table[i].symbol);
134 else
135 fprintf(fp, "%s", obj->symbol_table[i].symbol);
136 save_zero(fp);
138 fclose(fp);
141 #endif /* EXEC_A_OUT */
143 #ifdef EXEC_ELF
145 # ifdef PARROT_EXEC_OS_OPENBSD
146 # define R_386_32 1
147 # define R_386_PC32 2
148 # include <elf_abi.h>
149 # else
150 # include <elf.h>
151 # endif
153 # if defined(PARROT_PPC)
154 # if !defined(R_PPC_ADDR16_HI) && !defined(R_PPC_ADDR16_LO) && \
155 defined(R_PPC_16_HI) && defined(R_PPC_16_LO)
156 # define R_PPC_ADDR16_HI R_PPC_16_HI
157 # define R_PPC_ADDR16_LO R_PPC_16_LO
158 # endif
160 * NetBSD/powerpc 3.x and OpenBSD/powerpc doesn't define these constants,
161 * but instead has them as enums, so add some workarounds for those.
163 # if !defined(R_PPC_ADDR16_HI) && !defined(R_PPC_ADDR16_LO) && \
164 (defined(__NetBSD__) || defined(__OpenBSD__))
165 # define R_PPC_ADDR16_HI RELOC_16_HI
166 # define R_PPC_ADDR16_LO RELOC_16_LO
167 # endif
168 # if !defined(R_PPC_REL24) && (defined(__NetBSD__) || defined(__OpenBSD__))
169 # define R_PPC_REL24 RELOC_REL24
170 # endif
171 # endif /* PARROT_PPC */
173 /* Add a section to the file
175 * n = Name
176 * t = Type
177 * f = Flags
178 * s = Size
179 * l = Link
180 * i = Info
181 * a = Align
182 * e = Entry size
184 # define sh_add(n, t, f, s, l, i, a, e) { \
185 memset(&sechdr, 0, sizeof (Elf32_Shdr)); \
186 sechdr.sh_name = shste - shst; \
187 shste += sprintf(shste, "%s", (n)); \
188 shste++; \
189 sechdr.sh_type = (t); \
190 sechdr.sh_flags = (f); \
191 sechdr.sh_addr = 0; \
192 sechdr.sh_offset = current_offset; \
193 sechdr.sh_size = (s); \
194 sechdr.sh_link = (l); \
195 sechdr.sh_info = (i); \
196 sechdr.sh_addralign = (a); \
197 sechdr.sh_entsize = (e); \
198 save_struct(fp, &sechdr, sizeof (Elf32_Shdr)); \
199 current_offset += (s); \
200 if ((s) % 4) \
201 current_offset += (4 - (s) % 4); \
204 /* Sizeof the section header string table */
205 # define SHSTRTABSIZE 0x48
206 /* Previously defined symbols (zero, text, data, bss) */
207 # define PDFS 4
208 /* Number of sections */
209 # define NSECTIONS 8
211 void
212 Parrot_exec_save(PARROT_INTERP, Parrot_exec_objfile_t *obj, const char *file)
214 FILE *fp = fopen(file, "w");
215 char *shste;
216 char shst[SHSTRTABSIZE];
218 Elf32_Ehdr header;
219 Elf32_Shdr sechdr;
220 Elf32_Rel rellocation;
221 Elf32_Rela rel_addend;
222 Elf32_Sym symlst;
223 Elf32_Off current_offset;
224 int i;
226 memset(&header, 0, sizeof (Elf32_Ehdr));
227 header.e_ident[0] = ELFMAG0;
228 header.e_ident[1] = ELFMAG1;
229 header.e_ident[2] = ELFMAG2;
230 header.e_ident[3] = ELFMAG3;
231 header.e_ident[4] = ELFCLASS32;
232 # if PARROT_BIGENDIAN
233 header.e_ident[5] = ELFDATA2MSB;
234 # else /* PARROT_BIGENDIAN */
235 header.e_ident[5] = ELFDATA2LSB;
236 # endif /* PARROT_BIGENDIAN */
237 header.e_ident[6] = EV_CURRENT;
238 # ifdef PARROT_EXEC_OS_FREEBSD
239 header.e_ident[7] = ELFOSABI_FREEBSD;
240 # endif
241 # ifdef PARROT_EXEC_OS_NETBSD
242 header.e_ident[7] = ELFOSABI_NETBSD;
243 # endif
244 # if defined(PARROT_EXEC_OS_LINUX) && defined(ELFOSABI_LINUX) && \
245 !defined(PARROT_PPC) && !defined(PARROT_ARM)
246 header.e_ident[7] = ELFOSABI_LINUX;
247 # endif
249 header.e_type = ET_REL;
250 # ifdef PARROT_I386
251 header.e_machine = EM_386;
252 # endif
253 # ifdef PARROT_PPC
254 header.e_machine = EM_PPC;
255 # endif
256 # ifdef PARROT_ARM
257 header.e_ident[7] = ELFOSABI_ARM;
258 header.e_machine = EM_ARM;
259 # endif
260 header.e_version = EV_CURRENT;
261 header.e_entry = 0;
262 header.e_phoff = 0;
263 header.e_shoff = sizeof (Elf32_Ehdr);
264 header.e_flags = 0;
265 header.e_ehsize = sizeof (Elf32_Ehdr);
266 header.e_phentsize = 0;
267 header.e_phnum = 0;
268 header.e_shentsize = sizeof (Elf32_Shdr);
269 header.e_shnum = NSECTIONS;
270 header.e_shstrndx = 1;
272 save_struct(fp, &header, sizeof (Elf32_Ehdr));
274 current_offset = sizeof (Elf32_Ehdr) + NSECTIONS * sizeof (Elf32_Shdr);
276 /* Sections */
277 memset(&shst, 0, SHSTRTABSIZE);
278 shste = shst + 1;
280 /* NULL */
281 memset(&sechdr, 0, sizeof (Elf32_Shdr));
282 save_struct(fp, &sechdr, sizeof (Elf32_Shdr));
284 /* Section Header String Table */
285 sh_add(".shstrtab", SHT_STRTAB, 0, SHSTRTABSIZE, 0, 0, 1, 0);
287 /* Text */
288 sh_add(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, obj->text.size,
289 0, 0, 4, 0);
291 /* Data */
292 sh_add(".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, obj->data.size,
293 0, 0, 4, 0);
295 /* Bss */
296 sh_add(".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, obj->bss.size,
297 0, 0, 4, 0);
299 * Text rellocation records.
300 * Link must be the symtab section header index.
301 * Info is the text section header index.
303 # if defined(PARROT_I386) || defined(PARROT_ARM)
304 sh_add(".rel.text", SHT_REL, 0, obj->text_rellocation_count *
305 sizeof (Elf32_Rel), 6, 2, 4, sizeof (Elf32_Rel));
306 # endif
308 * PPC requires rellocation structures with addends.
310 # ifdef PARROT_PPC
311 sh_add(".rela.text", SHT_RELA, 0, obj->text_rellocation_count *
312 sizeof (Elf32_Rela), 6, 2, 4, sizeof (Elf32_Rela));
313 # endif
315 * Symbol table.
316 * Link is the strtab section header index.
317 * Info is the index of the first symbol in the symbol table.
319 sh_add(".symtab", SHT_SYMTAB, 0, (obj->symbol_count + PDFS) *
320 sizeof (Elf32_Sym), 7, PDFS - 1, 4, sizeof (Elf32_Sym));
321 /* String Table */
322 obj->symbol_list_size += 1; /* Trailing \0 */
323 sh_add(".strtab", SHT_STRTAB, 0, obj->symbol_list_size, 0, 0, 1, 0);
325 /* Section header string table */
326 save_struct(fp, &shst, SHSTRTABSIZE);
327 save_struct(fp, obj->text.code, obj->text.size); /* Text */
328 save_struct(fp, obj->data.code, obj->data.size); /* Data */
329 /* Text rellocations */
330 for (i = 0; i < obj->text_rellocation_count; i++) {
331 # ifdef PARROT_I386
332 memset(&rellocation, 0, sizeof (Elf32_Rel));
334 rellocation.r_offset = obj->text_rellocation_table[i].offset;
335 switch (obj->text_rellocation_table[i].type) {
336 case RTYPE_FUNC:
337 rellocation.r_info =
338 ELF32_R_INFO(
339 obj->text_rellocation_table[i].symbol_number + PDFS,
340 R_386_PC32);
341 break;
342 case RTYPE_DATA:
343 case RTYPE_COM:
344 rellocation.r_info =
345 ELF32_R_INFO(
346 obj->text_rellocation_table[i].symbol_number + PDFS,
347 R_386_32);
348 break;
349 default:
350 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
351 "Unknown text rellocation type: %d\n",
352 obj->text_rellocation_table[i].type);
353 break;
355 save_struct(fp, &rellocation, sizeof (Elf32_Rel));
356 # endif
357 # ifdef PARROT_PPC
358 memset(&rel_addend, 0, sizeof (Elf32_Rela));
359 rel_addend.r_offset = obj->text_rellocation_table[i].offset;
360 switch (obj->text_rellocation_table[i].type) {
361 case RTYPE_FUNC:
362 rel_addend.r_info =
363 ELF32_R_INFO(
364 obj->text_rellocation_table[i].symbol_number + PDFS,
365 R_PPC_REL24);
366 break;
367 case RTYPE_DATA:
368 case RTYPE_COM:
369 rel_addend.r_info =
370 ELF32_R_INFO(
371 obj->text_rellocation_table[i].symbol_number + PDFS,
372 R_PPC_ADDR16_HI);
373 rel_addend.r_addend = *((short *)
374 (&obj->text.code[obj->text_rellocation_table[i].offset]))
375 << 16;
376 rel_addend.r_addend += *((short *)
377 (&obj->text.code[
378 obj->text_rellocation_table[i].offset + 4]));
379 break;
380 case RTYPE_DATA1:
381 rel_addend.r_info =
382 ELF32_R_INFO(
383 obj->text_rellocation_table[i].symbol_number + PDFS,
384 R_PPC_ADDR16_LO);
385 rel_addend.r_addend = *((short *)
386 (&obj->text.code[obj->text_rellocation_table[i].offset]));
387 rel_addend.r_addend += *((short *)
388 (&obj->text.code[
389 obj->text_rellocation_table[i].offset - 4])) << 16;
390 break;
391 default:
392 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
393 "Unknown text rellocation type: %d\n",
394 obj->text_rellocation_table[i].type);
395 break;
397 save_struct(fp, &rel_addend, sizeof (Elf32_Rela));
398 # endif
399 # ifdef PARROT_ARM
400 memset(&rellocation, 0, sizeof (Elf32_Rel));
401 rellocation.r_offset = obj->text_rellocation_table[i].offset;
402 switch (obj->text_rellocation_table[i].type) {
403 case RTYPE_FUNC:
404 rellocation.r_info =
405 ELF32_R_INFO(
406 obj->text_rellocation_table[i].symbol_number + PDFS,
407 R_ARM_ABS32);
408 break;
409 case RTYPE_DATA:
410 rellocation.r_info =
411 ELF32_R_INFO(
412 obj->text_rellocation_table[i].symbol_number + PDFS,
413 R_ARM_ABS32);
414 break;
415 default:
416 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
417 "Unknown text rellocation type: %d\n",
418 obj->text_rellocation_table[i].type);
419 break;
421 save_struct(fp, &rellocation, sizeof (Elf32_Rel));
422 # endif
424 /* Symbol table */
425 /* zero */
426 memset(&symlst, 0, sizeof (Elf32_Sym));
427 save_struct(fp, &symlst, sizeof (Elf32_Sym));
429 /* Text */
430 memset(&symlst, 0, sizeof (Elf32_Sym));
431 symlst.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
432 symlst.st_shndx = 2;
433 save_struct(fp, &symlst, sizeof (Elf32_Sym));
435 /* Data */
436 memset(&symlst, 0, sizeof (Elf32_Sym));
437 symlst.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
438 symlst.st_shndx = 3;
439 save_struct(fp, &symlst, sizeof (Elf32_Sym));
441 /* Bss */
442 memset(&symlst, 0, sizeof (Elf32_Sym));
443 symlst.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
444 symlst.st_shndx = 4;
445 save_struct(fp, &symlst, sizeof (Elf32_Sym));
447 for (i = 0; i < obj->symbol_count; i++) {
448 memset(&symlst, 0, sizeof (Elf32_Sym));
449 symlst.st_name = obj->symbol_table[i].offset_list + 1;
450 switch (obj->symbol_table[i].type) {
451 case STYPE_FUNC:
452 symlst.st_info = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
453 symlst.st_size = obj->text.size;
454 symlst.st_shndx = 2; /* text */
455 break;
456 case STYPE_GDATA:
457 symlst.st_value = obj->symbol_table[i].value;
458 symlst.st_size = obj->data_size[i];
459 symlst.st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
460 symlst.st_shndx = 3; /* data */
461 break;
462 case STYPE_COM:
463 symlst.st_value = obj->symbol_table[i].value;
464 /* symlst.st_size = obj->data_size[i]; XXX daniel why? */
465 symlst.st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
466 symlst.st_shndx = SHN_COMMON;
467 break;
468 case STYPE_UND:
469 symlst.st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE);
470 break;
471 default:
472 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
473 "Unknown symbol type: %d\n", obj->symbol_table[i].type);
474 break;
476 save_struct(fp, &symlst, sizeof (Elf32_Sym));
478 /* String table */
479 save_zero(fp);
480 for (i = 0; i < obj->symbol_count; i++) {
481 fprintf(fp, "%s", obj->symbol_table[i].symbol);
482 save_zero(fp);
484 /* PAD */
485 for (i = 0; i < (4 - obj->symbol_list_size % 4); i++)
486 save_zero(fp);
487 fclose(fp);
490 #endif /* EXEC_ELF */
492 #ifdef EXEC_MACH_O
494 void
495 Parrot_exec_save(PARROT_INTERP, Parrot_exec_objfile_t *obj, const char *file)
497 FILE *fp = fopen(file, "w");
498 size_t i;
500 fprintf(fp, "\xFE\xED\xFA\xCE"); /* Header for Darwin */
501 save_int(fp, 0x12);
502 save_int(fp, 0);
503 save_int(fp, 0x1);
504 save_int(fp, 0x3);
505 save_int(fp, 0x128);
506 save_int(fp, 0);
507 save_int(fp, 0x1);
508 save_int(fp, 0xC0);
509 for (i = 0; i < 5; i++)
510 save_int(fp, 0);
511 /* Sizeof text + data */
512 save_int(fp, obj->text.size + obj->data.size);
513 /* Offset of text */
514 save_int(fp, 0x144);
515 save_int(fp, obj->text.size + obj->data.size);
516 save_int(fp, 0x7);
517 save_int(fp, 0x7);
518 save_int(fp, 0x2);
519 save_int(fp, 0);
520 fprintf(fp, "__text");
521 for (i = 0; i < 10; i++)
522 save_zero(fp);
523 fprintf(fp, "__TEXT");
524 for (i = 0; i < 10; i++)
525 save_zero(fp);
526 save_int(fp, 0);
527 /* Sizeof text */
528 save_int(fp, obj->text.size);
529 save_int(fp, 0x144);
530 save_int(fp, 0x2);
531 /* Offset of rellocation table. */
532 save_int(fp, 0x144 + obj->text.size + obj->data.size);
533 save_int(fp, obj->text_rellocation_count);
534 save_int(fp, 0x80000400);
535 save_int(fp, 0);
536 save_int(fp, 0);
537 fprintf(fp, "__data");
538 for (i = 0; i < 10; i++)
539 save_zero(fp);
540 fprintf(fp, "__DATA");
541 for (i = 0; i < 10; i++)
542 save_zero(fp);
543 /* Data VMA */
544 save_int(fp, obj->text.size);
545 /* Data size */
546 save_int(fp, obj->data.size);
547 /* Data file offset */
548 save_int(fp, 0x144 + obj->text.size);
549 save_int(fp, 0x2);
550 for (i = 0; i < 5; i++)
551 save_int(fp, 0);
552 save_int(fp, 0x2);
553 /* save_int(fp, obj->symbol_count * 0xc); */
554 save_int(fp, 0x18);
555 /* Offset of stabs */
556 save_int(fp, 0x144 +
557 obj->text.size + obj->data.size + obj->text_rellocation_count * 0x8);
558 /* Number of stabs (symbol table) */
559 save_int(fp, obj->symbol_count);
560 /* Offset of symbol list */
561 save_int(fp, 0x144 + obj->text.size + obj->data.size +
562 obj->text_rellocation_count * 0x8 + obj->symbol_count * 0xc);
563 /* Sizeof symbol list */
564 save_int(fp, obj->symbol_list_size);
565 save_int(fp, 0xB);
566 save_int(fp, 0x50);
567 for (i = 0; i < 3; i++)
568 save_int(fp, 0);
569 save_int(fp, obj->symbol_count);
570 save_int(fp, obj->symbol_count);
571 for (i = 0; i < 13; i++)
572 save_int(fp, 0);
574 /* Text */
575 for (i = 0; i < obj->text.size; i++)
576 fprintf(fp, "%c", obj->text.code[i]);
577 /* Data */
578 for (i = 0; i < obj->data.size; i++)
579 fprintf(fp, "%c", obj->data.code[i]);
580 /* Text rellocations */
581 /* XXX This is an infinite loop. When i = 0, i-- goes to very large. */
582 for (i = obj->text_rellocation_count - 1; i >= 0; i--) {
583 save_int(fp, obj->text_rellocation_table[i].offset);
584 save_short(fp, obj->text_rellocation_table[i].symbol_number);
585 save_short(fp, obj->text_rellocation_table[i].type);
587 /* Symbol table */
588 for (i = 0; i < obj->symbol_count; i++) {
589 save_int(fp, obj->symbol_table[i].offset_list);
590 save_int(fp, obj->symbol_table[i].type);
591 save_int(fp, obj->symbol_table[i].value);
593 /* Symbol list */
594 for (i = 0; i < obj->symbol_count; i++) {
595 if (obj->symbol_table[i].type != STYPE_GCC)
596 fprintf(fp, "_%s", obj->symbol_table[i].symbol);
597 else
598 fprintf(fp, "%s", obj->symbol_table[i].symbol);
599 save_zero(fp);
601 fclose(fp);
604 #endif /* EXEC_MACH_O */
606 #ifdef EXEC_COFF
608 /* File offsets */
609 # define TEXT_CODE 0x14 + (3 * 0x28)
610 # define DATA_CODE TEXT_CODE + obj->text.size
611 # define TEXT_RELOC DATA_CODE + obj->data.size
612 # define DATA_RELOC TEXT_RELOC + (obj->text_rellocation_count * 0xA)
613 # define SYMTAB DATA_RELOC + (obj->data_rellocation_count * 0xA)
615 void
616 Parrot_exec_save(PARROT_INTERP, Parrot_exec_objfile_t *obj, const char *file)
618 FILE *fp;
619 int i;
620 size_t j;
622 fp = fopen(file, "wb");
624 save_short(fp, 0x14C); /* i386 */
625 save_short(fp, 3); /* Number of sections */
626 save_int(fp, Parrot_intval_time());
627 save_int(fp, SYMTAB);
628 save_int(fp, obj->symbol_count);
629 save_short(fp, 0);
630 save_short(fp, 0x104); /* 32 bit LE, no line numbers */
632 fwrite(".text\0\0\0", 8, 1, fp);
633 save_int(fp, 0);
634 save_int(fp, 0);
635 save_int(fp, obj->text.size);
636 save_int(fp, TEXT_CODE);
637 save_int(fp, TEXT_RELOC);
638 save_int(fp, 0);
639 save_short(fp, (short)obj->text_rellocation_count);
640 save_short(fp, 0);
641 save_int(fp, 0x20);
643 fwrite(".data\0\0\0", 8, 1, fp);
644 save_int(fp, 0);
645 save_int(fp, 0);
646 save_int(fp, obj->data.size);
647 save_int(fp, DATA_CODE);
648 save_int(fp, DATA_RELOC);
649 save_int(fp, 0);
650 save_short(fp, (short)obj->data_rellocation_count);
651 save_short(fp, 0);
652 save_int(fp, 0x40);
654 fwrite(".bss\0\0\0\0", 8, 1, fp);
655 save_int(fp, 0);
656 save_int(fp, 0);
657 save_int(fp, obj->bss.size);
658 save_int(fp, 0);
659 save_int(fp, 0);
660 save_int(fp, 0);
661 save_short(fp, 0);
662 save_short(fp, 0);
663 save_int(fp, 0x80);
665 /* Text */
666 for (j = 0; j < obj->text.size; j++)
667 fprintf(fp, "%c", obj->text.code[j]);
668 /* Data */
669 for (j = 0; j < obj->data.size; j++)
670 fprintf(fp, "%c", obj->data.code[j]);
671 /* Text rellocations */
672 for (i = 0; i < obj->text_rellocation_count; i++) {
673 save_int(fp, obj->text_rellocation_table[i].offset);
674 save_int(fp, obj->text_rellocation_table[i].symbol_number);
675 switch (obj->text_rellocation_table[i].type) {
676 case RTYPE_FUNC:
677 save_short(fp, 0x14);
678 break;
679 case RTYPE_COM:
680 case RTYPE_DATA:
681 save_short(fp, 0x06);
682 break;
683 default:
684 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
685 "Unknown text rellocation type: %d\n",
686 obj->text_rellocation_table[i].type);
687 break;
690 /* Symbol table */
691 for (i = 0; i < obj->symbol_count; i++) {
692 save_int(fp, 0);
693 save_int(fp, obj->symbol_table[i].offset_list);
694 save_int(fp, obj->symbol_table[i].value);
695 switch (obj->symbol_table[i].type) {
696 case STYPE_FUNC:
697 save_short(fp, 1); /* .text */
698 save_short(fp, 0x20);
699 break;
700 case STYPE_GDATA:
701 save_short(fp, 2); /* .data */
702 save_short(fp, 0);
703 break;
704 case STYPE_COM:
705 save_short(fp, 0);
706 save_short(fp, 0);
707 break;
708 case STYPE_UND:
709 save_short(fp, 0);
710 save_short(fp, 0x20);
711 break;
712 default:
713 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_ERROR,
714 "Unknown symbol type: %d\n", obj->symbol_table[i].type);
715 break;
717 putc(2, fp); /* "extern" class */
718 putc(0, fp);
720 /* Symbol list */
721 save_int(fp, obj->symbol_list_size);
722 for (i = 0; i < obj->symbol_count; i++) {
723 if (obj->symbol_table[i].type != STYPE_GCC)
724 fprintf(fp, "_%s", obj->symbol_table[i].symbol);
725 else
726 fprintf(fp, "%s", obj->symbol_table[i].symbol);
727 save_zero(fp);
729 fclose(fp);
732 #endif /* EXEC_COFF */
736 =item C<static void save_struct(FILE *fp, void *sp, size_t size)>
738 Writes the C<struct> C<sp> to the file.
740 =cut
744 static void
745 save_struct(FILE *fp, void *sp, size_t size)
747 unsigned int i;
749 for (i = 0; i < size; i++)
750 fprintf(fp, "%c", ((char *)sp)[i]);
755 =item C<static void save_zero(FILE *fp)>
757 Writes 0 to the file.
759 =cut
763 static void
764 save_zero(FILE *fp)
766 fprintf(fp, "%c", 0);
769 #if PARROT_BIGENDIAN
773 =item C<static void save_int(FILE *fp, int i)>
775 Writes C<i> to the file.
777 =cut
781 static void
782 save_int(FILE *fp, int i)
784 fprintf(fp, "%c%c%c%c", (char)(i >> 24), (char)(i >> 16),
785 (char)(i >> 8), (char)i);
790 =item C<static void save_short(FILE *fp, short s)>
792 Writes C<s> to the file.
794 =cut
798 static void
799 save_short(FILE *fp, short s)
801 fprintf(fp, "%c%c", (char)(s >> 8), (char)s);
804 #else /* PARROT_BIGENDIAN */
806 static void
807 save_short(FILE *fp, short s)
809 fprintf(fp, "%c%c", (char)s, (char)(s >> 8));
812 static void
813 save_int(FILE *fp, int i)
815 fprintf(fp, "%c%c%c%c", (char)i, (char)(i >> 8),
816 (char)(i >> 16), (char)(i >> 24));
819 #endif /* PARROT_BIGENDIAN */
823 =back
825 =head1 SEE ALSO
827 F<include/parrot/exec.h>, F<src/exec_save.h>, F<src/exec.c>
828 and F<src/exec_start.c>.
830 =head1 HISTORY
832 Initial version by Daniel Grunblatt on 2003.6.9.
834 =cut
840 * Local variables:
841 * c-file-style: "parrot"
842 * End:
843 * vim: expandtab shiftwidth=4: