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

📄 outelf.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (segment == sects[i]->index) {		    sym->section = i+1;		    break;		}	}    }    if (is_global == 2) {	sym->size = offset;	sym->value = 0;	sym->section = SHN_COMMON;	/*	 * We have a common variable. Check the special text to see	 * if it's a valid number and power of two; if so, store it	 * as the alignment for the common variable.	 */	if (special) {	    int err;	    sym->value = readnum (special, &err);	    if (err)		error(ERR_NONFATAL, "alignment constraint `%s' is not a"		      " valid number", special);	    else if ( (sym->value | (sym->value-1)) != 2*sym->value - 1)		error(ERR_NONFATAL, "alignment constraint `%s' is not a"		      " power of two", special);	}	special_used = TRUE;    } else	sym->value = (sym->section == SHN_UNDEF ? 0 : offset);    if (sym->type == SYM_GLOBAL) {	/*	 * There's a problem here that needs fixing.	 * If sym->section == SHN_ABS, then the first line of the	 * else section causes a core dump, because its a reference	 * beyond the end of the section array.	 * This behaviour is exhibited by this code:	 *     GLOBAL crash_nasm	 *     crash_nasm equ 0	 *	 * I'm not sure how to procede, because I haven't got the	 * first clue about how ELF works, so I don't know what to	 * do with it. Furthermore, I'm not sure what the rest of this	 * section of code does. Help?	 *	 * For now, I'll see if doing absolutely nothing with it will	 * work...	 */	if (sym->section == SHN_UNDEF || sym->section == SHN_COMMON)	{	    bsym = raa_write (bsym, segment, nglobs);	}	else if (sym->section != SHN_ABS)	{	    /*	     * This is a global symbol; so we must add it to the linked	     * list of global symbols in its section. We'll push it on	     * the beginning of the list, because it doesn't matter	     * much which end we put it on and it's easier like this.	     *	     * In addition, we check the special text for symbol	     * type and size information.	     */	    sym->next = sects[sym->section-1]->gsyms;	    sects[sym->section-1]->gsyms = sym;	    if (special) {		int n = strcspn(special, " ");		if (!nasm_strnicmp(special, "function", n))		    sym->type |= SYM_FUNCTION;		else if (!nasm_strnicmp(special, "data", n) ||			 !nasm_strnicmp(special, "object", n))		    sym->type |= SYM_DATA;		else		    error(ERR_NONFATAL, "unrecognised symbol type `%.*s'",			  n, special);		if (special[n]) {		    struct tokenval tokval;		    expr *e;		    int fwd = FALSE;		    char *saveme=stdscan_bufptr;   /* bugfix? fbk 8/10/00 */		    while (special[n] && isspace(special[n]))			n++;		    /*		     * We have a size expression; attempt to		     * evaluate it.		     */		    stdscan_reset();		    stdscan_bufptr = special+n;		    tokval.t_type = TOKEN_INVALID;		    e = evaluate(stdscan, NULL, &tokval, &fwd, 0, error, NULL);		    if (fwd) {			sym->nextfwd = fwds;			fwds = sym;			sym->name = nasm_strdup(name);		    } else if (e) {			if (!is_simple(e))			    error (ERR_NONFATAL, "cannot use relocatable"				   " expression as symbol size");			else			    sym->size = reloc_value(e);		    }		    stdscan_bufptr=saveme;    /* bugfix? fbk 8/10/00 */		}		special_used = TRUE;	    }	}	sym->globnum = nglobs;	nglobs++;    } else	nlocals++;    if (special && !special_used)	error(ERR_NONFATAL, "no special symbol features supported here");}static void elf_add_reloc (struct Section *sect, long segment,			   int type){    struct Reloc *r;    r = *sect->tail = nasm_malloc(sizeof(struct Reloc));    sect->tail = &r->next;    r->next = NULL;    r->address = sect->len;    if (segment == NO_SEG)	r->symbol = 2;    else {	int i;	r->symbol = 0;	for (i=0; i<nsects; i++)	    if (segment == sects[i]->index)		r->symbol = i+3;	if (!r->symbol)	    r->symbol = GLOBAL_TEMP_BASE + raa_read(bsym, segment);    }    r->type = type;    sect->nrelocs++;}/* * This routine deals with ..got and ..sym relocations: the more * complicated kinds. In shared-library writing, some relocations * with respect to global symbols must refer to the precise symbol * rather than referring to an offset from the base of the section * _containing_ the symbol. Such relocations call to this routine, * which searches the symbol list for the symbol in question. * * R_386_GOT32 references require the _exact_ symbol address to be * used; R_386_32 references can be at an offset from the symbol. * The boolean argument `exact' tells us this. * * Return value is the adjusted value of `addr', having become an * offset from the symbol rather than the section. Should always be * zero when returning from an exact call. * * Limitation: if you define two symbols at the same place, * confusion will occur. * * Inefficiency: we search, currently, using a linked list which * isn't even necessarily sorted. */static long elf_add_gsym_reloc (struct Section *sect,				long segment, long offset,				int type, int exact){    struct Reloc *r;    struct Section *s;    struct Symbol *sym, *sm;    int i;    /*     * First look up the segment/offset pair and find a global     * symbol corresponding to it. If it's not one of our segments,     * then it must be an external symbol, in which case we're fine     * doing a normal elf_add_reloc after first sanity-checking     * that the offset from the symbol is zero.     */    s = NULL;    for (i=0; i<nsects; i++)	if (segment == sects[i]->index) {	    s = sects[i];	    break;	}    if (!s) {	if (exact && offset != 0)	    error (ERR_NONFATAL, "unable to find a suitable global symbol"		   " for this reference");	else	    elf_add_reloc (sect, segment, type);	return offset;    }    if (exact) {	/*	 * Find a symbol pointing _exactly_ at this one.	 */	for (sym = s->gsyms; sym; sym = sym->next)	    if (sym->value == offset)		break;    } else {	/*	 * Find the nearest symbol below this one.	 */	sym = NULL;	for (sm = s->gsyms; 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 = GLOBAL_TEMP_BASE + sym->globnum;    r->type = type;    sect->nrelocs++;    return offset - sym->value;}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);    }}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 (&sects[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));

⌨️ 快捷键说明

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