COFF: Fix SECREL and SECTION relocations.
authorRui Ueyama <ruiu@google.com>
Wed, 29 Jul 2015 16:30:45 +0000 (16:30 +0000)
committerRui Ueyama <ruiu@google.com>
Wed, 29 Jul 2015 16:30:45 +0000 (16:30 +0000)
SECREL should sets the 32-bit offset of the target from the beginning
of *target's* output section. Previously, the offset from the beginning
of source's output section was used instead.

SECTION means the target section's index, and not the source section's
index. This patch fixes that issue too.

llvm-svn: 243535

lld/COFF/Chunks.cpp
lld/COFF/Chunks.h
lld/COFF/Symbols.h
lld/COFF/Writer.cpp
lld/test/COFF/reloc-x64.test
lld/test/COFF/reloc-x86.test

index f051b68..a68e258 100644 (file)
@@ -50,8 +50,9 @@ static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
 static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
 static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
 
-void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S,
+void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
                                uint64_t P) {
+  uint64_t S = Sym->getRVA();
   switch (Type) {
   case IMAGE_REL_AMD64_ADDR32:   add32(Off, S + Config->ImageBase); break;
   case IMAGE_REL_AMD64_ADDR64:   add64(Off, S + Config->ImageBase); break;
@@ -62,22 +63,23 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S,
   case IMAGE_REL_AMD64_REL32_3:  add32(Off, S - P - 7); break;
   case IMAGE_REL_AMD64_REL32_4:  add32(Off, S - P - 8); break;
   case IMAGE_REL_AMD64_REL32_5:  add32(Off, S - P - 9); break;
-  case IMAGE_REL_AMD64_SECTION:  add16(Off, Out->SectionIndex); break;
-  case IMAGE_REL_AMD64_SECREL:   add32(Off, S - Out->getRVA()); break;
+  case IMAGE_REL_AMD64_SECTION:  add16(Off, Sym->getSectionIndex()); break;
+  case IMAGE_REL_AMD64_SECREL:   add32(Off, Sym->getSecrel()); break;
   default:
     llvm::report_fatal_error("Unsupported relocation type");
   }
 }
 
