clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name AArch64ErrataFix.cpp -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D LLD_VENDOR="Debian" -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lld/ELF -I /build/source/lld/ELF -I /build/source/lld/include -I tools/lld/include -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U 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-17/lib/clang/17/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 -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -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 -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -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-2023-05-10-133810-16478-1 -x c++ /build/source/lld/ELF/AArch64ErrataFix.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | #include "AArch64ErrataFix.h" |
29 | #include "InputFiles.h" |
30 | #include "LinkerScript.h" |
31 | #include "OutputSections.h" |
32 | #include "Relocations.h" |
33 | #include "Symbols.h" |
34 | #include "SyntheticSections.h" |
35 | #include "Target.h" |
36 | #include "lld/Common/CommonLinkerContext.h" |
37 | #include "lld/Common/Strings.h" |
38 | #include "llvm/Support/Endian.h" |
39 | #include <algorithm> |
40 | |
41 | using namespace llvm; |
42 | using namespace llvm::ELF; |
43 | using namespace llvm::object; |
44 | using namespace llvm::support; |
45 | using namespace llvm::support::endian; |
46 | using namespace lld; |
47 | using namespace lld::elf; |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | static bool isADRP(uint32_t instr) { |
55 | return (instr & 0x9f000000) == 0x90000000; |
56 | } |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | static bool isLoadStoreClass(uint32_t instr) { |
65 | return (instr & 0x0a000000) == 0x08000000; |
66 | } |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | static bool isST1MultipleOpcode(uint32_t instr) { |
81 | return (instr & 0x0000f000) == 0x00002000 || |
82 | (instr & 0x0000f000) == 0x00006000 || |
83 | (instr & 0x0000f000) == 0x00007000 || |
84 | (instr & 0x0000f000) == 0x0000a000; |
85 | } |
86 | |
87 | static bool isST1Multiple(uint32_t instr) { |
88 | return (instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(instr); |
89 | } |
90 | |
91 | |
92 | static bool isST1MultiplePost(uint32_t instr) { |
93 | return (instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(instr); |
94 | } |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | static bool isST1SingleOpcode(uint32_t instr) { |
109 | return (instr & 0x0040e000) == 0x00000000 || |
110 | (instr & 0x0040e000) == 0x00004000 || |
111 | (instr & 0x0040e000) == 0x00008000; |
112 | } |
113 | |
114 | static bool isST1Single(uint32_t instr) { |
115 | return (instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(instr); |
116 | } |
117 | |
118 | |
119 | static bool isST1SinglePost(uint32_t instr) { |
120 | return (instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(instr); |
121 | } |
122 | |
123 | static bool isST1(uint32_t instr) { |
124 | return isST1Multiple(instr) || isST1MultiplePost(instr) || |
125 | isST1Single(instr) || isST1SinglePost(instr); |
126 | } |
127 | |
128 | |
129 | |
130 | |
131 | static bool isLoadStoreExclusive(uint32_t instr) { |
132 | return (instr & 0x3f000000) == 0x08000000; |
133 | } |
134 | |
135 | static bool isLoadExclusive(uint32_t instr) { |
136 | return (instr & 0x3f400000) == 0x08400000; |
137 | } |
138 | |
139 | |
140 | |
141 | static bool isLoadLiteral(uint32_t instr) { |
142 | return (instr & 0x3b000000) == 0x18000000; |
143 | } |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | static bool isSTNP(uint32_t instr) { |
151 | return (instr & 0x3bc00000) == 0x28000000; |
152 | } |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | static bool isSTPPost(uint32_t instr) { |
160 | return (instr & 0x3bc00000) == 0x28800000; |
161 | } |
162 | |
163 | |
164 | |
165 | static bool isSTPOffset(uint32_t instr) { |
166 | return (instr & 0x3bc00000) == 0x29000000; |
167 | } |
168 | |
169 | |
170 | |
171 | |
172 | static bool isSTPPre(uint32_t instr) { |
173 | return (instr & 0x3bc00000) == 0x29800000; |
174 | } |
175 | |
176 | static bool isSTP(uint32_t instr) { |
177 | return isSTPPost(instr) || isSTPOffset(instr) || isSTPPre(instr); |
178 | } |
179 | |
180 | |
181 | |
182 | |
183 | static bool isLoadStoreUnscaled(uint32_t instr) { |
184 | return (instr & 0x3b000c00) == 0x38000000; |
185 | } |
186 | |
187 | |
188 | |
189 | static bool isLoadStoreImmediatePost(uint32_t instr) { |
190 | return (instr & 0x3b200c00) == 0x38000400; |
191 | } |
192 | |
193 | |
194 | |
195 | static bool isLoadStoreUnpriv(uint32_t instr) { |
196 | return (instr & 0x3b200c00) == 0x38000800; |
197 | } |
198 | |
199 | |
200 | |
201 | static bool isLoadStoreImmediatePre(uint32_t instr) { |
202 | return (instr & 0x3b200c00) == 0x38000c00; |
203 | } |
204 | |
205 | |
206 | |
207 | static bool isLoadStoreRegisterOff(uint32_t instr) { |
208 | return (instr & 0x3b200c00) == 0x38200800; |
209 | } |
210 | |
211 | |
212 | |
213 | static bool isLoadStoreRegisterUnsigned(uint32_t instr) { |
214 | return (instr & 0x3b000000) == 0x39000000; |
215 | } |
216 | |
217 | |
218 | static uint32_t getRt(uint32_t instr) { return (instr & 0x1f); } |
219 | |
220 | |
221 | static uint32_t getRn(uint32_t instr) { return (instr >> 5) & 0x1f; } |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | static bool isBranch(uint32_t instr) { |
231 | return ((instr & 0xfe000000) == 0xd6000000) || |
232 | ((instr & 0xfe000000) == 0x54000000) || |
233 | ((instr & 0x7c000000) == 0x14000000) || |
234 | ((instr & 0x7c000000) == 0x34000000); |
235 | } |
236 | |
237 | static bool isV8SingleRegisterNonStructureLoadStore(uint32_t instr) { |
238 | return isLoadStoreUnscaled(instr) || isLoadStoreImmediatePost(instr) || |
239 | isLoadStoreUnpriv(instr) || isLoadStoreImmediatePre(instr) || |
240 | isLoadStoreRegisterOff(instr) || isLoadStoreRegisterUnsigned(instr); |
241 | } |
242 | |
243 | |
244 | |
245 | |
246 | |
247 | static bool isV8NonStructureLoad(uint32_t instr) { |
248 | if (isLoadExclusive(instr)) |
249 | return true; |
250 | if (isLoadLiteral(instr)) |
251 | return true; |
252 | else if (isV8SingleRegisterNonStructureLoadStore(instr)) { |
253 | |
254 | |
255 | uint32_t size = (instr >> 30) & 0xff; |
256 | uint32_t v = (instr >> 26) & 0x1; |
257 | uint32_t opc = (instr >> 22) & 0x3; |
258 | |
259 | |
260 | |
261 | |
262 | |
263 | return opc != 0 && !(size == 0 && v == 1 && opc == 2) && |
264 | !(size == 3 && v == 0 && opc == 2); |
265 | } |
266 | return false; |
267 | } |
268 | |
269 | |
270 | |
271 | |
272 | |
273 | static bool hasWriteback(uint32_t instr) { |
274 | return isLoadStoreImmediatePre(instr) || isLoadStoreImmediatePost(instr) || |
275 | isSTPPre(instr) || isSTPPost(instr) || isST1SinglePost(instr) || |
276 | isST1MultiplePost(instr); |
277 | } |
278 | |
279 | |
280 | |
281 | |
282 | static bool doesLoadStoreWriteToReg(uint32_t instr, uint32_t reg) { |
283 | return (isV8NonStructureLoad(instr) && getRt(instr) == reg) || |
284 | (hasWriteback(instr) && getRn(instr) == reg); |
285 | } |
286 | |
287 | |
288 | |
289 | |
290 | |
291 | |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | static bool is843419ErratumSequence(uint32_t instr1, uint32_t instr2, |
317 | uint32_t instr4) { |
318 | if (!isADRP(instr1)) |
319 | return false; |
320 | |
321 | uint32_t rn = getRt(instr1); |
322 | return isLoadStoreClass(instr2) && |
323 | (isLoadStoreExclusive(instr2) || isLoadLiteral(instr2) || |
324 | isV8SingleRegisterNonStructureLoadStore(instr2) || isSTP(instr2) || |
325 | isSTNP(instr2) || isST1(instr2)) && |
326 | !doesLoadStoreWriteToReg(instr2, rn) && |
327 | isLoadStoreRegisterUnsigned(instr4) && getRn(instr4) == rn; |
328 | } |
329 | |
330 | |
331 | |
332 | |
333 | |
334 | |
335 | |
336 | static uint64_t scanCortexA53Errata843419(InputSection *isec, uint64_t &off, |
337 | uint64_t limit) { |
338 | uint64_t isecAddr = isec->getVA(0); |
339 | |
340 | |
341 | uint64_t initialPageOff = (isecAddr + off) & 0xfff; |
342 | if (initialPageOff < 0xff8) |
343 | off += 0xff8 - initialPageOff; |
344 | |
345 | bool optionalAllowed = limit - off > 12; |
346 | if (off >= limit || limit - off < 12) { |
347 | |
348 | off = limit; |
349 | return 0; |
350 | } |
351 | |
352 | uint64_t patchOff = 0; |
353 | const uint8_t *buf = isec->content().begin(); |
354 | const ulittle32_t *instBuf = reinterpret_cast<const ulittle32_t *>(buf + off); |
355 | uint32_t instr1 = *instBuf++; |
356 | uint32_t instr2 = *instBuf++; |
357 | uint32_t instr3 = *instBuf++; |
358 | if (is843419ErratumSequence(instr1, instr2, instr3)) { |
359 | patchOff = off + 8; |
360 | } else if (optionalAllowed && !isBranch(instr3)) { |
361 | uint32_t instr4 = *instBuf++; |
362 | if (is843419ErratumSequence(instr1, instr2, instr4)) |
363 | patchOff = off + 12; |
364 | } |
365 | if (((isecAddr + off) & 0xfff) == 0xff8) |
366 | off += 4; |
367 | else |
368 | off += 0xffc; |
369 | return patchOff; |
370 | } |
371 | |
372 | class elf::Patch843419Section final : public SyntheticSection { |
373 | public: |
374 | Patch843419Section(InputSection *p, uint64_t off); |
375 | |
376 | void writeTo(uint8_t *buf) override; |
377 | |
378 | size_t getSize() const override { return 8; } |
379 | |
380 | uint64_t getLDSTAddr() const; |
381 | |
382 | static bool classof(const SectionBase *d) { |
383 | return d->kind() == InputSectionBase::Synthetic && d->name == ".text.patch"; |
384 | } |
385 | |
386 | |
387 | const InputSection *patchee; |
388 | |
389 | uint64_t patcheeOffset; |
390 | |
391 | Symbol *patchSym; |
392 | }; |
393 | |
394 | Patch843419Section::Patch843419Section(InputSection *p, uint64_t off) |
395 | : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4, |
396 | ".text.patch"), |
397 | patchee(p), patcheeOffset(off) { |
398 | this->parent = p->getParent(); |
399 | patchSym = addSyntheticLocal( |
400 | saver().save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, |
401 | 0, getSize(), *this); |
402 | addSyntheticLocal(saver().save("$x"), STT_NOTYPE, 0, 0, *this); |
403 | } |
404 | |
405 | uint64_t Patch843419Section::getLDSTAddr() const { |
406 | return patchee->getVA(patcheeOffset); |
407 | } |
408 | |
409 | void Patch843419Section::writeTo(uint8_t *buf) { |
410 | |
411 | |
412 | write32le(buf, read32le(patchee->content().begin() + patcheeOffset)); |
413 | |
414 | |
415 | target->relocateAlloc(*this, buf); |
416 | |
417 | |
418 | uint64_t s = getLDSTAddr() + 4; |
419 | uint64_t p = patchSym->getVA() + 4; |
420 | target->relocateNoSym(buf + 4, R_AARCH64_JUMP26, s - p); |
421 | } |
422 | |
423 | void AArch64Err843419Patcher::init() { |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | |
434 | auto isCodeMapSymbol = [](const Symbol *b) { |
435 | return b->getName() == "$x" || b->getName().startswith("$x."); |
436 | }; |
437 | auto isDataMapSymbol = [](const Symbol *b) { |
438 | return b->getName() == "$d" || b->getName().startswith("$d."); |
439 | }; |
440 | |
441 | |
442 | for (ELFFileBase *file : ctx.objectFiles) { |
443 | for (Symbol *b : file->getLocalSymbols()) { |
444 | auto *def = dyn_cast<Defined>(b); |
445 | if (!def) |
446 | continue; |
447 | if (!isCodeMapSymbol(def) && !isDataMapSymbol(def)) |
448 | continue; |
449 | if (auto *sec = dyn_cast_or_null<InputSection>(def->section)) |
450 | if (sec->flags & SHF_EXECINSTR) |
451 | sectionMap[sec].push_back(def); |
452 | } |
453 | } |
454 | |
455 | |
456 | |
457 | |
458 | for (auto &kv : sectionMap) { |
459 | std::vector<const Defined *> &mapSyms = kv.second; |
460 | llvm::stable_sort(mapSyms, [](const Defined *a, const Defined *b) { |
461 | return a->value < b->value; |
462 | }); |
463 | mapSyms.erase( |
464 | std::unique(mapSyms.begin(), mapSyms.end(), |
465 | [=](const Defined *a, const Defined *b) { |
466 | return isCodeMapSymbol(a) == isCodeMapSymbol(b); |
467 | }), |
468 | mapSyms.end()); |
469 | |
470 | if (!mapSyms.empty() && !isCodeMapSymbol(mapSyms.front())) |
471 | mapSyms.erase(mapSyms.begin()); |
472 | } |
473 | initialized = true; |
474 | } |
475 | |
476 | |
477 | |
478 | |
479 | |
480 | |
481 | void AArch64Err843419Patcher::insertPatches( |
482 | InputSectionDescription &isd, std::vector<Patch843419Section *> &patches) { |
483 | uint64_t isecLimit; |
| 13 | | 'isecLimit' declared without an initial value | |
|
484 | uint64_t prevIsecLimit = isd.sections.front()->outSecOff; |
485 | uint64_t patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); |
486 | uint64_t outSecAddr = isd.sections.front()->getParent()->addr; |
487 | |
488 | |
489 | |
490 | |
491 | auto patchIt = patches.begin(); |
492 | auto patchEnd = patches.end(); |
493 | for (const InputSection *isec : isd.sections) { |
| 14 | | Assuming '__begin1' is equal to '__end1' | |
|
494 | isecLimit = isec->outSecOff + isec->getSize(); |
495 | if (isecLimit > patchUpperBound) { |
496 | while (patchIt != patchEnd) { |
497 | if ((*patchIt)->getLDSTAddr() - outSecAddr >= prevIsecLimit) |
498 | break; |
499 | (*patchIt)->outSecOff = prevIsecLimit; |
500 | ++patchIt; |
501 | } |
502 | patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); |
503 | } |
504 | prevIsecLimit = isecLimit; |
505 | } |
506 | for (; patchIt != patchEnd; ++patchIt) { |
| 15 | | Loop condition is true. Entering loop body | |
|
507 | (*patchIt)->outSecOff = isecLimit; |
| 16 | | Assigned value is garbage or undefined |
|
508 | } |
509 | |
510 | |
511 | |
512 | |
513 | |
514 | SmallVector<InputSection *, 0> tmp; |
515 | tmp.reserve(isd.sections.size() + patches.size()); |
516 | auto mergeCmp = [](const InputSection *a, const InputSection *b) { |
517 | if (a->outSecOff != b->outSecOff) |
518 | return a->outSecOff < b->outSecOff; |
519 | return isa<Patch843419Section>(a) && !isa<Patch843419Section>(b); |
520 | }; |
521 | std::merge(isd.sections.begin(), isd.sections.end(), patches.begin(), |
522 | patches.end(), std::back_inserter(tmp), mergeCmp); |
523 | isd.sections = std::move(tmp); |
524 | } |
525 | |
526 | |
527 | |
528 | |
529 | |
530 | static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset, |
531 | InputSection *isec, |
532 | std::vector<Patch843419Section *> &patches) { |
533 | |
534 | |
535 | |
536 | |
537 | |
538 | |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | |
545 | |
546 | |
547 | auto relIt = llvm::find_if(isec->relocs(), [=](const Relocation &r) { |
548 | return r.offset == patcheeOffset; |
549 | }); |
550 | if (relIt != isec->relocs().end() && |
551 | (relIt->type == R_AARCH64_JUMP26 || relIt->expr == R_RELAX_TLS_IE_TO_LE)) |
552 | return; |
553 | |
554 | log("detected cortex-a53-843419 erratum sequence starting at " + |
555 | utohexstr(adrpAddr) + " in unpatched output."); |
556 | |
557 | auto *ps = make<Patch843419Section>(isec, patcheeOffset); |
558 | patches.push_back(ps); |
559 | |
560 | auto makeRelToPatch = [](uint64_t offset, Symbol *patchSym) { |
561 | return Relocation{R_PC, R_AARCH64_JUMP26, offset, 0, patchSym}; |
562 | }; |
563 | |
564 | if (relIt != isec->relocs().end()) { |
565 | ps->addReloc({relIt->expr, relIt->type, 0, relIt->addend, relIt->sym}); |
566 | *relIt = makeRelToPatch(patcheeOffset, ps->patchSym); |
567 | } else |
568 | isec->addReloc(makeRelToPatch(patcheeOffset, ps->patchSym)); |
569 | } |
570 | |
571 | |
572 | |
573 | |
574 | std::vector<Patch843419Section *> |
575 | AArch64Err843419Patcher::patchInputSectionDescription( |
576 | InputSectionDescription &isd) { |
577 | std::vector<Patch843419Section *> patches; |
578 | for (InputSection *isec : isd.sections) { |
579 | |
580 | if (isa<SyntheticSection>(isec)) |
581 | continue; |
582 | |
583 | |
584 | |
585 | |
586 | |
587 | std::vector<const Defined *> &mapSyms = sectionMap[isec]; |
588 | |
589 | auto codeSym = mapSyms.begin(); |
590 | while (codeSym != mapSyms.end()) { |
591 | auto dataSym = std::next(codeSym); |
592 | uint64_t off = (*codeSym)->value; |
593 | uint64_t limit = (dataSym == mapSyms.end()) ? isec->content().size() |
594 | : (*dataSym)->value; |
595 | |
596 | while (off < limit) { |
597 | uint64_t startAddr = isec->getVA(off); |
598 | if (uint64_t patcheeOffset = |
599 | scanCortexA53Errata843419(isec, off, limit)) |
600 | implementPatch(startAddr, patcheeOffset, isec, patches); |
601 | } |
602 | if (dataSym == mapSyms.end()) |
603 | break; |
604 | codeSym = std::next(dataSym); |
605 | } |
606 | } |
607 | return patches; |
608 | } |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | |
615 | |
616 | |
617 | |
618 | |
619 | |
620 | |
621 | |
622 | bool AArch64Err843419Patcher::createFixes() { |
623 | if (!initialized) |
| 1 | Assuming field 'initialized' is true | |
|
| |
624 | init(); |
625 | |
626 | bool addressesChanged = false; |
627 | for (OutputSection *os : outputSections) { |
| 3 | | Assuming '__begin1' is not equal to '__end1' | |
|
628 | if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR)) |
| 4 | | Assuming the condition is false | |
|
| 5 | | Assuming the condition is false | |
|
| |
629 | continue; |
630 | for (SectionCommand *cmd : os->commands) |
| 7 | | Assuming '__begin2' is not equal to '__end2' | |
|
631 | if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) { |
| 8 | | Assuming 'cmd' is a 'CastReturnType' | |
|
| |
632 | std::vector<Patch843419Section *> patches = |
633 | patchInputSectionDescription(*isd); |
634 | if (!patches.empty()) { |
| 10 | | Assuming the condition is true | |
|
| |
635 | insertPatches(*isd, patches); |
| 12 | | Calling 'AArch64Err843419Patcher::insertPatches' | |
|
636 | addressesChanged = true; |
637 | } |
638 | } |
639 | } |
640 | return addressesChanged; |
641 | } |