Reimplement the .seh_scope directive
Checks
Commit Message
The .seh_scope directive was removed a little over a decade ago due to
being too Microsoft specific. This has proven to be a mistake as there is
now no easy way for reusable inline assembly to express Structured
Exception Handling scopes for Microsoft Windows targets, combined with the
handler count field that the xdata section requires. This patch
reimplements a simpler version of .seh_scope, with the proper semantics in
place
From cc9e143f8feb933ca8fc4b12deaab2985893b714 Mon Sep 17 00:00:00 2001
From: TheShermanTanker <tanksherman27@gmail.com>
Date: Sun, 2 Jul 2023 16:22:18 +0800
Subject: [PATCH] Reimplement .seh_scope
---
gas/config/obj-coff-seh.c | 26 ++++++++++++++++++++++++--
gas/config/obj-coff-seh.h | 5 ++++-
2 files changed, 28 insertions(+), 3 deletions(-)
--
2.35.1.windows.2
@@ -30,6 +32,7 @@ struct seh_seg_list {
/* Local data. */
static seh_context *seh_ctx_cur = NULL;
+static unsigned int scope = 0;
static htab_t seh_hash;
@@ -385,7 +388,21 @@ obj_coff_seh_handlerdata (int what ATTRIBUTE_UNUSED)
return;
demand_empty_rest_of_line ();
- switch_xdata (seh_ctx_cur->subsection + 1, seh_ctx_cur->code_seg);
+ switch_xdata (seh_ctx_cur->subsection + (scope == 0) ? 1 : 2,
seh_ctx_cur->code_seg);
+}
+
+static void obj_coff_seh_scope (int what)
+{
+ if (!verify_context_and_target (".seh_scope", seh_kind_x64))
+ return;
+
+ segT seg = now_seg;
+ int subseg = now_subseg;
+
+ scope++;
+ switch_xdata (seh_ctx_cur->subsection + 2, seh_ctx_cur->code_seg);
+ s_rva (4);
+ subseg_set(seg, subseg);
}
/* Mark end of current context. */
@@ -442,7 +459,7 @@ obj_coff_seh_proc (int what ATTRIBUTE_UNUSED)
{
x_segcur = seh_hash_find_or_make (seh_ctx_cur->code_seg, ".xdata");
seh_ctx_cur->subsection = x_segcur->subseg;
- x_segcur->subseg += 2;
+ x_segcur->subseg += 3;
}
SKIP_WHITESPACE ();
@@ -918,6 +935,11 @@ write_function_xdata (seh_context *c)
seh_x64_write_function_xdata (c);
+ if (scope > 0) {
+ switch_xdata (c->subsection + 1, c->code_seg);
+ out_four (scope);
+ }
+
subseg_set (save_seg, save_subseg);
}
@@ -57,6 +57,7 @@
.seh_savexmm
.seh_pushframe
.seh_code
+ .seh_scope
*/
/* architecture specific pdata/xdata handling. */
@@ -75,7 +76,8 @@
{"seh_no32", obj_coff_seh_32, 0}, \
{"seh_handler", obj_coff_seh_handler, 0}, \
{"seh_code", obj_coff_seh_code, 0}, \
- {"seh_handlerdata", obj_coff_seh_handlerdata, 0},
+ {"seh_handlerdata", obj_coff_seh_handlerdata, 0}, \
+ {"seh_scope", obj_coff_seh_scope, 0},
/* Type definitions. */
@@ -151,6 +153,7 @@ static void obj_coff_seh_proc (int);
static void obj_coff_seh_handler (int);
static void obj_coff_seh_handlerdata (int);
static void obj_coff_seh_code (int);
+static void obj_coff_seh_scope (int);
#define UNDSEC bfd_und_section_ptr