-void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S,
+void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
                                uint64_t P) {
+  uint64_t S = Sym->getRVA();
   switch (Type) {
   case IMAGE_REL_I386_ABSOLUTE: break;
   case IMAGE_REL_I386_DIR32:    add32(Off, S + Config->ImageBase); break;
   case IMAGE_REL_I386_DIR32NB:  add32(Off, S); break;
   case IMAGE_REL_I386_REL32:    add32(Off, S - P - 4); break;
-  case IMAGE_REL_I386_SECTION:  add16(Off, Out->SectionIndex); break;
-  case IMAGE_REL_I386_SECREL:   add32(Off, S - Out->getRVA()); break;
+  case IMAGE_REL_I386_SECTION:  add16(Off, Sym->getSectionIndex()); break;
+  case IMAGE_REL_I386_SECREL:   add32(Off, Sym->getSecrel()); break;
   default:
     llvm::report_fatal_error("Unsupported relocation type");
   }
@@ -100,8 +102,9 @@ static void applyBranchImm(uint8_t *Off, int32_t V) {
   or16(Off + 2, ((V >> 1) & 0x7ff) | (J2 << 11) | (J1 << 13));
 }
 
-void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, uint64_t S,
+void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
                                uint64_t P) {
+  uint64_t S = Sym->getRVA();
   switch (Type) {
   case IMAGE_REL_ARM_ADDR32:    add32(Off, S + Config->ImageBase); break;
   case IMAGE_REL_ARM_ADDR32NB:  add32(Off, S); break;
@@ -124,17 +127,17 @@ void SectionChunk::writeTo(uint8_t *Buf) {
   for (const coff_relocation &Rel : Relocs) {
     uint8_t *Off = Buf + FileOff + Rel.VirtualAddress;
     SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
-    uint64_t S = cast<Defined>(Body)->getRVA();
+    Defined *Sym = cast<Defined>(Body);
     uint64_t P = RVA + Rel.VirtualAddress;
     switch (Config->Machine) {
     case AMD64:
-      applyRelX64(Off, Rel.Type, S, P);
+      applyRelX64(Off, Rel.Type, Sym, P);
       break;
     case I386:
-      applyRelX86(Off, Rel.Type, S, P);
+      applyRelX86(Off, Rel.Type, Sym, P);
       break;
     case ARMNT:
-      applyRelARM(Off, Rel.Type, S, P);
+      applyRelARM(Off, Rel.Type, Sym, P);
       break;
     default:
       llvm_unreachable("unknown machine type");
index c360be9..3587830 100644 (file)
@@ -137,9 +137,9 @@ public:
   StringRef getSectionName() const override { return SectionName; }
   void getBaserels(std::vector<Baserel> *Res) override;
   bool isCOMDAT() const;
-  void applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
-  void applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
-  void applyRelARM(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
+  void applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P);
+  void applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P);
+  void applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P);
 
   // Called if the garbage collector decides to not include this chunk
   // in a final output. It's supposed to print out a log message to stdout.
index 3971889..eae1bfa 100644 (file)
@@ -130,6 +130,14 @@ public:
   // Returns the file offset of this symbol in the final executable.
   // The writer uses this information to apply relocations.
   uint64_t getFileOff();
+
+  // Returns the RVA relative to the beginning of the output section.
+  // Used to implement SECREL relocation type.
+  uint64_t getSecrel();
+
+  // Returns the output section index.
+  // Used to implement SECTION relocation type.
+  uint64_t getSectionIndex();
 };
 
 // Symbols defined via a COFF object file.
index 506adf6..62ac95c 100644 (file)
@@ -678,5 +678,17 @@ void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V) {
   Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
 }
 
+uint64_t Defined::getSecrel() {
+  if (auto *D = dyn_cast<DefinedRegular>(this))
+    return getRVA() - D->getChunk()->getOutputSection()->getRVA();
+  llvm::report_fatal_error("SECREL relocation points to a non-regular symbol");
+}
+
+uint64_t Defined::getSectionIndex() {
+  if (auto *D = dyn_cast<DefinedRegular>(this))
+    return D->getChunk()->getOutputSection()->SectionIndex;
+  llvm::report_fatal_error("SECTION relocation points to a non-regular symbol");
+}
+
 } // namespace coff
 } // namespace lld
index 624241b..96f0bf8 100644 (file)
@@ -3,16 +3,17 @@
 # RUN: llvm-objdump -d %t.exe | FileCheck %s
 
 # CHECK: .text:
-# CHECK: 1000: a1 00 10 00 40 00 00 00 00
-# CHECK: 1009: a1 00 10 00 40 01 00 00 00
-# CHECK: 1012: a1 00 10 00 00 00 00 00 00
-# CHECK: 101b: a1 e0 ff ff ff 00 00 00 00
-# CHECK: 1024: a1 d6 ff ff ff 00 00 00 00
-# CHECK: 102d: a1 cc ff ff ff 00 00 00 00
-# CHECK: 1036: a1 c2 ff ff ff 00 00 00 00
-# CHECK: 103f: a1 b8 ff ff ff 00 00 00 00
-# CHECK: 1048: a1 ae ff ff ff 00 00 00 00
-# CHECK: 1051: a1 01 00 00 00 00 00 00 00
+# CHECK: 1000: a1 03 20 00 40 00 00 00 00
+# CHECK: 1009: a1 03 20 00 40 01 00 00 00
+# CHECK: 1012: a1 03 20 00 00 00 00 00 00
+# CHECK: 101b: a1 e3 0f 00 00 00 00 00 00
+# CHECK: 1024: a1 d9 0f 00 00 00 00 00 00
+# CHECK: 102d: a1 cf 0f 00 00 00 00 00 00
+# CHECK: 1036: a1 c5 0f 00 00 00 00 00 00
+# CHECK: 103f: a1 bb 0f 00 00 00 00 00 00
+# CHECK: 1048: a1 b1 0f 00 00 00 00 00 00
+# CHECK: 1051: a1 02 00 00 00 00 00 00 00
+# CHECK: 105a: a1 03 00 00 00 00 00 00 00
 
 ---
 header:
