]> granicus.if.org Git - yasm/commitdiff
Fix #130: Add SAFESEH directive for indicating SEH handlers in win32 output.
authorPeter Johnson <peter@tortall.net>
Fri, 8 Feb 2008 18:26:40 +0000 (18:26 -0000)
committerPeter Johnson <peter@tortall.net>
Fri, 8 Feb 2008 18:26:40 +0000 (18:26 -0000)
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

modules/objfmts/coff/coff-objfmt.c
modules/objfmts/win32/tests/Makefile.inc
modules/objfmts/win32/tests/win32-safeseh.asm [new file with mode: 0644]
modules/objfmts/win32/tests/win32-safeseh.hex [new file with mode: 0644]
modules/objfmts/win32/tests/win32-safeseh.masm [new file with mode: 0644]
modules/preprocs/nasm/standard.mac

index 9c69ad35e13afcf976ec8d095f1031101d6fd886..64805610c9343cb1b71cdb344c0595bdbb1734d4 100644 (file)
@@ -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 }
 };
 
index 5bb8d143250d130b5fcccd9dab0d9a6126a45e4d..3b16d3db9c1ce593afe5e18aefbc3f6cf0567944 100644 (file)
@@ -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 (file)
index 0000000..9edd8ed
--- /dev/null
@@ -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 (file)
index 0000000..5598d6f
--- /dev/null
@@ -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 (file)
index 0000000..f165b9c
--- /dev/null
@@ -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
index 6efd3c84ffca0d7a7c61fd5d5d7d2c20475a5114..f459a7db515a6944d3c569e1e019688823554137 100644 (file)
@@ -131,6 +131,10 @@ __SECT__
 %imacro export 1+.nolist
 [export %1]
 %endmacro
+
+%imacro safeseh 1+.nolist
+[safeseh %1]
+%endmacro
 %endif
 
 %ifidn __YASM_OBJFMT__,win64