[lld] r329717 - [WebAssembly] Add support for custom sections

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 10 09:12:49 PDT 2018


Author: sbc
Date: Tue Apr 10 09:12:49 2018
New Revision: 329717

URL: http://llvm.org/viewvc/llvm-project?rev=329717&view=rev
Log:
[WebAssembly] Add support for custom sections

Copy user-defined custom sections into the output, concatenating
sections with the same name.

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

Added:
    lld/trunk/test/wasm/Inputs/custom.ll
    lld/trunk/test/wasm/custom-sections.ll
Modified:
    lld/trunk/wasm/InputChunks.cpp
    lld/trunk/wasm/InputChunks.h
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/InputFiles.h
    lld/trunk/wasm/OutputSections.cpp
    lld/trunk/wasm/OutputSections.h
    lld/trunk/wasm/Writer.cpp

Added: lld/trunk/test/wasm/Inputs/custom.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/custom.ll?rev=329717&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/custom.ll (added)
+++ lld/trunk/test/wasm/Inputs/custom.ll Tue Apr 10 09:12:49 2018
@@ -0,0 +1,6 @@
+target triple = "wasm32-unknown-unknown-wasm"
+
+!0 = !{ !"red", !"foo" }
+!1 = !{ !"green", !"bar" }
+!2 = !{ !"green", !"qux" }
+!wasm.custom_sections = !{ !0, !1, !2 }

Added: lld/trunk/test/wasm/custom-sections.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/custom-sections.ll?rev=329717&view=auto
==============================================================================
--- lld/trunk/test/wasm/custom-sections.ll (added)
+++ lld/trunk/test/wasm/custom-sections.ll Tue Apr 10 09:12:49 2018
@@ -0,0 +1,22 @@
+; RUN: llc -filetype=obj %s -o %t1.o
+; RUN: llc -filetype=obj  %S/Inputs/custom.ll -o %t2.o
+; RUN: wasm-ld --check-signatures --relocatable -o %t.wasm %t1.o %t2.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+define i32 @_start() local_unnamed_addr {
+entry:
+  %retval = alloca i32, align 4
+  ret i32 0
+}
+
+!0 = !{ !"red", !"extra" }
+!wasm.custom_sections = !{ !0 }
+
+; CHECK:        - Type:            CUSTOM
+; CHECK-NEXT:     Name:            green
+; CHECK-NEXT:     Payload:         '05677265656E626172717578'
+; CHECK-NEXT:   - Type:            CUSTOM
+; CHECK-NEXT:     Name:            red
+; CHECK-NEXT:     Payload:         037265646578747261666F6F

Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Tue Apr 10 09:12:49 2018
@@ -143,3 +143,13 @@ void InputFunction::setTableIndex(uint32
   assert(!hasTableIndex());
   TableIndex = Index;
 }
+
+InputSection::InputSection(const WasmSection &S, ObjFile *F)
+    : InputChunk(F, InputChunk::Section), Section(S) {
+  assert(Section.Type == llvm::wasm::WASM_SEC_CUSTOM);
+  // TODO check LEB errors
+  unsigned Count;
+  uint64_t NameSize = llvm::decodeULEB128(Section.Content.data(), &Count);
+  uint32_t PayloadOffset = Count + NameSize;
+  Payload = Section.Content.slice(PayloadOffset);
+}

Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Tue Apr 10 09:12:49 2018
@@ -44,7 +44,7 @@ class OutputSegment;
 
 class InputChunk {
 public:
-  enum Kind { DataSegment, Function, SyntheticFunction };
+  enum Kind { DataSegment, Function, SyntheticFunction, Section };
 
   Kind kind() const { return SectionKind; }
 
@@ -173,6 +173,25 @@ protected:
   ArrayRef<uint8_t> Body;
 };
 
+// Represents a single Wasm Section within an input file.
+class InputSection : public InputChunk {
+public:
+  InputSection(const WasmSection &S, ObjFile *F);
+
+  StringRef getName() const override { return Section.Name; }
+  uint32_t getComdat() const override { return UINT32_MAX; }
+
+protected:
+  ArrayRef<uint8_t> data() const override { return Payload; }
+
+  // Offset within the input section.  This is only zero since this chunk
+  // type represents an entire input section, not part of one.
+  uint32_t getInputSectionOffset() const override { return 0; }
+
+  const WasmSection &Section;
+  ArrayRef<uint8_t> Payload;
+};
+
 } // namespace wasm
 
 std::string toString(const wasm::InputChunk *);

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Tue Apr 10 09:12:49 2018
@@ -153,6 +153,8 @@ void ObjFile::parse() {
       CodeSection = &Section;
     else if (Section.Type == WASM_SEC_DATA)
       DataSection = &Section;
+    else if (Section.Type == WASM_SEC_CUSTOM)
+      CustomSections.emplace_back(make<InputSection>(Section, this));
   }
 
   TypeMap.resize(getWasmObj()->types().size());

Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Tue Apr 10 09:12:49 2018
@@ -35,6 +35,7 @@ class InputChunk;
 class InputFunction;
 class InputSegment;
 class InputGlobal;
