llvm-mc: Tweak section alignment and size computation to match 'as' closer.
authorDaniel Dunbar <daniel@zuster.org>
Fri, 28 Aug 2009 05:49:04 +0000 (05:49 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 28 Aug 2009 05:49:04 +0000 (05:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80345 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCAssembler.h
lib/MC/MCAssembler.cpp

index 6f9149b40c525e77da4650637130ededf427969e..edb504bda250a4441cbab240b79f9d9da14f12cd 100644 (file)
@@ -502,11 +502,7 @@ private:
   /// LayoutSection - Assign offsets and sizes to the fragments in the section
   /// \arg SD, and update the section size. The section file offset should
   /// already have been computed.
-  ///
-  /// \param NextAlign - The alignment for the section end address, which may
-  /// add padding bytes to the section (these are included in the section "file"
-  /// size, but not its regular size).
-  void LayoutSection(MCSectionData &SD, unsigned NextAlign);
+  void LayoutSection(MCSectionData &SD);
 
 public:
   /// Construct a new assembler instance.
index a01d8de46b225bd84df9c9fc2b7bcc231d848d5b..1375b779580692ec8ac362c3597eb9b66a19b3ea 100644 (file)
@@ -203,6 +203,7 @@ public:
   /// \arg NumSections - The number of sections in this segment.
   /// \arg SectionDataSize - The total size of the sections.
   void WriteSegmentLoadCommand32(unsigned NumSections,
+                                 uint64_t VMSize,
                                  uint64_t SectionDataStartOffset,
                                  uint64_t SectionDataSize) {
     // struct segment_command (56 bytes)
@@ -215,7 +216,7 @@ public:
 
     WriteString("", 16);
     Write32(0); // vmaddr
-    Write32(SectionDataSize); // vmsize
+    Write32(VMSize); // vmsize
     Write32(SectionDataStartOffset); // file offset
     Write32(SectionDataSize); // file size
     Write32(0x7); // maxprot
@@ -679,19 +680,35 @@ public:
       LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize;
     }
 
+    // Compute the total size of the section data, as well as its file size and
+    // vm size.
     uint64_t SectionDataStart = Header32Size + LoadCommandsSize;
-    uint64_t SectionDataEnd = SectionDataStart;
     uint64_t SectionDataSize = 0;
-    if (!Asm.getSectionList().empty()) {
-      MCSectionData &SD = Asm.getSectionList().back();
-      SectionDataSize = SD.getAddress() + SD.getSize();
-      SectionDataEnd = SectionDataStart + SD.getAddress() + SD.getFileSize();
+    uint64_t SectionDataFileSize = 0;
+    uint64_t VMSize = 0;
+    for (MCAssembler::iterator it = Asm.begin(),
+           ie = Asm.end(); it != ie; ++it) {
+      MCSectionData &SD = *it;
+
+      VMSize = std::max(VMSize, SD.getAddress() + SD.getSize());
+
+      SectionDataSize = std::max(SectionDataSize,
+                                 SD.getAddress() + SD.getSize());
+      SectionDataFileSize = std::max(SectionDataFileSize, 
+                                     SD.getAddress() + SD.getFileSize());
     }
 
+    // The section data is passed to 4 bytes.
+    //
+    // FIXME: Is this machine dependent?
+    unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
+    SectionDataFileSize += SectionDataPadding;
+
     // Write the prolog, starting with the header and load command...
     WriteHeader32(NumLoadCommands, LoadCommandsSize,
                   Asm.getSubsectionsViaSymbols());
-    WriteSegmentLoadCommand32(NumSections, SectionDataStart, SectionDataSize);
+    WriteSegmentLoadCommand32(NumSections, VMSize,
+                              SectionDataStart, SectionDataSize);
   
     // ... and then the section headers.
     // 
@@ -700,7 +717,7 @@ public:
     // value; this will be overwrite the appropriate data in the fragment when
     // it is written.
     std::vector<MachRelocationEntry> RelocInfos;
-    uint64_t RelocTableEnd = SectionDataEnd;
+    uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
     for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
          ++it) {
       MCSectionData &SD = *it;
@@ -756,6 +773,9 @@ public:
     for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
       WriteFileData(OS, *it, *this);
 
+    // Write the extra padding.
+    WriteZeros(SectionDataPadding);
+
     // Write the relocation entries.
     for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) {
       Write32(RelocInfos[i].Word0);
@@ -889,7 +909,7 @@ MCAssembler::MCAssembler(raw_ostream &_OS)
 MCAssembler::~MCAssembler() {
 }
 
-void MCAssembler::LayoutSection(MCSectionData &SD, unsigned NextAlign) {
+void MCAssembler::LayoutSection(MCSectionData &SD) {
   uint64_t Address = SD.getAddress();
 
   for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
@@ -955,7 +975,7 @@ void MCAssembler::LayoutSection(MCSectionData &SD, unsigned NextAlign) {
 
   // Set the section sizes.
   SD.setSize(Address - SD.getAddress());
-  SD.setFileSize(RoundUpToAlignment(Address, NextAlign) - SD.getAddress());
+  SD.setFileSize(Address - SD.getAddress());
 }
 
 /// WriteFileData - Write the \arg F data to the output file.
@@ -1060,22 +1080,24 @@ static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
 void MCAssembler::Finish() {
   // Layout the sections and fragments.
   uint64_t Address = 0;
-  for (iterator it = begin(), ie = end(); it != ie;) {
+  MCSectionData *Prev = 0;
+  for (iterator it = begin(), ie = end(); it != ie; ++it) {
     MCSectionData &SD = *it;
 
-    // Select the amount of padding alignment we need, based on either the next
-    // sections alignment or the default alignment.
-    //
-    // FIXME: This should probably match the native word size.
-    unsigned NextAlign = 4;
-    ++it;
-    if (it != ie)
-      NextAlign = it->getAlignment();
+    // Align this section if necessary by adding padding bytes to the previous
+    // section.
+    if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) {
+      assert(Prev && "Missing prev section!");
+      Prev->setFileSize(Prev->getFileSize() + Pad);
+      Address += Pad;
+    }
 
     // Layout the section fragments and its size.
     SD.setAddress(Address);
-    LayoutSection(SD, NextAlign);
+    LayoutSection(SD);
     Address += SD.getFileSize();
+
+    Prev = &SD;
   }
 
   // Write the object file.