clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name AArch64ErrataFix.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 -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-8/lib/clang/8.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lld/ELF -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lld/ELF -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lld/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lld/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/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-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lld/ELF -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/tools/lld/ELF/AArch64ErrataFix.cpp -faddrsig
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 | |
29 | |
30 | |
31 | |
32 | #include "AArch64ErrataFix.h" |
33 | #include "Config.h" |
34 | #include "LinkerScript.h" |
35 | #include "OutputSections.h" |
36 | #include "Relocations.h" |
37 | #include "Symbols.h" |
38 | #include "SyntheticSections.h" |
39 | #include "Target.h" |
40 | #include "lld/Common/Memory.h" |
41 | #include "lld/Common/Strings.h" |
42 | #include "llvm/Support/Endian.h" |
43 | #include "llvm/Support/raw_ostream.h" |
44 | #include <algorithm> |
45 | |
46 | using namespace llvm; |
47 | using namespace llvm::ELF; |
48 | using namespace llvm::object; |
49 | using namespace llvm::support; |
50 | using namespace llvm::support::endian; |
51 | |
52 | using namespace lld; |
53 | using namespace lld::elf; |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | static bool isADRP(uint32_t Instr) { |
61 | return (Instr & 0x9f000000) == 0x90000000; |
62 | } |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | static bool isLoadStoreClass(uint32_t Instr) { |
71 | return (Instr & 0x0a000000) == 0x08000000; |
72 | } |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | static bool isST1MultipleOpcode(uint32_t Instr) { |
87 | return (Instr & 0x0000f000) == 0x00002000 || |
88 | (Instr & 0x0000f000) == 0x00006000 || |
89 | (Instr & 0x0000f000) == 0x00007000 || |
90 | (Instr & 0x0000f000) == 0x0000a000; |
91 | } |
92 | |
93 | static bool isST1Multiple(uint32_t Instr) { |
94 | return (Instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(Instr); |
95 | } |
96 | |
97 | |
98 | static bool isST1MultiplePost(uint32_t Instr) { |
99 | return (Instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(Instr); |
100 | } |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | static bool isST1SingleOpcode(uint32_t Instr) { |
115 | return (Instr & 0x0040e000) == 0x00000000 || |
116 | (Instr & 0x0040e000) == 0x00004000 || |
117 | (Instr & 0x0040e000) == 0x00008000; |
118 | } |
119 | |
120 | static bool isST1Single(uint32_t Instr) { |
121 | return (Instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(Instr); |
122 | } |
123 | |
124 | |
125 | static bool isST1SinglePost(uint32_t Instr) { |
126 | return (Instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(Instr); |
127 | } |
128 | |
129 | static bool isST1(uint32_t Instr) { |
130 | return isST1Multiple(Instr) || isST1MultiplePost(Instr) || |
131 | isST1Single(Instr) || isST1SinglePost(Instr); |
132 | } |
133 | |
134 | |
135 | |
136 | |
137 | static bool isLoadStoreExclusive(uint32_t Instr) { |
138 | return (Instr & 0x3f000000) == 0x08000000; |
139 | } |
140 | |
141 | static bool isLoadExclusive(uint32_t Instr) { |
142 | return (Instr & 0x3f400000) == 0x08400000; |
143 | } |
144 | |
145 | |
146 | |
147 | static bool isLoadLiteral(uint32_t Instr) { |
148 | return (Instr & 0x3b000000) == 0x18000000; |
149 | } |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | static bool isSTNP(uint32_t Instr) { |
157 | return (Instr & 0x3bc00000) == 0x28000000; |
158 | } |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | static bool isSTPPost(uint32_t Instr) { |
166 | return (Instr & 0x3bc00000) == 0x28800000; |
167 | } |
168 | |
169 | |
170 | |
171 | static bool isSTPOffset(uint32_t Instr) { |
172 | return (Instr & 0x3bc00000) == 0x29000000; |
173 | } |
174 | |
175 | |
176 | |
177 | |
178 | static bool isSTPPre(uint32_t Instr) { |
179 | return (Instr & 0x3bc00000) == 0x29800000; |
180 | } |
181 | |
182 | static bool isSTP(uint32_t Instr) { |
183 | return isSTPPost(Instr) || isSTPOffset(Instr) || isSTPPre(Instr); |
184 | } |
185 | |
186 | |
187 | |
188 | |
189 | static bool isLoadStoreUnscaled(uint32_t Instr) { |
190 | return (Instr & 0x3b000c00) == 0x38000000; |
191 | } |
192 | |
193 | |
194 | |
195 | static bool isLoadStoreImmediatePost(uint32_t Instr) { |
196 | return (Instr & 0x3b200c00) == 0x38000400; |
197 | } |
198 | |
199 | |
200 | |
201 | static bool isLoadStoreUnpriv(uint32_t Instr) { |
202 | return (Instr & 0x3b200c00) == 0x38000800; |
203 | } |
204 | |
205 | |
206 | |
207 | static bool isLoadStoreImmediatePre(uint32_t Instr) { |
208 | return (Instr & 0x3b200c00) == 0x38000c00; |
209 | } |
210 | |
211 | |
212 | |
213 | static bool isLoadStoreRegisterOff(uint32_t Instr) { |
214 | return (Instr & 0x3b200c00) == 0x38200800; |
215 | } |
216 | |
217 | |
218 | |
219 | static bool isLoadStoreRegisterUnsigned(uint32_t Instr) { |
220 | return (Instr & 0x3b000000) == 0x39000000; |
221 | } |
222 | |
223 | |
224 | static uint32_t getRt(uint32_t Instr) { return (Instr & 0x1f); } |
225 | |
226 | |
227 | static uint32_t getRn(uint32_t Instr) { return (Instr >> 5) & 0x1f; } |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | static bool isBranch(uint32_t Instr) { |
237 | return ((Instr & 0xfe000000) == 0xd6000000) || |
238 | ((Instr & 0xfe000000) == 0x54000000) || |
239 | ((Instr & 0x7c000000) == 0x14000000) || |
240 | ((Instr & 0x7c000000) == 0x34000000); |
241 | } |
242 | |
243 | static bool isV8SingleRegisterNonStructureLoadStore(uint32_t Instr) { |
244 | return isLoadStoreUnscaled(Instr) || isLoadStoreImmediatePost(Instr) || |
245 | isLoadStoreUnpriv(Instr) || isLoadStoreImmediatePre(Instr) || |
246 | isLoadStoreRegisterOff(Instr) || isLoadStoreRegisterUnsigned(Instr); |
247 | } |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | static bool isV8NonStructureLoad(uint32_t Instr) { |
254 | if (isLoadExclusive(Instr)) |
255 | return true; |
256 | if (isLoadLiteral(Instr)) |
257 | return true; |
258 | else if (isV8SingleRegisterNonStructureLoadStore(Instr)) { |
259 | |
260 | |
261 | uint32_t Size = (Instr >> 30) & 0xff; |
262 | uint32_t V = (Instr >> 26) & 0x1; |
263 | uint32_t Opc = (Instr >> 22) & 0x3; |
264 | |
265 | |
266 | |
267 | |
268 | |
269 | return Opc != 0 && !(Size == 0 && V == 1 && Opc == 2) && |
270 | !(Size == 3 && V == 0 && Opc == 2); |
271 | } |
272 | return false; |
273 | } |
274 | |
275 | |
276 | |
277 | |
278 | |
279 | static bool hasWriteback(uint32_t Instr) { |
280 | return isLoadStoreImmediatePre(Instr) || isLoadStoreImmediatePost(Instr) || |
281 | isSTPPre(Instr) || isSTPPost(Instr) || isST1SinglePost(Instr) || |
282 | isST1MultiplePost(Instr); |
283 | } |
284 | |
285 | |
286 | |
287 | |
288 | static bool doesLoadStoreWriteToReg(uint32_t Instr, uint32_t Reg) { |
289 | return (isV8NonStructureLoad(Instr) && getRt(Instr) == Reg) || |
290 | (hasWriteback(Instr) && getRn(Instr) == Reg); |
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 | |
317 | |
318 | |
319 | |
320 | |
321 | |
322 | static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2, |
323 | uint32_t Instr4) { |
324 | if (!isADRP(Instr1)) |
325 | return false; |
326 | |
327 | uint32_t Rn = getRt(Instr1); |
328 | return isLoadStoreClass(Instr2) && |
329 | (isLoadStoreExclusive(Instr2) || isLoadLiteral(Instr2) || |
330 | isV8SingleRegisterNonStructureLoadStore(Instr2) || isSTP(Instr2) || |
331 | isSTNP(Instr2) || isST1(Instr2)) && |
332 | !doesLoadStoreWriteToReg(Instr2, Rn) && |
333 | isLoadStoreRegisterUnsigned(Instr4) && getRn(Instr4) == Rn; |
334 | } |
335 | |
336 | |
337 | |
338 | |
339 | |
340 | |
341 | |
342 | static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off, |
343 | uint64_t Limit) { |
344 | uint64_t ISAddr = IS->getVA(0); |
345 | |
346 | |
347 | uint64_t InitialPageOff = (ISAddr + Off) & 0xfff; |
348 | if (InitialPageOff < 0xff8) |
349 | Off += 0xff8 - InitialPageOff; |
350 | |
351 | bool OptionalAllowed = Limit - Off > 12; |
352 | if (Off >= Limit || Limit - Off < 12) { |
353 | |
354 | Off = Limit; |
355 | return 0; |
356 | } |
357 | |
358 | uint64_t PatchOff = 0; |
359 | const uint8_t *Buf = IS->data().begin(); |
360 | const ulittle32_t *InstBuf = reinterpret_cast<const ulittle32_t *>(Buf + Off); |
361 | uint32_t Instr1 = *InstBuf++; |
362 | uint32_t Instr2 = *InstBuf++; |
363 | uint32_t Instr3 = *InstBuf++; |
364 | if (is843419ErratumSequence(Instr1, Instr2, Instr3)) { |
365 | PatchOff = Off + 8; |
366 | } else if (OptionalAllowed && !isBranch(Instr3)) { |
367 | uint32_t Instr4 = *InstBuf++; |
368 | if (is843419ErratumSequence(Instr1, Instr2, Instr4)) |
369 | PatchOff = Off + 12; |
370 | } |
371 | if (((ISAddr + Off) & 0xfff) == 0xff8) |
372 | Off += 4; |
373 | else |
374 | Off += 0xffc; |
375 | return PatchOff; |
376 | } |
377 | |
378 | class lld::elf::Patch843419Section : public SyntheticSection { |
379 | public: |
380 | Patch843419Section(InputSection *P, uint64_t Off); |
381 | |
382 | void writeTo(uint8_t *Buf) override; |
383 | |
384 | size_t getSize() const override { return 8; } |
385 | |
386 | uint64_t getLDSTAddr() const; |
387 | |
388 | |
389 | const InputSection *Patchee; |
390 | |
391 | uint64_t PatcheeOffset; |
392 | |
393 | Symbol *PatchSym; |
394 | }; |
395 | |
396 | lld::elf::Patch843419Section::Patch843419Section(InputSection *P, uint64_t Off) |
397 | : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4, |
398 | ".text.patch"), |
399 | Patchee(P), PatcheeOffset(Off) { |
400 | this->Parent = P->getParent(); |
401 | PatchSym = addSyntheticLocal( |
402 | Saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0, |
403 | getSize(), *this); |
404 | addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, *this); |
405 | } |
406 | |
407 | uint64_t lld::elf::Patch843419Section::getLDSTAddr() const { |
408 | return Patchee->getVA(PatcheeOffset); |
409 | } |
410 | |
411 | void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) { |
412 | |
413 | |
414 | write32le(Buf, read32le(Patchee->data().begin() + PatcheeOffset)); |
415 | |
416 | |
417 | |
418 | |
419 | this->relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + getSize()); |
420 | |
421 | |
422 | uint64_t S = getLDSTAddr() + 4; |
423 | uint64_t P = PatchSym->getVA() + 4; |
424 | Target->relocateOne(Buf + 4, R_AARCH64_JUMP26, S - P); |
425 | } |
426 | |
427 | void AArch64Err843419Patcher::init() { |
428 | |
429 | |
430 | |
431 | |
432 | |
433 | |
434 | |
435 | |
436 | |
437 | |
438 | auto IsCodeMapSymbol = [](const Symbol *B) { |
439 | return B->getName() == "$x" || B->getName().startswith("$x."); |
440 | }; |
441 | auto IsDataMapSymbol = [](const Symbol *B) { |
442 | return B->getName() == "$d" || B->getName().startswith("$d."); |
443 | }; |
444 | |
445 | |
446 | for (InputFile *File : ObjectFiles) { |
447 | auto *F = cast<ObjFile<ELF64LE>>(File); |
448 | for (Symbol *B : F->getLocalSymbols()) { |
449 | auto *Def = dyn_cast<Defined>(B); |
450 | if (!Def) |
451 | continue; |
452 | if (!IsCodeMapSymbol(Def) && !IsDataMapSymbol(Def)) |
453 | continue; |
454 | if (auto *Sec = dyn_cast_or_null<InputSection>(Def->Section)) |
455 | if (Sec->Flags & SHF_EXECINSTR) |
456 | SectionMap[Sec].push_back(Def); |
457 | } |
458 | } |
459 | |
460 | |
461 | |
462 | |
463 | for (auto &KV : SectionMap) { |
464 | std::vector<const Defined *> &MapSyms = KV.second; |
465 | if (MapSyms.size() <= 1) |
466 | continue; |
467 | std::stable_sort( |
468 | MapSyms.begin(), MapSyms.end(), |
469 | [](const Defined *A, const Defined *B) { return A->Value < B->Value; }); |
470 | MapSyms.erase( |
471 | std::unique(MapSyms.begin(), MapSyms.end(), |
472 | [=](const Defined *A, const Defined *B) { |
473 | return (IsCodeMapSymbol(A) && IsCodeMapSymbol(B)) || |
474 | (IsDataMapSymbol(A) && IsDataMapSymbol(B)); |
475 | }), |
476 | MapSyms.end()); |
477 | } |
478 | Initialized = true; |
479 | } |
480 | |
481 | |
482 | |
483 | |
484 | |
485 | |
486 | void AArch64Err843419Patcher::insertPatches( |
487 | InputSectionDescription &ISD, std::vector<Patch843419Section *> &Patches) { |
488 | uint64_t ISLimit; |
| 10 | | 'ISLimit' declared without an initial value | |
|
489 | uint64_t PrevISLimit = ISD.Sections.front()->OutSecOff; |
490 | uint64_t PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing(); |
491 | |
492 | |
493 | |
494 | |
495 | auto PatchIt = Patches.begin(); |
496 | auto PatchEnd = Patches.end(); |
497 | for (const InputSection *IS : ISD.Sections) { |
498 | ISLimit = IS->OutSecOff + IS->getSize(); |
499 | if (ISLimit > PatchUpperBound) { |
500 | while (PatchIt != PatchEnd) { |
501 | if ((*PatchIt)->getLDSTAddr() >= PrevISLimit) |
502 | break; |
503 | (*PatchIt)->OutSecOff = PrevISLimit; |
504 | ++PatchIt; |
505 | } |
506 | PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing(); |
507 | } |
508 | PrevISLimit = ISLimit; |
509 | } |
510 | for (; PatchIt != PatchEnd; ++PatchIt) { |
| 11 | | Loop condition is true. Entering loop body | |
|
511 | (*PatchIt)->OutSecOff = ISLimit; |
| 12 | | Assigned value is garbage or undefined |
|
512 | } |
513 | |
514 | |
515 | |
516 | |
517 | |
518 | std::vector<InputSection *> Tmp; |
519 | Tmp.reserve(ISD.Sections.size() + Patches.size()); |
520 | auto MergeCmp = [](const InputSection *A, const InputSection *B) { |
521 | if (A->OutSecOff < B->OutSecOff) |
522 | return true; |
523 | if (A->OutSecOff == B->OutSecOff && isa<Patch843419Section>(A) && |
524 | !isa<Patch843419Section>(B)) |
525 | return true; |
526 | return false; |
527 | }; |
528 | std::merge(ISD.Sections.begin(), ISD.Sections.end(), Patches.begin(), |
529 | Patches.end(), std::back_inserter(Tmp), MergeCmp); |
530 | ISD.Sections = std::move(Tmp); |
531 | } |
532 | |
533 | |
534 | |
535 | |
536 | |
537 | static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset, |
538 | InputSection *IS, |
539 | std::vector<Patch843419Section *> &Patches) { |
540 | |
541 | |
542 | |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | auto RelIt = std::find_if( |
552 | IS->Relocations.begin(), IS->Relocations.end(), |
553 | [=](const Relocation &R) { return R.Offset == PatcheeOffset; }); |
554 | if (RelIt != IS->Relocations.end() && RelIt->Type == R_AARCH64_JUMP26) |
555 | return; |
556 | |
557 | log("detected cortex-a53-843419 erratum sequence starting at " + |
558 | utohexstr(AdrpAddr) + " in unpatched output."); |
559 | |
560 | auto *PS = make<Patch843419Section>(IS, PatcheeOffset); |
561 | Patches.push_back(PS); |
562 | |
563 | auto MakeRelToPatch = [](uint64_t Offset, Symbol *PatchSym) { |
564 | return Relocation{R_PC, R_AARCH64_JUMP26, Offset, 0, PatchSym}; |
565 | }; |
566 | |
567 | if (RelIt != IS->Relocations.end()) { |
568 | PS->Relocations.push_back( |
569 | {RelIt->Expr, RelIt->Type, 0, RelIt->Addend, RelIt->Sym}); |
570 | *RelIt = MakeRelToPatch(PatcheeOffset, PS->PatchSym); |
571 | } else |
572 | IS->Relocations.push_back(MakeRelToPatch(PatcheeOffset, PS->PatchSym)); |
573 | } |
574 | |
575 | |
576 | |
577 | |
578 | std::vector<Patch843419Section *> |
579 | AArch64Err843419Patcher::patchInputSectionDescription( |
580 | InputSectionDescription &ISD) { |
581 | std::vector<Patch843419Section *> Patches; |
582 | for (InputSection *IS : ISD.Sections) { |
583 | |
584 | if (isa<SyntheticSection>(IS)) |
585 | continue; |
586 | |
587 | |
588 | |
589 | |
590 | |
591 | std::vector<const Defined *> &MapSyms = SectionMap[IS]; |
592 | |
593 | auto CodeSym = llvm::find_if(MapSyms, [&](const Defined *MS) { |
594 | return MS->getName().startswith("$x"); |
595 | }); |
596 | |
597 | while (CodeSym != MapSyms.end()) { |
598 | auto DataSym = std::next(CodeSym); |
599 | uint64_t Off = (*CodeSym)->Value; |
600 | uint64_t Limit = |
601 | (DataSym == MapSyms.end()) ? IS->data().size() : (*DataSym)->Value; |
602 | |
603 | while (Off < Limit) { |
604 | uint64_t StartAddr = IS->getVA(Off); |
605 | if (uint64_t PatcheeOffset = scanCortexA53Errata843419(IS, Off, Limit)) |
606 | implementPatch(StartAddr, PatcheeOffset, IS, Patches); |
607 | } |
608 | if (DataSym == MapSyms.end()) |
609 | break; |
610 | CodeSym = std::next(DataSym); |
611 | } |
612 | } |
613 | return Patches; |
614 | } |
615 | |
616 | |
617 | |
618 | |
619 | |
620 | |
621 | |
622 | |
623 | |
624 | |
625 | |
626 | |
627 | |
628 | bool AArch64Err843419Patcher::createFixes() { |
629 | if (Initialized == false) |
| 1 | Assuming the condition is false | |
|
| |
630 | init(); |
631 | |
632 | bool AddressesChanged = false; |
633 | for (OutputSection *OS : OutputSections) { |
634 | if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) |
| 3 | | Assuming the condition is false | |
|
| 4 | | Assuming the condition is false | |
|
| |
635 | continue; |
636 | for (BaseCommand *BC : OS->SectionCommands) |
637 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { |
| |
638 | std::vector<Patch843419Section *> Patches = |
639 | patchInputSectionDescription(*ISD); |
640 | if (!Patches.empty()) { |
| 7 | | Assuming the condition is true | |
|
| |
641 | insertPatches(*ISD, Patches); |
| 9 | | Calling 'AArch64Err843419Patcher::insertPatches' | |
|
642 | AddressesChanged = true; |
643 | } |
644 | } |
645 | } |
646 | return AddressesChanged; |
647 | } |