[bolt] Fix std::prev()-past-begin in veneer handling code
authorNico Weber <thakis@chromium.org>
Fri, 18 Nov 2022 19:28:59 +0000 (14:28 -0500)
committerNico Weber <thakis@chromium.org>
Fri, 18 Nov 2022 19:42:08 +0000 (14:42 -0500)
matchLinkerVeneer() returns 3 if `Instruction` and the last
two instructions in `[Instructions.begin, Instructions.end())`
match the pattern

    ADRP  x16, imm
    ADD   x16, x16, imm
    BR    x16

BinaryContext.cpp used to use

    --Count;
    for (auto It = std::prev(Instructions.end()); Count != 0;
         It = std::prev(It), --Count) {
      ...use It...
    }

to walk these instructions. The first `--Count` skips the
instruction that's in `Instruction` instead of in `Instructions`.
The loop then walks over `Instructions`.

However, on the last iteration, this calls `std::prev()` on an
iterator that points at the container's begin(), which can blow
up.

Instead, use rbegin(), which sidesteps this issue.

Fixes test/AArch64/veneer-gold.s on a macOS host.
With this, check-bolt passes on macOS.

Differential Revision: https://reviews.llvm.org/D138313

bolt/lib/Core/BinaryContext.cpp

index d09d8af..9b614af 100644 (file)
@@ -1191,8 +1191,7 @@ bool BinaryContext::handleAArch64Veneer(uint64_t Address, bool MatchOnly) {
     MIB->addAnnotation(Instruction, "AArch64Veneer", true);
     Veneer->addInstruction(Offset, std::move(Instruction));
     --Count;
-    for (auto It = std::prev(Instructions.end()); Count != 0;
-         It = std::prev(It), --Count) {
+    for (auto It = Instructions.rbegin(); Count != 0; ++It, --Count) {
       MIB->addAnnotation(It->second, "AArch64Veneer", true);
       Veneer->addInstruction(It->first, std::move(It->second));
     }