/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Object/IRSymtab.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file contains data definitions and a reader and builder for a symbol |
11 | | // table for LLVM IR. Its purpose is to allow linkers and other consumers of |
12 | | // bitcode files to efficiently read the symbol table for symbol resolution |
13 | | // purposes without needing to construct a module in memory. |
14 | | // |
15 | | // As with most object files the symbol table has two parts: the symbol table |
16 | | // itself and a string table which is referenced by the symbol table. |
17 | | // |
18 | | // A symbol table corresponds to a single bitcode file, which may consist of |
19 | | // multiple modules, so symbol tables may likewise contain symbols for multiple |
20 | | // modules. |
21 | | // |
22 | | //===----------------------------------------------------------------------===// |
23 | | |
24 | | #ifndef LLVM_OBJECT_IRSYMTAB_H |
25 | | #define LLVM_OBJECT_IRSYMTAB_H |
26 | | |
27 | | #include "llvm/ADT/ArrayRef.h" |
28 | | #include "llvm/ADT/StringRef.h" |
29 | | #include "llvm/ADT/iterator_range.h" |
30 | | #include "llvm/IR/GlobalValue.h" |
31 | | #include "llvm/Object/SymbolicFile.h" |
32 | | #include "llvm/Support/Endian.h" |
33 | | #include "llvm/Support/Error.h" |
34 | | #include <cassert> |
35 | | #include <cstdint> |
36 | | #include <vector> |
37 | | |
38 | | namespace llvm { |
39 | | |
40 | | struct BitcodeFileContents; |
41 | | class StringTableBuilder; |
42 | | |
43 | | namespace irsymtab { |
44 | | |
45 | | namespace storage { |
46 | | |
47 | | // The data structures in this namespace define the low-level serialization |
48 | | // format. Clients that just want to read a symbol table should use the |
49 | | // irsymtab::Reader class. |
50 | | |
51 | | using Word = support::ulittle32_t; |
52 | | |
53 | | /// A reference to a string in the string table. |
54 | | struct Str { |
55 | | Word Offset, Size; |
56 | | |
57 | 3.36k | StringRef get(StringRef Strtab) const { |
58 | 3.36k | return {Strtab.data() + Offset, Size}; |
59 | 3.36k | } |
60 | | }; |
61 | | |
62 | | /// A reference to a range of objects in the symbol table. |
63 | | template <typename T> struct Range { |
64 | | Word Offset, Size; |
65 | | |
66 | 1.55k | ArrayRef<T> get(StringRef Symtab) const { |
67 | 1.55k | return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; |
68 | 1.55k | } llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Uncommon>::get(llvm::StringRef) const Line | Count | Source | 66 | 389 | ArrayRef<T> get(StringRef Symtab) const { | 67 | 389 | return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; | 68 | 389 | } |
llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Comdat>::get(llvm::StringRef) const Line | Count | Source | 66 | 389 | ArrayRef<T> get(StringRef Symtab) const { | 67 | 389 | return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; | 68 | 389 | } |
llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Symbol>::get(llvm::StringRef) const Line | Count | Source | 66 | 389 | ArrayRef<T> get(StringRef Symtab) const { | 67 | 389 | return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; | 68 | 389 | } |
llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Module>::get(llvm::StringRef) const Line | Count | Source | 66 | 389 | ArrayRef<T> get(StringRef Symtab) const { | 67 | 389 | return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size}; | 68 | 389 | } |
|
69 | | }; |
70 | | |
71 | | /// Describes the range of a particular module's symbols within the symbol |
72 | | /// table. |
73 | | struct Module { |
74 | | Word Begin, End; |
75 | | |
76 | | /// The index of the first Uncommon for this Module. |
77 | | Word UncBegin; |
78 | | }; |
79 | | |
80 | | /// This is equivalent to an IR comdat. |
81 | | struct Comdat { |
82 | | Str Name; |
83 | | }; |
84 | | |
85 | | /// Contains the information needed by linkers for symbol resolution, as well as |
86 | | /// by the LTO implementation itself. |
87 | | struct Symbol { |
88 | | /// The mangled symbol name. |
89 | | Str Name; |
90 | | |
91 | | /// The unmangled symbol name, or the empty string if this is not an IR |
92 | | /// symbol. |
93 | | Str IRName; |
94 | | |
95 | | /// The index into Header::Comdats, or -1 if not a comdat member. |
96 | | Word ComdatIndex; |
97 | | |
98 | | Word Flags; |
99 | | enum FlagBits { |
100 | | FB_visibility, // 2 bits |
101 | | FB_has_uncommon = FB_visibility + 2, |
102 | | FB_undefined, |
103 | | FB_weak, |
104 | | FB_common, |
105 | | FB_indirect, |
106 | | FB_used, |
107 | | FB_tls, |
108 | | FB_may_omit, |
109 | | FB_global, |
110 | | FB_format_specific, |
111 | | FB_unnamed_addr, |
112 | | FB_executable, |
113 | | }; |
114 | | }; |
115 | | |
116 | | /// This data structure contains rarely used symbol fields and is optionally |
117 | | /// referenced by a Symbol. |
118 | | struct Uncommon { |
119 | | Word CommonSize, CommonAlign; |
120 | | |
121 | | /// COFF-specific: the name of the symbol that a weak external resolves to |
122 | | /// if not defined. |
123 | | Str COFFWeakExternFallbackName; |
124 | | |
125 | | /// Specified section name, if any. |
126 | | Str SectionName; |
127 | | }; |
128 | | |
129 | | struct Header { |
130 | | /// Version number of the symtab format. This number should be incremented |
131 | | /// when the format changes, but it does not need to be incremented if a |
132 | | /// change to LLVM would cause it to create a different symbol table. |
133 | | Word Version; |
134 | | enum { kCurrentVersion = 1 }; |
135 | | |
136 | | /// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION). |
137 | | /// Consumers should rebuild the symbol table from IR if the producer's |
138 | | /// version does not match the consumer's version due to potential differences |
139 | | /// in symbol table format, symbol enumeration order and so on. |
140 | | Str Producer; |
141 | | |
142 | | Range<Module> Modules; |
143 | | Range<Comdat> Comdats; |
144 | | Range<Symbol> Symbols; |
145 | | Range<Uncommon> Uncommons; |
146 | | |
147 | | Str TargetTriple, SourceFileName; |
148 | | |
149 | | /// COFF-specific: linker directives. |
150 | | Str COFFLinkerOpts; |
151 | | }; |
152 | | |
153 | | } // end namespace storage |
154 | | |
155 | | /// Fills in Symtab and StrtabBuilder with a valid symbol and string table for |
156 | | /// Mods. |
157 | | Error build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab, |
158 | | StringTableBuilder &StrtabBuilder, BumpPtrAllocator &Alloc); |
159 | | |
160 | | /// This represents a symbol that has been read from a storage::Symbol and |
161 | | /// possibly a storage::Uncommon. |
162 | | struct Symbol { |
163 | | // Copied from storage::Symbol. |
164 | | StringRef Name, IRName; |
165 | | int ComdatIndex; |
166 | | uint32_t Flags; |
167 | | |
168 | | // Copied from storage::Uncommon. |
169 | | uint32_t CommonSize, CommonAlign; |
170 | | StringRef COFFWeakExternFallbackName; |
171 | | StringRef SectionName; |
172 | | |
173 | | /// Returns the mangled symbol name. |
174 | 0 | StringRef getName() const { return Name; } |
175 | | |
176 | | /// Returns the unmangled symbol name, or the empty string if this is not an |
177 | | /// IR symbol. |
178 | 0 | StringRef getIRName() const { return IRName; } |
179 | | |
180 | | /// Returns the index into the comdat table (see Reader::getComdatTable()), or |
181 | | /// -1 if not a comdat member. |
182 | 0 | int getComdatIndex() const { return ComdatIndex; } |
183 | | |
184 | | using S = storage::Symbol; |
185 | | |
186 | 0 | GlobalValue::VisibilityTypes getVisibility() const { |
187 | 0 | return GlobalValue::VisibilityTypes((Flags >> S::FB_visibility) & 3); |
188 | 0 | } |
189 | | |
190 | 0 | bool isUndefined() const { return (Flags >> S::FB_undefined) & 1; } |
191 | 0 | bool isWeak() const { return (Flags >> S::FB_weak) & 1; } |
192 | 0 | bool isCommon() const { return (Flags >> S::FB_common) & 1; } |
193 | 0 | bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; } |
194 | 0 | bool isUsed() const { return (Flags >> S::FB_used) & 1; } |
195 | 0 | bool isTLS() const { return (Flags >> S::FB_tls) & 1; } |
196 | | |
197 | 0 | bool canBeOmittedFromSymbolTable() const { |
198 | 0 | return (Flags >> S::FB_may_omit) & 1; |
199 | 0 | } |
200 | | |
201 | 0 | bool isGlobal() const { return (Flags >> S::FB_global) & 1; } |
202 | 0 | bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; } |
203 | 0 | bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; } |
204 | 0 | bool isExecutable() const { return (Flags >> S::FB_executable) & 1; } |
205 | | |
206 | 0 | uint64_t getCommonSize() const { |
207 | 0 | assert(isCommon()); |
208 | 0 | return CommonSize; |
209 | 0 | } |
210 | | |
211 | 0 | uint32_t getCommonAlignment() const { |
212 | 0 | assert(isCommon()); |
213 | 0 | return CommonAlign; |
214 | 0 | } |
215 | | |
216 | | /// COFF-specific: for weak externals, returns the name of the symbol that is |
217 | | /// used as a fallback if the weak external remains undefined. |
218 | 0 | StringRef getCOFFWeakExternalFallback() const { |
219 | 0 | assert(isWeak() && isIndirect()); |
220 | 0 | return COFFWeakExternFallbackName; |
221 | 0 | } |
222 | | |
223 | 0 | StringRef getSectionName() const { return SectionName; } |
224 | | }; |
225 | | |
226 | | /// This class can be used to read a Symtab and Strtab produced by |
227 | | /// irsymtab::build. |
228 | | class Reader { |
229 | | StringRef Symtab, Strtab; |
230 | | |
231 | | ArrayRef<storage::Module> Modules; |
232 | | ArrayRef<storage::Comdat> Comdats; |
233 | | ArrayRef<storage::Symbol> Symbols; |
234 | | ArrayRef<storage::Uncommon> Uncommons; |
235 | | |
236 | 0 | StringRef str(storage::Str S) const { return S.get(Strtab); } |
237 | | |
238 | 1.55k | template <typename T> ArrayRef<T> range(storage::Range<T> R) const { |
239 | 1.55k | return R.get(Symtab); |
240 | 1.55k | } llvm::ArrayRef<llvm::irsymtab::storage::Symbol> llvm::irsymtab::Reader::range<llvm::irsymtab::storage::Symbol>(llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Symbol>) const Line | Count | Source | 238 | 389 | template <typename T> ArrayRef<T> range(storage::Range<T> R) const { | 239 | 389 | return R.get(Symtab); | 240 | 389 | } |
llvm::ArrayRef<llvm::irsymtab::storage::Uncommon> llvm::irsymtab::Reader::range<llvm::irsymtab::storage::Uncommon>(llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Uncommon>) const Line | Count | Source | 238 | 389 | template <typename T> ArrayRef<T> range(storage::Range<T> R) const { | 239 | 389 | return R.get(Symtab); | 240 | 389 | } |
llvm::ArrayRef<llvm::irsymtab::storage::Comdat> llvm::irsymtab::Reader::range<llvm::irsymtab::storage::Comdat>(llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Comdat>) const Line | Count | Source | 238 | 389 | template <typename T> ArrayRef<T> range(storage::Range<T> R) const { | 239 | 389 | return R.get(Symtab); | 240 | 389 | } |
llvm::ArrayRef<llvm::irsymtab::storage::Module> llvm::irsymtab::Reader::range<llvm::irsymtab::storage::Module>(llvm::irsymtab::storage::Range<llvm::irsymtab::storage::Module>) const Line | Count | Source | 238 | 389 | template <typename T> ArrayRef<T> range(storage::Range<T> R) const { | 239 | 389 | return R.get(Symtab); | 240 | 389 | } |
|
241 | | |
242 | 2.72k | const storage::Header &header() const { |
243 | 2.72k | return *reinterpret_cast<const storage::Header *>(Symtab.data()); |
244 | 2.72k | } |
245 | | |
246 | | public: |
247 | | class SymbolRef; |
248 | | |
249 | 783 | Reader() = default; |
250 | 389 | Reader(StringRef Symtab, StringRef Strtab) : Symtab(Symtab), Strtab(Strtab) { |
251 | 389 | Modules = range(header().Modules); |
252 | 389 | Comdats = range(header().Comdats); |
253 | 389 | Symbols = range(header().Symbols); |
254 | 389 | Uncommons = range(header().Uncommons); |
255 | 389 | } |
256 | | |
257 | | using symbol_range = iterator_range<object::content_iterator<SymbolRef>>; |
258 | | |
259 | | /// Returns the symbol table for the entire bitcode file. |
260 | | /// The symbols enumerated by this method are ephemeral, but they can be |
261 | | /// copied into an irsymtab::Symbol object. |
262 | | symbol_range symbols() const; |
263 | | |
264 | 381 | size_t getNumModules() const { return Modules.size(); } |
265 | | |
266 | | /// Returns a slice of the symbol table for the I'th module in the file. |
267 | | /// The symbols enumerated by this method are ephemeral, but they can be |
268 | | /// copied into an irsymtab::Symbol object. |
269 | | symbol_range module_symbols(unsigned I) const; |
270 | | |
271 | 0 | StringRef getTargetTriple() const { return str(header().TargetTriple); } |
272 | | |
273 | | /// Returns the source file path specified at compile time. |
274 | 0 | StringRef getSourceFileName() const { return str(header().SourceFileName); } |
275 | | |
276 | | /// Returns a table with all the comdats used by this file. |
277 | | std::vector<StringRef> getComdatTable() const { |
278 | | std::vector<StringRef> ComdatTable; |
279 | | ComdatTable.reserve(Comdats.size()); |
280 | | for (auto C : Comdats) |
281 | | ComdatTable.push_back(str(C.Name)); |
282 | | return ComdatTable; |
283 | | } |
284 | | |
285 | | /// COFF-specific: returns linker options specified in the input file. |
286 | 0 | StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); } |
287 | | }; |
288 | | |
289 | | /// Ephemeral symbols produced by Reader::symbols() and |
290 | | /// Reader::module_symbols(). |
291 | | class Reader::SymbolRef : public Symbol { |
292 | | const storage::Symbol *SymI, *SymE; |
293 | | const storage::Uncommon *UncI; |
294 | | const Reader *R; |
295 | | |
296 | | void read() { |
297 | | if (SymI == SymE) |
298 | | return; |
299 | | |
300 | | Name = R->str(SymI->Name); |
301 | | IRName = R->str(SymI->IRName); |
302 | | ComdatIndex = SymI->ComdatIndex; |
303 | | Flags = SymI->Flags; |
304 | | |
305 | | if (Flags & (1 << storage::Symbol::FB_has_uncommon)) { |
306 | | CommonSize = UncI->CommonSize; |
307 | | CommonAlign = UncI->CommonAlign; |
308 | | COFFWeakExternFallbackName = R->str(UncI->COFFWeakExternFallbackName); |
309 | | SectionName = R->str(UncI->SectionName); |
310 | | } else |
311 | | // Reset this field so it can be queried unconditionally for all symbols. |
312 | | SectionName = ""; |
313 | | } |
314 | | |
315 | | public: |
316 | | SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE, |
317 | | const storage::Uncommon *UncI, const Reader *R) |
318 | 0 | : SymI(SymI), SymE(SymE), UncI(UncI), R(R) { |
319 | 0 | read(); |
320 | 0 | } |
321 | | |
322 | | void moveNext() { |
323 | | ++SymI; |
324 | | if (Flags & (1 << storage::Symbol::FB_has_uncommon)) |
325 | | ++UncI; |
326 | | read(); |
327 | | } |
328 | | |
329 | 0 | bool operator==(const SymbolRef &Other) const { return SymI == Other.SymI; } |
330 | | }; |
331 | | |
332 | 0 | inline Reader::symbol_range Reader::symbols() const { |
333 | 0 | return {SymbolRef(Symbols.begin(), Symbols.end(), Uncommons.begin(), this), |
334 | 0 | SymbolRef(Symbols.end(), Symbols.end(), nullptr, this)}; |
335 | 0 | } |
336 | | |
337 | 0 | inline Reader::symbol_range Reader::module_symbols(unsigned I) const { |
338 | 0 | const storage::Module &M = Modules[I]; |
339 | 0 | const storage::Symbol *MBegin = Symbols.begin() + M.Begin, |
340 | 0 | *MEnd = Symbols.begin() + M.End; |
341 | 0 | return {SymbolRef(MBegin, MEnd, Uncommons.begin() + M.UncBegin, this), |
342 | 0 | SymbolRef(MEnd, MEnd, nullptr, this)}; |
343 | 0 | } |
344 | | |
345 | | /// The contents of the irsymtab in a bitcode file. Any underlying data for the |
346 | | /// irsymtab are owned by Symtab and Strtab. |
347 | | struct FileContents { |
348 | | SmallVector<char, 0> Symtab, Strtab; |
349 | | Reader TheReader; |
350 | | }; |
351 | | |
352 | | /// Reads the contents of a bitcode file, creating its irsymtab if necessary. |
353 | | Expected<FileContents> readBitcode(const BitcodeFileContents &BFC); |
354 | | |
355 | | } // end namespace irsymtab |
356 | | } // end namespace llvm |
357 | | |
358 | | #endif // LLVM_OBJECT_IRSYMTAB_H |