mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
Merge [1878] from trunk: Fix bin objfmt handling of cross-section
RIP-relative values. svn path=/branches/yasm-0.6.x/; revision=1879
This commit is contained in:
commit
a682e7163a
4 changed files with 101 additions and 42 deletions
|
|
@ -103,11 +103,13 @@ bin_objfmt_expr_xform(/*@returned@*/ /*@only@*/ yasm_expr *e,
|
|||
/*@null@*/ yasm_intnum *dist;
|
||||
|
||||
for (i=0; i<e->numterms; 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 (value->rshift > 0)
|
||||
syme = yasm_expr_create(YASM_EXPR_SHR, yasm_expr_sym(value->rel),
|
||||
yasm_expr_int(yasm_intnum_create_uint(rshift)), bc->line);
|
||||
else
|
||||
syme = yasm_expr_create_ident(yasm_expr_sym(value->rel), bc->line);
|
||||
|
||||
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_expr(syme),
|
||||
yasm_expr_int(yasm_intnum_create_uint(rshift)), 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"));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
20
modules/objfmts/bin/tests/bin-rip.asm
Executable file
20
modules/objfmts/bin/tests/bin-rip.asm
Executable file
|
|
@ -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
|
||||
|
||||
46
modules/objfmts/bin/tests/bin-rip.hex
Normal file
46
modules/objfmts/bin/tests/bin-rip.hex
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue