blob: b34a2c06c188b6c7652429b1c47c5f3eb9256e44 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- OutputSections.cpp -------------------------------------------------===//
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#include "OutputSections.h"
11
Sam Clegg5fa274b2018-01-10 01:13:34 +000012#include "InputChunks.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000013#include "InputFiles.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000014#include "OutputSegment.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "lld/Common/ErrorHandler.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000016#include "lld/Common/Threads.h"
17#include "llvm/ADT/Twine.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";
42 case WASM_SEC_EXPORT:
43 return "EXPORT";
44 case WASM_SEC_START:
45 return "START";
46 case WASM_SEC_ELEM:
47 return "ELEM";
48 case WASM_SEC_CODE:
49 return "CODE";
50 case WASM_SEC_DATA:
51 return "DATA";
52 default:
53 fatal("invalid section type");
54 }
55}
56
Sam Cleggab2ac292017-12-20 05:14:48 +000057std::string lld::toString(const OutputSection &Section) {
58 std::string rtn = Section.getSectionName();
59 if (!Section.Name.empty())
60 rtn += "(" + Section.Name + ")";
Sam Cleggc94d3932017-11-17 18:14:09 +000061 return rtn;
62}
63
Sam Cleggab2ac292017-12-20 05:14:48 +000064std::string OutputSection::getSectionName() const {
Sam Clegg0d0dd392017-12-19 17:09:45 +000065 return sectionTypeToString(Type);
66}
67
Sam Cleggab2ac292017-12-20 05:14:48 +000068std::string SubSection::getSectionName() const {
Sam Clegg0d0dd392017-12-19 17:09:45 +000069 return std::string("subsection <type=") + std::to_string(Type) + ">";
70}
71
Sam Cleggc94d3932017-11-17 18:14:09 +000072void OutputSection::createHeader(size_t BodySize) {
73 raw_string_ostream OS(Header);
Sam Clegg0d0dd392017-12-19 17:09:45 +000074 debugWrite(OS.tell(), "section type [" + Twine(getSectionName()) + "]");
Sam Cleggc94d3932017-11-17 18:14:09 +000075 writeUleb128(OS, Type, nullptr);
76 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 Clegg5fa274b2018-01-10 01:13:34 +000091 for (InputChunk *Func : Functions) {
Sam Cleggd96d9352018-01-10 19:22:42 +000092 Func->setOutputOffset(BodySize);
Sam Clegg5fa274b2018-01-10 01:13:34 +000093 BodySize += Func->getSize();
Sam Cleggc94d3932017-11-17 18:14:09 +000094 }
95
96 createHeader(BodySize);
97}
98
99void CodeSection::writeTo(uint8_t *Buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +0000100 log("writing " + toString(*this));
Sam Cleggc94d3932017-11-17 18:14:09 +0000101 log(" size=" + Twine(getSize()));
Sam Clegg8d146bb2018-01-09 23:56:44 +0000102 log(" headersize=" + Twine(Header.size()));
103 log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
Sam Cleggc94d3932017-11-17 18:14:09 +0000104 Buf += Offset;
105
106 // Write section header
107 memcpy(Buf, Header.data(), Header.size());
108 Buf += Header.size();
109
110 uint8_t *ContentsStart = Buf;
111
112 // Write code section headers
113 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
114 Buf += CodeSectionHeader.size();
115
116 // Write code section bodies
Sam Cleggd96d9352018-01-10 19:22:42 +0000117 parallelForEach(Functions, [ContentsStart](const InputChunk *Chunk) {
118 Chunk->writeTo(ContentsStart);
Sam Cleggc94d3932017-11-17 18:14:09 +0000119 });
120}
121
122uint32_t CodeSection::numRelocations() const {
123 uint32_t Count = 0;
Sam Clegg5fa274b2018-01-10 01:13:34 +0000124 for (const InputChunk *Func : Functions)
Sam Clegg8d146bb2018-01-09 23:56:44 +0000125 Count += Func->OutRelocations.size();
Sam Cleggc94d3932017-11-17 18:14:09 +0000126 return Count;
127}
128
129void CodeSection::writeRelocations(raw_ostream &OS) const {
Sam Clegg5fa274b2018-01-10 01:13:34 +0000130 for (const InputChunk *Func : Functions)
Sam Clegg8d146bb2018-01-09 23:56:44 +0000131 for (const OutputRelocation &Reloc : Func->OutRelocations)
Sam Cleggc94d3932017-11-17 18:14:09 +0000132 writeReloc(OS, Reloc);
133}
134
Sam Clegg0fb6faa2017-12-08 01:09:21 +0000135DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
Sam Cleggc94d3932017-11-17 18:14:09 +0000136 : OutputSection(WASM_SEC_DATA), Segments(Segments) {
137 raw_string_ostream OS(DataSectionHeader);
138
139 writeUleb128(OS, Segments.size(), "data segment count");
140 OS.flush();
141 BodySize = DataSectionHeader.size();
142
143 for (OutputSegment *Segment : Segments) {
144 raw_string_ostream OS(Segment->Header);
145 writeUleb128(OS, 0, "memory index");
146 writeUleb128(OS, WASM_OPCODE_I32_CONST, "opcode:i32const");
147 writeSleb128(OS, Segment->StartVA, "memory offset");
148 writeUleb128(OS, WASM_OPCODE_END, "opcode:end");
149 writeUleb128(OS, Segment->Size, "segment size");
150 OS.flush();
151 Segment->setSectionOffset(BodySize);
Sam Cleggd96d9352018-01-10 19:22:42 +0000152 BodySize += Segment->Header.size() + Segment->Size;
Sam Cleggc94d3932017-11-17 18:14:09 +0000153 log("Data segment: size=" + Twine(Segment->Size));
Sam Cleggd96d9352018-01-10 19:22:42 +0000154 for (InputSegment *InputSeg : Segment->InputSegments)
155 InputSeg->setOutputOffset(Segment->getSectionOffset() +
156 Segment->Header.size() +
157 InputSeg->OutputSegmentOffset);
Sam Cleggc94d3932017-11-17 18:14:09 +0000158 }
159
160 createHeader(BodySize);
161}
162
163void DataSection::writeTo(uint8_t *Buf) {
Sam Cleggab2ac292017-12-20 05:14:48 +0000164 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
Sam Cleggc94d3932017-11-17 18:14:09 +0000165 " body=" + Twine(BodySize));
166 Buf += Offset;
167
168 // Write section header
169 memcpy(Buf, Header.data(), Header.size());
170 Buf += Header.size();
171
172 uint8_t *ContentsStart = Buf;
173
174 // Write data section headers
175 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
176
177 parallelForEach(Segments, [ContentsStart](const OutputSegment *Segment) {
178 // Write data segment header
179 uint8_t *SegStart = ContentsStart + Segment->getSectionOffset();
180 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
181
182 // Write segment data payload
Sam Cleggd96d9352018-01-10 19:22:42 +0000183 for (const InputChunk *Chunk : Segment->InputSegments)
184 Chunk->writeTo(ContentsStart);
Sam Cleggc94d3932017-11-17 18:14:09 +0000185 });
Sam Clegg5e8cba92017-12-19 20:45:15 +0000186}
Sam Cleggc94d3932017-11-17 18:14:09 +0000187
Sam Clegg5e8cba92017-12-19 20:45:15 +0000188uint32_t DataSection::numRelocations() const {
189 uint32_t Count = 0;
190 for (const OutputSegment *Seg : Segments)
Sam Clegg5fa274b2018-01-10 01:13:34 +0000191 for (const InputChunk *InputSeg : Seg->InputSegments)
Sam Clegg5e8cba92017-12-19 20:45:15 +0000192 Count += InputSeg->OutRelocations.size();
193 return Count;
Sam Cleggc94d3932017-11-17 18:14:09 +0000194}
195
196void DataSection::writeRelocations(raw_ostream &OS) const {
Sam Clegg5e8cba92017-12-19 20:45:15 +0000197 for (const OutputSegment *Seg : Segments)
Sam Clegg5fa274b2018-01-10 01:13:34 +0000198 for (const InputChunk *InputSeg : Seg->InputSegments)
Sam Clegg5e8cba92017-12-19 20:45:15 +0000199 for (const OutputRelocation &Reloc : InputSeg->OutRelocations)
200 writeReloc(OS, Reloc);
Sam Cleggc94d3932017-11-17 18:14:09 +0000201}