diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Revision history for ghc-debug-stub
 
+## 0.8.0.0 -- 2026-03-26
+
+* Support non-moving segements and other large block groups
+* Workaround GHC issues #26745
+* Interpret AP_STACK size as words rather than bytes
+* Add support for the `ANN_FRAME` stack frame
+* Fix CPP guard in stub
+
 ## 0.7.0.0 -- 2025-05-20
 
 * Compatability with 9.10 and 9.12
diff --git a/cbits/stub.cpp b/cbits/stub.cpp
--- a/cbits/stub.cpp
+++ b/cbits/stub.cpp
@@ -21,6 +21,10 @@
 #include <stdarg.h>
 #include <stdio.h>
 
+extern "C" {
+extern StgClosure stg_dummy_ret_closure;
+}
+
 #if !defined(THREADED_RTS)
 #error You must use a patched version of cabal-install which includes - https://github.com/haskell/cabal/pull/7183
 #endif
@@ -389,6 +393,18 @@
     write_blocks((Response *) user, bd);
 }
 
+#define NONMOVING_SEGMENT_BITS 15   // 2^15 = 32kByte
+// Mask to find base of segment
+#define NONMOVING_SEGMENT_MASK ((1 << NONMOVING_SEGMENT_BITS) - 1)
+
+// Get the segment which a closure resides in. Assumes that pointer points into
+// non-moving heap.
+bdescr *nonmovingGetSegmentHead(StgPtr p)
+{
+    const uintptr_t mask = ~NONMOVING_SEGMENT_MASK;
+    return Bdescr((StgPtr)(((uintptr_t) p) & mask));
+}
+
 /* return non-zero on error */
 static int handle_command(Socket& sock, const char *buf, uint32_t cmd_len) {
     trace("handling command of length: %d\n", cmd_len);
@@ -583,6 +599,9 @@
               case STOP_FRAME:
               case CATCH_FRAME:
               case UPDATE_FRAME:
+#ifdef ANN_FRAME
+              case ANN_FRAME:
+#endif
               case RET_SMALL:
               {
                   // Small bitmap
@@ -724,9 +743,18 @@
         trace("CON_DESCR\n");
         StgConInfoTable *ptr_end = (StgConInfoTable *) p.get<uint64_t>();
         trace("CON_DESC2 %p\n", ptr_end);
-        const char * con_desc = GET_CON_DESC(ptr_end - 1);
-        trace("CON_DESC: %p %lu\n", con_desc, strlen(con_desc));
-        write_string(resp, con_desc);
+        // See GHC bug #26745 for why this special case exists.
+        const void *requested_info_ptr = (const void *)ptr_end;
+        const void *dummy_info_ptr = (const void *)stg_dummy_ret_closure.header.info;
+        if (requested_info_ptr == dummy_info_ptr) {
+            trace("CON_DESC: dummy_ret sentinel, overriding descriptor\n");
+            write_string(resp, "RTS:DUMMY_RET");
+        }
+        else {
+          const char * con_desc = GET_CON_DESC(ptr_end - 1);
+          trace("CON_DESC: %p %lu\n", con_desc, strlen(con_desc));
+          write_string(resp, con_desc);
+        }
         resp.finish(RESP_OKAY);
         break;
         }
@@ -801,11 +829,15 @@
 
       case CMD_BLOCK:
         {
-        // TODO: This doesn't work correctly for BF_NONMOVING blocks
-        // For those blocks you need to apply the NONMOVING_SEGMENT_MASK
-        // in order to find the start of the block.
         bdescr *bd = Bdescr ((P_) p.get<uint64_t>());
         trace("BD_ADDR: %p", bd);
+        if (bd->flags & BF_NONMOVING && !(bd->flags & BF_PINNED || bd->flags & BF_LARGE)) {
+          // If our closure lives inside a nonmoving segment, then we will need to find the bdescr
+          // for the head block in the block group.
+          // Pinned and large blocks even if they live in the nonmoving heap do not use segments,
+          // so we should ignore them.
+          bd = nonmovingGetSegmentHead(bd->start);
+        }
         write_block(&resp, bd);
         resp.finish(RESP_OKAY);
         break;
@@ -993,4 +1025,3 @@
     g_savedObjectState.n_objects = i;
     return 0;
 }
-
diff --git a/ghc-debug-stub.cabal b/ghc-debug-stub.cabal
--- a/ghc-debug-stub.cabal
+++ b/ghc-debug-stub.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                ghc-debug-stub
-version:             0.7.0.0
+version:             0.8.0.0
 synopsis:            Functions for instrumenting your application so the heap
                      can be analysed with ghc-debug-common.
 description:         Functions for instrumenting your application so the heap can
@@ -9,11 +9,12 @@
 license:             BSD-3-Clause
 license-file:        LICENSE
 author:              Ben Gamari, Matthew Pickering
-maintainer:          matthewtpickering@gmail.com
+maintainer:          hannes@well-typed.com
 copyright:           (c) 2019-2021 Ben Gamari, Matthew Pickering
 category:            Development
 build-type:          Simple
-extra-source-files:  CHANGELOG.md, cbits/socket.h, cbits/trace.h, cbits/parser.h
+extra-doc-files:     CHANGELOG.md
+extra-source-files:  cbits/socket.h, cbits/trace.h, cbits/parser.h
 
 flag trace
   Description: Enable tracing
@@ -32,7 +33,7 @@
                      , directory ^>= 1.3
                      , filepath >= 1.4 && < 1.6
                      , ghc-prim >= 0.8 && < 0.14
-                     , ghc-debug-convention == 0.7.0.0
+                     , ghc-debug-convention == 0.8.0.0
   default-language:    Haskell2010
   cxx-sources:         cbits/stub.cpp, cbits/socket.cpp, cbits/trace.cpp
   cxx-options:         -std=gnu++11 -pthread -O3 -g3 -DTHREADED_RTS
