static void coff_write_relocs (struct Section *s) { struct Reloc *r; for (r = s->head; r; r = r->next) { fwritelong (r->address, coffp); fwritelong (r->symbol + (r->symbase == REAL_SYMBOLS ? initsym : r->symbase == ABS_SYMBOL ? initsym-1 : r->symbase == SECT_SYMBOLS ? 2 : 0), coffp); /* * Strange: Microsoft's COFF documentation says 0x03 for an * absolute relocation, but both Visual C++ and DJGPP agree * that in fact it's 0x06. I'll use 0x06 until someone * argues. */ fwriteshort (r->relative ? 0x14 : 0x06, coffp); } }
static void aout_write_relocs (struct Reloc *r) { while (r) { unsigned long word2; fwritelong (r->address, aoutfp); if (r->symbol >= 0) word2 = r->symbol; else word2 = -r->symbol; word2 |= r->reltype << 24; word2 |= (r->bytes == 1 ? 0 : r->bytes == 2 ? 0x2000000L : 0x4000000L); fwritelong (word2, aoutfp); r = r->next; } }
static void coff_symbol (char *name, long strpos, long value, int section, int type, int aux) { char padname[8]; if (name) { memset (padname, 0, 8); strncpy (padname, name, 8); fwrite (padname, 8, 1, coffp); } else { fwritelong (0L, coffp); fwritelong (strpos, coffp); } fwritelong (value, coffp); fwriteshort (section, coffp); fwriteshort (0, coffp); fputc (type, coffp); fputc (aux, coffp); }
static void aout_write_syms (void) { unsigned long i; saa_rewind (syms); for (i = 0; i < nsyms; i++) { struct Symbol *sym = saa_rstruct(syms); fwritelong (sym->strpos, aoutfp); fwritelong ((long)sym->type & ~SYM_WITH_SIZE, aoutfp); /* * Fix up the symbol value now we know the final section * sizes. */ if ((sym->type & SECT_MASK) == SECT_DATA) sym->value += stext.len; if ((sym->type & SECT_MASK) == SECT_BSS) sym->value += stext.len + sdata.len; fwritelong (sym->value, aoutfp); /* * Output a size record if necessary. */ if (sym->type & SYM_WITH_SIZE) { fwritelong(sym->strpos, aoutfp); fwritelong(0x0DL, aoutfp); /* special value: means size */ fwritelong(sym->size, aoutfp); i++; /* use up another of `nsyms' */ } } }
static void elf_section_header(int name, int type, int flags, void *data, int is_saa, long datalen, int link, int info, int align, int eltsize) { elf_sects[elf_nsect].data = data; elf_sects[elf_nsect].len = datalen; elf_sects[elf_nsect].is_saa = is_saa; elf_nsect++; fwritelong((long)name, elffp); fwritelong((long)type, elffp); fwritelong((long)flags, elffp); fwritelong(0L, elffp); /* no address, ever, in object files */ fwritelong(type == 0 ? 0L : elf_foffs, elffp); fwritelong(datalen, elffp); if (data) elf_foffs += (datalen + SEG_ALIGN_1) & ~SEG_ALIGN_1; fwritelong((long)link, elffp); fwritelong((long)info, elffp); fwritelong((long)align, elffp); fwritelong((long)eltsize, elffp); }
static void aout_write(void) { /* * Emit the a.out header. */ /* OMAGIC, M_386 or MID_I386, no flags */ fwritelong (bsd ? 0x07018600 | is_pic : 0x640107L, aoutfp); fwritelong (stext.len, aoutfp); fwritelong (sdata.len, aoutfp); fwritelong (sbss.len, aoutfp); fwritelong (nsyms * 12, aoutfp); /* length of symbol table */ fwritelong (0L, aoutfp); /* object files have no entry point */ fwritelong (stext.nrelocs * 8, aoutfp); /* size of text relocs */ fwritelong (sdata.nrelocs * 8, aoutfp); /* size of data relocs */ /* * Write out the code section and the data section. */ saa_fpwrite (stext.data, aoutfp); saa_fpwrite (sdata.data, aoutfp); /* * Write out the relocations. */ aout_write_relocs (stext.head); aout_write_relocs (sdata.head); /* * Write the symbol table. */ aout_write_syms (); /* * And the string table. */ fwritelong (strslen+4, aoutfp); /* length includes length count */ saa_fpwrite (strs, aoutfp); }
static void coff_write_symbols (void) { char filename[18]; int i; /* * The `.file' record, and the file name auxiliary record. */ coff_symbol (".file", 0L, 0L, -2, 0x67, 1); memset (filename, 0, 18); strncpy (filename, coff_infile, 18); fwrite (filename, 18, 1, coffp); /* * The section records, with their auxiliaries. */ memset (filename, 0, 18); /* useful zeroed buffer */ for (i=0; i<nsects; i++) { coff_symbol (sects[i]->name, 0L, 0L, i+1, 3, 1); fwritelong (sects[i]->len, coffp); fwriteshort (sects[i]->nrelocs, coffp); fwrite (filename, 12, 1, coffp); } /* * The absolute symbol, for relative-to-absolute relocations. */ coff_symbol (".absolut", 0L, 0L, -1, 3, 0); /* * The real symbols. */ saa_rewind (syms); for (i=0; i<nsyms; i++) { struct Symbol *sym = saa_rstruct (syms); coff_symbol (sym->strpos == -1 ? sym->name : NULL, sym->strpos, sym->value, sym->section, sym->is_global ? 2 : 3, 0); } }
static void coff_section_header (char *name, long vsize, long datalen, long datapos, long relpos, int nrelocs, long flags) { char padname[8]; memset (padname, 0, 8); strncpy (padname, name, 8); fwrite (padname, 8, 1, coffp); fwritelong (vsize, coffp); fwritelong (0L, coffp); /* RVA/offset - we ignore */ fwritelong (datalen, coffp); fwritelong (datapos, coffp); fwritelong (relpos, coffp); fwritelong (0L, coffp); /* no line numbers - we don't do 'em */ fwriteshort (nrelocs, coffp); fwriteshort (0, coffp); /* again, no line numbers */ fwritelong (flags, coffp); }
static void elf_write(void) { int nsections, align; int scount; char *p; int commlen; char comment[64]; int i; struct SAA *symtab; long symtablen, symtablocal; /* * Work out how many sections we will have. We have SHN_UNDEF, * then the flexible user sections, then the four fixed * sections `.comment', `.shstrtab', `.symtab' and `.strtab', * then optionally relocation sections for the user sections. */ if (of_elf.current_dfmt == &df_stabs) nsections = 8; else nsections = 5; /* SHN_UNDEF and the fixed ones */ add_sectname("", ".comment"); add_sectname("", ".shstrtab"); add_sectname("", ".symtab"); add_sectname("", ".strtab"); for (i = 0; i < nsects; i++) { nsections++; /* for the section itself */ if (sects[i]->head) { nsections++; /* for its relocations */ add_sectname(".rel", sects[i]->name); } } if (of_elf.current_dfmt == &df_stabs) { /* in case the debug information is wanted, just add these three sections... */ add_sectname("", ".stab"); add_sectname("", ".stabstr"); add_sectname(".rel", ".stab"); } /* * Do the comment. */ *comment = '\0'; commlen = 2 + sprintf(comment + 1, "The Netwide Assembler %s", NASM_VER); /* * Output the ELF header. */ fwrite("\177ELF\1\1\1\0\0\0\0\0\0\0\0\0", 16, 1, elffp); fwriteshort(1, elffp); /* ET_REL relocatable file */ fwriteshort(3, elffp); /* EM_386 processor ID */ fwritelong(1L, elffp); /* EV_CURRENT file format version */ fwritelong(0L, elffp); /* no entry point */ fwritelong(0L, elffp); /* no program header table */ fwritelong(0x40L, elffp); /* section headers straight after * ELF header plus alignment */ fwritelong(0L, elffp); /* 386 defines no special flags */ fwriteshort(0x34, elffp); /* size of ELF header */ fwriteshort(0, elffp); /* no program header table, again */ fwriteshort(0, elffp); /* still no program header table */ fwriteshort(0x28, elffp); /* size of section header */ fwriteshort(nsections, elffp); /* number of sections */ fwriteshort(nsects + 2, elffp); /* string table section index for * section header table */ fwritelong(0L, elffp); /* align to 0x40 bytes */ fwritelong(0L, elffp); fwritelong(0L, elffp); /* * Build the symbol table and relocation tables. */ symtab = elf_build_symtab(&symtablen, &symtablocal); for (i = 0; i < nsects; i++) if (sects[i]->head) sects[i]->rel = elf_build_reltab(§s[i]->rellen, sects[i]->head); /* * Now output the section header table. */ elf_foffs = 0x40 + 0x28 * nsections; align = ((elf_foffs + SEG_ALIGN_1) & ~SEG_ALIGN_1) - elf_foffs; elf_foffs += align; elf_nsect = 0; elf_sects = nasm_malloc(sizeof(*elf_sects) * (2 * nsects + 10)); elf_section_header(0, 0, 0, NULL, FALSE, 0L, 0, 0, 0, 0); /* SHN_UNDEF */ scount = 1; /* needed for the stabs debugging to track the symtable section */ p = shstrtab + 1; for (i = 0; i < nsects; i++) { elf_section_header(p - shstrtab, sects[i]->type, sects[i]->flags, (sects[i]->type == SHT_PROGBITS ? sects[i]->data : NULL), TRUE, sects[i]->len, 0, 0, sects[i]->align, 0); p += strlen(p) + 1; scount++; /* dito */ } elf_section_header(p - shstrtab, 1, 0, comment, FALSE, (long)commlen, 0, 0, 1, 0); /* .comment */ scount++; /* dito */ p += strlen(p) + 1; elf_section_header(p - shstrtab, 3, 0, shstrtab, FALSE, (long)shstrtablen, 0, 0, 1, 0); /* .shstrtab */ scount++; /* dito */ p += strlen(p) + 1; elf_section_header(p - shstrtab, 2, 0, symtab, TRUE, symtablen, nsects + 4, symtablocal, 4, 16); /* .symtab */ symtabsection = scount; /* now we got the symtab section index in the ELF file */ p += strlen(p) + 1; elf_section_header(p - shstrtab, 3, 0, strs, TRUE, strslen, 0, 0, 1, 0); /* .strtab */ for (i = 0; i < nsects; i++) if (sects[i]->head) { p += strlen(p) + 1; elf_section_header(p - shstrtab, 9, 0, sects[i]->rel, TRUE, sects[i]->rellen, nsects + 3, i + 1, 4, 8); } if (of_elf.current_dfmt == &df_stabs) { /* for debugging information, create the last three sections which are the .stab , .stabstr and .rel.stab sections respectively */ /* this function call creates the stab sections in memory */ stabs_generate(); if ((stabbuf) && (stabstrbuf) && (stabrelbuf)) { p += strlen(p) + 1; elf_section_header(p - shstrtab, 1, 0, stabbuf, 0, stablen, nsections - 2, 0, 4, 12); p += strlen(p) + 1; elf_section_header(p - shstrtab, 3, 0, stabstrbuf, 0, stabstrlen, 0, 0, 4, 0); p += strlen(p) + 1; /* link -> symtable info -> section to refer to */ elf_section_header(p - shstrtab, 9, 0, stabrelbuf, 0, stabrellen, symtabsection, nsections - 3, 4, 8); } } fwrite(align_str, align, 1, elffp); /* * Now output the sections. */ elf_write_sections(); nasm_free(elf_sects); saa_free(symtab); }
static void coff_write (void) { long pos, sympos, vsize; int i; /* * Work out how big the file will get. Calculate the start of * the `real' symbols at the same time. */ pos = 0x14 + 0x28 * nsects; initsym = 3; /* two for the file, one absolute */ for (i=0; i<nsects; i++) { if (sects[i]->data) { sects[i]->pos = pos; pos += sects[i]->len; sects[i]->relpos = pos; pos += 10 * sects[i]->nrelocs; } else sects[i]->pos = sects[i]->relpos = 0L; initsym += 2; /* two for each section */ } sympos = pos; /* * Output the COFF header. */ fwriteshort (0x14C, coffp); /* MACHINE_i386 */ fwriteshort (nsects, coffp); /* number of sections */ fwritelong (time(NULL), coffp); /* time stamp */ fwritelong (sympos, coffp); fwritelong (nsyms + initsym, coffp); fwriteshort (0, coffp); /* no optional header */ /* Flags: 32-bit, no line numbers. Win32 doesn't even bother with them. */ fwriteshort (win32 ? 0 : 0x104, coffp); /* * Output the section headers. */ vsize = 0L; for (i=0; i<nsects; i++) { coff_section_header (sects[i]->name, vsize, sects[i]->len, sects[i]->pos, sects[i]->relpos, sects[i]->nrelocs, sects[i]->flags); vsize += sects[i]->len; } /* * Output the sections and their relocations. */ for (i=0; i<nsects; i++) if (sects[i]->data) { saa_fpwrite (sects[i]->data, coffp); coff_write_relocs (sects[i]); } /* * Output the symbol and string tables. */ coff_write_symbols(); fwritelong (strslen+4, coffp); /* length includes length count */ saa_fpwrite (strs, coffp); }
static void as86_write_section (struct Section *sect, int index) { struct Piece *p; unsigned long s; long length; fputc (0x20+index, as86fp); /* select the right section */ saa_rewind (sect->data); for (p = sect->head; p; p = p->next) switch (p->type) { case 0: /* * Absolute data. Emit it in chunks of at most 64 * bytes. */ length = p->bytes; do { char buf[64]; long tmplen = (length > 64 ? 64 : length); fputc (0x40 | (tmplen & 0x3F), as86fp); saa_rnbytes (sect->data, buf, tmplen); fwrite (buf, 1, tmplen, as86fp); length -= tmplen; } while (length > 0); break; case 1: /* * A segment-type relocation. First fix up the BSS. */ if (p->number == SECT_BSS) p->number = SECT_DATA, p->offset += sdata.len; as86_set_rsize (p->bytes); fputc (0x80 | (p->relative ? 0x20 : 0) | p->number, as86fp); if (as86_reloc_size == 2) fwriteshort (p->offset, as86fp); else fwritelong (p->offset, as86fp); break; case 2: /* * A symbol-type relocation. */ as86_set_rsize (p->bytes); s = p->offset; if (s > 65535L) s = 3; else if (s > 255) s = 2; else if (s > 0) s = 1; else s = 0; fputc (0xC0 | (p->relative ? 0x20 : 0) | (p->number > 255 ? 0x04 : 0) | s, as86fp); if (p->number > 255) fwriteshort (p->number, as86fp); else fputc (p->number, as86fp); switch ((int)s) { case 0: break; case 1: fputc (p->offset, as86fp); break; case 2: fwriteshort (p->offset, as86fp); break; case 3: fwritelong (p->offset, as86fp); break; } break; } }
static void as86_write(void) { int i; long symlen, seglen, segsize; /* * First, go through the symbol records working out how big * each will be. Also fix up BSS references at this time, and * set the flags words up completely. */ symlen = 0; saa_rewind (syms); for (i = 0; i < nsyms; i++) { struct Symbol *sym = saa_rstruct (syms); if (sym->segment == SECT_BSS) sym->segment = SECT_DATA, sym->value += sdata.len; sym->flags |= sym->segment; if (sym->value == 0) sym->flags |= 0 << 14, symlen += 4; else if (sym->value >= 0 && sym->value <= 255) sym->flags |= 1 << 14, symlen += 5; else if (sym->value >= 0 && sym->value <= 65535L) sym->flags |= 2 << 14, symlen += 6; else sym->flags |= 3 << 14, symlen += 8; } /* * Now do the same for the segments, and get the segment size * descriptor word at the same time. */ seglen = segsize = 0; if ((unsigned long) stext.len > 65535L) segsize |= 0x03000000L, seglen += 4; else segsize |= 0x02000000L, seglen += 2; if ((unsigned long) sdata.len > 65535L) segsize |= 0xC0000000L, seglen += 4; else segsize |= 0x80000000L, seglen += 2; /* * Emit the as86 header. */ fwritelong (0x000186A3L, as86fp); fputc (0x2A, as86fp); fwritelong (27+symlen+seglen+strslen, as86fp); /* header length */ fwritelong (stext.len+sdata.len, as86fp); fwriteshort (strslen, as86fp); fwriteshort (0, as86fp); /* class = revision = 0 */ fwritelong (0x55555555L, as86fp); /* segment max sizes: always this */ fwritelong (segsize, as86fp); /* segment size descriptors */ if (segsize & 0x01000000L) fwritelong (stext.len, as86fp); else fwriteshort (stext.len, as86fp); if (segsize & 0x40000000L) fwritelong (sdata.len, as86fp); else fwriteshort (sdata.len, as86fp); fwriteshort (nsyms, as86fp); /* * Write the symbol table. */ saa_rewind (syms); for (i = 0; i < nsyms; i++) { struct Symbol *sym = saa_rstruct (syms); fwriteshort (sym->strpos, as86fp); fwriteshort (sym->flags, as86fp); switch (sym->flags & (3<<14)) { case 0<<14: break; case 1<<14: fputc (sym->value, as86fp); break; case 2<<14: fwriteshort (sym->value, as86fp); break; case 3<<14: fwritelong (sym->value, as86fp); break; } } /* * Write out the string table. */ saa_fpwrite (strs, as86fp); /* * Write the program text. */ as86_reloc_size = -1; as86_write_section (&stext, SECT_TEXT); as86_write_section (&sdata, SECT_DATA); fputc (0, as86fp); /* termination */ }