herkforth's bootstrapping process
This page describes the herkforth rebuilds itself. The word to do this
is called bootstrap
(so you can see the source by typing bootstrapD
General
Herkforth creates an image of a new ELF file in memory at here
, using
w,
and allot
. No binary code is preserved. This image is then written
out to a new file, and copied back down to the initial load address and
executed there.
Details
- Align on a 32 byte boundary. (So when subsequent pieces are aligned, they will still be aligned then the whole thing is moved down to the load address.)
- Append elf header, saving the addresses where various fields need to be filled in later (the entry point, and the size of the file)
- Append the source blocks. As the source is copied, mark which dictionary entries are used (in a separate array.)
- Padding (make room for more source blocks to be added.)
- Next the dictionary is copied in. The following modifications are made as it is copied:
- 1) If the entry was not used by a source token (as marked above) then that dictionary entry is replaced by null bytes.
- 2) If the entry is a normal word (eg not a variable) then the CFA field is set to zero.
- 3) If the entry is a variable, then the CFA field is updated so it will still point to the variable_value field.
- Padding (so the dictionary can expand)
- Now data objects are copied. To accomplish this, loop through the new dictionary, and for entries with the flags set to indicate a data word, copy the data object pointed to by the CFA, and update the CFA.
- Note: there is no padding after the data, because data objects are added on the heap. (And are copied all to the same place as described above when you bootstrap.)
- Kernel words compiled.
- The CFAs for the kernel words are copied and translated into the new dictionary.
- initialization routine is compiled in (a word called _start). This sets up the registers to point to the source blocks, dictionary, stacks etc, and then finishes by telling the kernel to load block 0.
- That's it for appending stuff.
- Fix up the headers in the elf file (entry point, and file size).
- Write out ELF to a new file
- Now to copy the whole mess back to the initial load address ($10000000 on linux) and execute it. But this isn't as easy as it sounds, because doing so will overwrite the memory copy routine, etc.. So:
- 1) compile code (which does not call any existing code) to move the new image to the load address,
- 2) to flush the caches
- 3) branch to the new entry point
- run it.