Search code examples
c++windowsassemblyx86dumpbin

What's the meaning of HIGHLOW in a disassembled binary file?


I just used DUMPBIN for the first time and I see the term HIGHLOW repeatedly in the output file:

BASE RELOCATIONS #7
   11000 RVA,       E0 SizeOfBlock
    ...
         3B5  HIGHLOW            2001753D  ___onexitbegin
         3C1  HIGHLOW            2001753D  ___onexitbegin
    ...

I'm curious what this term stands for. I didn't find anything on Google or Stackoverflow about it.


Solution

  • 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

    1. what memory must be changed ("offset" field)
    2. what value is needed for its relocation ("delta" value)
    3. 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

    1. 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.
    2. gets to the .reloc section of the file
    3. 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
    4. gets data at relocation offset
    5. adds the delta value (in the way as type field states)
    6. places the new value at relocation offset
    7. 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".