[lld] r222043 - [PECOFF] Fix section alignment.

Rui Ueyama ruiu at google.com
Fri Nov 14 13:33:07 PST 2014


Author: ruiu
Date: Fri Nov 14 15:33:07 2014
New Revision: 222043

URL: http://llvm.org/viewvc/llvm-project?rev=222043&view=rev
Log:
[PECOFF] Fix section alignment.

If you have something like

  __declspec(align(8192)) int foo = 1;

in your code, the compiler makes the data to be aligned to 8192-byte
boundary, and the linker align the section containing the data to 8192.

LLD always aligned the section to 4192. So, as long as alignment
requirement is smaller than 4192, it was correct, but for larger
requirements, it's wrong.

This patch fixes the issue.

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
    lld/trunk/test/pecoff/Inputs/alignment.obj.yaml
    lld/trunk/test/pecoff/alignment.test

Modified: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=222043&r1=222042&r2=222043&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Fri Nov 14 15:33:07 2014
@@ -219,6 +219,7 @@ public:
   uint64_t align() const override { return SECTOR_SIZE; }
   uint32_t getCharacteristics() const { return _characteristics; }
   StringRef getSectionName() const { return _sectionName; }
+  virtual uint64_t memAlign() const { return _memAlign; }
 
   static bool classof(const Chunk *c) {
     Kind kind = c->getKind();
@@ -232,16 +233,18 @@ public:
   void setStringTableOffset(uint32_t offset) { _stringTableOffset = offset; }
 
 protected:
-  SectionChunk(Kind kind, StringRef sectionName, uint32_t characteristics)
+  SectionChunk(Kind kind, StringRef sectionName, uint32_t characteristics,
+               const PECOFFLinkingContext &ctx)
       : Chunk(kind), _sectionName(sectionName),
         _characteristics(characteristics), _virtualAddress(0),
-        _stringTableOffset(0) {}
+        _stringTableOffset(0), _memAlign(ctx.getPageSize()) {}
 
 private:
   StringRef _sectionName;
   const uint32_t _characteristics;
   uint64_t _virtualAddress;
   uint32_t _stringTableOffset;
+  uint64_t _memAlign;
 };
 
 /// An AtomChunk represents a section containing atoms.
@@ -252,6 +255,7 @@ public:
 
   void write(uint8_t *buffer) override;
 
+  uint64_t memAlign() const override;
   void appendAtom(const DefinedAtom *atom);
   void buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const;
 
@@ -293,6 +297,7 @@ private:
 
   mutable llvm::BumpPtrAllocator _alloc;
   llvm::COFF::MachineTypes _machineType;
+  const PECOFFLinkingContext &_ctx;
 };
 
 /// A DataDirectoryChunk represents data directory entries that follows the PE
@@ -334,7 +339,7 @@ class BaseRelocChunk : public SectionChu
 
 public:
   BaseRelocChunk(ChunkVectorT &chunks, const PECOFFLinkingContext &ctx)
