[lld] r241657 - COFF: Support x86 file header and relocations.

Rui Ueyama ruiu at google.com
Tue Jul 7 18:45:29 PDT 2015


Author: ruiu
Date: Tue Jul  7 20:45:29 2015
New Revision: 241657

URL: http://llvm.org/viewvc/llvm-project?rev=241657&view=rev
Log:
COFF: Support x86 file header and relocations.

Added:
    lld/trunk/test/COFF/reloc-x86.test
Modified:
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/Writer.cpp
    lld/trunk/COFF/Writer.h

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=241657&r1=241656&r2=241657&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Tue Jul  7 20:45:29 2015
@@ -67,6 +67,20 @@ void SectionChunk::applyRelX64(uint8_t *
   }
 }
 
+void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S,
+                               uint64_t P) {
+  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->getSectionIndex() + 1); break;
+  case IMAGE_REL_I386_SECREL:   add32(Off, S - Out->getRVA()); break;
+  default:
+    llvm::report_fatal_error("Unsupported relocation type");
+  }
+}
+
 void SectionChunk::writeTo(uint8_t *Buf) {
   if (!hasData())
     return;
@@ -80,7 +94,16 @@ void SectionChunk::writeTo(uint8_t *Buf)
     SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
     uint64_t S = cast<Defined>(Body)->getRVA();
     uint64_t P = RVA + Rel.VirtualAddress;
-    applyRelX64(Off, Rel.Type, S, P);
+    switch (Config->MachineType) {
+    case IMAGE_FILE_MACHINE_AMD64:
+      applyRelX64(Off, Rel.Type, S, P);
+      break;
+    case IMAGE_FILE_MACHINE_I386:
+      applyRelX86(Off, Rel.Type, S, P);
+      break;
+    default:
+      llvm_unreachable("unknown machine type");
+    }
   }
 }
 

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=241657&r1=241656&r2=241657&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Tue Jul  7 20:45:29 2015
@@ -137,6 +137,7 @@ public:
   void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) 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);
 
   // 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.

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=241657&r1=241656&r2=241657&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Tue Jul  7 20:45:29 2015
@@ -52,7 +52,11 @@ std::error_code Writer::write(StringRef
   removeEmptySections();
   if (auto EC = openFile(OutputPath))
     return EC;
-  writeHeader();
+  if (Is64) {
+    writeHeader<pe32plus_header>();
+  } else {
+    writeHeader<pe32_header>();
+  }
   writeSections();
   sortExceptionTable();
   return Buffer->commit();
@@ -105,6 +109,9 @@ void OutputSection::writeHeaderTo(uint8_
   }
 }
 
+Writer::Writer(SymbolTable *T)
+    : Symtab(T), Is64(Config->MachineType == IMAGE_FILE_MACHINE_AMD64) {}
+
 // Set live bit on for each reachable chunk. Unmarked (unreachable)
 // COMDAT chunks will be ignored in the next step, so that they don't
 // come to the final output file.
@@ -278,11 +285,11 @@ void Writer::removeEmptySections() {
 // Visits all sections to assign incremental, non-overlapping RVAs and
 // file offsets.
 void Writer::assignAddresses() {
-  SizeOfHeaders = RoundUpToAlignment(
-      DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
-      sizeof(pe32plus_header) +
-      sizeof(data_directory) * NumberfOfDataDirectory +
-      sizeof(coff_section) * OutputSections.size(), PageSize);
+  SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
+                  sizeof(data_directory) * NumberfOfDataDirectory +
+                  sizeof(coff_section) * OutputSections.size();
+  SizeOfHeaders += Is64 ? sizeof(pe32plus_header) : sizeof(pe32_header);
+  SizeOfHeaders = RoundUpToAlignment(SizeOfHeaders, PageSize);
   uint64_t RVA = 0x1000; // The first page is kept unmapped.
   uint64_t FileOff = SizeOfHeaders;
   for (OutputSection *Sec : OutputSections) {
@@ -309,7 +316,7 @@ inferMachineType(const std::vector<Objec
   return IMAGE_FILE_MACHINE_UNKNOWN;
 }
 
-void Writer::writeHeader() {
+template <typename PEHeaderTy> void Writer::writeHeader() {
   // Write DOS stub
   uint8_t *Buf = Buffer->getBufferStart();
   auto *DOS = reinterpret_cast<dos_header *>(Buf);
@@ -334,18 +341,19 @@ void Writer::writeHeader() {
   COFF->Machine = MachineType;
   COFF->NumberOfSections = OutputSections.size();
   COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
-  COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
+  if (Is64)
+    COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
   if (Config->DLL)
     COFF->Characteristics |= IMAGE_FILE_DLL;
   if (!Config->Relocatable)
     COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
   COFF->SizeOfOptionalHeader =
-      sizeof(pe32plus_header) + sizeof(data_directory) * NumberfOfDataDirectory;
+      sizeof(PEHeaderTy) + sizeof(data_directory) * NumberfOfDataDirectory;
 
   // Write PE header
-  auto *PE = reinterpret_cast<pe32plus_header *>(Buf);
+  auto *PE = reinterpret_cast<PEHeaderTy *>(Buf);
   Buf += sizeof(*PE);
-  PE->Magic = PE32Header::PE32_PLUS;
+  PE->Magic = Is64 ? PE32Header::PE32_PLUS : PE32Header::PE32;
   PE->ImageBase = Config->ImageBase;
   PE->SectionAlignment = SectionAlignment;
   PE->FileAlignment = FileAlignment;

Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=241657&r1=241656&r2=241657&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Tue Jul  7 20:45:29 2015
@@ -74,7 +74,7 @@ private:
 // The writer writes a SymbolTable result to a file.
 class Writer {
 public:
-  explicit Writer(SymbolTable *T) : Symtab(T) {}
+  explicit Writer(SymbolTable *T);
   std::error_code write(StringRef Path);
 
 private:
@@ -87,7 +87,7 @@ private:
   void assignAddresses();
   void removeEmptySections();
   std::error_code openFile(StringRef OutputPath);
-  void writeHeader();
+  template <typename PEHeaderTy> void writeHeader();
   void writeSections();
   void sortExceptionTable();
   void applyRelocations();
@@ -109,6 +109,7 @@ private:
   DelayLoadContents DelayIdata;
   EdataContents Edata;
 
+  bool Is64;
   uint64_t FileSize;
   uint64_t SizeOfImage;
   uint64_t SizeOfHeaders;

Added: lld/trunk/test/COFF/reloc-x86.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/reloc-x86.test?rev=241657&view=auto
==============================================================================
--- lld/trunk/test/COFF/reloc-x86.test (added)
+++ lld/trunk/test/COFF/reloc-x86.test Tue Jul  7 20:45:29 2015
@@ -0,0 +1,60 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld -flavor link2 /out:%t.exe /entry:main /base:0x400000 %t.obj
+# 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
+
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4096
+    SectionData:     A100000000A100000000A100000000A100000000A100000000A100000000
+    Relocations:
+      - VirtualAddress:  1
+        SymbolName:      main
+        Type:            IMAGE_REL_I386_ABSOLUTE
+      - VirtualAddress:  6
+        SymbolName:      main
+        Type:            IMAGE_REL_I386_DIR32
+      - VirtualAddress:  11
+        SymbolName:      main
+        Type:            IMAGE_REL_I386_DIR32NB
+      - VirtualAddress:  16
+        SymbolName:      main
+        Type:            IMAGE_REL_I386_REL32
+      - VirtualAddress:  23
+        SymbolName:      main
+        Type:            IMAGE_REL_I386_SECTION
+      - VirtualAddress:  26
+        SymbolName:      main
+        Type:            IMAGE_REL_I386_SECREL
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          6
+      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
+...





More information about the llvm-commits mailing list