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); }
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; }
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); }