Exemple #1
0
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' */
	}
    }
}
Exemple #2
0
/*
 * a.out files have the curious property that all references to
 * things in the data or bss sections are done by addresses which
 * are actually relative to the start of the _text_ section, in the
 * _file_. (No relation to what happens after linking. No idea why
 * this should be so. It's very strange.) So we have to go through
 * the relocation table, _after_ the final size of each section is
 * known, and fix up the relocations pointed to.
 */
static void aout_fixup_relocs(struct Section *sect) 
{
    struct Reloc *r;

    saa_rewind (sect->data);
    for (r = sect->head; r; r = r->next) {
	unsigned char *p, *q, blk[4];
	long l;

	saa_fread (sect->data, r->address, blk, (long)r->bytes);
	p = q = blk;
	l = *p++;
	if (r->bytes > 1) {
	    l += ((long)*p++) << 8;
	    if (r->bytes == 4) {
		l += ((long)*p++) << 16;
		l += ((long)*p++) << 24;
	    }
	}
	if (r->symbol == -SECT_DATA)
	    l += stext.len;
	else if (r->symbol == -SECT_BSS)
	    l += stext.len + sdata.len;
	if (r->bytes == 4)
	    WRITELONG(q, l);
	else if (r->bytes == 2)
	    WRITESHORT(q, l);
	else
	    *q++ = l & 0xFF;
	saa_fwrite (sect->data, r->address, blk, (long)r->bytes);
    }
}
Exemple #3
0
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);
    }
}
Exemple #4
0
static struct SAA *elf_build_symtab(long *len, long *local)
{
    struct SAA *s = saa_init(1L);
    struct Symbol *sym;
    unsigned char entry[16], *p;
    int i;

    *len = *local = 0;

    /*
     * First, an all-zeros entry, required by the ELF spec.
     */
    saa_wbytes(s, NULL, 16L);   /* null symbol table entry */
    *len += 16;
    (*local)++;

    /*
     * Next, an entry for the file name.
     */
    p = entry;
    WRITELONG(p, 1);            /* we know it's 1st thing in strtab */
    WRITELONG(p, 0);            /* no value */
    WRITELONG(p, 0);            /* no size either */
    WRITESHORT(p, 4);           /* type FILE */
    WRITESHORT(p, SHN_ABS);
    saa_wbytes(s, entry, 16L);
    *len += 16;
    (*local)++;

    /*
     * Now some standard symbols defining the segments, for relocation
     * purposes.
     */
    for (i = 1; i <= nsects + 1; i++) {
        p = entry;
        WRITELONG(p, 0);        /* no symbol name */
        WRITELONG(p, 0);        /* offset zero */
        WRITELONG(p, 0);        /* size zero */
        WRITESHORT(p, 3);       /* local section-type thing */
        WRITESHORT(p, (i == 1 ? SHN_ABS : i - 1));      /* the section id */
        saa_wbytes(s, entry, 16L);
        *len += 16;
        (*local)++;
    }

    /*
     * Now the other local symbols.
     */
    saa_rewind(syms);
    while ((sym = saa_rstruct(syms))) {
        if (sym->type & SYM_GLOBAL)
            continue;
        p = entry;
        WRITELONG(p, sym->strpos);
        WRITELONG(p, sym->value);
        WRITELONG(p, sym->size);
        WRITESHORT(p, sym->type);       /* local non-typed thing */
        WRITESHORT(p, sym->section);
        saa_wbytes(s, entry, 16L);
        *len += 16;
        (*local)++;
    }

    /*
     * Now the global symbols.
     */
    saa_rewind(syms);
    while ((sym = saa_rstruct(syms))) {
        if (!(sym->type & SYM_GLOBAL))
            continue;
        p = entry;
        WRITELONG(p, sym->strpos);
        WRITELONG(p, sym->value);
        WRITELONG(p, sym->size);
        WRITESHORT(p, sym->type);       /* global non-typed thing */
        WRITESHORT(p, sym->section);
        saa_wbytes(s, entry, 16L);
        *len += 16;
    }

