blob: fc73f36ad286561c4db9cbf043a51c4c57fdda15 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- OutputSections.h -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLD_WASM_OUTPUT_SECTIONS_H
11#define LLD_WASM_OUTPUT_SECTIONS_H
12
13#include "InputSegment.h"
14#include "WriterUtils.h"
15#include "lld/Common/ErrorHandler.h"
16#include "llvm/ADT/DenseMap.h"
17
18using llvm::raw_ostream;
19using llvm::raw_string_ostream;
20
21namespace lld {
22
23namespace wasm {
24class OutputSection;
25}
Sam Cleggab2ac292017-12-20 05:14:48 +000026std::string toString(const wasm::OutputSection &Section);
Sam Cleggc94d3932017-11-17 18:14:09 +000027
28namespace wasm {
29
30class OutputSegment;
31class ObjFile;
32
33class OutputSection {
34public:
35 OutputSection(uint32_t Type, std::string Name = "")
36 : Type(Type), Name(Name) {}
Sam Cleggc94d3932017-11-17 18:14:09 +000037 virtual ~OutputSection() = default;
38
Sam Cleggab2ac292017-12-20 05:14:48 +000039 std::string getSectionName() const;
Sam Cleggc94d3932017-11-17 18:14:09 +000040 void setOffset(size_t NewOffset) {
Sam Cleggab2ac292017-12-20 05:14:48 +000041 log("setOffset: " + toString(*this) + ": " + Twine(NewOffset));
Sam Cleggc94d3932017-11-17 18:14:09 +000042 Offset = NewOffset;
43 }
Sam Cleggc94d3932017-11-17 18:14:09 +000044 void createHeader(size_t BodySize);
45 virtual size_t getSize() const = 0;
46 virtual void writeTo(uint8_t *Buf) = 0;
47 virtual void finalizeContents() {}
Sam Cleggab2ac292017-12-20 05:14:48 +000048 virtual uint32_t numRelocations() const { return 0; }
49 virtual void writeRelocations(raw_ostream &OS) const {}
Sam Cleggc94d3932017-11-17 18:14:09 +000050
51 std::string Header;
52 uint32_t Type;
53 std::string Name;
54
Sam Cleggc94d3932017-11-17 18:14:09 +000055protected:
56 size_t Offset = 0;
57};
58
59class SyntheticSection : public OutputSection {
60public:
61 SyntheticSection(uint32_t Type, std::string Name = "")
62 : OutputSection(Type, Name), BodyOutputStream(Body) {
63 if (!Name.empty())
64 writeStr(BodyOutputStream, Name);
65 }
66
67 void writeTo(uint8_t *Buf) override {
68 assert(Offset);
Sam Cleggab2ac292017-12-20 05:14:48 +000069 log("writing " + toString(*this));
Sam Cleggc94d3932017-11-17 18:14:09 +000070 memcpy(Buf + Offset, Header.data(), Header.size());
71 memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());
72 }
73
74 size_t getSize() const override { return Header.size() + Body.size(); }
75
76 void finalizeContents() override {
77 BodyOutputStream.flush();
78 createHeader(Body.size());
79 }
80
81 raw_ostream &getStream() { return BodyOutputStream; }
82
83 std::string Body;
84
85protected:
86 raw_string_ostream BodyOutputStream;
87};
88
89// Some synthetic sections (e.g. "name" and "linking") have subsections.
90// Just like the synthetic sections themselves these need to be created before
91// they can be written out (since they are preceded by their length). This
92// class is used to create subsections and then write them into the stream
93// of the parent section.
94class SubSection : public SyntheticSection {
95public:
96 explicit SubSection(uint32_t Type) : SyntheticSection(Type) {}
97
Sam Cleggab2ac292017-12-20 05:14:48 +000098 std::string getSectionName() const;
Sam Cleggc94d3932017-11-17 18:14:09 +000099 void writeToStream(raw_ostream &OS) {
100 writeBytes(OS, Header.data(), Header.size());
101 writeBytes(OS, Body.data(), Body.size());
102 }
103};
104
105class CodeSection : public OutputSection {
106public:
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000107 explicit CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs);
Sam Cleggc94d3932017-11-17 18:14:09 +0000108 size_t getSize() const override { return Header.size() + BodySize; }
109 void writeTo(uint8_t *Buf) override;
110 uint32_t numRelocations() const override;
111 void writeRelocations(raw_ostream &OS) const override;
112
113protected:
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000114 ArrayRef<ObjFile *> InputObjects;
Sam Cleggc94d3932017-11-17 18:14:09 +0000115 std::string CodeSectionHeader;
116 size_t BodySize = 0;
117};
118
119class DataSection : public OutputSection {
120public:
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000121 explicit DataSection(ArrayRef<OutputSegment *> Segments);
Sam Cleggc94d3932017-11-17 18:14:09 +0000122 size_t getSize() const override { return Header.size() + BodySize; }
123 void writeTo(uint8_t *Buf) override;
Sam Clegg5e8cba92017-12-19 20:45:15 +0000124 uint32_t numRelocations() const override;
Sam Cleggc94d3932017-11-17 18:14:09 +0000125 void writeRelocations(raw_ostream &OS) const override;
126
127protected:
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000128 ArrayRef<OutputSegment *> Segments;
Sam Cleggc94d3932017-11-17 18:14:09 +0000129 std::string DataSectionHeader;
130 size_t BodySize = 0;
131};
132
133} // namespace wasm
134} // namespace lld
135
136#endif // LLD_WASM_OUTPUT_SECTIONS_H