In computer programming, a self-relocating program is a program that relocates its own address-dependent instructions and data when run, and is therefore capable of being loaded into memory at any address. In many cases, self-relocating code is also a form of self-modifying code.
Overview
Self-relocation is similar to the relocation process employed by the linker-loader when a program is copied from external storage into main memory; the difference is that it is the loaded program itself rather than the loader in the operating system or shell that performs the relocation. One form of self-relocation occurs when a program copies the code of its instructions from one sequence of locations to another sequence of locations within the main memory of a single computer, and then transfers processor control from the instructions found at the source locations of memory to the instructions found at the destination locations of memory. As such, the data operated upon by the algorithm of the program is the sequence of bytes which define the program. Self-relocation typically happens at load-time, sometimes also when changing the program's configuration at a later stage during runtime.
Examples
Boot loaders
As an example, self-relocation is often employed in the early stages of bootstrapping operating systems on architectures like IBM PC compatibles, where lower-level chain boot loaders, Volume Boot Record move themselves out of place in order to load the next stage into memory.
Under DOS, self-relocation is sometimes also used by more advanced drivers and RSXs/TSRs loading themselves "high" into upper memory more effectively than possible for externally provided "high"-loaders in order to maximize the memory available for applications. This is down to the fact that the operating system has no knowledge of the inner workings of a driver to be loaded and thus has to load it into a free memory area large enough to hold the whole driver as a block including its initialization code, even if that would be freed after the initialization. For TSRs, the operating system also has to allocate a Program Segment Prefix and an environment segment. This might cause the driver not to be loaded into the most suitable free memory area or even prevent it from being loaded high at all. In contrast to this, a self-relocating driver can be loaded anywhere and then relocate only its resident portion into a suitable free memory area in upper memory. In addition, advanced self-relocating TSRs can relocate over most of their own PSP segment and command line buffer and free their environment segment in order to further reduce the resulting memory footprint and avoid fragmentation. Some self-relocating TSRs can also dynamically change their "nature" and morph into device drivers even if originally loaded as TSRs, thereby typically also freeing some memory. Finally, it is technically impossible for an external loader to relocate drivers into expanded memory, the high memory area or extended memory, because these methods require small driver-specific stubs to remain in conventional or upper memory in order to coordinate the access to the relocation target area, and in the case of device drivers also because the driver's header must always remain in the first megabyte. In order to achieve this, the drivers must be specially designed to support self-relocation into these areas. Some advanced DOS drivers also contain both a device driver and TSR sharing a common code portion internally as fat binary. If the shared code is not designed to be position-independent, it requires some form of internal address fix-up similar to what would otherwise have been carried out by a relocating loader already; this is similar to the fix-up stage of self-relocation but with the code already being loaded at the target location by the operating system's loader.
did not have the ability to relocate programs during loading. Sometimes multiple versions of a program were maintained, each built for a different load address. A special class of programs, called self-relocating programs, were coded to relocate themselves after loading. IBM OS/360 relocated executable programs when they were loaded into memory. Only one copy of the program was required, but once loaded the program could not be moved.
Other examples
As an extreme example of self-relocation it is possible to construct a computer program so that it does not stay at a fixed address in memory, even as it executes. The Apple Worm is a dynamic self-relocator.