    return s;
}
static void as86_write_section(struct Section *sect, int index)
{
    struct Piece *p;
    uint32_t s;
    int32_t length;

    fputc(0x20 + index, ofile);        /* 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];
                int32_t tmplen = (length > 64 ? 64 : length);
                fputc(0x40 | (tmplen & 0x3F), ofile);
                saa_rnbytes(sect->data, buf, tmplen);
                nasm_write(buf, tmplen, ofile);
                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, ofile);
            if (as86_reloc_size == 2)
                fwriteint16_t(p->offset, ofile);
            else
                fwriteint32_t(p->offset, ofile);
            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, ofile);
            if (p->number > 255)
                fwriteint16_t(p->number, ofile);
            else
                fputc(p->number, ofile);
            switch (s) {
            case 0:
                break;
            case 1:
                fputc(p->offset, ofile);
                break;
            case 2:
                fwriteint16_t(p->offset, ofile);
                break;
            case 3:
                fwriteint32_t(p->offset, ofile);
                break;
            }
            break;
        }
}
static void as86_write(void)
{
    uint32_t i;
    int32_t 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 ((uint32_t)stext.len > 65535L)
        segsize |= 0x03000000L, seglen += 4;
    else
        segsize |= 0x02000000L, seglen += 2;
    if ((uint32_t)sdata.len > 65535L)
        segsize |= 0xC0000000L, seglen += 4;
    else
        segsize |= 0x80000000L, seglen += 2;

    /*
     * Emit the as86 header.
     */
    fwriteint32_t(0x000186A3L, ofile);
    fputc(0x2A, ofile);
    fwriteint32_t(27 + symlen + seglen + strslen, ofile); /* header length */
    fwriteint32_t(stext.len + sdata.len + bsslen, ofile);
    fwriteint16_t(strslen, ofile);
    fwriteint16_t(0, ofile);     /* class = revision = 0 */
    fwriteint32_t(0x55555555L, ofile);    /* segment max sizes: always this */
    fwriteint32_t(segsize, ofile);        /* segment size descriptors */
    if (segsize & 0x01000000L)
        fwriteint32_t(stext.len, ofile);
    else
        fwriteint16_t(stext.len, ofile);
    if (segsize & 0x40000000L)
        fwriteint32_t(sdata.len + bsslen, ofile);
    else
        fwriteint16_t(sdata.len + bsslen, ofile);
    fwriteint16_t(nsyms, ofile);

    /*
     * Write the symbol table.
     */
    saa_rewind(syms);
    for (i = 0; i < nsyms; i++) {
        struct Symbol *sym = saa_rstruct(syms);
        fwriteint16_t(sym->strpos, ofile);
        fwriteint16_t(sym->flags, ofile);
        switch (sym->flags & (3 << 14)) {
        case 0 << 14:
            break;
        case 1 << 14:
            fputc(sym->value, ofile);
            break;
        case 2 << 14:
            fwriteint16_t(sym->value, ofile);
            break;
        case 3 << 14:
            fwriteint32_t(sym->value, ofile);
            break;
        }
    }

    /*
     * Write out the string table.
     */
    saa_fpwrite(strs, ofile);

    /*
     * Write the program text.
     */
    as86_reloc_size = -1;
    as86_write_section(&stext, SECT_TEXT);
    as86_write_section(&sdata, SECT_DATA);
    /*
     * Append the BSS section to the .data section
     */
    if (bsslen > 65535L) {
        fputc(0x13, ofile);
        fwriteint32_t(bsslen, ofile);
    } else if (bsslen > 255) {
        fputc(0x12, ofile);
        fwriteint16_t(bsslen, ofile);
    } else if (bsslen) {
        fputc(0x11, ofile);
        fputc(bsslen, ofile);
    }

    fputc(0, ofile);           /* termination */
}