annotate lld/wasm/InputFiles.cpp @ 213:25ca0248ac32

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 11 Jul 2021 17:05:31 +0900
parents 2e18cbf3894f
children 5f17cb93ff66
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===- InputFiles.cpp -----------------------------------------------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "InputFiles.h"
anatofuz
parents:
diff changeset
10 #include "Config.h"
anatofuz
parents:
diff changeset
11 #include "InputChunks.h"
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
12 #include "InputElement.h"
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
13 #include "OutputSegment.h"
150
anatofuz
parents:
diff changeset
14 #include "SymbolTable.h"
anatofuz
parents:
diff changeset
15 #include "lld/Common/ErrorHandler.h"
anatofuz
parents:
diff changeset
16 #include "lld/Common/Memory.h"
anatofuz
parents:
diff changeset
17 #include "lld/Common/Reproduce.h"
anatofuz
parents:
diff changeset
18 #include "llvm/Object/Binary.h"
anatofuz
parents:
diff changeset
19 #include "llvm/Object/Wasm.h"
anatofuz
parents:
diff changeset
20 #include "llvm/Support/TarWriter.h"
anatofuz
parents:
diff changeset
21 #include "llvm/Support/raw_ostream.h"
anatofuz
parents:
diff changeset
22
anatofuz
parents:
diff changeset
23 #define DEBUG_TYPE "lld"
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 using namespace llvm;
anatofuz
parents:
diff changeset
26 using namespace llvm::object;
anatofuz
parents:
diff changeset
27 using namespace llvm::wasm;
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 namespace lld {
anatofuz
parents:
diff changeset
30
anatofuz
parents:
diff changeset
31 // Returns a string in the format of "foo.o" or "foo.a(bar.o)".
anatofuz
parents:
diff changeset
32 std::string toString(const wasm::InputFile *file) {
anatofuz
parents:
diff changeset
33 if (!file)
anatofuz
parents:
diff changeset
34 return "<internal>";
anatofuz
parents:
diff changeset
35
anatofuz
parents:
diff changeset
36 if (file->archiveName.empty())
anatofuz
parents:
diff changeset
37 return std::string(file->getName());
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 return (file->archiveName + "(" + file->getName() + ")").str();
anatofuz
parents:
diff changeset
40 }
anatofuz
parents:
diff changeset
41
anatofuz
parents:
diff changeset
42 namespace wasm {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
43
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
44 void InputFile::checkArch(Triple::ArchType arch) const {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
45 bool is64 = arch == Triple::wasm64;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
46 if (is64 && !config->is64.hasValue()) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
47 fatal(toString(this) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
48 ": must specify -mwasm64 to process wasm64 object files");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
49 } else if (config->is64.getValueOr(false) != is64) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
50 fatal(toString(this) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
51 ": wasm32 object file can't be linked in wasm64 mode");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
52 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
53 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
54
150
anatofuz
parents:
diff changeset
55 std::unique_ptr<llvm::TarWriter> tar;
anatofuz
parents:
diff changeset
56
anatofuz
parents:
diff changeset
57 Optional<MemoryBufferRef> readFile(StringRef path) {
anatofuz
parents:
diff changeset
58 log("Loading: " + path);
anatofuz
parents:
diff changeset
59
anatofuz
parents:
diff changeset
60 auto mbOrErr = MemoryBuffer::getFile(path);
anatofuz
parents:
diff changeset
61 if (auto ec = mbOrErr.getError()) {
anatofuz
parents:
diff changeset
62 error("cannot open " + path + ": " + ec.message());
anatofuz
parents:
diff changeset
63 return None;
anatofuz
parents:
diff changeset
64 }
anatofuz
parents:
diff changeset
65 std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
anatofuz
parents:
diff changeset
66 MemoryBufferRef mbref = mb->getMemBufferRef();
anatofuz
parents:
diff changeset
67 make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take MB ownership
anatofuz
parents:
diff changeset
68
anatofuz
parents:
diff changeset
69 if (tar)
anatofuz
parents:
diff changeset
70 tar->append(relativeToRoot(path), mbref.getBuffer());
anatofuz
parents:
diff changeset
71 return mbref;
anatofuz
parents:
diff changeset
72 }
anatofuz
parents:
diff changeset
73
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
74 InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName) {
150
anatofuz
parents:
diff changeset
75 file_magic magic = identify_magic(mb.getBuffer());
anatofuz
parents:
diff changeset
76 if (magic == file_magic::wasm_object) {
anatofuz
parents:
diff changeset
77 std::unique_ptr<Binary> bin =
anatofuz
parents:
diff changeset
78 CHECK(createBinary(mb), mb.getBufferIdentifier());
anatofuz
parents:
diff changeset
79 auto *obj = cast<WasmObjectFile>(bin.get());
anatofuz
parents:
diff changeset
80 if (obj->isSharedObject())
anatofuz
parents:
diff changeset
81 return make<SharedFile>(mb);
anatofuz
parents:
diff changeset
82 return make<ObjFile>(mb, archiveName);
anatofuz
parents:
diff changeset
83 }
anatofuz
parents:
diff changeset
84
anatofuz
parents:
diff changeset
85 if (magic == file_magic::bitcode)
anatofuz
parents:
diff changeset
86 return make<BitcodeFile>(mb, archiveName);
anatofuz
parents:
diff changeset
87
anatofuz
parents:
diff changeset
88 fatal("unknown file type: " + mb.getBufferIdentifier());
anatofuz
parents:
diff changeset
89 }
anatofuz
parents:
diff changeset
90
anatofuz
parents:
diff changeset
91 void ObjFile::dumpInfo() const {
anatofuz
parents:
diff changeset
92 log("info for: " + toString(this) +
anatofuz
parents:
diff changeset
93 "\n Symbols : " + Twine(symbols.size()) +
anatofuz
parents:
diff changeset
94 "\n Function Imports : " + Twine(wasmObj->getNumImportedFunctions()) +
anatofuz
parents:
diff changeset
95 "\n Global Imports : " + Twine(wasmObj->getNumImportedGlobals()) +
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
96 "\n Event Imports : " + Twine(wasmObj->getNumImportedEvents()) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
97 "\n Table Imports : " + Twine(wasmObj->getNumImportedTables()));
150
anatofuz
parents:
diff changeset
98 }
anatofuz
parents:
diff changeset
99
anatofuz
parents:
diff changeset
100 // Relocations contain either symbol or type indices. This function takes a
anatofuz
parents:
diff changeset
101 // relocation and returns relocated index (i.e. translates from the input
anatofuz
parents:
diff changeset
102 // symbol/type space to the output symbol/type space).
anatofuz
parents:
diff changeset
103 uint32_t ObjFile::calcNewIndex(const WasmRelocation &reloc) const {
anatofuz
parents:
diff changeset
104 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {
anatofuz
parents:
diff changeset
105 assert(typeIsUsed[reloc.Index]);
anatofuz
parents:
diff changeset
106 return typeMap[reloc.Index];
anatofuz
parents:
diff changeset
107 }
anatofuz
parents:
diff changeset
108 const Symbol *sym = symbols[reloc.Index];
anatofuz
parents:
diff changeset
109 if (auto *ss = dyn_cast<SectionSymbol>(sym))
anatofuz
parents:
diff changeset
110 sym = ss->getOutputSectionSymbol();
anatofuz
parents:
diff changeset
111 return sym->getOutputSymbolIndex();
anatofuz
parents:
diff changeset
112 }
anatofuz
parents:
diff changeset
113
anatofuz
parents:
diff changeset
114 // Relocations can contain addend for combined sections. This function takes a
anatofuz
parents:
diff changeset
115 // relocation and returns updated addend by offset in the output section.
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
116 uint64_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
150
anatofuz
parents:
diff changeset
117 switch (reloc.Type) {
anatofuz
parents:
diff changeset
118 case R_WASM_MEMORY_ADDR_LEB:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
119 case R_WASM_MEMORY_ADDR_LEB64:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
120 case R_WASM_MEMORY_ADDR_SLEB64:
150
anatofuz
parents:
diff changeset
121 case R_WASM_MEMORY_ADDR_SLEB:
anatofuz
parents:
diff changeset
122 case R_WASM_MEMORY_ADDR_REL_SLEB:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
123 case R_WASM_MEMORY_ADDR_REL_SLEB64:
150
anatofuz
parents:
diff changeset
124 case R_WASM_MEMORY_ADDR_I32:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
125 case R_WASM_MEMORY_ADDR_I64:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
126 case R_WASM_MEMORY_ADDR_TLS_SLEB:
150
anatofuz
parents:
diff changeset
127 case R_WASM_FUNCTION_OFFSET_I32:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
128 case R_WASM_FUNCTION_OFFSET_I64:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
129 case R_WASM_MEMORY_ADDR_LOCREL_I32:
150
anatofuz
parents:
diff changeset
130 return reloc.Addend;
anatofuz
parents:
diff changeset
131 case R_WASM_SECTION_OFFSET_I32:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
132 return getSectionSymbol(reloc.Index)->section->getOffset(reloc.Addend);
150
anatofuz
parents:
diff changeset
133 default:
anatofuz
parents:
diff changeset
134 llvm_unreachable("unexpected relocation type");
anatofuz
parents:
diff changeset
135 }
anatofuz
parents:
diff changeset
136 }
anatofuz
parents:
diff changeset
137
anatofuz
parents:
diff changeset
138 // Translate from the relocation's index into the final linked output value.
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
139 uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc, uint64_t tombstone,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
140 const InputChunk *chunk) const {
150
anatofuz
parents:
diff changeset
141 const Symbol* sym = nullptr;
anatofuz
parents:
diff changeset
142 if (reloc.Type != R_WASM_TYPE_INDEX_LEB) {
anatofuz
parents:
diff changeset
143 sym = symbols[reloc.Index];
anatofuz
parents:
diff changeset
144
anatofuz
parents:
diff changeset
145 // We can end up with relocations against non-live symbols. For example
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
146 // in debug sections. We return a tombstone value in debug symbol sections
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
147 // so this will not produce a valid range conflicting with ranges of actual
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
148 // code. In other sections we return reloc.Addend.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
149
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
150 if (!isa<SectionSymbol>(sym) && !sym->isLive())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
151 return tombstone ? tombstone : reloc.Addend;
150
anatofuz
parents:
diff changeset
152 }
anatofuz
parents:
diff changeset
153
anatofuz
parents:
diff changeset
154 switch (reloc.Type) {
anatofuz
parents:
diff changeset
155 case R_WASM_TABLE_INDEX_I32:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
156 case R_WASM_TABLE_INDEX_I64:
150
anatofuz
parents:
diff changeset
157 case R_WASM_TABLE_INDEX_SLEB:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
158 case R_WASM_TABLE_INDEX_SLEB64:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
159 case R_WASM_TABLE_INDEX_REL_SLEB:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
160 case R_WASM_TABLE_INDEX_REL_SLEB64: {
150
anatofuz
parents:
diff changeset
161 if (!getFunctionSymbol(reloc.Index)->hasTableIndex())
anatofuz
parents:
diff changeset
162 return 0;
anatofuz
parents:
diff changeset
163 uint32_t index = getFunctionSymbol(reloc.Index)->getTableIndex();
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
164 if (reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB ||
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
165 reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB64)
150
anatofuz
parents:
diff changeset
166 index -= config->tableBase;
anatofuz
parents:
diff changeset
167 return index;
anatofuz
parents:
diff changeset
168 }
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
169 case R_WASM_MEMORY_ADDR_LEB:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
170 case R_WASM_MEMORY_ADDR_LEB64:
150
anatofuz
parents:
diff changeset
171 case R_WASM_MEMORY_ADDR_SLEB:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
172 case R_WASM_MEMORY_ADDR_SLEB64:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
173 case R_WASM_MEMORY_ADDR_REL_SLEB:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
174 case R_WASM_MEMORY_ADDR_REL_SLEB64:
150
anatofuz
parents:
diff changeset
175 case R_WASM_MEMORY_ADDR_I32:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
176 case R_WASM_MEMORY_ADDR_I64:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
177 case R_WASM_MEMORY_ADDR_LOCREL_I32: {
150
anatofuz
parents:
diff changeset
178 if (isa<UndefinedData>(sym) || sym->isUndefWeak())
anatofuz
parents:
diff changeset
179 return 0;
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
180 auto D = cast<DefinedData>(sym);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
181 // Treat non-TLS relocation against symbols that live in the TLS segment
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
182 // like TLS relocations. This beaviour exists to support older object
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
183 // files created before we introduced TLS relocations.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
184 // TODO(sbc): Remove this legacy behaviour one day. This will break
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
185 // backward compat with old object files built with `-fPIC`.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
186 if (D->segment && D->segment->outputSeg->isTLS())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
187 return D->getOutputSegmentOffset() + reloc.Addend;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
188
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
189 uint64_t value = D->getVA() + reloc.Addend;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
190 if (reloc.Type == R_WASM_MEMORY_ADDR_LOCREL_I32) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
191 const auto *segment = cast<InputSegment>(chunk);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
192 uint64_t p = segment->outputSeg->startVA + segment->outputSegmentOffset +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
193 reloc.Offset - segment->getInputSectionOffset();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
194 value -= p;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
195 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
196 return value;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
197 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
198 case R_WASM_MEMORY_ADDR_TLS_SLEB:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
199 if (isa<UndefinedData>(sym) || sym->isUndefWeak())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
200 return 0;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
201 // TLS relocations are relative to the start of the TLS output segment
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
202 return cast<DefinedData>(sym)->getOutputSegmentOffset() + reloc.Addend;
150
anatofuz
parents:
diff changeset
203 case R_WASM_TYPE_INDEX_LEB:
anatofuz
parents:
diff changeset
204 return typeMap[reloc.Index];
anatofuz
parents:
diff changeset
205 case R_WASM_FUNCTION_INDEX_LEB:
anatofuz
parents:
diff changeset
206 return getFunctionSymbol(reloc.Index)->getFunctionIndex();
anatofuz
parents:
diff changeset
207 case R_WASM_GLOBAL_INDEX_LEB:
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
208 case R_WASM_GLOBAL_INDEX_I32:
150
anatofuz
parents:
diff changeset
209 if (auto gs = dyn_cast<GlobalSymbol>(sym))
anatofuz
parents:
diff changeset
210 return gs->getGlobalIndex();
anatofuz
parents:
diff changeset
211 return sym->getGOTIndex();
anatofuz
parents:
diff changeset
212 case R_WASM_EVENT_INDEX_LEB:
anatofuz
parents:
diff changeset
213 return getEventSymbol(reloc.Index)->getEventIndex();
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
214 case R_WASM_FUNCTION_OFFSET_I32:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
215 case R_WASM_FUNCTION_OFFSET_I64: {
150
anatofuz
parents:
diff changeset
216 auto *f = cast<DefinedFunction>(sym);
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
217 return f->function->getOffset(f->function->getFunctionCodeOffset() +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
218 reloc.Addend);
150
anatofuz
parents:
diff changeset
219 }
anatofuz
parents:
diff changeset
220 case R_WASM_SECTION_OFFSET_I32:
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
221 return getSectionSymbol(reloc.Index)->section->getOffset(reloc.Addend);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
222 case R_WASM_TABLE_NUMBER_LEB:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
223 return getTableSymbol(reloc.Index)->getTableNumber();
150
anatofuz
parents:
diff changeset
224 default:
anatofuz
parents:
diff changeset
225 llvm_unreachable("unknown relocation type");
anatofuz
parents:
diff changeset
226 }
anatofuz
parents:
diff changeset
227 }
anatofuz
parents:
diff changeset
228
anatofuz
parents:
diff changeset
229 template <class T>
anatofuz
parents:
diff changeset
230 static void setRelocs(const std::vector<T *> &chunks,
anatofuz
parents:
diff changeset
231 const WasmSection *section) {
anatofuz
parents:
diff changeset
232 if (!section)
anatofuz
parents:
diff changeset
233 return;
anatofuz
parents:
diff changeset
234
anatofuz
parents:
diff changeset
235 ArrayRef<WasmRelocation> relocs = section->Relocations;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
236 assert(llvm::is_sorted(
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
237 relocs, [](const WasmRelocation &r1, const WasmRelocation &r2) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
238 return r1.Offset < r2.Offset;
150
anatofuz
parents:
diff changeset
239 }));
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
240 assert(llvm::is_sorted(chunks, [](InputChunk *c1, InputChunk *c2) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
241 return c1->getInputSectionOffset() < c2->getInputSectionOffset();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
242 }));
150
anatofuz
parents:
diff changeset
243
anatofuz
parents:
diff changeset
244 auto relocsNext = relocs.begin();
anatofuz
parents:
diff changeset
245 auto relocsEnd = relocs.end();
anatofuz
parents:
diff changeset
246 auto relocLess = [](const WasmRelocation &r, uint32_t val) {
anatofuz
parents:
diff changeset
247 return r.Offset < val;
anatofuz
parents:
diff changeset
248 };
anatofuz
parents:
diff changeset
249 for (InputChunk *c : chunks) {
anatofuz
parents:
diff changeset
250 auto relocsStart = std::lower_bound(relocsNext, relocsEnd,
anatofuz
parents:
diff changeset
251 c->getInputSectionOffset(), relocLess);
anatofuz
parents:
diff changeset
252 relocsNext = std::lower_bound(
anatofuz
parents:
diff changeset
253 relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(),
anatofuz
parents:
diff changeset
254 relocLess);
anatofuz
parents:
diff changeset
255 c->setRelocations(ArrayRef<WasmRelocation>(relocsStart, relocsNext));
anatofuz
parents:
diff changeset
256 }
anatofuz
parents:
diff changeset
257 }
anatofuz
parents:
diff changeset
258
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
259 // An object file can have two approaches to tables. With the reference-types
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
260 // feature enabled, input files that define or use tables declare the tables
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
261 // using symbols, and record each use with a relocation. This way when the
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
262 // linker combines inputs, it can collate the tables used by the inputs,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
263 // assigning them distinct table numbers, and renumber all the uses as
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
264 // appropriate. At the same time, the linker has special logic to build the
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
265 // indirect function table if it is needed.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
266 //
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
267 // However, MVP object files (those that target WebAssembly 1.0, the "minimum
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
268 // viable product" version of WebAssembly) neither write table symbols nor
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
269 // record relocations. These files can have at most one table, the indirect
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
270 // function table used by call_indirect and which is the address space for
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
271 // function pointers. If this table is present, it is always an import. If we
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
272 // have a file with a table import but no table symbols, it is an MVP object
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
273 // file. synthesizeMVPIndirectFunctionTableSymbolIfNeeded serves as a shim when
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
274 // loading these input files, defining the missing symbol to allow the indirect
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
275 // function table to be built.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
276 //
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
277 // As indirect function table table usage in MVP objects cannot be relocated,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
278 // the linker must ensure that this table gets assigned index zero.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
279 void ObjFile::addLegacyIndirectFunctionTableIfNeeded(
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
280 uint32_t tableSymbolCount) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
281 uint32_t tableCount = wasmObj->getNumImportedTables() + tables.size();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
282
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
283 // If there are symbols for all tables, then all is good.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
284 if (tableCount == tableSymbolCount)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
285 return;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
286
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
287 // It's possible for an input to define tables and also use the indirect
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
288 // function table, but forget to compile with -mattr=+reference-types.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
289 // For these newer files, we require symbols for all tables, and
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
290 // relocations for all of their uses.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
291 if (tableSymbolCount != 0) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
292 error(toString(this) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
293 ": expected one symbol table entry for each of the " +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
294 Twine(tableCount) + " table(s) present, but got " +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
295 Twine(tableSymbolCount) + " symbol(s) instead.");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
296 return;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
297 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
298
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
299 // An MVP object file can have up to one table import, for the indirect
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
300 // function table, but will have no table definitions.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
301 if (tables.size()) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
302 error(toString(this) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
303 ": unexpected table definition(s) without corresponding "
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
304 "symbol-table entries.");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
305 return;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
306 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
307
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
308 // An MVP object file can have only one table import.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
309 if (tableCount != 1) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
310 error(toString(this) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
311 ": multiple table imports, but no corresponding symbol-table "
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
312 "entries.");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
313 return;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
314 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
315
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
316 const WasmImport *tableImport = nullptr;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
317 for (const auto &import : wasmObj->imports()) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
318 if (import.Kind == WASM_EXTERNAL_TABLE) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
319 assert(!tableImport);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
320 tableImport = &import;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
321 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
322 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
323 assert(tableImport);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
324
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
325 // We can only synthesize a symtab entry for the indirect function table; if
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
326 // it has an unexpected name or type, assume that it's not actually the
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
327 // indirect function table.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
328 if (tableImport->Field != functionTableName ||
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
329 tableImport->Table.ElemType != uint8_t(ValType::FUNCREF)) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
330 error(toString(this) + ": table import " + Twine(tableImport->Field) +
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
331 " is missing a symbol table entry.");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
332 return;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
333 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
334
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
335 auto *info = make<WasmSymbolInfo>();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
336 info->Name = tableImport->Field;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
337 info->Kind = WASM_SYMBOL_TYPE_TABLE;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
338 info->ImportModule = tableImport->Module;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
339 info->ImportName = tableImport->Field;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
340 info->Flags = WASM_SYMBOL_UNDEFINED;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
341 info->Flags |= WASM_SYMBOL_NO_STRIP;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
342 info->ElementIndex = 0;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
343 LLVM_DEBUG(dbgs() << "Synthesizing symbol for table import: " << info->Name
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
344 << "\n");
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
345 const WasmGlobalType *globalType = nullptr;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
346 const WasmEventType *eventType = nullptr;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
347 const WasmSignature *signature = nullptr;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
348 auto *wasmSym = make<WasmSymbol>(*info, globalType, &tableImport->Table,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
349 eventType, signature);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
350 Symbol *sym = createUndefined(*wasmSym, false);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
351 // We're only sure it's a TableSymbol if the createUndefined succeeded.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
352 if (errorCount())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
353 return;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
354 symbols.push_back(sym);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
355 // Because there are no TABLE_NUMBER relocs, we can't compute accurate
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
356 // liveness info; instead, just mark the symbol as always live.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
357 sym->markLive();
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
358
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
359 // We assume that this compilation unit has unrelocatable references to
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
360 // this table.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
361 config->legacyFunctionTable = true;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
362 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
363
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
364 static bool shouldMerge(const WasmSection &sec) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
365 if (config->optimize == 0)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
366 return false;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
367 // Sadly we don't have section attributes yet for custom sections, so we
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
368 // currently go by the name alone.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
369 // TODO(sbc): Add ability for wasm sections to carry flags so we don't
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
370 // need to use names here.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
371 // For now, keep in sync with uses of wasm::WASM_SEG_FLAG_STRINGS in
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
372 // MCObjectFileInfo::initWasmMCObjectFileInfo which creates these custom
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
373 // sections.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
374 return sec.Name == ".debug_str" || sec.Name == ".debug_str.dwo" ||
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
375 sec.Name == ".debug_line_str";
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
376 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
377
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
378 static bool shouldMerge(const WasmSegment &seg) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
379 // As of now we only support merging strings, and only with single byte
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
380 // alignment (2^0).
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
381 if (!(seg.Data.LinkingFlags & WASM_SEG_FLAG_STRINGS) ||
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
382 (seg.Data.Alignment != 0))
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
383 return false;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
384
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
385 // On a regular link we don't merge sections if -O0 (default is -O1). This
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
386 // sometimes makes the linker significantly faster, although the output will
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
387 // be bigger.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
388 if (config->optimize == 0)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
389 return false;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
390
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
391 // A mergeable section with size 0 is useless because they don't have
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
392 // any data to merge. A mergeable string section with size 0 can be
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
393 // argued as invalid because it doesn't end with a null character.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
394 // We'll avoid a mess by handling them as if they were non-mergeable.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
395 if (seg.Data.Content.size() == 0)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
396 return false;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
397
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
398 return true;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
399 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
400
150
anatofuz
parents:
diff changeset
401 void ObjFile::parse(bool ignoreComdats) {
anatofuz
parents:
diff changeset
402 // Parse a memory buffer as a wasm file.
anatofuz
parents:
diff changeset
403 LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
anatofuz
parents:
diff changeset
404 std::unique_ptr<Binary> bin = CHECK(createBinary(mb), toString(this));
anatofuz
parents:
diff changeset
405
anatofuz
parents:
diff changeset
406 auto *obj = dyn_cast<WasmObjectFile>(bin.get());
anatofuz
parents:
diff changeset
407 if (!obj)
anatofuz
parents:
diff changeset
408 fatal(toString(this) + ": not a wasm file");
anatofuz
parents:
diff changeset
409 if (!obj->isRelocatableObject())
anatofuz
parents:
diff changeset
410 fatal(toString(this) + ": not a relocatable wasm file");
anatofuz
parents:
diff changeset
411
anatofuz
parents:
diff changeset
412 bin.release();
anatofuz
parents:
diff changeset
413 wasmObj.reset(obj);
anatofuz
parents:
diff changeset
414
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
415 checkArch(obj->getArch());
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
416
150
anatofuz
parents:
diff changeset
417 // Build up a map of function indices to table indices for use when
anatofuz
parents:
diff changeset
418 // verifying the existing table index relocations
anatofuz
parents:
diff changeset
419 uint32_t totalFunctions =
anatofuz
parents:
diff changeset
420 wasmObj->getNumImportedFunctions() + wasmObj->functions().size();
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
421 tableEntriesRel.resize(totalFunctions);
150
anatofuz
parents:
diff changeset
422 tableEntries.resize(totalFunctions);
anatofuz
parents:
diff changeset
423 for (const WasmElemSegment &seg : wasmObj->elements()) {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
424 int64_t offset;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
425 if (seg.Offset.Opcode == WASM_OPCODE_I32_CONST)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
426 offset = seg.Offset.Value.Int32;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
427 else if (seg.Offset.Opcode == WASM_OPCODE_I64_CONST)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
428 offset = seg.Offset.Value.Int64;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
429 else
150
anatofuz
parents:
diff changeset
430 fatal(toString(this) + ": invalid table elements");
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
431 for (size_t index = 0; index < seg.Functions.size(); index++) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
432 auto functionIndex = seg.Functions[index];
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
433 tableEntriesRel[functionIndex] = index;
150
anatofuz
parents:
diff changeset
434 tableEntries[functionIndex] = offset + index;
anatofuz
parents:
diff changeset
435 }
anatofuz
parents:
diff changeset
436 }
anatofuz
parents:
diff changeset
437
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
438 ArrayRef<StringRef> comdats = wasmObj->linkingData().Comdats;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
439 for (StringRef comdat : comdats) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
440 bool isNew = ignoreComdats || symtab->addComdat(comdat);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
441 keptComdats.push_back(isNew);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
442 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
443
150
anatofuz
parents:
diff changeset
444 uint32_t sectionIndex = 0;
anatofuz
parents:
diff changeset
445
anatofuz
parents:
diff changeset
446 // Bool for each symbol, true if called directly. This allows us to implement
anatofuz
parents:
diff changeset
447 // a weaker form of signature checking where undefined functions that are not
anatofuz
parents:
diff changeset
448 // called directly (i.e. only address taken) don't have to match the defined
anatofuz
parents:
diff changeset
449 // function's signature. We cannot do this for directly called functions
anatofuz
parents:
diff changeset
450 // because those signatures are checked at validation times.
anatofuz
parents:
diff changeset
451 // See https://bugs.llvm.org/show_bug.cgi?id=40412
anatofuz
parents:
diff changeset
452 std::vector<bool> isCalledDirectly(wasmObj->getNumberOfSymbols(), false);
anatofuz
parents:
diff changeset
453 for (const SectionRef &sec : wasmObj->sections()) {
anatofuz
parents:
diff changeset
454 const WasmSection &section = wasmObj->getWasmSection(sec);
anatofuz
parents:
diff changeset
455 // Wasm objects can have at most one code and one data section.
anatofuz
parents:
diff changeset
456 if (section.Type == WASM_SEC_CODE) {
anatofuz
parents:
diff changeset
457 assert(!codeSection);
anatofuz
parents:
diff changeset
458 codeSection = &section;
anatofuz
parents:
diff changeset
459 } else if (section.Type == WASM_SEC_DATA) {
anatofuz
parents:
diff changeset
460 assert(!dataSection);
anatofuz
parents:
diff changeset
461 dataSection = &section;
anatofuz
parents:
diff changeset
462 } else if (section.Type == WASM_SEC_CUSTOM) {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
463 InputChunk *customSec;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
464 if (shouldMerge(section))
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
465 customSec = make<MergeInputChunk>(section, this);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
466 else
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
467 customSec = make<InputSection>(section, this);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
468 customSec->discarded = isExcludedByComdat(customSec);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
469 customSections.emplace_back(customSec);
150
anatofuz
parents:
diff changeset
470 customSections.back()->setRelocations(section.Relocations);
anatofuz
parents:
diff changeset
471 customSectionsByIndex[sectionIndex] = customSections.back();
anatofuz
parents:
diff changeset
472 }
anatofuz
parents:
diff changeset
473 sectionIndex++;
anatofuz
parents:
diff changeset
474 // Scans relocations to determine if a function symbol is called directly.
anatofuz
parents:
diff changeset
475 for (const WasmRelocation &reloc : section.Relocations)
anatofuz
parents:
diff changeset
476 if (reloc.Type == R_WASM_FUNCTION_INDEX_LEB)
anatofuz
parents:
diff changeset
477 isCalledDirectly[reloc.Index] = true;
anatofuz
parents:
diff changeset
478 }
anatofuz
parents:
diff changeset
479
anatofuz
parents:
diff changeset
480 typeMap.resize(getWasmObj()->types().size());
anatofuz
parents:
diff changeset
481 typeIsUsed.resize(getWasmObj()->types().size(), false);
anatofuz
parents:
diff changeset
482
anatofuz
parents:
diff changeset
483
anatofuz
parents:
diff changeset
484 // Populate `Segments`.
anatofuz
parents:
diff changeset
485 for (const WasmSegment &s : wasmObj->dataSegments()) {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
486 InputChunk *seg;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
487 if (shouldMerge(s)) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
488 seg = make<MergeInputChunk>(s, this);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
489 } else
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
490 seg = make<InputSegment>(s, this);
150
anatofuz
parents:
diff changeset
491 seg->discarded = isExcludedByComdat(seg);
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
492
150
anatofuz
parents:
diff changeset
493 segments.emplace_back(seg);
anatofuz
parents:
diff changeset
494 }
anatofuz
parents:
diff changeset
495 setRelocs(segments, dataSection);
anatofuz
parents:
diff changeset
496
anatofuz
parents:
diff changeset
497 // Populate `Functions`.
anatofuz
parents:
diff changeset
498 ArrayRef<WasmFunction> funcs = wasmObj->functions();
anatofuz
parents:
diff changeset
499 ArrayRef<uint32_t> funcTypes = wasmObj->functionTypes();
anatofuz
parents:
diff changeset
500 ArrayRef<WasmSignature> types = wasmObj->types();
anatofuz
parents:
diff changeset
501 functions.reserve(funcs.size());
anatofuz
parents:
diff changeset
502
anatofuz
parents:
diff changeset
503 for (size_t i = 0, e = funcs.size(); i != e; ++i) {
anatofuz
parents:
diff changeset
504 auto* func = make<InputFunction>(types[funcTypes[i]], &funcs[i], this);
anatofuz
parents:
diff changeset
505 func->discarded = isExcludedByComdat(func);
anatofuz
parents:
diff changeset
506 functions.emplace_back(func);
anatofuz
parents:
diff changeset
507 }
anatofuz
parents:
diff changeset
508 setRelocs(functions, codeSection);
anatofuz
parents:
diff changeset
509
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
510 // Populate `Tables`.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
511 for (const WasmTable &t : wasmObj->tables())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
512 tables.emplace_back(make<InputTable>(t, this));
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
513
150
anatofuz
parents:
diff changeset
514 // Populate `Globals`.
anatofuz
parents:
diff changeset
515 for (const WasmGlobal &g : wasmObj->globals())
anatofuz
parents:
diff changeset
516 globals.emplace_back(make<InputGlobal>(g, this));
anatofuz
parents:
diff changeset
517
anatofuz
parents:
diff changeset
518 // Populate `Events`.
anatofuz
parents:
diff changeset
519 for (const WasmEvent &e : wasmObj->events())
anatofuz
parents:
diff changeset
520 events.emplace_back(make<InputEvent>(types[e.Type.SigIndex], e, this));
anatofuz
parents:
diff changeset
521
anatofuz
parents:
diff changeset
522 // Populate `Symbols` based on the symbols in the object.
anatofuz
parents:
diff changeset
523 symbols.reserve(wasmObj->getNumberOfSymbols());
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
524 uint32_t tableSymbolCount = 0;
150
anatofuz
parents:
diff changeset
525 for (const SymbolRef &sym : wasmObj->symbols()) {
anatofuz
parents:
diff changeset
526 const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(sym.getRawDataRefImpl());
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
527 if (wasmSym.isTypeTable())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
528 tableSymbolCount++;
150
anatofuz
parents:
diff changeset
529 if (wasmSym.isDefined()) {
anatofuz
parents:
diff changeset
530 // createDefined may fail if the symbol is comdat excluded in which case
anatofuz
parents:
diff changeset
531 // we fall back to creating an undefined symbol
anatofuz
parents:
diff changeset
532 if (Symbol *d = createDefined(wasmSym)) {
anatofuz
parents:
diff changeset
533 symbols.push_back(d);
anatofuz
parents:
diff changeset
534 continue;
anatofuz
parents:
diff changeset
535 }
anatofuz
parents:
diff changeset
536 }
anatofuz
parents:
diff changeset
537 size_t idx = symbols.size();
anatofuz
parents:
diff changeset
538 symbols.push_back(createUndefined(wasmSym, isCalledDirectly[idx]));
anatofuz
parents:
diff changeset
539 }
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
540
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
541 addLegacyIndirectFunctionTableIfNeeded(tableSymbolCount);
150
anatofuz
parents:
diff changeset
542 }
anatofuz
parents:
diff changeset
543
anatofuz
parents:
diff changeset
544 bool ObjFile::isExcludedByComdat(InputChunk *chunk) const {
anatofuz
parents:
diff changeset
545 uint32_t c = chunk->getComdat();
anatofuz
parents:
diff changeset
546 if (c == UINT32_MAX)
anatofuz
parents:
diff changeset
547 return false;
anatofuz
parents:
diff changeset
548 return !keptComdats[c];
anatofuz
parents:
diff changeset
549 }
anatofuz
parents:
diff changeset
550
anatofuz
parents:
diff changeset
551 FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t index) const {
anatofuz
parents:
diff changeset
552 return cast<FunctionSymbol>(symbols[index]);
anatofuz
parents:
diff changeset
553 }
anatofuz
parents:
diff changeset
554
anatofuz
parents:
diff changeset
555 GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t index) const {
anatofuz
parents:
diff changeset
556 return cast<GlobalSymbol>(symbols[index]);
anatofuz
parents:
diff changeset
557 }
anatofuz
parents:
diff changeset
558
anatofuz
parents:
diff changeset
559 EventSymbol *ObjFile::getEventSymbol(uint32_t index) const {
anatofuz
parents:
diff changeset
560 return cast<EventSymbol>(symbols[index]);
anatofuz
parents:
diff changeset
561 }
anatofuz
parents:
diff changeset
562
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
563 TableSymbol *ObjFile::getTableSymbol(uint32_t index) const {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
564 return cast<TableSymbol>(symbols[index]);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
565 }
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
566
150
anatofuz
parents:
diff changeset
567 SectionSymbol *ObjFile::getSectionSymbol(uint32_t index) const {
anatofuz
parents:
diff changeset
568 return cast<SectionSymbol>(symbols[index]);
anatofuz
parents:
diff changeset
569 }
anatofuz
parents:
diff changeset
570
anatofuz
parents:
diff changeset
571 DataSymbol *ObjFile::getDataSymbol(uint32_t index) const {
anatofuz
parents:
diff changeset
572 return cast<DataSymbol>(symbols[index]);
anatofuz
parents:
diff changeset
573 }
anatofuz
parents:
diff changeset
574
anatofuz
parents:
diff changeset
575 Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
anatofuz
parents:
diff changeset
576 StringRef name = sym.Info.Name;
anatofuz
parents:
diff changeset
577 uint32_t flags = sym.Info.Flags;
anatofuz
parents:
diff changeset
578
anatofuz
parents:
diff changeset
579 switch (sym.Info.Kind) {
anatofuz
parents:
diff changeset
580 case WASM_SYMBOL_TYPE_FUNCTION: {
anatofuz
parents:
diff changeset
581 InputFunction *func =
anatofuz
parents:
diff changeset
582 functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
anatofuz
parents:
diff changeset
583 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
584 return make<DefinedFunction>(name, flags, this, func);
anatofuz
parents:
diff changeset
585 if (func->discarded)
anatofuz
parents:
diff changeset
586 return nullptr;
anatofuz
parents:
diff changeset
587 return symtab->addDefinedFunction(name, flags, this, func);
anatofuz
parents:
diff changeset
588 }
anatofuz
parents:
diff changeset
589 case WASM_SYMBOL_TYPE_DATA: {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
590 InputChunk *seg = segments[sym.Info.DataRef.Segment];
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
591 auto offset = sym.Info.DataRef.Offset;
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
592 auto size = sym.Info.DataRef.Size;
150
anatofuz
parents:
diff changeset
593 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
594 return make<DefinedData>(name, flags, this, seg, offset, size);
anatofuz
parents:
diff changeset
595 if (seg->discarded)
anatofuz
parents:
diff changeset
596 return nullptr;
anatofuz
parents:
diff changeset
597 return symtab->addDefinedData(name, flags, this, seg, offset, size);
anatofuz
parents:
diff changeset
598 }
anatofuz
parents:
diff changeset
599 case WASM_SYMBOL_TYPE_GLOBAL: {
anatofuz
parents:
diff changeset
600 InputGlobal *global =
anatofuz
parents:
diff changeset
601 globals[sym.Info.ElementIndex - wasmObj->getNumImportedGlobals()];
anatofuz
parents:
diff changeset
602 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
603 return make<DefinedGlobal>(name, flags, this, global);
anatofuz
parents:
diff changeset
604 return symtab->addDefinedGlobal(name, flags, this, global);
anatofuz
parents:
diff changeset
605 }
anatofuz
parents:
diff changeset
606 case WASM_SYMBOL_TYPE_SECTION: {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
607 InputChunk *section = customSectionsByIndex[sym.Info.ElementIndex];
150
anatofuz
parents:
diff changeset
608 assert(sym.isBindingLocal());
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
609 // Need to return null if discarded here? data and func only do that when
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
610 // binding is not local.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
611 if (section->discarded)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
612 return nullptr;
150
anatofuz
parents:
diff changeset
613 return make<SectionSymbol>(flags, section, this);
anatofuz
parents:
diff changeset
614 }
anatofuz
parents:
diff changeset
615 case WASM_SYMBOL_TYPE_EVENT: {
anatofuz
parents:
diff changeset
616 InputEvent *event =
anatofuz
parents:
diff changeset
617 events[sym.Info.ElementIndex - wasmObj->getNumImportedEvents()];
anatofuz
parents:
diff changeset
618 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
619 return make<DefinedEvent>(name, flags, this, event);
anatofuz
parents:
diff changeset
620 return symtab->addDefinedEvent(name, flags, this, event);
anatofuz
parents:
diff changeset
621 }
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
622 case WASM_SYMBOL_TYPE_TABLE: {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
623 InputTable *table =
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
624 tables[sym.Info.ElementIndex - wasmObj->getNumImportedTables()];
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
625 if (sym.isBindingLocal())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
626 return make<DefinedTable>(name, flags, this, table);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
627 return symtab->addDefinedTable(name, flags, this, table);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
628 }
150
anatofuz
parents:
diff changeset
629 }
anatofuz
parents:
diff changeset
630 llvm_unreachable("unknown symbol kind");
anatofuz
parents:
diff changeset
631 }
anatofuz
parents:
diff changeset
632
anatofuz
parents:
diff changeset
633 Symbol *ObjFile::createUndefined(const WasmSymbol &sym, bool isCalledDirectly) {
anatofuz
parents:
diff changeset
634 StringRef name = sym.Info.Name;
anatofuz
parents:
diff changeset
635 uint32_t flags = sym.Info.Flags | WASM_SYMBOL_UNDEFINED;
anatofuz
parents:
diff changeset
636
anatofuz
parents:
diff changeset
637 switch (sym.Info.Kind) {
anatofuz
parents:
diff changeset
638 case WASM_SYMBOL_TYPE_FUNCTION:
anatofuz
parents:
diff changeset
639 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
640 return make<UndefinedFunction>(name, sym.Info.ImportName,
anatofuz
parents:
diff changeset
641 sym.Info.ImportModule, flags, this,
anatofuz
parents:
diff changeset
642 sym.Signature, isCalledDirectly);
anatofuz
parents:
diff changeset
643 return symtab->addUndefinedFunction(name, sym.Info.ImportName,
anatofuz
parents:
diff changeset
644 sym.Info.ImportModule, flags, this,
anatofuz
parents:
diff changeset
645 sym.Signature, isCalledDirectly);
anatofuz
parents:
diff changeset
646 case WASM_SYMBOL_TYPE_DATA:
anatofuz
parents:
diff changeset
647 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
648 return make<UndefinedData>(name, flags, this);
anatofuz
parents:
diff changeset
649 return symtab->addUndefinedData(name, flags, this);
anatofuz
parents:
diff changeset
650 case WASM_SYMBOL_TYPE_GLOBAL:
anatofuz
parents:
diff changeset
651 if (sym.isBindingLocal())
anatofuz
parents:
diff changeset
652 return make<UndefinedGlobal>(name, sym.Info.ImportName,
anatofuz
parents:
diff changeset
653 sym.Info.ImportModule, flags, this,
anatofuz
parents:
diff changeset
654 sym.GlobalType);
anatofuz
parents:
diff changeset
655 return symtab->addUndefinedGlobal(name, sym.Info.ImportName,
anatofuz
parents:
diff changeset
656 sym.Info.ImportModule, flags, this,
anatofuz
parents:
diff changeset
657 sym.GlobalType);
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
658 case WASM_SYMBOL_TYPE_TABLE:
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
659 if (sym.isBindingLocal())
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
660 return make<UndefinedTable>(name, sym.Info.ImportName,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
661 sym.Info.ImportModule, flags, this,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
662 sym.TableType);
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
663 return symtab->addUndefinedTable(name, sym.Info.ImportName,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
664 sym.Info.ImportModule, flags, this,
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
665 sym.TableType);
150
anatofuz
parents:
diff changeset
666 case WASM_SYMBOL_TYPE_SECTION:
anatofuz
parents:
diff changeset
667 llvm_unreachable("section symbols cannot be undefined");
anatofuz
parents:
diff changeset
668 }
anatofuz
parents:
diff changeset
669 llvm_unreachable("unknown symbol kind");
anatofuz
parents:
diff changeset
670 }
anatofuz
parents:
diff changeset
671
anatofuz
parents:
diff changeset
672 void ArchiveFile::parse() {
anatofuz
parents:
diff changeset
673 // Parse a MemoryBufferRef as an archive file.
anatofuz
parents:
diff changeset
674 LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
anatofuz
parents:
diff changeset
675 file = CHECK(Archive::create(mb), toString(this));
anatofuz
parents:
diff changeset
676
anatofuz
parents:
diff changeset
677 // Read the symbol table to construct Lazy symbols.
anatofuz
parents:
diff changeset
678 int count = 0;
anatofuz
parents:
diff changeset
679 for (const Archive::Symbol &sym : file->symbols()) {
anatofuz
parents:
diff changeset
680 symtab->addLazy(this, &sym);
anatofuz
parents:
diff changeset
681 ++count;
anatofuz
parents:
diff changeset
682 }
anatofuz
parents:
diff changeset
683 LLVM_DEBUG(dbgs() << "Read " << count << " symbols\n");
anatofuz
parents:
diff changeset
684 }
anatofuz
parents:
diff changeset
685
anatofuz
parents:
diff changeset
686 void ArchiveFile::addMember(const Archive::Symbol *sym) {
anatofuz
parents:
diff changeset
687 const Archive::Child &c =
anatofuz
parents:
diff changeset
688 CHECK(sym->getMember(),
anatofuz
parents:
diff changeset
689 "could not get the member for symbol " + sym->getName());
anatofuz
parents:
diff changeset
690
anatofuz
parents:
diff changeset
691 // Don't try to load the same member twice (this can happen when members
anatofuz
parents:
diff changeset
692 // mutually reference each other).
anatofuz
parents:
diff changeset
693 if (!seen.insert(c.getChildOffset()).second)
anatofuz
parents:
diff changeset
694 return;
anatofuz
parents:
diff changeset
695
anatofuz
parents:
diff changeset
696 LLVM_DEBUG(dbgs() << "loading lazy: " << sym->getName() << "\n");
anatofuz
parents:
diff changeset
697 LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
anatofuz
parents:
diff changeset
698
anatofuz
parents:
diff changeset
699 MemoryBufferRef mb =
anatofuz
parents:
diff changeset
700 CHECK(c.getMemoryBufferRef(),
anatofuz
parents:
diff changeset
701 "could not get the buffer for the member defining symbol " +
anatofuz
parents:
diff changeset
702 sym->getName());
anatofuz
parents:
diff changeset
703
anatofuz
parents:
diff changeset
704 InputFile *obj = createObjectFile(mb, getName());
anatofuz
parents:
diff changeset
705 symtab->addFile(obj);
anatofuz
parents:
diff changeset
706 }
anatofuz
parents:
diff changeset
707
anatofuz
parents:
diff changeset
708 static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
anatofuz
parents:
diff changeset
709 switch (gvVisibility) {
anatofuz
parents:
diff changeset
710 case GlobalValue::DefaultVisibility:
anatofuz
parents:
diff changeset
711 return WASM_SYMBOL_VISIBILITY_DEFAULT;
anatofuz
parents:
diff changeset
712 case GlobalValue::HiddenVisibility:
anatofuz
parents:
diff changeset
713 case GlobalValue::ProtectedVisibility:
anatofuz
parents:
diff changeset
714 return WASM_SYMBOL_VISIBILITY_HIDDEN;
anatofuz
parents:
diff changeset
715 }
anatofuz
parents:
diff changeset
716 llvm_unreachable("unknown visibility");
anatofuz
parents:
diff changeset
717 }
anatofuz
parents:
diff changeset
718
anatofuz
parents:
diff changeset
719 static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
anatofuz
parents:
diff changeset
720 const lto::InputFile::Symbol &objSym,
anatofuz
parents:
diff changeset
721 BitcodeFile &f) {
anatofuz
parents:
diff changeset
722 StringRef name = saver.save(objSym.getName());
anatofuz
parents:
diff changeset
723
anatofuz
parents:
diff changeset
724 uint32_t flags = objSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0;
anatofuz
parents:
diff changeset
725 flags |= mapVisibility(objSym.getVisibility());
anatofuz
parents:
diff changeset
726
anatofuz
parents:
diff changeset
727 int c = objSym.getComdatIndex();
anatofuz
parents:
diff changeset
728 bool excludedByComdat = c != -1 && !keptComdats[c];
anatofuz
parents:
diff changeset
729
anatofuz
parents:
diff changeset
730 if (objSym.isUndefined() || excludedByComdat) {
anatofuz
parents:
diff changeset
731 flags |= WASM_SYMBOL_UNDEFINED;
anatofuz
parents:
diff changeset
732 if (objSym.isExecutable())
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
733 return symtab->addUndefinedFunction(name, None, None, flags, &f, nullptr,
150
anatofuz
parents:
diff changeset
734 true);
anatofuz
parents:
diff changeset
735 return symtab->addUndefinedData(name, flags, &f);
anatofuz
parents:
diff changeset
736 }
anatofuz
parents:
diff changeset
737
anatofuz
parents:
diff changeset
738 if (objSym.isExecutable())
anatofuz
parents:
diff changeset
739 return symtab->addDefinedFunction(name, flags, &f, nullptr);
anatofuz
parents:
diff changeset
740 return symtab->addDefinedData(name, flags, &f, nullptr, 0, 0);
anatofuz
parents:
diff changeset
741 }
anatofuz
parents:
diff changeset
742
anatofuz
parents:
diff changeset
743 bool BitcodeFile::doneLTO = false;
anatofuz
parents:
diff changeset
744
anatofuz
parents:
diff changeset
745 void BitcodeFile::parse() {
anatofuz
parents:
diff changeset
746 if (doneLTO) {
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
747 error(toString(this) + ": attempt to add bitcode file after LTO.");
150
anatofuz
parents:
diff changeset
748 return;
anatofuz
parents:
diff changeset
749 }
anatofuz
parents:
diff changeset
750
anatofuz
parents:
diff changeset
751 obj = check(lto::InputFile::create(MemoryBufferRef(
anatofuz
parents:
diff changeset
752 mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier()))));
anatofuz
parents:
diff changeset
753 Triple t(obj->getTargetTriple());
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
754 if (!t.isWasm()) {
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
755 error(toString(this) + ": machine type must be wasm32 or wasm64");
150
anatofuz
parents:
diff changeset
756 return;
anatofuz
parents:
diff changeset
757 }
207
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
758 checkArch(t.getArch());
150
anatofuz
parents:
diff changeset
759 std::vector<bool> keptComdats;
anatofuz
parents:
diff changeset
760 for (StringRef s : obj->getComdatTable())
anatofuz
parents:
diff changeset
761 keptComdats.push_back(symtab->addComdat(s));
anatofuz
parents:
diff changeset
762
anatofuz
parents:
diff changeset
763 for (const lto::InputFile::Symbol &objSym : obj->symbols())
anatofuz
parents:
diff changeset
764 symbols.push_back(createBitcodeSymbol(keptComdats, objSym, *this));
anatofuz
parents:
diff changeset
765 }
anatofuz
parents:
diff changeset
766
anatofuz
parents:
diff changeset
767 } // namespace wasm
anatofuz
parents:
diff changeset
768 } // namespace lld