To apply a fixup, a delta is calculated as the difference between the
preferred base address, and the base where the image is actually
loaded.
The basic idea is that when doing a fixup at some address, we must know
- what memory must be changed ("offset" field)
- what value is needed for its relocation ("delta" value)
- which parts of relocated data and delta value to use ("type" field)
Here are some possible values of the "type" field
HIGH
- add higher word (16 bits) of delta to the 16-bit value at "offset"
LOW
- add lower word of delta to the value at "offset"
HIGHLOW
- add full delta to the 32-bit value at "offset"
In other words, HIGHLOW
type tells the program that it's doing a fix-up on offset "offset" from the page of this relocation block*, and that there is a doubleword that needs to be modified in order to have properly working executable.
* all of the relocation entries are grouped into blocks, and every block has a page on which its entries are applied
Let's say that you have this instruction in your code:
section .data
message: "Hello World!", 0
section .code
...
mov eax, message
...
You run assembler and immediately after it you run disassembler. Now your code looks like this:
mov eax, dword [0x702000]
You're now curious why is it 0x700000
, and when you look into file dump, you see that
ImageBase: 0x00700000
Now you understand where did this number come from and you'e ready to run the executable.
Loader which loads executable files into memory and creates address space for them finds out, that memory 0x700000
is unavailable and it needs to place that file somewhere else. It decides that 0xf00000
will be OK and copies the file contents there.
But, your program was linked to work only with data on 0x700000
and there was no way for linker to know that its output would be relocated. Because of this, loader must do its magic. It
- calculates delta value - the old address (image base) is
0x700000
but it wants 0xf00000
(preferred address). It subtracts one from another and gets 0x800000
as result.
- gets to the
.reloc
section of the file
- checks if there is still another page (4KB of data) to be relocated. If no, it continues toward calling file“s entry point.
4.for every relocation for the current page, it
- gets data at relocation offset
- adds the delta value (in the way as type field states)
- places the new value at relocation offset
- continues on step 3
There are also more types of relocation entry and some of them are architecture-specific. To see a full list, read the "Microsoft Portable Executable and Common Object File Format, section 6.6.2. Fixup Types".