예제 #1
0
static void
elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn, elf_reloc_entry *reloc)
{
    /* .rela: copy value out as addend, replace original with 0 */
    reloc->addend = yasm_intnum_copy(intn);
    yasm_intnum_zero(intn);
}
예제 #2
0
파일: valparam.c 프로젝트: Jonnyliu/hf-2011
int
yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
                     void *data, uintptr_t arg)
{
    yasm_object *object = (yasm_object *)obj;
    /*@only@*/ /*@null@*/ yasm_expr *e;
    /*@dependent@*/ /*@null@*/ yasm_intnum *local;
    yasm_intnum **intn = (yasm_intnum **)data;

    if (*intn)
        yasm_intnum_destroy(*intn);
    if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
        !(local = yasm_expr_get_intnum(&e, 0))) {
        yasm_error_set(YASM_ERROR_NOT_CONSTANT,
                       N_("argument to `%s' is not an integer"),
                       vp->val);
        if (e)
            yasm_expr_destroy(e);
        return -1;
    }
    *intn = yasm_intnum_copy(local);
    yasm_expr_destroy(e);
    return 0;
}
예제 #3
0
yasm_intnum *
yasm_value_get_intnum(yasm_value *value, yasm_bytecode *bc, int calc_bc_dist)
{
    /*@dependent@*/ /*@null@*/ yasm_intnum *intn = NULL;
    /*@only@*/ yasm_intnum *outval;
    int sym_local;

    if (value->abs) {
        /* Handle integer expressions, if non-integer or too complex, return
         * NULL.
         */
        intn = yasm_expr_get_intnum(&value->abs, calc_bc_dist);
        if (!intn)
            return NULL;
    }

    if (value->rel) {
        /* If relative portion is not in bc section, return NULL.
         * Otherwise get the relative portion's offset.
         */
        /*@dependent@*/ yasm_bytecode *rel_prevbc;
        unsigned long dist;

        if (!bc)
            return NULL;    /* Can't calculate relative value */

        sym_local = yasm_symrec_get_label(value->rel, &rel_prevbc);
        if (value->wrt || value->seg_of || value->section_rel || !sym_local)
            return NULL;    /* we can't handle SEG, WRT, or external symbols */
        if (rel_prevbc->section != bc->section)
            return NULL;    /* not in this section */
        if (!value->curpos_rel)
            return NULL;    /* not PC-relative */

        /* Calculate value relative to current assembly position */
        dist = yasm_bc_next_offset(rel_prevbc);
        if (dist < bc->offset) {
            outval = yasm_intnum_create_uint(bc->offset - dist);
            yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL);
        } else {
            dist -= bc->offset;
            outval = yasm_intnum_create_uint(dist);
        }

        if (value->rshift > 0) {
            /*@only@*/ yasm_intnum *shamt =
                yasm_intnum_create_uint((unsigned long)value->rshift);
            yasm_intnum_calc(outval, YASM_EXPR_SHR, shamt);
            yasm_intnum_destroy(shamt);
        }
        /* Add in absolute portion */
        if (intn)
            yasm_intnum_calc(outval, YASM_EXPR_ADD, intn);
        return outval;
    }

    if (intn)
        return yasm_intnum_copy(intn);
    
    /* No absolute or relative portions: output 0 */
    return yasm_intnum_create_uint(0);
}