+class InputSection;
 
 class InputFile {
 public:
@@ -108,6 +109,7 @@ public:
   std::vector<InputSegment *> Segments;
   std::vector<InputFunction *> Functions;
   std::vector<InputGlobal *> Globals;
+  std::vector<InputSection *> CustomSections;
 
   ArrayRef<Symbol *> getSymbols() const { return Symbols; }
   Symbol *getSymbol(uint32_t Index) const { return Symbols[Index]; }

Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Tue Apr 10 09:12:49 2018
@@ -189,3 +189,38 @@ void DataSection::writeRelocations(raw_o
     for (const InputChunk *C : Seg->InputSegments)
       C->writeRelocations(OS);
 }
+
+CustomSection::CustomSection(std::string Name,
+                             ArrayRef<InputSection *> InputSections)
+    : OutputSection(WASM_SEC_CUSTOM, Name), PayloadSize(0),
+      InputSections(InputSections) {
+  raw_string_ostream OS(NameData);
+  encodeULEB128(Name.size(), OS);
+  OS << Name;
+  OS.flush();
+
+  for (InputSection *Section : InputSections) {
+    Section->OutputOffset = PayloadSize;
+    PayloadSize += Section->getSize();
+  }
+
+  createHeader(PayloadSize + NameData.size());
+}
+
+void CustomSection::writeTo(uint8_t *Buf) {
+  log("writing " + toString(*this) + " size=" + Twine(getSize()) +
+      " chunks=" + Twine(InputSections.size()));
+
+  assert(Offset);
+  Buf += Offset;
+
+  // Write section header
+  memcpy(Buf, Header.data(), Header.size());
+  Buf += Header.size();
+  memcpy(Buf, NameData.data(), NameData.size());
+  Buf += NameData.size();
+
+  // Write custom sections payload
+  parallelForEach(InputSections,
+                  [&](const InputSection *Section) { Section->writeTo(Buf); });
+}

Modified: lld/trunk/wasm/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.h?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.h (original)
+++ lld/trunk/wasm/OutputSections.h Tue Apr 10 09:12:49 2018
@@ -113,6 +113,27 @@ protected:
   size_t BodySize = 0;
 };
 
+// Represents a custom section in the output file.  Wasm custom sections are 
+// used for storing user-defined metadata.  Unlike the core sections types
+// they are identified by their string name.
+// The linker combines custom sections that have the same name by simply
+// concatenating them.
+// Note that some custom sections such as "name" and "linking" are handled
+// separately and are instead synthesized by the linker.
+class CustomSection : public OutputSection {
+public:
+  CustomSection(std::string Name, ArrayRef<InputSection *> InputSections);
+  size_t getSize() const override {
+    return Header.size() + NameData.size() + PayloadSize;
+  }
+  void writeTo(uint8_t *Buf) override;
+
+protected:
+  size_t PayloadSize;
+  ArrayRef<InputSection *> InputSections;
+  std::string NameData;
+};
+
 } // namespace wasm
 } // namespace lld
 

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Tue Apr 10 09:12:49 2018
@@ -20,6 +20,7 @@
 #include "lld/Common/Strings.h"
 #include "lld/Common/Threads.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/Object/WasmTraits.h"
 #include "llvm/Support/FileOutputBuffer.h"
@@ -85,6 +86,7 @@ private:
   void createElemSection();
   void createCodeSection();
   void createDataSection();
+  void createCustomSections();
 
   // Custom sections
   void createRelocSections();
@@ -111,6 +113,8 @@ private:
   std::vector<const Symbol *> SymtabEntries;
   std::vector<WasmInitEntry> InitFunctions;
 
+  llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping;
+
   // Elements that are used to construct the final output
   std::string Header;
   std::vector<OutputSection *> OutputSections;
@@ -295,6 +299,23 @@ void Writer::createExportSection() {
   }
 }
 
+void Writer::createCustomSections() {
+  log("createCustomSections");
+  for (ObjFile *File : Symtab->ObjectFiles)
+    for (InputSection *Section : File->CustomSections)
+      CustomSectionMapping[Section->getName()].push_back(Section);
+
+  for (auto &Pair : CustomSectionMapping) {
+    StringRef Name = Pair.first();
+    // These custom sections are known the linker and synthesized rather than
+    // blindly copied
+    if (Name == "linking" || Name == "name" || Name.startswith("reloc."))
+      continue;
+    DEBUG(dbgs() << "createCustomSection: " << Name << "\n");
+    OutputSections.push_back(make<CustomSection>(Name, Pair.second));
+  }
+}
+
 void Writer::createElemSection() {
   if (IndirectFunctions.empty())
     return;
@@ -647,6 +668,7 @@ void Writer::createSections() {
   createElemSection();
   createCodeSection();
   createDataSection();
+  createCustomSections();
 
   // Custom sections
   if (Config->Relocatable) {




More information about the llvm-commits mailing list