[lld] r301287 - Add comments about Widnows .reloc section.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 20:31:10 PDT 2017


Author: ruiu
Date: Mon Apr 24 22:31:10 2017
New Revision: 301287

URL: http://llvm.org/viewvc/llvm-project?rev=301287&view=rev
Log:
Add comments about Widnows .reloc section.

Modified:
    lld/trunk/COFF/Chunks.cpp

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=301287&r1=301286&r2=301287&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Mon Apr 24 22:31:10 2017
@@ -319,8 +319,48 @@ void SEHTableChunk::writeTo(uint8_t *Buf
   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 <actual
+// base address> - <desired base address> 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.




More information about the llvm-commits mailing list