aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Johnson <peter@tortall.net>2011-10-30 22:21:57 -0700
committerPeter Johnson <peter@tortall.net>2011-10-30 22:21:57 -0700
commitb334347286cc1cd088d79ff7c81ceca0a4ad923c (patch)
treeb42a9e2411ed778281af4af1a422652981fca857
parent2bd66514b6b100887c19d8598da38347b3cff40e (diff)
downloadyasm-b334347286cc1cd088d79ff7c81ceca0a4ad923c.tar.gz
win64: Default to nobase for .xdata section.
Also add ..imagebase special symbol to force use of a nobase relocation. [#135 state:resolved]
-rw-r--r--modules/objfmts/coff/coff-objfmt.c31
-rw-r--r--modules/objfmts/win64/tests/Makefile.inc2
-rw-r--r--modules/objfmts/win64/tests/win64-imagebase.asm17
-rw-r--r--modules/objfmts/win64/tests/win64-imagebase.hex512
4 files changed, 557 insertions, 5 deletions
diff --git a/modules/objfmts/coff/coff-objfmt.c b/modules/objfmts/coff/coff-objfmt.c
index 4278fa6d..c9646c62 100644
--- a/modules/objfmts/coff/coff-objfmt.c
+++ b/modules/objfmts/coff/coff-objfmt.c
@@ -189,6 +189,8 @@ typedef struct yasm_objfmt_coff {
unsigned long proc_frame; /* Line number of start of proc, or 0 */
unsigned long done_prolog; /* Line number of end of prologue, or 0 */
/*@null@*/ coff_unwind_info *unwind; /* Unwind info */
+
+ yasm_symrec *ssym_imagebase; /* ..imagebase symbol for win64 */
} yasm_objfmt_coff;
typedef struct coff_objfmt_output_info {
@@ -296,6 +298,7 @@ coff_common_create(yasm_object *object)
objfmt_coff->proc_frame = 0;
objfmt_coff->done_prolog = 0;
objfmt_coff->unwind = NULL;
+ objfmt_coff->ssym_imagebase = NULL;
return objfmt_coff;
}
@@ -382,6 +385,8 @@ win64_objfmt_create(yasm_object *object)
objfmt_coff->objfmt.module = &yasm_win64_LTX_objfmt;
objfmt_coff->win32 = 1;
objfmt_coff->win64 = 1;
+ objfmt_coff->ssym_imagebase =
+ yasm_symtab_define_label(object->symtab, "..imagebase", NULL, 0, 0);
}
return (yasm_objfmt *)objfmt_coff;
}
@@ -489,14 +494,18 @@ coff_objfmt_output_value(yasm_value *value, unsigned char *buf,
/*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
unsigned long addr;
coff_reloc *reloc;
+ int nobase = info->csd->flags2 & COFF_FLAG_NOBASE;
/* Sometimes we want the relocation to be generated against one
* symbol but the value generated correspond to a different symbol.
* This is done through (sym being referenced) WRT (sym used for
* reloc). Note both syms need to be in the same section!
*/
- if (value->wrt) {
+ if (value->wrt && value->wrt == objfmt_coff->ssym_imagebase)
+ nobase = 1;
+ else if (value->wrt) {
/*@dependent@*/ /*@null@*/ yasm_bytecode *rel_precbc, *wrt_precbc;
+
if (!yasm_symrec_get_label(sym, &rel_precbc)
|| !yasm_symrec_get_label(value->wrt, &wrt_precbc)) {
yasm_error_set(YASM_ERROR_TOO_COMPLEX,
@@ -644,13 +653,13 @@ coff_objfmt_output_value(yasm_value *value, unsigned char *buf,
yasm_internal_error(N_("coff objfmt: unrecognized machine"));
} else {
if (objfmt_coff->machine == COFF_MACHINE_I386) {
- if (info->csd->flags2 & COFF_FLAG_NOBASE)
+ if (nobase)
reloc->type = COFF_RELOC_I386_ADDR32NB;
else
reloc->type = COFF_RELOC_I386_ADDR32;
} else if (objfmt_coff->machine == COFF_MACHINE_AMD64) {
if (valsize == 32) {
- if (info->csd->flags2 & COFF_FLAG_NOBASE)
+ if (nobase)
reloc->type = COFF_RELOC_AMD64_ADDR32NB;
else
reloc->type = COFF_RELOC_AMD64_ADDR32;
@@ -1514,6 +1523,7 @@ coff_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
} else if (objfmt_coff->win64 && strcmp(sectname, ".xdata") == 0) {
data.flags = COFF_STYP_DATA | COFF_STYP_READ;
align = 8;
+ data.flags2 = COFF_FLAG_NOBASE;
} else if (objfmt_coff->win32 && strcmp(sectname, ".sxdata") == 0) {
data.flags = COFF_STYP_INFO;
} else if (strcmp(sectname, ".comment") == 0) {
@@ -1596,6 +1606,17 @@ coff_objfmt_get_special_sym(yasm_object *object, const char *name,
return NULL;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+win64_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ if (yasm__strcasecmp(name, "imagebase") == 0) {
+ yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
+ return objfmt_coff->ssym_imagebase;
+ }
+ return NULL;
+}
+
static void
coff_section_data_destroy(void *data)
{
@@ -2465,7 +2486,7 @@ yasm_objfmt_module yasm_win64_LTX_objfmt = {
coff_objfmt_add_default_section,
coff_objfmt_init_new_section,
coff_objfmt_section_switch,
- coff_objfmt_get_special_sym
+ win64_objfmt_get_special_sym
};
yasm_objfmt_module yasm_x64_LTX_objfmt = {
"Win64",
@@ -2483,5 +2504,5 @@ yasm_objfmt_module yasm_x64_LTX_objfmt = {
coff_objfmt_add_default_section,
coff_objfmt_init_new_section,
coff_objfmt_section_switch,
- coff_objfmt_get_special_sym
+ win64_objfmt_get_special_sym
};
diff --git a/modules/objfmts/win64/tests/Makefile.inc b/modules/objfmts/win64/tests/Makefile.inc
index d1096268..24584267 100644
--- a/modules/objfmts/win64/tests/Makefile.inc
+++ b/modules/objfmts/win64/tests/Makefile.inc
@@ -27,6 +27,8 @@ EXTRA_DIST += modules/objfmts/win64/tests/win64-dataref.masm
EXTRA_DIST += modules/objfmts/win64/tests/win64-dataref2.asm
EXTRA_DIST += modules/objfmts/win64/tests/win64-dataref2.hex
EXTRA_DIST += modules/objfmts/win64/tests/win64-dataref2.masm
+EXTRA_DIST += modules/objfmts/win64/tests/win64-imagebase.hex
+EXTRA_DIST += modules/objfmts/win64/tests/win64-imagebase.asm
EXTRA_DIST += modules/objfmts/win64/tests/gas/Makefile.inc
diff --git a/modules/objfmts/win64/tests/win64-imagebase.asm b/modules/objfmts/win64/tests/win64-imagebase.asm
new file mode 100644
index 00000000..bd636026
--- /dev/null
+++ b/modules/objfmts/win64/tests/win64-imagebase.asm
@@ -0,0 +1,17 @@
+[section .text]
+handler: ret
+func: ret
+func_end:
+
+[section .pdata]
+ dd func
+ dd func_end
+ dd myunwnd
+
+[section .xdata]
+myunwnd:
+ db 9,0,0,0
+ dd handler
+
+[section .foo]
+ dd handler wrt ..imagebase
diff --git a/modules/objfmts/win64/tests/win64-imagebase.hex b/modules/objfmts/win64/tests/win64-imagebase.hex
new file mode 100644
index 00000000..b715eb43
--- /dev/null
+++ b/modules/objfmts/win64/tests/win64-imagebase.hex
@@ -0,0 +1,512 @@
+64
+86
+04
+00
+00
+00
+00
+00
+00
+01
+00
+00
+0e
+00
+00
+00
+00
+00
+04
+00
+2e
+74
+65
+78
+74
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+b4
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+20
+00
+50
+60
+2e
+70
+64
+61
+74
+61
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+0c
+00
+00
+00
+b6
+00
+00
+00
+c2
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+40
+00
+30
+40
+2e
+78
+64
+61
+74
+61
+00
+00
+0e
+00
+00
+00
+00
+00
+00
+00
+08
+00
+00
+00
+e0
+00
+00
+00
+e8
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+40
+00
+40
+40
+2e
+66
+6f
+6f
+00
+00
+00
+00
+16
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+f2
+00
+00
+00
+f6
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+20
+00
+00
+60
+c3
+c3
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+05
+00
+00
+00
+03
+00
+04
+00
+00
+00
+06
+00
+00
+00
+03
+00
+08
+00
+00
+00
+09
+00
+00
+00
+03
+00
+09
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+04
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+03
+00
+2e
+66
+69
+6c
+65
+00
+00
+00
+00
+00
+00
+00
+fe
+ff
+00
+00
+67
+01
+2d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+03
+01
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+68
+61
+6e
+64
+6c
+65
+72
+00
+00
+00
+00
+00
+01
+00
+00
+00
+03
+00
+66
+75
+6e
+63
+00
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+03
+00
+66
+75
+6e
+63
+5f
+65
+6e
+64
+02
+00
+00
+00
+01
+00
+00
+00
+03
+00
+2e
+70
+64
+61
+74
+61
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+03
+01
+0c
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+6d
+79
+75
+6e
+77
+6e
+64
+00
+00
+00
+00
+00
+03
+00
+00
+00
+03
+00
+2e
+78
+64
+61
+74
+61
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+03
+01
+08
+00
+00
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+2e
+66
+6f
+6f
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+03
+01
+04
+00
+00
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00