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

📄 bin-objfmt.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Flat-format binary 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: bin-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	1024static void bin_section_data_destroy(/*@only@*/ void *d);static void bin_section_data_print(void *data, FILE *f, int indent_level);static const yasm_assoc_data_callback bin_section_data_callback = {    bin_section_data_destroy,    bin_section_data_print};typedef struct yasm_objfmt_bin {    yasm_objfmt_base objfmt;		/* base structure */    yasm_object *object;    yasm_symtab *symtab;    /*@dependent@*/ yasm_arch *arch;} yasm_objfmt_bin;yasm_objfmt_module yasm_bin_LTX_objfmt;static yasm_objfmt *bin_objfmt_create(/*@unused@*/ const char *in_filename, yasm_object *object,		  yasm_arch *a){    yasm_objfmt_bin *objfmt_bin = yasm_xmalloc(sizeof(yasm_objfmt_bin));    objfmt_bin->objfmt.module = &yasm_bin_LTX_objfmt;    objfmt_bin->object = object;    objfmt_bin->symtab = yasm_object_get_symtab(object);    objfmt_bin->arch = a;    return (yasm_objfmt *)objfmt_bin;}/* Aligns sect to either its specified alignment (in its objfmt-specific data) * or def_align if no alignment was specified.  Uses prevsect and base to both * determine the new starting address (returned) and the total length of * prevsect after sect has been aligned. */static unsigned longbin_objfmt_align_section(yasm_section *sect, yasm_section *prevsect,			 unsigned long base, unsigned long def_align,			 /*@out@*/ unsigned long *prevsectlen,			 /*@out@*/ unsigned long *padamt){    /*@dependent@*/ /*@null@*/ yasm_bytecode *last;    unsigned long start;    /*@dependent@*/ /*@null@*/ unsigned long *alignptr;    unsigned long align;    /* Figure out the size of .text by looking at the last bytecode's offset     * plus its length.  Add the start and size together to get the new start.     */    last = yasm_section_bcs_last(prevsect);    if (last)	*prevsectlen = last->offset + last->len;    else	*prevsectlen = 0;    start = base + *prevsectlen;    /* Round new start up to alignment of .data section, and adjust textlen to     * indicate padded size.  Because aignment is always a power of two, we     * can use some bit trickery to do this easily.     */    alignptr = yasm_section_get_data(sect, &bin_section_data_callback);    if (alignptr)	align = *alignptr;    else	align = def_align;	/* No alignment: use default */    if (start & (align-1))	start = (start & ~(align-1)) + align;    *padamt = start - (base + *prevsectlen);    return start;}typedef struct bin_objfmt_output_info {    yasm_objfmt_bin *objfmt_bin;    /*@dependent@*/ FILE *f;    /*@only@*/ unsigned char *buf;    /*@observer@*/ const yasm_section *sect;    unsigned long start;} bin_objfmt_output_info;static /*@only@*/ yasm_expr *bin_objfmt_expr_xform(/*@returned@*/ /*@only@*/ yasm_expr *e,		      /*@unused@*/ /*@null@*/ void *d){    int i;    /*@dependent@*/ yasm_section *sect;    /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;    /*@null@*/ yasm_intnum *dist;    for (i=0; i<e->numterms; i++) {	/* Transform symrecs that reference sections into	 * start expr + intnum(dist).	 */	if (e->terms[i].type == YASM_EXPR_SYM &&	    yasm_symrec_get_label(e->terms[i].data.sym, &precbc) &&	    (sect = yasm_bc_get_section(precbc)) &&	    (dist = yasm_common_calc_bc_dist(yasm_section_bcs_first(sect),					     precbc))) {	    const yasm_expr *start = yasm_section_get_start(sect);	    e->terms[i].type = YASM_EXPR_EXPR;	    e->terms[i].data.expn =		yasm_expr_create(YASM_EXPR_ADD,				 yasm_expr_expr(yasm_expr_copy(start)),				 yasm_expr_int(dist), e->line);	}    }    return e;}static intbin_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,		       size_t valsize, int shift,		       /*@unused@*/ unsigned long offset, yasm_bytecode *bc,		       int rel, int warn, /*@null@*/ void *d){    /*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;    /*@dependent@*/ /*@null@*/ yasm_intnum *intn;    /*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;    assert(info != NULL);    /* For binary output, this is trivial: any expression that doesn't simplify     * to an integer is an error (references something external).     * Other object formats need to generate their relocation list from here!     */    *ep = yasm_expr__level_tree(*ep, 1, 1, NULL, bin_objfmt_expr_xform, NULL,				NULL);    /* 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(info->objfmt_bin->arch, flt, buf,					  destsize, valsize,					  (unsigned int)shift, warn, bc->line);    }    /* Handle integer expressions */    intn = yasm_expr_get_intnum(ep, NULL);    if (intn) {	if (rel) {	    int retval = yasm_arch_intnum_fixup_rel(info->objfmt_bin->arch,						    intn, valsize, bc,						    bc->line);	    if (retval)		return retval;	}	return yasm_arch_intnum_tobytes(info->objfmt_bin->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;    }    /* Couldn't output, assume it contains an external reference. */    yasm__error(bc->line,	N_("binary object format does not support external references"));    return 1;}static intbin_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d){    /*@null@*/ bin_objfmt_output_info *info = (bin_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,			     bin_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;    }    /* 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 voidbin_objfmt_output(yasm_objfmt *objfmt, FILE *f, const char *obj_filename,		  /*@unused@*/ int all_syms, /*@unused@*/ yasm_dbgfmt *df){    yasm_objfmt_bin *objfmt_bin = (yasm_objfmt_bin *)objfmt;    /*@observer@*/ /*@null@*/ yasm_section *text, *data, *bss, *prevsect;    /*@null@*/ yasm_expr *startexpr;    /*@dependent@*/ /*@null@*/ const yasm_intnum *startnum;    unsigned long start = 0, textstart = 0, datastart = 0;    unsigned long textlen = 0, textpad = 0, datalen = 0, datapad = 0;    unsigned long *prevsectlenptr, *prevsectpadptr;    unsigned long i;    bin_objfmt_output_info info;    info.objfmt_bin = objfmt_bin;    info.f = f;    info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);    text = yasm_object_find_general(objfmt_bin->object, ".text");    data = yasm_object_find_general(objfmt_bin->object, ".data");    bss = yasm_object_find_general(objfmt_bin->object, ".bss");    if (!text)	yasm_internal_error(N_("No `.text' section in bin objfmt output"));    /* First determine the actual starting offsets for .data and .bss.     * As the order in the file is .text -> .data -> .bss (not present),     * use the last bytecode in .text (and the .text section start) to     * determine the starting offset in .data, and likewise for .bss.     * Also compensate properly for alignment.     */    /* Find out the start of .text */    startexpr = yasm_expr_copy(yasm_section_get_start(text));

⌨️ 快捷键说明

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