⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outaout.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (exact) {	/*	 * Find a symbol pointing _exactly_ at this one.	 */	for (sym = shead; sym; sym = sym->next)	    if (sym->value == offset)		break;    } else {	/*	 * Find the nearest symbol below this one.	 */	sym = NULL;	for (sm = shead; sm; sm = sm->next)	    if (sm->value <= offset && (!sym || sm->value > sym->value))		sym = sm;    }    if (!sym && exact) {	error (ERR_NONFATAL, "unable to find a suitable global symbol"	       " for this reference");	return 0;    }    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));    sect->tail = &r->next;    r->next = NULL;    r->address = sect->len;    r->symbol = sym->symnum;    r->reltype = type | RELTYPE_SYMFLAG;    r->bytes = bytes;    sect->nrelocs++;    return offset - sym->value;}/* * This routine deals with ..gotoff relocations. These _must_ refer * to a symbol, due to a perversity of *BSD's PIC implementation, * and it must be a non-global one as well; so we store `asym', the * first nonglobal symbol defined in each section, and always work * from that. Relocation type is always RELTYPE_GOTOFF. * * Return value is the adjusted value of `addr', having become an * offset from the `asym' symbol rather than the section. */static long aout_add_gotoff_reloc (struct Section *sect, long segment,				   long offset, int bytes) {    struct Reloc *r;    struct Symbol *asym;    /*     * First look up the segment to find whether it's text, data,     * bss or an external symbol.     */    asym = NULL;    if (segment == stext.index)	asym = stext.asym;    else if (segment == sdata.index)	asym = sdata.asym;    else if (segment == sbss.index)	asym = sbss.asym;    if (!asym)	error (ERR_NONFATAL, "`..gotoff' relocations require a non-global"	       " symbol in the section");    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));    sect->tail = &r->next;    r->next = NULL;    r->address = sect->len;    r->symbol = asym->symnum;    r->reltype = RELTYPE_GOTOFF;    r->bytes = bytes;    sect->nrelocs++;    return offset - asym->value;}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);    }}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;}/* * 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);    }}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 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 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 aout_sect_write (struct Section *sect,			     const unsigned char *data, unsigned long len) {    saa_wbytes (sect->data, data, len);    sect->len += len;}static long aout_segbase (long segment) {    return segment;}static int aout_directive (char *directive, char *value, int pass) {    return 0;}static void aout_filename (char *inname, char *outname, efunc error) {    standard_extension (inname, outname, ".o", error);}static const char *aout_stdmac[] = {    "%define __SECT__ [section .text]",    "%macro __NASM_CDecl__ 1",    "%endmacro",    NULL};static int aout_set_info(enum geninfo type, char **val){    return 0;}#endif /* OF_AOUT || OF_AOUTB */#ifdef OF_AOUTstruct ofmt of_aout = {    "Linux a.out object files",    "aout",    NULL,    null_debug_arr,    &null_debug_form,    aout_stdmac,    aout_init,    aout_set_info,    aout_out,    aout_deflabel,    aout_section_names,    aout_segbase,    aout_directive,    aout_filename,    aout_cleanup};#endif#ifdef OF_AOUTBstruct ofmt of_aoutb = {    "NetBSD/FreeBSD a.out object files",    "aoutb",    NULL,    null_debug_arr,    &null_debug_form,    aout_stdmac,    aoutb_init,    aout_set_info,    aout_out,    aout_deflabel,    aout_section_names,    aout_segbase,    aout_directive,    aout_filename,    aout_cleanup};#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -