Example #1
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);
    }
}
Example #2
0
static void elf_out(long segto, const void *data, unsigned long type,
                    long segment, long wrt)
{
    struct Section *s;
    long realbytes = type & OUT_SIZMASK;
    long addr;
    unsigned char mydata[4], *p;
    int i;
    static struct symlininfo sinfo;

    type &= OUT_TYPMASK;

    /*
     * handle absolute-assembly (structure definitions)
     */
    if (segto == NO_SEG) {
        if (type != OUT_RESERVE)
            error(ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
                  " space");
        return;
    }

    s = NULL;
    for (i = 0; i < nsects; i++)
        if (segto == sects[i]->index) {
            s = sects[i];
            break;
        }
    if (!s) {
        int tempint;            /* ignored */
        if (segto != elf_section_names(".text", 2, &tempint))
            error(ERR_PANIC, "strange segment conditions in ELF driver");
        else {
            s = sects[nsects - 1];
            i = nsects - 1;
        }
    }

    /* again some stabs debugging stuff */
    if (of_elf.current_dfmt) {
        sinfo.offset = s->len;
        sinfo.section = i;
        sinfo.name = s->name;
        of_elf.current_dfmt->debug_output(TY_STABSSYMLIN, &sinfo);
    }
    /* end of debugging stuff */

    if (s->type == SHT_NOBITS && type != OUT_RESERVE) {
        error(ERR_WARNING, "attempt to initialise memory in"
              " BSS section `%s': ignored", s->name);
        if (type == OUT_REL2ADR)
            realbytes = 2;
        else if (type == OUT_REL4ADR)
            realbytes = 4;
        s->len += realbytes;
        return;
    }

    if (type == OUT_RESERVE) {
        if (s->type == SHT_PROGBITS) {
            error(ERR_WARNING, "uninitialised space declared in"
                  " non-BSS section `%s': zeroing", s->name);
            elf_sect_write(s, NULL, realbytes);
        } else
            s->len += realbytes;
    } else if (type == OUT_RAWDATA) {
        if (segment != NO_SEG)
            error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
        elf_sect_write(s, data, realbytes);
    } else if (type == OUT_ADDRESS) {
        int gnu16 = 0;
        addr = *(long *)data;
        if (segment != NO_SEG) {
            if (segment % 2) {
                error(ERR_NONFATAL, "ELF format does not support"
                      " segment base references");
            } else {
                if (wrt == NO_SEG) {
                    if (realbytes == 2) {
                        gnu16 = 1;
                        elf_add_reloc(s, segment, R_386_16);
                    } else {
                        elf_add_reloc(s, segment, R_386_32);
                    }
                } else if (wrt == elf_gotpc_sect + 1) {
                    /*
                     * The user will supply GOT relative to $$. ELF
                     * will let us have GOT relative to $. So we
                     * need to fix up the data item by $-$$.
                     */
                    addr += s->len;
                    elf_add_reloc(s, segment, R_386_GOTPC);
                } else if (wrt == elf_gotoff_sect + 1) {
                    elf_add_reloc(s, segment, R_386_GOTOFF);
                } else if (wrt == elf_got_sect + 1) {
                    addr = elf_add_gsym_reloc(s, segment, addr,
                                              R_386_GOT32, TRUE);
                } else if (wrt == elf_sym_sect + 1) {
                    if (realbytes == 2) {
                        gnu16 = 1;
                        addr = elf_add_gsym_reloc(s, segment, addr,
                                                  R_386_16, FALSE);
                    } else {
                        addr = elf_add_gsym_reloc(s, segment, addr,
                                                  R_386_32, FALSE);
                    }
                } else if (wrt == elf_plt_sect + 1) {
                    error(ERR_NONFATAL, "ELF format cannot produce non-PC-"
                          "relative PLT references");
                } else {
                    error(ERR_NONFATAL, "ELF format does not support this"
                          " use of WRT");
                    wrt = NO_SEG;       /* we can at least _try_ to continue */
                }
            }
        }
        p = mydata;
        if (gnu16) {
            error(ERR_WARNING | ERR_WARN_GNUELF,
                  "16-bit relocations in ELF is a GNU extension");
            WRITESHORT(p, addr);
        } else {
            if (realbytes != 4 && segment != NO_SEG) {
                error(ERR_NONFATAL,
                      "Unsupported non-32-bit ELF relocation");
            }
            WRITELONG(p, addr);
        }
        elf_sect_write(s, mydata, realbytes);
    } else if (type == OUT_REL2ADR) {
        if (segment == segto)
            error(ERR_PANIC, "intra-segment OUT_REL2ADR");
        if (segment != NO_SEG && segment % 2) {
            error(ERR_NONFATAL, "ELF format does not support"
                  " segment base references");
        } else {
            if (wrt == NO_SEG) {
                error(ERR_WARNING | ERR_WARN_GNUELF,
                      "16-bit relocations in ELF is a GNU extension");
                elf_add_reloc(s, segment, R_386_PC16);
            } else {
                error(ERR_NONFATAL,
                      "Unsupported non-32-bit ELF relocation");
            }
        }
        p = mydata;
        WRITESHORT(p, *(long *)data - realbytes);
        elf_sect_write(s, mydata, 2L);
    } else if (type == OUT_REL4ADR) {
        if (segment == segto)
            error(ERR_PANIC, "intra-segment OUT_REL4ADR");
        if (segment != NO_SEG && segment % 2) {
            error(ERR_NONFATAL, "ELF format does not support"
                  " segment base references");
        } else {
            if (wrt == NO_SEG) {
                elf_add_reloc(s, segment, R_386_PC32);
            } else if (wrt == elf_plt_sect + 1) {
                elf_add_reloc(s, segment, R_386_PLT32);
            } else if (wrt == elf_gotpc_sect + 1 ||
                       wrt == elf_gotoff_sect + 1 ||
                       wrt == elf_got_sect + 1) {
                error(ERR_NONFATAL, "ELF format cannot produce PC-"
                      "relative GOT references");
            } else {
                error(ERR_NONFATAL, "ELF format does not support this"
                      " use of WRT");
                wrt = NO_SEG;   /* we can at least _try_ to continue */
            }
        }
        p = mydata;
        WRITELONG(p, *(long *)data - realbytes);
        elf_sect_write(s, mydata, 4L);
    }
}
Example #3
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;
}
Example #4
0
static void aout_out (long segto, const void *data, unsigned long type,
		      long segment, long wrt) 
{
    struct Section *s;
    long realbytes = type & OUT_SIZMASK;
    long addr;
    unsigned char mydata[4], *p;

    type &= OUT_TYPMASK;

    /*
     * handle absolute-assembly (structure definitions)
     */
    if (segto == NO_SEG) {
	if (type != OUT_RESERVE)
	    error (ERR_NONFATAL, "attempt to assemble code in [ABSOLUTE]"
		   " space");
	return;
    }

    if (segto == stext.index)
	s = &stext;
    else if (segto == sdata.index)
	s = &sdata;
    else if (segto == sbss.index)
	s = NULL;
    else {
	error(ERR_WARNING, "attempt to assemble code in"
	      " segment %d: defaulting to `.text'", segto);
	s = &stext;
    }

    if (!s && type != OUT_RESERVE) {
	error(ERR_WARNING, "attempt to initialise memory in the"
	      " BSS section: ignored");
	if (type == OUT_REL2ADR)
	    realbytes = 2;
	else if (type == OUT_REL4ADR)
	    realbytes = 4;
	sbss.len += realbytes;
	return;
    }

    if (type == OUT_RESERVE) {
	if (s) {
	    error(ERR_WARNING, "uninitialised space declared in"
		  " %s section: zeroing",
		  (segto == stext.index ? "code" : "data"));
	    aout_sect_write (s, NULL, realbytes);
	} else
	    sbss.len += realbytes;
    } else if (type == OUT_RAWDATA) {
	if (segment != NO_SEG)
	    error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
	aout_sect_write (s, data, realbytes);
    } else if (type == OUT_ADDRESS) {
	addr = *(long *)data;
	if (segment != NO_SEG) {
	    if (segment % 2) {
		error(ERR_NONFATAL, "a.out format does not support"
		      " segment base references");
	    } else {
		if (wrt == NO_SEG) {
		    aout_add_reloc (s, segment, RELTYPE_ABSOLUTE, realbytes);
		} else if (!bsd) {
		    error (ERR_NONFATAL, "Linux a.out format does not support"
			   " any use of WRT");
		    wrt = NO_SEG;      /* we can at least _try_ to continue */
		} else if (wrt == aout_gotpc_sect+1) {
		    is_pic = 0x40;
		    aout_add_reloc (s, segment, RELTYPE_GOTPC, realbytes);
		} else if (wrt == aout_gotoff_sect+1) {
		    is_pic = 0x40;
		    addr = aout_add_gotoff_reloc (s, segment,
						  addr, realbytes);
		} else if (wrt == aout_got_sect+1) {
		    is_pic = 0x40;
		    addr = aout_add_gsym_reloc (s, segment, addr, RELTYPE_GOT,
						realbytes, TRUE);
		} else if (wrt == aout_sym_sect+1) {
		    addr = aout_add_gsym_reloc (s, segment, addr,
						RELTYPE_ABSOLUTE, realbytes,
						FALSE);
		} else if (wrt == aout_plt_sect+1) {
		    is_pic = 0x40;
		    error(ERR_NONFATAL, "a.out format cannot produce non-PC-"
			  "relative PLT references");
		} else {
		    error (ERR_NONFATAL, "a.out format does not support this"
			   " use of WRT");
		    wrt = NO_SEG;      /* we can at least _try_ to continue */
		}
	    }
	}
	p = mydata;
	if (realbytes == 2)
	    WRITESHORT (p, addr);
	else
	    WRITELONG (p, addr);
	aout_sect_write (s, mydata, realbytes);
    } else if (type == OUT_REL2ADR) {
	if (segment == segto)
	    error(ERR_PANIC, "intra-segment OUT_REL2ADR");
	if (segment != NO_SEG && segment % 2) {
	    error(ERR_NONFATAL, "a.out format does not support"
		  " segment base references");
	} else {
	    if (wrt == NO_SEG) {
		aout_add_reloc (s, segment, RELTYPE_RELATIVE, 2);
	    } else if (!bsd) {
		error (ERR_NONFATAL, "Linux a.out format does not support"
		       " any use of WRT");
		wrt = NO_SEG;      /* we can at least _try_ to continue */
	    } else if (wrt == aout_plt_sect+1) {
		is_pic = 0x40;
		aout_add_reloc (s, segment, RELTYPE_PLT, 2);
	    } else if (wrt == aout_gotpc_sect+1 ||
		       wrt == aout_gotoff_sect+1 ||
		       wrt == aout_got_sect+1) {
		error(ERR_NONFATAL, "a.out format cannot produce PC-"
		      "relative GOT references");
	    } else {
		error (ERR_NONFATAL, "a.out format does not support this"
		       " use of WRT");
		wrt = NO_SEG;      /* we can at least _try_ to continue */
	    }
	}
	p = mydata;
	WRITESHORT (p, *(long*)data-(realbytes + s->len));
	aout_sect_write (s, mydata, 2L);
    } else if (type == OUT_REL4ADR) {
	if (segment == segto)
	    error(ERR_PANIC, "intra-segment OUT_REL4ADR");
	if (segment != NO_SEG && segment % 2) {
	    error(ERR_NONFATAL, "a.out format does not support"
		  " segment base references");
	} else {
	    if (wrt == NO_SEG) {
		aout_add_reloc (s, segment, RELTYPE_RELATIVE, 4);
	    } else if (!bsd) {
		error (ERR_NONFATAL, "Linux a.out format does not support"
		       " any use of WRT");
		wrt = NO_SEG;      /* we can at least _try_ to continue */
	    } else if (wrt == aout_plt_sect+1) {
		is_pic = 0x40;
		aout_add_reloc (s, segment, RELTYPE_PLT, 4);
	    } else if (wrt == aout_gotpc_sect+1 ||
		       wrt == aout_gotoff_sect+1 ||
		       wrt == aout_got_sect+1) {
		error(ERR_NONFATAL, "a.out format cannot produce PC-"
		      "relative GOT references");
	    } else {
		error (ERR_NONFATAL, "a.out format does not support this"
		       " use of WRT");
		wrt = NO_SEG;      /* we can at least _try_ to continue */
	    }
	}
	p = mydata;
	WRITELONG (p, *(long*)data-(realbytes + s->len));
	aout_sect_write (s, mydata, 4L);
    }
}
Example #5
0
File: listing.c Project: aosm/nasm
static void list_output(long offset, const void *data, unsigned long type)
{
    unsigned long typ, size;

    if (!listp || suppress || user_nolist)      /* fbk - 9/2/00 */
        return;

    typ = type & OUT_TYPMASK;
    size = type & OUT_SIZMASK;

    if (typ == OUT_RAWDATA) {
        unsigned char const *p = data;
        char q[3];
        while (size--) {
            HEX(q, *p);
            q[2] = '\0';
            list_out(offset++, q);
            p++;
        }
    } else if (typ == OUT_ADDRESS) {
        unsigned long d = *(long *)data;
        char q[11];
        unsigned char p[4], *r = p;
        if (size == 4) {
            q[0] = '[';
            q[9] = ']';
            q[10] = '\0';
            WRITELONG(r, d);
            HEX(q + 1, p[0]);
            HEX(q + 3, p[1]);
            HEX(q + 5, p[2]);
            HEX(q + 7, p[3]);
            list_out(offset, q);
        } else {
            q[0] = '[';
            q[5] = ']';
            q[6] = '\0';
            WRITESHORT(r, d);
            HEX(q + 1, p[0]);
            HEX(q + 3, p[1]);
            list_out(offset, q);
        }
    } else if (typ == OUT_REL2ADR) {
        unsigned long d = *(long *)data;
        char q[11];
        unsigned char p[4], *r = p;
        q[0] = '(';
        q[5] = ')';
        q[6] = '\0';
        WRITESHORT(r, d);
        HEX(q + 1, p[0]);
        HEX(q + 3, p[1]);
        list_out(offset, q);
    } else if (typ == OUT_REL4ADR) {
        unsigned long d = *(long *)data;
        char q[11];
        unsigned char p[4], *r = p;
        q[0] = '(';
        q[9] = ')';
        q[10] = '\0';
        WRITELONG(r, d);
        HEX(q + 1, p[0]);
        HEX(q + 3, p[1]);
        HEX(q + 5, p[2]);
        HEX(q + 7, p[3]);
        list_out(offset, q);
    } else if (typ == OUT_RESERVE) {
        char q[20];
        snprintf(q, sizeof(q), "<res %08lX>", size);
        list_out(offset, q);
    }
}