clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name BPFELFObjectWriter.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/BPF/MCTargetDesc -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/BPF/MCTargetDesc -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/BPF/MCTargetDesc -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/BPF -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/BPF -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/BPF/MCTargetDesc -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "MCTargetDesc/BPFMCTargetDesc.h" |
10 | #include "llvm/BinaryFormat/ELF.h" |
11 | #include "llvm/MC/MCELFObjectWriter.h" |
12 | #include "llvm/MC/MCFixup.h" |
13 | #include "llvm/MC/MCObjectWriter.h" |
14 | #include "llvm/MC/MCValue.h" |
15 | #include "llvm/Support/ErrorHandling.h" |
16 | #include <cstdint> |
17 | |
18 | using namespace llvm; |
19 | |
20 | namespace { |
21 | |
22 | class BPFELFObjectWriter : public MCELFObjectTargetWriter { |
23 | public: |
24 | BPFELFObjectWriter(uint8_t OSABI); |
25 | ~BPFELFObjectWriter() override = default; |
26 | |
27 | protected: |
28 | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
29 | const MCFixup &Fixup, bool IsPCRel) const override; |
30 | }; |
31 | |
32 | } |
33 | |
34 | BPFELFObjectWriter::BPFELFObjectWriter(uint8_t OSABI) |
35 | : MCELFObjectTargetWriter( true, OSABI, ELF::EM_BPF, |
36 | false) {} |
37 | |
38 | unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, |
39 | const MCFixup &Fixup, |
40 | bool IsPCRel) const { |
41 | |
42 | switch (Fixup.getKind()) { |
| 1 | Control jumps to 'case FK_Data_4:' at line 53 | |
|
43 | default: |
44 | llvm_unreachable("invalid fixup kind!"); |
45 | case FK_SecRel_8: |
46 | |
47 | return ELF::R_BPF_64_64; |
48 | case FK_PCRel_4: |
49 | |
50 | return ELF::R_BPF_64_32; |
51 | case FK_Data_8: |
52 | return ELF::R_BPF_64_ABS64; |
53 | case FK_Data_4: |
54 | if (const MCSymbolRefExpr *A = Target.getSymA()) { |
| 2 | | Assuming 'A' is non-null | |
|
| |
55 | const MCSymbol &Sym = A->getSymbol(); |
56 | |
57 | if (Sym.isDefined()) { |
| 4 | | Calling 'MCSymbol::isDefined' | |
|
| 9 | | Returning from 'MCSymbol::isDefined' | |
|
| |
58 | MCSection &Section = Sym.getSection(); |
59 | const MCSectionELF *SectionELF = dyn_cast<MCSectionELF>(&Section); |
| 11 | | Assuming the object is not a 'MCSectionELF' | |
|
| 12 | | 'SectionELF' initialized to a null pointer value | |
|
60 | assert(SectionELF && "Null section for reloc symbol"); |
61 | |
62 | unsigned Flags = SectionELF->getFlags(); |
| 13 | | Called C++ object pointer is null |
|
63 | |
64 | if (Sym.isTemporary()) { |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_EXECINSTR)) |
72 | return ELF::R_BPF_64_NODYLD32; |
73 | } else { |
74 | |
75 | |
76 | |
77 | if ((Flags & ELF::SHF_ALLOC) && (Flags & ELF::SHF_WRITE)) |
78 | return ELF::R_BPF_64_NODYLD32; |
79 | } |
80 | } |
81 | } |
82 | return ELF::R_BPF_64_ABS32; |
83 | } |
84 | } |
85 | |
86 | std::unique_ptr<MCObjectTargetWriter> |
87 | llvm::createBPFELFObjectWriter(uint8_t OSABI) { |
88 | return std::make_unique<BPFELFObjectWriter>(OSABI); |
89 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_MC_MCSYMBOL_H |
14 | #define LLVM_MC_MCSYMBOL_H |
15 | |
16 | #include "llvm/ADT/PointerIntPair.h" |
17 | #include "llvm/ADT/StringMap.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/MC/MCExpr.h" |
20 | #include "llvm/MC/MCFragment.h" |
21 | #include "llvm/Support/ErrorHandling.h" |
22 | #include "llvm/Support/MathExtras.h" |
23 | #include <cassert> |
24 | #include <cstddef> |
25 | #include <cstdint> |
26 | |
27 | namespace llvm { |
28 | |
29 | class MCAsmInfo; |
30 | class MCContext; |
31 | class MCSection; |
32 | class raw_ostream; |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | class MCSymbol { |
42 | protected: |
43 | |
44 | |
45 | enum SymbolKind { |
46 | SymbolKindUnset, |
47 | SymbolKindCOFF, |
48 | SymbolKindELF, |
49 | SymbolKindGOFF, |
50 | SymbolKindMachO, |
51 | SymbolKindWasm, |
52 | SymbolKindXCOFF, |
53 | }; |
54 | |
55 | |
56 | |
57 | enum Contents : uint8_t { |
58 | SymContentsUnset, |
59 | SymContentsOffset, |
60 | SymContentsVariable, |
61 | SymContentsCommon, |
62 | SymContentsTargetCommon, |
63 | }; |
64 | |
65 | |
66 | static MCFragment *AbsolutePseudoFragment; |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName; |
84 | |
85 | |
86 | |
87 | |
88 | unsigned IsTemporary : 1; |
89 | |
90 | |
91 | unsigned IsRedefinable : 1; |
92 | |
93 | |
94 | mutable unsigned IsUsed : 1; |
95 | |
96 | mutable unsigned IsRegistered : 1; |
97 | |
98 | |
99 | |
100 | mutable unsigned IsExternal : 1; |
101 | |
102 | |
103 | mutable unsigned IsPrivateExtern : 1; |
104 | |
105 | |
106 | |
107 | unsigned Kind : 3; |
108 | |
109 | |
110 | mutable unsigned IsUsedInReloc : 1; |
111 | |
112 | |
113 | |
114 | unsigned SymbolContents : 3; |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | enum : unsigned { NumCommonAlignmentBits = 5 }; |
122 | unsigned CommonAlignLog2 : NumCommonAlignmentBits; |
123 | |
124 | |
125 | |
126 | enum : unsigned { NumFlagsBits = 16 }; |
127 | mutable uint32_t Flags : NumFlagsBits; |
128 | |
129 | |
130 | mutable uint32_t Index = 0; |
131 | |
132 | union { |
133 | |
134 | uint64_t Offset; |
135 | |
136 | |
137 | uint64_t CommonSize; |
138 | |
139 | |
140 | const MCExpr *Value; |
141 | }; |
142 | |
143 | |
144 | friend class MCExpr; |
145 | friend class MCContext; |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | using NameEntryStorageTy = union { |
152 | const StringMapEntry<bool> *NameEntry; |
153 | uint64_t AlignmentPadding; |
154 | }; |
155 | |
156 | MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary) |
157 | : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), |
158 | IsRegistered(false), IsExternal(false), IsPrivateExtern(false), |
159 | Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), |
160 | CommonAlignLog2(0), Flags(0) { |
161 | Offset = 0; |
162 | FragmentAndHasName.setInt(!!Name); |
163 | if (Name) |
164 | getNameEntryPtr() = Name; |
165 | } |
166 | |
167 | |
168 | |
169 | void *operator new(size_t s, const StringMapEntry<bool> *Name, |
170 | MCContext &Ctx); |
171 | |
172 | private: |
173 | void operator delete(void *); |
174 | |
175 | void operator delete(void*, unsigned) { |
176 | llvm_unreachable("Constructor throws?"); |
177 | } |
178 | |
179 | void operator delete(void*, unsigned, bool) { |
180 | llvm_unreachable("Constructor throws?"); |
181 | } |
182 | |
183 | |
184 | const StringMapEntry<bool> *&getNameEntryPtr() { |
185 | assert(FragmentAndHasName.getInt() && "Name is required"); |
186 | NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); |
187 | return (*(Name - 1)).NameEntry; |
188 | } |
189 | const StringMapEntry<bool> *&getNameEntryPtr() const { |
190 | return const_cast<MCSymbol*>(this)->getNameEntryPtr(); |
191 | } |
192 | |
193 | public: |
194 | MCSymbol(const MCSymbol &) = delete; |
195 | MCSymbol &operator=(const MCSymbol &) = delete; |
196 | |
197 | |
198 | StringRef getName() const { |
199 | if (!FragmentAndHasName.getInt()) |
200 | return StringRef(); |
201 | |
202 | return getNameEntryPtr()->first(); |
203 | } |
204 | |
205 | bool isRegistered() const { return IsRegistered; } |
206 | void setIsRegistered(bool Value) const { IsRegistered = Value; } |
207 | |
208 | void setUsedInReloc() const { IsUsedInReloc = true; } |
209 | bool isUsedInReloc() const { return IsUsedInReloc; } |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | bool isTemporary() const { return IsTemporary; } |
216 | |
217 | |
218 | bool isUsed() const { return IsUsed; } |
219 | |
220 | |
221 | bool isRedefinable() const { return IsRedefinable; } |
222 | |
223 | void setRedefinable(bool Value) { IsRedefinable = Value; } |
224 | |
225 | void redefineIfPossible() { |
226 | if (IsRedefinable) { |
227 | if (SymbolContents == SymContentsVariable) { |
228 | Value = nullptr; |
229 | SymbolContents = SymContentsUnset; |
230 | } |
231 | setUndefined(); |
232 | IsRedefinable = false; |
233 | } |
234 | } |
235 | |
236 | |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | |
243 | bool isDefined() const { return !isUndefined(); } |
| 5 | | Calling 'MCSymbol::isUndefined' | |
|
| 7 | | Returning from 'MCSymbol::isUndefined' | |
|
| 8 | | Returning the value 1, which participates in a condition later | |
|
244 | |
245 | |
246 | |
247 | bool isInSection() const { |
248 | return isDefined() && !isAbsolute(); |
249 | } |
250 | |
251 | |
252 | bool isUndefined(bool SetUsed = true) const { |
253 | return getFragment(SetUsed) == nullptr; |
| 6 | | Returning zero, which participates in a condition later | |
|
254 | } |
255 | |
256 | |
257 | bool isAbsolute() const { |
258 | return getFragment() == AbsolutePseudoFragment; |
259 | } |
260 | |
261 | |
262 | MCSection &getSection() const { |
263 | assert(isInSection() && "Invalid accessor!"); |
264 | return *getFragment()->getParent(); |
265 | } |
266 | |
267 | |
268 | void setFragment(MCFragment *F) const { |
269 | assert(!isVariable() && "Cannot set fragment of variable"); |
270 | FragmentAndHasName.setPointer(F); |
271 | } |
272 | |
273 | |
274 | void setUndefined() { FragmentAndHasName.setPointer(nullptr); } |
275 | |
276 | bool isELF() const { return Kind == SymbolKindELF; } |
277 | |
278 | bool isCOFF() const { return Kind == SymbolKindCOFF; } |
279 | |
280 | bool isGOFF() const { return Kind == SymbolKindGOFF; } |
281 | |
282 | bool isMachO() const { return Kind == SymbolKindMachO; } |
283 | |
284 | bool isWasm() const { return Kind == SymbolKindWasm; } |
285 | |
286 | bool isXCOFF() const { return Kind == SymbolKindXCOFF; } |
287 | |
288 | |
289 | |
290 | |
291 | |
292 | |
293 | bool isVariable() const { |
294 | return SymbolContents == SymContentsVariable; |
295 | } |
296 | |
297 | |
298 | const MCExpr *getVariableValue(bool SetUsed = true) const { |
299 | assert(isVariable() && "Invalid accessor!"); |
300 | IsUsed |= SetUsed; |
301 | return Value; |
302 | } |
303 | |
304 | void setVariableValue(const MCExpr *Value); |
305 | |
306 | |
307 | |
308 | |
309 | uint32_t getIndex() const { |
310 | return Index; |
311 | } |
312 | |
313 | |
314 | void setIndex(uint32_t Value) const { |
315 | Index = Value; |
316 | } |
317 | |
318 | bool isUnset() const { return SymbolContents == SymContentsUnset; } |
319 | |
320 | uint64_t getOffset() const { |
321 | assert((SymbolContents == SymContentsUnset || |
322 | SymbolContents == SymContentsOffset) && |
323 | "Cannot get offset for a common/variable symbol"); |
324 | return Offset; |
325 | } |
326 | void setOffset(uint64_t Value) { |
327 | assert((SymbolContents == SymContentsUnset || |
328 | SymbolContents == SymContentsOffset) && |
329 | "Cannot set offset for a common/variable symbol"); |
330 | Offset = Value; |
331 | SymbolContents = SymContentsOffset; |
332 | } |
333 | |
334 | |
335 | uint64_t getCommonSize() const { |
336 | assert(isCommon() && "Not a 'common' symbol!"); |
337 | return CommonSize; |
338 | } |
339 | |
340 | |
341 | |
342 | |
343 | |
344 | |
345 | void setCommon(uint64_t Size, unsigned Align, bool Target = false) { |
346 | assert(getOffset() == 0); |
347 | CommonSize = Size; |
348 | SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon; |
349 | |
350 | assert((!Align || isPowerOf2_32(Align)) && |
351 | "Alignment must be a power of 2"); |
352 | unsigned Log2Align = Log2_32(Align) + 1; |
353 | assert(Log2Align < (1U << NumCommonAlignmentBits) && |
354 | "Out of range alignment"); |
355 | CommonAlignLog2 = Log2Align; |
356 | } |
357 | |
358 | |
359 | unsigned getCommonAlignment() const { |
360 | assert(isCommon() && "Not a 'common' symbol!"); |
361 | return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0; |
362 | } |
363 | |
364 | |
365 | |
366 | |
367 | |
368 | |
369 | |
370 | bool declareCommon(uint64_t Size, unsigned Align, bool Target = false) { |
371 | assert(isCommon() || getOffset() == 0); |
372 | if(isCommon()) { |
373 | if (CommonSize != Size || getCommonAlignment() != Align || |
374 | isTargetCommon() != Target) |
375 | return true; |
376 | } else |
377 | setCommon(Size, Align, Target); |
378 | return false; |
379 | } |
380 | |
381 | |
382 | bool isCommon() const { |
383 | return SymbolContents == SymContentsCommon || |
384 | SymbolContents == SymContentsTargetCommon; |
385 | } |
386 | |
387 | |
388 | bool isTargetCommon() const { |
389 | return SymbolContents == SymContentsTargetCommon; |
390 | } |
391 | |
392 | MCFragment *getFragment(bool SetUsed = true) const { |
393 | MCFragment *Fragment = FragmentAndHasName.getPointer(); |
394 | if (Fragment || !isVariable()) |
395 | return Fragment; |
396 | Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); |
397 | FragmentAndHasName.setPointer(Fragment); |
398 | return Fragment; |
399 | } |
400 | |
401 | bool isExternal() const { return IsExternal; } |
402 | void setExternal(bool Value) const { IsExternal = Value; } |
403 | |
404 | bool isPrivateExtern() const { return IsPrivateExtern; } |
405 | void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } |
406 | |
407 | |
408 | void print(raw_ostream &OS, const MCAsmInfo *MAI) const; |
409 | |
410 | |
411 | void dump() const; |
412 | |
413 | protected: |
414 | |
415 | uint32_t getFlags() const { return Flags; } |
416 | |
417 | |
418 | void setFlags(uint32_t Value) const { |
419 | assert(Value < (1U << NumFlagsBits) && "Out of range flags"); |
420 | Flags = Value; |
421 | } |
422 | |
423 | |
424 | void modifyFlags(uint32_t Value, uint32_t Mask) const { |
425 | assert(Value < (1U << NumFlagsBits) && "Out of range flags"); |
426 | Flags = (Flags & ~Mask) | Value; |
427 | } |
428 | }; |
429 | |
430 | inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { |
431 | Sym.print(OS, nullptr); |
432 | return OS; |
433 | } |
434 | |
435 | } |
436 | |
437 | #endif // LLVM_MC_MCSYMBOL_H |