home *** CD-ROM | disk | FTP | other *** search
- /* Unexec for the Archimedes.
- *
- * This routine saves a "snapshot" of the running program, in a form
- * suitable for later running as a RISC OS application. The whole of the
- * executing image is saved, but NOT the heap or the stack, so that pointers
- * to heap allocated space, or automatic variables, will be garbage when the
- * process is restarted.
- */
-
- #include <assert.h>
- #include <stdio.h>
- #include "kernel.h"
- #include "unexec.h"
-
- /* This lot are really addresses (void *), but we call them unsigned
- * integers here (unlike in the "utils.h" header file), as that is how
- * we will be using them. nasty, but it saves a lot of casts...
- */
-
- extern unsigned int _RO_Base;
- extern unsigned int _RO_Limit;
- extern unsigned int _RW_Base;
- extern unsigned int _RW_Limit;
- extern unsigned int _ZI_Base;
- extern unsigned int _ZI_Limit;
-
- extern unsigned int _Stub_Entries_Base;
- extern unsigned int _Stub_Entries_Limit;
- extern unsigned int _Stub_Data_Base;
- extern unsigned int _Stub_Data_Limit;
-
- void unexec (char *file)
- {
- int fd;
- int offset;
- int length;
- _kernel_osfile_block blk;
-
- /* Make sure the necessary assumptions are valid! */
- assert(_RO_Limit == _RW_Base);
- assert(_ZI_Base == _ZI_Limit);
- assert(_RO_Base <= _RW_Limit);
- assert(_RO_Base == 0x8080);
-
- blk.load = 0xFF8;
- blk.exec = 0;
- blk.start = 0x8000;
- blk.end = _RW_Limit;
- _kernel_osfile(10,file,&blk);
-
- /* *******************************************************
- * The following code is HIGHLY dependent on the exact
- * format of the shared C library stubs! It is probably
- * not necessary, either! If in doubt, comment it out!
- * Based on Shared C Library stubs 3.50 (supplied with
- * Acorn C v3.0).
- * It has been visually verified with stubs 3.75 (the
- * version supplied with Desktop C v4.0), and appears
- * to be OK with this, too.
- * *******************************************************/
-
- /* Now open the dumped image to zap the C Library stubs data */
- fd = _kernel_osfind(0xC7,file);
-
- /* If we can't open it for update, leave it as it is */
- if (fd == 0)
- return;
-
- /* Set Stub$$Entries to 0xE3A0F000 (repeated) */
- offset = _Stub_Entries_Base - 0x8000;
- length = (_Stub_Entries_Limit - _Stub_Entries_Base);
-
- /* Must be an exact number of words */
- assert((length & 0x03) == 0);
-
- /* Go to the area start (give up if we cannot) */
- if (_kernel_osargs(1,fd,offset) == _kernel_ERROR)
- goto quit;
-
- while (length > 0)
- {
- _kernel_osbput(0x00,fd);
- --length;
- _kernel_osbput(0xF0,fd);
- --length;
- _kernel_osbput(0xA0,fd);
- --length;
- _kernel_osbput(0xE3,fd);
- --length;
- }
-
- /* Zero out Stub$$Data */
- offset = _Stub_Data_Base - 0x8000;
- length = (_Stub_Data_Limit - _Stub_Data_Base);
-
- /* Go to the area start (give up if we cannot) */
- if (_kernel_osargs(1,fd,offset) == _kernel_ERROR)
- goto quit;
-
- while (length > 0)
- {
- _kernel_osbput(0,fd);
- --length;
- }
-
- /* We are done. Close the file */
- quit:
- _kernel_osfind(0,(char *)fd);
- }
-