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

📄 coff-objfmt.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * COFF (DJGPP) object format * *  Copyright (C) 2002  Peter Johnson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include <util.h>/*@unused@*/ RCSID("$Id: coff-objfmt.c 1168 2004-10-31 01:07:52Z peter $");#define YASM_LIB_INTERNAL#define YASM_BC_INTERNAL#define YASM_EXPR_INTERNAL#include <libyasm.h>#define REGULAR_OUTBUF_SIZE	1024/* Defining this to 0 sets all section VMA's to 0 rather than as the same as * the LMA.  According to the DJGPP COFF Spec, this should be set to 1 * (VMA=LMA), and indeed DJGPP's GCC output shows VMA=LMA.  However, NASM * outputs VMA=0 (as if this was 0), and GNU objdump output looks a lot nicer * with VMA=0.  Who's right?  This is #defined as changing this setting affects * several places in the code. */#define COFF_SET_VMA	(!objfmt_coff->win32)#define COFF_MACHINE_I386	0x014C#define COFF_MACHINE_AMD64	0x8664#define COFF_F_LNNO	0x0004	    /* line number info NOT present */#define COFF_F_LSYMS	0x0008	    /* local symbols NOT present */#define COFF_F_AR32WR	0x0100	    /* 32-bit little endian file */typedef struct coff_reloc {    yasm_reloc reloc;    enum {	COFF_RELOC_ABSOLUTE = 0,	    /* absolute, no reloc needed */	/* I386 relocations */	COFF_RELOC_I386_ADDR16 = 0x1,	    /* 16-bit absolute reference */	COFF_RELOC_I386_REL16 = 0x2,	    /* 16-bit PC-relative reference */	COFF_RELOC_I386_ADDR32 = 0x6,	    /* 32-bit absolute reference */	COFF_RELOC_I386_ADDR32NB = 0x7,	    /* 32-bit absolute ref w/o base */	COFF_RELOC_I386_SEG12 = 0x9,	    /* 16-bit absolute segment ref */	COFF_RELOC_I386_SECTION = 0xA,	    /* section index */	COFF_RELOC_I386_SECREL = 0xB,	    /* offset from start of segment */	COFF_RELOC_I386_TOKEN = 0xC,	    /* CLR metadata token */	COFF_RELOC_I386_SECREL7 = 0xD,	/* 7-bit offset from base of sect */	COFF_RELOC_I386_REL32 = 0x14,	    /* 32-bit PC-relative reference */	/* AMD64 relocations */	COFF_RELOC_AMD64_ADDR64 = 0x1,	    /* 64-bit address (VA) */	COFF_RELOC_AMD64_ADDR32 = 0x2,	    /* 32-bit address (VA) */	COFF_RELOC_AMD64_ADDR32NB = 0x3,    /* 32-bit address w/o base (RVA) */	COFF_RELOC_AMD64_REL32 = 0x4,	    /* 32-bit relative (0 byte dist) */	COFF_RELOC_AMD64_REL32_1 = 0x5,	    /* 32-bit relative (1 byte dist) */	COFF_RELOC_AMD64_REL32_2 = 0x6,	    /* 32-bit relative (2 byte dist) */	COFF_RELOC_AMD64_REL32_3 = 0x7,	    /* 32-bit relative (3 byte dist) */	COFF_RELOC_AMD64_REL32_4 = 0x8,	    /* 32-bit relative (4 byte dist) */	COFF_RELOC_AMD64_REL32_5 = 0x9,	    /* 32-bit relative (5 byte dist) */	COFF_RELOC_AMD64_SECTION = 0xA,	    /* section index */	COFF_RELOC_AMD64_SECREL = 0xB,	/* 32-bit offset from base of sect */	COFF_RELOC_AMD64_SECREL7 = 0xC,	/* 7-bit offset from base of sect */	COFF_RELOC_AMD64_TOKEN = 0xD	    /* CLR metadata token */    } type;			    /* type of relocation */} coff_reloc;#define COFF_STYP_TEXT		0x00000020UL#define COFF_STYP_DATA		0x00000040UL#define COFF_STYP_BSS		0x00000080UL#define COFF_STYP_INFO		0x00000200UL#define COFF_STYP_STD_MASK	0x000003FFUL#define COFF_STYP_ALIGN_MASK	0x00F00000UL#define COFF_STYP_ALIGN_SHIFT	20#define COFF_STYP_DISCARD	0x02000000UL#define COFF_STYP_NOCACHE	0x04000000UL#define COFF_STYP_NOPAGE	0x08000000UL#define COFF_STYP_SHARED	0x10000000UL#define COFF_STYP_EXECUTE	0x20000000UL#define COFF_STYP_READ		0x40000000UL#define COFF_STYP_WRITE		0x80000000UL#define COFF_STYP_WIN32_MASK	0xFE000000ULtypedef struct coff_section_data {    /*@dependent@*/ yasm_symrec *sym;	/* symbol created for this section */    unsigned int scnum;	    /* section number (1=first section) */    unsigned long flags;    /* section flags (see COFF_STYP_* above) */    unsigned long addr;	    /* starting memory address (first section -> 0) */    unsigned long scnptr;   /* file ptr to raw data */    unsigned long size;	    /* size of raw data (section data) in bytes */    unsigned long relptr;   /* file ptr to relocation */    unsigned long nreloc;   /* number of relocation entries >64k -> error */} coff_section_data;typedef enum coff_symrec_sclass {    COFF_SCL_EFCN = 0xff,	/* physical end of function	*/    COFF_SCL_NULL = 0,    COFF_SCL_AUTO = 1,		/* automatic variable		*/    COFF_SCL_EXT = 2,		/* external symbol		*/    COFF_SCL_STAT = 3,		/* static			*/    COFF_SCL_REG = 4,		/* register variable		*/    COFF_SCL_EXTDEF = 5,	/* external definition		*/    COFF_SCL_LABEL = 6,		/* label			*/    COFF_SCL_ULABEL = 7,	/* undefined label		*/    COFF_SCL_MOS = 8,		/* member of structure		*/    COFF_SCL_ARG = 9,		/* function argument		*/    COFF_SCL_STRTAG = 10,	/* structure tag		*/    COFF_SCL_MOU = 11,		/* member of union		*/    COFF_SCL_UNTAG = 12,	/* union tag			*/    COFF_SCL_TPDEF = 13,	/* type definition		*/    COFF_SCL_USTATIC = 14,	/* undefined static		*/    COFF_SCL_ENTAG = 15,	/* enumeration tag		*/    COFF_SCL_MOE = 16,		/* member of enumeration	*/    COFF_SCL_REGPARM = 17,	/* register parameter		*/    COFF_SCL_FIELD = 18,	/* bit field			*/    COFF_SCL_AUTOARG = 19,	/* auto argument		*/    COFF_SCL_LASTENT = 20,	/* dummy entry (end of block)	*/    COFF_SCL_BLOCK = 100,	/* ".bb" or ".eb"		*/    COFF_SCL_FCN = 101,		/* ".bf" or ".ef"		*/    COFF_SCL_EOS = 102,		/* end of structure		*/    COFF_SCL_FILE = 103,	/* file name			*/    COFF_SCL_LINE = 104,	/* line # reformatted as symbol table entry */    COFF_SCL_ALIAS = 105,	/* duplicate tag		*/    COFF_SCL_HIDDEN = 106	/* ext symbol in dmert public lib */} coff_symrec_sclass;typedef struct coff_symrec_data {    unsigned long index;		/* assigned COFF symbol table index */    coff_symrec_sclass sclass;		/* storage class */    /*@owned@*/ /*@null@*/ yasm_expr *size; /* size if COMMON declaration */} coff_symrec_data;typedef union coff_symtab_auxent {    /* no data needed for section symbol auxent, all info avail from sym */    /*@owned@*/ char *fname;	    /* filename aux entry */} coff_symtab_auxent;typedef enum coff_symtab_auxtype {    COFF_SYMTAB_AUX_NONE = 0,    COFF_SYMTAB_AUX_SECT,    COFF_SYMTAB_AUX_FILE} coff_symtab_auxtype;typedef struct coff_symtab_entry {    STAILQ_ENTRY(coff_symtab_entry) link;    /*@dependent@*/ yasm_symrec *sym;    int numaux;			/* number of auxiliary entries */    coff_symtab_auxtype auxtype;    /* type of aux entries */    coff_symtab_auxent aux[1];	/* actually may be any size (including 0) */} coff_symtab_entry;typedef STAILQ_HEAD(coff_symtab_head, coff_symtab_entry) coff_symtab_head;typedef struct yasm_objfmt_coff {    yasm_objfmt_base objfmt;		    /* base structure*/    unsigned int parse_scnum;		    /* sect numbering in parser */    coff_symtab_head coff_symtab;	    /* symbol table of indexed syms */    int win32;				    /* nonzero for win32 output */    unsigned int machine;		    /* COFF machine to use */    yasm_object *object;    yasm_symtab *symtab;    /*@dependent@*/ yasm_arch *arch;} yasm_objfmt_coff;typedef struct coff_objfmt_output_info {    yasm_objfmt_coff *objfmt_coff;    /*@dependent@*/ FILE *f;    /*@only@*/ unsigned char *buf;    yasm_section *sect;    /*@dependent@*/ coff_section_data *csd;    unsigned long addr;	    /* start of next section */} coff_objfmt_output_info;static void coff_section_data_destroy(/*@only@*/ void *d);static void coff_section_data_print(void *data, FILE *f, int indent_level);static const yasm_assoc_data_callback coff_section_data_cb = {    coff_section_data_destroy,    coff_section_data_print};static void coff_symrec_data_destroy(/*@only@*/ void *d);static void coff_symrec_data_print(void *data, FILE *f, int indent_level);static const yasm_assoc_data_callback coff_symrec_data_cb = {    coff_symrec_data_destroy,    coff_symrec_data_print};yasm_objfmt_module yasm_coff_LTX_objfmt;yasm_objfmt_module yasm_win32_LTX_objfmt;static /*@dependent@*/ coff_symtab_entry *coff_objfmt_symtab_append(yasm_objfmt_coff *objfmt_coff, yasm_symrec *sym,			  coff_symrec_sclass sclass,			  /*@only@*/ /*@null@*/ yasm_expr *size, int numaux,			  coff_symtab_auxtype auxtype){    /*@null@*/ /*@dependent@*/ coff_symrec_data *sym_data_prev;    coff_symrec_data *sym_data;    coff_symtab_entry *entry;    if (STAILQ_EMPTY(&objfmt_coff->coff_symtab))	yasm_internal_error(N_("empty COFF symbol table"));    entry = STAILQ_LAST(&objfmt_coff->coff_symtab, coff_symtab_entry, link);    sym_data_prev = yasm_symrec_get_data(entry->sym, &coff_symrec_data_cb);    assert(sym_data_prev != NULL);    sym_data = yasm_xmalloc(sizeof(coff_symrec_data));    sym_data->index = sym_data_prev->index + entry->numaux + 1;    sym_data->sclass = sclass;    sym_data->size = size;    yasm_symrec_add_data(sym, &coff_symrec_data_cb, sym_data);    entry = yasm_xmalloc(sizeof(coff_symtab_entry) +			 (numaux-1)*sizeof(coff_symtab_auxent));    entry->sym = sym;    entry->numaux = numaux;    entry->auxtype = auxtype;    STAILQ_INSERT_TAIL(&objfmt_coff->coff_symtab, entry, link);    return entry;}static intcoff_objfmt_append_local_sym(yasm_symrec *sym, /*@unused@*/ /*@null@*/ void *d){    /*@null@*/ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)d;    assert(objfmt_coff != NULL);    if (!yasm_symrec_get_data(sym, &coff_symrec_data_cb))	coff_objfmt_symtab_append(objfmt_coff, sym, COFF_SCL_STAT, NULL, 0,				  COFF_SYMTAB_AUX_NONE);    return 1;}static yasm_objfmt_coff *coff_common_create(const char *in_filename, yasm_object *object, yasm_arch *a){    yasm_objfmt_coff *objfmt_coff = yasm_xmalloc(sizeof(yasm_objfmt_coff));    yasm_symrec *filesym;    coff_symrec_data *data;    coff_symtab_entry *entry;    objfmt_coff->object = object;    objfmt_coff->symtab = yasm_object_get_symtab(object);    objfmt_coff->arch = a;    /* Only support x86 arch */    if (yasm__strcasecmp(yasm_arch_keyword(a), "x86") != 0) {	yasm_xfree(objfmt_coff);	return NULL;    }    /* Support x86 and amd64 machines of x86 arch */    if (yasm__strcasecmp(yasm_arch_get_machine(a), "x86") == 0) {	objfmt_coff->machine = COFF_MACHINE_I386;    } else if (yasm__strcasecmp(yasm_arch_get_machine(a), "amd64") == 0) {	objfmt_coff->machine = COFF_MACHINE_AMD64;    } else {	yasm_xfree(objfmt_coff);	return NULL;    }    objfmt_coff->parse_scnum = 1;    /* section numbering starts at 1 */    STAILQ_INIT(&objfmt_coff->coff_symtab);    data = yasm_xmalloc(sizeof(coff_symrec_data));    data->index = 0;    data->sclass = COFF_SCL_FILE;    data->size = NULL;    /* FIXME: misuse of NULL bytecode here; it works, but only barely. */    filesym = yasm_symtab_define_label(objfmt_coff->symtab, ".file", NULL, 0,				       0);    yasm_symrec_add_data(filesym, &coff_symrec_data_cb, data);    entry = yasm_xmalloc(sizeof(coff_symtab_entry));    entry->sym = filesym;    entry->numaux = 1;    entry->auxtype = COFF_SYMTAB_AUX_FILE;    entry->aux[0].fname = yasm__xstrdup(in_filename);    STAILQ_INSERT_TAIL(&objfmt_coff->coff_symtab, entry, link);    return objfmt_coff;}static yasm_objfmt *coff_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a){    yasm_objfmt_coff *objfmt_coff =	coff_common_create(in_filename, object, a);    if (objfmt_coff) {	objfmt_coff->objfmt.module = &yasm_coff_LTX_objfmt;	objfmt_coff->win32 = 0;    }    return (yasm_objfmt *)objfmt_coff;}static yasm_objfmt *win32_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a){    yasm_objfmt_coff *objfmt_coff =	coff_common_create(in_filename, object, a);    if (objfmt_coff) {	objfmt_coff->objfmt.module = &yasm_win32_LTX_objfmt;	objfmt_coff->win32 = 1;    }    return (yasm_objfmt *)objfmt_coff;}static intcoff_objfmt_set_section_addr(yasm_section *sect, /*@null@*/ void *d){    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;    /*@dependent@*/ /*@null@*/ coff_section_data *csd;    /*@null@*/ yasm_bytecode *last;    /* Don't output absolute sections */    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;    last = yasm_section_bcs_last(sect);    if (last)	info->addr += last->offset + last->len;    return 0;}static intcoff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,			size_t valsize, int shift, unsigned long offset,			yasm_bytecode *bc, int rel, int warn,			/*@null@*/ void *d){    /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;    yasm_objfmt_coff *objfmt_coff;    /*@dependent@*/ /*@null@*/ yasm_intnum *intn;    /*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;    /*@dependent@*/ /*@null@*/ yasm_symrec *sym;    /*@dependent@*/ yasm_section *label_sect;    /*@dependent@*/ /*@null@*/ yasm_bytecode *label_precbc;    assert(info != NULL);    objfmt_coff = info->objfmt_coff;    *ep = yasm_expr_simplify(*ep, yasm_common_calc_bc_dist);    /* Handle floating point expressions */    flt = yasm_expr_get_floatnum(ep);    if (flt) {	if (shift < 0)	    yasm_internal_error(N_("attempting to negative shift a float"));	return yasm_arch_floatnum_tobytes(objfmt_coff->arch, flt, buf,					  destsize, valsize,					  (unsigned int)shift, warn, bc->line);    }    /* Handle integer expressions, with relocation if necessary */    sym = yasm_expr_extract_symrec(ep, 1, yasm_common_calc_bc_dist);    if (sym) {	unsigned long addr;	coff_reloc *reloc;	yasm_sym_vis vis;	if (valsize != 32) {	    yasm__error(bc->line, N_("coff: invalid relocation size"));	    return 1;	}	reloc = yasm_xmalloc(sizeof(coff_reloc));	addr = bc->offset + offset;	if (COFF_SET_VMA)	    addr += info->addr;	reloc->reloc.addr = yasm_intnum_create_uint(addr);	reloc->reloc.sym = sym;	vis = yasm_symrec_get_visibility(sym);	if (vis & YASM_SYM_COMMON) {	    /* In standard COFF, COMMON symbols have their length added in */	    if (!objfmt_coff->win32) {		/*@dependent@*/ /*@null@*/ coff_symrec_data *csymd;		csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb);		assert(csymd != NULL);		*ep = yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(*ep),		    yasm_expr_expr(yasm_expr_copy(csymd->size)),		    csymd->size->line);		*ep = yasm_expr_simplify(*ep, yasm_common_calc_bc_dist);	    }	} else if (!(vis & YASM_SYM_EXTERN)) {	    /* Local symbols need relocation to their section's start */	    if (yasm_symrec_get_label(sym, &label_precbc)) {		/*@null@*/ coff_section_data *label_csd;		label_sect = yasm_bc_get_section(label_precbc);		label_csd = yasm_section_get_data(label_sect,						  &coff_section_data_cb);		assert(label_csd != NULL);		reloc->reloc.sym = label_csd->sym;		if (COFF_SET_VMA)		    *ep = yasm_expr_create(YASM_EXPR_ADD, yasm_expr_expr(*ep),			yasm_expr_int(yasm_intnum_create_uint(label_csd->addr)),			(*ep)->line);	    }	}

⌨️ 快捷键说明

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