[lld] r352336 - [LLD][COFF] Partial sections

Alexandre Ganea via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 27 17:45:36 PST 2019


Author: aganea
Date: Sun Jan 27 17:45:35 2019
New Revision: 352336

URL: http://llvm.org/viewvc/llvm-project?rev=352336&view=rev
Log:
[LLD][COFF] Partial sections

Persist (input) sections that make up an OutputSection. This is a supporting patch for the upcoming D54802.

Differential Revision: https://reviews.llvm.org/D55293

Modified:
    lld/trunk/COFF/Writer.cpp

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=352336&r1=352335&r2=352336&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Sun Jan 27 17:45:35 2019
@@ -156,6 +156,33 @@ public:
   mutable codeview::DebugInfo *BuildId = nullptr;
 };
 
+// PartialSection represents a group of chunks that contribute to an
+// OutputSection. Collating a collection of PartialSections of same name and
+// characteristics constitutes the OutputSection.
+class PartialSection {
+public:
+  PartialSection(StringRef N, uint32_t Chars)
+      : Name(N), Characteristics(Chars) {}
+  StringRef Name;
+  unsigned Characteristics;
+  std::vector<Chunk *> Chunks;
+
+  bool operator<(const PartialSection &Other) const {
+    int C = Name.compare(Other.Name);
+    if (C == 1)
+      return false;
+    if (C == 0)
+      return Characteristics < Other.Characteristics;
+    return true;
+  }
+};
+
+struct PartialLess {
+  bool operator()(PartialSection *L, PartialSection *R) const {
+    return *L < *R;
+  }
+};
+
 // The writer writes a SymbolTable result to a file.
 class Writer {
 public:
@@ -167,8 +194,7 @@ private:
   void createMiscChunks();
   void createImportTables();
   void appendImportThunks();
-  void locateImportTables(
-      std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map);
+  void locateImportTables();
   void createExportTable();
   void mergeSections();
   void readRelocTargets();
@@ -193,6 +219,10 @@ private:
   void writeBuildId();
   void sortExceptionTable();
   void sortCRTSectionChunks(std::vector<Chunk *> &Chunks);
+  void addSyntheticIdata();
+  bool fixGnuImportChunks();
+  PartialSection *createPartialSection(StringRef Name, uint32_t OutChars);
+  PartialSection *findPartialSection(StringRef Name, uint32_t OutChars);
 
   llvm::Optional<coff_symbol16> createSymbol(Defined *D);
   size_t addEntryToStringTable(StringRef Str);
@@ -202,9 +232,9 @@ private:
   void addBaserelBlocks(std::vector<Baserel> &V);
 
   uint32_t getSizeOfInitializedData();
-  std::map<StringRef, std::vector<DefinedImportData *>> binImports();
 
   std::unique_ptr<FileOutputBuffer> &Buffer;
+  std::set<PartialSection *, PartialLess> PartialSections;
   std::vector<OutputSection *> OutputSections;
   std::vector<char> Strtab;
   std::vector<llvm::object::coff_symbol16> OutputSymtab;
@@ -567,34 +597,30 @@ static void sortBySectionOrder(std::vect
 // be formed correctly, the section chunks within each .idata$* section need
 // to be grouped by library, and sorted alphabetically within each library
 // (which makes sure the header comes first and the trailer last).
-static bool fixGnuImportChunks(
-    std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) {
+bool Writer::fixGnuImportChunks() {
   uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
 
   // Make sure all .idata$* section chunks are mapped as RDATA in order to
   // be sorted into the same sections as our own synthesized .idata chunks.
-  for (auto &Pair : Map) {
-    StringRef SectionName = Pair.first.first;
-    uint32_t OutChars = Pair.first.second;
-    if (!SectionName.startswith(".idata"))
+  for (PartialSection *PSec : PartialSections) {
+    if (!PSec->Name.startswith(".idata"))
       continue;
-    if (OutChars == RDATA)
+    if (PSec->Characteristics == RDATA)
       continue;
-    std::vector<Chunk *> &SrcVect = Pair.second;
-    std::vector<Chunk *> &DestVect = Map[{SectionName, RDATA}];
-    DestVect.insert(DestVect.end(), SrcVect.begin(), SrcVect.end());
-    SrcVect.clear();
+    PartialSection *RDataSec = createPartialSection(PSec->Name, RDATA);
+    RDataSec->Chunks.insert(RDataSec->Chunks.end(), PSec->Chunks.begin(),
+                            PSec->Chunks.end());
+    PSec->Chunks.clear();
   }
 
   bool HasIdata = false;
   // Sort all .idata$* chunks, grouping chunks from the same library,
   // with alphabetical ordering of the object fils within a library.
-  for (auto &Pair : Map) {
-    StringRef SectionName = Pair.first.first;
-    if (!SectionName.startswith(".idata"))
+  for (PartialSection *PSec : PartialSections) {
+    if (!PSec->Name.startswith(".idata"))
       continue;
 
-    std::vector<Chunk *> &Chunks = Pair.second;
+    std::vector<Chunk *> &Chunks = PSec->Chunks;
     if (!Chunks.empty())
       HasIdata = true;
     std::stable_sort(Chunks.begin(), Chunks.end(), [&](Chunk *S, Chunk *T) {
@@ -620,9 +646,7 @@ static bool fixGnuImportChunks(
 
 // Add generated idata chunks, for imported symbols and DLLs, and a
 // terminator in .idata$2.
-static void addSyntheticIdata(
-    IdataContents &Idata,
-    std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) {
+void Writer::addSyntheticIdata() {
   uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
   Idata.create();
 
@@ -630,8 +654,8 @@ static void addSyntheticIdata(
   // chunks from other linked in object files to be grouped together.
   // See Microsoft PE/COFF spec 5.4 for details.
   auto Add = [&](StringRef N, std::vector<Chunk *> &V) {
-    std::vector<Chunk *> &DestVect = Map[{N, RDATA}];
-    DestVect.insert(DestVect.end(), V.begin(), V.end());
+    PartialSection *PSec = createPartialSection(N, RDATA);
+    PSec->Chunks.insert(PSec->Chunks.end(), V.begin(), V.end());
   };
 
   // The loader assumes a specific order of data.
@@ -645,20 +669,22 @@ static void addSyntheticIdata(
 
 // Locate the first Chunk and size of the import directory list and the
 // IAT.
-void Writer::locateImportTables(
-    std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) {
+void Writer::locateImportTables() {
   uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
-  std::vector<Chunk *> &ImportTables = Map[{".idata$2", RDATA}];
-  if (!ImportTables.empty())
-    ImportTableStart = ImportTables.front();
-  for (Chunk *C : ImportTables)
-    ImportTableSize += C->getSize();
-
-  std::vector<Chunk *> &IAT = Map[{".idata$5", RDATA}];
-  if (!IAT.empty())
-    IATStart = IAT.front();
-  for (Chunk *C : IAT)
-    IATSize += C->getSize();
+
+  if (PartialSection *ImportDirs = findPartialSection(".idata$2", RDATA)) {
+    if (!ImportDirs->Chunks.empty())
+      ImportTableStart = ImportDirs->Chunks.front();
+    for (Chunk *C : ImportDirs->Chunks)
+      ImportTableSize += C->getSize();
+  }
+
+  if (PartialSection *ImportAddresses = findPartialSection(".idata$5", RDATA)) {
+    if (!ImportAddresses->Chunks.empty())
+      IATStart = ImportAddresses->Chunks.front();
+    for (Chunk *C : ImportAddresses->Chunks)
+      IATSize += C->getSize();
+  }
 }
 
 // Create output section objects and add them to OutputSections.
@@ -698,7 +724,6 @@ void Writer::createSections() {
   DtorsSec = CreateSection(".dtors", DATA | R | W);
 
   // Then bin chunks by name and output characteristics.
-  std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> Map;
   for (Chunk *C : Symtab->getChunks()) {
     auto *SC = dyn_cast<SectionChunk>(C);
     if (SC && !SC->Live) {
@@ -706,33 +731,35 @@ void Writer::createSections() {
         SC->printDiscardedMessage();
       continue;
     }
-    Map[{C->getSectionName(), C->getOutputCharacteristics()}].push_back(C);
+    PartialSection *PSec = createPartialSection(C->getSectionName(),
+                                                C->getOutputCharacteristics());
+    PSec->Chunks.push_back(C);
   }
 
   // Even in non MinGW cases, we might need to link against GNU import
   // libraries.
-  bool HasIdata = fixGnuImportChunks(Map);
+  bool HasIdata = fixGnuImportChunks();
   if (!Idata.empty())
     HasIdata = true;
 
   if (HasIdata)
-    addSyntheticIdata(Idata, Map);
+    addSyntheticIdata();
 
   // Process an /order option.
   if (!Config->Order.empty())
-    for (auto &Pair : Map)
-      sortBySectionOrder(Pair.second);
+    for (PartialSection *PSec : PartialSections)
+      sortBySectionOrder(PSec->Chunks);
 
   if (HasIdata)
-    locateImportTables(Map);
+    locateImportTables();
 
   // Then create an OutputSection for each section.
   // '$' and all following characters in input section names are
   // discarded when determining output section. So, .text$foo
   // contributes to .text, for example. See PE/COFF spec 3.2.
-  for (auto &Pair : Map) {
-    StringRef Name = getOutputSectionName(Pair.first.first);
-    uint32_t OutChars = Pair.first.second;
+  for (PartialSection *PSec : PartialSections) {
+    StringRef Name = getOutputSectionName(PSec->Name);
+    uint32_t OutChars = PSec->Characteristics;
 
     if (Name == ".CRT") {
       // In link.exe, there is a special case for the I386 target where .CRT
@@ -741,14 +768,13 @@ void Writer::createSections() {
       // special case for all architectures.
       OutChars = DATA | R;
 
-      log("Processing section " + Pair.first.first + " -> " + Name);
+      log("Processing section " + PSec->Name + " -> " + Name);
 
-      sortCRTSectionChunks(Pair.second);
+      sortCRTSectionChunks(PSec->Chunks);
     }
 
     OutputSection *Sec = CreateSection(Name, OutChars);
-    std::vector<Chunk *> &Chunks = Pair.second;
-    for (Chunk *C : Chunks)
+    for (Chunk *C : PSec->Chunks)
       Sec->addChunk(C);
   }
 
@@ -1716,3 +1742,22 @@ void Writer::addBaserelBlocks(std::vecto
     return;
   RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
 }
+
+PartialSection *Writer::createPartialSection(StringRef Name,
+                                             uint32_t OutChars) {
+  PartialSection *PSec = findPartialSection(Name, OutChars);
+  if (PSec)
+    return PSec;
+  PSec = make<PartialSection>(Name, OutChars);
+  PartialSections.insert(PSec);
+  return PSec;
+}
+
+PartialSection *Writer::findPartialSection(StringRef Name, uint32_t OutChars) {
+  auto It = find_if(PartialSections, [&](PartialSection *P) {
+    return P->Name == Name && P->Characteristics == OutChars;
+  });
+  if (It != PartialSections.end())
+    return *It;
+  return nullptr;
+}




More information about the llvm-commits mailing list