-      : SectionChunk(kindSection, ".reloc", characteristics),
+      : SectionChunk(kindSection, ".reloc", characteristics, ctx),
         _ctx(ctx), _contents(createContents(chunks)) {}
 
   void write(uint8_t *buffer) override {
@@ -485,8 +490,8 @@ void PEHeaderChunk<PEHeader>::write(uint
 AtomChunk::AtomChunk(const PECOFFLinkingContext &ctx, StringRef sectionName,
                      const std::vector<const DefinedAtom *> &atoms)
     : SectionChunk(kindAtomChunk, sectionName,
-                   computeCharacteristics(ctx, sectionName, atoms)),
-      _virtualAddress(0), _machineType(ctx.getMachineType()) {
+                   computeCharacteristics(ctx, sectionName, atoms), ctx),
+      _virtualAddress(0), _machineType(ctx.getMachineType()), _ctx(ctx) {
   for (auto *a : atoms)
     appendAtom(a);
 }
@@ -727,6 +732,19 @@ void DataDirectoryChunk::write(uint8_t *
   std::memcpy(buffer, &_data[0], size());
 }
 
+uint64_t AtomChunk::memAlign() const {
+  // ReaderCOFF propagated the section alignment to the first atom in
+  // the section. We restore that here.
+  if (_atomLayouts.empty())
+    return _ctx.getPageSize();
+  int align = _ctx.getPageSize();
+  for (auto atomLayout : _atomLayouts) {
+    auto *atom = cast<const DefinedAtom>(atomLayout->_atom);
+    align = std::max(align, 1 << atom->alignment().powerOf2);
+  }
+  return align;
+}
+
 void AtomChunk::appendAtom(const DefinedAtom *atom) {
   // Atom may have to be at a proper alignment boundary. If so, move the
   // pointer to make a room after the last atom before adding new one.
@@ -1230,23 +1248,24 @@ void PECOFFWriter::addChunk(Chunk *chunk
 void PECOFFWriter::addSectionChunk(std::unique_ptr<SectionChunk> chunk,
                                    SectionHeaderTableChunk *table,
                                    StringTableChunk *stringTable) {
-  SectionChunk &ref = *chunk;
-  _chunks.push_back(std::move(chunk));
-  table->addSection(&ref);
+  table->addSection(chunk.get());
   _numSections++;
 
-  StringRef sectionName = ref.getSectionName();
+  StringRef sectionName = chunk->getSectionName();
   if (sectionName.size() > llvm::COFF::NameSize) {
     uint32_t stringTableOffset = stringTable->addSectionName(sectionName);
-    ref.setStringTableOffset(stringTableOffset);
+    chunk->setStringTableOffset(stringTableOffset);
   }
 
   // Compute and set the starting address of sections when loaded in
   // memory. They are different from positions on disk because sections need
   // to be sector-aligned on disk but page-aligned in memory.
-  ref.setVirtualAddress(_imageSizeInMemory);
   _imageSizeInMemory = llvm::RoundUpToAlignment(
-      _imageSizeInMemory + ref.size(), _ctx.getPageSize());
+      _imageSizeInMemory, chunk->memAlign());
+  chunk->setVirtualAddress(_imageSizeInMemory);
+  _imageSizeInMemory = llvm::RoundUpToAlignment(
+      _imageSizeInMemory + chunk->size(), _ctx.getPageSize());
+  _chunks.push_back(std::move(chunk));
 }
 
 void PECOFFWriter::setImageSizeOnDisk() {

Modified: lld/trunk/test/pecoff/Inputs/alignment.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/alignment.obj.yaml?rev=222043&r1=222042&r2=222043&view=diff
==============================================================================
--- lld/trunk/test/pecoff/Inputs/alignment.obj.yaml (original)
+++ lld/trunk/test/pecoff/Inputs/alignment.obj.yaml Fri Nov 14 15:33:07 2014
@@ -31,6 +31,14 @@ sections:
     Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
     Alignment:       16
     SectionData:     0000
+  - Name:            .yyy
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4096
+    SectionData:     0000
+  - Name:            .zzz
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       16384
+    SectionData:     0000
 symbols:
   - Name:            .text
     Value:           0
@@ -80,4 +88,16 @@ symbols:
     SimpleType:      IMAGE_SYM_TYPE_NULL
     ComplexType:     IMAGE_SYM_DTYPE_NULL
     StorageClass:    IMAGE_SYM_CLASS_STATIC
+  - Name:            .foo
+    Value:           0
+    SectionNumber:   8
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+  - Name:            .bar
+    Value:           0
+    SectionNumber:   9
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
 ...

Modified: lld/trunk/test/pecoff/alignment.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/alignment.test?rev=222043&r1=222042&r2=222043&view=diff
==============================================================================
--- lld/trunk/test/pecoff/alignment.test (original)
+++ lld/trunk/test/pecoff/alignment.test Fri Nov 14 15:33:07 2014
@@ -12,3 +12,11 @@ CHECK-NEXT: VirtualSize: 0x6
 
 CHECK:      Name: .text (2E 74 65 78 74 00 00 00)
 CHECK-NEXT: VirtualSize: 0x1001
+
+CHECK:      Name: .yyy
+CHECK-NEXT: VirtualSize: 0x2
+CHECK-NEXT: VirtualAddress: 0x5000
+
+CHECK:      Name: .zzz
+CHECK-NEXT: VirtualSize: 0x2
+CHECK-NEXT: VirtualAddress: 0x8000





More information about the llvm-commits mailing list