blob: 469a51a0f06857239b4c31d7259b1d82e17026a1 [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;
Sam Cleggc94d3932017-11-17 18:14:09 +000023
Fangrui Song33c59ab2019-10-10 05:25:39 +000024namespace 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();
30 return sec.getSectionName();
31}
32
33namespace wasm {
Rui Ueyama136d27a2019-07-11 05:40:30 +000034static StringRef sectionTypeToString(uint32_t sectionType) {
35 switch (sectionType) {
Sam Cleggc94d3932017-11-17 18:14:09 +000036 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:43 +000050 case WASM_SEC_EVENT:
51 return "EVENT";
Sam Cleggc94d3932017-11-17 18:14:09 +000052 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:36 +000062 case WASM_SEC_DATACOUNT:
63 return "DATACOUNT";
Sam Cleggc94d3932017-11-17 18:14:09 +000064 default:
65 fatal("invalid section type");
66 }
67}
68
Rui Ueyama22c8f332018-02-28 17:33:04 +000069StringRef OutputSection::getSectionName() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +000070 return sectionTypeToString(type);
Sam Clegg0d0dd392017-12-19 17:09:45 +000071}
72
Rui Ueyama136d27a2019-07-11 05:40:30 +000073void 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:09 +000080 " total=" + Twine(getSize()));
81}
82
Sam Cleggd029bf02019-05-16 21:36:06 +000083void CodeSection::finalizeContents() {
Rui Ueyama136d27a2019-07-11 05:40:30 +000084 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:09 +000088
Rui Ueyama136d27a2019-07-11 05:40:30 +000089 for (InputFunction *func : functions) {
90 func->outputOffset = bodySize;
91 func->calculateSize();
92 bodySize += func->getSize();
Sam Cleggc94d3932017-11-17 18:14:09 +000093 }
94
Rui Ueyama136d27a2019-07-11 05:40:30 +000095 createHeader(bodySize);
Sam Cleggc94d3932017-11-17 18:14:09 +000096}
97
Rui Ueyama136d27a2019-07-11 05:40:30 +000098void 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()));
Rui Ueyama136d27a2019-07-11 05:40:30 +0000101 log(" headersize=" + Twine(header.size()));
102 log(" codeheadersize=" + Twine(codeSectionHeader.size()));
103 buf += offset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000104
105 // Write section header
Rui Ueyama136d27a2019-07-11 05:40:30 +0000106 memcpy(buf, header.data(), header.size());
107 buf += header.size();
Sam Cleggc94d3932017-11-17 18:14:09 +0000108
Sam Cleggc94d3932017-11-17 18:14:09 +0000109 // Write code section headers
Rui Ueyama136d27a2019-07-11 05:40:30 +0000110 memcpy(buf, codeSectionHeader.data(), codeSectionHeader.size());
Sam Cleggc94d3932017-11-17 18:14:09 +0000111
112 // Write code section bodies
Rui Ueyama136d27a2019-07-11 05:40:30 +0000113 for (const InputChunk *chunk : functions)
114 chunk->writeTo(buf);
Sam Cleggc94d3932017-11-17 18:14:09 +0000115}
116
Rui Ueyama7e296ad2019-07-10 09:10:01 +0000117uint32_t CodeSection::getNumRelocations() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000118 uint32_t count = 0;
119 for (const InputChunk *func : functions)
120 count += func->getNumRelocations();
121 return count;
Sam Cleggc94d3932017-11-17 18:14:09 +0000122}
123
Rui Ueyama136d27a2019-07-11 05:40:30 +0000124void CodeSection::writeRelocations(raw_ostream &os) const {
125 for (const InputChunk *c : functions)
126 c->writeRelocations(os);
Sam Cleggc94d3932017-11-17 18:14:09 +0000127}
128
Sam Cleggd029bf02019-05-16 21:36:06 +0000129void DataSection::finalizeContents() {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000130 raw_string_ostream os(dataSectionHeader);
Sam Cleggc94d3932017-11-17 18:14:09 +0000131
Rui Ueyama136d27a2019-07-11 05:40:30 +0000132 writeUleb128(os, segments.size(), "data segment count");
133 os.flush();
134 bodySize = dataSectionHeader.size();
Sam Cleggc94d3932017-11-17 18:14:09 +0000135
Rui Ueyama136d27a2019-07-11 05:40:30 +0000136 assert((!config->isPic || segments.size() <= 1) &&
Bill Wendling858e3512019-07-08 22:05:02 +0000137 "Currenly only a single data segment is supported in PIC mode");
Thomas Lively6004d9a2019-07-03 22:04:54 +0000138
Rui Ueyama136d27a2019-07-11 05:40:30 +0000139 for (OutputSegment *segment : segments) {
140 raw_string_ostream os(segment->header);
141 writeUleb128(os, segment->initFlags, "init flags");
142 if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX)
143 writeUleb128(os, 0, "memory index");
144 if ((segment->initFlags & WASM_SEGMENT_IS_PASSIVE) == 0) {
145 WasmInitExpr initExpr;
146 if (config->isPic) {
147 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
148 initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex();
Thomas Lively6004d9a2019-07-03 22:04:54 +0000149 } else {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000150 initExpr.Opcode = WASM_OPCODE_I32_CONST;
151 initExpr.Value.Int32 = segment->startVA;
Thomas Lively6004d9a2019-07-03 22:04:54 +0000152 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000153 writeInitExpr(os, initExpr);
Sam Cleggbfb75342018-11-15 00:37:21 +0000154 }
Rui Ueyama136d27a2019-07-11 05:40:30 +0000155 writeUleb128(os, segment->size, "segment size");
156 os.flush();
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000157
Rui Ueyama136d27a2019-07-11 05:40:30 +0000158 segment->sectionOffset = bodySize;
159 bodySize += segment->header.size() + segment->size;
160 log("Data segment: size=" + Twine(segment->size) + ", startVA=" +
161 Twine::utohexstr(segment->startVA) + ", name=" + segment->name);
Rui Ueyamaac95bb12018-04-05 19:37:31 +0000162
Rui Ueyama136d27a2019-07-11 05:40:30 +0000163 for (InputSegment *inputSeg : segment->inputSegments)
164 inputSeg->outputOffset = segment->sectionOffset + segment->header.size() +
165 inputSeg->outputSegmentOffset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000166 }
167
Rui Ueyama136d27a2019-07-11 05:40:30 +0000168 createHeader(bodySize);
Sam Cleggc94d3932017-11-17 18:14:09 +0000169}
170
Rui Ueyama136d27a2019-07-11 05:40:30 +0000171void DataSection::writeTo(uint8_t *buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +0000172 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Rui Ueyama136d27a2019-07-11 05:40:30 +0000173 " body=" + Twine(bodySize));
174 buf += offset;
Sam Cleggc94d3932017-11-17 18:14:09 +0000175
176 // Write section header
Rui Ueyama136d27a2019-07-11 05:40:30 +0000177 memcpy(buf, header.data(), header.size());
178 buf += header.size();
Sam Cleggc94d3932017-11-17 18:14:09 +0000179
Sam Cleggc94d3932017-11-17 18:14:09 +0000180 // Write data section headers
Rui Ueyama136d27a2019-07-11 05:40:30 +0000181 memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size());
Sam Cleggc94d3932017-11-17 18:14:09 +0000182
Rui Ueyama136d27a2019-07-11 05:40:30 +0000183 for (const OutputSegment *segment : segments) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000184 // Write data segment header
Rui Ueyama136d27a2019-07-11 05:40:30 +0000185 uint8_t *segStart = buf + segment->sectionOffset;
186 memcpy(segStart, segment->header.data(), segment->header.size());
Sam Cleggc94d3932017-11-17 18:14:09 +0000187
188 // Write segment data payload
Rui Ueyama136d27a2019-07-11 05:40:30 +0000189 for (const InputChunk *chunk : segment->inputSegments)
190 chunk->writeTo(buf);
Rui Ueyama5081e412019-04-17 02:12:47 +0000191 }
Sam Clegg5e8cba92017-12-19 20:45:15 +0000192}
Sam Cleggc94d3932017-11-17 18:14:09 +0000193
Rui Ueyama7e296ad2019-07-10 09:10:01 +0000194uint32_t DataSection::getNumRelocations() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000195 uint32_t count = 0;
196 for (const OutputSegment *seg : segments)
197 for (const InputChunk *inputSeg : seg->inputSegments)
198 count += inputSeg->getNumRelocations();
199 return count;
Sam Cleggc94d3932017-11-17 18:14:09 +0000200}
201
Rui Ueyama136d27a2019-07-11 05:40:30 +0000202void DataSection::writeRelocations(raw_ostream &os) const {
203 for (const OutputSegment *seg : segments)
204 for (const InputChunk *c : seg->inputSegments)
205 c->writeRelocations(os);
Sam Cleggc94d3932017-11-17 18:14:09 +0000206}
Sam Clegg80ba4382018-04-10 16:12:49 +0000207
Sam Cleggd029bf02019-05-16 21:36:06 +0000208void CustomSection::finalizeContents() {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000209 raw_string_ostream os(nameData);
210 encodeULEB128(name.size(), os);
211 os << name;
212 os.flush();
Sam Clegg80ba4382018-04-10 16:12:49 +0000213
Rui Ueyama136d27a2019-07-11 05:40:30 +0000214 for (InputSection *section : inputSections) {
215 section->outputOffset = payloadSize;
216 section->outputSec = this;
217 payloadSize += section->getSize();
Sam Clegg80ba4382018-04-10 16:12:49 +0000218 }
219
Rui Ueyama136d27a2019-07-11 05:40:30 +0000220 createHeader(payloadSize + nameData.size());
Sam Clegg80ba4382018-04-10 16:12:49 +0000221}
222
Rui Ueyama136d27a2019-07-11 05:40:30 +0000223void CustomSection::writeTo(uint8_t *buf) {
Sam Clegg80ba4382018-04-10 16:12:49 +0000224 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Rui Ueyama136d27a2019-07-11 05:40:30 +0000225 " chunks=" + Twine(inputSections.size()));
Sam Clegg80ba4382018-04-10 16:12:49 +0000226
Rui Ueyama136d27a2019-07-11 05:40:30 +0000227 assert(offset);
228 buf += offset;
Sam Clegg80ba4382018-04-10 16:12:49 +0000229
230 // Write section header
Rui Ueyama136d27a2019-07-11 05:40:30 +0000231 memcpy(buf, header.data(), header.size());
232 buf += header.size();
233 memcpy(buf, nameData.data(), nameData.size());
234 buf += nameData.size();
Sam Clegg80ba4382018-04-10 16:12:49 +0000235
236 // Write custom sections payload
Rui Ueyama136d27a2019-07-11 05:40:30 +0000237 for (const InputSection *section : inputSections)
238 section->writeTo(buf);
Sam Clegg80ba4382018-04-10 16:12:49 +0000239}
Sam Cleggd177ab22018-05-04 23:14:42 +0000240
Rui Ueyama7e296ad2019-07-10 09:10:01 +0000241uint32_t CustomSection::getNumRelocations() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000242 uint32_t count = 0;
243 for (const InputSection *inputSect : inputSections)
244 count += inputSect->getNumRelocations();
245 return count;
Sam Cleggd177ab22018-05-04 23:14:42 +0000246}
247
Rui Ueyama136d27a2019-07-11 05:40:30 +0000248void CustomSection::writeRelocations(raw_ostream &os) const {
249 for (const InputSection *s : inputSections)
250 s->writeRelocations(os);
Sam Cleggd177ab22018-05-04 23:14:42 +0000251}
Fangrui Song33c59ab2019-10-10 05:25:39 +0000252
253} // namespace wasm
254} // namespace lld