diff -pruN 0.6-1/Makefile 0.7-1/Makefile
--- 0.6-1/Makefile	2025-02-04 19:37:40.000000000 +0000
+++ 0.7-1/Makefile	2025-10-04 10:35:49.000000000 +0000
@@ -1,4 +1,5 @@
 PROG = djstubify
+VER = 7
 prefix ?= /usr/local
 BINDIR ?= $(prefix)/bin
 CFLAGS ?= -Wall -Og -g
@@ -6,7 +7,7 @@ CFLAGS ?= -Wall -Og -g
 STYPE = mini
 STUB = $(STYPE)stub.exe
 STUB_S = $(STYPE)stub.S
-CPPFLAGS += \
+CPPFLAGS += -DDJSTUB_VER=$(VER) \
   -D_binary_stub_exe_start=_binary_$(STYPE)stub_exe_start \
   -D_binary_stub_exe_end=_binary_$(STYPE)stub_exe_end \
   -D_binary_stub_exe_size=_binary_$(STYPE)stub_exe_size
@@ -28,11 +29,13 @@ install:
 	install -m 0755 $(PROG) $(DESTDIR)$(BINDIR)
 	install -m 0755 djstrip $(DESTDIR)$(BINDIR)
 	install -m 0755 djlink $(DESTDIR)$(BINDIR)
+	install -m 0755 djelfextract $(DESTDIR)$(BINDIR)
 
 uninstall:
 	$(RM) $(DESTDIR)$(BINDIR)/$(PROG)
 	$(RM) $(DESTDIR)$(BINDIR)/djstrip
 	$(RM) $(DESTDIR)$(BINDIR)/djlink
+	$(RM) $(DESTDIR)$(BINDIR)/djelfextract
 
 deb:
 	debuild -i -us -uc -b
diff -pruN 0.6-1/debian/changelog 0.7-1/debian/changelog
--- 0.6-1/debian/changelog	2025-05-02 15:20:59.000000000 +0000
+++ 0.7-1/debian/changelog	2025-10-05 08:14:41.000000000 +0000
@@ -1,3 +1,10 @@
+djstub (0.7-1) unstable; urgency=medium
+
+  * New upstream release.
+  * Drop “Rules-Requires-Root: no” since it’s now the default.
+
+ -- Stephen Kitt <skitt@debian.org>  Sun, 05 Oct 2025 10:14:41 +0200
+
 djstub (0.6-1) unstable; urgency=medium
 
   * New upstream release.
diff -pruN 0.6-1/debian/control 0.7-1/debian/control
--- 0.6-1/debian/control	2025-05-02 15:20:50.000000000 +0000
+++ 0.7-1/debian/control	2025-10-05 08:10:25.000000000 +0000
@@ -9,7 +9,6 @@ Build-Depends:
 Homepage: https://github.com/stsp/djstub
 Vcs-Browser: https://salsa.debian.org/debian/djstub
 Vcs-Git: https://salsa.debian.org/debian/djstub.git
-Rules-Requires-Root: no
 
 Package: djstub
 Architecture: any
@@ -23,6 +22,7 @@ Description: DJGPP-compatible stub manip
  .
   - djstubify to modify the stub itself, in COFF and PE executables;
   - djlink to link ELF binaries and produce a dj64 executable;
+  - djelfextract to extract an ELF binary from a dj64 executable;
   - djstrip to strip dj64 executables.
  .
  It includes a stub with COFF and ELF loaders, capable of loading
