Bug Summary

File:tools/lld/wasm/OutputSections.cpp
Warning:line 237, column 3
Value stored to 'Buf' is never read

Annotated Source Code

[?] Use j/k keys for keyboard navigation

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 "Config.h"
13#include "InputFiles.h"
14#include "OutputSegment.h"
15#include "SymbolTable.h"
16#include "lld/Common/ErrorHandler.h"
17#include "lld/Common/Memory.h"
18#include "lld/Common/Threads.h"
19#include "llvm/ADT/Twine.h"
20#include "llvm/Support/LEB128.h"
21
22#define DEBUG_TYPE"lld" "lld"
23
24using namespace llvm;
25using namespace llvm::wasm;
26using namespace lld;
27using namespace lld::wasm;
28
29enum class RelocEncoding {
30 Uleb128,
31 Sleb128,
32 I32,
33};
34
35static StringRef sectionTypeToString(uint32_t SectionType) {
36 switch (SectionType) {
37 case WASM_SEC_CUSTOM:
38 return "CUSTOM";
39 case WASM_SEC_TYPE:
40 return "TYPE";
41 case WASM_SEC_IMPORT:
42 return "IMPORT";
43 case WASM_SEC_FUNCTION:
44 return "FUNCTION";
45 case WASM_SEC_TABLE:
46 return "TABLE";
47 case WASM_SEC_MEMORY:
48 return "MEMORY";
49 case WASM_SEC_GLOBAL:
50 return "GLOBAL";
51 case WASM_SEC_EXPORT:
52 return "EXPORT";
53 case WASM_SEC_START:
54 return "START";
55 case WASM_SEC_ELEM:
56 return "ELEM";
57 case WASM_SEC_CODE:
58 return "CODE";
59 case WASM_SEC_DATA:
60 return "DATA";
61 default:
62 fatal("invalid section type");
63 }
64}
65
66std::string lld::toString(const OutputSection &Section) {
67 std::string rtn = Section.getSectionName();
68 if (!Section.Name.empty())
69 rtn += "(" + Section.Name + ")";
70 return rtn;
71}
72
73static void applyRelocation(uint8_t *Buf, const OutputRelocation &Reloc) {
74 DEBUG(dbgs() << "write reloc: type=" << Reloc.Reloc.Typedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "write reloc: type=" << Reloc
.Reloc.Type << " index=" << Reloc.Reloc.Index <<
" value=" << Reloc.Value << " offset=" << Reloc
.Reloc.Offset << "\n"; } } while (false)
75 << " index=" << Reloc.Reloc.Index << " value=" << Reloc.Valuedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "write reloc: type=" << Reloc
.Reloc.Type << " index=" << Reloc.Reloc.Index <<
" value=" << Reloc.Value << " offset=" << Reloc
.Reloc.Offset << "\n"; } } while (false)
76 << " offset=" << Reloc.Reloc.Offset << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "write reloc: type=" << Reloc
.Reloc.Type << " index=" << Reloc.Reloc.Index <<
" value=" << Reloc.Value << " offset=" << Reloc
.Reloc.Offset << "\n"; } } while (false)
;
77 Buf += Reloc.Reloc.Offset;
78 int64_t ExistingValue;
79 switch (Reloc.Reloc.Type) {
80 case R_WEBASSEMBLY_TYPE_INDEX_LEB:
81 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
82 ExistingValue = decodeULEB128(Buf);
83 if (ExistingValue != Reloc.Reloc.Index) {
84 DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "existing value: " << decodeULEB128
(Buf) << "\n"; } } while (false)
;
85 assert(decodeULEB128(Buf) == Reloc.Reloc.Index)(static_cast <bool> (decodeULEB128(Buf) == Reloc.Reloc.
Index) ? void (0) : __assert_fail ("decodeULEB128(Buf) == Reloc.Reloc.Index"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/lld/wasm/OutputSections.cpp"
, 85, __extension__ __PRETTY_FUNCTION__))
;
86 }
87 LLVM_FALLTHROUGH[[clang::fallthrough]];
88 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
89 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
90 encodeULEB128(Reloc.Value, Buf, 5);
91 break;
92 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
93 ExistingValue = decodeSLEB128(Buf);
94 if (ExistingValue != Reloc.Reloc.Index) {
95 DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "existing value: " << decodeSLEB128
(Buf) << "\n"; } } while (false)
;
96 assert(decodeSLEB128(Buf) == Reloc.Reloc.Index)(static_cast <bool> (decodeSLEB128(Buf) == Reloc.Reloc.
Index) ? void (0) : __assert_fail ("decodeSLEB128(Buf) == Reloc.Reloc.Index"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/lld/wasm/OutputSections.cpp"
, 96, __extension__ __PRETTY_FUNCTION__))
;
97 }
98 LLVM_FALLTHROUGH[[clang::fallthrough]];
99 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
100 encodeSLEB128(static_cast<int32_t>(Reloc.Value), Buf, 5);
101 break;
102 case R_WEBASSEMBLY_TABLE_INDEX_I32:
103 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
104 support::endian::write32<support::little>(Buf, Reloc.Value);
105 break;
106 default:
107 llvm_unreachable("unknown relocation type")::llvm::llvm_unreachable_internal("unknown relocation type", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/lld/wasm/OutputSections.cpp"
, 107)
;
108 }
109}
110
111static void applyRelocations(uint8_t *Buf, ArrayRef<OutputRelocation> Relocs) {
112 if (!Relocs.size())
113 return;
114 log("applyRelocations: count=" + Twine(Relocs.size()));
115 for (const OutputRelocation &Reloc : Relocs)
116 applyRelocation(Buf, Reloc);
117}
118
119// Relocations contain an index into the function, global or table index
120// space of the input file. This function takes a relocation and returns the
121// relocated index (i.e. translates from the input index space to the output
122// index space).
123static uint32_t calcNewIndex(const ObjFile &File, const WasmRelocation &Reloc) {
124 switch (Reloc.Type) {
125 case R_WEBASSEMBLY_TYPE_INDEX_LEB:
126 return File.relocateTypeIndex(Reloc.Index);
127 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
128 return File.relocateFunctionIndex(Reloc.Index);
129 case R_WEBASSEMBLY_TABLE_INDEX_I32:
130 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
131 return File.relocateTableIndex(Reloc.Index);
132 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
133 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
134 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
135 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
136 return File.relocateGlobalIndex(Reloc.Index);
137 default:
138 llvm_unreachable("unknown relocation type")::llvm::llvm_unreachable_internal("unknown relocation type", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/lld/wasm/OutputSections.cpp"
, 138)
;
139 }
140}
141
142// Take a vector of relocations from an input file and create output
143// relocations based on them. Calculates the updated index and offset for
144// each relocation as well as the value to write out in the final binary.
145static void calcRelocations(const ObjFile &File,
146 ArrayRef<WasmRelocation> Relocs,
147 std::vector<OutputRelocation> &OutputRelocs,
148 int32_t OutputOffset) {
149 log("calcRelocations: " + File.getName() + " offset=" + Twine(OutputOffset));
150 for (const WasmRelocation &Reloc : Relocs) {
151 OutputRelocation NewReloc;
152 NewReloc.Reloc = Reloc;
153 NewReloc.Reloc.Offset += OutputOffset;
154 DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Indexdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "reloc: type=" << Reloc.Type
<< " index=" << Reloc.Index << " offset=" <<
Reloc.Offset << " newOffset=" << NewReloc.Reloc.
Offset << "\n"; } } while (false)
155 << " offset=" << Reloc.Offsetdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "reloc: type=" << Reloc.Type
<< " index=" << Reloc.Index << " offset=" <<
Reloc.Offset << " newOffset=" << NewReloc.Reloc.
Offset << "\n"; } } while (false)
156 << " newOffset=" << NewReloc.Reloc.Offset << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("lld")) { dbgs() << "reloc: type=" << Reloc.Type
<< " index=" << Reloc.Index << " offset=" <<
Reloc.Offset << " newOffset=" << NewReloc.Reloc.
Offset << "\n"; } } while (false)
;
157
158 if (Config->EmitRelocs)
159 NewReloc.NewIndex = calcNewIndex(File, Reloc);
160 else
161 NewReloc.NewIndex = UINT32_MAX(4294967295U);
162
163 switch (Reloc.Type) {
164 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
165 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
166 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
167 NewReloc.Value = File.getRelocatedAddress(Reloc.Index);
168 if (NewReloc.Value != UINT32_MAX(4294967295U))
169 NewReloc.Value += Reloc.Addend;
170 break;
171 default:
172 NewReloc.Value = calcNewIndex(File, Reloc);
173 break;
174 }
175
176 OutputRelocs.emplace_back(NewReloc);
177 }
178}
179
180std::string OutputSection::getSectionName() const {
181 return sectionTypeToString(Type);
182}
183
184std::string SubSection::getSectionName() const {
185 return std::string("subsection <type=") + std::to_string(Type) + ">";
186}
187
188void OutputSection::createHeader(size_t BodySize) {
189 raw_string_ostream OS(Header);
190 debugWrite(OS.tell(), "section type [" + Twine(getSectionName()) + "]");
191 writeUleb128(OS, Type, nullptr);
192 writeUleb128(OS, BodySize, "section size");
193 OS.flush();
194 log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) +
195 " total=" + Twine(getSize()));
196}
197
198CodeSection::CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs)
199 : OutputSection(WASM_SEC_CODE), InputObjects(Objs) {
200 raw_string_ostream OS(CodeSectionHeader);
201 writeUleb128(OS, NumFunctions, "function count");
202 OS.flush();
203 BodySize = CodeSectionHeader.size();
204
205 for (ObjFile *File : InputObjects) {
206 if (!File->CodeSection)
207 continue;
208
209 File->CodeOffset = BodySize;
210 ArrayRef<uint8_t> Content = File->CodeSection->Content;
211 unsigned HeaderSize = 0;
212 decodeULEB128(Content.data(), &HeaderSize);
213
214 calcRelocations(*File, File->CodeSection->Relocations,
215 File->CodeRelocations, BodySize - HeaderSize);
216
217 size_t PayloadSize = Content.size() - HeaderSize;
218 BodySize += PayloadSize;
219 }
220
221 createHeader(BodySize);
222}
223
224void CodeSection::writeTo(uint8_t *Buf) {
225 log("writing " + toString(*this));
226 log(" size=" + Twine(getSize()));
227 Buf += Offset;
228
229 // Write section header
230 memcpy(Buf, Header.data(), Header.size());
231 Buf += Header.size();
232
233 uint8_t *ContentsStart = Buf;
234
235 // Write code section headers
236 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());
237 Buf += CodeSectionHeader.size();
Value stored to 'Buf' is never read
238
239 // Write code section bodies
240 parallelForEach(InputObjects, [ContentsStart](ObjFile *File) {
241 if (!File->CodeSection)
242 return;
243
244 ArrayRef<uint8_t> Content(File->CodeSection->Content);
245
246 // Payload doesn't include the initial header (function count)
247 unsigned HeaderSize = 0;
248 decodeULEB128(Content.data(), &HeaderSize);
249
250 size_t PayloadSize = Content.size() - HeaderSize;
251 memcpy(ContentsStart + File->CodeOffset, Content.data() + HeaderSize,
252 PayloadSize);
253
254 log("applying relocations for: " + File->getName());
255 applyRelocations(ContentsStart, File->CodeRelocations);
256 });
257}
258
259uint32_t CodeSection::numRelocations() const {
260 uint32_t Count = 0;
261 for (ObjFile *File : InputObjects)
262 Count += File->CodeRelocations.size();
263 return Count;
264}
265
266void CodeSection::writeRelocations(raw_ostream &OS) const {
267 for (ObjFile *File : InputObjects)
268 for (const OutputRelocation &Reloc : File->CodeRelocations)
269 writeReloc(OS, Reloc);
270}
271
272DataSection::DataSection(ArrayRef<OutputSegment *> Segments)
273 : OutputSection(WASM_SEC_DATA), Segments(Segments) {
274 raw_string_ostream OS(DataSectionHeader);
275
276 writeUleb128(OS, Segments.size(), "data segment count");
277 OS.flush();
278 BodySize = DataSectionHeader.size();
279
280 for (OutputSegment *Segment : Segments) {
281 raw_string_ostream OS(Segment->Header);
282 writeUleb128(OS, 0, "memory index");
283 writeUleb128(OS, WASM_OPCODE_I32_CONST, "opcode:i32const");
284 writeSleb128(OS, Segment->StartVA, "memory offset");
285 writeUleb128(OS, WASM_OPCODE_END, "opcode:end");
286 writeUleb128(OS, Segment->Size, "segment size");
287 OS.flush();
288 Segment->setSectionOffset(BodySize);
289 BodySize += Segment->Header.size();
290 log("Data segment: size=" + Twine(Segment->Size));
291 for (InputSegment *InputSeg : Segment->InputSegments) {
292 uint32_t InputOffset = InputSeg->getInputSectionOffset();
293 uint32_t OutputOffset = Segment->getSectionOffset() +
294 Segment->Header.size() +
295 InputSeg->getOutputSegmentOffset();
296 calcRelocations(*InputSeg->File, InputSeg->Relocations,
297 InputSeg->OutRelocations, OutputOffset - InputOffset);
298 }
299 BodySize += Segment->Size;
300 }
301
302 createHeader(BodySize);
303}
304
305void DataSection::writeTo(uint8_t *Buf) {
306 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
307 " body=" + Twine(BodySize));
308 Buf += Offset;
309
310 // Write section header
311 memcpy(Buf, Header.data(), Header.size());
312 Buf += Header.size();
313
314 uint8_t *ContentsStart = Buf;
315
316 // Write data section headers
317 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());
318
319 parallelForEach(Segments, [ContentsStart](const OutputSegment *Segment) {
320 // Write data segment header
321 uint8_t *SegStart = ContentsStart + Segment->getSectionOffset();
322 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());
323
324 // Write segment data payload
325 for (const InputSegment *Input : Segment->InputSegments) {
326 ArrayRef<uint8_t> Content(Input->Segment->Data.Content);
327 memcpy(SegStart + Segment->Header.size() +
328 Input->getOutputSegmentOffset(),
329 Content.data(), Content.size());
330 applyRelocations(ContentsStart, Input->OutRelocations);
331 }
332 });
333}
334
335uint32_t DataSection::numRelocations() const {
336 uint32_t Count = 0;
337 for (const OutputSegment *Seg : Segments)
338 for (const InputSegment *InputSeg : Seg->InputSegments)
339 Count += InputSeg->OutRelocations.size();
340 return Count;
341}
342
343void DataSection::writeRelocations(raw_ostream &OS) const {
344 for (const OutputSegment *Seg : Segments)
345 for (const InputSegment *InputSeg : Seg->InputSegments)
346 for (const OutputRelocation &Reloc : InputSeg->OutRelocations)
347 writeReloc(OS, Reloc);
348}