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

📄 xdf-objfmt.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Extended Dynamic Object format * *  Copyright (C) 2004  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: xdf-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#define XDF_MAGIC	0x87654321#define XDF_SYM_EXTERN	1#define XDF_SYM_GLOBAL	2#define XDF_SYM_EQU	4typedef STAILQ_HEAD(xdf_reloc_head, xdf_reloc) xdf_reloc_head;typedef struct xdf_reloc {    yasm_reloc reloc;    /*@null@*/ yasm_symrec *base;   /* base symbol (for WRT) */    enum {	XDF_RELOC_REL = 1,	    /* relative to segment */	XDF_RELOC_WRT = 2,	    /* relative to symbol */	XDF_RELOC_RIP = 4,	    /* RIP-relative */	XDF_RELOC_SEG = 8	    /* segment containing symbol */    } type;			    /* type of relocation */    enum {	XDF_RELOC_8  = 1,         	XDF_RELOC_16 = 2,      	XDF_RELOC_32 = 4,      	XDF_RELOC_64 = 8    } size;			    /* size of relocation */    unsigned int shift;		    /* relocation shift (0,4,8,16,24,32) */} xdf_reloc;typedef struct xdf_section_data {    /*@dependent@*/ yasm_symrec *sym;	/* symbol created for this section */    yasm_intnum *addr;	    /* starting memory address */    long scnum;		    /* section number (0=first section) */    unsigned int align;	    /* section alignment (0-4096) */    enum {	XDF_SECT_ABSOLUTE = 0x01,	XDF_SECT_FLAT = 0x02,	XDF_SECT_BSS = 0x04,	XDF_SECT_EQU = 0x08,	XDF_SECT_USE_16 = 0x10,	XDF_SECT_USE_32 = 0x20,	XDF_SECT_USE_64 = 0x40    } flags;		    /* section flags */    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 */    /*@owned@*/ xdf_reloc_head relocs;} xdf_section_data;typedef struct xdf_symrec_data {    unsigned long index;		/* assigned XDF symbol table index */} xdf_symrec_data;typedef struct xdf_symtab_entry {    STAILQ_ENTRY(xdf_symtab_entry) link;    /*@dependent@*/ yasm_symrec *sym;} xdf_symtab_entry;typedef STAILQ_HEAD(xdf_symtab_head, xdf_symtab_entry) xdf_symtab_head;typedef struct yasm_objfmt_xdf {    yasm_objfmt_base objfmt;		    /* base structure */    long parse_scnum;		    /* sect numbering in parser */    xdf_symtab_head xdf_symtab;	    /* symbol table of indexed syms */    yasm_object *object;    yasm_symtab *symtab;    /*@dependent@*/ yasm_arch *arch;} yasm_objfmt_xdf;typedef struct xdf_objfmt_output_info {    yasm_objfmt_xdf *objfmt_xdf;    /*@dependent@*/ FILE *f;    /*@only@*/ unsigned char *buf;    yasm_section *sect;    /*@dependent@*/ xdf_section_data *xsd;} xdf_objfmt_output_info;static void xdf_section_data_destroy(/*@only@*/ void *d);static void xdf_section_data_print(void *data, FILE *f, int indent_level);static const yasm_assoc_data_callback xdf_section_data_cb = {    xdf_section_data_destroy,    xdf_section_data_print};static void xdf_symrec_data_destroy(/*@only@*/ void *d);static void xdf_symrec_data_print(void *data, FILE *f, int indent_level);static const yasm_assoc_data_callback xdf_symrec_data_cb = {    xdf_symrec_data_destroy,    xdf_symrec_data_print};yasm_objfmt_module yasm_xdf_LTX_objfmt;static /*@dependent@*/ xdf_symtab_entry *xdf_objfmt_symtab_append(yasm_objfmt_xdf *objfmt_xdf, yasm_symrec *sym){    /*@null@*/ /*@dependent@*/ xdf_symrec_data *sym_data_prev;    xdf_symrec_data *sym_data;    xdf_symtab_entry *entry;    unsigned long indx;    if (STAILQ_EMPTY(&objfmt_xdf->xdf_symtab))	indx = 0;    else {	entry = STAILQ_LAST(&objfmt_xdf->xdf_symtab, xdf_symtab_entry, link);	sym_data_prev = yasm_symrec_get_data(entry->sym, &xdf_symrec_data_cb);	assert(sym_data_prev != NULL);	indx = sym_data_prev->index + 1;    }    sym_data = yasm_xmalloc(sizeof(xdf_symrec_data));    sym_data->index = indx;    yasm_symrec_add_data(sym, &xdf_symrec_data_cb, sym_data);    entry = yasm_xmalloc(sizeof(xdf_symtab_entry));    entry->sym = sym;    STAILQ_INSERT_TAIL(&objfmt_xdf->xdf_symtab, entry, link);    return entry;}static intxdf_objfmt_append_local_sym(yasm_symrec *sym, /*@unused@*/ /*@null@*/ void *d){    /*@null@*/ yasm_objfmt_xdf *objfmt_xdf = (yasm_objfmt_xdf *)d;    assert(objfmt_xdf != NULL);    if (!yasm_symrec_get_data(sym, &xdf_symrec_data_cb))	xdf_objfmt_symtab_append(objfmt_xdf, sym);    return 1;}static yasm_objfmt *xdf_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a){    yasm_objfmt_xdf *objfmt_xdf = yasm_xmalloc(sizeof(yasm_objfmt_xdf));    objfmt_xdf->object = object;    objfmt_xdf->symtab = yasm_object_get_symtab(object);    objfmt_xdf->arch = a;    /* Only support x86 arch */    if (yasm__strcasecmp(yasm_arch_keyword(a), "x86") != 0) {	yasm_xfree(objfmt_xdf);	return NULL;    }    /* Support x86 and amd64 machines of x86 arch */    if (yasm__strcasecmp(yasm_arch_get_machine(a), "x86") &&	yasm__strcasecmp(yasm_arch_get_machine(a), "amd64")) {	yasm_xfree(objfmt_xdf);	return NULL;    }    objfmt_xdf->parse_scnum = 0;    /* section numbering starts at 0 */    STAILQ_INIT(&objfmt_xdf->xdf_symtab);    objfmt_xdf->objfmt.module = &yasm_xdf_LTX_objfmt;    return (yasm_objfmt *)objfmt_xdf;}static intxdf_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@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;    yasm_objfmt_xdf *objfmt_xdf;    /*@dependent@*/ /*@null@*/ yasm_intnum *intn;    /*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;    /*@dependent@*/ /*@null@*/ yasm_symrec *sym;    yasm_expr *shr_expr;    yasm_expr *wrt_expr;    unsigned int shr = 0;    unsigned int seg = 0;    assert(info != NULL);    objfmt_xdf = info->objfmt_xdf;    *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_xdf->arch, flt, buf,					  destsize, valsize,					  (unsigned int)shift, warn, bc->line);    }    /* Check for a right shift value */    shr_expr = yasm_expr_extract_shr(ep);    if (shr_expr) {	/*@dependent@*/ /*@null@*/ const yasm_intnum *shr_intn;	shr_intn = yasm_expr_get_intnum(&shr_expr, NULL);	if (!shr_intn) {	    yasm__error(bc->line, N_("shift expression too complex"));	    return 1;	}	shr = yasm_intnum_get_uint(shr_intn);    }    /* Check for a segment relocation */    if (yasm_expr_extract_seg(ep))	seg = 1;    /* Check for a WRT relocation */    wrt_expr = yasm_expr_extract_wrt(ep);    /* Handle integer expressions, with relocation if necessary */    sym = yasm_expr_extract_symrec(ep, 0, yasm_common_calc_bc_dist);    if (sym) {	xdf_reloc *reloc;	reloc = yasm_xmalloc(sizeof(xdf_reloc));	reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);	reloc->reloc.sym = sym;	reloc->base = NULL;	reloc->size = valsize/8;	reloc->shift = shr;	if (seg)	    reloc->type = XDF_RELOC_SEG;	else if (wrt_expr) {	    reloc->base = yasm_expr_extract_symrec(&wrt_expr, 0,						   yasm_common_calc_bc_dist);	    if (!reloc->base) {		yasm__error(bc->line, N_("WRT expression too complex"));		return 1;	    }	    reloc->type = XDF_RELOC_WRT;	} else if (rel) {	    reloc->type = XDF_RELOC_RIP;	    /* Need to reference to start of section, so add $$ in. */	    *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	    reloc->type = XDF_RELOC_REL;	info->xsd->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_xdf->arch, intn,						    valsize, bc, bc->line);	    if (retval)		return retval;	}	return yasm_arch_intnum_tobytes(objfmt_xdf->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_("xdf: relocation too complex"));    return 1;}static intxdf_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d){    /*@null@*/ xdf_objfmt_output_info *info = (xdf_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,			     xdf_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->xsd->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: 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 intxdf_objfmt_output_section(yasm_section *sect, /*@null@*/ void *d){    /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;    /*@dependent@*/ /*@null@*/ xdf_section_data *xsd;    long pos;    xdf_reloc *reloc;    yasm_bytecode *last;    /* FIXME: Don't output absolute sections into the section table */    if (yasm_section_is_absolute(sect))	return 0;    assert(info != NULL);    xsd = yasm_section_get_data(sect, &xdf_section_data_cb);    assert(xsd != NULL);    last = yasm_section_bcs_last(sect);    if (xsd->flags & XDF_SECT_BSS) {	/* Don't output BSS sections.	 * TODO: Check for non-reserve bytecodes?	 */	pos = 0;    /* position = 0 because it's not in the file */	xsd->size = last->offset + last->len;    } else {	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->xsd = xsd;	yasm_section_bcs_traverse(sect, info, xdf_objfmt_output_bytecode);	/* Sanity check final section size */	if (xsd->size != (last->offset + last->len))	    yasm_internal_error(		N_("xdf: section computed size did not match actual size"));    }    /* Empty?  Go on to next section */    if (xsd->size == 0)	return 0;    xsd->scnptr = (unsigned long)pos;    /* No relocations to output?  Go on to next section */    if (xsd->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;    }    xsd->relptr = (unsigned long)pos;    reloc = (xdf_reloc *)yasm_section_relocs_first(sect);    while (reloc) {	unsigned char *localbuf = info->buf;	/*@null@*/ xdf_symrec_data *xsymd;	xsymd = yasm_symrec_get_data(reloc->reloc.sym, &xdf_symrec_data_cb);	if (!xsymd)	    yasm_internal_error(		N_("xdf: 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, xsymd->index);    /* relocated symbol */	if (reloc->base) {	    xsymd = yasm_symrec_get_data(reloc->base, &xdf_symrec_data_cb);	    if (!xsymd)		yasm_internal_error(		    N_("xdf: no symbol data for relocated base symbol"));	    YASM_WRITE_32_L(localbuf, xsymd->index); /* base symbol */	} else {	    if (reloc->type == XDF_RELOC_WRT)		yasm_internal_error(		    N_("xdf: no base symbol for WRT relocation"));	    YASM_WRITE_32_L(localbuf, 0);	    /* no base symbol */	}	YASM_WRITE_8(localbuf, reloc->type);	    /* type of relocation */	YASM_WRITE_8(localbuf, reloc->size);	    /* size of relocation */	YASM_WRITE_8(localbuf, reloc->shift);	    /* relocation shift */	YASM_WRITE_8(localbuf, 0);		    /* flags */	fwrite(info->buf, 16, 1, info->f);	reloc = (xdf_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);    }    return 0;}static intxdf_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d){

⌨️ 快捷键说明

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