Coverage Report

Created: 2019-01-21 03:01

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/OutputSections.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- OutputSections.cpp -------------------------------------------------===//
2
//
3
// 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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "OutputSections.h"
10
#include "InputChunks.h"
11
#include "InputFiles.h"
12
#include "OutputSegment.h"
13
#include "WriterUtils.h"
14
#include "lld/Common/ErrorHandler.h"
15
#include "lld/Common/Threads.h"
16
#include "llvm/ADT/Twine.h"
17
#include "llvm/Support/LEB128.h"
18
19
#define DEBUG_TYPE "lld"
20
21
using namespace llvm;
22
using namespace llvm::wasm;
23
using namespace lld;
24
using namespace lld::wasm;
25
26
4.38k
static StringRef sectionTypeToString(uint32_t SectionType) {
27
4.38k
  switch (SectionType) {
28
4.38k
  case WASM_SEC_CUSTOM:
29
726
    return "CUSTOM";
30
4.38k
  case WASM_SEC_TYPE:
31
529
    return "TYPE";
32
4.38k
  case WASM_SEC_IMPORT:
33
100
    return "IMPORT";
34
4.38k
  case WASM_SEC_FUNCTION:
35
524
    return "FUNCTION";
36
4.38k
  case WASM_SEC_TABLE:
37
519
    return "TABLE";
38
4.38k
  case WASM_SEC_MEMORY:
39
514
    return "MEMORY";
40
4.38k
  case WASM_SEC_GLOBAL:
41
444
    return "GLOBAL";
42
4.38k
  case WASM_SEC_EVENT:
43
5
    return "EVENT";
44
4.38k
  case WASM_SEC_EXPORT:
45
444
    return "EXPORT";
46
4.38k
  case WASM_SEC_START:
47
0
    return "START";
48
4.38k
  case WASM_SEC_ELEM:
49
75
    return "ELEM";
50
4.38k
  case WASM_SEC_CODE:
51
419
    return "CODE";
52
4.38k
  case WASM_SEC_DATA:
53
92
    return "DATA";
54
4.38k
  default:
55
0
    fatal("invalid section type");
56
4.38k
  }
57
4.38k
}
58
59
// Returns a string, e.g. "FUNCTION(.text)".
60
3.48k
std::string lld::toString(const OutputSection &Sec) {
61
3.48k
  if (!Sec.Name.empty())
62
577
    return (Sec.getSectionName() + "(" + Sec.Name + ")").str();
63
2.90k
  return Sec.getSectionName();
64
2.90k
}
65
66
4.38k
StringRef OutputSection::getSectionName() const {
67
4.38k
  return sectionTypeToString(Type);
68
4.38k
}
69
70
909
void OutputSection::createHeader(size_t BodySize) {
71
909
  raw_string_ostream OS(Header);
72
909
  debugWrite(OS.tell(), "section type [" + getSectionName() + "]");
73
909
  encodeULEB128(Type, OS);
74
909
  writeUleb128(OS, BodySize, "section size");
75
909
  OS.flush();
76
909
  log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) +
77
909
      " total=" + Twine(getSize()));
