Beispiel #1
0
static void aout_pad_sections(void) {
    static unsigned char pad[] = { 0x90, 0x90, 0x90, 0x90 };
    /*
     * Pad each of the text and data sections with NOPs until their
     * length is a multiple of four. (NOP == 0x90.) Also increase
     * the length of the BSS section similarly.
     */
    aout_sect_write (&stext, pad, (-(long)stext.len) & 3);
    aout_sect_write (&sdata, pad, (-(long)sdata.len) & 3);
    sbss.len = (sbss.len + 3) & ~3;
}
Beispiel #2
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);
    }
}