diff --git a/clib/s/cl_stub b/clib/s/cl_stub
index 337d214af771e8bcc1d43eba6ab1d25f2af766ae..c8c74cd9e39f908b6e06f78bb2035a5042cc01d9 100644
--- a/clib/s/cl_stub
+++ b/clib/s/cl_stub
@@ -36,9 +36,8 @@ SharedLibrary      SETL  {TRUE}
 
         AREA    |Stub$$Code|, CODE, READONLY
 
-      [ Code_Destination = "RAM"
         IMPORT  |__RelocCode|, WEAK
-      |
+      [ Code_Destination <> "RAM"
         IMPORT  |_Shared_Lib_Module_SWI_Code|
 
         ; These in the RAM version are provided by the entry inclusions
@@ -153,9 +152,13 @@ OS_Module EQU &1e
         ; so initialise always acquires it.  Is this reasonable?
         STMFD   sp!, {r14}
         MOV     r9, r0                  ; save 'copy statics' flag
-      [ Code_Destination = "RAM"
-        BL      |__RelocCode|
-      ]
+;      [ Code_Destination = "RAM"
+        LDR     r0, =|__RelocCode|      ; if __RelocCode is present, call it and
+        TEQ     r0, #0                  ; note the address of the relocation table
+        MOVEQ   r0, #-1                 ; in r8, else just set r8 to -1
+        BLNE    __RelocCode
+        MOV     r8, r0
+;      ]
         MOV     r4, #0
         MOV     r5, #-1
         CMP     r9, #0
@@ -185,17 +188,42 @@ OS_Module EQU &1e
         MOV     r6, r6, ASR #10
         MOVS    r6, r6, ASL #16
       [ Code_Destination = "RAM"
+        STMFD   sp!, {r8}
         SWI     X:OR:Lib_Init + 2
+        LDMFD   sp!, {r8}               ; KJB - why preserve here???
       |
         ; For ROM BL to the SWI code directly (yuck!)
-        STMFD   r13!,{r11,r12}
+        STMFD   r13!,{r8,r11,r12}
         MOV     r11,#2          ; SWI offset
         MOV     r12,#-3         ; A number liable to address exception if used
         BL      |_Shared_Lib_Module_SWI_Code|
-        LDMFD   r13!,{r11,r12}
+        LDMFD   r13!,{r8,r11,r12}
       ]
         BVS     %F99
 
+; [ Code_Destination = "RAM"
+        ; Chunk of code to relocate all the pointers in the data area
+        STMFD   sp!, {r1-r5}
+        LDR     r1, [r12]
+        CMP     r1, #12
+        BEQ     %F80
+        CMP     r8, #0
+        BMI     %F80
+        LDR     r1, =|Image$$RO$$Base|  ; r1 = pointer to code
+        LDR     r2, =|Image$$RW$$Base|  ; r2 = pointer to data template in module code area
+        ADD     r3, r12, #fixedwssize   ; r3 = pointer to our real data area (XXXX what if r0 was 0 on entry?? XXXX)
+        SUB     r3, r3, r2              ; r3 = offset from data template to real data
+        ADD     r1, r1, r3              ; r1 = code + data offset (odd, but saves work below)
+70      LDR     r4, [r8], #4            ; get a word from the relocation table
+        MOVS    r4, r4, ASR #2
+        BMI     %F80                    ; if top bit set, it's the end of the table
+        BCC     %B70                    ; if bit 1 not set, it's not a data relocation
+        LDR     r5, [r1, r4, LSL #2]    ; read in the word to be relocated from the data area
+        ADD     r5, r5, r3              ; add the magic offset
+        STR     r5, [r1, r4, LSL #2]    ; and put it back
+        B       %B70
+80      LDMFD   sp!, {r1-r5}
+
  [ Code_Destination = "RAM"
         MOV     r6, r6, ASL #16
         CMP     r6, #LibraryVersionNumber :SHL: 16
@@ -314,7 +342,7 @@ GetRoundObjAsm SETS ""
 $GetRoundObjAsm
 |_rlib_entries_end|
 
-        AREA    |Stub$$Data|, DATA
+        AREA    |Stub$$Data|, DATA, NOINIT
 
 |_k_data_start|
         GET     kernel.s.k_data