STAILQ_FOREACH(dv, &bc_data->datahead, link) {
switch (dv->type) {
case DV_VALUE:
- if (yasm_value_finalize(&dv->data.val)) {
+ if (yasm_value_finalize(&dv->data.val, prev_bc)) {
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("data expression too complex"));
return;
bytecode_incbin *incbin = (bytecode_incbin *)bc->contents;
yasm_value val;
- if (yasm_value_finalize_expr(&val, incbin->start, 0))
+ if (yasm_value_finalize_expr(&val, incbin->start, prev_bc, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("start expression too complex"));
else if (val.rel)
N_("start expression not absolute"));
incbin->start = val.abs;
- if (yasm_value_finalize_expr(&val, incbin->maxlen, 0))
+ if (yasm_value_finalize_expr(&val, incbin->maxlen, prev_bc, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("maximum length expression too complex"));
else if (val.rel)
yasm_immval *
-yasm_imm_create_expr(yasm_expr *e)
+yasm_imm_create_expr(yasm_expr *e, yasm_bytecode *precbc)
{
yasm_immval *im = yasm_xmalloc(sizeof(yasm_immval));
- if (yasm_value_finalize_expr(&im->val, e, 0))
+ if (yasm_value_finalize_expr(&im->val, e, precbc, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("immediate expression too complex"));
im->sign = 0;
bytecode_reserve *reserve = (bytecode_reserve *)bc->contents;
yasm_value val;
- if (yasm_value_finalize_expr(&val, reserve->numitems, 0))
+ if (yasm_value_finalize_expr(&val, reserve->numitems, prev_bc, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("reserve expression too complex"));
else if (val.rel)
if (bc->multiple) {
yasm_value val;
- if (yasm_value_finalize_expr(&val, bc->multiple, 0))
+ if (yasm_value_finalize_expr(&val, bc->multiple, prev_bc, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("multiple expression too complex"));
else if (val.rel)
#endif
/** Create an immediate value from an expression.
- * \param e expression (kept, do not free).
+ * \param e expression (kept, do not free).
+ * \param precbc previous bytecode to bytecode containing immediate
* \return Newly allocated immediate value.
*/
-/*@only@*/ yasm_immval *yasm_imm_create_expr(/*@keep@*/ yasm_expr *e);
+/*@only@*/ yasm_immval *yasm_imm_create_expr(/*@keep@*/ yasm_expr *e,
+ /*@null@*/ yasm_bytecode *precbc);
/** Get the displacement portion of an effective address.
* \param ea effective address
}
static int
-value_finalize_scan(yasm_value *value, yasm_expr *e, int ssym_not_ok)
+value_finalize_scan(yasm_value *value, yasm_expr *e,
+ /*@null@*/ yasm_bytecode *expr_precbc, int ssym_not_ok)
{
int i;
/*@dependent@*/ yasm_section *sect;
if (sube->op != YASM_EXPR_MUL || sube->numterms != 2) {
/* recurse instead */
- if (value_finalize_scan(value, sube, ssym_not_ok))
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
return 1;
continue;
}
sym = sube->terms[0].data.sym;
intn = sube->terms[1].data.intn;
} else {
- if (value_finalize_scan(value, sube, ssym_not_ok))
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
return 1;
continue;
}
if (!yasm_intnum_is_neg1(intn)) {
- if (value_finalize_scan(value, sube, ssym_not_ok))
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
return 1;
continue;
}
if (!yasm_symrec_get_label(sym, &precbc)) {
- if (value_finalize_scan(value, sube, ssym_not_ok))
+ if (value_finalize_scan(value, sube, expr_precbc,
+ ssym_not_ok))
return 1;
continue;
}
* unused symrec terms in other segments and generate
* a curpos-relative reloc.
*
+ * Similarly, handle -1*symrec in other segment via the
+ * following transformation:
+ * other-this = (other-.)+(.-this)
+ * We can only do this transformation if "this" is in
+ * this expr's segment.
+ *
* Don't do this if we've already become curpos-relative.
* The unmatched symrec will be caught below.
*/
- if (j == e->numterms && yasm_symrec_is_curpos(sym)
- && !value->curpos_rel) {
+ if (j == e->numterms && !value->curpos_rel
+ && (yasm_symrec_is_curpos(sym)
+ || (expr_precbc
+ && sect2 == yasm_bc_get_section(expr_precbc)))) {
for (j=0; j<e->numterms; j++) {
if (e->terms[j].type == YASM_EXPR_SYM
&& yasm_symrec_get_label(e->terms[j].data.sym,
return 1;
value->rel = e->terms[j].data.sym;
value->curpos_rel = 1;
- /* Replace both symrec portions with 0 */
- yasm_expr_destroy(sube);
- e->terms[i].type = YASM_EXPR_INT;
- e->terms[i].data.intn = yasm_intnum_create_uint(0);
- e->terms[j].type = YASM_EXPR_INT;
- e->terms[j].data.intn = yasm_intnum_create_uint(0);
+ if (yasm_symrec_is_curpos(sym)) {
+ /* Replace both symrec portions with 0 */
+ yasm_expr_destroy(sube);
+ e->terms[i].type = YASM_EXPR_INT;
+ e->terms[i].data.intn =
+ yasm_intnum_create_uint(0);
+ e->terms[j].type = YASM_EXPR_INT;
+ e->terms[j].data.intn =
+ yasm_intnum_create_uint(0);
+ } else {
+ /* Replace positive portion with curpos */
+ yasm_symtab *symtab =
+ yasm_object_get_symtab(
+ yasm_section_get_object(sect2));
+ e->terms[j].data.sym =
+ yasm_symtab_define_curpos
+ (symtab, ".", expr_precbc, e->line);
+ }
break; /* stop looking */
}
}
}
+
if (j == e->numterms)
return 1; /* We didn't find a match! */
}
case YASM_EXPR_SYM:
return 1;
case YASM_EXPR_EXPR:
- if (value_finalize_scan(value, e->terms[1].data.expn, 1))
+ if (value_finalize_scan(value, e->terms[1].data.expn,
+ expr_precbc, 1))
return 1;
break;
default:
case YASM_EXPR_EXPR:
/* recurse */
if (value_finalize_scan(value, e->terms[0].data.expn,
- ssym_not_ok))
+ expr_precbc, ssym_not_ok))
return 1;
break;
default:
case YASM_EXPR_EXPR:
/* recurse */
return value_finalize_scan(value, e->terms[0].data.expn,
- ssym_not_ok);
+ expr_precbc, ssym_not_ok);
default:
break; /* ignore */
}
case YASM_EXPR_EXPR:
/* recurse */
return value_finalize_scan(value,
- e->terms[i].data.expn, 1);
+ e->terms[i].data.expn,
+ expr_precbc, 1);
default:
break;
}
}
int
-yasm_value_finalize_expr(yasm_value *value, yasm_expr *e, unsigned int size)
+yasm_value_finalize_expr(yasm_value *value, yasm_expr *e,
+ yasm_bytecode *precbc, unsigned int size)
{
if (!e) {
yasm_value_initialize(value, NULL, size);
}
}
- if (value_finalize_scan(value, value->abs, 0))
+ 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);
}
int
-yasm_value_finalize(yasm_value *value)
+yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
{
unsigned int valsize = value->size;
- return yasm_value_finalize_expr(value, value->abs, valsize);
+ return yasm_value_finalize_expr(value, value->abs, precbc, valsize);
}
yasm_intnum *
/** Perform yasm_value_finalize_expr() on a value that already exists from
* being initialized with yasm_value_initialize().
* \param value value
+ * \param precbc previous bytecode to bytecode containing value
* \return Nonzero if value could not be split.
*/
-int yasm_value_finalize(yasm_value *value);
+int yasm_value_finalize(yasm_value *value, /*@null@*/ yasm_bytecode *precbc);
/** Break a #yasm_expr into a #yasm_value constituent parts. Extracts
* the relative portion of the value, SEG and WRT portions, and top-level
* symrec offset within the absolute section.
* \param value value to store split portions into
* \param e expression input
+ * \param precbc previous bytecode to bytecode containing expression
* \param size value size (in bits)
* \return Nonzero if the expr could not be split into a value for some
* reason (e.g. the relative portion was not added, but multiplied,
*/
int yasm_value_finalize_expr(/*@out@*/ yasm_value *value,
/*@null@*/ /*@kept@*/ yasm_expr *e,
+ /*@null@*/ yasm_bytecode *precbc,
unsigned int size);
/** Get value if absolute or PC-relative section-local relative. Returns NULL
0xff if unknown */
} x86_effaddr;
-void yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare);
+void yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
+ yasm_bytecode *precbc);
void yasm_x86__ea_set_disponly(x86_effaddr *x86_ea);
x86_effaddr *yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
}
void
-yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare)
+yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
+ yasm_bytecode *precbc)
{
- if (yasm_value_finalize(&x86_ea->ea.disp))
+ if (yasm_value_finalize(&x86_ea->ea.disp, precbc))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("effective address too complex"));
x86_ea->modrm &= 0xC7; /* zero spare/reg bits */
}
static void
-x86_finalize_jmpfar(yasm_arch *arch, yasm_bytecode *bc,
+x86_finalize_jmpfar(yasm_arch *arch, yasm_bytecode *bc, yasm_bytecode *prev_bc,
const unsigned long data[4], int num_operands,
yasm_insn_operands *operands, int num_prefixes,
unsigned long **prefixes, const x86_insn_info *info)
segment = yasm_expr_extract_segoff(&op->data.val);
if (!segment)
yasm_internal_error(N_("didn't get SEG:OFF expression in jmpfar"));
- if (yasm_value_finalize_expr(&jmpfar->segment, segment, 16))
+ if (yasm_value_finalize_expr(&jmpfar->segment, segment, prev_bc, 16))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("jump target segment too complex"));
- if (yasm_value_finalize_expr(&jmpfar->offset, op->data.val, 0))
+ if (yasm_value_finalize_expr(&jmpfar->offset, op->data.val, prev_bc,
+ 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("jump target offset too complex"));
} else if (op->targetmod == X86_FAR) {
/* "FAR imm" target needs to become "seg imm:imm". */
if (yasm_value_finalize_expr(&jmpfar->offset,
- yasm_expr_copy(op->data.val), 0)
- || yasm_value_finalize_expr(&jmpfar->segment, op->data.val, 16))
+ yasm_expr_copy(op->data.val), prev_bc, 0)
+ || yasm_value_finalize_expr(&jmpfar->segment, op->data.val,
+ prev_bc, 16))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("jump target expression too complex"));
jmpfar->segment.seg_of = 1;
jmp = yasm_xmalloc(sizeof(x86_jmp));
x86_finalize_common(&jmp->common, jinfo, mode_bits);
- if (yasm_value_finalize_expr(&jmp->target, op->data.val, 0))
+ if (yasm_value_finalize_expr(&jmp->target, op->data.val, prev_bc, 0))
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
N_("jump target expression too complex"));
if (jmp->target.seg_of || jmp->target.rshift || jmp->target.curpos_rel)
return;
case OPA_JmpFar:
/* Shortcut to JmpFar */
- x86_finalize_jmpfar(arch, bc, data, num_operands, operands,
- num_prefixes, prefixes, info);
+ x86_finalize_jmpfar(arch, bc, prev_bc, data, num_operands,
+ operands, num_prefixes, prefixes, info);
return;
}
}
}
if (insn->x86_ea) {
- yasm_x86__ea_init(insn->x86_ea, spare);
+ yasm_x86__ea_init(insn->x86_ea, spare, prev_bc);
for (i=0; i<num_segregs; i++)
yasm_ea_set_segreg(&insn->x86_ea->ea, segregs[i]);
} else if (num_segregs > 0 && insn->special_prefix == 0) {
yasm_internal_error(N_("unhandled segment prefix"));
if (imm) {
- insn->imm = yasm_imm_create_expr(imm);
+ insn->imm = yasm_imm_create_expr(imm, prev_bc);
insn->imm->val.size = im_len;
insn->imm->sign = im_sign;
} else
TESTS += modules/objfmts/elf/tests/gas64/elf_gas64_test.sh
EXTRA_DIST += modules/objfmts/elf/tests/gas64/elf_gas64_test.sh
+EXTRA_DIST += modules/objfmts/elf/tests/gas64/crosssect.asm
+EXTRA_DIST += modules/objfmts/elf/tests/gas64/crosssect.hex
EXTRA_DIST += modules/objfmts/elf/tests/gas64/elf_gas64_curpos.asm
EXTRA_DIST += modules/objfmts/elf/tests/gas64/elf_gas64_curpos.hex
EXTRA_DIST += modules/objfmts/elf/tests/gas64/elf_gas64_reloc.asm
--- /dev/null
+.section .rodata
+ .align 4
+_sys_srt:
+ .long 0
+
+.text
+ .align 4,0x90
+ .long _sys_srt-.
+ .long _sys_srt-_sys_info
+ #.long _sys_info-_sys_srt
+ #.long -(_sys_srt-_sys_info)
+ .long _sys_info-.
+ .long .-_sys_info
+ .long (_sys_srt-.)+(.-_sys_info) # GAS cannot handle this but we can
+ .long 0
+ .long 65558
+_sys_info:
+ .long 0
--- /dev/null
+7f
+45
+4c
+46
+02
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+3e
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+40
+00
+07
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+14
+00
+00
+00
+f0
+ff
+ff
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+16
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+04
+00
+00
+00
+e8
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+10
+00
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+04
+00
+00
+00
+f4
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+00
+00
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+2e
+72
+6f
+64
+61
+74
+61
+00
+2e
+72
+65
+6c
+61
+2e
+74
+65
+78
+74
+00
+2e
+73
+74
+72
+74
+61
+62
+00
+2e
+73
+79
+6d
+74
+61
+62
+00
+2e
+73
+68
+73
+74
+72
+74
+61
+62
+00
+00
+2d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+04
+00
+f1
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+1c
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+2a
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ac
+00
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+1a
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+e0
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+22
+00
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+e4
+00
+00
+00
+00
+00
+00
+00
+90
+00
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+06
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+00
+00
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0f
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+60
+00
+00
+00
+00
+00
+00
+00
+48
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+04
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+07
+00
+00
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+a8
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
cdef struct yasm_dataval
cdef struct yasm_datavalhead
- cdef yasm_immval* yasm_imm_create_expr(yasm_expr *e)
+ cdef yasm_immval* yasm_imm_create_expr(yasm_expr *e, yasm_bytecode *precbc)
cdef yasm_expr* yasm_ea_get_disp(yasm_effaddr *ea)
cdef void yasm_ea_set_len(yasm_effaddr *ea, unsigned int len)
cdef void yasm_ea_set_nosplit(yasm_effaddr *ea, unsigned int nosplit)
cdef class ImmVal:
cdef yasm_immval *imm
- def __new__(self, value):
+ def __new__(self, value, precbc=None):
if isinstance(value, Expression):
- self.imm = yasm_imm_create_expr(
- yasm_expr_copy((<Expression>value).expr))
+ if precbc is None:
+ self.imm = yasm_imm_create_expr(
+ yasm_expr_copy((<Expression>value).expr), NULL)
+ elif isinstance(precbc, Bytecode):
+ self.imm = yasm_imm_create_expr(
+ yasm_expr_copy((<Expression>value).expr),
+ (<Bytecode>precbc).bc)
+ else:
+ raise TypeError("Invalid precbc type '%s'" % type(precbc))
elif PyCObject_Check(value):
self.imm = <yasm_immval *>__get_voidp(value, ImmVal)
else:
- raise TypeError
+ raise TypeError("Invalid value type '%s'" % type(value))
cdef class Bytecode:
cdef yasm_bytecode *bc
cdef void yasm_value_init_sym(yasm_value *value, yasm_symrec *sym,
unsigned int size)
cdef void yasm_value_delete(yasm_value *value)
- cdef int yasm_value_finalize(yasm_value *value)
+ cdef int yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
cdef int yasm_value_finalize_expr(yasm_value *value, yasm_expr *e,
- unsigned int size)
+ yasm_bytecode *precbc, unsigned int size)
cdef yasm_intnum *yasm_value_get_intnum(yasm_value *value,
yasm_bytecode *bc)
cdef int yasm_value_output_basic(yasm_value *value, unsigned char *buf,
elif isinstance(value, Symbol):
yasm_value_init_sym(&self.value, (<Symbol>value).sym, sz)
else:
- raise ValueError("Invalid value type '%s'" % type(value))
+ raise TypeError("Invalid value type '%s'" % type(value))
def __dealloc__(self):
yasm_value_delete(&self.value)
- def finalize(self):
- return yasm_value_finalize(&self.value)
+ def finalize(self, precbc=None):
+ if precbc is None:
+ return yasm_value_finalize(&self.value, NULL)
+ elif isinstance(precbc, Bytecode):
+ return yasm_value_finalize(&self.value, (<Bytecode>precbc).bc)
+ else:
+ raise TypeError("Invalid precbc type '%s'" % type(precbc))