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

📄 coff-objfmt.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (rel) {	    if (objfmt_coff->machine == COFF_MACHINE_I386)		reloc->type = COFF_RELOC_I386_REL32;	    else if (objfmt_coff->machine == COFF_MACHINE_AMD64)		reloc->type = COFF_RELOC_AMD64_REL32;	    else		yasm_internal_error(N_("coff objfmt: unrecognized machine"));	    /* For standard COFF, need to reference to start of section, so add	     * $$ in.	     * For Win32 COFF, need to reference to next bytecode, so add '$'	     * (really $+$.len) in.	     */	    if (objfmt_coff->win32)		*ep = yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(*ep),		    yasm_expr_sym(yasm_symtab_define_label2("$", bc,							    0, (*ep)->line)),		    (*ep)->line);	    else		*ep = yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(*ep),		    yasm_expr_sym(yasm_symtab_define_label2("$$",			yasm_section_bcs_first(info->sect), 0, (*ep)->line)),		    (*ep)->line);	    *ep = yasm_expr_simplify(*ep, yasm_common_calc_bc_dist);	} else {	    if (objfmt_coff->machine == COFF_MACHINE_I386)		reloc->type = COFF_RELOC_I386_ADDR32;	    else if (objfmt_coff->machine == COFF_MACHINE_AMD64)		reloc->type = COFF_RELOC_AMD64_ADDR32;	    else		yasm_internal_error(N_("coff objfmt: unrecognized machine"));	}	info->csd->nreloc++;	yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);    }    intn = yasm_expr_get_intnum(ep, NULL);    if (intn) {	if (rel) {	    int retval = yasm_arch_intnum_fixup_rel(objfmt_coff->arch, intn,						    valsize, bc, bc->line);	    if (retval)		return retval;	}	return yasm_arch_intnum_tobytes(objfmt_coff->arch, intn, buf, destsize,					valsize, shift, bc, warn, bc->line);    }    /* Check for complex float expressions */    if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {	yasm__error(bc->line, N_("floating point expression too complex"));	return 1;    }    yasm__error(bc->line, N_("coff: relocation too complex"));    return 1;}static intcoff_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d){    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;    /*@null@*/ /*@only@*/ unsigned char *bigbuf;    unsigned long size = REGULAR_OUTBUF_SIZE;    unsigned long multiple;    unsigned long i;    int gap;    assert(info != NULL);    bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &multiple, &gap, info,			     coff_objfmt_output_expr, NULL);    /* Don't bother doing anything else if size ended up being 0. */    if (size == 0) {	if (bigbuf)	    yasm_xfree(bigbuf);	return 0;    }    info->csd->size += multiple*size;    /* Warn that gaps are converted to 0 and write out the 0's. */    if (gap) {	unsigned long left;	yasm__warning(YASM_WARN_GENERAL, bc->line,	    N_("uninitialized space declared in code/data section: zeroing"));	/* Write out in chunks */	memset(info->buf, 0, REGULAR_OUTBUF_SIZE);	left = multiple*size;	while (left > REGULAR_OUTBUF_SIZE) {	    fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);	    left -= REGULAR_OUTBUF_SIZE;	}	fwrite(info->buf, left, 1, info->f);    } else {	/* Output multiple copies of buf (or bigbuf if non-NULL) to file */	for (i=0; i<multiple; i++)	    fwrite(bigbuf ? bigbuf : info->buf, (size_t)size, 1, info->f);    }    /* If bigbuf was allocated, free it */    if (bigbuf)	yasm_xfree(bigbuf);    return 0;}static intcoff_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d){    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;    /*@dependent@*/ /*@null@*/ coff_section_data *csd;    long pos;    coff_reloc *reloc;    /* Don't output absolute sections into the section table */    if (yasm_section_is_absolute(sect))	return 0;    assert(info != NULL);    csd = yasm_section_get_data(sect, &coff_section_data_cb);    assert(csd != NULL);    csd->addr = info->addr;    if ((csd->flags & COFF_STYP_STD_MASK) == COFF_STYP_BSS) {	yasm_bytecode *last = yasm_section_bcs_last(sect);	/* Don't output BSS sections.	 * TODO: Check for non-reserve bytecodes?	 */	pos = 0;    /* position = 0 because it's not in the file */	csd->size = last->offset + last->len;    } else {	yasm_bytecode *last = yasm_section_bcs_last(sect);	pos = ftell(info->f);	if (pos == -1) {	    yasm__fatal(N_("could not get file position on output file"));	    /*@notreached@*/	    return 1;	}	info->sect = sect;	info->csd = csd;	yasm_section_bcs_traverse(sect, info, coff_objfmt_output_bytecode);	/* Sanity check final section size */	if (csd->size != (last->offset + last->len))	    yasm_internal_error(		N_("coff: section computed size did not match actual size"));    }    /* Empty?  Go on to next section */    if (csd->size == 0)	return 0;    info->addr += csd->size;    csd->scnptr = (unsigned long)pos;    /* No relocations to output?  Go on to next section */    if (csd->nreloc == 0)	return 0;    pos = ftell(info->f);    if (pos == -1) {	yasm__fatal(N_("could not get file position on output file"));	/*@notreached@*/	return 1;    }    csd->relptr = (unsigned long)pos;    reloc = (coff_reloc *)yasm_section_relocs_first(sect);    while (reloc) {	unsigned char *localbuf = info->buf;	/*@null@*/ coff_symrec_data *csymd;	csymd = yasm_symrec_get_data(reloc->reloc.sym, &coff_symrec_data_cb);	if (!csymd)	    yasm_internal_error(		N_("coff: no symbol data for relocated symbol"));	yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0, 0);	localbuf += 4;				/* address of relocation */	YASM_WRITE_32_L(localbuf, csymd->index);    /* relocated symbol */	YASM_WRITE_16_L(localbuf, reloc->type);	    /* type of relocation */	fwrite(info->buf, 10, 1, info->f);	reloc = (coff_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);    }    return 0;}static intcoff_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d){    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;    yasm_objfmt_coff *objfmt_coff;    /*@dependent@*/ /*@null@*/ coff_section_data *csd;    unsigned char *localbuf;    /* Don't output absolute sections into the section table */    if (yasm_section_is_absolute(sect))	return 0;    assert(info != NULL);    objfmt_coff = info->objfmt_coff;    csd = yasm_section_get_data(sect, &coff_section_data_cb);    assert(csd != NULL);    localbuf = info->buf;    strncpy((char *)localbuf, yasm_section_get_name(sect), 8);/* section name */    localbuf += 8;    YASM_WRITE_32_L(localbuf, csd->addr);	/* physical address */    if (COFF_SET_VMA)	YASM_WRITE_32_L(localbuf, csd->addr);   /* virtual address */    else	YASM_WRITE_32_L(localbuf, 0);		/* virtual address */    YASM_WRITE_32_L(localbuf, csd->size);	/* section size */    YASM_WRITE_32_L(localbuf, csd->scnptr);	/* file ptr to data */    YASM_WRITE_32_L(localbuf, csd->relptr);	/* file ptr to relocs */    YASM_WRITE_32_L(localbuf, 0);		/* file ptr to line nums */    if (csd->nreloc >= 64*1024) {	yasm__warning(YASM_WARN_GENERAL, 0,		      N_("too many relocations in section `%s'"),		      yasm_section_get_name(sect));	YASM_WRITE_16_L(localbuf, 0xFFFF);	/* max out */    } else	YASM_WRITE_16_L(localbuf, csd->nreloc); /* num of relocation entries */    YASM_WRITE_16_L(localbuf, 0);		/* num of line number entries */    YASM_WRITE_32_L(localbuf, csd->flags);	/* flags */    fwrite(info->buf, 40, 1, info->f);    return 0;}static voidcoff_objfmt_output(yasm_objfmt *objfmt, FILE *f, const char *obj_filename,		   int all_syms, /*@unused@*/ yasm_dbgfmt *df){    yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)objfmt;    coff_objfmt_output_info info;    unsigned char *localbuf;    long pos;    unsigned long symtab_pos;    unsigned long symtab_count = 0;    unsigned long strtab_offset = 4;    coff_symtab_entry *entry;    info.objfmt_coff = objfmt_coff;    info.f = f;    info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);    /* Allocate space for headers by seeking forward */    if (fseek(f, (long)(20+40*(objfmt_coff->parse_scnum-1)), SEEK_SET) < 0) {	yasm__fatal(N_("could not seek on output file"));	/*@notreached@*/	return;    }    /* Section data/relocs */    if (COFF_SET_VMA) {	/* If we're setting the VMA, we need to do a first section pass to	 * determine each section's addr value before actually outputting	 * relocations, as a relocation's section address is added into the	 * addends in the generated code.	 */	info.addr = 0;	if (yasm_object_sections_traverse(objfmt_coff->object, &info,					  coff_objfmt_set_section_addr))	    return;    }    info.addr = 0;    if (yasm_object_sections_traverse(objfmt_coff->object, &info,				      coff_objfmt_output_section))	return;    /* Symbol table */    if (all_syms) {	/* Need to put all local syms into COFF symbol table */	yasm_symtab_traverse(objfmt_coff->symtab, objfmt_coff,			     coff_objfmt_append_local_sym);    }    pos = ftell(f);    if (pos == -1) {	yasm__fatal(N_("could not get file position on output file"));	/*@notreached@*/	return;    }    symtab_pos = (unsigned long)pos;    STAILQ_FOREACH(entry, &objfmt_coff->coff_symtab, link) {	const char *name = yasm_symrec_get_name(entry->sym);	const yasm_expr *equ_val;	const yasm_intnum *intn;	size_t len = strlen(name);	int aux;	/*@dependent@*/ /*@null@*/ coff_symrec_data *csymd;	unsigned long value = 0;	unsigned int scnum = 0xfffe;	/* -2 = debugging symbol */	/*@dependent@*/ /*@null@*/ yasm_section *sect;	/*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;	unsigned long scnlen = 0;   /* for sect auxent */	unsigned long nreloc = 0;   /* for sect auxent */	/* Get symrec's of_data (needed for storage class) */	csymd = yasm_symrec_get_data(entry->sym, &coff_symrec_data_cb);	if (!csymd)	    yasm_internal_error(N_("coff: expected sym data to be present"));	/* Look at symrec for value/scnum/etc. */	if (yasm_symrec_get_label(entry->sym, &precbc)) {	    if (precbc)		sect = yasm_bc_get_section(precbc);	    else		sect = NULL;	    /* it's a label: get value and offset.	     * If there is not a section, leave as debugging symbol.	     */	    if (sect) {		/*@dependent@*/ /*@null@*/ coff_section_data *csectd;		csectd = yasm_section_get_data(sect, &coff_section_data_cb);		if (csectd) {		    scnum = csectd->scnum;		    scnlen = csectd->size;		    nreloc = csectd->nreloc;		    if (COFF_SET_VMA)			value = csectd->addr;		} else if (yasm_section_is_absolute(sect)) {		    yasm_expr *abs_start;		    abs_start = yasm_expr_copy(yasm_section_get_start(sect));		    intn = yasm_expr_get_intnum(&abs_start,						yasm_common_calc_bc_dist);		    if (!intn)			yasm__error(abs_start->line,			    N_("absolute section start not an integer expression"));		    else			value = yasm_intnum_get_uint(intn);		    yasm_expr_destroy(abs_start);		    scnum = 0xffff;	/* -1 = absolute symbol */		} else		    yasm_internal_error(N_("didn't understand section"));		if (precbc)		    value += precbc->offset + precbc->len;	    }	} else if ((equ_val = yasm_symrec_get_equ(entry->sym))) {	    yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);	    intn = yasm_expr_get_intnum(&equ_val_copy,					yasm_common_calc_bc_dist);	    if (!intn) {		yasm_sym_vis vis = yasm_symrec_get_visibility(entry->sym);		if (vis & YASM_SYM_GLOBAL)		    yasm__error(equ_val->line,			N_("global EQU value not an integer expression"));	    } else		value = yasm_intnum_get_uint(intn);	    yasm_expr_destroy(equ_val_copy);	    scnum = 0xffff;     /* -1 = absolute symbol */	} else {	    yasm_sym_vis vis = yasm_symrec_get_visibility(entry->sym);	    if (vis & YASM_SYM_COMMON) {		intn = yasm_expr_get_intnum(&csymd->size,					    yasm_common_calc_bc_dist);		if (!intn)		    yasm__error(csymd->size->line,			N_("COMMON data size not an integer expression"));		else		    value = yasm_intnum_get_uint(intn);		scnum = 0;	    }	    if (vis & YASM_SYM_EXTERN)		scnum = 0;	}	localbuf = info.buf;	if (len > 8) {	    YASM_WRITE_32_L(localbuf, 0);	/* "zeros" field */	    YASM_WRITE_32_L(localbuf, strtab_offset); /* string table offset */	    strtab_offset += len+1;	} else {	    /* <8 chars, so no string table entry needed */	    strncpy((char *)localbuf, name, 8);	    localbuf += 8;	}	YASM_WRITE_32_L(localbuf, value);	/* value */	YASM_WRITE_16_L(localbuf, scnum);	/* section number */	YASM_WRITE_16_L(localbuf, 0);	    /* type is always zero (for now) */	YASM_WRITE_8(localbuf, csymd->sclass);	/* storage class */	YASM_WRITE_8(localbuf, entry->numaux);	/* number of aux entries */	fwrite(info.buf, 18, 1, f);	for (aux=0; aux<entry->numaux; aux++) {	    localbuf = info.buf;	    memset(localbuf, 0, 18);	    switch (entry->auxtype) {		case COFF_SYMTAB_AUX_NONE:		    break;		case COFF_SYMTAB_AUX_SECT:		    YASM_WRITE_32_L(localbuf, scnlen);	/* section length */		    YASM_WRITE_16_L(localbuf, nreloc);	/* number relocs */		    YASM_WRITE_16_L(localbuf, 0);	/* number line nums */		    break;		case COFF_SYMTAB_AUX_FILE:		    len = strlen(entry->aux[0].fname);		    if (len > 14) {			YASM_WRITE_32_L(localbuf, 0);			YASM_WRITE_32_L(localbuf, strtab_offset);			strtab_offset += len+1;		    } else			strncpy((char *)localbuf, entry->aux[0].fname, 14);		    break;		default:		    yasm_internal_error(			N_("coff: unrecognized aux symtab type"));	    }	    fwrite(info.buf, 18, 1, f);	    symtab_count++;	}	symtab_count++;    }    /* String table */    yasm_fwrite_32_l(strtab_offset, f); /* first four bytes are total length */    STAILQ_FOREACH(entry, &objfmt_coff->coff_symtab, link) {	const char *name = yasm_symrec_get_name(entry->sym);	size_t len = strlen(name);	int aux;	if (len > 8)	    fwrite(name, len+1, 1, f);

⌨️ 快捷键说明

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