Coverage Report

Created: 2019-07-24 05:18

/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
7.13k
static StringRef sectionTypeToString(uint32_t sectionType) {
27
7.13k
  switch (sectionType) {
28
7.13k
  case WASM_SEC_CUSTOM:
29
1.21k
    return "CUSTOM";
30
7.13k
  case WASM_SEC_TYPE:
31
735
    return "TYPE";
32
7.13k
  case WASM_SEC_IMPORT:
33
150
    return "IMPORT";
34
7.13k
  case WASM_SEC_FUNCTION:
35
735
    return "FUNCTION";
36
7.13k
  case WASM_SEC_TABLE:
37
830
    return "TABLE";
38
7.13k
  case WASM_SEC_MEMORY:
39
830
    return "MEMORY";
40
7.13k
  case WASM_SEC_GLOBAL:
41
755
    return "GLOBAL";
42
7.13k
  case WASM_SEC_EVENT:
43
5
    return "EVENT";
44
7.13k
  case WASM_SEC_EXPORT:
45
760
    return "EXPORT";
46
7.13k
  case WASM_SEC_START:
47
0
    return "START";
48
7.13k
  case WASM_SEC_ELEM:
49
120
    return "ELEM";
50
7.13k
  case WASM_SEC_CODE:
51
735
    return "CODE";
52
7.13k
  case WASM_SEC_DATA:
53
230
    return "DATA";
54
7.13k
  case WASM_SEC_DATACOUNT:
55
40
    return "DATACOUNT";
56
7.13k
  default:
57
0
    fatal("invalid section type");
58
7.13k
  }
59
7.13k
}
60
61
// Returns a string, e.g. "FUNCTION(.text)".
62
5.70k
std::string lld::toString(const OutputSection &sec) {
63
5.70k
  if (!sec.name.empty())
64
968
    return (sec.getSectionName() + "(" + sec.name + ")").str();
65
4.74k
  return sec.getSectionName();
66
4.74k
}
67
68
7.13k
StringRef OutputSection::getSectionName() const {
69
7.13k
  return sectionTypeToString(type);
70
7.13k
}
71
72
1.42k
void OutputSection::createHeader(size_t bodySize) {
73
1.42k
  raw_string_ostream os(header);
74
1.42k
  debugWrite(os.tell(), "section type [" + getSectionName() + "]");
75
1.42k
  encodeULEB128(type, os);
76
1.42k
  writeUleb128(os, bodySize, "section size");
77
1.42k
  os.flush();
78
1.42k
  log("createHeader: " + toString(*this) + " body=" + Twine(bodySize) +
79
1.42k
      " total=" + Twine(getSize()));
80
1.42k
}
81
82
147
void CodeSection::finalizeContents() {
83
147
  raw_string_ostream os(codeSectionHeader);
84
147
  writeUleb128(os, functions.size(), "function count");
85
147
  os.flush();
86
147
  bodySize = codeSectionHeader.size();
87
147
88
533
  for (InputFunction *func : functions) {
89
533
    func->outputOffset = bodySize;
90
533
    func->calculateSize();
91
533
    bodySize += func->getSize();
92
533
  }
93
147
94
147
  createHeader(bodySize);
95
147
}
96
97
147
void CodeSection::writeTo(uint8_t *buf) {
98
147
  log("writing " + toString(*this));
99
147
  log(" size=" + Twine(getSize()));
100
147
  log(" headersize=" + Twine(header.size()));
101
147
  log(" codeheadersize=" + Twine(codeSectionHeader.size()));
102
147
  buf += offset;
103
147
104
147
  // Write section header
105
147
  memcpy(buf, header.data(), header.size());
106
147
  buf += header.size();
107
147
108
147
  // Write code section headers
109
147
  memcpy(buf, codeSectionHeader.data(), codeSectionHeader.size());
110
147
111
147
  // Write code section bodies
112
147
  for (const InputChunk *chunk : functions)
113
533
    chunk->writeTo(buf);
114
147
}
115
116
47
uint32_t CodeSection::getNumRelocations() const {
117
47
  uint32_t count = 0;
118
47
  for (const InputChunk *func : functions)
119
596
    count += func->getNumRelocations();
120
47
  return count;
121
47
}
122
123
13
void CodeSection::writeRelocations(raw_ostream &os) const {
124
13
  for (const InputChunk *c : functions)
125
194
    c->writeRelocations(os);
126
13
}
127
128
46
void DataSection::finalizeContents() {
129
46
  raw_string_ostream os(dataSectionHeader);
130
46
131
46
  writeUleb128(os, segments.size(), "data segment count");
132
46
  os.flush();
133
46
  bodySize = dataSectionHeader.size();
134
46
135
46
  assert((!config->isPic || segments.size() <= 1) &&
136
46
         "Currenly only a single data segment is supported in PIC mode");
137
46
138
95
  for (OutputSegment *segment : segments) {
139
95
    raw_string_ostream os(segment->header);
140
95
    writeUleb128(os, segment->initFlags, "init flags");
141
95
    if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX)
142
0
      writeUleb128(os, 0, "memory index");
143
95
    if ((segment->initFlags & WASM_SEGMENT_IS_PASSIVE) == 0) {
144
72
      WasmInitExpr initExpr;
145
72
      if (config->isPic) {
146
4
        initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
147
4
        initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex();
148
68
      } else {
149
68
        initExpr.Opcode = WASM_OPCODE_I32_CONST;
150
68
        initExpr.Value.Int32 = segment->startVA;
151
68
      }
152
72
      writeInitExpr(os, initExpr);
153
72
    }
154
95
    writeUleb128(os, segment->size, "segment size");
155
95
    os.flush();
156
95
157
95
    segment->sectionOffset = bodySize;
158
95
    bodySize += segment->header.size() + segment->size;
159
95
    log("Data segment: size=" + Twine(segment->size) + ", startVA=" +
160
95
        Twine::utohexstr(segment->startVA) + ", name=" + segment->name);
161
95
162
95
    for (InputSegment *inputSeg : segment->inputSegments)
163
161
      inputSeg->outputOffset = segment->sectionOffset + segment->header.size() +
164
161
                               inputSeg->outputSegmentOffset;
165
95
  }