diff -pruN 0.6-1/debian/copyright 0.7-1/debian/copyright
--- 0.6-1/debian/copyright	2024-11-06 07:02:06.000000000 +0000
+++ 0.7-1/debian/copyright	2025-10-05 08:14:23.000000000 +0000
@@ -12,7 +12,7 @@ License: LGPL-2.1-or-later
 
 Files: debian/*
 Copyright: 2022 Stas Sergeev
-           2024 Stephen Kitt
+           2024-2025 Stephen Kitt
 License: GPL-3-or-later
 
 
diff -pruN 0.6-1/djelfextract 0.7-1/djelfextract
--- 0.6-1/djelfextract	1970-01-01 00:00:00.000000000 +0000
+++ 0.7-1/djelfextract	2025-10-04 10:35:49.000000000 +0000
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+if [ "$#" -lt 2 ]; then
+  echo "Usage: djelfextract <solib_name> <out_elf>"
+  exit 0
+fi
+
+ID="`LC_ALL=C readelf -W -S $1 | grep .dj64startup | sed -E -e 's/.+\] +//' | \
+    tr -s '[:space:]'`"
+if [ -z "$ID" ]; then
+  echo ".dj64startup section not found"
+  exit 1
+fi
+
+SZ=`echo "$ID" | cut -d " " -f 5 | sed -E -e 's/0*/0x/'`
+OFF=`echo "$ID" | cut -d " " -f 4 | sed -E -e 's/0*/0x/'`
+dd if=$1 of=$2 bs=1 count=$(($SZ)) skip=$(($OFF))
diff -pruN 0.6-1/djlink 0.7-1/djlink
--- 0.6-1/djlink	2025-02-04 19:37:40.000000000 +0000
+++ 0.7-1/djlink	2025-10-04 10:35:49.000000000 +0000
@@ -1,11 +1,34 @@
 #!/usr/bin/env bash
 
+OS=`uname -s`
+if test "$OS" == "Darwin" && command -v brew &>/dev/null; then
+  # add keg-only llvm to PATH so llvm-objcopy and llvm-readobj can be found
+  PATH=$PATH:$(brew --prefix llvm)/bin
+fi
+
 if [ -z "$OBJCOPY" ]; then
   OBJCOPY=objcopy
+  if ! $OBJCOPY --version &> /dev/null; then
+     OBJCOPY=llvm-objcopy
+     if ! $OBJCOPY --version &> /dev/null; then
+       echo "Neither objcopy nor llvm-objcopy are installed"
+       exit 1
+     fi
+  fi
 fi
 if [ -z "$STRIP" ]; then
   STRIP=strip
 fi
+if [ "$OS" != "Darwin" -a -z "$READELF" ]; then
+  READELF=readelf
+  if ! $READELF --version &> /dev/null; then
+     READELF=llvm-readelf
+     if ! $READELF --version &> /dev/null; then
+       echo "Neither readelf nor llvm-readelf are installed"
+       exit 1
+     fi
+  fi
+fi
 
 if [ "$#" -lt 1 ]; then
   echo "Usage: djlink [-d <debug_name>] <solib_name> [<djstubify_opts>]"
@@ -34,26 +57,50 @@ if [ ! -f "$SO" ]; then
 fi
 
 if [ -n "$D" ]; then
-  if [ -z "`readelf -S $SO | grep .debug_info`" ]; then
+  if test "$OS" == "Darwin"; then
+    debuginfo="`dsymutil -s libtmp.so | grep N_OSO`"
+  else
+    debuginfo="`$READELF -S $SO | grep .debug_info`"
+  fi
+  if [ -z "$debuginfo" ]; then
     echo "$0: -d is specified but $SO is stripped"
     exit 1
   fi
   DBG="/tmp/$D"
-  $OBJCOPY --only-keep-debug $SO $DBG
   TMP=$(mktemp)
-  $STRIP -o $TMP $SO
-  $OBJCOPY --add-gnu-debuglink=$DBG $TMP
-  OFFS=`LC_ALL=C readelf -S $TMP | grep .gnu_debuglink | \
-    tr -s '[:space:]' | cut -d " " -f 6 | sed -E -e 's/0*/0x/'`
+  if test "$OS" == "Darwin"; then
+    dsymutil -f $SO -o $DBG
+    $STRIP -x -o $TMP $SO
+    TMP2=$(mktemp)
+    echo $D > $TMP2
+    $OBJCOPY --add-section __TEXT,.gnu_debuglink=$TMP2 $TMP
+    OFFS=`LC_ALL=C llvm-readobj -S $TMP | grep -A 4 .gnu_debuglink | \
+       grep Offset | sed 's/.* //'`
+  else
+    $OBJCOPY --only-keep-debug $SO $DBG
+    $STRIP -o $TMP $SO
+    $OBJCOPY --add-gnu-debuglink=$DBG $TMP
+    OFFS=`LC_ALL=C $READELF -S $TMP | grep .gnu_debuglink | \
+      tr -s '[:space:]' | cut -d " " -f 6 | sed -E -e 's/0*/0x/'`
+  fi
   SO=$TMP
   DOPT="-n $OFFS -l $DBG"
 fi
 
