unwind: export and use symbolic names in assembler

While here, expand some documentation
diff --git a/sdk/include/unwind-assembly.h b/sdk/include/unwind-assembly.h
new file mode 100644
index 0000000..377d97f
--- /dev/null
+++ b/sdk/include/unwind-assembly.h
@@ -0,0 +1,12 @@
+// Copyright CHERIoT Contributors.
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include <assembly-helpers.h>
+#include <setjmp-assembly.h>
+
+#define INVOCATION_LOCAL_UNWIND_LIST_OFFSET 8
+
+EXPORT_ASSEMBLY_OFFSET(CleanupList, next, 0)
+EXPORT_ASSEMBLY_OFFSET(CleanupList, env, 8)
diff --git a/sdk/include/unwind.h b/sdk/include/unwind.h
index 3f55c81..ce6a25a 100644
--- a/sdk/include/unwind.h
+++ b/sdk/include/unwind.h
@@ -14,6 +14,8 @@
 	struct __jmp_buf env;
 };
 
+#include <unwind-assembly.h>
+
 /**
  * Head of the cleanup list.
  *
@@ -25,7 +27,8 @@
 {
 	void     *csp = __builtin_cheri_stack_get();
 	ptraddr_t top = __builtin_cheri_top_get(csp);
-	csp           = __builtin_cheri_address_set(csp, top - 8);
+	csp           = __builtin_cheri_address_set(
+	            csp, top - INVOCATION_LOCAL_UNWIND_LIST_OFFSET);
 	return (struct CleanupList **)csp;
 }
 
diff --git a/sdk/lib/unwind_error_handler/unwind.S b/sdk/lib/unwind_error_handler/unwind.S
index 6e56a98..6c74c06 100644
--- a/sdk/lib/unwind_error_handler/unwind.S
+++ b/sdk/lib/unwind_error_handler/unwind.S
@@ -1,16 +1,29 @@
+#include <unwind-assembly.h>
+
+/**
+ * A direct re-implementation of unwind.h's cleanup_unwind() as a stackless
+ * error handler.
+ *
+ * If there is no registered CleanupList structure (equivalently, there's no
+ * CHERIOT_DURING block active at the time of the fault), then this requests
+ * unwnding out of the compartment.  Otherwise, we will longjmp() out to the
+ * indicated handler (that is, the CHERIOT_HANDLER block associated with the
+ * current CHERIOT_DURING block), having reset the compartment error handler
+ * invocation counter to zero.
+ */
 .section .compartment_error_handler_stackless,"aw",@progbits
 .globl compartment_error_handler_stackless
 .p2align 2
 .type compartment_error_handler_stackless,@function
 compartment_error_handler_stackless:
-// Get the head of the error list.
+// Get the head of the error list (see cleanup_list_head)
 	cgettop      t0, csp
 	csetaddr     csp, csp, t0
-	clc          cs0, -8(csp)
+	clc          cs0, -INVOCATION_LOCAL_UNWIND_LIST_OFFSET(csp)
 	beqz         s0, .Lforce_unwind
-// Pop the top error from the list. */
-	clc          ct0, 0(cs0)
-	csc          ct0, -8(csp)
+// Pop the top error from the list
+	clc          ct0, CleanupList_offset_next(cs0)
+	csc          ct0, -INVOCATION_LOCAL_UNWIND_LIST_OFFSET(csp)
 // Mark this error handler as having finished.  We may still trap again
 // and reenter this, but now that we've popped the top element from the
 // stack we will run some different cleanup code next time. */
@@ -19,11 +32,12 @@
 	clc             ct2, %cheriot_compartment_lo_i(.Llookup_reset)(ct2)
 	cjalr           ct2
 // longjmp to the error handler.
-	clc          cs1, 16(cs0)
-	clc          csp, 24(cs0)
-	clc          cra, 32(cs0)
-	clc          cs0, 8(cs0)
+	clc          cs1, (CleanupList_offset_env + __jmp_buf_offset___cs1)(cs0)
+	clc          csp, (CleanupList_offset_env + __jmp_buf_offset___csp)(cs0)
+	clc          cra, (CleanupList_offset_env + __jmp_buf_offset___cra)(cs0)
+	clc          cs0, (CleanupList_offset_env + __jmp_buf_offset___cs0)(cs0)
 	cjr          cra
+
 .Lforce_unwind:
 	li           a0, 1
 	cret