Index: llvm/include/llvm/MC/MCInstrAnalysis.h =================================================================== --- llvm/include/llvm/MC/MCInstrAnalysis.h +++ llvm/include/llvm/MC/MCInstrAnalysis.h @@ -147,10 +147,13 @@ } /// Given a branch instruction try to get the address the branch - /// targets. Return true on success, and the address in Target. - virtual bool - evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, - uint64_t &Target) const; + /// targets. Some callers may pass PreviousInst, which (if present) will be + /// used on targets that use two-instruction branch sequences. Return true + /// on success, and the address in Target. + virtual bool evaluateBranch(const MCInst &Inst, + const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, + uint64_t &Target) const; /// Given an instruction tries to get the address of a memory operand. Returns /// the address on success. Index: llvm/lib/MC/MCInstrAnalysis.cpp =================================================================== --- llvm/lib/MC/MCInstrAnalysis.cpp +++ llvm/lib/MC/MCInstrAnalysis.cpp @@ -23,8 +23,9 @@ return false; } -bool MCInstrAnalysis::evaluateBranch(const MCInst & /*Inst*/, uint64_t /*Addr*/, - uint64_t /*Size*/, +bool MCInstrAnalysis::evaluateBranch(const MCInst & /*Inst*/, + const Optional & /*PreviousInst*/, + uint64_t /*Addr*/, uint64_t /*Size*/, uint64_t & /*Target*/) const { return false; } Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp +++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp @@ -322,7 +322,8 @@ public: AArch64MCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { // Search for a PC-relative argument. // This will handle instructions like bcc (where the first argument is the Index: llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp +++ llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp @@ -118,7 +118,8 @@ explicit AMDGPUMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { if (Inst.getNumOperands() == 0 || !Inst.getOperand(0).isImm() || Info->get(Inst.getOpcode()).OpInfo[0].OperandType != Index: llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -426,7 +426,8 @@ return MCInstrAnalysis::isConditionalBranch(Inst); } - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { const MCInstrDesc &Desc = Info->get(Inst.getOpcode()); Index: llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp +++ llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp @@ -75,7 +75,8 @@ explicit BPFMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { // The target is the 3rd operand of cond inst and the 1st of uncond inst. int16_t Imm; Index: llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -588,8 +588,9 @@ return MCInstrAnalysis::isConditionalBranch(Inst); } - bool evaluateBranch(MCInst const &Inst, uint64_t Addr, - uint64_t Size, uint64_t &Target) const override { + bool evaluateBranch(MCInst const &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { if (!(isCall(Inst) || isUnconditionalBranch(Inst) || isConditionalBranch(Inst))) return false; Index: llvm/lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp +++ llvm/lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp @@ -93,7 +93,8 @@ explicit LanaiMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { if (Inst.getNumOperands() == 0) return false; Index: llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -137,7 +137,8 @@ public: MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { unsigned NumOps = Inst.getNumOperands(); if (NumOps == 0) Index: llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -376,7 +376,8 @@ explicit PPCMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { unsigned NumOps = Inst.getNumOperands(); if (NumOps == 0 || Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -119,7 +119,8 @@ explicit RISCVMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override { if (isConditionalBranch(Inst)) { int64_t Imm; Index: llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp =================================================================== --- llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp +++ llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp @@ -417,7 +417,7 @@ // binary object. if (SymbolizeOperands && MIA) { uint64_t Target; - if (MIA->evaluateBranch(*MI, 0, 0, Target)) + if (MIA->evaluateBranch(*MI, Optional(), 0, 0, Target)) return; if (MIA->evaluateMemoryOperandAddress(*MI, /*STI=*/nullptr, 0, 0)) return; Index: llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp =================================================================== --- llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp +++ llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp @@ -375,7 +375,7 @@ // binary object. if (SymbolizeOperands && MIA) { uint64_t Target; - if (MIA->evaluateBranch(*MI, 0, 0, Target)) + if (MIA->evaluateBranch(*MI, Optional(), 0, 0, Target)) return; if (MIA->evaluateMemoryOperandAddress(*MI, /*STI=*/nullptr, 0, 0)) return; Index: llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp =================================================================== --- llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -402,7 +402,8 @@ uint64_t GotSectionVA, const Triple &TargetTriple) const override; - bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + bool evaluateBranch(const MCInst &Inst, const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, uint64_t &Target) const override; Optional evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI, @@ -526,8 +527,10 @@ } } -bool X86MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, - uint64_t Size, uint64_t &Target) const { +bool X86MCInstrAnalysis::evaluateBranch(const MCInst &Inst, + const Optional &PreviousInst, + uint64_t Addr, uint64_t Size, + uint64_t &Target) const { if (Inst.getNumOperands() == 0 || Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL) return false; Index: llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp =================================================================== --- llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp +++ llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp @@ -175,8 +175,9 @@ if (!InstrDesc.isCall()) return false; uint64_t Target; - if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress, - InstrMeta.InstructionSize, Target)) + if (!MIA->evaluateBranch(InstrMeta.Instruction, Optional(), + InstrMeta.VMAddress, InstrMeta.InstructionSize, + Target)) return false; return TrapOnFailFunctionAddresses.contains(Target); } @@ -210,8 +211,9 @@ return nullptr; uint64_t Target; - if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress, - InstrMeta.InstructionSize, Target)) + if (!MIA->evaluateBranch(InstrMeta.Instruction, Optional(), + InstrMeta.VMAddress, InstrMeta.InstructionSize, + Target)) return nullptr; NextMetaPtr = getInstruction(Target); @@ -504,7 +506,8 @@ continue; uint64_t Target; - if (MIA->evaluateBranch(Instruction, VMAddress, InstructionSize, Target)) { + if (MIA->evaluateBranch(Instruction, Optional(), VMAddress, + InstructionSize, Target)) { // If the target can be evaluated, it's not indirect. StaticBranchTargetings[Target].push_back(VMAddress); continue; Index: llvm/tools/llvm-cfi-verify/lib/GraphBuilder.cpp =================================================================== --- llvm/tools/llvm-cfi-verify/lib/GraphBuilder.cpp +++ llvm/tools/llvm-cfi-verify/lib/GraphBuilder.cpp @@ -137,8 +137,9 @@ // We already know the fallthrough, evaluate the target. uint64_t Target; if (!Analysis.getMCInstrAnalysis()->evaluateBranch( - BranchInstrMeta.Instruction, BranchInstrMeta.VMAddress, - BranchInstrMeta.InstructionSize, Target)) { + BranchInstrMeta.Instruction, Optional(), + BranchInstrMeta.VMAddress, BranchInstrMeta.InstructionSize, + Target)) { errs() << "Failed to get branch target for conditional branch at address " << format_hex(BranchInstrMeta.VMAddress, 2) << ".\n"; return; @@ -254,7 +255,7 @@ // of a fallthrough or the target of a branch. uint64_t BranchTarget; if (!Analysis.getMCInstrAnalysis()->evaluateBranch( - ParentMeta.Instruction, ParentMeta.VMAddress, + ParentMeta.Instruction, Optional(), ParentMeta.VMAddress, ParentMeta.InstructionSize, BranchTarget)) { errs() << "Failed to evaluate branch target for instruction at address " << format_hex(ParentMeta.VMAddress, 2) << ".\n"; Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -987,6 +987,7 @@ Start += SectionAddr; End += SectionAddr; uint64_t Index = Start; + Optional PreviousInst; while (Index < End) { // Disassemble a real instruction and record function-local branch labels. MCInst Inst; @@ -998,7 +999,8 @@ if (Disassembled && MIA) { uint64_t Target; - bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target); + bool TargetKnown = + MIA->evaluateBranch(Inst, PreviousInst, Index, Size, Target); // On PowerPC, if the address of a branch is the same as the target, it // means that it's a function call. Do not mark the label for this case. if (TargetKnown && (Target >= Start && Target < End) && @@ -1007,6 +1009,11 @@ Labels[Target] = ("L" + Twine(LabelCount++)).str(); } + if (Disassembled) + PreviousInst = Inst; + else + PreviousInst.reset(); + Index += Size; } } @@ -1408,6 +1415,8 @@ collectLocalBranchTargets(Bytes, MIA, DisAsm, IP, PrimarySTI, SectionAddr, Index, End, AllLabels); + Optional PreviousInst; + while (Index < End) { // ARM and AArch64 ELF binaries can interleave data and text in the // same section. We rely on the markers introduced to understand what @@ -1483,8 +1492,8 @@ // Branch targets are printed just after the instructions. llvm::raw_ostream *TargetOS = &FOS; uint64_t Target; - bool PrintTarget = - MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target); + bool PrintTarget = MIA->evaluateBranch( + Inst, PreviousInst, SectionAddr + Index, Size, Target); if (!PrintTarget) if (Optional MaybeTarget = MIA->evaluateMemoryOperandAddress( @@ -1577,6 +1586,10 @@ *TargetOS << "\n"; } } + if (Disassembled) + PreviousInst = Inst; + else + PreviousInst.reset(); } assert(Ctx.getAsmInfo()); Index: llvm/tools/sancov/sancov.cpp =================================================================== --- llvm/tools/sancov/sancov.cpp +++ llvm/tools/sancov/sancov.cpp @@ -768,7 +768,8 @@ uint64_t CovPoint = getPreviousInstructionPc(Addr + Size, TheTriple); uint64_t Target; if (MIA->isCall(Inst) && - MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target) && + MIA->evaluateBranch(Inst, Optional(), SectionAddr + Index, + Size, Target) && SanCovAddrs.find(Target) != SanCovAddrs.end()) Addrs->insert(CovPoint); }