Hi everyone,
I'm trying to check the the forth dictionary is being loaded correctly on Sparc64, and I'm struggling to understand the dynamic relocation code from kernel/dict.c:
==== cut ====
dicthead = target_long(header->length);
memcpy(dict, data, dicthead); reloc_table=(ucell *)(data+dicthead);
#ifdef CONFIG_DEBUG_DICTIONARY printk("\nmoving dictionary (%x bytes) to %x\n", (ucell)dicthead, (ucell)dict); printk("\ndynamic relocation..."); #endif
for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead); walk++) { int pos, bit, l; l=(walk-(ucell *)dict); pos=l/BITS; bit=l&~(-BITS); if (reloc_table[pos]&target_ucell(1UL<<bit)) { // printk("%lx, pos %x, bit %d\n",*walk, pos, bit); write_ucell(walk, read_ucell(walk)+pointer2cell(dict)); } }
#ifdef CONFIG_DEBUG_DICTIONARY printk(" done.\n"); #endif
==== cut ====
Stepping through with the debugger, l appears to be a count of the number of words from the beginning of the dictionary, pos is set to either 0 or 1 depending upon whether the word offset is a multiple of the target word size and bit is a modulo of l, again based upon the word size.
It looks as if bit is being used to set up a shifting bit mask up to the word size in bits, and it is based upon the interaction of this and reloc_table[pos] which decides whether any code is moved.
Can anyone shed any light on exactly what this code does, and how it actually does it? The part that confuses me the most is that decisions are being made on which words to relocate, but these criteria are based upon some strange combination of arithmetic involving the current offset and the target word size.
Many thanks,
Mark.
Mark Cave-Ayland wrote:
Stepping through with the debugger, l appears to be a count of the number of words from the beginning of the dictionary, pos is set to either 0 or 1 depending upon whether the word offset is a multiple of the target word size and bit is a modulo of l, again based upon the word size.
It looks as if bit is being used to set up a shifting bit mask up to the word size in bits, and it is based upon the interaction of this and reloc_table[pos] which decides whether any code is moved.
Can anyone shed any light on exactly what this code does, and how it actually does it? The part that confuses me the most is that decisions are being made on which words to relocate, but these criteria are based upon some strange combination of arithmetic involving the current offset and the target word size.
A dictionary is basically a linked list between forth words. When the dictionary is created, it lives at some virtual address in userspace, but that address might not be the one where it is finally executed. This would lead to all the pointers pointing to nirvana. Now, we solved this by making the dictionary relocatable. For that we needed to find out which words in the dictionary are data, and which are pointers. Therefore we compile the dictionary twice and compare the dictionary words for differences between the two dictionaries. If they're different, it's a pointer and thus needs to be relocated. The relocation table is a bit mask with one bit per dictionary word, noting whether a relocation is required upon dictionary loading or not. Now, if it is, the base address of the dictionary is added to the value so the pointer becomes valid again.
Stefan
Stefan Reinauer wrote:
A dictionary is basically a linked list between forth words. When the dictionary is created, it lives at some virtual address in userspace, but that address might not be the one where it is finally executed. This would lead to all the pointers pointing to nirvana. Now, we solved this by making the dictionary relocatable. For that we needed to find out which words in the dictionary are data, and which are pointers. Therefore we compile the dictionary twice and compare the dictionary words for differences between the two dictionaries. If they're different, it's a pointer and thus needs to be relocated. The relocation table is a bit mask with one bit per dictionary word, noting whether a relocation is required upon dictionary loading or not. Now, if it is, the base address of the dictionary is added to the value so the pointer becomes valid again.
Stefan
Hi Stefan,
Wow. Thanks for this. I found a small reference to the linked-list directory format on the FUtils page, although it's not easy to find. Am I right in thinking from the code that the relocation table is appended at the end of the dictionary in the image file?
Many thanks,
Mark.
On 22.01.2009 14:40 Uhr, Mark Cave-Ayland wrote:
Hi Stefan,
Wow. Thanks for this. I found a small reference to the linked-list directory format on the FUtils page, although it's not easy to find. Am I right in thinking from the code that the relocation table is appended at the end of the dictionary in the image file?
This is correct.