Coverage Report

Created: 2019-05-22 02:55

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