[llvm] r315504 - Reland 'Classify llvm-cfi-verify.'

Marcello Maggioni via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 11 21:52:34 PDT 2017


Thanks Vlad for the fast reply!

Marcello

> On Oct 11, 2017, at 9:18 PM, Vlad Tsyrklevich <vlad at tsyrklevich.net> wrote:
> 
> Hey Marcello, sorry about that. This failure got lost in all of the other broken buildbot spam today. I've disabled the test from being built for build configs without the X86 target until I can take a look at it tomorrow.
> 
> On Wed, Oct 11, 2017 at 8:09 PM Marcello Maggioni <mmaggioni at apple.com <mailto:mmaggioni at apple.com>> wrote:
> Hi Vlad,
> 
> The test you added here for FileAnalysis seems to be failing if you don’t have x86 compiled. Is there a way to make that test to be unsupported if x86 is not compiled? It is making our internal validation fail where we don’t compile x86
> .
> Marcello
> 
> > On Oct 11, 2017, at 1:35 PM, Vlad Tsyrklevich via llvm-commits <llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>> wrote:
> >
> > Author: vlad.tsyrklevich
> > Date: Wed Oct 11 13:35:01 2017
> > New Revision: 315504
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=315504&view=rev <http://llvm.org/viewvc/llvm-project?rev=315504&view=rev>
> > Log:
> > Reland 'Classify llvm-cfi-verify.'
> >
> > Summary: Move llvm-cfi-verify into a class in preparation for CFI analysis to come.
> >
> > Reviewers: vlad.tsyrklevich
> >
> > Reviewed By: vlad.tsyrklevich
> >
> > Subscribers: mgorny, llvm-commits, pcc, kcc
> >
> > Differential Revision: https://reviews.llvm.org/D38379 <https://reviews.llvm.org/D38379>
> >
> > Added:
> >    llvm/trunk/tools/llvm-cfi-verify/lib/
> >    llvm/trunk/tools/llvm-cfi-verify/lib/CMakeLists.txt
> >    llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
> >    llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h
> >    llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt
> >      - copied, changed from r315502, llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt
> >    llvm/trunk/unittests/tools/
> >    llvm/trunk/unittests/tools/CMakeLists.txt
> >    llvm/trunk/unittests/tools/llvm-cfi-verify/
> >    llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt
> >      - copied, changed from r315502, llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt
> >    llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp
> > Modified:
> >    llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt
> >    llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt
> >    llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
> >    llvm/trunk/unittests/CMakeLists.txt
> >
> > Modified: llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt?rev=315504&r1=315503&r2=315504&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt?rev=315504&r1=315503&r2=315504&view=diff>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt (original)
> > +++ llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt Wed Oct 11 13:35:01 2017
> > @@ -5,7 +5,6 @@ set(LLVM_LINK_COMPONENTS
> >   AllTargetsDisassemblers
> >   AllTargetsInfos
> >   MC
> > -  Object
> >   MCParser
> >   Object
> >   Support
> > @@ -13,4 +12,7 @@ set(LLVM_LINK_COMPONENTS
> >
> > add_llvm_tool(llvm-cfi-verify
> >   llvm-cfi-verify.cpp
> > +  lib/FileAnalysis.cpp
> >   )
> > +
> > +add_subdirectory(lib)
> >
> > Modified: llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt?rev=315504&r1=315503&r2=315504&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt?rev=315504&r1=315503&r2=315504&view=diff>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt (original)
> > +++ llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt Wed Oct 11 13:35:01 2017
> > @@ -19,4 +19,4 @@
> > type = Tool
> > name = llvm-cfi-verify
> > parent = Tools
> > -required_libraries = MC MCDisassembler MCParser Support all-targets
> > +required_libraries = all-targets MC MCDisassembler MCParser Support
> >
> > Added: llvm/trunk/tools/llvm-cfi-verify/lib/CMakeLists.txt
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/CMakeLists.txt?rev=315504&view=auto <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/CMakeLists.txt?rev=315504&view=auto>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/lib/CMakeLists.txt (added)
> > +++ llvm/trunk/tools/llvm-cfi-verify/lib/CMakeLists.txt Wed Oct 11 13:35:01 2017
> > @@ -0,0 +1,9 @@
> > +add_llvm_library(LLVMCFIVerify
> > +  FileAnalysis.cpp
> > +  FileAnalysis.h
> > +
> > +  LINK_COMPONENTS
> > +  MC
> > +  MCParser
> > +  Object
> > +  Support)
> >
> > Added: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp?rev=315504&view=auto <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp?rev=315504&view=auto>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp (added)
> > +++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp Wed Oct 11 13:35:01 2017
> > @@ -0,0 +1,277 @@
> > +//===- FileAnalysis.cpp -----------------------------------------*- C++ -*-===//
> > +//
> > +//                      The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===----------------------------------------------------------------------===//
> > +
> > +#include "FileAnalysis.h"
> > +
> > +#include "llvm/BinaryFormat/ELF.h"
> > +#include "llvm/MC/MCAsmInfo.h"
> > +#include "llvm/MC/MCContext.h"
> > +#include "llvm/MC/MCDisassembler/MCDisassembler.h"
> > +#include "llvm/MC/MCInst.h"
> > +#include "llvm/MC/MCInstPrinter.h"
> > +#include "llvm/MC/MCInstrAnalysis.h"
> > +#include "llvm/MC/MCInstrDesc.h"
> > +#include "llvm/MC/MCInstrInfo.h"
> > +#include "llvm/MC/MCObjectFileInfo.h"
> > +#include "llvm/MC/MCRegisterInfo.h"
> > +#include "llvm/MC/MCSubtargetInfo.h"
> > +#include "llvm/Object/Binary.h"
> > +#include "llvm/Object/COFF.h"
> > +#include "llvm/Object/ELFObjectFile.h"
> > +#include "llvm/Object/ObjectFile.h"
> > +#include "llvm/Support/Casting.h"
> > +#include "llvm/Support/CommandLine.h"
> > +#include "llvm/Support/Error.h"
> > +#include "llvm/Support/FormatVariadic.h"
> > +#include "llvm/Support/MemoryBuffer.h"
> > +#include "llvm/Support/TargetRegistry.h"
> > +#include "llvm/Support/TargetSelect.h"
> > +#include "llvm/Support/raw_ostream.h"
> > +
> > +#include <functional>
> > +
> > +using Instr = llvm::cfi_verify::FileAnalysis::Instr;
> > +
> > +namespace llvm {
> > +namespace cfi_verify {
> > +
> > +Expected<FileAnalysis> FileAnalysis::Create(StringRef Filename) {
> > +  // Open the filename provided.
> > +  Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
> > +      object::createBinary(Filename);
> > +  if (!BinaryOrErr)
> > +    return BinaryOrErr.takeError();
> > +
> > +  // Construct the object and allow it to take ownership of the binary.
> > +  object::OwningBinary<object::Binary> Binary = std::move(BinaryOrErr.get());
> > +  FileAnalysis Analysis(std::move(Binary));
> > +
> > +  Analysis.Object = dyn_cast<object::ObjectFile>(Analysis.Binary.getBinary());
> > +  if (!Analysis.Object)
> > +    return make_error<UnsupportedDisassembly>();
> > +
> > +  Analysis.ObjectTriple = Analysis.Object->makeTriple();
> > +  Analysis.Features = Analysis.Object->getFeatures();
> > +
> > +  // Init the rest of the object.
> > +  if (auto InitResponse = Analysis.initialiseDisassemblyMembers())
> > +    return std::move(InitResponse);
> > +
> > +  if (auto SectionParseResponse = Analysis.parseCodeSections())
> > +    return std::move(SectionParseResponse);
> > +
> > +  return std::move(Analysis);
> > +}
> > +
> > +FileAnalysis::FileAnalysis(object::OwningBinary<object::Binary> Binary)
> > +    : Binary(std::move(Binary)) {}
> > +
> > +FileAnalysis::FileAnalysis(const Triple &ObjectTriple,
> > +                           const SubtargetFeatures &Features)
> > +    : ObjectTriple(ObjectTriple), Features(Features) {}
> > +
> > +const Instr *
> > +FileAnalysis::getPrevInstructionSequential(const Instr &InstrMeta) const {
> > +  std::map<uint64_t, Instr>::const_iterator KV =
> > +      Instructions.find(InstrMeta.VMAddress);
> > +  if (KV == Instructions.end() || KV == Instructions.begin())
> > +    return nullptr;
> > +
> > +  if (!(--KV)->second.Valid)
> > +    return nullptr;
> > +
> > +  return &KV->second;
> > +}
> > +
> > +const Instr *
> > +FileAnalysis::getNextInstructionSequential(const Instr &InstrMeta) const {
> > +  std::map<uint64_t, Instr>::const_iterator KV =
> > +      Instructions.find(InstrMeta.VMAddress);
> > +  if (KV == Instructions.end() || ++KV == Instructions.end())
> > +    return nullptr;
> > +
> > +  if (!KV->second.Valid)
> > +    return nullptr;
> > +
> > +  return &KV->second;
> > +}
> > +
> > +bool FileAnalysis::usesRegisterOperand(const Instr &InstrMeta) const {
> > +  for (const auto &Operand : InstrMeta.Instruction) {
> > +    if (Operand.isReg())
> > +      return true;
> > +  }
> > +  return false;
> > +}
> > +
> > +const Instr *FileAnalysis::getInstruction(uint64_t Address) const {
> > +  const auto &InstrKV = Instructions.find(Address);
> > +  if (InstrKV == Instructions.end())
> > +    return nullptr;
> > +
> > +  return &InstrKV->second;
> > +}
> > +
> > +const Instr &FileAnalysis::getInstructionOrDie(uint64_t Address) const {
> > +  const auto &InstrKV = Instructions.find(Address);
> > +  assert(InstrKV != Instructions.end() && "Address doesn't exist.");
> > +  return InstrKV->second;
> > +}
> > +
> > +const std::set<uint64_t> &FileAnalysis::getIndirectInstructions() const {
> > +  return IndirectInstructions;
> > +}
> > +
> > +const MCRegisterInfo *FileAnalysis::getRegisterInfo() const {
> > +  return RegisterInfo.get();
> > +}
> > +
> > +const MCInstrInfo *FileAnalysis::getMCInstrInfo() const { return MII.get(); }
> > +
> > +const MCInstrAnalysis *FileAnalysis::getMCInstrAnalysis() const {
> > +  return MIA.get();
> > +}
> > +
> > +Error FileAnalysis::initialiseDisassemblyMembers() {
> > +  std::string TripleName = ObjectTriple.getTriple();
> > +  ArchName = "";
> > +  MCPU = "";
> > +  std::string ErrorString;
> > +
> > +  ObjectTarget =
> > +      TargetRegistry::lookupTarget(ArchName, ObjectTriple, ErrorString);
> > +  if (!ObjectTarget)
> > +    return make_error<StringError>(Twine("Couldn't find target \"") +
> > +                                       ObjectTriple.getTriple() +
> > +                                       "\", failed with error: " + ErrorString,
> > +                                   inconvertibleErrorCode());
> > +
> > +  RegisterInfo.reset(ObjectTarget->createMCRegInfo(TripleName));
> > +  if (!RegisterInfo)
> > +    return make_error<StringError>("Failed to initialise RegisterInfo.",
> > +                                   inconvertibleErrorCode());
> > +
> > +  AsmInfo.reset(ObjectTarget->createMCAsmInfo(*RegisterInfo, TripleName));
> > +  if (!AsmInfo)
> > +    return make_error<StringError>("Failed to initialise AsmInfo.",
> > +                                   inconvertibleErrorCode());
> > +
> > +  SubtargetInfo.reset(ObjectTarget->createMCSubtargetInfo(
> > +      TripleName, MCPU, Features.getString()));
> > +  if (!SubtargetInfo)
> > +    return make_error<StringError>("Failed to initialise SubtargetInfo.",
> > +                                   inconvertibleErrorCode());
> > +
> > +  MII.reset(ObjectTarget->createMCInstrInfo());
> > +  if (!MII)
> > +    return make_error<StringError>("Failed to initialise MII.",
> > +                                   inconvertibleErrorCode());
> > +
> > +  Context.reset(new MCContext(AsmInfo.get(), RegisterInfo.get(), &MOFI));
> > +
> > +  Disassembler.reset(
> > +      ObjectTarget->createMCDisassembler(*SubtargetInfo, *Context));
> > +
> > +  if (!Disassembler)
> > +    return make_error<StringError>("No disassembler available for target",
> > +                                   inconvertibleErrorCode());
> > +
> > +  MIA.reset(ObjectTarget->createMCInstrAnalysis(MII.get()));
> > +
> > +  Printer.reset(ObjectTarget->createMCInstPrinter(
> > +      ObjectTriple, AsmInfo->getAssemblerDialect(), *AsmInfo, *MII,
> > +      *RegisterInfo));
> > +
> > +  return Error::success();
> > +}
> > +
> > +Error FileAnalysis::parseCodeSections() {
> > +  for (const object::SectionRef &Section : Object->sections()) {
> > +    // Ensure only executable sections get analysed.
> > +    if (!(object::ELFSectionRef(Section).getFlags() & ELF::SHF_EXECINSTR))
> > +      continue;
> > +
> > +    StringRef SectionContents;
> > +    if (Section.getContents(SectionContents))
> > +      return make_error<StringError>("Failed to retrieve section contents",
> > +                                     inconvertibleErrorCode());
> > +
> > +    ArrayRef<uint8_t> SectionBytes((const uint8_t *)SectionContents.data(),
> > +                                   Section.getSize());
> > +    parseSectionContents(SectionBytes, Section.getAddress());
> > +  }
> > +  return Error::success();
> > +}
> > +
> > +void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
> > +                                        uint64_t SectionAddress) {
> > +  MCInst Instruction;
> > +  Instr InstrMeta;
> > +  uint64_t InstructionSize;
> > +
> > +  for (uint64_t Byte = 0; Byte < SectionBytes.size();) {
> > +    bool ValidInstruction =
> > +        Disassembler->getInstruction(Instruction, InstructionSize,
> > +                                     SectionBytes.drop_front(Byte), 0, nulls(),
> > +                                     outs()) == MCDisassembler::Success;
> > +
> > +    Byte += InstructionSize;
> > +
> > +    uint64_t VMAddress = SectionAddress + Byte - InstructionSize;
> > +    InstrMeta.Instruction = Instruction;
> > +    InstrMeta.VMAddress = VMAddress;
> > +    InstrMeta.InstructionSize = InstructionSize;
> > +    InstrMeta.Valid = ValidInstruction;
> > +    addInstruction(InstrMeta);
> > +
> > +    if (!ValidInstruction)
> > +      continue;
> > +
> > +    // Skip additional parsing for instructions that do not affect the control
> > +    // flow.
> > +    const auto &InstrDesc = MII->get(Instruction.getOpcode());
> > +    if (!InstrDesc.mayAffectControlFlow(Instruction, *RegisterInfo))
> > +      continue;
> > +
> > +    uint64_t Target;
> > +    if (MIA->evaluateBranch(Instruction, VMAddress, InstructionSize, Target)) {
> > +      // If the target can be evaluated, it's not indirect.
> > +      StaticBranchTargetings[Target].push_back(VMAddress);
> > +      continue;
> > +    }
> > +
> > +    if (!usesRegisterOperand(InstrMeta))
> > +      continue;
> > +
> > +    IndirectInstructions.insert(VMAddress);
> > +  }
> > +}
> > +
> > +void FileAnalysis::addInstruction(const Instr &Instruction) {
> > +  const auto &KV =
> > +      Instructions.insert(std::make_pair(Instruction.VMAddress, Instruction));
> > +  if (!KV.second) {
> > +    errs() << "Failed to add instruction at address "
> > +           << format_hex(Instruction.VMAddress, 2)
> > +           << ": Instruction at this address already exists.\n";
> > +    exit(EXIT_FAILURE);
> > +  }
> > +}
> > +
> > +char UnsupportedDisassembly::ID;
> > +void UnsupportedDisassembly::log(raw_ostream &OS) const {
> > +  OS << "Dissassembling of non-objects not currently supported.\n";
> > +}
> > +
> > +std::error_code UnsupportedDisassembly::convertToErrorCode() const {
> > +  return std::error_code();
> > +}
> > +
> > +} // namespace cfi_verify
> > +} // namespace llvm
> >
> > Added: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h?rev=315504&view=auto <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h?rev=315504&view=auto>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h (added)
> > +++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h Wed Oct 11 13:35:01 2017
> > @@ -0,0 +1,157 @@
> > +//===- FileAnalysis.h -------------------------------------------*- C++ -*-===//
> > +//
> > +//                      The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===----------------------------------------------------------------------===//
> > +
> > +#ifndef LLVM_CFI_VERIFY_FILE_ANALYSIS_H
> > +#define LLVM_CFI_VERIFY_FILE_ANALYSIS_H
> > +
> > +#include "llvm/BinaryFormat/ELF.h"
> > +#include "llvm/MC/MCAsmInfo.h"
> > +#include "llvm/MC/MCContext.h"
> > +#include "llvm/MC/MCDisassembler/MCDisassembler.h"
> > +#include "llvm/MC/MCInst.h"
> > +#include "llvm/MC/MCInstPrinter.h"
> > +#include "llvm/MC/MCInstrAnalysis.h"
> > +#include "llvm/MC/MCInstrDesc.h"
> > +#include "llvm/MC/MCInstrInfo.h"
> > +#include "llvm/MC/MCObjectFileInfo.h"
> > +#include "llvm/MC/MCRegisterInfo.h"
> > +#include "llvm/MC/MCSubtargetInfo.h"
> > +#include "llvm/Object/Binary.h"
> > +#include "llvm/Object/COFF.h"
> > +#include "llvm/Object/ELFObjectFile.h"
> > +#include "llvm/Object/ObjectFile.h"
> > +#include "llvm/Support/Casting.h"
> > +#include "llvm/Support/CommandLine.h"
> > +#include "llvm/Support/Error.h"
> > +#include "llvm/Support/MemoryBuffer.h"
> > +#include "llvm/Support/TargetRegistry.h"
> > +#include "llvm/Support/TargetSelect.h"
> > +#include "llvm/Support/raw_ostream.h"
> > +
> > +#include <functional>
> > +#include <set>
> > +#include <string>
> > +#include <unordered_map>
> > +
> > +namespace llvm {
> > +namespace cfi_verify {
> > +
> > +// Disassembler and analysis tool for machine code files. Keeps track of non-
> > +// sequential control flows, including indirect control flow instructions.
> > +class FileAnalysis {
> > +public:
> > +  // A metadata struct for an instruction.
> > +  struct Instr {
> > +    uint64_t VMAddress;       // Virtual memory address of this instruction.
> > +    MCInst Instruction;       // Instruction.
> > +    uint64_t InstructionSize; // Size of this instruction.
> > +    bool Valid; // Is this a valid instruction? If false, Instr::Instruction is
> > +                // undefined.
> > +  };
> > +
> > +  // Construct a FileAnalysis from a file path.
> > +  static Expected<FileAnalysis> Create(StringRef Filename);
> > +
> > +  // Construct and take ownership of the supplied object. Do not use this
> > +  // constructor, prefer to use FileAnalysis::Create instead.
> > +  FileAnalysis(object::OwningBinary<object::Binary> Binary);
> > +  FileAnalysis() = delete;
> > +  FileAnalysis(const FileAnalysis &) = delete;
> > +  FileAnalysis(FileAnalysis &&Other) = default;
> > +
> > +  // Returns the instruction at the provided address. Returns nullptr if there
> > +  // is no instruction at the provided address.
> > +  const Instr *getInstruction(uint64_t Address) const;
> > +
> > +  // Returns the instruction at the provided adress, dying if the instruction is
> > +  // not found.
> > +  const Instr &getInstructionOrDie(uint64_t Address) const;
> > +
> > +  // Returns a pointer to the previous/next instruction in sequence,
> > +  // respectively. Returns nullptr if the next/prev instruction doesn't exist,
> > +  // or if the provided instruction doesn't exist.
> > +  const Instr *getPrevInstructionSequential(const Instr &InstrMeta) const;
> > +  const Instr *getNextInstructionSequential(const Instr &InstrMeta) const;
> > +
> > +  // Returns whether this instruction uses a register operand.
> > +  bool usesRegisterOperand(const Instr &InstrMeta) const;
> > +
> > +  // Returns the list of indirect instructions.
> > +  const std::set<uint64_t> &getIndirectInstructions() const;
> > +
> > +  const MCRegisterInfo *getRegisterInfo() const;
> > +  const MCInstrInfo *getMCInstrInfo() const;
> > +  const MCInstrAnalysis *getMCInstrAnalysis() const;
> > +
> > +protected:
> > +  // Construct a blank object with the provided triple and features. Used in
> > +  // testing, where a sub class will dependency inject protected methods to
> > +  // allow analysis of raw binary, without requiring a fully valid ELF file.
> > +  FileAnalysis(const Triple &ObjectTriple, const SubtargetFeatures &Features);
> > +
> > +  // Add an instruction to this object.
> > +  void addInstruction(const Instr &Instruction);
> > +
> > +  // Disassemble and parse the provided bytes into this object. Instruction
> > +  // address calculation is done relative to the provided SectionAddress.
> > +  void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
> > +                            uint64_t SectionAddress);
> > +
> > +  // Constructs and initialises members required for disassembly.
> > +  Error initialiseDisassemblyMembers();
> > +
> > +  // Parses code sections from the internal object file. Saves them into the
> > +  // internal members. Should only be called once by Create().
> > +  Error parseCodeSections();
> > +
> > +private:
> > +  // Members that describe the input file.
> > +  object::OwningBinary<object::Binary> Binary;
> > +  const object::ObjectFile *Object = nullptr;
> > +  Triple ObjectTriple;
> > +  std::string ArchName;
> > +  std::string MCPU;
> > +  const Target *ObjectTarget = nullptr;
> > +  SubtargetFeatures Features;
> > +
> > +  // Members required for disassembly.
> > +  std::unique_ptr<const MCRegisterInfo> RegisterInfo;
> > +  std::unique_ptr<const MCAsmInfo> AsmInfo;
> > +  std::unique_ptr<MCSubtargetInfo> SubtargetInfo;
> > +  std::unique_ptr<const MCInstrInfo> MII;
> > +  MCObjectFileInfo MOFI;
> > +  std::unique_ptr<MCContext> Context;
> > +  std::unique_ptr<const MCDisassembler> Disassembler;
> > +  std::unique_ptr<const MCInstrAnalysis> MIA;
> > +  std::unique_ptr<MCInstPrinter> Printer;
> > +
> > +  // A mapping between the virtual memory address to the instruction metadata
> > +  // struct.
> > +  std::map<uint64_t, Instr> Instructions;
> > +
> > +  // Contains a mapping between a specific address, and a list of instructions
> > +  // that use this address as a branch target (including call instructions).
> > +  std::unordered_map<uint64_t, std::vector<uint64_t>> StaticBranchTargetings;
> > +
> > +  // A list of addresses of indirect control flow instructions.
> > +  std::set<uint64_t> IndirectInstructions;
> > +};
> > +
> > +class UnsupportedDisassembly : public ErrorInfo<UnsupportedDisassembly> {
> > +public:
> > +  static char ID;
> > +
> > +  void log(raw_ostream &OS) const override;
> > +  std::error_code convertToErrorCode() const override;
> > +};
> > +
> > +} // namespace cfi_verify
> > +} // namespace llvm
> > +
> > +#endif // LLVM_CFI_VERIFY_FILE_ANALYSIS_H
> >
> > Copied: llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt (from r315502, llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt)
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt?p2=llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt&p1=llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt&r1=315502&r2=315504&rev=315504&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt?p2=llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt&p1=llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt&r1=315502&r2=315504&rev=315504&view=diff>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/LLVMBuild.txt (original)
> > +++ llvm/trunk/tools/llvm-cfi-verify/lib/LLVMBuild.txt Wed Oct 11 13:35:01 2017
> > @@ -1,4 +1,4 @@
> > -;===- ./tools/llvm-cfi-verify/LLVMBuild.txt --------------------*- Conf -*--===;
> > +;===- ./tools/llvm-cfi-verify/lib/LLVMBuild.txt ----------------*- Conf -*--===;
> > ;
> > ;                     The LLVM Compiler Infrastructure
> > ;
> > @@ -16,7 +16,7 @@
> > ;===------------------------------------------------------------------------===;
> >
> > [component_0]
> > -type = Tool
> > -name = llvm-cfi-verify
> > -parent = Tools
> > -required_libraries = MC MCDisassembler MCParser Support all-targets
> > +type = Library
> > +name = CFIVerify
> > +parent = Libraries
> > +required_libraries = MC MCDisassembler MCParser Support
> >
> > Modified: llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp?rev=315504&r1=315503&r2=315504&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp?rev=315504&r1=315503&r2=315504&view=diff>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp (original)
> > +++ llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp Wed Oct 11 13:35:01 2017
> > @@ -17,64 +17,31 @@
> > //
> > //===----------------------------------------------------------------------===//
> >
> > -#include "llvm/MC/MCAsmInfo.h"
> > -#include "llvm/MC/MCContext.h"
> > -#include "llvm/MC/MCDisassembler/MCDisassembler.h"
> > -#include "llvm/MC/MCInst.h"
> > -#include "llvm/MC/MCInstPrinter.h"
> > -#include "llvm/MC/MCInstrAnalysis.h"
> > -#include "llvm/MC/MCInstrDesc.h"
> > -#include "llvm/MC/MCInstrInfo.h"
> > -#include "llvm/MC/MCObjectFileInfo.h"
> > -#include "llvm/MC/MCRegisterInfo.h"
> > -#include "llvm/MC/MCSubtargetInfo.h"
> > -#include "llvm/Object/Binary.h"
> > -#include "llvm/Object/COFF.h"
> > -#include "llvm/Object/ObjectFile.h"
> > -#include "llvm/Support/Casting.h"
> > +#include "lib/FileAnalysis.h"
> > +
> > +#include "llvm/BinaryFormat/ELF.h"
> > #include "llvm/Support/CommandLine.h"
> > -#include "llvm/Support/MemoryBuffer.h"
> > -#include "llvm/Support/TargetRegistry.h"
> > -#include "llvm/Support/TargetSelect.h"
> > -#include "llvm/Support/raw_ostream.h"
> > +#include "llvm/Support/Error.h"
> >
> > -#include <cassert>
> > #include <cstdlib>
> >
> > using namespace llvm;
> > using namespace llvm::object;
> > +using namespace llvm::cfi_verify;
> >
> > -cl::opt<bool> ArgDumpSymbols("sym", cl::desc("Dump the symbol table."));
> > cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"),
> >                                    cl::Required);
> >
> > -static void printSymbols(const ObjectFile *Object) {
> > -  for (const SymbolRef &Symbol : Object->symbols()) {
> > -    outs() << "Symbol [" << format_hex_no_prefix(Symbol.getValue(), 2)
> > -           << "] = ";
> > -
> > -    auto SymbolName = Symbol.getName();
> > -    if (SymbolName)
> > -      outs() << *SymbolName;
> > -    else
> > -      outs() << "UNKNOWN";
> > -
> > -    if (Symbol.getFlags() & SymbolRef::SF_Hidden)
> > -      outs() << " .hidden";
> > -
> > -    outs() << " (Section = ";
> > -
> > -    auto SymbolSection = Symbol.getSection();
> > -    if (SymbolSection) {
> > -      StringRef SymbolSectionName;
> > -      if ((*SymbolSection)->getName(SymbolSectionName))
> > -        outs() << "UNKNOWN)";
> > -      else
> > -        outs() << SymbolSectionName << ")";
> > -    } else {
> > -      outs() << "N/A)";
> > -    }
> > +ExitOnError ExitOnErr;
> >
> > +void printIndirectCFInstructions(const FileAnalysis &Verifier) {
> > +  for (uint64_t Address : Verifier.getIndirectInstructions()) {
> > +    const auto &InstrMeta = Verifier.getInstructionOrDie(Address);
> > +    outs() << format_hex(Address, 2) << " |"
> > +           << Verifier.getMCInstrInfo()->getName(
> > +                  InstrMeta.Instruction.getOpcode())
> > +           << " ";
> > +    InstrMeta.Instruction.print(outs());
> >     outs() << "\n";
> >   }
> > }
> > @@ -87,155 +54,8 @@ int main(int argc, char **argv) {
> >   InitializeAllAsmParsers();
> >   InitializeAllDisassemblers();
> >
> > -  Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFilename);
> > -  if (!BinaryOrErr) {
> > -    errs() << "Failed to open file.\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  Binary &Binary = *BinaryOrErr.get().getBinary();
> > -  ObjectFile *Object = dyn_cast<ObjectFile>(&Binary);
> > -  if (!Object) {
> > -    errs() << "Disassembling of non-objects not currently supported.\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  Triple TheTriple = Object->makeTriple();
> > -  std::string TripleName = TheTriple.getTriple();
> > -  std::string ArchName = "";
> > -  std::string ErrorString;
> > -
> > -  const Target *TheTarget =
> > -      TargetRegistry::lookupTarget(ArchName, TheTriple, ErrorString);
> > -
> > -  if (!TheTarget) {
> > -    errs() << "Couldn't find target \"" << TheTriple.getTriple()
> > -           << "\", failed with error: " << ErrorString << ".\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  SubtargetFeatures Features = Object->getFeatures();
> > -
> > -  std::unique_ptr<const MCRegisterInfo> RegisterInfo(
> > -      TheTarget->createMCRegInfo(TripleName));
> > -  if (!RegisterInfo) {
> > -    errs() << "Failed to initialise RegisterInfo.\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  std::unique_ptr<const MCAsmInfo> AsmInfo(
> > -      TheTarget->createMCAsmInfo(*RegisterInfo, TripleName));
> > -  if (!AsmInfo) {
> > -    errs() << "Failed to initialise AsmInfo.\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  std::string MCPU = "";
> > -  std::unique_ptr<MCSubtargetInfo> SubtargetInfo(
> > -      TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
> > -  if (!SubtargetInfo) {
> > -    errs() << "Failed to initialise SubtargetInfo.\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
> > -  if (!MII) {
> > -    errs() << "Failed to initialise MII.\n";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  MCObjectFileInfo MOFI;
> > -  MCContext Context(AsmInfo.get(), RegisterInfo.get(), &MOFI);
> > -
> > -  std::unique_ptr<const MCDisassembler> Disassembler(
> > -      TheTarget->createMCDisassembler(*SubtargetInfo, Context));
> > -
> > -  if (!Disassembler) {
> > -    errs() << "No disassembler available for target.";
> > -    return EXIT_FAILURE;
> > -  }
> > -
> > -  std::unique_ptr<const MCInstrAnalysis> MIA(
> > -      TheTarget->createMCInstrAnalysis(MII.get()));
> > -
> > -  std::unique_ptr<MCInstPrinter> Printer(
> > -      TheTarget->createMCInstPrinter(TheTriple, AsmInfo->getAssemblerDialect(),
> > -                                     *AsmInfo, *MII, *RegisterInfo));
> > -
> > -  if (ArgDumpSymbols)
> > -    printSymbols(Object);
> > -
> > -  for (const SectionRef &Section : Object->sections()) {
> > -    outs() << "Section [" << format_hex_no_prefix(Section.getAddress(), 2)
> > -           << "] = ";
> > -    StringRef SectionName;
> > -
> > -    if (Section.getName(SectionName))
> > -      outs() << "UNKNOWN.\n";
> > -    else
> > -      outs() << SectionName << "\n";
> > -
> > -    StringRef SectionContents;
> > -    if (Section.getContents(SectionContents)) {
> > -      errs() << "Failed to retrieve section contents.\n";
> > -      return EXIT_FAILURE;
> > -    }
> > -
> > -    MCInst Instruction;
> > -    uint64_t InstructionSize;
> > -
> > -    ArrayRef<uint8_t> SectionBytes((const uint8_t *)SectionContents.data(),
> > -                                   Section.getSize());
> > -
> > -    for (uint64_t Byte = 0; Byte < Section.getSize();) {
> > -      bool BadInstruction = false;
> > -
> > -      // Disassemble the instruction.
> > -      if (Disassembler->getInstruction(
> > -              Instruction, InstructionSize, SectionBytes.drop_front(Byte), 0,
> > -              nulls(), outs()) != MCDisassembler::Success) {
> > -        BadInstruction = true;
> > -      }
> > -
> > -      Byte += InstructionSize;
> > -
> > -      if (BadInstruction)
> > -        continue;
> > -
> > -      // Skip instructions that do not affect the control flow.
> > -      const auto &InstrDesc = MII->get(Instruction.getOpcode());
> > -      if (!InstrDesc.mayAffectControlFlow(Instruction, *RegisterInfo))
> > -        continue;
> > -
> > -      // Skip instructions that do not operate on register operands.
> > -      bool UsesRegisterOperand = false;
> > -      for (const auto &Operand : Instruction) {
> > -        if (Operand.isReg())
> > -          UsesRegisterOperand = true;
> > -      }
> > -
> > -      if (!UsesRegisterOperand)
> > -        continue;
> > -
> > -      // Print the instruction address.
> > -      outs() << "    "
> > -             << format_hex(Section.getAddress() + Byte - InstructionSize, 2)
> > -             << ": ";
> > -
> > -      // Print the instruction bytes.
> > -      for (uint64_t i = 0; i < InstructionSize; ++i) {
> > -        outs() << format_hex_no_prefix(SectionBytes[Byte - InstructionSize + i],
> > -                                       2)
> > -               << " ";
> > -      }
> > -
> > -      // Print the instruction.
> > -      outs() << " | " << MII->getName(Instruction.getOpcode()) << " ";
> > -      Instruction.dump_pretty(outs(), Printer.get());
> > -
> > -      outs() << "\n";
> > -    }
> > -  }
> > +  FileAnalysis Verifier = ExitOnErr(FileAnalysis::Create(InputFilename));
> > +  printIndirectCFInstructions(Verifier);
> >
> >   return EXIT_SUCCESS;
> > }
> >
> > Modified: llvm/trunk/unittests/CMakeLists.txt
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=315504&r1=315503&r2=315504&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=315504&r1=315503&r2=315504&view=diff>
> > ==============================================================================
> > --- llvm/trunk/unittests/CMakeLists.txt (original)
> > +++ llvm/trunk/unittests/CMakeLists.txt Wed Oct 11 13:35:01 2017
> > @@ -27,3 +27,4 @@ add_subdirectory(Support)
> > add_subdirectory(Target)
> > add_subdirectory(Transforms)
> > add_subdirectory(XRay)
> > +add_subdirectory(tools)
> >
> > Added: llvm/trunk/unittests/tools/CMakeLists.txt
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/CMakeLists.txt?rev=315504&view=auto <http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/CMakeLists.txt?rev=315504&view=auto>
> > ==============================================================================
> > --- llvm/trunk/unittests/tools/CMakeLists.txt (added)
> > +++ llvm/trunk/unittests/tools/CMakeLists.txt Wed Oct 11 13:35:01 2017
> > @@ -0,0 +1 @@
> > +add_subdirectory(llvm-cfi-verify)
> >
> > Copied: llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt (from r315502, llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt)
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt?p2=llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt&p1=llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt&r1=315502&r2=315504&rev=315504&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt?p2=llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt&p1=llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt&r1=315502&r2=315504&rev=315504&view=diff>
> > ==============================================================================
> > --- llvm/trunk/tools/llvm-cfi-verify/CMakeLists.txt (original)
> > +++ llvm/trunk/unittests/tools/llvm-cfi-verify/CMakeLists.txt Wed Oct 11 13:35:01 2017
> > @@ -4,13 +4,12 @@ set(LLVM_LINK_COMPONENTS
> >   AllTargetsDescs
> >   AllTargetsDisassemblers
> >   AllTargetsInfos
> > +  CFIVerify
> >   MC
> > -  Object
> >   MCParser
> >   Object
> >   Support
> >   )
> >
> > -add_llvm_tool(llvm-cfi-verify
> > -  llvm-cfi-verify.cpp
> > -  )
> > +add_llvm_unittest(CFIVerifyTests
> > +  FileAnalysis.cpp)
> >
> > Added: llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp?rev=315504&view=auto <http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp?rev=315504&view=auto>
> > ==============================================================================
> > --- llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp (added)
> > +++ llvm/trunk/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp Wed Oct 11 13:35:01 2017
> > @@ -0,0 +1,216 @@
> > +//===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===//
> > +//
> > +//                     The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===----------------------------------------------------------------------===//
> > +
> > +#include "../tools/llvm-cfi-verify/lib/FileAnalysis.h"
> > +#include "gmock/gmock.h"
> > +#include "gtest/gtest.h"
> > +
> > +#include "llvm/BinaryFormat/ELF.h"
> > +#include "llvm/MC/MCAsmInfo.h"
> > +#include "llvm/MC/MCContext.h"
> > +#include "llvm/MC/MCDisassembler/MCDisassembler.h"
> > +#include "llvm/MC/MCInst.h"
> > +#include "llvm/MC/MCInstPrinter.h"
> > +#include "llvm/MC/MCInstrAnalysis.h"
> > +#include "llvm/MC/MCInstrDesc.h"
> > +#include "llvm/MC/MCInstrInfo.h"
> > +#include "llvm/MC/MCObjectFileInfo.h"
> > +#include "llvm/MC/MCRegisterInfo.h"
> > +#include "llvm/MC/MCSubtargetInfo.h"
> > +#include "llvm/Object/Binary.h"
> > +#include "llvm/Object/COFF.h"
> > +#include "llvm/Object/ELFObjectFile.h"
> > +#include "llvm/Object/ObjectFile.h"
> > +#include "llvm/Support/Casting.h"
> > +#include "llvm/Support/CommandLine.h"
> > +#include "llvm/Support/Error.h"
> > +#include "llvm/Support/MemoryBuffer.h"
> > +#include "llvm/Support/TargetRegistry.h"
> > +#include "llvm/Support/TargetSelect.h"
> > +#include "llvm/Support/raw_ostream.h"
> > +
> > +#include <cstdlib>
> > +
> > +using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
> > +using ::testing::Eq;
> > +
> > +namespace llvm {
> > +namespace cfi_verify {
> > +namespace {
> > +class ELFx86TestFileAnalysis : public FileAnalysis {
> > +public:
> > +  ELFx86TestFileAnalysis()
> > +      : FileAnalysis(Triple("x86_64--"), SubtargetFeatures()) {}
> > +
> > +  // Expose this method publicly for testing.
> > +  void parseSectionContents(ArrayRef<uint8_t> SectionBytes,
> > +                            uint64_t SectionAddress) {
> > +    FileAnalysis::parseSectionContents(SectionBytes, SectionAddress);
> > +  }
> > +
> > +  Error initialiseDisassemblyMembers() {
> > +    return FileAnalysis::initialiseDisassemblyMembers();
> > +  }
> > +};
> > +
> > +class BasicFileAnalysisTest : public ::testing::Test {
> > +protected:
> > +  virtual void SetUp() {
> > +    if (Analysis.initialiseDisassemblyMembers()) {
> > +      FAIL() << "Failed to initialise FileAnalysis.";
> > +    }
> > +  }
> > +
> > +  ELFx86TestFileAnalysis Analysis;
> > +};
> > +
> > +TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) {
> > +  Analysis.parseSectionContents(
> > +      {
> > +          0x90,                   // 0: nop
> > +          0xb0, 0x00,             // 1: mov $0x0, %al
> > +          0x48, 0x89, 0xe5,       // 3: mov %rsp, %rbp
> > +          0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
> > +          0x48, 0xbe, 0xc4, 0x07, 0x40,
> > +          0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
> > +          0x2f,                         // 20: (bad)
> > +          0x41, 0x0e,                   // 21: rex.B (bad)
> > +          0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
> > +      },
> > +      0xDEADBEEF);
> > +
> > +  EXPECT_EQ(nullptr, Analysis.getInstruction(0x0));
> > +  EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000));
> > +
> > +  // 0xDEADBEEF: nop
> > +  const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress);
> > +  EXPECT_EQ(1u, InstrMeta->InstructionSize);
> > +  EXPECT_TRUE(InstrMeta->Valid);
> > +
> > +  const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
> > +  EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +  const auto *PrevInstrMeta = InstrMeta;
> > +
> > +  // 0xDEADBEEF + 1: mov $0x0, %al
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(NextInstrMeta, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress);
> > +  EXPECT_EQ(2u, InstrMeta->InstructionSize);
> > +  EXPECT_TRUE(InstrMeta->Valid);
> > +
> > +  NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
> > +  EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +  PrevInstrMeta = InstrMeta;
> > +
> > +  // 0xDEADBEEF + 3: mov %rsp, %rbp
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(NextInstrMeta, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress);
> > +  EXPECT_EQ(3u, InstrMeta->InstructionSize);
> > +  EXPECT_TRUE(InstrMeta->Valid);
> > +
> > +  NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
> > +  EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +  PrevInstrMeta = InstrMeta;
> > +
> > +  // 0xDEADBEEF + 6: sub $0x18, %rsp
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(NextInstrMeta, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress);
> > +  EXPECT_EQ(4u, InstrMeta->InstructionSize);
> > +  EXPECT_TRUE(InstrMeta->Valid);
> > +
> > +  NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta);
> > +  EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +  PrevInstrMeta = InstrMeta;
> > +
> > +  // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(NextInstrMeta, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress);
> > +  EXPECT_EQ(10u, InstrMeta->InstructionSize);
> > +  EXPECT_TRUE(InstrMeta->Valid);
> > +
> > +  EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
> > +  EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +  PrevInstrMeta = InstrMeta;
> > +
> > +  // 0xDEADBEEF + 20: (bad)
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress);
> > +  EXPECT_EQ(1u, InstrMeta->InstructionSize);
> > +  EXPECT_FALSE(InstrMeta->Valid);
> > +
> > +  EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
> > +  EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +
> > +  // 0xDEADBEEF + 21: rex.B (bad)
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress);
> > +  EXPECT_EQ(2u, InstrMeta->InstructionSize);
> > +  EXPECT_FALSE(InstrMeta->Valid);
> > +
> > +  EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
> > +  EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +
> > +  // 0xDEADBEEF + 6: (bad) {%k1}
> > +  InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23);
> > +  EXPECT_NE(nullptr, InstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress);
> > +  EXPECT_EQ(5u, InstrMeta->InstructionSize);
> > +  EXPECT_FALSE(InstrMeta->Valid);
> > +
> > +  EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta));
> > +  EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta));
> > +}
> > +
> > +TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) {
> > +  Analysis.parseSectionContents(
> > +      {
> > +          0x90, // 0: nop
> > +          0x2f, // 1: (bad)
> > +          0x90  // 2: nop
> > +      },
> > +      0xDEADBEEF);
> > +  const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1);
> > +  const auto *GoodInstrMeta =
> > +      Analysis.getPrevInstructionSequential(BadInstrMeta);
> > +  EXPECT_NE(nullptr, GoodInstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress);
> > +  EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
> > +
> > +  GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta);
> > +  EXPECT_NE(nullptr, GoodInstrMeta);
> > +  EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress);
> > +  EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
> > +}
> > +
> > +} // anonymous namespace
> > +} // end namespace cfi_verify
> > +} // end namespace llvm
> > +
> > +int main(int argc, char **argv) {
> > +  ::testing::InitGoogleTest(&argc, argv);
> > +  llvm::cl::ParseCommandLineOptions(argc, argv);
> > +
> > +  llvm::InitializeAllTargetInfos();
> > +  llvm::InitializeAllTargetMCs();
> > +  llvm::InitializeAllAsmParsers();
> > +  llvm::InitializeAllDisassemblers();
> > +
> > +  return RUN_ALL_TESTS();
> > +}
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits <http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits>
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171011/08fe5ecb/attachment.html>


More information about the llvm-commits mailing list