-ID="`LC_ALL=C readelf -S $SO | grep .dj64startup`"
+if test "$OS" == "Darwin"; then
+  ID="`LC_ALL=C llvm-readobj -W -S $SO | grep -A 4 .dj64startup`"
+else
+  ID="`LC_ALL=C $READELF -W -S $SO | grep .dj64startup | sed -E -e 's/.+\] +//' | \
+    tr -s '[:space:]'`"
+fi
 if [ -n "$ID" ]; then
-  SZ=`LC_ALL=C readelf -S $SO | grep -A 1 .dj64startup | tail -n 1 | \
-    tr -s '[:space:]' | cut -d " " -f 2 | sed -E -e 's/0*/0x/'`
-  OFF=`echo "$ID" | tr -s '[:space:]' | cut -d " " -f 6 | sed -E -e 's/0*/0x/'`
+  if test "$OS" == "Darwin"; then
+    SZ=`echo "$ID" | grep Size | sed -e 's/.* //'`
+    OFF=`echo "$ID" | grep Offset | sed -e 's/.* //'`
+  else
+    SZ=`echo "$ID" | cut -d " " -f 5 | sed -E -e 's/0*/0x/'`
+    OFF=`echo "$ID" | cut -d " " -f 4 | sed -E -e 's/0*/0x/'`
+  fi
   DOPT="$DOPT -S $SZ -O $OFF -f 0x8000"
 fi
 
@@ -62,6 +109,7 @@ CMD="djstubify -g $* -l $SO $DOPT"
 $CMD
 
 [ -z "$TMP" ] || rm "$TMP"
+[ -z "$TMP2" ] || rm "$TMP2"
 if [ -n "$DBG" -a -f "$DBG" ]; then
   rm $DBG
 fi
diff -pruN 0.6-1/mini/ministub.c 0.7-1/mini/ministub.c
--- 0.6-1/mini/ministub.c	2025-02-04 19:37:40.000000000 +0000
+++ 0.7-1/mini/ministub.c	2025-10-04 10:35:49.000000000 +0000
@@ -17,10 +17,12 @@
  *
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <assert.h>
 
 #define DJSTUB_API_VER 5
 
