示例#1
0
文件: expr.c 项目: Acidburn0zzz/yasm
/*@-compmempass@*/
yasm_expr *
yasm_expr_create(yasm_expr_op op, yasm_expr__item *left,
                 yasm_expr__item *right, unsigned long line)
{
    yasm_expr *ptr, *sube;
    unsigned long z;
    ptr = yasm_xmalloc(sizeof(yasm_expr));

    ptr->op = op;
    ptr->numterms = 0;
    ptr->terms[0].type = YASM_EXPR_NONE;
    ptr->terms[1].type = YASM_EXPR_NONE;
    if (left) {
        ptr->terms[0] = *left;  /* structure copy */
        z = (unsigned long)(left-itempool);
        if (z>=31)
            yasm_internal_error(N_("could not find expritem in pool"));
        itempool_used &= ~(1<<z);
        ptr->numterms++;

        /* Search downward until we find something *other* than an
         * IDENT, then bring it up to the current level.
         */
        while (ptr->terms[0].type == YASM_EXPR_EXPR &&
               ptr->terms[0].data.expn->op == YASM_EXPR_IDENT) {
            sube = ptr->terms[0].data.expn;
            ptr->terms[0] = sube->terms[0];     /* structure copy */
            /*@-usereleased@*/
            yasm_xfree(sube);
            /*@=usereleased@*/
        }
    } else {
        yasm_internal_error(N_("Right side of expression must exist"));
    }

    if (right) {
        ptr->terms[1] = *right; /* structure copy */
        z = (unsigned long)(right-itempool);
        if (z>=31)
            yasm_internal_error(N_("could not find expritem in pool"));
        itempool_used &= ~(1<<z);
        ptr->numterms++;

        /* Search downward until we find something *other* than an
         * IDENT, then bring it up to the current level.
         */
        while (ptr->terms[1].type == YASM_EXPR_EXPR &&
               ptr->terms[1].data.expn->op == YASM_EXPR_IDENT) {
            sube = ptr->terms[1].data.expn;
            ptr->terms[1] = sube->terms[0];     /* structure copy */
            /*@-usereleased@*/
            yasm_xfree(sube);
            /*@=usereleased@*/
        }
    }

    ptr->line = line;

    return expr_level_op(ptr, 1, 1, 0);
}
示例#2
0
文件: elf.c 项目: Mirocow/balancer
/* takes ownership of addr */
elf_reloc_entry *
elf_reloc_entry_create(yasm_symrec *sym,
                       yasm_symrec *wrt,
                       yasm_intnum *addr,
                       int rel,
                       size_t valsize)
{
    elf_reloc_entry *entry;

    if (!elf_march->accepts_reloc)
        yasm_internal_error(N_("Unsupported machine for ELF output"));

    if (!elf_march->accepts_reloc(valsize, wrt, elf_ssyms))
    {
        if (addr)
            yasm_intnum_destroy(addr);
        return NULL;
    }

    if (sym == NULL)
        yasm_internal_error("sym is null");

    entry = yasm_xmalloc(sizeof(elf_reloc_entry));
    entry->reloc.sym = sym;
    entry->reloc.addr = addr;
    entry->rtype_rel = rel;
    entry->valsize = valsize;
    entry->addend = NULL;
    entry->wrt = wrt;

    return entry;
}
示例#3
0
文件: intnum.c 项目: kstephens/yasm
long
yasm_intnum_get_int(const yasm_intnum *intn)
{
    switch (intn->type) {
        case INTNUM_L:
            return intn->val.l;
        case INTNUM_BV:
            if (BitVector_msb_(intn->val.bv)) {
                /* it's negative: negate the bitvector to get a positive
                 * number, then negate the positive number.
                 */
                unsigned long ul;

                BitVector_Negate(conv_bv, intn->val.bv);
                if (Set_Max(conv_bv) >= 32) {
                    /* too negative */
                    return LONG_MIN;
                }
                ul = BitVector_Chunk_Read(conv_bv, 32, 0);
                /* check for too negative */
                return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
            }

            /* it's positive, and since it's a BV, it must be >0x7FFFFFFF */
            return LONG_MAX;
        default:
            yasm_internal_error(N_("unknown intnum type"));
            /*@notreached@*/
            return 0;
    }
}
示例#4
0
文件: intnum.c 项目: kstephens/yasm
yasm_intnum *
yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize,
                         int bigendian)
{
    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
    unsigned long i = 0;

    if (srcsize*8 > BITVECT_NATIVE_SIZE)
        yasm_error_set(YASM_ERROR_OVERFLOW,
                       N_("Numeric constant too large for internal format"));

    /* Read the buffer into a bitvect */
    BitVector_Empty(conv_bv);
    if (bigendian) {
        /* TODO */
        yasm_internal_error(N_("big endian not implemented"));
    } else {
        for (i = 0; i < srcsize; i++)
            BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]);
    }

    /* Sign extend if needed */
    if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80)
        BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1);

    intnum_frombv(intn, conv_bv);
    return intn;
}
/*@null@*/ /*@only@*/ unsigned char *
yasm_bc_tobytes(yasm_bytecode *bc, unsigned char *buf, unsigned long *bufsize,
                /*@out@*/ int *gap, void *d,
                yasm_output_value_func output_value,
                /*@null@*/ yasm_output_reloc_func output_reloc)
    /*@sets *buf@*/
{
    /*@only@*/ /*@null@*/ unsigned char *mybuf = NULL;
    unsigned char *origbuf, *destbuf;
    long i;
    int error = 0;

    if (yasm_bc_get_multiple(bc, &bc->mult_int, 1) || bc->mult_int == 0) {
        *bufsize = 0;
        return NULL;
    }

    /* special case for reserve bytecodes */
    if (bc->callback->special == YASM_BC_SPECIAL_RESERVE) {
        *bufsize = bc->len*bc->mult_int;
        *gap = 1;
        return NULL;    /* we didn't allocate a buffer */
    }
    *gap = 0;

    if (*bufsize < bc->len*bc->mult_int) {
        mybuf = yasm_xmalloc(bc->len*bc->mult_int);
        destbuf = mybuf;
    } else
        destbuf = buf;

    *bufsize = bc->len*bc->mult_int;

    if (!bc->callback)
        yasm_internal_error(N_("got empty bytecode in bc_tobytes"));
    else for (i=0; i<bc->mult_int; i++) {
        origbuf = destbuf;
        error = bc->callback->tobytes(bc, &destbuf, d, output_value,
                                      output_reloc);

        if (!error && ((unsigned long)(destbuf - origbuf) != bc->len))
            yasm_internal_error(
                N_("written length does not match optimized length"));
    }

    return mybuf;
}
int
yasm_bc_calc_len_common(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                        void *add_span_data)
{
    yasm_internal_error(N_("bytecode length cannot be calculated"));
    /*@unreached@*/
    return 0;
}
int
yasm_bc_expand_common(yasm_bytecode *bc, int span, long old_val, long new_val,
                      /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
{
    yasm_internal_error(N_("bytecode does not have any dependent spans"));
    /*@unreached@*/
    return 0;
}
int
yasm_bc_tobytes_common(yasm_bytecode *bc, unsigned char **bufp, void *d,
                       yasm_output_value_func output_value,
                       /*@null@*/ yasm_output_reloc_func output_reloc)
{
    yasm_internal_error(N_("bytecode cannot be converted to bytes"));
    /*@unreached@*/
    return 0;
}
示例#9
0
文件: elf.c 项目: Mirocow/balancer
elf_strtab_entry *
elf_strtab_append_str(elf_strtab_head *strtab, const char *str)
{
    elf_strtab_entry *last, *entry;

    if (strtab == NULL)
        yasm_internal_error("strtab is null");
    if (STAILQ_EMPTY(strtab))
        yasm_internal_error("strtab is missing initial dummy entry");

    last = STAILQ_LAST(strtab, elf_strtab_entry, qlink);

    entry = elf_strtab_entry_create(str);
    entry->index = last->index + (unsigned long)strlen(last->str) + 1;

    STAILQ_INSERT_TAIL(strtab, entry, qlink);
    return entry;
}
示例#10
0
static unsigned int
elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc,
                                     yasm_symrec **ssyms)
{
    if (reloc->wrt) {
        size_t i;
        for (i=0; i<NELEMS(elf_x86_amd64_ssyms); i++) {
            if (reloc->wrt == ssyms[i] &&
                reloc->valsize == elf_x86_amd64_ssyms[i].size) {
                /* Force TLS type; this is required by the linker. */
                if (elf_x86_amd64_ssyms[i].sym_rel & ELF_SSYM_THREAD_LOCAL) {
                    elf_symtab_entry *esym;

                    esym = yasm_symrec_get_data(reloc->reloc.sym,
                                                &elf_symrec_data);
                    if (esym)
                        esym->type = STT_TLS;
                }
                /* Map PC-relative GOT to appropriate relocation */
                if (reloc->rtype_rel &&
                    elf_x86_amd64_ssyms[i].reloc == R_X86_64_GOT32)
                    return (unsigned char) R_X86_64_GOTPCREL;
                return (unsigned char) elf_x86_amd64_ssyms[i].reloc;
            }
        }
        yasm_internal_error(N_("Unsupported WRT"));
    } else if (reloc->rtype_rel) {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_PC8;
            case 16: return (unsigned char) R_X86_64_PC16;
            case 32: return (unsigned char) R_X86_64_PC32;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    } else {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_8;
            case 16: return (unsigned char) R_X86_64_16;
            case 32: return (unsigned char) R_X86_64_32;
            case 64: return (unsigned char) R_X86_64_64;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    }
    return 0;
}
示例#11
0
static unsigned int
elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc)
{
    if (reloc->wrt) {
        const elf_machine_ssym *ssym = (elf_machine_ssym *)
            yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data);
        if (!ssym || reloc->valsize != ssym->size)
            yasm_internal_error(N_("Unsupported WRT"));

        /* Force TLS type; this is required by the linker. */
        if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) {
            elf_symtab_entry *esym;

            esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data);
            if (esym)
                esym->type = STT_TLS;
        }
        /* Map PC-relative GOT to appropriate relocation */
        if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32)
            return (unsigned char) R_X86_64_GOTPCREL;
        return (unsigned char) ssym->reloc;
    } else if (reloc->is_GOT_sym && reloc->valsize == 32) {
        return (unsigned char) R_X86_64_GOTPC32;
    } else if (reloc->is_GOT_sym && reloc->valsize == 64) {
        return (unsigned char) R_X86_64_GOTPC64;
    } else if (reloc->rtype_rel) {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_PC8;
            case 16: return (unsigned char) R_X86_64_PC16;
            case 32: return (unsigned char) R_X86_64_PC32;
            case 64: return (unsigned char) R_X86_64_PC64;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    } else {
        switch (reloc->valsize) {
            case 8: return (unsigned char) R_X86_64_8;
            case 16: return (unsigned char) R_X86_64_16;
            case 32: return (unsigned char) R_X86_64_32;
            case 64: return (unsigned char) R_X86_64_64;
            default: yasm_internal_error(N_("Unsupported relocation size"));
        }
    }
    return 0;
}
示例#12
0
文件: elf.c 项目: Mirocow/balancer
void
elf_strtab_destroy(elf_strtab_head *strtab)
{
    elf_strtab_entry *s1, *s2;

    if (strtab == NULL)
        yasm_internal_error("strtab is null");
    if (STAILQ_EMPTY(strtab))
        yasm_internal_error("strtab is missing initial dummy entry");

    s1 = STAILQ_FIRST(strtab);
    while (s1 != NULL) {
        s2 = STAILQ_NEXT(s1, qlink);
        yasm_xfree(s1->str);
        yasm_xfree(s1);
        s1 = s2;
    }
    yasm_xfree(strtab);
}
示例#13
0
/* IEEE-754r "half precision" format:
 * 16 bits:
 * 15     9      Bit 0
 * |      |          |
 * seee eemm mmmm mmmm
 *
 * e = bias 15 exponent
 * s = sign bit
 * m = mantissa bits, bit 10 is an implied one bit.
 *
 * IEEE-754 (Intel) "single precision" format:
 * 32 bits:
 * Bit 31    Bit 22              Bit 0
 * |         |                       |
 * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
 *
 * e = bias 127 exponent
 * s = sign bit
 * m = mantissa bits, bit 23 is an implied one bit.
 *
 * IEEE-754 (Intel) "double precision" format:
 * 64 bits:
 * bit 63       bit 51                                               bit 0
 * |            |                                                        |
 * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
 *
 * e = bias 1023 exponent.
 * s = sign bit.
 * m = mantissa bits.  Bit 52 is an implied one bit.
 *
 * IEEE-754 (Intel) "extended precision" format:
 * 80 bits:
 * bit 79            bit 63                           bit 0
 * |                 |                                    |
 * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
 *
 * e = bias 16383 exponent
 * m = 64 bit mantissa with NO implied bit!
 * s = sign (for mantissa)
 */
