blob: a1853cb32ad9eb05c378877525dedd6df0979867 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- OutputSections.h -----------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Sam Cleggc94d3932017-11-17 18:14:09 +00006//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_WASM_OUTPUT_SECTIONS_H
10#define LLD_WASM_OUTPUT_SECTIONS_H
11
Sam Clegg5fa274b2018-01-10 01:13:34 +000012#include "InputChunks.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000013#include "WriterUtils.h"
14#include "lld/Common/ErrorHandler.h"
Sam Clegg45218f42018-11-27 01:08:16 +000015#include "lld/Common/LLVM.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000016#include "llvm/ADT/DenseMap.h"
17
Sam Cleggc94d3932017-11-17 18:14:09 +000018namespace lld {
19
20namespace wasm {
21class OutputSection;
22}
Sam Cleggab2ac292017-12-20 05:14:48 +000023std::string toString(const wasm::OutputSection &Section);
Sam Cleggc94d3932017-11-17 18:14:09 +000024
25namespace wasm {
26
27class OutputSegment;
Sam Cleggc94d3932017-11-17 18:14:09 +000028
29class OutputSection {
30public:
31 OutputSection(uint32_t Type, std::string Name = "")
32 : Type(Type), Name(Name) {}
Sam Cleggc94d3932017-11-17 18:14:09 +000033 virtual ~OutputSection() = default;
34
Rui Ueyama22c8f332018-02-28 17:33:04 +000035 StringRef getSectionName() const;
Sam Cleggc94d3932017-11-17 18:14:09 +000036 void setOffset(size_t NewOffset) {
Sam Cleggab2ac292017-12-20 05:14:48 +000037 log("setOffset: " + toString(*this) + ": " + Twine(NewOffset));
Sam Cleggc94d3932017-11-17 18:14:09 +000038 Offset = NewOffset;
39 }
Sam Cleggc94d3932017-11-17 18:14:09 +000040 void createHeader(size_t BodySize);
41 virtual size_t getSize() const = 0;
42 virtual void writeTo(uint8_t *Buf) = 0;
43 virtual void finalizeContents() {}
Sam Cleggab2ac292017-12-20 05:14:48 +000044 virtual uint32_t numRelocations() const { return 0; }
45 virtual void writeRelocations(raw_ostream &OS) const {}
Sam Cleggc94d3932017-11-17 18:14:09 +000046
47 std::string Header;
48 uint32_t Type;
49 std::string Name;
50
Sam Cleggc94d3932017-11-17 18:14:09 +000051protected:
52 size_t Offset = 0;
53};
54
55class SyntheticSection : public OutputSection {
56public:
57 SyntheticSection(uint32_t Type, std::string Name = "")
58 : OutputSection(Type, Name), BodyOutputStream(Body) {
59 if (!Name.empty())
Rui Ueyama11842532018-02-16 20:38:00 +000060 writeStr(BodyOutputStream, Name, "section name");
Sam Cleggc94d3932017-11-17 18:14:09 +000061 }
62
63 void writeTo(uint8_t *Buf) override {
64 assert(Offset);
Sam Cleggab2ac292017-12-20 05:14:48 +000065 log("writing " + toString(*this));
Sam Cleggc94d3932017-11-17 18:14:09 +000066 memcpy(Buf + Offset, Header.data(), Header.size());
67 memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());
68 }
69
70 size_t getSize() const override { return Header.size() + Body.size(); }
71
72 void finalizeContents() override {
73 BodyOutputStream.flush();
74 createHeader(Body.size());
75 }
76
77 raw_ostream &getStream() { return BodyOutputStream; }
78
79 std::string Body;
80
81protected:
Sam Clegg45218f42018-11-27 01:08:16 +000082 llvm::raw_string_ostream BodyOutputStream;
Sam Cleggc94d3932017-11-17 18:14:09 +000083};
84
Sam Cleggc94d3932017-11-17 18:14:09 +000085class CodeSection : public OutputSection {
86public:
Sam Clegg8d146bb2018-01-09 23:56:44 +000087 explicit CodeSection(ArrayRef<InputFunction *> Functions);
Sam Cleggc94d3932017-11-17 18:14:09 +000088 size_t getSize() const override { return Header.size() + BodySize; }
89 void writeTo(uint8_t *Buf) override;
90 uint32_t numRelocations() const override;
91 void writeRelocations(raw_ostream &OS) const override;
92
93protected:
Sam Clegg8d146bb2018-01-09 23:56:44 +000094 ArrayRef<InputFunction *> Functions;
Sam Cleggc94d3932017-11-17 18:14:09 +000095 std::string CodeSectionHeader;
96 size_t BodySize = 0;
97};
98
99class DataSection : public OutputSection {
100public:
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000101 explicit DataSection(ArrayRef<OutputSegment *> Segments);
Sam Cleggc94d3932017-11-17 18:14:09 +0000102 size_t getSize() const override { return Header.size() + BodySize; }
103 void writeTo(uint8_t *Buf) override;
Sam Clegg5e8cba92017-12-19 20:45:15 +0000104 uint32_t numRelocations() const override;
Sam Cleggc94d3932017-11-17 18:14:09 +0000105 void writeRelocations(raw_ostream &OS) const override;
106
107protected:
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000108 ArrayRef<OutputSegment *> Segments;
Sam Cleggc94d3932017-11-17 18:14:09 +0000109 std::string DataSectionHeader;
110 size_t BodySize = 0;
111};
112
Heejin Ahn4821ebf2018-08-29 21:03:16 +0000113// Represents a custom section in the output file. Wasm custom sections are
Sam Clegg80ba4382018-04-10 16:12:49 +0000114// used for storing user-defined metadata. Unlike the core sections types
115// they are identified by their string name.
116// The linker combines custom sections that have the same name by simply
117// concatenating them.
118// Note that some custom sections such as "name" and "linking" are handled
119// separately and are instead synthesized by the linker.
120class CustomSection : public OutputSection {
121public:
122 CustomSection(std::string Name, ArrayRef<InputSection *> InputSections);
123 size_t getSize() const override {
124 return Header.size() + NameData.size() + PayloadSize;
125 }
126 void writeTo(uint8_t *Buf) override;
Sam Cleggd177ab22018-05-04 23:14:42 +0000127 uint32_t numRelocations() const override;
128 void writeRelocations(raw_ostream &OS) const override;
Sam Clegg80ba4382018-04-10 16:12:49 +0000129
130protected:
131 size_t PayloadSize;
132 ArrayRef<InputSection *> InputSections;
133 std::string NameData;
134};
135
Sam Cleggc94d3932017-11-17 18:14:09 +0000136} // namespace wasm
137} // namespace lld
138
139#endif // LLD_WASM_OUTPUT_SECTIONS_H