Coverage Report

Created: 2018-01-17 17:22

/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
//                             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
12
#include "InputChunks.h"
13
#include "InputFiles.h"
14
#include "OutputSegment.h"
15
#include "lld/Common/ErrorHandler.h"
16
#include "lld/Common/Threads.h"
17
#include "llvm/ADT/Twine.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
0
static StringRef sectionTypeToString(uint32_t SectionType) {
27
0
  switch (SectionType) {
28
0
  case WASM_SEC_CUSTOM:
29
0
    return "CUSTOM";
30
0
  case WASM_SEC_TYPE:
31
0
    return "TYPE";
32
0
  case WASM_SEC_IMPORT:
33
0
    return "IMPORT";
34
0
  case WASM_SEC_FUNCTION:
35
0
    return "FUNCTION";
36
0
  case WASM_SEC_TABLE:
37
0
    return "TABLE";
38
0
  case WASM_SEC_MEMORY:
39
0
    return "MEMORY";
40
0
  case WASM_SEC_GLOBAL:
41
0
    return "GLOBAL";
42
0
  case WASM_SEC_EXPORT:
43
0
    return "EXPORT";
44
0
  case WASM_SEC_START:
45
0
    return "START";
46
0
  case WASM_SEC_ELEM:
47
0
    return "ELEM";
48
0
  case WASM_SEC_CODE:
49
0
    return "CODE";
50
0
  case WASM_SEC_DATA:
51
0
    return "DATA";
52
0
  default:
53
0
    fatal("invalid section type");
54
0
  }
55
0
}
56
57
0
std::string lld::toString(const OutputSection &Section) {
58
0
  std::string rtn = Section.getSectionName();
59
0
  if (!Section.Name.empty())
60
0
    rtn += "(" + Section.Name + ")";
61
0
  return rtn;
62
0
}
63
64
0
std::string OutputSection::getSectionName() const {
65
0
  return sectionTypeToString(Type);
66
0
}
67
68
0
std::string SubSection::getSectionName() const {
69
0
  return std::string("subsection <type=") + std::to_string(Type) + ">";
70
0
}
71
72
0
void OutputSection::createHeader(size_t BodySize) {
73
0
  raw_string_ostream OS(Header);
74
0
  debugWrite(OS.tell(), "section type [" + Twine(getSectionName()) + "]");
75
0
  writeUleb128(OS, Type, nullptr);
76
0
  writeUleb128(OS, BodySize, "section size");
77
0
  OS.flush();
78
0
  log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) +
79
0
      " total=" + Twine(getSize()));
80
0
}
81
82
CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
83
0
    : OutputSection(WASM_SEC_CODE), Functions(Functions) {
84
0
  assert(Functions.size() > 0);
85
0
86
0
  raw_string_ostream OS(CodeSectionHeader);
87
0
  writeUleb128(OS, Functions.size(), "function count");
88
0
  OS.flush();
89
0
  BodySize = CodeSectionHeader.size();
90
0
91
0
  for (InputChunk *Func : Functions) {
92
0
    Func->setOutputOffset(BodySize);
93
0
    BodySize += Func->getSize();
94
0
  }
95
0
96
0
  createHeader(BodySize);
97
0
}
98
99
0
void CodeSection::writeTo(uint8_t *Buf) {
100
0
  log("writing " + toString(*this));
101
0
  log(" size=" + Twine(getSize()));
102
0
  log(" headersize=" + Twine(Header.size()));
103
0
  log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
104
0
  Buf += Offset;
105
0
106
0
  // Write section header
107
0
  memcpy(Buf, Header.data(), Header.size());
108
0
  Buf += Header.size();
109
0
110
0
  uint8_t *ContentsStart = Buf;
111
0
112
0
  // Write code section headers
113
0
  memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
114
0
  Buf += CodeSectionHeader.size();
115
0
116
0
  // Write code section bodies
117
0
  parallelForEach(Functions, [ContentsStart](const InputChunk *Chunk) {
118
0
    Chunk->writeTo(ContentsStart);
119
0
  });
120
0
}
121
122
0
uint32_t CodeSection::numRelocations() const {
123
0
  uint32_t Count = 0;
124
0
  for (const InputChunk *Func : Functions)
125
0
    Count += Func->OutRelocations.size();
126
0
  return Count;
127
0
}
128
129
0
void CodeSection::writeRelocations(raw_ostream &OS) const {
130
0
  for (const InputChunk *Func : Functions)
131
0
    for (const OutputRelocation &Reloc : Func->OutRelocations)
132
0
      writeReloc(OS, Reloc);
133
0
}
134
135
DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
136
0
    : OutputSection(WASM_SEC_DATA), Segments(Segments) {
137
0
  raw_string_ostream OS(DataSectionHeader);
138
0
139
0
  writeUleb128(OS, Segments.size(), "data segment count");
140
0
  OS.flush();
141
0
  BodySize = DataSectionHeader.size();
142
0
143
0
  for (OutputSegment *Segment : Segments) {
144
0
    raw_string_ostream OS(Segment->Header);
145
0
    writeUleb128(OS, 0, "memory index");
146
0
    writeUleb128(OS, WASM_OPCODE_I32_CONST, "opcode:i32const");
147
0
    writeSleb128(OS, Segment->StartVA, "memory offset");
148
0
    writeUleb128(OS, WASM_OPCODE_END, "opcode:end");
149
0
    writeUleb128(OS, Segment->Size, "segment size");
150
0
    OS.flush();
151
0
    Segment->setSectionOffset(BodySize);
152
0
    BodySize += Segment->Header.size() + Segment->Size;
153
0
    log("Data segment: size=" + Twine(Segment->Size));
154
0
    for (InputSegment *InputSeg : Segment->InputSegments)
155
0
      InputSeg->setOutputOffset(Segment->getSectionOffset() +
156
0
                                Segment->Header.size() +
157
0
                                InputSeg->OutputSegmentOffset);
158
0
  }
159
0
160
0
  createHeader(BodySize);
161
0
}
162
163
0
void DataSection::writeTo(uint8_t *Buf) {
164
0
  log("writing " + toString(*this) + " size=" + Twine(getSize()) +
165
0
      " body=" + Twine(BodySize));
166
0
  Buf += Offset;
167
0
168
0
  // Write section header
169
0
  memcpy(Buf, Header.data(), Header.size());
170
0
  Buf += Header.size();
171
0
172
0
  uint8_t *ContentsStart = Buf;
173
0
174
0
  // Write data section headers
175
0
  memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
176
0
177
0
  parallelForEach(Segments, [ContentsStart](const OutputSegment *Segment) {
178
0
    // Write data segment header
179
0
    uint8_t *SegStart = ContentsStart + Segment->getSectionOffset();
180
0
    memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
181
0
182
0
    // Write segment data payload
183
0
    for (const InputChunk *Chunk : Segment->InputSegments)
184
0
      Chunk->writeTo(ContentsStart);
185
0
  });
186
0
}
187
188
0
uint32_t DataSection::numRelocations() const {
189
0
  uint32_t Count = 0;
190
0
  for (const OutputSegment *Seg : Segments)
191
0
    for (const InputChunk *InputSeg : Seg->InputSegments)
192
0
      Count += InputSeg->OutRelocations.size();
193
0
  return Count;
194
0
}
195
196
0
void DataSection::writeRelocations(raw_ostream &OS) const {
197
0
  for (const OutputSegment *Seg : Segments)
198
0
    for (const InputChunk *InputSeg : Seg->InputSegments)
199
0
      for (const OutputRelocation &Reloc : InputSeg->OutRelocations)
200
0
        writeReloc(OS, Reloc);
201
0
}