166
46
167
46
  createHeader(bodySize);
168
46
}
169
170
46
void DataSection::writeTo(uint8_t *buf) {
171
46
  log("writing " + toString(*this) + " size=" + Twine(getSize()) +
172
46
      " body=" + Twine(bodySize));
173
46
  buf += offset;
174
46
175
46
  // Write section header
176
46
  memcpy(buf, header.data(), header.size());
177
46
  buf += header.size();
178
46
179
46
  // Write data section headers
180
46
  memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size());
181
46
182
95
  for (const OutputSegment *segment : segments) {
183
95
    // Write data segment header
184
95
    uint8_t *segStart = buf + segment->sectionOffset;
185
95
    memcpy(segStart, segment->header.data(), segment->header.size());
186
95
187
95
    // Write segment data payload
188
95
    for (const InputChunk *chunk : segment->inputSegments)
189
161
      chunk->writeTo(buf);
190
95
  }
191
46
}
192
193
12
uint32_t DataSection::getNumRelocations() const {
194
12
  uint32_t count = 0;
195
12
  for (const OutputSegment *seg : segments)
196
48
    for (const InputChunk *inputSeg : seg->inputSegments)
197
51
      count += inputSeg->getNumRelocations();
198
12
  return count;
199
12
}
200
201
3
void DataSection::writeRelocations(raw_ostream &os) const {
202
3
  for (const OutputSegment *seg : segments)
203
14
    for (const InputChunk *c : seg->inputSegments)
204
14
      c->writeRelocations(os);
205
3
}
206
207
22
void CustomSection::finalizeContents() {
208
22
  raw_string_ostream os(nameData);
209
22
  encodeULEB128(name.size(), os);
210
22
  os << name;
211
22
  os.flush();
212
22
213
34
  for (InputSection *section : inputSections) {
214
34
    section->outputOffset = payloadSize;
215
34
    section->outputSec = this;
216
34
    payloadSize += section->getSize();
217
34
  }
218
22
219
22
  createHeader(payloadSize + nameData.size());
220
22
}
221
222
22
void CustomSection::writeTo(uint8_t *buf) {
223
22
  log("writing " + toString(*this) + " size=" + Twine(getSize()) +
224
22
      " chunks=" + Twine(inputSections.size()));
225
22
226
22
  assert(offset);
227
22
  buf += offset;
228
22
229
22
  // Write section header
230
22
  memcpy(buf, header.data(), header.size());
231
22
  buf += header.size();
232
22
  memcpy(buf, nameData.data(), nameData.size());
233
22
  buf += nameData.size();
234
22
235
22
  // Write custom sections payload
236
22
  for (const InputSection *section : inputSections)
237
34
    section->writeTo(buf);
238
22
}
239
240
6
uint32_t CustomSection::getNumRelocations() const {
241
6
  uint32_t count = 0;
242
6
  for (const InputSection *inputSect : inputSections)
243
11
    count += inputSect->getNumRelocations();
244
6
  return count;
245
6
}
246
247
1
void CustomSection::writeRelocations(raw_ostream &os) const {
248
1
  for (const InputSection *s : inputSections)
249
2
    s->writeRelocations(os);
250
1
}