| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827 |
- /* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2017 The NASM Authors - All Rights Reserved
- * See the file AUTHORS included with the NASM distribution for
- * the specific copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following
- * conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ----------------------------------------------------------------------- */
- /*
- * codeview.c Codeview Debug Format support for COFF
- */
- #include "version.h"
- #include "compiler.h"
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include "nasm.h"
- #include "nasmlib.h"
- #include "error.h"
- #include "preproc.h"
- #include "saa.h"
- #include "hashtbl.h"
- #include "outlib.h"
- #include "pecoff.h"
- #include "md5.h"
- static void cv8_init(void);
- static void cv8_linenum(const char *filename, int32_t linenumber,
- int32_t segto);
- static void cv8_deflabel(char *name, int32_t segment, int64_t offset,
- int is_global, char *special);
- static void cv8_typevalue(int32_t type);
- static void cv8_output(int type, void *param);
- static void cv8_cleanup(void);
- const struct dfmt df_cv8 = {
- "Codeview 8", /* .fullname */
- "cv8", /* .shortname */
- cv8_init, /* .init */
- cv8_linenum, /* .linenum */
- cv8_deflabel, /* .debug_deflabel */
- null_debug_directive, /* .debug_directive */
- cv8_typevalue, /* .debug_typevalue */
- cv8_output, /* .debug_output */
- cv8_cleanup, /* .cleanup */
- NULL /* pragma list */
- };
- /*******************************************************************************
- * dfmt callbacks
- ******************************************************************************/
- struct source_file;
- struct source_file {
- const char *filename;
- char *fullname;
- uint32_t fullnamelen;
- struct source_file *next;
- uint32_t filetbl_off;
- uint32_t sourcetbl_off;
- struct SAA *lines;
- uint32_t num_lines;
- unsigned char md5sum[MD5_HASHBYTES];
- };
- struct linepair {
- uint32_t file_offset;
- uint32_t linenumber;
- };
- enum symbol_type {
- SYMTYPE_CODE,
- SYMTYPE_PROC,
- SYMTYPE_LDATA,
- SYMTYPE_GDATA,
- SYMTYPE_MAX
- };
- struct cv8_symbol {
- enum symbol_type type;
- char *name;
- uint32_t secrel;
- uint16_t section;
- uint32_t size;
- uint32_t typeindex;
- enum symtype {
- TYPE_UNREGISTERED = 0x0000, /* T_NOTYPE */
- TYPE_BYTE = 0x0020,
- TYPE_WORD = 0x0021,
- TYPE_DWORD= 0x0022,
- TYPE_QUAD = 0x0023,
- TYPE_REAL32 = 0x0040,
- TYPE_REAL64 = 0x0041,
- TYPE_REAL80 = 0x0042,
- TYPE_REAL128= 0x0043,
- TYPE_REAL256= 0x0044,
- TYPE_REAL512= 0x0045
- } symtype;
- };
- struct cv8_state {
- int symbol_sect;
- int type_sect;
- uint32_t text_offset;
- struct source_file *source_files, **source_files_tail;
- const char *last_filename;
- struct source_file *last_source_file;
- struct hash_table file_hash;
- unsigned num_files;
- uint32_t total_filename_len;
- unsigned total_lines;
- struct SAA *symbols;
- struct cv8_symbol *last_sym;
- unsigned num_syms[SYMTYPE_MAX];
- unsigned symbol_lengths;
- unsigned total_syms;
- struct {
- char *name;
- size_t namebytes;
- } outfile;
- };
- struct cv8_state cv8_state;
- static void cv8_init(void)
- {
- const uint32_t sect_flags = IMAGE_SCN_MEM_READ |
- IMAGE_SCN_MEM_DISCARDABLE |
- IMAGE_SCN_CNT_INITIALIZED_DATA |
- IMAGE_SCN_ALIGN_1BYTES;
- cv8_state.symbol_sect = coff_make_section(".debug$S", sect_flags);
- cv8_state.type_sect = coff_make_section(".debug$T", sect_flags);
- cv8_state.text_offset = 0;
- cv8_state.source_files = NULL;
- cv8_state.source_files_tail = &cv8_state.source_files;
- hash_init(&cv8_state.file_hash, HASH_MEDIUM);
- cv8_state.num_files = 0;
- cv8_state.total_filename_len = 0;
- cv8_state.total_lines = 0;
- cv8_state.symbols = saa_init(sizeof(struct cv8_symbol));
- cv8_state.last_sym = NULL;
- }
- static struct source_file *register_file(const char *filename);
- static struct coff_Section *find_section(int32_t segto);
- static void cv8_linenum(const char *filename, int32_t linenumber,
- int32_t segto)
- {
- struct coff_Section *s;
- struct linepair *li;
- struct source_file *file;
- file = register_file(filename);
- s = find_section(segto);
- if (s == NULL)
- return;
- if ((s->flags & IMAGE_SCN_MEM_EXECUTE) == 0)
- return;
- li = saa_wstruct(file->lines);
- li->file_offset = cv8_state.text_offset;
- li->linenumber = linenumber;
- file->num_lines++;
- cv8_state.total_lines++;
- }
- static void cv8_deflabel(char *name, int32_t segment, int64_t offset,
- int is_global, char *special)
- {
- struct cv8_symbol *sym;
- struct coff_Section *s;
- (void)special;
- s = find_section(segment);
- if (s == NULL)
- return;
- sym = saa_wstruct(cv8_state.symbols);
- if (s->flags & IMAGE_SCN_MEM_EXECUTE)
- sym->type = is_global ? SYMTYPE_PROC : SYMTYPE_CODE;
- else
- sym->type = is_global ? SYMTYPE_GDATA : SYMTYPE_LDATA;
- cv8_state.num_syms[sym->type]++;
- cv8_state.total_syms++;
- sym->section = segment;
- sym->secrel = offset;
- sym->symtype = TYPE_UNREGISTERED;
- sym->size = 0;
- sym->typeindex = 0;
- sym->name = nasm_strdup(name);
- cv8_state.symbol_lengths += strlen(sym->name) + 1;
- if (cv8_state.last_sym && cv8_state.last_sym->section == segment)
- cv8_state.last_sym->size = offset - cv8_state.last_sym->secrel;
- cv8_state.last_sym = sym;
- }
- static void cv8_typevalue(int32_t type)
- {
- if (!cv8_state.last_sym)
- return;
- if (cv8_state.last_sym->symtype != TYPE_UNREGISTERED)
- return;
- switch (TYM_TYPE(type)) {
- case TY_BYTE:
- cv8_state.last_sym->symtype = TYPE_BYTE;
- break;
- case TY_WORD:
- cv8_state.last_sym->symtype = TYPE_WORD;
- break;
- case TY_DWORD:
- cv8_state.last_sym->symtype = TYPE_DWORD;
- break;
- case TY_QWORD:
- cv8_state.last_sym->symtype = TYPE_QUAD;
- break;
- case TY_FLOAT:
- cv8_state.last_sym->symtype = TYPE_REAL32;
- break;
- case TY_TBYTE:
- cv8_state.last_sym->symtype = TYPE_REAL80;
- break;
- case TY_OWORD:
- cv8_state.last_sym->symtype = TYPE_REAL128;
- break;
- case TY_YWORD:
- cv8_state.last_sym->symtype = TYPE_REAL256;
- break;
- case TY_ZWORD:
- cv8_state.last_sym->symtype = TYPE_REAL512;
- break;
- case TY_UNKNOWN:
- break;
- case TY_LABEL:
- break;
- }
- }
- static void cv8_output(int type, void *param)
- {
- struct coff_DebugInfo *dinfo = param;
- (void)type;
- if (dinfo->section && dinfo->section->name &&
- !strncmp(dinfo->section->name, ".text", 5))
- cv8_state.text_offset += dinfo->size;
- }
- static void build_symbol_table(struct coff_Section *const sect);
- static void build_type_table(struct coff_Section *const sect);
- static void cv8_cleanup(void)
- {
- struct cv8_symbol *sym;
- struct source_file *file;
- struct coff_Section *symbol_sect = coff_sects[cv8_state.symbol_sect];
- struct coff_Section *type_sect = coff_sects[cv8_state.type_sect];
- cv8_state.outfile.name = nasm_realpath(outname);
- cv8_state.outfile.namebytes = strlen(cv8_state.outfile.name) + 1;
- build_symbol_table(symbol_sect);
- build_type_table(type_sect);
- list_for_each(file, cv8_state.source_files) {
- nasm_free(file->fullname);
- saa_free(file->lines);
- free(file);
- }
- hash_free(&cv8_state.file_hash);
- saa_rewind(cv8_state.symbols);
- while ((sym = saa_rstruct(cv8_state.symbols)))
- nasm_free(sym->name);
- saa_free(cv8_state.symbols);
- nasm_free(cv8_state.outfile.name);
- }
- /*******************************************************************************
- * implementation
- ******************************************************************************/
- static void calc_md5(const char *const filename,
- unsigned char sum[MD5_HASHBYTES])
- {
- int success = 0;
- unsigned char *file_buf;
- FILE *f;
- MD5_CTX ctx;
- f = pp_input_fopen(filename, NF_BINARY);
- if (!f)
- goto done;
- file_buf = nasm_zalloc(BUFSIZ);
- MD5Init(&ctx);
- while (!feof(f)) {
- size_t i = fread(file_buf, 1, BUFSIZ, f);
- if (ferror(f))
- goto done_0;
- else if (i == 0)
- break;
- MD5Update(&ctx, file_buf, i);
- }
- MD5Final(sum, &ctx);
- success = 1;
- done_0:
- nasm_free(file_buf);
- fclose(f);
- done:
- if (!success) {
- nasm_error(ERR_NONFATAL, "unable to hash file %s. "
- "Debug information may be unavailable.\n",
- filename);
- }
- return;
- }
- static struct source_file *register_file(const char *filename)
- {
- struct source_file *file;
- void **filep;
- char *fullpath;
- struct hash_insert hi;
- /*
- * The common case is that we are invoked with the same filename
- * as we were last time. Make this a pointer comparison: this is
- * safe because the NASM core code allocates each filename once
- * and never frees it.
- */
- if (likely(cv8_state.last_filename == filename))
- return cv8_state.last_source_file;
- cv8_state.last_filename = filename;
- filep = hash_find(&cv8_state.file_hash, filename, &hi);
- if (likely(filep)) {
- file = *filep;
- } else {
- /* New filename encounter */
- fullpath = nasm_realpath(filename);
- file = nasm_zalloc(sizeof(*file));
- file->filename = filename;
- file->fullname = fullpath;
- file->fullnamelen = strlen(fullpath);
- file->lines = saa_init(sizeof(struct linepair));
- *cv8_state.source_files_tail = file;
- cv8_state.source_files_tail = &file->next;
- calc_md5(fullpath, file->md5sum);
- hash_add(&hi, filename, file);
- cv8_state.num_files++;
- cv8_state.total_filename_len += file->fullnamelen + 1;
- }
- cv8_state.last_source_file = file;
- return file;
- }
- static struct coff_Section *find_section(int32_t segto)
- {
- int i;
- for (i = 0; i < coff_nsects; i++) {
- struct coff_Section *sec;
- sec = coff_sects[i];
- if (segto == sec->index)
- return sec;
- }
- return NULL;
- }
- static void register_reloc(struct coff_Section *const sect,
- char *sym, uint32_t addr, uint16_t type)
- {
- struct coff_Reloc *r;
- struct coff_Section *sec;
- uint32_t i;
- r = *sect->tail = nasm_malloc(sizeof(struct coff_Reloc));
- sect->tail = &r->next;
- r->next = NULL;
- sect->nrelocs++;
- r->address = addr;
- r->symbase = SECT_SYMBOLS;
- r->type = type;
- r->symbol = 0;
- for (i = 0; i < (uint32_t)coff_nsects; i++) {
- sec = coff_sects[i];
- if (!strcmp(sym, sec->name)) {
- return;
- }
- r->symbol += 2;
- }
- saa_rewind(coff_syms);
- for (i = 0; i < coff_nsyms; i++) {
- struct coff_Symbol *s = saa_rstruct(coff_syms);
- r->symbol++;
- if (s->strpos == -1 && !strcmp(sym, s->name)) {
- return;
- } else if (s->strpos != -1) {
- int res;
- char *symname;
- symname = nasm_malloc(s->namlen + 1);
- saa_fread(coff_strs, s->strpos-4, symname, s->namlen);
- symname[s->namlen] = '\0';
- res = strcmp(sym, symname);
- nasm_free(symname);
- if (!res)
- return;
- }
- }
- nasm_panic(0, "codeview: relocation for unregistered symbol: %s", sym);
- }
- static inline void section_write32(struct coff_Section *sect, uint32_t val)
- {
- saa_write32(sect->data, val);
- sect->len += 4;
- }
- static inline void section_write16(struct coff_Section *sect, uint16_t val)
- {
- saa_write16(sect->data, val);
- sect->len += 2;
- }
- static inline void section_write8(struct coff_Section *sect, uint8_t val)
- {
- saa_write8(sect->data, val);
- sect->len++;
- }
- static inline void section_wbytes(struct coff_Section *sect, const void *buf,
- size_t len)
- {
- saa_wbytes(sect->data, buf, len);
- sect->len += len;
- }
- static void write_filename_table(struct coff_Section *const sect)
- {
- uint32_t field_length;
- uint32_t tbl_off = 1; /* offset starts at 1 to skip NULL entry */
- struct source_file *file;
- nasm_assert(cv8_state.source_files != NULL);
- nasm_assert(cv8_state.num_files > 0);
- nasm_assert(cv8_state.total_filename_len > 0);
- field_length = 1 + cv8_state.total_filename_len;
- section_write32(sect, 0x000000F3);
- section_write32(sect, field_length);
- section_write8(sect, 0);
- list_for_each(file, cv8_state.source_files) {
- section_wbytes(sect, file->fullname, file->fullnamelen + 1);
- file->filetbl_off = tbl_off;
- tbl_off += file->fullnamelen + 1;
- }
- }
- static void write_sourcefile_table(struct coff_Section *const sect)
- {
- const uint32_t entry_size = 4 + 2 + MD5_HASHBYTES + 2;
- uint32_t field_length = 0;
- uint32_t tbl_off = 0;
- struct source_file *file;
- field_length = entry_size * cv8_state.num_files;
- section_write32(sect, 0x000000F4);
- section_write32(sect, field_length);
- list_for_each(file, cv8_state.source_files) {
- nasm_assert(file->filetbl_off > 0);
- section_write32(sect, file->filetbl_off);
- section_write16(sect, 0x0110);
- section_wbytes(sect, file->md5sum, MD5_HASHBYTES);
- section_write16(sect, 0);
- file->sourcetbl_off = tbl_off;
- tbl_off += entry_size;
- }
- }
- static void write_linenumber_table(struct coff_Section *const sect)
- {
- const uint32_t file_field_len = 12;
- const uint32_t line_field_len = 8;
- int i;
- uint32_t field_length = 0;
- size_t field_base;
- struct source_file *file;
- struct coff_Section *s;
- for (i = 0; i < coff_nsects; i++) {
- if (!strncmp(coff_sects[i]->name, ".text", 5))
- break;
- }
- if (i == coff_nsects)
- return;
- s = coff_sects[i];
- field_length = 12;
- field_length += (cv8_state.num_files * file_field_len);
- field_length += (cv8_state.total_lines * line_field_len);
- section_write32(sect, 0x000000F2);
- section_write32(sect, field_length);
- field_base = sect->len;
- section_write32(sect, 0); /* SECREL, updated by relocation */
- section_write16(sect, 0); /* SECTION, updated by relocation*/
- section_write16(sect, 0); /* pad */
- section_write32(sect, s->len);
- register_reloc(sect, ".text", field_base,
- win64 ? IMAGE_REL_AMD64_SECREL : IMAGE_REL_I386_SECREL);
- register_reloc(sect, ".text", field_base + 4,
- win64 ? IMAGE_REL_AMD64_SECTION : IMAGE_REL_I386_SECTION);
- list_for_each(file, cv8_state.source_files) {
- struct linepair *li;
- /* source mapping */
- section_write32(sect, file->sourcetbl_off);
- section_write32(sect, file->num_lines);
- section_write32(sect, file_field_len + (file->num_lines * line_field_len));
- /* the pairs */
- saa_rewind(file->lines);
- while ((li = saa_rstruct(file->lines))) {
- section_write32(sect, li->file_offset);
- section_write32(sect, li->linenumber |= 0x80000000);
- }
- }
- }
- static uint16_t write_symbolinfo_obj(struct coff_Section *sect)
- {
- uint16_t obj_len;
- obj_len = 2 + 4 + cv8_state.outfile.namebytes;
- section_write16(sect, obj_len);
- section_write16(sect, 0x1101);
- section_write32(sect, 0); /* ASM language */
- section_wbytes(sect, cv8_state.outfile.name, cv8_state.outfile.namebytes);
- return obj_len;
- }
- static uint16_t write_symbolinfo_properties(struct coff_Section *sect,
- const char *const creator_str)
- {
- /* https://github.com/Microsoft/microsoft-pdb/blob/1d60e041/include/cvinfo.h#L3313 */
- uint16_t creator_len;
- creator_len = 2 + 4 + 2 + 3*2 + 3*2 + strlen(creator_str)+1 + 2;
- /*
- * We used to use a language ID of 3 for "MASM", since it's closest of the
- * options available; however, BinScope from WACK (the Windows Application
- * Certification Kit) tests for specific minimum MASM versions and trying to
- * match an increasing sequence of random MASM version/build numbers seems
- * like a fool's errand.
- *
- * Instead, use a different language ID (NASM is, after all, not MASM
- * syntax) and just write the actual NASM version number. BinScope appears
- * to be happy with that.
- */
- section_write16(sect, creator_len);
- section_write16(sect, 0x1116);
- section_write32(sect, 'N'); /* language: 'N' (0x4e) for "NASM"; flags are 0 */
- if (win64)
- section_write16(sect, 0x00D0); /* machine */
- else if (win32)
- section_write16(sect, 0x0006); /* machine */
- else
- nasm_assert(!"neither win32 nor win64 are set!");
- section_write16(sect, 0); /* verFEMajor */
- section_write16(sect, 0); /* verFEMinor */
- section_write16(sect, 0); /* verFEBuild */
- /* BinScope/WACK insist on version >= 8.0.50727 */
- section_write16(sect, NASM_MAJOR_VER); /* verMajor */
- section_write16(sect, NASM_MINOR_VER); /* verMinor */
- section_write16(sect, NASM_SUBMINOR_VER*100 + NASM_PATCHLEVEL_VER); /* verBuild */
- section_wbytes(sect, creator_str, strlen(creator_str)+1); /* verSt */
- /*
- * normally there would be key/value pairs here, but they aren't
- * necessary. They are terminated by 2B
- */
- section_write16(sect, 0);
- return creator_len;
- }
- static uint16_t write_symbolinfo_symbols(struct coff_Section *sect)
- {
- uint16_t len = 0, field_len;
- uint32_t field_base;
- struct cv8_symbol *sym;
- saa_rewind(cv8_state.symbols);
- while ((sym = saa_rstruct(cv8_state.symbols))) {
- switch (sym->type) {
- case SYMTYPE_LDATA:
- case SYMTYPE_GDATA:
- field_len = 12 + strlen(sym->name) + 1;
- len += field_len - 2;
- section_write16(sect, field_len);
- if (sym->type == SYMTYPE_LDATA)
- section_write16(sect, 0x110C);
- else
- section_write16(sect, 0x110D);
- section_write32(sect, sym->symtype);
- field_base = sect->len;
- section_write32(sect, 0); /* SECREL */
- section_write16(sect, 0); /* SECTION */
- break;
- case SYMTYPE_PROC:
- case SYMTYPE_CODE:
- field_len = 9 + strlen(sym->name) + 1;
- len += field_len - 2;
- section_write16(sect, field_len);
- section_write16(sect, 0x1105);
- field_base = sect->len;
- section_write32(sect, 0); /* SECREL */
- section_write16(sect, 0); /* SECTION */
- section_write8(sect, 0); /* FLAG */
- break;
- default:
- nasm_assert(!"unknown symbol type");
- }
- section_wbytes(sect, sym->name, strlen(sym->name) + 1);
- register_reloc(sect, sym->name, field_base,
- win64 ? IMAGE_REL_AMD64_SECREL :
- IMAGE_REL_I386_SECREL);
- register_reloc(sect, sym->name, field_base + 4,
- win64 ? IMAGE_REL_AMD64_SECTION :
- IMAGE_REL_I386_SECTION);
- }
- return len;
- }
- static void write_symbolinfo_table(struct coff_Section *const sect)
- {
- static const char creator_str[] = "The Netwide Assembler " NASM_VER;
- uint16_t obj_length, creator_length, sym_length;
- uint32_t field_length = 0, out_len;
- nasm_assert(cv8_state.outfile.namebytes);
- /* signature, language, outfile NULL */
- obj_length = 2 + 4 + cv8_state.outfile.namebytes;
- creator_length = 2 + 4 + 2 + 3*2 + 3*2 + strlen(creator_str)+1 + 2;
- sym_length = ( cv8_state.num_syms[SYMTYPE_CODE] * 7) +
- ( cv8_state.num_syms[SYMTYPE_PROC] * 7) +
- ( cv8_state.num_syms[SYMTYPE_LDATA] * 10) +
- ( cv8_state.num_syms[SYMTYPE_GDATA] * 10) +
- cv8_state.symbol_lengths;
- field_length = 2 + obj_length +
- 2 + creator_length +
- (4 * cv8_state.total_syms) + sym_length;
- section_write32(sect, 0x000000F1);
- section_write32(sect, field_length);
- /* for sub fields, length preceeds type */
- out_len = write_symbolinfo_obj(sect);
- nasm_assert(out_len == obj_length);
- out_len = write_symbolinfo_properties(sect, creator_str);
- nasm_assert(out_len == creator_length);
- out_len = write_symbolinfo_symbols(sect);
- nasm_assert(out_len == sym_length);
- }
- static inline void align4_table(struct coff_Section *const sect)
- {
- unsigned diff;
- uint32_t zero = 0;
- struct SAA *data = sect->data;
- if (data->wptr % 4 == 0)
- return;
- diff = 4 - (data->wptr % 4);
- if (diff)
- section_wbytes(sect, &zero, diff);
- }
- static void build_symbol_table(struct coff_Section *const sect)
- {
- section_write32(sect, 0x00000004);
- write_filename_table(sect);
- align4_table(sect);
- write_sourcefile_table(sect);
- align4_table(sect);
- write_linenumber_table(sect);
- align4_table(sect);
- write_symbolinfo_table(sect);
- align4_table(sect);
- }
- static void build_type_table(struct coff_Section *const sect)
- {
- uint16_t field_len;
- struct cv8_symbol *sym;
- section_write32(sect, 0x00000004);
- saa_rewind(cv8_state.symbols);
- while ((sym = saa_rstruct(cv8_state.symbols))) {
- if (sym->type != SYMTYPE_PROC)
- continue;
- /* proc leaf */
- field_len = 2 + 4 + 4 + 4 + 2;
- section_write16(sect, field_len);
- section_write16(sect, 0x1008); /* PROC type */
- section_write32(sect, 0x00000003); /* return type */
- section_write32(sect, 0); /* calling convention (default) */
- section_write32(sect, sym->typeindex);
- section_write16(sect, 0); /* # params */
- /* arglist */
- field_len = 2 + 4;
- section_write16(sect, field_len);
- section_write16(sect, 0x1201); /* ARGLIST */
- section_write32(sect, 0); /*num params */
- }
- }
|