//===- OutputSections.h -----------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_WASM_OUTPUT_SECTIONS_H #define LLD_WASM_OUTPUT_SECTIONS_H #include "InputChunks.h" #include "WriterUtils.h" #include "lld/Common/ErrorHandler.h" #include "llvm/ADT/DenseMap.h" using llvm::raw_ostream; using llvm::raw_string_ostream; namespace lld { namespace wasm { class OutputSection; } std::string toString(const wasm::OutputSection &Section); namespace wasm { class OutputSegment; class OutputSection { public: OutputSection(uint32_t Type, std::string Name = "") : Type(Type), Name(Name) {} virtual ~OutputSection() = default; StringRef getSectionName() const; void setOffset(size_t NewOffset) { log("setOffset: " + toString(*this) + ": " + Twine(NewOffset)); Offset = NewOffset; } void createHeader(size_t BodySize); virtual size_t getSize() const = 0; virtual void writeTo(uint8_t *Buf) = 0; virtual void finalizeContents() {} virtual uint32_t numRelocations() const { return 0; } virtual void writeRelocations(raw_ostream &OS) const {} std::string Header; uint32_t Type; std::string Name; protected: size_t Offset = 0; }; class SyntheticSection : public OutputSection { public: SyntheticSection(uint32_t Type, std::string Name = "") : OutputSection(Type, Name), BodyOutputStream(Body) { if (!Name.empty()) writeStr(BodyOutputStream, Name, "section name"); } void writeTo(uint8_t *Buf) override { assert(Offset); log("writing " + toString(*this)); memcpy(Buf + Offset, Header.data(), Header.size()); memcpy(Buf + Offset + Header.size(), Body.data(), Body.size()); } size_t getSize() const override { return Header.size() + Body.size(); } void finalizeContents() override { BodyOutputStream.flush(); createHeader(Body.size()); } raw_ostream &getStream() { return BodyOutputStream; } std::string Body; protected: raw_string_ostream BodyOutputStream; }; class CodeSection : public OutputSection { public: explicit CodeSection(ArrayRef Functions); size_t getSize() const override { return Header.size() + BodySize; } void writeTo(uint8_t *Buf) override; uint32_t numRelocations() const override; void writeRelocations(raw_ostream &OS) const override; protected: ArrayRef Functions; std::string CodeSectionHeader; size_t BodySize = 0; }; class DataSection : public OutputSection { public: explicit DataSection(ArrayRef Segments); size_t getSize() const override { return Header.size() + BodySize; } void writeTo(uint8_t *Buf) override; uint32_t numRelocations() const override; void writeRelocations(raw_ostream &OS) const override; protected: ArrayRef Segments; std::string DataSectionHeader; 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 InputSections); size_t getSize() const override { return Header.size() + NameData.size() + PayloadSize; } void writeTo(uint8_t *Buf) override; uint32_t numRelocations() const override; void writeRelocations(raw_ostream &OS) const override; protected: size_t PayloadSize; ArrayRef InputSections; std::string NameData; }; } // namespace wasm } // namespace lld #endif // LLD_WASM_OUTPUT_SECTIONS_H