diff options
author | Peter Johnson <peter@tortall.net> | 2011-10-30 22:21:57 -0700 |
---|---|---|
committer | Peter Johnson <peter@tortall.net> | 2011-10-30 22:21:57 -0700 |
commit | b334347286cc1cd088d79ff7c81ceca0a4ad923c (patch) | |
tree | b42a9e2411ed778281af4af1a422652981fca857 | |
parent | 2bd66514b6b100887c19d8598da38347b3cff40e (diff) | |
download | yasm-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.c | 31 | ||||
-rw-r--r-- | modules/objfmts/win64/tests/Makefile.inc | 2 | ||||
-rw-r--r-- | modules/objfmts/win64/tests/win64-imagebase.asm | 17 | ||||
-rw-r--r-- | modules/objfmts/win64/tests/win64-imagebase.hex | 512 |
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 |