From 1a7f6afe7d8121b737ec76cda8fc6d52705a2b81 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Tue, 25 Apr 2017 03:31:10 +0000 Subject: [PATCH] Add comments about Widnows .reloc section. llvm-svn: 301287 --- lld/COFF/Chunks.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 10eeedd..2e49f41 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -319,8 +319,48 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const { std::sort(Begin, Begin + Cnt); } -// Windows-specific. -// This class represents a block in .reloc section. +// Windows-specific. This class represents a block in .reloc section. +// The format is described here. +// +// On Windows, each DLL is linked against a fixed base address and +// usually loaded to that address. However, if there's already another +// DLL that overlaps, the loader has to relocate it. To do that, DLLs +// contain .reloc sections which contain offsets that need to be fixed +// up at runtime. If the loader find that a DLL cannot be loaded to its +// desired base address, it loads it to somewhere else, and add - to each offset that is +// specified by .reloc section. +// +// In ELF terms, .reloc sections contain arrays of relocation offsets. +// All these offsets in the section are implicitly R_*_RELATIVE, and +// addends are read from section contents (so it is REL as opposed to +// RELA). +// +// This already reduce the size of relocations to 1/3 compared to ELF +// .dynrel, but Windows does more to reduce it (probably because it was +// invented for PCs in the late '80s or early '90s.) Offsets in .reloc +// are grouped by page where page size is 16 bits, and offsets sharing +// the same page address are stored consecutively to represent them with +// less space. This is a very similar to the page table which is grouped +// by (multiple stages of) pages. +// +// For example, let's say we have 0x00030, 0x00500, 0x01000, 0x01100, +// 0x20004, and 0x20008 in a .reloc section. In the section, they are +// represented like this: +// +// 0x00000 -- page address (4 bytes) +// 16 -- size of this block (4 bytes) +// 0x0030 -- entries (2 bytes each) +// 0x0500 +// 0x1000 +// 0x1100 +// 0x20000 -- page address (4 bytes) +// 12 -- size of this block (4 bytes) +// 0x0004 -- entries (2 bytes each) +// 0x0008 +// +// Usually we have a lot of relocatinos for each page, so the number of +// bytes for one .reloc entry is close to 2 bytes. BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) { // Block header consists of 4 byte page RVA and 4 byte block size. // Each entry is 2 byte. Last entry may be padding. -- 2.7.4