blob: 279a9fa9b8d63e27ab84b5811cafc7055e951c10 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- OutputSections.cpp -------------------------------------------------===//
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#include "OutputSections.h"
Sam Clegg5fa274b2018-01-10 01:13:34 +000010#include "InputChunks.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000011#include "InputFiles.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000012#include "OutputSegment.h"
Rui Ueyama4a1b2bb2018-02-28 00:52:42 +000013#include "WriterUtils.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000014#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "lld/Common/Threads.h"
16#include "llvm/ADT/Twine.h"
Rui Ueyama11842532018-02-16 20:38:00 +000017#include "llvm/Support/LEB128.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000018
19#define DEBUG_TYPE "lld"
20
21using namespace llvm;
22using namespace llvm::wasm;
23using namespace lld;
24using namespace lld::wasm;
25
Sam Cleggc94d3932017-11-17 18:14:09 +000026static StringRef sectionTypeToString(uint32_t SectionType) {
27 switch (SectionType) {
28 case WASM_SEC_CUSTOM:
29 return "CUSTOM";
30 case WASM_SEC_TYPE:
31 return "TYPE";
32 case WASM_SEC_IMPORT:
33 return "IMPORT";
34 case WASM_SEC_FUNCTION:
35 return "FUNCTION";
36 case WASM_SEC_TABLE:
37 return "TABLE";
38 case WASM_SEC_MEMORY:
39 return "MEMORY";
40 case WASM_SEC_GLOBAL:
41 return "GLOBAL";
Heejin Ahne915a712018-12-08 06:17:43 +000042 case WASM_SEC_EVENT:
43 return "EVENT";
Sam Cleggc94d3932017-11-17 18:14:09 +000044 case WASM_SEC_EXPORT:
45 return "EXPORT";
46 case WASM_SEC_START:
47 return "START";
48 case WASM_SEC_ELEM:
49 return "ELEM";
50 case WASM_SEC_CODE:
51 return "CODE";
52 case WASM_SEC_DATA:
53 return "DATA";
Thomas Lively84771e22019-04-19 23:40:36 +000054 case WASM_SEC_DATACOUNT:
55 return "DATACOUNT";
Sam Cleggc94d3932017-11-17 18:14:09 +000056 default:
57 fatal("invalid section type");
58 }
59}
60
Rui Ueyama22c8f332018-02-28 17:33:04 +000061// Returns a string, e.g. "FUNCTION(.text)".
62std::string lld::toString(const OutputSection &Sec) {
63 if (!Sec.Name.empty())
64 return (Sec.getSectionName() + "(" + Sec.Name + ")").str();
65 return Sec.getSectionName();
Sam Cleggc94d3932017-11-17 18:14:09 +000066}
67
Rui Ueyama22c8f332018-02-28 17:33:04 +000068StringRef OutputSection::getSectionName() const {
Sam Clegg0d0dd392017-12-19 17:09:45 +000069 return sectionTypeToString(Type);
70}
71
Sam Cleggc94d3932017-11-17 18:14:09 +000072void OutputSection::createHeader(size_t BodySize) {
73 raw_string_ostream OS(Header);
Rui Ueyama22c8f332018-02-28 17:33:04 +000074 debugWrite(OS.tell(), "section type [" + getSectionName() + "]");
Rui Ueyama11842532018-02-16 20:38:00 +000075 encodeULEB128(Type, OS);
Sam Cleggc94d3932017-11-17 18:14:09 +000076 writeUleb128(OS, BodySize, "section size");
77 OS.flush();
Sam Cleggab2ac292017-12-20 05:14:48 +000078 log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) +
Sam Cleggc94d3932017-11-17 18:14:09 +000079 " total=" + Twine(getSize()));
80}
81
Sam Clegg8d146bb2018-01-09 23:56:44 +000082CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
83 : OutputSection(WASM_SEC_CODE), Functions(Functions) {
84 assert(Functions.size() > 0);
85
Sam Cleggc94d3932017-11-17 18:14:09 +000086 raw_string_ostream OS(CodeSectionHeader);
Sam Clegg8d146bb2018-01-09 23:56:44 +000087 writeUleb128(OS, Functions.size(), "function count");
Sam Cleggc94d3932017-11-17 18:14:09 +000088 OS.flush();
89 BodySize = CodeSectionHeader.size();
90
Sam Cleggfb983cd2018-05-18 23:28:05 +000091 for (InputFunction *Func : Functions) {
Rui Ueyamabf450d92018-02-20 04:26:26 +000092 Func->OutputOffset = BodySize;
Sam Cleggfb983cd2018-05-18 23:28:05 +000093 Func->calculateSize();
Sam Clegg5fa274b2018-01-10 01:13:34 +000094 BodySize += Func->getSize();
Sam Cleggc94d3932017-11-17 18:14:09 +000095 }
96
97 createHeader(BodySize);
98}
99
100void CodeSection::writeTo(uint8_t *Buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +0000101 log("writing " + toString(*this));
Sam Cleggc94d3932017-11-17 18:14:09 +0000102 log(" size=" + Twine(getSize()));
Sam Clegg8d146bb2018-01-09 23:56:44 +0000103 log(" headersize=" + Twine(Header.size()));
104 log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
Sam Cleggc94d3932017-11-17 18:14:09 +0000105 Buf += Offset;
106
107 // Write section header
108 memcpy(Buf, Header.data(), Header.size());
109 Buf += Header.size();
110
Sam Cleggc94d3932017-11-17 18:14:09 +0000111 // Write code section headers
112 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
Sam Cleggc94d3932017-11-17 18:14:09 +0000113
114 // Write code section bodies
Rui Ueyama5081e412019-04-17 02:12:47 +0000115 for (const InputChunk *Chunk : Functions)
116 Chunk->writeTo(Buf);
Sam Cleggc94d3932017-11-17 18:14:09 +0000117}
118
119uint32_t CodeSection::numRelocations() const {
120 uint32_t Count = 0;
Sam Clegg5fa274b2018-01-10 01:13:34 +0000121 for (const InputChunk *Func : Functions)
Rui Ueyamabf450d92018-02-20 04:26:26 +0000122 Count += Func->NumRelocations();
Sam Cleggc94d3932017-11-17 18:14:09 +0000123 return Count;
124}
125
126void CodeSection::writeRelocations(raw_ostream &OS) const {
Rui Ueyamabf450d92018-02-20 04:26:26 +0000127 for (const InputChunk *C : Functions)
128 C->writeRelocations(OS);
Sam Cleggc94d3932017-11-17 18:14:09 +0000129}
130
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000131DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
Sam Cleggc94d3932017-11-17 18:14:09 +0000132 : OutputSection(WASM_SEC_DATA), Segments(Segments) {
133 raw_string_ostream OS(DataSectionHeader);
134
135 writeUleb128(OS, Segments.size(), "data segment count");
136 OS.flush();
137 BodySize = DataSectionHeader.size();
138
139 for (OutputSegment *Segment : Segments) {
140 raw_string_ostream OS(Segment->Header);
141 writeUleb128(OS, 0, "memory index");
Sam Cleggbfb75342018-11-15 00:37:21 +0000142 WasmInitExpr InitExpr;
143 if (Config->Pic) {
144 assert(Segments.size() <= 1 &&
145 "Currenly only a single data segment is supported in PIC mode");
Thomas Lively25ff8932019-01-08 06:25:55 +0000146 InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
Sam Clegg2dad4e22018-11-15 18:15:54 +0000147 InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex();
Sam Cleggbfb75342018-11-15 00:37:21 +0000148 } else {
149 InitExpr.Opcode = WASM_OPCODE_I32_CONST;
150 InitExpr.Value.Int32 = Segment->StartVA;
151 }
152 writeInitExpr(OS, InitExpr);
Sam Cleggc94d3932017-11-17 18:14:09 +0000153 writeUleb128(OS, Segment->Size, "segment size");
154 OS.flush();
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000155
156 Segment->SectionOffset = BodySize;
Sam Cleggd96d9352018-01-10 19:22:42 +0000157 BodySize += Segment->Header.size() + Segment->Size;
Sam Cleggc94d3932017-11-17 18:14:09 +0000158 log("Data segment: size=" + Twine(Segment->Size));
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000159
Sam Cleggd96d9352018-01-10 19:22:42 +0000160 for (InputSegment *InputSeg : Segment->InputSegments)
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000161 InputSeg->OutputOffset = Segment->SectionOffset + Segment->Header.size() +
Rui Ueyamabf450d92018-02-20 04:26:26 +0000162 InputSeg->OutputSegmentOffset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000163 }
164
165 createHeader(BodySize);
166}
167
168void DataSection::writeTo(uint8_t *Buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +0000169 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Sam Cleggc94d3932017-11-17 18:14:09 +0000170 " body=" + Twine(BodySize));
171 Buf += Offset;
172
173 // Write section header
174 memcpy(Buf, Header.data(), Header.size());
175 Buf += Header.size();
176
Sam Cleggc94d3932017-11-17 18:14:09 +0000177 // Write data section headers
178 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
179
Rui Ueyama5081e412019-04-17 02:12:47 +0000180 for (const OutputSegment *Segment : Segments) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000181 // Write data segment header
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000182 uint8_t *SegStart = Buf + Segment->SectionOffset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000183 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
184
185 // Write segment data payload
Sam Cleggd96d9352018-01-10 19:22:42 +0000186 for (const InputChunk *Chunk : Segment->InputSegments)
Rui Ueyama319eb8b2018-02-28 00:31:16 +0000187 Chunk->writeTo(Buf);
Rui Ueyama5081e412019-04-17 02:12:47 +0000188 }
Sam Clegg5e8cba92017-12-19 20:45:15 +0000189}
Sam Cleggc94d3932017-11-17 18:14:09 +0000190
Sam Clegg5e8cba92017-12-19 20:45:15 +0000191uint32_t DataSection::numRelocations() const {
192 uint32_t Count = 0;
193 for (const OutputSegment *Seg : Segments)
Sam Clegg5fa274b2018-01-10 01:13:34 +0000194 for (const InputChunk *InputSeg : Seg->InputSegments)
Rui Ueyamabf450d92018-02-20 04:26:26 +0000195 Count += InputSeg->NumRelocations();
Sam Clegg5e8cba92017-12-19 20:45:15 +0000196 return Count;
Sam Cleggc94d3932017-11-17 18:14:09 +0000197}
198
199void DataSection::writeRelocations(raw_ostream &OS) const {
Sam Clegg5e8cba92017-12-19 20:45:15 +0000200 for (const OutputSegment *Seg : Segments)
Rui Ueyamabf450d92018-02-20 04:26:26 +0000201 for (const InputChunk *C : Seg->InputSegments)
202 C->writeRelocations(OS);
Sam Cleggc94d3932017-11-17 18:14:09 +0000203}
Sam Clegg80ba4382018-04-10 16:12:49 +0000204
205CustomSection::CustomSection(std::string Name,
206 ArrayRef<InputSection *> InputSections)
207 : OutputSection(WASM_SEC_CUSTOM, Name), PayloadSize(0),
208 InputSections(InputSections) {
209 raw_string_ostream OS(NameData);
210 encodeULEB128(Name.size(), OS);
211 OS << Name;
212 OS.flush();
213
214 for (InputSection *Section : InputSections) {
215 Section->OutputOffset = PayloadSize;
216 PayloadSize += Section->getSize();
217 }
218
219 createHeader(PayloadSize + NameData.size());
220}
221
222void CustomSection::writeTo(uint8_t *Buf) {
223 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
224 " chunks=" + Twine(InputSections.size()));
225
226 assert(Offset);
227 Buf += Offset;
228
229 // Write section header
230 memcpy(Buf, Header.data(), Header.size());
231 Buf += Header.size();
232 memcpy(Buf, NameData.data(), NameData.size());
233 Buf += NameData.size();
234
235 // Write custom sections payload
Rui Ueyama5081e412019-04-17 02:12:47 +0000236 for (const InputSection *Section : InputSections)
237 Section->writeTo(Buf);
Sam Clegg80ba4382018-04-10 16:12:49 +0000238}
Sam Cleggd177ab22018-05-04 23:14:42 +0000239
240uint32_t CustomSection::numRelocations() const {
241 uint32_t Count = 0;
242 for (const InputSection *InputSect : InputSections)
243 Count += InputSect->NumRelocations();
244 return Count;
245}
246
247void CustomSection::writeRelocations(raw_ostream &OS) const {
248 for (const InputSection *S : InputSections)
249 S->writeRelocations(OS);
250}