blob: a59ef8ca10a71f1748e66a12893825c8eed88f3f [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";
54 default:
55 fatal("invalid section type");
56 }
57}
58
Rui Ueyama22c8f332018-02-28 17:33:04 +000059// Returns a string, e.g. "FUNCTION(.text)".
60std::string lld::toString(const OutputSection &Sec) {
61 if (!Sec.Name.empty())
62 return (Sec.getSectionName() + "(" + Sec.Name + ")").str();
63 return Sec.getSectionName();
Sam Cleggc94d3932017-11-17 18:14:09 +000064}
65
Rui Ueyama22c8f332018-02-28 17:33:04 +000066StringRef OutputSection::getSectionName() const {
Sam Clegg0d0dd392017-12-19 17:09:45 +000067 return sectionTypeToString(Type);
68}
69
Sam Cleggc94d3932017-11-17 18:14:09 +000070void OutputSection::createHeader(size_t BodySize) {
71 raw_string_ostream OS(Header);
Rui Ueyama22c8f332018-02-28 17:33:04 +000072 debugWrite(OS.tell(), "section type [" + getSectionName() + "]");
Rui Ueyama11842532018-02-16 20:38:00 +000073 encodeULEB128(Type, OS);
Sam Cleggc94d3932017-11-17 18:14:09 +000074 writeUleb128(OS, BodySize, "section size");
75 OS.flush();
Sam Cleggab2ac292017-12-20 05:14:48 +000076 log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) +
Sam Cleggc94d3932017-11-17 18:14:09 +000077 " total=" + Twine(getSize()));
78}
79
Sam Clegg8d146bb2018-01-09 23:56:44 +000080CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
81 : OutputSection(WASM_SEC_CODE), Functions(Functions) {
82 assert(Functions.size() > 0);
83
Sam Cleggc94d3932017-11-17 18:14:09 +000084 raw_string_ostream OS(CodeSectionHeader);
Sam Clegg8d146bb2018-01-09 23:56:44 +000085 writeUleb128(OS, Functions.size(), "function count");
Sam Cleggc94d3932017-11-17 18:14:09 +000086 OS.flush();
87 BodySize = CodeSectionHeader.size();
88
Sam Cleggfb983cd2018-05-18 23:28:05 +000089 for (InputFunction *Func : Functions) {
Rui Ueyamabf450d92018-02-20 04:26:26 +000090 Func->OutputOffset = BodySize;
Sam Cleggfb983cd2018-05-18 23:28:05 +000091 Func->calculateSize();
Sam Clegg5fa274b2018-01-10 01:13:34 +000092 BodySize += Func->getSize();
Sam Cleggc94d3932017-11-17 18:14:09 +000093 }
94
95 createHeader(BodySize);
96}
97
98void CodeSection::writeTo(uint8_t *Buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +000099 log("writing " + toString(*this));
Sam Cleggc94d3932017-11-17 18:14:09 +0000100 log(" size=" + Twine(getSize()));
Sam Clegg8d146bb2018-01-09 23:56:44 +0000101 log(" headersize=" + Twine(Header.size()));
102 log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
Sam Cleggc94d3932017-11-17 18:14:09 +0000103 Buf += Offset;
104
105 // Write section header
106 memcpy(Buf, Header.data(), Header.size());
107 Buf += Header.size();
108
Sam Cleggc94d3932017-11-17 18:14:09 +0000109 // Write code section headers
110 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
Sam Cleggc94d3932017-11-17 18:14:09 +0000111
112 // Write code section bodies
Rui Ueyama5081e412019-04-17 02:12:47 +0000113 for (const InputChunk *Chunk : Functions)
114 Chunk->writeTo(Buf);
Sam Cleggc94d3932017-11-17 18:14:09 +0000115}
116
117uint32_t CodeSection::numRelocations() const {
118 uint32_t Count = 0;
Sam Clegg5fa274b2018-01-10 01:13:34 +0000119 for (const InputChunk *Func : Functions)
Rui Ueyamabf450d92018-02-20 04:26:26 +0000120 Count += Func->NumRelocations();
Sam Cleggc94d3932017-11-17 18:14:09 +0000121 return Count;
122}
123
124void CodeSection::writeRelocations(raw_ostream &OS) const {
Rui Ueyamabf450d92018-02-20 04:26:26 +0000125 for (const InputChunk *C : Functions)
126 C->writeRelocations(OS);
Sam Cleggc94d3932017-11-17 18:14:09 +0000127}
128
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000129DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
Sam Cleggc94d3932017-11-17 18:14:09 +0000130 : OutputSection(WASM_SEC_DATA), Segments(Segments) {
131 raw_string_ostream OS(DataSectionHeader);
132
133 writeUleb128(OS, Segments.size(), "data segment count");
134 OS.flush();
135 BodySize = DataSectionHeader.size();
136
137 for (OutputSegment *Segment : Segments) {
138 raw_string_ostream OS(Segment->Header);
139 writeUleb128(OS, 0, "memory index");
Sam Cleggbfb75342018-11-15 00:37:21 +0000140 WasmInitExpr InitExpr;
141 if (Config->Pic) {
142 assert(Segments.size() <= 1 &&
143 "Currenly only a single data segment is supported in PIC mode");
Thomas Lively25ff8932019-01-08 06:25:55 +0000144 InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
Sam Clegg2dad4e22018-11-15 18:15:54 +0000145 InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex();
Sam Cleggbfb75342018-11-15 00:37:21 +0000146 } else {
147 InitExpr.Opcode = WASM_OPCODE_I32_CONST;
148 InitExpr.Value.Int32 = Segment->StartVA;
149 }
150 writeInitExpr(OS, InitExpr);
Sam Cleggc94d3932017-11-17 18:14:09 +0000151 writeUleb128(OS, Segment->Size, "segment size");
152 OS.flush();
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000153
154 Segment->SectionOffset = BodySize;
Sam Cleggd96d9352018-01-10 19:22:42 +0000155 BodySize += Segment->Header.size() + Segment->Size;
Sam Cleggc94d3932017-11-17 18:14:09 +0000156 log("Data segment: size=" + Twine(Segment->Size));
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000157
Sam Cleggd96d9352018-01-10 19:22:42 +0000158 for (InputSegment *InputSeg : Segment->InputSegments)
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000159 InputSeg->OutputOffset = Segment->SectionOffset + Segment->Header.size() +
Rui Ueyamabf450d92018-02-20 04:26:26 +0000160 InputSeg->OutputSegmentOffset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000161 }
162
163 createHeader(BodySize);
164}
165
166void DataSection::writeTo(uint8_t *Buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +0000167 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Sam Cleggc94d3932017-11-17 18:14:09 +0000168 " body=" + Twine(BodySize));
169 Buf += Offset;
170
171 // Write section header
172 memcpy(Buf, Header.data(), Header.size());
173 Buf += Header.size();
174
Sam Cleggc94d3932017-11-17 18:14:09 +0000175 // Write data section headers
176 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
177
Rui Ueyama5081e412019-04-17 02:12:47 +0000178 for (const OutputSegment *Segment : Segments) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000179 // Write data segment header
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000180 uint8_t *SegStart = Buf + Segment->SectionOffset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000181 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
182
183 // Write segment data payload
Sam Cleggd96d9352018-01-10 19:22:42 +0000184 for (const InputChunk *Chunk : Segment->InputSegments)
Rui Ueyama319eb8b2018-02-28 00:31:16 +0000185 Chunk->writeTo(Buf);
Rui Ueyama5081e412019-04-17 02:12:47 +0000186 }
Sam Clegg5e8cba92017-12-19 20:45:15 +0000187}
Sam Cleggc94d3932017-11-17 18:14:09 +0000188
Sam Clegg5e8cba92017-12-19 20:45:15 +0000189uint32_t DataSection::numRelocations() const {
190 uint32_t Count = 0;
191 for (const OutputSegment *Seg : Segments)
Sam Clegg5fa274b2018-01-10 01:13:34 +0000192 for (const InputChunk *InputSeg : Seg->InputSegments)
Rui Ueyamabf450d92018-02-20 04:26:26 +0000193 Count += InputSeg->NumRelocations();
Sam Clegg5e8cba92017-12-19 20:45:15 +0000194 return Count;
Sam Cleggc94d3932017-11-17 18:14:09 +0000195}
196
197void DataSection::writeRelocations(raw_ostream &OS) const {
Sam Clegg5e8cba92017-12-19 20:45:15 +0000198 for (const OutputSegment *Seg : Segments)
Rui Ueyamabf450d92018-02-20 04:26:26 +0000199 for (const InputChunk *C : Seg->InputSegments)
200 C->writeRelocations(OS);
Sam Cleggc94d3932017-11-17 18:14:09 +0000201}
Sam Clegg80ba4382018-04-10 16:12:49 +0000202
203CustomSection::CustomSection(std::string Name,
204 ArrayRef<InputSection *> InputSections)
205 : OutputSection(WASM_SEC_CUSTOM, Name), PayloadSize(0),
206 InputSections(InputSections) {
207 raw_string_ostream OS(NameData);
208 encodeULEB128(Name.size(), OS);
209 OS << Name;
210 OS.flush();
211
212 for (InputSection *Section : InputSections) {
213 Section->OutputOffset = PayloadSize;
214 PayloadSize += Section->getSize();
215 }
216
217 createHeader(PayloadSize + NameData.size());
218}
219
220void CustomSection::writeTo(uint8_t *Buf) {
221 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
222 " chunks=" + Twine(InputSections.size()));
223
224 assert(Offset);
225 Buf += Offset;
226
227 // Write section header
228 memcpy(Buf, Header.data(), Header.size());
229 Buf += Header.size();
230 memcpy(Buf, NameData.data(), NameData.size());
231 Buf += NameData.size();
232
233 // Write custom sections payload
Rui Ueyama5081e412019-04-17 02:12:47 +0000234 for (const InputSection *Section : InputSections)
235 Section->writeTo(Buf);
Sam Clegg80ba4382018-04-10 16:12:49 +0000236}
Sam Cleggd177ab22018-05-04 23:14:42 +0000237
238uint32_t CustomSection::numRelocations() const {
239 uint32_t Count = 0;
240 for (const InputSection *InputSect : InputSections)
241 Count += InputSect->NumRelocations();
242 return Count;
243}
244
245void CustomSection::writeRelocations(raw_ostream &OS) const {
246 for (const InputSection *S : InputSections)
247 S->writeRelocations(OS);
248}