blob: a936562992dd358cf8cb15b79b5dc6fecab8c216 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:091//===- OutputSections.cpp -------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// 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:096//
7//===----------------------------------------------------------------------===//
8
9#include "OutputSections.h"
Sam Clegg5fa274b2018-01-10 01:13:3410#include "InputChunks.h"
Sam Cleggc94d3932017-11-17 18:14:0911#include "InputFiles.h"
Sam Cleggc94d3932017-11-17 18:14:0912#include "OutputSegment.h"
Rui Ueyama4a1b2bb2018-02-28 00:52:4213#include "WriterUtils.h"
Sam Cleggc94d3932017-11-17 18:14:0914#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:0915#include "llvm/ADT/Twine.h"
Rui Ueyama11842532018-02-16 20:38:0016#include "llvm/Support/LEB128.h"
Reid Kleckner932f0272020-05-05 03:03:1917#include "llvm/Support/Parallel.h"
Sam Cleggc94d3932017-11-17 18:14:0918
19#define DEBUG_TYPE "lld"
20
21using namespace llvm;
22using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:0923
Fangrui Song33c59ab2019-10-10 05:25:3924namespace lld {
25
26// Returns a string, e.g. "FUNCTION(.text)".
27std::string toString(const wasm::OutputSection &sec) {
28 if (!sec.name.empty())
29 return (sec.getSectionName() + "(" + sec.name + ")").str();
Benjamin Krameradcd0262020-01-28 19:23:4630 return std::string(sec.getSectionName());
Fangrui Song33c59ab2019-10-10 05:25:3931}
32
33namespace wasm {
Rui Ueyama136d27a2019-07-11 05:40:3034static StringRef sectionTypeToString(uint32_t sectionType) {
35 switch (sectionType) {
Sam Cleggc94d3932017-11-17 18:14:0936 case WASM_SEC_CUSTOM:
37 return "CUSTOM";
38 case WASM_SEC_TYPE:
39 return "TYPE";
40 case WASM_SEC_IMPORT:
41 return "IMPORT";
42 case WASM_SEC_FUNCTION:
43 return "FUNCTION";
44 case WASM_SEC_TABLE:
45 return "TABLE";
46 case WASM_SEC_MEMORY:
47 return "MEMORY";
48 case WASM_SEC_GLOBAL:
49 return "GLOBAL";
Heejin Ahne915a712018-12-08 06:17:4350 case WASM_SEC_EVENT:
51 return "EVENT";
Sam Cleggc94d3932017-11-17 18:14:0952 case WASM_SEC_EXPORT:
53 return "EXPORT";
54 case WASM_SEC_START:
55 return "START";
56 case WASM_SEC_ELEM:
57 return "ELEM";
58 case WASM_SEC_CODE:
59 return "CODE";
60 case WASM_SEC_DATA:
61 return "DATA";
Thomas Lively84771e22019-04-19 23:40:3662 case WASM_SEC_DATACOUNT:
63 return "DATACOUNT";
Sam Cleggc94d3932017-11-17 18:14:0964 default:
65 fatal("invalid section type");
66 }
67}
68
Rui Ueyama22c8f332018-02-28 17:33:0469StringRef OutputSection::getSectionName() const {
Rui Ueyama136d27a2019-07-11 05:40:3070 return sectionTypeToString(type);
Sam Clegg0d0dd392017-12-19 17:09:4571}
72
Rui Ueyama136d27a2019-07-11 05:40:3073void OutputSection::createHeader(size_t bodySize) {
74 raw_string_ostream os(header);
75 debugWrite(os.tell(), "section type [" + getSectionName() + "]");
76 encodeULEB128(type, os);
77 writeUleb128(os, bodySize, "section size");
78 os.flush();
79 log("createHeader: " + toString(*this) + " body=" + Twine(bodySize) +
Sam Cleggc94d3932017-11-17 18:14:0980 " total=" + Twine(getSize()));
81}
82
Sam Cleggd029bf02019-05-16 21:36:0683void CodeSection::finalizeContents() {
Rui Ueyama136d27a2019-07-11 05:40:3084 raw_string_ostream os(codeSectionHeader);
85 writeUleb128(os, functions.size(), "function count");
86 os.flush();
87 bodySize = codeSectionHeader.size();
Sam Cleggc94d3932017-11-17 18:14:0988
Rui Ueyama136d27a2019-07-11 05:40:3089 for (InputFunction *func : functions) {
90 func->outputOffset = bodySize;
91 func->calculateSize();
92 bodySize += func->getSize();
Sam Cleggc94d3932017-11-17 18:14:0993 }
94
Rui Ueyama136d27a2019-07-11 05:40:3095 createHeader(bodySize);
Sam Cleggc94d3932017-11-17 18:14:0996}
97
Rui Ueyama136d27a2019-07-11 05:40:3098void CodeSection::writeTo(uint8_t *buf) {
Sam Cleggab2ac292017-12-20 05:14:4899 log("writing " + toString(*this));
Sam Cleggc94d3932017-11-17 18:14:09100 log(" size=" + Twine(getSize()));
Rui Ueyama136d27a2019-07-11 05:40:30101 log(" headersize=" + Twine(header.size()));
102 log(" codeheadersize=" + Twine(codeSectionHeader.size()));
103 buf += offset;
Sam Cleggc94d3932017-11-17 18:14:09104
105 // Write section header
Rui Ueyama136d27a2019-07-11 05:40:30106 memcpy(buf, header.data(), header.size());
107 buf += header.size();
Sam Cleggc94d3932017-11-17 18:14:09108
Sam Cleggc94d3932017-11-17 18:14:09109 // Write code section headers
Rui Ueyama136d27a2019-07-11 05:40:30110 memcpy(buf, codeSectionHeader.data(), codeSectionHeader.size());
Sam Cleggc94d3932017-11-17 18:14:09111
112 // Write code section bodies
Rui Ueyama136d27a2019-07-11 05:40:30113 for (const InputChunk *chunk : functions)
114 chunk->writeTo(buf);
Sam Cleggc94d3932017-11-17 18:14:09115}
116
Rui Ueyama7e296ad2019-07-10 09:10:01117uint32_t CodeSection::getNumRelocations() const {
Rui Ueyama136d27a2019-07-11 05:40:30118 uint32_t count = 0;
119 for (const InputChunk *func : functions)
120 count += func->getNumRelocations();
121 return count;
Sam Cleggc94d3932017-11-17 18:14:09122}
123
Rui Ueyama136d27a2019-07-11 05:40:30124void CodeSection::writeRelocations(raw_ostream &os) const {
125 for (const InputChunk *c : functions)
126 c->writeRelocations(os);
Sam Cleggc94d3932017-11-17 18:14:09127}
128
Sam Cleggd029bf02019-05-16 21:36:06129void DataSection::finalizeContents() {
Rui Ueyama136d27a2019-07-11 05:40:30130 raw_string_ostream os(dataSectionHeader);
Thomas Lively190dacc2019-10-15 19:05:11131 unsigned segmentCount =
132 std::count_if(segments.begin(), segments.end(),
133 [](OutputSegment *segment) { return !segment->isBss; });
Sam Cleggc94d3932017-11-17 18:14:09134
Thomas Lively190dacc2019-10-15 19:05:11135 writeUleb128(os, segmentCount, "data segment count");
Rui Ueyama136d27a2019-07-11 05:40:30136 os.flush();
137 bodySize = dataSectionHeader.size();
Sam Cleggc94d3932017-11-17 18:14:09138
Rui Ueyama136d27a2019-07-11 05:40:30139 assert((!config->isPic || segments.size() <= 1) &&
Bill Wendling858e3512019-07-08 22:05:02140 "Currenly only a single data segment is supported in PIC mode");
Thomas Lively6004d9a2019-07-03 22:04:54141
Rui Ueyama136d27a2019-07-11 05:40:30142 for (OutputSegment *segment : segments) {
Thomas Lively190dacc2019-10-15 19:05:11143 if (segment->isBss)
144 continue;
Rui Ueyama136d27a2019-07-11 05:40:30145 raw_string_ostream os(segment->header);
146 writeUleb128(os, segment->initFlags, "init flags");
147 if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX)
148 writeUleb128(os, 0, "memory index");
149 if ((segment->initFlags & WASM_SEGMENT_IS_PASSIVE) == 0) {
150 WasmInitExpr initExpr;
151 if (config->isPic) {
152 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
153 initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex();
Thomas Lively6004d9a2019-07-03 22:04:54154 } else {
Wouter van Oortmerssen582fd472020-08-07 20:24:43155 // FIXME(wvo): I64?
Rui Ueyama136d27a2019-07-11 05:40:30156 initExpr.Opcode = WASM_OPCODE_I32_CONST;
157 initExpr.Value.Int32 = segment->startVA;
Thomas Lively6004d9a2019-07-03 22:04:54158 }
Rui Ueyama136d27a2019-07-11 05:40:30159 writeInitExpr(os, initExpr);
Sam Cleggbfb75342018-11-15 00:37:21160 }
Rui Ueyama136d27a2019-07-11 05:40:30161 writeUleb128(os, segment->size, "segment size");
162 os.flush();
Rui Ueyamaac95bb12018-04-05 19:37:31163
Rui Ueyama136d27a2019-07-11 05:40:30164 segment->sectionOffset = bodySize;
165 bodySize += segment->header.size() + segment->size;
166 log("Data segment: size=" + Twine(segment->size) + ", startVA=" +
167 Twine::utohexstr(segment->startVA) + ", name=" + segment->name);
Rui Ueyamaac95bb12018-04-05 19:37:31168
Rui Ueyama136d27a2019-07-11 05:40:30169 for (InputSegment *inputSeg : segment->inputSegments)
170 inputSeg->outputOffset = segment->sectionOffset + segment->header.size() +
171 inputSeg->outputSegmentOffset;
Sam Cleggc94d3932017-11-17 18:14:09172 }
173
Rui Ueyama136d27a2019-07-11 05:40:30174 createHeader(bodySize);
Sam Cleggc94d3932017-11-17 18:14:09175}
176
Rui Ueyama136d27a2019-07-11 05:40:30177void DataSection::writeTo(uint8_t *buf) {
Sam Cleggab2ac292017-12-20 05:14:48178 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Rui Ueyama136d27a2019-07-11 05:40:30179 " body=" + Twine(bodySize));
180 buf += offset;
Sam Cleggc94d3932017-11-17 18:14:09181
182 // Write section header
Rui Ueyama136d27a2019-07-11 05:40:30183 memcpy(buf, header.data(), header.size());
184 buf += header.size();
Sam Cleggc94d3932017-11-17 18:14:09185
Sam Cleggc94d3932017-11-17 18:14:09186 // Write data section headers
Rui Ueyama136d27a2019-07-11 05:40:30187 memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size());
Sam Cleggc94d3932017-11-17 18:14:09188
Rui Ueyama136d27a2019-07-11 05:40:30189 for (const OutputSegment *segment : segments) {
Thomas Lively190dacc2019-10-15 19:05:11190 if (segment->isBss)
191 continue;
Sam Cleggc94d3932017-11-17 18:14:09192 // Write data segment header
Rui Ueyama136d27a2019-07-11 05:40:30193 uint8_t *segStart = buf + segment->sectionOffset;
194 memcpy(segStart, segment->header.data(), segment->header.size());
Sam Cleggc94d3932017-11-17 18:14:09195
196 // Write segment data payload
Rui Ueyama136d27a2019-07-11 05:40:30197 for (const InputChunk *chunk : segment->inputSegments)
198 chunk->writeTo(buf);
Rui Ueyama5081e412019-04-17 02:12:47199 }
Sam Clegg5e8cba92017-12-19 20:45:15200}
Sam Cleggc94d3932017-11-17 18:14:09201
Rui Ueyama7e296ad2019-07-10 09:10:01202uint32_t DataSection::getNumRelocations() const {
Rui Ueyama136d27a2019-07-11 05:40:30203 uint32_t count = 0;
204 for (const OutputSegment *seg : segments)
205 for (const InputChunk *inputSeg : seg->inputSegments)
206 count += inputSeg->getNumRelocations();
207 return count;
Sam Cleggc94d3932017-11-17 18:14:09208}
209
Rui Ueyama136d27a2019-07-11 05:40:30210void DataSection::writeRelocations(raw_ostream &os) const {
211 for (const OutputSegment *seg : segments)
212 for (const InputChunk *c : seg->inputSegments)
213 c->writeRelocations(os);
Sam Cleggc94d3932017-11-17 18:14:09214}
Sam Clegg80ba4382018-04-10 16:12:49215
Thomas Lively190dacc2019-10-15 19:05:11216bool DataSection::isNeeded() const {
217 for (const OutputSegment *seg : segments)
218 if (!seg->isBss)
219 return true;
220 return false;
221}
222
Sam Cleggd029bf02019-05-16 21:36:06223void CustomSection::finalizeContents() {
Rui Ueyama136d27a2019-07-11 05:40:30224 raw_string_ostream os(nameData);
225 encodeULEB128(name.size(), os);
226 os << name;
227 os.flush();
Sam Clegg80ba4382018-04-10 16:12:49228
Rui Ueyama136d27a2019-07-11 05:40:30229 for (InputSection *section : inputSections) {
230 section->outputOffset = payloadSize;
231 section->outputSec = this;
232 payloadSize += section->getSize();
Sam Clegg80ba4382018-04-10 16:12:49233 }
234
Rui Ueyama136d27a2019-07-11 05:40:30235 createHeader(payloadSize + nameData.size());
Sam Clegg80ba4382018-04-10 16:12:49236}
237
Rui Ueyama136d27a2019-07-11 05:40:30238void CustomSection::writeTo(uint8_t *buf) {
Sam Clegg80ba4382018-04-10 16:12:49239 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Rui Ueyama136d27a2019-07-11 05:40:30240 " chunks=" + Twine(inputSections.size()));
Sam Clegg80ba4382018-04-10 16:12:49241
Rui Ueyama136d27a2019-07-11 05:40:30242 assert(offset);
243 buf += offset;
Sam Clegg80ba4382018-04-10 16:12:49244
245 // Write section header
Rui Ueyama136d27a2019-07-11 05:40:30246 memcpy(buf, header.data(), header.size());
247 buf += header.size();
248 memcpy(buf, nameData.data(), nameData.size());
249 buf += nameData.size();
Sam Clegg80ba4382018-04-10 16:12:49250
251 // Write custom sections payload
Rui Ueyama136d27a2019-07-11 05:40:30252 for (const InputSection *section : inputSections)
253 section->writeTo(buf);
Sam Clegg80ba4382018-04-10 16:12:49254}
Sam Cleggd177ab22018-05-04 23:14:42255
Rui Ueyama7e296ad2019-07-10 09:10:01256uint32_t CustomSection::getNumRelocations() const {
Rui Ueyama136d27a2019-07-11 05:40:30257 uint32_t count = 0;
258 for (const InputSection *inputSect : inputSections)
259 count += inputSect->getNumRelocations();
260 return count;
Sam Cleggd177ab22018-05-04 23:14:42261}
262
Rui Ueyama136d27a2019-07-11 05:40:30263void CustomSection::writeRelocations(raw_ostream &os) const {
264 for (const InputSection *s : inputSections)
265 s->writeRelocations(os);
Sam Cleggd177ab22018-05-04 23:14:42266}
Fangrui Song33c59ab2019-10-10 05:25:39267
268} // namespace wasm
269} // namespace lld