int
yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
                        size_t destsize, size_t valsize, size_t shift,
                        int bigendian, int warn)
{
    int retval;
    if (destsize*8 != valsize || shift>0 || bigendian) {
        /* TODO */
        yasm_internal_error(N_("unsupported floatnum functionality"));
    }
    switch (destsize) {
        case 2:
            retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5);
            break;
        case 4:
            retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
            break;
        case 8:
            retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
            break;
        case 10:
            retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
            break;
        default:
            yasm_internal_error(N_("Invalid float conversion size"));
            /*@notreached@*/
            return 1;
    }
    if (warn) {
        if (retval < 0)
            yasm_warn_set(YASM_WARN_GENERAL,
                          N_("underflow in floating point expression"));
        else if (retval > 0)
            yasm_warn_set(YASM_WARN_GENERAL,
                          N_("overflow in floating point expression"));
    }
    return retval;
}
示例#14
0
static int
bc_incbin_tobytes(yasm_bytecode *bc, unsigned char **bufp,
                  unsigned char *bufstart, void *d,
                  yasm_output_value_func output_value,
                  /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
    FILE *f;
    /*@dependent@*/ /*@null@*/ const yasm_intnum *num;
    unsigned long start = 0;

    /* Convert start to integer value */
    if (incbin->start) {
        num = yasm_expr_get_intnum(&incbin->start, 0);
        if (!num)
            yasm_internal_error(
                N_("could not determine start in bc_tobytes_incbin"));
        start = yasm_intnum_get_uint(num);
    }

    /* Open file */
    f = yasm_fopen_include(incbin->filename, incbin->from, "rb", NULL);
    if (!f) {
        yasm_error_set(YASM_ERROR_IO, N_("`incbin': unable to open file `%s'"),
                       incbin->filename);
        return 1;
    }

    /* Seek to start of data */
    if (fseek(f, (long)start, SEEK_SET) < 0) {
        yasm_error_set(YASM_ERROR_IO,
                       N_("`incbin': unable to seek on file `%s'"),
                       incbin->filename);
        fclose(f);
        return 1;
    }

    /* Read len bytes */
    if (fread(*bufp, 1, (size_t)bc->len, f) < (size_t)bc->len) {
        yasm_error_set(YASM_ERROR_IO,
                       N_("`incbin': unable to read %lu bytes from file `%s'"),
                       bc->len, incbin->filename);
        fclose(f);
        return 1;
    }

    *bufp += bc->len;
    fclose(f);
    return 0;
}
示例#15
0
文件: expr.c 项目: Acidburn0zzz/yasm
/* helpers */
static yasm_expr__item *
expr_get_item(void)
{
    int z = 0;
    unsigned long v = itempool_used & 0x7fffffff;

    while (v & 1) {
        v >>= 1;
        z++;
    }
    if (z>=31)
        yasm_internal_error(N_("too many expritems"));
    itempool_used |= 1<<z;
    return &itempool[z];
}
示例#16
0
文件: elf.c 项目: Mirocow/balancer
unsigned long
elf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab)
{
    unsigned long size = 0;
    elf_strtab_entry *entry;

    if (strtab == NULL)
        yasm_internal_error("strtab is null");

    /* consider optimizing tables here */
    STAILQ_FOREACH(entry, strtab, qlink) {
        size_t len = 1 + strlen(entry->str);
        fwrite(entry->str, len, 1, f);
        size += (unsigned long)len;
    }
int
yasm_bc_expand(yasm_bytecode *bc, int span, long old_val, long new_val,
               /*@out@*/ long *neg_thres, /*@out@*/ long *pos_thres)
{
    if (span == 0) {
        bc->mult_int = new_val;
        return 1;
    }
    if (!bc->callback) {
        yasm_internal_error(N_("got empty bytecode in yasm_bc_expand"));
        /*@unreached@*/
        return -1;
    } else
        return bc->callback->expand(bc, span, old_val, new_val, neg_thres,
                                    pos_thres);
}
int
yasm_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span,
                 void *add_span_data)
{
    int retval = 0;

    bc->len = 0;

    if (!bc->callback)
        yasm_internal_error(N_("got empty bytecode in yasm_bc_calc_len"));
    else
        retval = bc->callback->calc_len(bc, add_span, add_span_data);

    /* Check for multiples */
    bc->mult_int = 1;
    if (bc->multiple) {
        /*@dependent@*/ /*@null@*/ const yasm_intnum *num;

        num = yasm_expr_get_intnum(&bc->multiple, 0);
        if (num) {
            if (yasm_intnum_sign(num) < 0) {
                yasm_error_set(YASM_ERROR_VALUE, N_("multiple is negative"));
                retval = -1;
            } else
                bc->mult_int = yasm_intnum_get_int(num);
        } else {
            if (yasm_expr__contains(bc->multiple, YASM_EXPR_FLOAT)) {
                yasm_error_set(YASM_ERROR_VALUE,
                    N_("expression must not contain floating point value"));
                retval = -1;
            } else {
                yasm_value value;
                yasm_value_initialize(&value, bc->multiple, 0);
                add_span(add_span_data, bc, 0, &value, 0, 0);
                bc->mult_int = 0;   /* assume 0 to start */
            }
        }
    }

    /* If we got an error somewhere along the line, clear out any calc len */
    if (retval < 0)
        bc->len = 0;

    return retval;
}
示例#19
0
文件: intnum.c 项目: kstephens/yasm
unsigned long
yasm_intnum_get_uint(const yasm_intnum *intn)
{
    switch (intn->type) {
        case INTNUM_L:
            if (intn->val.l < 0)
                return 0;
            return (unsigned long)intn->val.l;
        case INTNUM_BV:
            if (BitVector_msb_(intn->val.bv))
                return 0;
            if (Set_Max(intn->val.bv) > 32)
                return ULONG_MAX;
            return BitVector_Chunk_Read(intn->val.bv, 32, 0);
        default:
            yasm_internal_error(N_("unknown intnum type"));
            /*@notreached@*/
            return 0;
    }
}
示例#20
0
static void
elf_x86_amd64_write_symtab_entry(unsigned char *bufp,
                                 elf_symtab_entry *entry,
                                 yasm_intnum *value_intn,
                                 yasm_intnum *size_intn)
{
    YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0);
    YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type));
    YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis));
    if (entry->sect) {
        elf_secthead *shead =
            yasm_section_get_data(entry->sect, &elf_section_data);
        if (!shead)
            yasm_internal_error(N_("symbol references section without data"));
        YASM_WRITE_16_L(bufp, shead->index);
    } else {
        YASM_WRITE_16_L(bufp, entry->index);
    }
    YASM_WRITE_64I_L(bufp, value_intn);
    YASM_WRITE_64I_L(bufp, size_intn);
}
示例#21
0
static int
lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp,
                     unsigned char *bufstart, void *d,
                     yasm_output_value_func output_value,
                     /*@unused@*/ yasm_output_reloc_func output_reloc)
{
    lc3b_insn *insn = (lc3b_insn *)bc->contents;
    /*@only@*/ yasm_intnum *delta;
    unsigned long buf_off = (unsigned long)(*bufp - bufstart);

    /* Output opcode */
    YASM_SAVE_16_L(*bufp, insn->opcode);

    /* Insert immediate into opcode. */
    switch (insn->imm_type) {
        case LC3B_IMM_NONE:
            break;
        case LC3B_IMM_4:
            insn->imm.size = 4;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        case LC3B_IMM_5:
            insn->imm.size = 5;
            insn->imm.sign = 1;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        case LC3B_IMM_6_WORD:
            insn->imm.size = 6;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        case LC3B_IMM_6_BYTE:
            insn->imm.size = 6;
            insn->imm.sign = 1;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        case LC3B_IMM_8:
            insn->imm.size = 8;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        case LC3B_IMM_9_PC:
            /* Adjust relative displacement to end of bytecode */
            delta = yasm_intnum_create_int(-1);
            if (!insn->imm.abs)
                insn->imm.abs = yasm_expr_create_ident(yasm_expr_int(delta),
                                                       bc->line);
            else
                insn->imm.abs =
                    yasm_expr_create(YASM_EXPR_ADD,
                                     yasm_expr_expr(insn->imm.abs),
                                     yasm_expr_int(delta), bc->line);

            insn->imm.size = 9;
            insn->imm.sign = 1;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        case LC3B_IMM_9:
            insn->imm.size = 9;
            if (output_value(&insn->imm, *bufp, 2, buf_off, bc, 1, d))
                return 1;
            break;
        default:
            yasm_internal_error(N_("Unrecognized immediate type"));
    }

    *bufp += 2;     /* all instructions are 2 bytes in size */
    return 0;
}
示例#22
0
static int
xdf_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;

    assert(info != NULL);
    xsd = yasm_section_get_data(sect, &xdf_section_data_cb);
    assert(xsd != NULL);

    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 = yasm_bc_next_offset(yasm_section_bcs_last(sect));
    } 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->errwarns, info,
                                  xdf_objfmt_output_bytecode);

        /* Sanity check final section size */
        if (xsd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect)))
            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);
        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;
}
示例#23
0
static int
xdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d)
{
    /*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
    yasm_sym_vis vis = yasm_symrec_get_visibility(sym);

    assert(info != NULL);

    if (info->all_syms || vis != YASM_SYM_LOCAL) {
        /*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object);
        const yasm_expr *equ_val;
        const yasm_intnum *intn;
        size_t len = strlen(name);
        unsigned long value = 0;
        long scnum = -3;        /* -3 = debugging symbol */
        /*@dependent@*/ /*@null@*/ yasm_section *sect;
        /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
        unsigned long flags = 0;
        unsigned char *localbuf;

        if (vis & YASM_SYM_GLOBAL)
            flags = XDF_SYM_GLOBAL;

        /* Look at symrec for value/scnum/etc. */
        if (yasm_symrec_get_label(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@*/ xdf_section_data *csectd;
                csectd = yasm_section_get_data(sect, &xdf_section_data_cb);
                if (csectd)
                    scnum = csectd->scnum;
                else
                    yasm_internal_error(N_("didn't understand section"));
                if (precbc)
                    value += yasm_bc_next_offset(precbc);
            }
        } else if ((equ_val = yasm_symrec_get_equ(sym))) {
            yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
            intn = yasm_expr_get_intnum(&equ_val_copy, 1);
            if (!intn) {
                if (vis & YASM_SYM_GLOBAL) {
                    yasm_error_set(YASM_ERROR_NOT_CONSTANT,
                        N_("global EQU value not an integer expression"));
                    yasm_errwarn_propagate(info->errwarns, equ_val->line);
                }
            } else
                value = yasm_intnum_get_uint(intn);
            yasm_expr_destroy(equ_val_copy);

            flags |= XDF_SYM_EQU;
            scnum = -2;     /* -2 = absolute symbol */
        } else {
            if (vis & YASM_SYM_EXTERN) {
                flags = XDF_SYM_EXTERN;
                scnum = -1;
            }
        }

        localbuf = info->buf;
        YASM_WRITE_32_L(localbuf, scnum);       /* section number */
        YASM_WRITE_32_L(localbuf, value);       /* value */
        YASM_WRITE_32_L(localbuf, info->strtab_offset);
        info->strtab_offset += (unsigned long)(len+1);
        YASM_WRITE_32_L(localbuf, flags);       /* flags */
        fwrite(info->buf, 16, 1, info->f);
        yasm_xfree(name);
    }
    return 0;
}
示例#24
0
int
yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
{
    if (!value->abs)
        return 0;

    value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);

    /* quit early if there was an issue in simplify() */
    if (yasm_error_occurred())
        return 1;

    /* Strip top-level AND masking to an all-1s mask the same size
     * of the value size.  This allows forced avoidance of overflow warnings.
     */
    if (value->abs->op == YASM_EXPR_AND) {
        int term;

        /* Calculate 1<<size - 1 value */
        yasm_intnum *mask = yasm_intnum_create_uint(1);
        yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size);
        yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp);
        yasm_intnum_set_uint(mask_tmp, 1);
        yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp);
        yasm_intnum_destroy(mask_tmp);

        /* Walk terms and delete matching masks */
        for (term=value->abs->numterms-1; term>=0; term--) {
            if (value->abs->terms[term].type == YASM_EXPR_INT &&
                yasm_intnum_compare(value->abs->terms[term].data.intn,
                                    mask) == 0) {
                /* Delete the intnum */
                yasm_intnum_destroy(value->abs->terms[term].data.intn);

                /* Slide everything to its right over by 1 */
                if (term != value->abs->numterms-1) /* if it wasn't last.. */
                    memmove(&value->abs->terms[term],
                            &value->abs->terms[term+1],
                            (value->abs->numterms-1-term)*
                                sizeof(yasm_expr__item));

                /* Update numterms */
                value->abs->numterms--;

                /* Indicate warnings have been disabled */
                value->no_warn = 1;
            }
        }
        if (value->abs->numterms == 1)
            value->abs->op = YASM_EXPR_IDENT;
        yasm_intnum_destroy(mask);
    }

    /* Handle trivial (IDENT) cases immediately */
    if (value->abs->op == YASM_EXPR_IDENT) {
        switch (value->abs->terms[0].type) {
            case YASM_EXPR_INT:
                if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
                    yasm_expr_destroy(value->abs);
                    value->abs = NULL;
                }
                return 0;
            case YASM_EXPR_REG:
            case YASM_EXPR_FLOAT:
                return 0;
            case YASM_EXPR_SYM:
                value->rel = value->abs->terms[0].data.sym;
                yasm_expr_destroy(value->abs);
                value->abs = NULL;
                return 0;
            case YASM_EXPR_EXPR:
                /* Bring up lower values. */
                while (value->abs->op == YASM_EXPR_IDENT
                       && value->abs->terms[0].type == YASM_EXPR_EXPR) {
                    yasm_expr *sube = value->abs->terms[0].data.expn;
                    yasm_xfree(value->abs);
                    value->abs = sube;
                }
                break;
            default:
                yasm_internal_error(N_("unexpected expr term type"));
        }
    }

    if (value_finalize_scan(value, value->abs, precbc, 0))
        return 1;

    value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);

    /* Simplify 0 in abs to NULL */
    if (value->abs->op == YASM_EXPR_IDENT
        && value->abs->terms[0].type == YASM_EXPR_INT
        && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
        yasm_expr_destroy(value->abs);
        value->abs = NULL;
    }
    return 0;
}
示例#25
0
/* Function used by conversion routines to actually perform the conversion.
 *
 * ptr -> the array to return the little-endian floating point value into.
 * flt -> the floating point value to convert.
 * byte_size -> the size in bytes of the output format.
 * mant_bits -> the size in bits of the output mantissa.
 * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
 * exp_bits -> the size in bits of the output exponent.
 *
 * Returns 0 on success, 1 if overflow, -1 if underflow.
 */
