2 Copyright (C) 2001-2003, The Perl Foundation.
7 src/exec_save.c - Save object file in native format
11 Save the C<Parrot_exec_objfile_t> to the native format.
21 /* HEADERIZER HFILE: none */
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
);
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>.
50 Parrot_exec_save(PARROT_INTERP
, Parrot_exec_objfile_t
*obj
, const char *file
)
55 struct relocation_info rellocation
;
58 fp
= fopen(file
, "w");
60 header
.a_midmag
= 0x07018600;
61 header
.a_text
= obj
->text
.size
;
62 header
.a_data
= obj
->data
.size
;
63 header
.a_bss
= obj
->bss
.size
;
64 header
.a_syms
= obj
->symbol_count
* sizeof (struct nlist
);
66 header
.a_trsize
= obj
->text_rellocation_count
67 * sizeof (struct relocation_info
);
68 header
.a_drsize
= obj
->data_rellocation_count
69 * sizeof (struct relocation_info
);
70 save_struct(fp
, &header
, sizeof (struct exec
));
72 for (i
= 0; i
< obj
->text
.size
; i
++)
73 fprintf(fp
, "%c", obj
->text
.code
[i
]);
75 for (i
= 0; i
< obj
->data
.size
; i
++)
76 fprintf(fp
, "%c", obj
->data
.code
[i
]);
77 /* Text rellocations */
78 for (i
= obj
->text_rellocation_count
- 1; i
>= 0; i
--) {
79 bzero(&rellocation
, sizeof (struct relocation_info
));
80 rellocation
.r_address
= obj
->text_rellocation_table
[i
].offset
;
81 rellocation
.r_symbolnum
= obj
->text_rellocation_table
[i
].symbol_number
;
82 switch (obj
->text_rellocation_table
[i
].type
) {
84 rellocation
.r_pcrel
= 1;
85 rellocation
.r_length
= 2;
86 rellocation
.r_extern
= 1;
90 rellocation
.r_length
= 2;
91 rellocation
.r_extern
= 1;
94 real_exception(interp
, NULL
, EXEC_ERROR
,
95 "Unknown text rellocation type: %d\n",
96 obj
->text_rellocation_table
[i
].type
);
99 save_struct(fp
, &rellocation
, sizeof (struct relocation_info
));
102 for (i
= 0; i
< obj
->symbol_count
; i
++) {
103 bzero(&symlst
, sizeof (struct nlist
));
104 symlst
.n_un
.n_strx
= obj
->symbol_table
[i
].offset_list
;
105 switch (obj
->symbol_table
[i
].type
) {
107 symlst
.n_type
= N_EXT
| N_TEXT
;
108 symlst
.n_other
= AUX_FUNC
;
111 symlst
.n_type
= N_EXT
| N_DATA
;
112 symlst
.n_other
= AUX_OBJECT
;
113 symlst
.n_value
= obj
->symbol_table
[i
].value
;
116 symlst
.n_type
= N_EXT
;
117 symlst
.n_value
= obj
->symbol_table
[i
].value
;
120 symlst
.n_type
= N_EXT
;
123 real_exception(interp
, NULL
, EXEC_ERROR
, "Unknown symbol type: %d\n",
124 obj
->symbol_table
[i
].type
);
127 save_struct(fp
, &symlst
, sizeof (struct nlist
));
129 /* String table size */
130 save_int(fp
, obj
->symbol_list_size
);
132 for (i
= 0; i
< obj
->symbol_count
; i
++) {
133 if (obj
->symbol_table
[i
].type
!= STYPE_GCC
)
134 fprintf(fp
, "_%s", obj
->symbol_table
[i
].symbol
);
136 fprintf(fp
, "%s", obj
->symbol_table
[i
].symbol
);
142 #endif /* EXEC_A_OUT */
146 # ifdef PARROT_EXEC_OS_OPENBSD
148 # define R_386_PC32 2
149 # include <elf_abi.h>
154 /* Add a section to the file
165 # define sh_add(n, t, f, s, l, i, a, e) { \
166 bzero(&sechdr, sizeof (Elf32_Ehdr)); \
167 sechdr.sh_name = shste - shst; \
168 shste += sprintf(shste, "%s", n); \
170 sechdr.sh_type = t; \
171 sechdr.sh_flags = f; \
172 sechdr.sh_addr = 0; \
173 sechdr.sh_offset = current_offset; \
174 sechdr.sh_size = s; \
175 sechdr.sh_link = l; \
176 sechdr.sh_info = i; \
177 sechdr.sh_addralign = a; \
178 sechdr.sh_entsize = e; \
179 save_struct(fp, &sechdr, sizeof (Elf32_Shdr)); \
180 current_offset += s; \
182 current_offset += (4 - s % 4); \
185 /* Sizeof the section header string table */
186 # define SHSTRTABSIZE 0x48
187 /* Previously defined symbols (zero, text, data, bss) */
189 /* Number of sections */
193 Parrot_exec_save(PARROT_INTERP
, Parrot_exec_objfile_t
*obj
, const char *file
)
197 Elf32_Rel rellocation
;
198 Elf32_Rela rel_addend
;
200 Elf32_Off current_offset
;
203 char shst
[SHSTRTABSIZE
], *shste
;
205 fp
= fopen(file
, "w");
207 bzero(&header
, sizeof (Elf32_Ehdr
));
208 header
.e_ident
[0] = ELFMAG0
;
209 header
.e_ident
[1] = ELFMAG1
;
210 header
.e_ident
[2] = ELFMAG2
;
211 header
.e_ident
[3] = ELFMAG3
;
212 header
.e_ident
[4] = ELFCLASS32
;
213 # if PARROT_BIGENDIAN
214 header
.e_ident
[5] = ELFDATA2MSB
;
215 # else /* PARROT_BIGENDIAN */
216 header
.e_ident
[5] = ELFDATA2LSB
;
217 # endif /* PARROT_BIGENDIAN */
218 header
.e_ident
[6] = EV_CURRENT
;
219 # ifdef PARROT_EXEC_OS_FREEBSD
220 header
.e_ident
[7] = ELFOSABI_FREEBSD
;
222 # ifdef PARROT_EXEC_OS_NETBSD
223 header
.e_ident
[7] = ELFOSABI_NETBSD
;
225 # if defined(PARROT_EXEC_OS_LINUX) && defined(ELFOSABI_LINUX) && \
226 !defined(PARROT_PPC) && !defined(PARROT_ARM)
227 header
.e_ident
[7] = ELFOSABI_LINUX
;
230 header
.e_type
= ET_REL
;
232 header
.e_machine
= EM_386
;
235 header
.e_machine
= EM_PPC
;
238 header
.e_ident
[7] = ELFOSABI_ARM
;
239 header
.e_machine
= EM_ARM
;
241 header
.e_version
= EV_CURRENT
;
244 header
.e_shoff
= sizeof (Elf32_Ehdr
);
246 header
.e_ehsize
= sizeof (Elf32_Ehdr
);
247 header
.e_phentsize
= 0;
249 header
.e_shentsize
= sizeof (Elf32_Shdr
);
250 header
.e_shnum
= NSECTIONS
;
251 header
.e_shstrndx
= 1;
253 save_struct(fp
, &header
, sizeof (Elf32_Ehdr
));
255 current_offset
= sizeof (Elf32_Ehdr
) + NSECTIONS
* sizeof (Elf32_Shdr
);
258 bzero(&shst
, SHSTRTABSIZE
);
261 bzero(&sechdr
, sizeof (Elf32_Ehdr
));
262 save_struct(fp
, &sechdr
, sizeof (Elf32_Shdr
));
263 /* Section Header String Table */
264 sh_add(".shstrtab", SHT_STRTAB
, 0, SHSTRTABSIZE
, 0, 0, 1, 0);
266 sh_add(".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
, obj
->text
.size
,
269 sh_add(".data", SHT_PROGBITS
, SHF_WRITE
| SHF_ALLOC
, obj
->data
.size
,
272 sh_add(".bss", SHT_NOBITS
, SHF_WRITE
| SHF_ALLOC
, obj
->bss
.size
,
275 * Text rellocation records.
276 * Link must be the symtab section header index.
277 * Info is the text section header index.
279 # if defined(PARROT_I386) || defined(PARROT_ARM)
280 sh_add(".rel.text", SHT_REL
, 0, obj
->text_rellocation_count
*
281 sizeof (Elf32_Rel
), 6, 2, 4, sizeof (Elf32_Rel
));
284 * PPC requires rellocation structures with addends.
287 sh_add(".rela.text", SHT_RELA
, 0, obj
->text_rellocation_count
*
288 sizeof (Elf32_Rela
), 6, 2, 4, sizeof (Elf32_Rela
));
292 * Link is the strtab section header index.
293 * Info is the index of the first symbol in the symbol table.
295 sh_add(".symtab", SHT_SYMTAB
, 0, (obj
->symbol_count
+ PDFS
) *
296 sizeof (Elf32_Sym
), 7, PDFS
- 1, 4, sizeof (Elf32_Sym
));
298 obj
->symbol_list_size
+= 1; /* Trailing \0 */
299 sh_add(".strtab", SHT_STRTAB
, 0, obj
->symbol_list_size
, 0, 0, 1, 0);
301 /* Section header string table */
302 save_struct(fp
, &shst
, SHSTRTABSIZE
);
303 save_struct(fp
, obj
->text
.code
, obj
->text
.size
); /* Text */
304 save_struct(fp
, obj
->data
.code
, obj
->data
.size
); /* Data */
305 /* Text rellocations */
306 for (i
= 0; i
< obj
->text_rellocation_count
; i
++) {
308 bzero(&rellocation
, sizeof (Elf32_Rel
));
309 rellocation
.r_offset
= obj
->text_rellocation_table
[i
].offset
;
310 switch (obj
->text_rellocation_table
[i
].type
) {
314 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
321 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
325 real_exception(interp
, NULL
, EXEC_ERROR
,
326 "Unknown text rellocation type: %d\n",
327 obj
->text_rellocation_table
[i
].type
);
330 save_struct(fp
, &rellocation
, sizeof (Elf32_Rel
));
333 bzero(&rel_addend
, sizeof (Elf32_Rela
));
334 rel_addend
.r_offset
= obj
->text_rellocation_table
[i
].offset
;
335 switch (obj
->text_rellocation_table
[i
].type
) {
339 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
346 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
348 rel_addend
.r_addend
= *((short *)
349 (&obj
->text
.code
[obj
->text_rellocation_table
[i
].offset
]))
351 rel_addend
.r_addend
+= *((short *)
353 obj
->text_rellocation_table
[i
].offset
+ 4]));
358 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
360 rel_addend
.r_addend
= *((short *)
361 (&obj
->text
.code
[obj
->text_rellocation_table
[i
].offset
]));
362 rel_addend
.r_addend
+= *((short *)
364 obj
->text_rellocation_table
[i
].offset
- 4])) << 16;
367 real_exception(interp
, NULL
, EXEC_ERROR
,
368 "Unknown text rellocation type: %d\n",
369 obj
->text_rellocation_table
[i
].type
);
372 save_struct(fp
, &rel_addend
, sizeof (Elf32_Rela
));
375 bzero(&rellocation
, sizeof (Elf32_Rel
));
376 rellocation
.r_offset
= obj
->text_rellocation_table
[i
].offset
;
377 switch (obj
->text_rellocation_table
[i
].type
) {
381 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
387 obj
->text_rellocation_table
[i
].symbol_number
+ PDFS
,
391 real_exception(interp
, NULL
, EXEC_ERROR
,
392 "Unknown text rellocation type: %d\n",
393 obj
->text_rellocation_table
[i
].type
);
396 save_struct(fp
, &rellocation
, sizeof (Elf32_Rel
));
401 bzero(&symlst
, sizeof (Elf32_Sym
));
402 save_struct(fp
, &symlst
, sizeof (Elf32_Sym
));
404 bzero(&symlst
, sizeof (Elf32_Sym
));
405 symlst
.st_info
= ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
);
407 save_struct(fp
, &symlst
, sizeof (Elf32_Sym
));
409 bzero(&symlst
, sizeof (Elf32_Sym
));
410 symlst
.st_info
= ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
);
412 save_struct(fp
, &symlst
, sizeof (Elf32_Sym
));
414 bzero(&symlst
, sizeof (Elf32_Sym
));
415 symlst
.st_info
= ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
);
417 save_struct(fp
, &symlst
, sizeof (Elf32_Sym
));
419 for (i
= 0; i
< obj
->symbol_count
; i
++) {
420 bzero(&symlst
, sizeof (Elf32_Sym
));
421 symlst
.st_name
= obj
->symbol_table
[i
].offset_list
+ 1;
422 switch (obj
->symbol_table
[i
].type
) {
424 symlst
.st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_FUNC
);
425 symlst
.st_size
= obj
->text
.size
;
426 symlst
.st_shndx
= 2; /* text */
429 symlst
.st_value
= obj
->symbol_table
[i
].value
;
430 symlst
.st_size
= obj
->data_size
[i
];
431 symlst
.st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_OBJECT
);
432 symlst
.st_shndx
= 3; /* data */
435 symlst
.st_value
= obj
->symbol_table
[i
].value
;
436 /* symlst.st_size = obj->data_size[i]; XXX daniel why? */
437 symlst
.st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_OBJECT
);
438 symlst
.st_shndx
= SHN_COMMON
;
441 symlst
.st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
);
444 real_exception(interp
, NULL
, EXEC_ERROR
, "Unknown symbol type: %d\n",
445 obj
->symbol_table
[i
].type
);
448 save_struct(fp
, &symlst
, sizeof (Elf32_Sym
));
452 for (i
= 0; i
< obj
->symbol_count
; i
++) {
453 fprintf(fp
, "%s", obj
->symbol_table
[i
].symbol
);
457 for (i
= 0; i
< (4 - obj
->symbol_list_size
% 4); i
++)
462 #endif /* EXEC_ELF */
467 Parrot_exec_save(PARROT_INTERP
, Parrot_exec_objfile_t
*obj
, const char *file
)
472 fp
= fopen(file
, "w");
474 fprintf(fp
, "\xFE\xED\xFA\xCE"); /* Header for Darwin */
483 for (i
= 0; i
< 5; i
++)
485 /* Sizeof text + data */
486 save_int(fp
, obj
->text
.size
+ obj
->data
.size
);
489 save_int(fp
, obj
->text
.size
+ obj
->data
.size
);
494 fprintf(fp
, "__text");
495 for (i
= 0; i
< 10; i
++)
497 fprintf(fp
, "__TEXT");
498 for (i
= 0; i
< 10; i
++)
502 save_int(fp
, obj
->text
.size
);
505 /* Offset of rellocation table. */
506 save_int(fp
, 0x144 + obj
->text
.size
+ obj
->data
.size
);
507 save_int(fp
, obj
->text_rellocation_count
);
508 save_int(fp
, 0x80000400);
511 fprintf(fp
, "__data");
512 for (i
= 0; i
< 10; i
++)
514 fprintf(fp
, "__DATA");
515 for (i
= 0; i
< 10; i
++)
518 save_int(fp
, obj
->text
.size
);
520 save_int(fp
, obj
->data
.size
);
521 /* Data file offset */
522 save_int(fp
, 0x144 + obj
->text
.size
);
524 for (i
= 0; i
< 5; i
++)
527 /* save_int(fp, obj->symbol_count * 0xc); */
529 /* Offset of stabs */
531 obj
->text
.size
+ obj
->data
.size
+ obj
->text_rellocation_count
* 0x8);
532 /* Number of stabs (symbol table) */
533 save_int(fp
, obj
->symbol_count
);
534 /* Offset of symbol list */
535 save_int(fp
, 0x144 + obj
->text
.size
+ obj
->data
.size
+
536 obj
->text_rellocation_count
* 0x8 + obj
->symbol_count
* 0xc);
537 /* Sizeof symbol list */
538 save_int(fp
, obj
->symbol_list_size
);
541 for (i
= 0; i
< 3; i
++)
543 save_int(fp
, obj
->symbol_count
);
544 save_int(fp
, obj
->symbol_count
);
545 for (i
= 0; i
< 13; i
++)
548 for (i
= 0; i
< obj
->text
.size
; i
++)
549 fprintf(fp
, "%c", obj
->text
.code
[i
]);
551 for (i
= 0; i
< obj
->data
.size
; i
++)
552 fprintf(fp
, "%c", obj
->data
.code
[i
]);
553 /* Text rellocations */
554 for (i
= obj
->text_rellocation_count
- 1; i
>= 0; i
--) {
555 save_int(fp
, obj
->text_rellocation_table
[i
].offset
);
556 save_short(fp
, obj
->text_rellocation_table
[i
].symbol_number
);
557 save_short(fp
, obj
->text_rellocation_table
[i
].type
);
560 for (i
= 0; i
< obj
->symbol_count
; i
++) {
561 save_int(fp
, obj
->symbol_table
[i
].offset_list
);
562 save_int(fp
, obj
->symbol_table
[i
].type
);
563 save_int(fp
, obj
->symbol_table
[i
].value
);
566 for (i
= 0; i
< obj
->symbol_count
; i
++) {
567 if (obj
->symbol_table
[i
].type
!= STYPE_GCC
)
568 fprintf(fp
, "_%s", obj
->symbol_table
[i
].symbol
);
570 fprintf(fp
, "%s", obj
->symbol_table
[i
].symbol
);
576 #endif /* EXEC_MACH_O */
581 # define TEXT_CODE 0x14 + (3 * 0x28)
582 # define DATA_CODE TEXT_CODE + obj->text.size
583 # define TEXT_RELOC DATA_CODE + obj->data.size
584 # define DATA_RELOC TEXT_RELOC + (obj->text_rellocation_count * 0xA)
585 # define SYMTAB DATA_RELOC + (obj->data_rellocation_count * 0xA)
588 Parrot_exec_save(PARROT_INTERP
, Parrot_exec_objfile_t
*obj
, const char *file
)
593 fp
= fopen(file
, "wb");
595 save_short(fp
, 0x14C); /* i386 */
596 save_short(fp
, 3); /* Number of sections */
597 save_int(fp
, Parrot_intval_time());
598 save_int(fp
, SYMTAB
);
599 save_int(fp
, obj
->symbol_count
);
601 save_short(fp
, 0x104); /* 32 bit LE, no line numbers */
603 fwrite(".text\0\0\0", 8, 1, fp
);
606 save_int(fp
, obj
->text
.size
);
607 save_int(fp
, TEXT_CODE
);
608 save_int(fp
, TEXT_RELOC
);
610 save_short(fp
, (short)obj
->text_rellocation_count
);
614 fwrite(".data\0\0\0", 8, 1, fp
);
617 save_int(fp
, obj
->data
.size
);
618 save_int(fp
, DATA_CODE
);
619 save_int(fp
, DATA_RELOC
);
621 save_short(fp
, (short)obj
->data_rellocation_count
);
625 fwrite(".bss\0\0\0\0", 8, 1, fp
);
628 save_int(fp
, obj
->bss
.size
);
637 for (i
= 0; i
< obj
->text
.size
; i
++)
638 fprintf(fp
, "%c", obj
->text
.code
[i
]);
640 for (i
= 0; i
< obj
->data
.size
; i
++)
641 fprintf(fp
, "%c", obj
->data
.code
[i
]);
642 /* Text rellocations */
643 for (i
= 0; i
< obj
->text_rellocation_count
; i
++) {
644 save_int(fp
, obj
->text_rellocation_table
[i
].offset
);
645 save_int(fp
, obj
->text_rellocation_table
[i
].symbol_number
);
646 switch (obj
->text_rellocation_table
[i
].type
) {
648 save_short(fp
, 0x14);
652 save_short(fp
, 0x06);
655 real_exception(interp
, NULL
, EXEC_ERROR
,
656 "Unknown text rellocation type: %d\n",
657 obj
->text_rellocation_table
[i
].type
);
662 for (i
= 0; i
< obj
->symbol_count
; i
++) {
664 save_int(fp
, obj
->symbol_table
[i
].offset_list
);
665 save_int(fp
, obj
->symbol_table
[i
].value
);
666 switch (obj
->symbol_table
[i
].type
) {
668 save_short(fp
, 1); /* .text */
669 save_short(fp
, 0x20);
672 save_short(fp
, 2); /* .data */
681 save_short(fp
, 0x20);
684 real_exception(interp
, NULL
, EXEC_ERROR
, "Unknown symbol type: %d\n",
685 obj
->symbol_table
[i
].type
);
688 putc(2, fp
); /* "extern" class */
692 save_int(fp
, obj
->symbol_list_size
);
693 for (i
= 0; i
< obj
->symbol_count
; i
++) {
694 if (obj
->symbol_table
[i
].type
!= STYPE_GCC
)
695 fprintf(fp
, "_%s", obj
->symbol_table
[i
].symbol
);
697 fprintf(fp
, "%s", obj
->symbol_table
[i
].symbol
);
703 #endif /* EXEC_COFF */
707 =item C<static void save_struct(FILE *fp, void *sp, size_t size)>
709 Writes the C<struct> C<sp> to the file.
716 save_struct(FILE *fp
, void *sp
, size_t size
)
720 for (i
= 0; i
< size
; i
++)
721 fprintf(fp
, "%c", ((char *)sp
)[i
]);
726 =item C<static void save_zero(FILE *fp)>
728 Writes 0 to the file.
737 fprintf(fp
, "%c", 0);
744 =item C<static void save_int(FILE *fp, int i)>
746 Writes C<i> to the file.
753 save_int(FILE *fp
, int i
)
755 fprintf(fp
, "%c%c%c%c", (char)(i
>> 24), (char)(i
>> 16),
756 (char)(i
>> 8), (char)i
);
761 =item C<static void save_short(FILE *fp, short s)>
763 Writes C<s> to the file.
770 save_short(FILE *fp
, short s
)
772 fprintf(fp
, "%c%c", (char)(s
>> 8), (char)s
);
775 #else /* PARROT_BIGENDIAN */
778 save_short(FILE *fp
, short s
)
780 fprintf(fp
, "%c%c", (char)s
, (char)(s
>> 8));
784 save_int(FILE *fp
, int i
)
786 fprintf(fp
, "%c%c%c%c", (char)i
, (char)(i
>> 8),
787 (char)(i
>> 16), (char)(i
>> 24));
790 #endif /* PARROT_BIGENDIAN */
798 F<include/parrot/exec.h>, F<src/exec_save.h>, F<src/exec.c>
799 and F<src/exec_start.c>.
803 Initial version by Daniel Grunblatt on 2003.6.9.
812 * c-file-style: "parrot"
814 * vim: expandtab shiftwidth=4: