[lld] r238661 - COFF: Support long section name.

Rui Ueyama ruiu at google.com
Sat May 30 12:09:50 PDT 2015


Author: ruiu
Date: Sat May 30 14:09:50 2015
New Revision: 238661

URL: http://llvm.org/viewvc/llvm-project?rev=238661&view=rev
Log:
COFF: Support long section name.

Section names were truncated to 8 bytes because the section table's
name field is 8 byte long. This patch creates the string table to
store long names.

Added:
    lld/trunk/test/COFF/long-section-name.test
Modified:
    lld/trunk/COFF/Writer.cpp
    lld/trunk/COFF/Writer.h

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=238661&r1=238660&r2=238661&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Sat May 30 14:09:50 2015
@@ -18,13 +18,16 @@
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
+#include <cstdio>
 #include <functional>
 #include <map>
 #include <utility>
 
 using namespace llvm;
-using namespace llvm::object;
 using namespace llvm::COFF;
+using namespace llvm::object;
+using namespace llvm::support;
+using namespace llvm::support::endian;
 
 static const int PageSize = 4096;
 static const int FileAlignment = 512;
@@ -41,7 +44,6 @@ namespace coff {
 OutputSection::OutputSection(StringRef N, uint32_t SI)
     : Name(N), SectionIndex(SI) {
   memset(&Header, 0, sizeof(Header));
-  strncpy(Header.Name, Name.data(), std::min(Name.size(), size_t(8)));
 }
 
 void OutputSection::setRVA(uint64_t RVA) {
@@ -77,6 +79,19 @@ void OutputSection::addPermissions(uint3
   Header.Characteristics = Header.Characteristics | (C & PermMask);
 }
 
+// Write the section header to a given buffer.
+void OutputSection::writeHeader(uint8_t *Buf) {
+  auto *Hdr = reinterpret_cast<coff_section *>(Buf);
+  *Hdr = Header;
+  if (StringTableOff) {
+    // If name is too long, write offset into the string table as a name.
+    sprintf(Hdr->Name, "/%d", StringTableOff);
+  } else {
+    assert(Name.size() <= COFF::NameSize);
+    strncpy(Hdr->Name, Name.data(), Name.size());
+  }
+}
+
 void Writer::markLive() {
   Entry = cast<Defined>(Symtab->find(Config->EntryName));
   Entry->markLive();
@@ -307,11 +322,41 @@ void Writer::writeHeader() {
     DataDirectory[IAT].Size = ImportAddressTableSize;
   }
 
+  // Section table
+  // Name field in the string table is 8 byte long. Longer names need
+  // to be written to the string table. First, construct string table.
+  std::vector<char> Strtab;
+  for (std::unique_ptr<OutputSection> &Sec : OutputSections) {
+    StringRef Name = Sec->getName();
+    if (Name.size() <= COFF::NameSize)
+      continue;
+    Sec->setStringTableOff(Strtab.size() + 4); // +4 for the size field
+    Strtab.insert(Strtab.end(), Name.begin(), Name.end());
+    Strtab.push_back('\0');
+  }
+
   // Write section table
-  coff_section *SectionTable = reinterpret_cast<coff_section *>(Buf);
-  int Idx = 0;
-  for (std::unique_ptr<OutputSection> &Sec : OutputSections)
-    SectionTable[Idx++] = Sec->getHeader();
+  for (std::unique_ptr<OutputSection> &Sec : OutputSections) {
+    Sec->writeHeader(Buf);
+    Buf += sizeof(coff_section);
+  }
+
+  // Write string table if we need to. The string table immediately
+  // follows the symbol table, so we create a dummy symbol table
+  // first. The symbol table contains one dummy symbol.
+  if (Strtab.empty())
+    return;
+  COFF->PointerToSymbolTable = Buf - Buffer->getBufferStart();
+  COFF->NumberOfSymbols = 1;
+  auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(Buf);
+  Buf += sizeof(*SymbolTable);
+  // (Set 4 to make the dummy symbol point to the first string table
+  // entry, so that tools to print out symbols don't read NUL bytes.)
+  SymbolTable->Name.Offset.Offset = 4;
+  // Then create the symbol table. The first 4 bytes is length
+  // including itself.
+  write32le(Buf, Strtab.size() + 4);
+  memcpy(Buf + 4, Strtab.data(), Strtab.size());
 }
 
 std::error_code Writer::openFile(StringRef Path) {

Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=238661&r1=238660&r2=238661&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Sat May 30 14:09:50 2015
@@ -37,13 +37,12 @@ public:
   StringRef getName() { return Name; }
   uint64_t getSectionIndex() { return SectionIndex; }
   std::vector<Chunk *> &getChunks() { return Chunks; }
-
-  const llvm::object::coff_section getHeader() { return Header; }
   void addPermissions(uint32_t C);
   uint32_t getPermissions() { return Header.Characteristics & PermMask; }
   uint32_t getCharacteristics() { return Header.Characteristics; }
   uint64_t getRVA() { return Header.VirtualAddress; }
   uint64_t getFileOff() { return Header.PointerToRawData; }
+  void writeHeader(uint8_t *Buf);
 
   // Returns the size of this section in an executable memory image.
   // This may be smaller than the raw size (the raw size is multiple
@@ -55,10 +54,15 @@ public:
   // Returns the size of the section in the output file.
   uint64_t getRawSize() { return Header.SizeOfRawData; }
 
+  // Set offset into the string table storing this section name.
+  // Used only when the name is longer than 8 bytes.
+  void setStringTableOff(uint32_t V) { StringTableOff = V; }
+
 private:
-  llvm::object::coff_section Header;
+  coff_section Header;
   StringRef Name;
   uint32_t SectionIndex;
+  uint32_t StringTableOff = 0;
   std::vector<Chunk *> Chunks;
 };
 

Added: lld/trunk/test/COFF/long-section-name.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/long-section-name.test?rev=238661&view=auto
==============================================================================
--- lld/trunk/test/COFF/long-section-name.test (added)
+++ lld/trunk/test/COFF/long-section-name.test Sat May 30 14:09:50 2015
@@ -0,0 +1,58 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: lld -flavor link2 /out:%t.exe /subsystem:console %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck %s
+
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: [  ]
+sections:
+  - Name:            .text_long_section_name
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     B82A000000C3
+  - Name:            .data_long_section_name
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4
+    SectionData:     "00"
+symbols:
+  - Name:            "@comp.id"
+    Value:           10394907
+    SectionNumber:   65535
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+  - Name:            .text_long_section_name
+    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:            .data_long_section_name
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          0
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            mainCRTStartup
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...
+
+# CHECK: Name: .data_long_section_name
+# CHECK: Name: .text_long_section_name





More information about the llvm-commits mailing list