Merge tag 'nasm-2.15'
[nasm.git] / output / codeview.c
blobbe3fd27a2827710a43348421a45a49a9e3db46ef
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2020 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * codeview.c Codeview Debug Format support for COFF
38 #include "version.h"
39 #include "compiler.h"
42 #include "nasm.h"
43 #include "nasmlib.h"
44 #include "error.h"
45 #include "preproc.h"
46 #include "saa.h"
47 #include "hashtbl.h"
48 #include "outlib.h"
49 #include "pecoff.h"
50 #include "md5.h"
52 static void cv8_init(void);
53 static void cv8_linenum(const char *filename, int32_t linenumber,
54 int32_t segto);
55 static void cv8_deflabel(char *name, int32_t segment, int64_t offset,
56 int is_global, char *special);
57 static void cv8_typevalue(int32_t type);
58 static void cv8_output(int type, void *param);
59 static void cv8_cleanup(void);
61 const struct dfmt df_cv8 = {
62 "Codeview 8+", /* .fullname */
63 "cv8", /* .shortname */
64 cv8_init, /* .init */
65 cv8_linenum, /* .linenum */
66 cv8_deflabel, /* .debug_deflabel */
67 null_debug_directive, /* .debug_directive */
68 cv8_typevalue, /* .debug_typevalue */
69 cv8_output, /* .debug_output */
70 cv8_cleanup, /* .cleanup */
71 NULL /* pragma list */
74 /*******************************************************************************
75 * dfmt callbacks
76 ******************************************************************************/
77 struct source_file;
79 struct source_file {
80 const char *filename;
81 char *fullname;
82 uint32_t fullnamelen;
84 struct source_file *next;
86 uint32_t filetbl_off;
87 uint32_t sourcetbl_off;
89 struct SAA *lines;
90 uint32_t num_lines;
92 unsigned char md5sum[MD5_HASHBYTES];
95 struct linepair {
96 uint32_t file_offset;
97 uint32_t linenumber;
100 enum symbol_type {
101 SYMTYPE_CODE,
102 SYMTYPE_PROC,
103 SYMTYPE_LDATA,
104 SYMTYPE_GDATA,
106 SYMTYPE_MAX
109 struct cv8_symbol {
110 enum symbol_type type;
111 char *name;
113 uint32_t secrel;
114 uint16_t section;
115 uint32_t size;
116 uint32_t typeindex;
118 enum symtype {
119 TYPE_UNREGISTERED = 0x0000, /* T_NOTYPE */
120 TYPE_BYTE = 0x0020,
121 TYPE_WORD = 0x0021,
122 TYPE_DWORD= 0x0022,
123 TYPE_QUAD = 0x0023,
125 TYPE_REAL32 = 0x0040,
126 TYPE_REAL64 = 0x0041,
127 TYPE_REAL80 = 0x0042,
128 TYPE_REAL128= 0x0043,
129 TYPE_REAL256= 0x0044,
130 TYPE_REAL512= 0x0045
131 } symtype;
134 struct cv8_state {
135 int symbol_sect;
136 int type_sect;
138 uint32_t text_offset;
140 struct source_file *source_files, **source_files_tail;
141 const char *last_filename;
142 struct source_file *last_source_file;
143 struct hash_table file_hash;
144 unsigned num_files;
145 uint32_t total_filename_len;
148 unsigned total_lines;
150 struct SAA *symbols;
151 struct cv8_symbol *last_sym;
152 unsigned num_syms[SYMTYPE_MAX];
153 unsigned symbol_lengths;
154 unsigned total_syms;
156 struct {
157 char *name;
158 size_t namebytes;
159 } outfile;
161 struct cv8_state cv8_state;
163 static void cv8_init(void)
165 const uint32_t sect_flags = IMAGE_SCN_MEM_READ |
166 IMAGE_SCN_MEM_DISCARDABLE |
167 IMAGE_SCN_CNT_INITIALIZED_DATA |
168 IMAGE_SCN_ALIGN_1BYTES;
170 cv8_state.symbol_sect = coff_make_section(".debug$S", sect_flags);
171 cv8_state.type_sect = coff_make_section(".debug$T", sect_flags);
173 cv8_state.text_offset = 0;
175 cv8_state.source_files = NULL;
176 cv8_state.source_files_tail = &cv8_state.source_files;
178 cv8_state.num_files = 0;
179 cv8_state.total_filename_len = 0;
181 cv8_state.total_lines = 0;
183 cv8_state.symbols = saa_init(sizeof(struct cv8_symbol));
184 cv8_state.last_sym = NULL;
187 static struct source_file *register_file(const char *filename);
188 static struct coff_Section *find_section(int32_t segto);
190 static void cv8_linenum(const char *filename, int32_t linenumber,
191 int32_t segto)
193 struct coff_Section *s;
194 struct linepair *li;
195 struct source_file *file;
197 file = register_file(filename);
199 s = find_section(segto);
200 if (s == NULL)
201 return;
203 if ((s->flags & IMAGE_SCN_MEM_EXECUTE) == 0)
204 return;
206 li = saa_wstruct(file->lines);
207 li->file_offset = cv8_state.text_offset;
208 li->linenumber = linenumber;
210 file->num_lines++;
211 cv8_state.total_lines++;
214 static void cv8_deflabel(char *name, int32_t segment, int64_t offset,
215 int is_global, char *special)
217 struct cv8_symbol *sym;
218 struct coff_Section *s;
220 (void)special;
222 s = find_section(segment);
223 if (s == NULL)
224 return;
226 sym = saa_wstruct(cv8_state.symbols);
228 if (s->flags & IMAGE_SCN_MEM_EXECUTE)
229 sym->type = is_global ? SYMTYPE_PROC : SYMTYPE_CODE;
230 else
231 sym->type = is_global ? SYMTYPE_GDATA : SYMTYPE_LDATA;
232 cv8_state.num_syms[sym->type]++;
233 cv8_state.total_syms++;
235 sym->section = segment;
236 sym->secrel = offset;
237 sym->symtype = TYPE_UNREGISTERED;
238 sym->size = 0;
239 sym->typeindex = 0;
241 sym->name = nasm_strdup(name);
242 cv8_state.symbol_lengths += strlen(sym->name) + 1;
244 if (cv8_state.last_sym && cv8_state.last_sym->section == segment)
245 cv8_state.last_sym->size = offset - cv8_state.last_sym->secrel;
246 cv8_state.last_sym = sym;
249 static void cv8_typevalue(int32_t type)
251 if (!cv8_state.last_sym)
252 return;
253 if (cv8_state.last_sym->symtype != TYPE_UNREGISTERED)
254 return;
256 switch (TYM_TYPE(type)) {
257 case TY_BYTE:
258 cv8_state.last_sym->symtype = TYPE_BYTE;
259 break;
260 case TY_WORD:
261 cv8_state.last_sym->symtype = TYPE_WORD;
262 break;
263 case TY_DWORD:
264 cv8_state.last_sym->symtype = TYPE_DWORD;
265 break;
266 case TY_QWORD:
267 cv8_state.last_sym->symtype = TYPE_QUAD;
268 break;
269 case TY_FLOAT:
270 cv8_state.last_sym->symtype = TYPE_REAL32;
271 break;
272 case TY_TBYTE:
273 cv8_state.last_sym->symtype = TYPE_REAL80;
274 break;
275 case TY_OWORD:
276 cv8_state.last_sym->symtype = TYPE_REAL128;
277 break;
278 case TY_YWORD:
279 cv8_state.last_sym->symtype = TYPE_REAL256;
280 break;
281 case TY_ZWORD:
282 cv8_state.last_sym->symtype = TYPE_REAL512;
283 break;
284 case TY_UNKNOWN:
285 break;
286 case TY_LABEL:
287 break;
291 static void cv8_output(int type, void *param)
293 struct coff_DebugInfo *dinfo = param;
295 (void)type;
297 if (dinfo->section && dinfo->section->name &&
298 !strncmp(dinfo->section->name, ".text", 5))
299 cv8_state.text_offset += dinfo->size;
302 static void build_symbol_table(struct coff_Section *const sect);
303 static void build_type_table(struct coff_Section *const sect);
305 static void cv8_cleanup(void)
307 struct cv8_symbol *sym;
308 struct source_file *file;
310 struct coff_Section *symbol_sect = coff_sects[cv8_state.symbol_sect];
311 struct coff_Section *type_sect = coff_sects[cv8_state.type_sect];
313 cv8_state.outfile.name = nasm_realpath(outname);
314 cv8_state.outfile.namebytes = strlen(cv8_state.outfile.name) + 1;
316 build_symbol_table(symbol_sect);
317 build_type_table(type_sect);
319 list_for_each(file, cv8_state.source_files) {
320 nasm_free(file->fullname);
321 saa_free(file->lines);
322 free(file);
324 hash_free(&cv8_state.file_hash);
326 saa_rewind(cv8_state.symbols);
327 while ((sym = saa_rstruct(cv8_state.symbols)))
328 nasm_free(sym->name);
329 saa_free(cv8_state.symbols);
331 nasm_free(cv8_state.outfile.name);
334 /*******************************************************************************
335 * implementation
336 ******************************************************************************/
337 static void calc_md5(const char *const filename,
338 unsigned char sum[MD5_HASHBYTES])
340 int success = 0;
341 unsigned char *file_buf;
342 FILE *f;
343 MD5_CTX ctx;
345 f = pp_input_fopen(filename, NF_BINARY);
346 if (!f)
347 goto done;
349 file_buf = nasm_zalloc(BUFSIZ);
351 MD5Init(&ctx);
352 while (!feof(f)) {
353 size_t i = fread(file_buf, 1, BUFSIZ, f);
354 if (ferror(f))
355 goto done_0;
356 else if (i == 0)
357 break;
358 MD5Update(&ctx, file_buf, i);
360 MD5Final(sum, &ctx);
362 success = 1;
363 done_0:
364 nasm_free(file_buf);
365 fclose(f);
366 done:
367 if (!success) {
368 nasm_nonfatal("unable to hash file %s. "
369 "Debug information may be unavailable.",
370 filename);
372 return;
375 static struct source_file *register_file(const char *filename)
377 struct source_file *file;
378 void **filep;
379 char *fullpath;
380 struct hash_insert hi;
383 * The common case is that we are invoked with the same filename
384 * as we were last time. Make this a pointer comparison: this is
385 * safe because the NASM core code allocates each filename once
386 * and never frees it.
388 if (likely(cv8_state.last_filename == filename))
389 return cv8_state.last_source_file;
391 cv8_state.last_filename = filename;
393 filep = hash_find(&cv8_state.file_hash, filename, &hi);
394 if (likely(filep)) {
395 file = *filep;
396 } else {
397 /* New filename encounter */
399 fullpath = nasm_realpath(filename);
401 file = nasm_zalloc(sizeof(*file));
403 file->filename = filename;
404 file->fullname = fullpath;
405 file->fullnamelen = strlen(fullpath);
406 file->lines = saa_init(sizeof(struct linepair));
407 *cv8_state.source_files_tail = file;
408 cv8_state.source_files_tail = &file->next;
409 calc_md5(fullpath, file->md5sum);
411 hash_add(&hi, filename, file);
413 cv8_state.num_files++;
414 cv8_state.total_filename_len += file->fullnamelen + 1;
417 cv8_state.last_source_file = file;
418 return file;
421 static struct coff_Section *find_section(int32_t segto)
423 int i;
425 for (i = 0; i < coff_nsects; i++) {
426 struct coff_Section *sec;
428 sec = coff_sects[i];
429 if (segto == sec->index)
430 return sec;
432 return NULL;
435 static void register_reloc(struct coff_Section *const sect,
436 char *sym, uint32_t addr, uint16_t type)
438 struct coff_Reloc *r;
439 struct coff_Section *sec;
440 uint32_t i;
442 r = *sect->tail = nasm_malloc(sizeof(struct coff_Reloc));
443 sect->tail = &r->next;
444 r->next = NULL;
445 sect->nrelocs++;
447 r->address = addr;
448 r->symbase = SECT_SYMBOLS;
449 r->type = type;
451 r->symbol = 0;
452 for (i = 0; i < (uint32_t)coff_nsects; i++) {
453 sec = coff_sects[i];
454 if (!strcmp(sym, sec->name)) {
455 return;
457 r->symbol += 2;
460 saa_rewind(coff_syms);
461 for (i = 0; i < coff_nsyms; i++) {
462 struct coff_Symbol *s = saa_rstruct(coff_syms);
463 r->symbol++;
464 if (s->strpos == -1 && !strcmp(sym, s->name)) {
465 return;
466 } else if (s->strpos != -1) {
467 int res;
468 char *symname;
470 symname = nasm_malloc(s->namlen + 1);
471 saa_fread(coff_strs, s->strpos-4, symname, s->namlen);
472 symname[s->namlen] = '\0';
473 res = strcmp(sym, symname);
474 nasm_free(symname);
475 if (!res)
476 return;
479 nasm_panic("codeview: relocation for unregistered symbol: %s", sym);
482 static inline void section_write32(struct coff_Section *sect, uint32_t val)
484 saa_write32(sect->data, val);
485 sect->len += 4;
488 static inline void section_write16(struct coff_Section *sect, uint16_t val)
490 saa_write16(sect->data, val);
491 sect->len += 2;
494 static inline void section_write8(struct coff_Section *sect, uint8_t val)
496 saa_write8(sect->data, val);
497 sect->len++;
500 static inline void section_wbytes(struct coff_Section *sect, const void *buf,
501 size_t len)
503 saa_wbytes(sect->data, buf, len);
504 sect->len += len;
507 static void write_filename_table(struct coff_Section *const sect)
509 uint32_t field_length;
510 uint32_t tbl_off = 1; /* offset starts at 1 to skip NULL entry */
511 struct source_file *file;
513 nasm_assert(cv8_state.source_files != NULL);
514 nasm_assert(cv8_state.num_files > 0);
515 nasm_assert(cv8_state.total_filename_len > 0);
517 field_length = 1 + cv8_state.total_filename_len;
519 section_write32(sect, 0x000000F3);
520 section_write32(sect, field_length);
522 section_write8(sect, 0);
524 list_for_each(file, cv8_state.source_files) {
525 section_wbytes(sect, file->fullname, file->fullnamelen + 1);
526 file->filetbl_off = tbl_off;
527 tbl_off += file->fullnamelen + 1;
531 static void write_sourcefile_table(struct coff_Section *const sect)
533 const uint32_t entry_size = 4 + 2 + MD5_HASHBYTES + 2;
535 uint32_t field_length = 0;
536 uint32_t tbl_off = 0;
537 struct source_file *file;
539 field_length = entry_size * cv8_state.num_files;
541 section_write32(sect, 0x000000F4);
542 section_write32(sect, field_length);
544 list_for_each(file, cv8_state.source_files) {
545 nasm_assert(file->filetbl_off > 0);
546 section_write32(sect, file->filetbl_off);
547 section_write16(sect, 0x0110);
548 section_wbytes(sect, file->md5sum, MD5_HASHBYTES);
549 section_write16(sect, 0);
551 file->sourcetbl_off = tbl_off;
552 tbl_off += entry_size;
556 static void write_linenumber_table(struct coff_Section *const sect)
558 const uint32_t file_field_len = 12;
559 const uint32_t line_field_len = 8;
561 int i;
562 uint32_t field_length = 0;
563 size_t field_base;
564 struct source_file *file;
565 struct coff_Section *s;
567 for (i = 0; i < coff_nsects; i++) {
568 if (!strncmp(coff_sects[i]->name, ".text", 5))
569 break;
572 if (i == coff_nsects)
573 return;
574 s = coff_sects[i];
576 field_length = 12;
577 field_length += (cv8_state.num_files * file_field_len);
578 field_length += (cv8_state.total_lines * line_field_len);
580 section_write32(sect, 0x000000F2);
581 section_write32(sect, field_length);
583 field_base = sect->len;
584 section_write32(sect, 0); /* SECREL, updated by relocation */
585 section_write16(sect, 0); /* SECTION, updated by relocation*/
586 section_write16(sect, 0); /* pad */
587 section_write32(sect, s->len);
589 register_reloc(sect, ".text", field_base,
590 win64 ? IMAGE_REL_AMD64_SECREL : IMAGE_REL_I386_SECREL);
592 register_reloc(sect, ".text", field_base + 4,
593 win64 ? IMAGE_REL_AMD64_SECTION : IMAGE_REL_I386_SECTION);
595 list_for_each(file, cv8_state.source_files) {
596 struct linepair *li;
598 /* source mapping */
599 section_write32(sect, file->sourcetbl_off);
600 section_write32(sect, file->num_lines);
601 section_write32(sect, file_field_len + (file->num_lines * line_field_len));
603 /* the pairs */
604 saa_rewind(file->lines);
605 while ((li = saa_rstruct(file->lines))) {
606 section_write32(sect, li->file_offset);
607 section_write32(sect, li->linenumber |= 0x80000000);
612 static uint32_t write_symbolinfo_obj(struct coff_Section *sect)
614 uint32_t obj_len;
616 obj_len = 2 + 4 + cv8_state.outfile.namebytes;
618 section_write16(sect, obj_len);
619 section_write16(sect, 0x1101);
620 section_write32(sect, 0); /* ASM language */
621 section_wbytes(sect, cv8_state.outfile.name, cv8_state.outfile.namebytes);
623 return obj_len;
626 static uint32_t write_symbolinfo_properties(struct coff_Section *sect,
627 const char *const creator_str)
629 /* https://github.com/Microsoft/microsoft-pdb/blob/1d60e041/include/cvinfo.h#L3313 */
630 uint32_t creator_len;
632 creator_len = 2 + 4 + 2 + 3*2 + 3*2 + strlen(creator_str)+1 + 2;
635 * We used to use a language ID of 3 for "MASM", since it's closest of the
636 * options available; however, BinScope from WACK (the Windows Application
637 * Certification Kit) tests for specific minimum MASM versions and trying to
638 * match an increasing sequence of random MASM version/build numbers seems
639 * like a fool's errand.
641 * Instead, use a different language ID (NASM is, after all, not MASM
642 * syntax) and just write the actual NASM version number. BinScope appears
643 * to be happy with that.
646 section_write16(sect, creator_len);
647 section_write16(sect, 0x1116);
648 section_write32(sect, 'N'); /* language: 'N' (0x4e) for "NASM"; flags are 0 */
649 if (win64)
650 section_write16(sect, 0x00D0); /* machine */
651 else if (win32)
652 section_write16(sect, 0x0006); /* machine */
653 else
654 nasm_panic("neither win32 nor win64 are set!");
655 section_write16(sect, 0); /* verFEMajor */
656 section_write16(sect, 0); /* verFEMinor */
657 section_write16(sect, 0); /* verFEBuild */
659 /* BinScope/WACK insist on version >= 8.0.50727 */
660 section_write16(sect, NASM_MAJOR_VER); /* verMajor */
661 section_write16(sect, NASM_MINOR_VER); /* verMinor */
662 section_write16(sect, NASM_SUBMINOR_VER*100 + NASM_PATCHLEVEL_VER); /* verBuild */
664 section_wbytes(sect, creator_str, strlen(creator_str)+1); /* verSt */
666 * normally there would be key/value pairs here, but they aren't
667 * necessary. They are terminated by 2B
669 section_write16(sect, 0);
671 return creator_len;
674 static uint32_t write_symbolinfo_symbols(struct coff_Section *sect)
676 uint32_t len = 0, field_len;
677 uint32_t field_base;
678 struct cv8_symbol *sym;
680 saa_rewind(cv8_state.symbols);
681 while ((sym = saa_rstruct(cv8_state.symbols))) {
682 switch (sym->type) {
683 case SYMTYPE_LDATA:
684 case SYMTYPE_GDATA:
685 field_len = 12 + strlen(sym->name) + 1;
686 len += field_len - 2;
687 section_write16(sect, field_len);
688 if (sym->type == SYMTYPE_LDATA)
689 section_write16(sect, 0x110C);
690 else
691 section_write16(sect, 0x110D);
692 section_write32(sect, sym->symtype);
694 field_base = sect->len;
695 section_write32(sect, 0); /* SECREL */
696 section_write16(sect, 0); /* SECTION */
697 break;
698 case SYMTYPE_PROC:
699 case SYMTYPE_CODE:
700 field_len = 9 + strlen(sym->name) + 1;
701 len += field_len - 2;
702 section_write16(sect, field_len);
703 section_write16(sect, 0x1105);
705 field_base = sect->len;
706 section_write32(sect, 0); /* SECREL */
707 section_write16(sect, 0); /* SECTION */
708 section_write8(sect, 0); /* FLAG */
709 break;
710 default:
711 nasm_panic("unknown symbol type");
714 section_wbytes(sect, sym->name, strlen(sym->name) + 1);
716 register_reloc(sect, sym->name, field_base,
717 win64 ? IMAGE_REL_AMD64_SECREL :
718 IMAGE_REL_I386_SECREL);
719 register_reloc(sect, sym->name, field_base + 4,
720 win64 ? IMAGE_REL_AMD64_SECTION :
721 IMAGE_REL_I386_SECTION);
724 return len;
727 static void write_symbolinfo_table(struct coff_Section *const sect)
729 static const char creator_str[] = "The Netwide Assembler " NASM_VER;
730 uint32_t obj_length, creator_length, sym_length;
731 uint32_t field_length = 0, out_len;
733 nasm_assert(cv8_state.outfile.namebytes);
735 /* signature, language, outfile NULL */
736 obj_length = 2 + 4 + cv8_state.outfile.namebytes;
737 creator_length = 2 + 4 + 2 + 3*2 + 3*2 + strlen(creator_str)+1 + 2;
739 sym_length = ( cv8_state.num_syms[SYMTYPE_CODE] * 7) +
740 ( cv8_state.num_syms[SYMTYPE_PROC] * 7) +
741 ( cv8_state.num_syms[SYMTYPE_LDATA] * 10) +
742 ( cv8_state.num_syms[SYMTYPE_GDATA] * 10) +
743 cv8_state.symbol_lengths;
745 field_length = 2 + obj_length +
746 2 + creator_length +
747 (4 * cv8_state.total_syms) + sym_length;
749 section_write32(sect, 0x000000F1);
750 section_write32(sect, field_length);
752 /* for sub fields, length preceeds type */
754 out_len = write_symbolinfo_obj(sect);
755 nasm_assert(out_len == obj_length);
757 out_len = write_symbolinfo_properties(sect, creator_str);
758 nasm_assert(out_len == creator_length);
760 out_len = write_symbolinfo_symbols(sect);
761 nasm_assert(out_len == sym_length);
764 static inline void align4_table(struct coff_Section *const sect)
766 unsigned diff;
767 uint32_t zero = 0;
768 struct SAA *data = sect->data;
770 if (data->wptr % 4 == 0)
771 return;
773 diff = 4 - (data->wptr % 4);
774 if (diff)
775 section_wbytes(sect, &zero, diff);
778 static void build_symbol_table(struct coff_Section *const sect)
780 section_write32(sect, 0x00000004);
782 write_filename_table(sect);
783 align4_table(sect);
784 write_sourcefile_table(sect);
785 align4_table(sect);
786 write_linenumber_table(sect);
787 align4_table(sect);
788 write_symbolinfo_table(sect);
789 align4_table(sect);
792 static void build_type_table(struct coff_Section *const sect)
794 uint32_t field_len;
795 uint32_t typeindex = 0x1000;
796 uint32_t idx_arglist;
798 section_write32(sect, 0x00000004);
800 /* empty argument list type */
801 field_len = 2 + 4;
802 section_write16(sect, field_len);
803 section_write16(sect, 0x1201); /* ARGLIST */
804 section_write32(sect, 0); /* num params */
805 idx_arglist = typeindex++;
807 /* procedure type: void proc(void) */
808 field_len = 2 + 4 + 1 + 1 + 2 + 4;
809 section_write16(sect, field_len);
810 section_write16(sect, 0x1008); /* PROC type */
812 section_write32(sect, 0x00000003); /* return type VOID */
813 section_write8(sect, 0); /* calling convention (default) */
814 section_write8(sect, 0); /* function attributes */
815 section_write16(sect, 0); /* # params */
816 section_write32(sect, idx_arglist); /* argument list type */
817 /* idx_voidfunc = typeindex++; */