78
909
}
79
80
CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
81
105
    : OutputSection(WASM_SEC_CODE), Functions(Functions) {
82
105
  assert(Functions.size() > 0);
83
105
84
105
  raw_string_ostream OS(CodeSectionHeader);
85
105
  writeUleb128(OS, Functions.size(), "function count");
86
105
  OS.flush();
87
105
  BodySize = CodeSectionHeader.size();
88
105
89
494
  for (InputFunction *Func : Functions) {
90
494
    Func->OutputOffset = BodySize;
91
494
    Func->calculateSize();
92
494
    BodySize += Func->getSize();
93
494
  }
94
105
95
105
  createHeader(BodySize);
96
105
}
97
98
104
void CodeSection::writeTo(uint8_t *Buf) {
99
104
  log("writing " + toString(*this));
100
104
  log(" size=" + Twine(getSize()));
101
104
  log(" headersize=" + Twine(Header.size()));
102
104
  log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
103
104
  Buf += Offset;
104
104
105
104
  // Write section header
106
104
  memcpy(Buf, Header.data(), Header.size());
107
104
  Buf += Header.size();
108
104
109
104
  // Write code section headers
110
104
  memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
111
104
112
104
  // Write code section bodies
113
104
  parallelForEach(Functions,
114
492
                  [&](const InputChunk *Chunk) { Chunk->writeTo(Buf); });
115
104
}
116
117
16
uint32_t CodeSection::numRelocations() const {
118
16
  uint32_t Count = 0;
119
16
  for (const InputChunk *Func : Functions)
120
197
    Count += Func->NumRelocations();
121
16
  return Count;
122
16
}
123
124
9
void CodeSection::writeRelocations(raw_ostream &OS) const {
125
9
  for (const InputChunk *C : Functions)
126
184
    C->writeRelocations(OS);
127
9
}
128
129
DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
130
23
    : OutputSection(WASM_SEC_DATA), Segments(Segments) {
131
23
  raw_string_ostream OS(DataSectionHeader);
132
23
133
23
  writeUleb128(OS, Segments.size(), "data segment count");
134
23
  OS.flush();
135
23
  BodySize = DataSectionHeader.size();
136
23
137
49
  for (OutputSegment *Segment : Segments) {
138
49
    raw_string_ostream OS(Segment->Header);
139
49
    writeUleb128(OS, 0, "memory index");
140
49
    WasmInitExpr InitExpr;
141
49
    if (Config->Pic) {
142
1
      assert(Segments.size() <= 1 &&
143
1
             "Currenly only a single data segment is supported in PIC mode");
144
1
      InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
145
1
      InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex();
146
48
    } else {
147
48
      InitExpr.Opcode = WASM_OPCODE_I32_CONST;
148
48
      InitExpr.Value.Int32 = Segment->StartVA;
149
48
    }
150
49
    writeInitExpr(OS, InitExpr);
151
49
    writeUleb128(OS, Segment->Size, "segment size");
152
49
    OS.flush();
153
49
154
49
    Segment->SectionOffset = BodySize;
155
49
    BodySize += Segment->Header.size() + Segment->Size;
156
49
    log("Data segment: size=" + Twine(Segment->Size));
157
49
158
49
    for (InputSegment *InputSeg : Segment->InputSegments)
159
78
      InputSeg->OutputOffset = Segment->SectionOffset + Segment->Header.size() +
160
78
                               InputSeg->OutputSegmentOffset;
161
49
  }
162
23
163
23
  createHeader(BodySize);
164
23
}
165
166
23
void DataSection::writeTo(uint8_t *Buf) {
167
23
  log("writing " + toString(*this) + " size=" + Twine(getSize()) +
168
23
      " body=" + Twine(BodySize));
169
23
  Buf += Offset;
170
23
171
23
  // Write section header
172
23
  memcpy(Buf, Header.data(), Header.size());
173
23
  Buf += Header.size();
174
23
175
23
  // Write data section headers
176
23
  memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
177
23
178
49
  parallelForEach(Segments, [&](const OutputSegment *Segment) {
179
49
    // Write data segment header
180
49
    uint8_t *SegStart = Buf + Segment->SectionOffset;
181
49
    memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
182
49
183
49
    // Write segment data payload
184
49
    for (const InputChunk *Chunk : Segment->InputSegments)
185
78
      Chunk->writeTo(Buf);
186
49
  });
187
23
}
188
189
5
uint32_t DataSection::numRelocations() const {
190
5
  uint32_t Count = 0;
191
5
  for (const OutputSegment *Seg : Segments)
192
19
    for (const InputChunk *InputSeg : Seg->InputSegments)
193
22
      Count += InputSeg->NumRelocations();
194
5
  return Count;
195
5
}
196
197
3
void DataSection::writeRelocations(raw_ostream &OS) const {
198
3
  for (const OutputSegment *Seg : Segments)
199
14
    for (const InputChunk *C : Seg->InputSegments)
200
14
      C->writeRelocations(OS);
201
3
}
202
203
CustomSection::CustomSection(std::string Name,
204
                             ArrayRef<InputSection *> InputSections)
205
    : OutputSection(WASM_SEC_CUSTOM, Name), PayloadSize(0),
206
18
      InputSections(InputSections) {
207
18
  raw_string_ostream OS(NameData);
208
18
  encodeULEB128(Name.size(), OS);
209
18
  OS << Name;
210
18
  OS.flush();
211
18
212
26
  for (InputSection *Section : InputSections) {
213
26
    Section->OutputOffset = PayloadSize;
214
26
    PayloadSize += Section->getSize();
215
26
  }
216
18
217
18
  createHeader(PayloadSize + NameData.size());
218
18
}
219
220
18
void CustomSection::writeTo(uint8_t *Buf) {
221
18
  log("writing " + toString(*this) + " size=" + Twine(getSize()) +
222
18
      " chunks=" + Twine(InputSections.size()));
223
18
224
18
  assert(Offset);
225
18
  Buf += Offset;
226
18
227
18
  // Write section header
228
18
  memcpy(Buf, Header.data(), Header.size());
229
18
  Buf += Header.size();
230
18
  memcpy(Buf, NameData.data(), NameData.size());
231
18
  Buf += NameData.size();
232
18
233
18
  // Write custom sections payload
234
18
  parallelForEach(InputSections,
235
26
                  [&](const InputSection *Section) { Section->writeTo(Buf); });
236
18
}
237
238
2
uint32_t CustomSection::numRelocations() const {
239
2
  uint32_t Count = 0;
240
2
  for (const InputSection *InputSect : InputSections)
241
3
    Count += InputSect->NumRelocations();
242
2
  return Count;
243
2
}
244
245
0
void CustomSection::writeRelocations(raw_ostream &OS) const {
246
0
  for (const InputSection *S : InputSections)
247
0
    S->writeRelocations(OS);
248
0
}