[PATCH] gas: support for .pushsection and .popsection pseudo ops for coff

Johannes Khoshnazar-Thoma johannes@johannesthoma.com
Sat Jul 18 16:22:02 GMT 2026


Current Linux kernels make heavy use of the .pushsection and
.popsection pseudo ops. Normally, the Linux kernel is built
as an ELF object, where the assembler supports those pseudo
ops. When compiling the Linux kernel as a Windows/ReactOS
driver however, it must be compiled as a COFF object, since
the Windows/ReactOS kernel does not know how to load ELF
binaries.

In order to be able to compile the Linux kernel as a COFF
object (and further on as a PE32 native executable) the
implementation of those pseudo ops has been copiied from
the obj-elf.c support code to the obj-coff.c support code.
It has been verified that the Linux kernel works without
assembler errors when using an assembler with this patch.

Signed-off-by: Johannes Khoshnazar-Thoma <johannes@johannesthoma.com>
---
 gas/config/obj-coff.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index 7732c0af911..73c571b71de 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -1536,6 +1536,32 @@ obj_coff_finalize_section_relocs (asection *sec, arelent **relocs,
   return true;
 }
 
+struct section_stack
+{
+  struct section_stack *next;
+  segT seg;
+  int subseg;
+};
+
+static struct section_stack *section_stack;
+
+static void
+obj_coff_popsection (int xxx ATTRIBUTE_UNUSED)
+{
+  struct section_stack *top = section_stack;
+
+  if (top == NULL)
+    {
+      as_warn (_(".popsection without corresponding .pushsection; ignored"));
+      return;
+    }
+
+  section_stack = top->next;
+  subseg_set (top->seg, top->subseg);
+  free (top);
+}
+
+
 /* Implement the .section pseudo op:
   	.section name {, "flags"}
                   ^         ^
@@ -1559,7 +1585,7 @@ obj_coff_finalize_section_relocs (asection *sec, arelent **relocs,
    .section directive to be parsed in both ELF and COFF formats.  */
 
 void
-obj_coff_section (int ignore ATTRIBUTE_UNUSED)
+obj_coff_section (int push)
 {
   /* Strip out the section name.  */
   char *section_name;
@@ -1691,6 +1717,17 @@ obj_coff_section (int ignore ATTRIBUTE_UNUSED)
 	}
     }
 
+  /* .pushsection implementation */
+  if (push)
+    {
+      struct section_stack *elt;
+      elt = XNEW (struct section_stack);
+      elt->next = section_stack;
+      elt->seg = now_seg;
+      elt->subseg = now_subseg;
+      section_stack = elt;
+    }
+
   sec = subseg_new (name, exp);
 
   if (is_bss)
@@ -1903,6 +1940,8 @@ static const pseudo_typeS coff_pseudo_table[] =
   {"sect.s", obj_coff_section, 0},
   {"section", obj_coff_section, 0},
   {"section.s", obj_coff_section, 0},
+  {"pushsection", obj_coff_section, 1},
+  {"popsection", obj_coff_popsection, 0},
   /* FIXME: We ignore the MRI short attribute.  */
   {"size", obj_coff_size, 0},
   {"tag", obj_coff_tag, 0},
-- 
2.55.0



More information about the Binutils mailing list