@@ -90,7 +92,8 @@ static void enter_stub(unsigned sel, uns
 
 extern void* __dpmi_psp;
 extern void* __dpmi_env;
-static unsigned psp;
+static unsigned short psp;
+static unsigned esp;
 
 int main(int argc, char *argv[])
 {
@@ -105,7 +108,7 @@ int main(int argc, char *argv[])
 
   if (argc == 0) {
     puts("no env");
-    return 1;
+    return EXIT_FAILURE;
   }
   for (envc = i = letter = 0;; i++) {
     if (env[i] == '\0') {
@@ -152,21 +155,23 @@ int main(int argc, char *argv[])
     "mov cx, 0\n"
     "mov dx, 0ffh\n"  // to PSP size
     "int 31h\n"
+    "mov [_esp], esp\n"
   );
   err = DPMIQueryExtension(&sel, &off, ext_nm);
   if (err) {
     printf("%s unsupported (%x)\n", ext_nm, err);
-    return 1;
+    return EXIT_FAILURE;
   }
 
   fd = open(argv[0], O_RDONLY);
   if (fd == -1) {
     printf("unable to open %s: %s\n", argv[0], strerror(errno));
-    return 1;
+    return EXIT_FAILURE;
   }
 
   memset(&regs, 0, sizeof(regs));
   /* nuke out initial stub as it is no longer needed */
+  assert(esp > 0x110000); /* not going to free own stack */
   regs.eax = 0x4a00;
   regs.ebx = 0x10;  // leave only PSP
   regs.es = (unsigned)__dpmi_psp >> 4;
@@ -174,5 +179,5 @@ int main(int argc, char *argv[])
   enter_stub(sel, off, argc, argv, envc, envp, psp, fd, DJSTUB_API_VER);
   close(fd);
   puts("stub returned");
-  return 0;
+  return EXIT_FAILURE;
 }
diff -pruN 0.6-1/stubify.c 0.7-1/stubify.c
--- 0.6-1/stubify.c	2025-02-04 19:37:40.000000000 +0000
+++ 0.7-1/stubify.c	2025-10-04 10:35:49.000000000 +0000
@@ -40,9 +40,11 @@
 #include <assert.h>
 #include "elf.h"
 
-extern char _binary_stub_exe_end[];
-extern char _binary_stub_exe_size[];
-extern char _binary_stub_exe_start[];
+#define str(s) #s
+#define ASMSYM(s) asm(str(s))
+extern char _binary_stub_exe_end[] ASMSYM(_binary_stub_exe_end);
+extern char _binary_stub_exe_size[] ASMSYM(_binary_stub_exe_size);
+extern char _binary_stub_exe_start[] ASMSYM(_binary_stub_exe_start);
 
 #define v_printf if(verbose)printf
 static int verbose;
@@ -52,7 +54,7 @@ static char *overlay[MAX_OVL];
 static int strip;
 static uint8_t stub_ver = 6;
 static uint8_t flags_ver = 0;
-static const int version = 0;
+static const int version = DJSTUB_VER;
 
 static int copy_file(const char *ovl, int ofile)
 {
@@ -223,7 +225,6 @@ static int coff2exe(const char *fname, c
           dyn++;
         memcpy(&offs, &buf[0x3c], sizeof(offs));
         coffset = offs;
-        memcpy(&coff_file_size, &buf[0x1c], sizeof(coff_file_size));
         memcpy(mzhdr_buf, buf, sizeof(mzhdr_buf));
         can_copy_ovl++;
         if (rmstub || strip)
@@ -236,18 +237,14 @@ static int coff2exe(const char *fname, c
         }
         if (info || strip) {
           int cnt = 0;
+          int embl = 0;
           uint32_t sz = 0;
           char name[20] = {};
           for (i = 0x1c; i < 0x28; i += 4) {
             uint32_t sz0;
             memcpy(&sz0, &buf[i], sizeof(sz0));
-            if (!sz0) {
-              if (strip && sz) {
-                coff_file_size = offs - sz - coffset;
-                memset(&mzhdr_buf[i - 4], 0, 4);
-              }
+            if (!sz0)
               break;
-            }
             sz = sz0;
             if (!cnt) {
               has_o0++;
@@ -256,16 +253,21 @@ static int coff2exe(const char *fname, c
                 offs += ooffs;
               }
             }
-            if (stub_v6 && cnt == 1 && (flags & 0x8000))
+            if (stub_v6 && cnt == 1 && (flags & 0x8000)) {
               offs = coffset;
+              embl = 1;
+            }
             if (info) {
               int prname = 0;
               if (stub_v6 && cnt + dyn == 1 && buf[0x28]) {
                 uint32_t noff;
                 memcpy(&noff, &buf[0x28], sizeof(noff));
                 lseek(ifile, offs + noff, SEEK_SET);
-                read(ifile, name, 16);
-                name[16] = '\0';
+                rc = read(ifile, name, 16);
+                if (rc == 16)
+                  name[16] = '\0';
+                else
+                  name[0] = '\0';
               }
               prname = (name[0] && cnt + dyn == 2);
               IPRINTF("Overlay %i (%s%s%s) at %i, size %i\n", cnt,
@@ -276,6 +278,13 @@ static int coff2exe(const char *fname, c
             offs += sz;
             cnt++;
           }
+          if (rmstub) {
+            /* rmstub removes all overlays */
+            memcpy(&coff_file_size, &buf[0x1c], sizeof(coff_file_size));
+          } else if (strip && cnt > 1 + embl) {
+            coff_file_size = offs - sz - coffset;
+            memset(&mzhdr_buf[i - 4], 0, 4);
+          }
           if (stub_v4 && !stub_v6) {
             if (buf[0x2e])
               IPRINTF("Overlay name: %.12s\n", buf + 0x2e);
@@ -442,7 +451,7 @@ int main(int argc, char **argv)
     case 'v':
 #define _S(x) #x
 #define S(x) _S(x)
-      printf("djstubify version 0.%i\n", version + stub_ver);
+      printf("djstubify version 0.%i\n", version);
       return 0;
     case 'd':
       verbose = 1;