@@ -22,41 +23,45 @@ sections:
   - Name:            .text
     Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
     Alignment:       4096
-    SectionData:     A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000
+    SectionData:     A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000
     Relocations:
       - VirtualAddress:  1
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_ADDR32
       - VirtualAddress:  10
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_ADDR64
       - VirtualAddress:  19
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_ADDR32NB
       - VirtualAddress:  28
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_REL32
       - VirtualAddress:  37
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_REL32_1
       - VirtualAddress:  46
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_REL32_2
       - VirtualAddress:  55
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_REL32_3
       - VirtualAddress:  64
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_REL32_4
       - VirtualAddress:  73
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_REL32_5
       - VirtualAddress:  82
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_SECTION
       - VirtualAddress:  91
-        SymbolName:      main
+        SymbolName:      foo
         Type:            IMAGE_REL_AMD64_SECREL
+  - Name:            .zzz
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4096
+    SectionData:     0000000000000000
 symbols:
   - Name:            .text
     Value:           0
@@ -70,10 +75,28 @@ symbols:
       NumberOfLinenumbers: 0
       CheckSum:        0
       Number:          0
+  - Name:            .zzz
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          8
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
   - Name:            main
     Value:           0
     SectionNumber:   1
     SimpleType:      IMAGE_SYM_TYPE_NULL
     ComplexType:     IMAGE_SYM_DTYPE_NULL
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            foo
+    Value:           3
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
 ...
index b26b4c6..001ce6d 100644 (file)
@@ -3,12 +3,12 @@
 # RUN: llvm-objdump -d %t.exe | FileCheck %s
 
 # CHECK: .text:
-# CHECK:     1000:       a1 00 00 00 00
-# CHECK:     1005:       a1 00 10 40 00
-# CHECK:     100a:       a1 00 10 00 00
-# CHECK:     100f:       a1 ec ff ff ff
-# CHECK:     1014:       a1 00 00 01 00
-# CHECK:     1019:       a1 00 00 00 00
+# CHECK: 1000: a1 00 00 00 00
+# CHECK: 1005: a1 03 20 40 00
+# CHECK: 100a: a1 03 20 00 00
+# CHECK: 100f: a1 ef 0f 00 00
+# CHECK: 1014: a1 00 00 02 00
+# CHECK: 1019: a1 03 00 00 00
 
 ---
 header:
@@ -21,23 +21,27 @@ sections:
     SectionData:     A100000000A100000000A100000000A100000000A100000000A100000000
     Relocations:
       - VirtualAddress:  1
-        SymbolName:      _main
+        SymbolName:      _foo
         Type:            IMAGE_REL_I386_ABSOLUTE
       - VirtualAddress:  6
-        SymbolName:      _main
+        SymbolName:      _foo
         Type:            IMAGE_REL_I386_DIR32
       - VirtualAddress:  11
-        SymbolName:      _main
+        SymbolName:      _foo
         Type:            IMAGE_REL_I386_DIR32NB
       - VirtualAddress:  16
-        SymbolName:      _main
+        SymbolName:      _foo
         Type:            IMAGE_REL_I386_REL32
       - VirtualAddress:  23
-        SymbolName:      _main
+        SymbolName:      _foo
         Type:            IMAGE_REL_I386_SECTION
       - VirtualAddress:  26
-        SymbolName:      _main
+        SymbolName:      _foo
         Type:            IMAGE_REL_I386_SECREL
+  - Name:            .zzz
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4096
+    SectionData:     0000000000000000
 symbols:
   - Name:            .text
     Value:           0
@@ -51,10 +55,28 @@ symbols:
       NumberOfLinenumbers: 0
       CheckSum:        0
       Number:          0
+  - Name:            .zzz
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          8
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
   - Name:            _main
     Value:           0
     SectionNumber:   1
     SimpleType:      IMAGE_SYM_TYPE_NULL
     ComplexType:     IMAGE_SYM_DTYPE_NULL
     StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            _foo
+    Value:           3
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
 ...