From: Peter Johnson Date: Mon, 4 Jun 2007 01:12:37 +0000 (-0000) Subject: Fix bin objfmt handling of cross-section RIP-relative values; also clean X-Git-Tag: v0.6.1~1^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=01b18c53e9665ff620a3fbb319533e1684455e77;p=yasm Fix bin objfmt handling of cross-section RIP-relative values; also clean up absolute value handling. svn path=/trunk/yasm/; revision=1878 --- diff --git a/modules/objfmts/bin/bin-objfmt.c b/modules/objfmts/bin/bin-objfmt.c index 1a0c9ec2..2e7fd727 100644 --- a/modules/objfmts/bin/bin-objfmt.c +++ b/modules/objfmts/bin/bin-objfmt.c @@ -103,11 +103,13 @@ bin_objfmt_expr_xform(/*@returned@*/ /*@only@*/ yasm_expr *e, /*@null@*/ yasm_intnum *dist; for (i=0; inumterms; i++) { - /* Transform symrecs that reference sections into + /* Transform symrecs or precbcs 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) && + if (((e->terms[i].type == YASM_EXPR_SYM && + yasm_symrec_get_label(e->terms[i].data.sym, &precbc)) || + (e->terms[i].type == YASM_EXPR_PRECBC && + (precbc = e->terms[i].data.precbc))) && (sect = yasm_bc_get_section(precbc)) && (dist = yasm_calc_bc_dist(yasm_section_bcs_first(sect), precbc))) { const yasm_expr *start = yasm_section_get_start(sect); @@ -135,17 +137,36 @@ bin_objfmt_output_value(yasm_value *value, unsigned char *buf, assert(info != NULL); /* Binary objects we need to resolve against object, not against section. */ - if (value->rel && !value->curpos_rel - && yasm_symrec_get_label(value->rel, &precbc) - && (sect = yasm_bc_get_section(precbc))) { + if (value->rel) { unsigned int rshift = (unsigned int)value->rshift; yasm_expr *syme; + + if (yasm_symrec_is_abs(value->rel)) { + syme = yasm_expr_create_ident(yasm_expr_int( + yasm_intnum_create_uint(0)), bc->line); + } else if (yasm_symrec_get_label(value->rel, &precbc) + && (sect = yasm_bc_get_section(precbc))) { + syme = yasm_expr_create_ident(yasm_expr_sym(value->rel), bc->line); + } else + goto done; + + /* Handle PC-relative */ + if (value->curpos_rel) { + yasm_expr *sube; + sube = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_precbc(bc), + yasm_expr_int(yasm_intnum_create_uint(bc->len*bc->mult_int)), + bc->line); + syme = yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(syme), + yasm_expr_expr(sube), bc->line); + value->curpos_rel = 0; + value->ip_rel = 0; + } else + if (value->rshift > 0) - syme = yasm_expr_create(YASM_EXPR_SHR, yasm_expr_sym(value->rel), + syme = yasm_expr_create(YASM_EXPR_SHR, yasm_expr_expr(syme), yasm_expr_int(yasm_intnum_create_uint(rshift)), bc->line); - else - syme = yasm_expr_create_ident(yasm_expr_sym(value->rel), bc->line); + /* Add into absolute portion */ if (!value->abs) value->abs = syme; else @@ -155,7 +176,7 @@ bin_objfmt_output_value(yasm_value *value, unsigned char *buf, value->rel = NULL; value->rshift = 0; } - +done: /* Simplify absolute portion of value, transforming symrecs */ if (value->abs) value->abs = yasm_expr__level_tree @@ -172,36 +193,6 @@ bin_objfmt_output_value(yasm_value *value, unsigned char *buf, return 0; } - /* Absolute value; handle it here as output_basic won't understand it */ - if (value->rel && yasm_symrec_is_abs(value->rel)) { - if (value->curpos_rel) { - /* Calculate value relative to current assembly position */ - /*@only@*/ yasm_intnum *outval; - unsigned int valsize = value->size; - int retval = 0; - - outval = yasm_intnum_create_uint(bc->offset + info->abs_start); - yasm_intnum_calc(outval, YASM_EXPR_NEG, NULL); - - 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 (value->abs) - yasm_intnum_calc(outval, YASM_EXPR_ADD, - yasm_expr_get_intnum(&value->abs, 1)); - /* Output! */ - if (yasm_arch_intnum_tobytes(info->object->arch, outval, buf, - destsize, valsize, 0, bc, warn)) - retval = 1; - yasm_intnum_destroy(outval); - return retval; - } - } - /* Couldn't output, assume it contains an external reference. */ yasm_error_set(YASM_ERROR_GENERAL, N_("binary object format does not support external references")); diff --git a/modules/objfmts/bin/tests/Makefile.inc b/modules/objfmts/bin/tests/Makefile.inc index 70070b00..e1993ea4 100644 --- a/modules/objfmts/bin/tests/Makefile.inc +++ b/modules/objfmts/bin/tests/Makefile.inc @@ -10,6 +10,8 @@ EXTRA_DIST += modules/objfmts/bin/tests/bigorg.hex EXTRA_DIST += modules/objfmts/bin/tests/bigorg.errwarn EXTRA_DIST += modules/objfmts/bin/tests/bin-farabs.asm EXTRA_DIST += modules/objfmts/bin/tests/bin-farabs.hex +EXTRA_DIST += modules/objfmts/bin/tests/bin-rip.asm +EXTRA_DIST += modules/objfmts/bin/tests/bin-rip.hex EXTRA_DIST += modules/objfmts/bin/tests/bintest.asm EXTRA_DIST += modules/objfmts/bin/tests/bintest.hex EXTRA_DIST += modules/objfmts/bin/tests/float-err.asm diff --git a/modules/objfmts/bin/tests/bin-rip.asm b/modules/objfmts/bin/tests/bin-rip.asm new file mode 100755 index 00000000..22110545 --- /dev/null +++ b/modules/objfmts/bin/tests/bin-rip.asm @@ -0,0 +1,20 @@ +bits 64 +org 0x100 +foo_equ equ 0x12345678 + +section .text +nop +foo_text: +nop +mov rax,[foo_equ wrt rip] +mov rax,[foo_text wrt rip] +mov rax,[foo_data wrt rip] +mov rbx,[foo_equ wrt rip] +mov rbx,[foo_text wrt rip] +mov rbx,[foo_data wrt rip] + +section .data +db 0 +foo_data: +db 0 + diff --git a/modules/objfmts/bin/tests/bin-rip.hex b/modules/objfmts/bin/tests/bin-rip.hex new file mode 100644 index 00000000..d56601d9 --- /dev/null +++ b/modules/objfmts/bin/tests/bin-rip.hex @@ -0,0 +1,46 @@ +90 +90 +48 +8b +05 +6f +55 +34 +12 +48 +8b +05 +f1 +ff +ff +ff +48 +8b +05 +16 +00 +00 +00 +48 +8b +1d +5a +55 +34 +12 +48 +8b +1d +dc +ff +ff +ff +48 +8b +1d +01 +00 +00 +00 +00 +00