From: Peter Johnson Date: Fri, 8 Feb 2008 18:26:40 +0000 (-0000) Subject: Fix #130: Add SAFESEH directive for indicating SEH handlers in win32 output. X-Git-Tag: v0.7.0~25 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0fba7dca8d2e22a5825dd7c9f14c24a7ffee17b3;p=yasm Fix #130: Add SAFESEH directive for indicating SEH handlers in win32 output. Unlike in MASM, no command-line switch is required. Usage: extern handler (or handler: to define locally) safeseh handler svn path=/trunk/yasm/; revision=2032 --- diff --git a/modules/objfmts/coff/coff-objfmt.c b/modules/objfmts/coff/coff-objfmt.c index 9c69ad35..64805610 100644 --- a/modules/objfmts/coff/coff-objfmt.c +++ b/modules/objfmts/coff/coff-objfmt.c @@ -218,6 +218,28 @@ static const yasm_assoc_data_callback coff_symrec_data_cb = { coff_symrec_data_print }; +/* Bytecode callback function prototypes */ +static void win32_sxdata_bc_destroy(void *contents); +static void win32_sxdata_bc_print(const void *contents, FILE *f, + int indent_level); +static int win32_sxdata_bc_calc_len + (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data); +static int win32_sxdata_bc_tobytes + (yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + /*@null@*/ yasm_output_reloc_func output_reloc); + +/* Bytecode callback structures */ +static const yasm_bytecode_callback win32_sxdata_bc_callback = { + win32_sxdata_bc_destroy, + win32_sxdata_bc_print, + yasm_bc_finalize_common, + win32_sxdata_bc_calc_len, + yasm_bc_expand_common, + win32_sxdata_bc_tobytes, + 0 +}; + yasm_objfmt_module yasm_coff_LTX_objfmt; yasm_objfmt_module yasm_win32_LTX_objfmt; yasm_objfmt_module yasm_win64_LTX_objfmt; @@ -1478,6 +1500,8 @@ 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; + } else if (objfmt_coff->win32 && strcmp(sectname, ".sxdata") == 0) { + data.flags = COFF_STYP_INFO; } else if (strcmp(sectname, ".comment") == 0) { data.flags = COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ; } else if (yasm__strncasecmp(sectname, ".debug", 6)==0) { @@ -1649,6 +1673,88 @@ dir_export(yasm_object *object, yasm_valparamhead *valparams, yasm_section_bcs_append(sect, yasm_bc_create_data(&dvs, 1, 0, NULL, line)); } +static void +dir_safeseh(yasm_object *object, yasm_valparamhead *valparams, + yasm_valparamhead *objext_valparams, unsigned long line) +{ + yasm_valparam *vp; + /*@null@*/ const char *symname; + yasm_symrec *sym; + int isnew; + yasm_section *sect; + + /* Reference symbol (to generate error if not declared). + * Also, symbol must be externally visible, so force global. + */ + vp = yasm_vps_first(valparams); + symname = yasm_vp_id(vp); + if (symname) { + sym = yasm_symtab_use(object->symtab, symname, line); + yasm_symrec_declare(sym, YASM_SYM_GLOBAL, line); + } else { + yasm_error_set(YASM_ERROR_SYNTAX, + N_("argument to SAFESEH must be symbol name")); + return; + } + + /* + * Add symbol number to end of .sxdata section. + */ + + sect = yasm_object_get_general(object, ".sxdata", 0, 0, 0, &isnew, line); + + /* Initialize sxdata section if needed */ + if (isnew) { + coff_section_data *csd; + csd = coff_objfmt_init_new_section(object, sect, ".sxdata", line); + csd->flags = COFF_STYP_INFO; + } + + /* Add as sxdata bytecode */ + yasm_section_bcs_append(sect, + yasm_bc_create_common(&win32_sxdata_bc_callback, + sym, line)); +} + +static void +win32_sxdata_bc_destroy(void *contents) +{ + /* Contents is just the symbol pointer, so no need to delete */ +} + +static void +win32_sxdata_bc_print(const void *contents, FILE *f, int indent_level) +{ + /* TODO */ +} + +static int +win32_sxdata_bc_calc_len(yasm_bytecode *bc, yasm_bc_add_span_func add_span, + void *add_span_data) +{ + bc->len += 4; + return 0; +} + +static int +win32_sxdata_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d, + yasm_output_value_func output_value, + yasm_output_reloc_func output_reloc) +{ + yasm_symrec *sym = (yasm_symrec *)bc->contents; + unsigned char *buf = *bufp; + coff_symrec_data *csymd; + + csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb); + if (!csymd) + yasm_internal_error(N_("coff: no symbol data for SAFESEH symbol")); + + YASM_WRITE_32_L(buf, csymd->index); + + *bufp = buf; + return 0; +} + static void dir_ident(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) @@ -2099,6 +2205,7 @@ static const yasm_directive win32_objfmt_directives[] = { { ".export", "gas", dir_export, YASM_DIR_ID_REQUIRED }, { "ident", "nasm", dir_ident, YASM_DIR_ANY }, { "export", "nasm", dir_export, YASM_DIR_ID_REQUIRED }, + { "safeseh", "nasm", dir_safeseh, YASM_DIR_ID_REQUIRED }, { NULL, NULL, NULL, 0 } }; diff --git a/modules/objfmts/win32/tests/Makefile.inc b/modules/objfmts/win32/tests/Makefile.inc index 5bb8d143..3b16d3db 100644 --- a/modules/objfmts/win32/tests/Makefile.inc +++ b/modules/objfmts/win32/tests/Makefile.inc @@ -9,6 +9,9 @@ EXTRA_DIST += modules/objfmts/win32/tests/win32-curpos.asm EXTRA_DIST += modules/objfmts/win32/tests/win32-curpos.hex EXTRA_DIST += modules/objfmts/win32/tests/win32-overdef.asm EXTRA_DIST += modules/objfmts/win32/tests/win32-overdef.hex +EXTRA_DIST += modules/objfmts/win32/tests/win32-safeseh.asm +EXTRA_DIST += modules/objfmts/win32/tests/win32-safeseh.hex +EXTRA_DIST += modules/objfmts/win32/tests/win32-safeseh.masm EXTRA_DIST += modules/objfmts/win32/tests/win32-segof.asm EXTRA_DIST += modules/objfmts/win32/tests/win32-segof.hex EXTRA_DIST += modules/objfmts/win32/tests/win32test.c diff --git a/modules/objfmts/win32/tests/win32-safeseh.asm b/modules/objfmts/win32/tests/win32-safeseh.asm new file mode 100644 index 00000000..9edd8ede --- /dev/null +++ b/modules/objfmts/win32/tests/win32-safeseh.asm @@ -0,0 +1,5 @@ +MyHandler: + ret +safeseh MyHandler +extern MyHandler3 +safeseh MyHandler3 diff --git a/modules/objfmts/win32/tests/win32-safeseh.hex b/modules/objfmts/win32/tests/win32-safeseh.hex new file mode 100644 index 00000000..5598d6fc --- /dev/null +++ b/modules/objfmts/win32/tests/win32-safeseh.hex @@ -0,0 +1,278 @@ +4c +01 +02 +00 +00 +00 +00 +00 +6d +00 +00 +00 +08 +00 +00 +00 +00 +00 +0c +01 +2e +74 +65 +78 +74 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +64 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +20 +00 +50 +60 +2e +73 +78 +64 +61 +74 +61 +00 +01 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +65 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +c3 +04 +00 +00 +00 +07 +00 +00 +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 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +02 +00 +2e +73 +78 +64 +61 +74 +61 +00 +00 +00 +00 +00 +02 +00 +00 +00 +03 +01 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0e +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +02 +00 +19 +00 +00 +00 +4d +79 +48 +61 +6e +64 +6c +65 +72 +00 +4d +79 +48 +61 +6e +64 +6c +65 +72 +33 +00 diff --git a/modules/objfmts/win32/tests/win32-safeseh.masm b/modules/objfmts/win32/tests/win32-safeseh.masm new file mode 100644 index 00000000..f165b9c3 --- /dev/null +++ b/modules/objfmts/win32/tests/win32-safeseh.masm @@ -0,0 +1,10 @@ +.386 +.model flat +_TEXT SEGMENT USE32 PUBLIC 'CODE' +MyHandler proc +.safeseh MyHandler +MyHandler endp +_TEXT ENDS +MyHandler3 proto +.safeseh MyHandler3 +end diff --git a/modules/preprocs/nasm/standard.mac b/modules/preprocs/nasm/standard.mac index 6efd3c84..f459a7db 100644 --- a/modules/preprocs/nasm/standard.mac +++ b/modules/preprocs/nasm/standard.mac @@ -131,6 +131,10 @@ __SECT__ %imacro export 1+.nolist [export %1] %endmacro + +%imacro safeseh 1+.nolist +[safeseh %1] +%endmacro %endif %ifidn __YASM_OBJFMT__,win64