static int
floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
                    N_int byte_size, N_int mant_bits, int implicit1,
                    N_int exp_bits)
{
    long exponent = (long)flt->exponent;
    wordptr output;
    charptr buf;
    unsigned int len;
    unsigned int overflow = 0, underflow = 0;
    int retval = 0;
    long exp_bias = (1<<(exp_bits-1))-1;
    long exp_inf = (1<<exp_bits)-1;

    output = BitVector_Create(byte_size*8, TRUE);

    /* copy mantissa */
    BitVector_Interval_Copy(output, flt->mantissa, 0,
                            (N_int)((MANT_BITS-implicit1)-mant_bits),
                            mant_bits);

    /* round mantissa */
    if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
        BitVector_increment(output);

    if (BitVector_bit_test(output, mant_bits)) {
        /* overflowed, so zero mantissa (and set explicit bit if necessary) */
        BitVector_Empty(output);
        BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
        /* and up the exponent (checking for overflow) */
        if (exponent+1 >= EXP_INF)
            overflow = 1;
        else
            exponent++;
    }

    /* adjust the exponent to the output bias, checking for overflow */
    exponent -= EXP_BIAS-exp_bias;
    if (exponent >= exp_inf)
        overflow = 1;
    else if (exponent <= 0)
        underflow = 1;

    /* underflow and overflow both set!? */
    if (underflow && overflow)
        yasm_internal_error(N_("Both underflow and overflow set"));

    /* check for underflow or overflow and set up appropriate output */
    if (underflow) {
        BitVector_Empty(output);
        exponent = 0;
        if (!(flt->flags & FLAG_ISZERO))
            retval = -1;
    } else if (overflow) {
        BitVector_Empty(output);
        exponent = exp_inf;
        retval = 1;
    }

    /* move exponent into place */
    BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);

    /* merge in sign bit */
    BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);

    /* get little-endian bytes */
    buf = BitVector_Block_Read(output, &len);
    if (len < byte_size)
        yasm_internal_error(
            N_("Byte length of BitVector does not match bit length"));

    /* copy to output */
    memcpy(ptr, buf, byte_size*sizeof(unsigned char));

    /* free allocated resources */
    yasm_xfree(buf);

    BitVector_Destroy(output);

    return retval;
}
示例#26
0
文件: intnum.c 项目: kstephens/yasm
void
yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
                      size_t destsize, size_t valsize, int shift,
                      int bigendian, int warn)
{
    wordptr op1 = op1static, op2;
    unsigned char *buf;
    unsigned int len;
    size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
    int carry_in;

    /* Currently don't support destinations larger than our native size */
    if (destsize*8 > BITVECT_NATIVE_SIZE)
        yasm_internal_error(N_("destination too large"));

    /* General size warnings */
    if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1))
        yasm_warn_set(YASM_WARN_GENERAL,
                      N_("value does not fit in signed %d bit field"),
                      valsize);
    if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
        yasm_warn_set(YASM_WARN_GENERAL,
                      N_("value does not fit in %d bit field"), valsize);

    /* Read the original data into a bitvect */
    if (bigendian) {
        /* TODO */
        yasm_internal_error(N_("big endian not implemented"));
    } else
        BitVector_Block_Store(op1, ptr, (N_int)destsize);

    /* If not already a bitvect, convert value to be written to a bitvect */
    op2 = intnum_tobv(op2static, intn);

    /* Check low bits if right shifting and warnings enabled */
    if (warn && rshift > 0) {
        BitVector_Copy(conv_bv, op2);
        BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift));
        if (!BitVector_is_empty(conv_bv))
            yasm_warn_set(YASM_WARN_GENERAL,
                          N_("misaligned value, truncating to boundary"));
    }

    /* Shift right if needed */
    if (rshift > 0) {
        carry_in = BitVector_msb_(op2);
        while (rshift-- > 0)
            BitVector_shift_right(op2, carry_in);
        shift = 0;
    }

    /* Write the new value into the destination bitvect */
    BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize);

    /* Write out the new data */
    buf = BitVector_Block_Read(op1, &len);
    if (bigendian) {
        /* TODO */
        yasm_internal_error(N_("big endian not implemented"));
    } else
        memcpy(ptr, buf, destsize);
    yasm_xfree(buf);
}